1: /*
2: ================================================================================
3: RPL/2 (R) version 4.0.10
4: Copyright (C) 1989-2010 Dr. BERTRAND Joël
5:
6: This file is part of RPL/2.
7:
8: RPL/2 is free software; you can redistribute it and/or modify it
9: under the terms of the CeCILL V2 License as published by the french
10: CEA, CNRS and INRIA.
11:
12: RPL/2 is distributed in the hope that it will be useful, but WITHOUT
13: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14: FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License
15: for more details.
16:
17: You should have received a copy of the CeCILL License
18: along with RPL/2. If not, write to info@cecill.info.
19: ================================================================================
20: */
21:
22:
23: #include "rpl.conv.h"
24: #include <stdarg.h>
25: #undef fprintf
26: #undef printf
27:
28:
29: /*
30: ================================================================================
31: Fonction de translitération
32: ================================================================================
33: Entrées :
34: --------------------------------------------------------------------------------
35: Sorties :
36: --------------------------------------------------------------------------------
37: Effets de bord : néant
38: ================================================================================
39: */
40:
41: unsigned char *
42: transliteration(struct_processus *s_etat_processus,
43: unsigned char *chaine_entree,
44: unsigned char *codage_entree,
45: unsigned char *codage_sortie)
46: {
47: unsigned char *codage_sortie_transliteral;
48: unsigned char *tampon;
49:
50: if ((codage_sortie_transliteral = malloc((strlen(codage_sortie)
51: + strlen("//TRANSLIT") + 1) * sizeof(unsigned char))) == NULL)
52: {
53: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
54: return(NULL);
55: }
56:
57: sprintf(codage_sortie_transliteral, "%s//TRANSLIT", codage_sortie);
58:
59: tampon = reencodage(s_etat_processus, chaine_entree,
60: codage_entree, codage_sortie_transliteral);
61: free(codage_sortie_transliteral);
62:
63: return(tampon);
64: }
65:
66:
67: unsigned char *
68: reencodage(struct_processus *s_etat_processus,
69: unsigned char *chaine_entree,
70: unsigned char *codage_entree,
71: unsigned char *codage_sortie)
72: {
73: # define d_LONGUEUR 1024
74:
75: iconv_t transcodage;
76:
77: size_t ios;
78: size_t longueur_entree;
79: size_t longueur_sortie;
80:
81: unsigned char *buffer_entree;
82: unsigned char *buffer_sortie;
83: unsigned char *chaine_sortie;
84: unsigned char *pointeur;
85: unsigned char *tampon;
86:
87: if ((transcodage = iconv_open(codage_sortie, codage_entree)) ==
88: (iconv_t) -1)
89: {
90: (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
91: return(NULL);
92: }
93:
94: buffer_entree = chaine_entree;
95: longueur_entree = strlen(chaine_entree);
96:
97: if ((chaine_sortie = malloc(sizeof(unsigned char))) == NULL)
98: {
99: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
100: return(NULL);
101: }
102:
103: chaine_sortie[0] = d_code_fin_chaine;
104:
105: if ((buffer_sortie = malloc((d_LONGUEUR + 1) * sizeof(char))) == NULL)
106: {
107: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
108: return(NULL);
109: }
110:
111: do
112: {
113: longueur_sortie = d_LONGUEUR;
114: pointeur = buffer_sortie;
115:
116: if ((ios = iconv(transcodage, (char **) &buffer_entree,
117: &longueur_entree, (char **) &pointeur, &longueur_sortie))
118: == (size_t) -1)
119: {
120: // On autorise les erreurs EINVAL et EILSEQ
121: if (errno == EILSEQ)
122: {
123: free(buffer_sortie);
124: free(chaine_sortie);
125:
126: (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
127: return(NULL);
128: }
129: }
130:
131: tampon = (unsigned char *) chaine_sortie;
132: (*pointeur) = d_code_fin_chaine;
133:
134: if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1)
135: * sizeof(unsigned char))) == NULL)
136: {
137: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
138: return(NULL);
139: }
140:
141: sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie);
142: free(tampon);
143: } while((*buffer_entree) != d_code_fin_chaine);
144:
145: free(buffer_sortie);
146: iconv_close(transcodage);
147:
148: return(chaine_sortie);
149: }
150:
151:
152: /*
153: ================================================================================
154: Fonctions spécifiques
155: ================================================================================
156: Entrées :
157: --------------------------------------------------------------------------------
158: Sorties :
159: --------------------------------------------------------------------------------
160: Effets de bord : néant
161: ================================================================================
162: */
163:
164: void
165: localisation_courante(struct_processus *s_etat_processus)
166: {
167: char **arguments;
168:
169: int ios;
170: int pipes_entree[2];
171: int pipes_erreur[2];
172: int pipes_sortie[2];
173: int status;
174:
175: logical1 drapeau_fin;
176:
177: long i;
178: long nombre_arguments;
179:
180: pid_t pid;
181:
182: sigset_t oldset;
183: sigset_t set;
184:
185: struct sigaction action_passee;
186:
187: unsigned char *tampon;
188:
189: unsigned long longueur_lecture;
190: unsigned long nombre_iterations;
191: unsigned long pointeur;
192:
193: if ((arguments = malloc(3 * sizeof(char **))) == NULL)
194: {
195: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
196: return;
197: }
198:
199: if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL)
200: {
201: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
202: return;
203: }
204:
205: if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL)
206: {
207: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
208: return;
209: }
210:
211: strcpy(arguments[0], "locale");
212: strcpy(arguments[1], "charmap");
213: arguments[2] = NULL;
214:
215: nombre_arguments = 2;
216: drapeau_fin = d_faux;
217:
218: if (pipe(pipes_entree) != 0)
219: {
220: (*s_etat_processus).erreur_systeme = d_es_processus;
221: return;
222: }
223:
224: if (pipe(pipes_sortie) != 0)
225: {
226: (*s_etat_processus).erreur_systeme = d_es_processus;
227: return;
228: }
229:
230: if (pipe(pipes_erreur) != 0)
231: {
232: (*s_etat_processus).erreur_systeme = d_es_processus;
233: return;
234: }
235:
236: sigfillset(&set);
237: pthread_sigmask(SIG_BLOCK, &set, &oldset);
238:
239: verrouillage_threads_concurrents(s_etat_processus);
240: pid = fork();
241: deverrouillage_threads_concurrents(s_etat_processus);
242:
243: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
244: sigpending(&set);
245:
246: if (pid < 0)
247: {
248: if (close(pipes_entree[0]) != 0)
249: {
250: (*s_etat_processus).erreur_systeme = d_es_processus;
251: return;
252: }
253:
254: if (close(pipes_entree[1]) != 0)
255: {
256: (*s_etat_processus).erreur_systeme = d_es_processus;
257: return;
258: }
259:
260: if (close(pipes_sortie[0]) != 0)
261: {
262: (*s_etat_processus).erreur_systeme = d_es_processus;
263: return;
264: }
265:
266: if (close(pipes_sortie[1]) != 0)
267: {
268: (*s_etat_processus).erreur_systeme = d_es_processus;
269: return;
270: }
271:
272: if (close(pipes_erreur[0]) != 0)
273: {
274: (*s_etat_processus).erreur_systeme = d_es_processus;
275: return;
276: }
277:
278: if (close(pipes_erreur[1]) != 0)
279: {
280: (*s_etat_processus).erreur_systeme = d_es_processus;
281: return;
282: }
283:
284: (*s_etat_processus).erreur_systeme = d_es_processus;
285: return;
286: }
287: else if (pid == 0)
288: {
289: if (close(pipes_entree[1]) != 0)
290: {
291: (*s_etat_processus).erreur_systeme = d_es_processus;
292: return;
293: }
294:
295: if (close(pipes_sortie[0]) != 0)
296: {
297: (*s_etat_processus).erreur_systeme = d_es_processus;
298: return;
299: }
300:
301: if (close(pipes_erreur[0]) != 0)
302: {
303: (*s_etat_processus).erreur_systeme = d_es_processus;
304: return;
305: }
306:
307: if (pipes_entree[0] != STDIN_FILENO)
308: {
309: if (dup2(pipes_entree[0], STDIN_FILENO) == -1)
310: {
311: (*s_etat_processus).erreur_systeme = d_es_processus;
312: return;
313: }
314: }
315:
316: if (pipes_sortie[1] != STDOUT_FILENO)
317: {
318: if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1)
319: {
320: (*s_etat_processus).erreur_systeme = d_es_processus;
321: return;
322: }
323: }
324:
325: if (pipes_sortie[1] != STDERR_FILENO)
326: {
327: if (dup2(pipes_sortie[1], STDERR_FILENO) == -1)
328: {
329: (*s_etat_processus).erreur_systeme = d_es_processus;
330: return;
331: }
332: }
333:
334: if (nombre_arguments != 0)
335: {
336: execvp(arguments[0], arguments);
337: }
338: else
339: {
340: exit(EXIT_SUCCESS);
341: }
342:
343: /*
344: * L'appel système execvp() a généré une erreur et n'a pu exécuter
345: * argument[0] (fichier non exécutable ou inexistant).
346: */
347:
348: close(pipes_entree[0]);
349: close(pipes_sortie[1]);
350:
351: for(i = 0; i < nombre_arguments; i++)
352: {
353: free(arguments[i]);
354: }
355:
356: free(arguments);
357: (*s_etat_processus).erreur_systeme = d_es_processus;
358:
359: /*
360: * Envoi d'une erreur dans le pipe idoine. On ne regarde pas
361: * le nombre d'octets écrits car l'erreur ne pourra de toute
362: * façon pas être traitée.
363: */
364:
365: write_atomic(s_etat_processus, pipes_erreur[1], " ", 1);
366: close(pipes_erreur[1]);
367:
368: exit(EXIT_SUCCESS);
369: }
370: else
371: {
372: if (close(pipes_entree[0]) != 0)
373: {
374: (*s_etat_processus).erreur_systeme = d_es_processus;
375: return;
376: }
377:
378: if (close(pipes_sortie[1]) != 0)
379: {
380: (*s_etat_processus).erreur_systeme = d_es_processus;
381: return;
382: }
383:
384: if (close(pipes_erreur[1]) != 0)
385: {
386: (*s_etat_processus).erreur_systeme = d_es_processus;
387: return;
388: }
389:
390: if (close(pipes_entree[1]) != 0)
391: {
392: (*s_etat_processus).erreur_systeme = d_es_processus;
393: return;
394: }
395:
396: do
397: {
398: if (kill(pid, 0) != 0)
399: {
400: break;
401: }
402:
403: /*
404: * Récupération de la valeur de retour du processus détaché
405: */
406:
407: if (sem_post(&((*s_etat_processus).semaphore_fork))
408: != 0)
409: {
410: (*s_etat_processus).erreur_systeme = d_es_processus;
411: return;
412: }
413:
414: if (waitpid(pid, &status, 0) == -1)
415: {
416: if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
417: {
418: if (errno != EINTR)
419: {
420: (*s_etat_processus).erreur_systeme = d_es_processus;
421: return;
422: }
423: }
424:
425: (*s_etat_processus).erreur_systeme = d_es_processus;
426: return;
427: }
428:
429: if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
430: {
431: if (errno != EINTR)
432: {
433: (*s_etat_processus).erreur_systeme = d_es_processus;
434: return;
435: }
436: }
437: } while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
438:
439: longueur_lecture = 256;
440: pointeur = 0;
441: nombre_iterations = 1;
442:
443: if ((tampon = malloc((longueur_lecture + 1) *
444: sizeof(unsigned char))) == NULL)
445: {
446: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
447: return;
448: }
449:
450: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
451: {
452: (*s_etat_processus).erreur_systeme = d_es_processus;
453: return;
454: }
455:
456: while((ios = read_atomic(s_etat_processus,
457: pipes_sortie[0], &(tampon[pointeur]),
458: longueur_lecture)) > 0)
459: {
460: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
461: {
462: if (errno != EINTR)
463: {
464: (*s_etat_processus).erreur_systeme = d_es_processus;
465: return;
466: }
467: }
468:
469: tampon[pointeur + ios] = d_code_fin_chaine;
470: pointeur += longueur_lecture;
471: nombre_iterations++;
472:
473: if ((tampon = realloc(tampon,
474: ((nombre_iterations * longueur_lecture) + 1) *
475: sizeof(unsigned char))) == NULL)
476: {
477: (*s_etat_processus).erreur_systeme =
478: d_es_allocation_memoire;
479: return;
480: }
481:
482: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
483: {
484: (*s_etat_processus).erreur_systeme = d_es_processus;
485: return;
486: }
487: }
488:
489: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
490: {
491: if (errno != EINTR)
492: {
493: (*s_etat_processus).erreur_systeme = d_es_processus;
494: return;
495: }
496: }
497:
498: if (strlen(tampon) == 0)
499: {
500: (*s_etat_processus).erreur_systeme = d_es_processus;
501: return;
502: }
503:
504: tampon[strlen(tampon) - 1] = d_code_fin_chaine;
505:
506: if (ios == -1)
507: {
508: (*s_etat_processus).erreur_systeme = d_es_processus;
509: return;
510: }
511:
512: if (close(pipes_sortie[0]) != 0)
513: {
514: (*s_etat_processus).erreur_systeme = d_es_processus;
515: return;
516: }
517:
518: (*s_etat_processus).localisation = tampon;
519:
520: if (sigaction(SIGINT, &action_passee, NULL) != 0)
521: {
522: for(i = 0; i < nombre_arguments; i++)
523: {
524: free(arguments[i]);
525: }
526:
527: free(arguments);
528: (*s_etat_processus).erreur_systeme = d_es_signal;
529: return;
530: }
531:
532: for(i = 0; i < nombre_arguments; i++)
533: {
534: free(arguments[i]);
535: }
536:
537: free(arguments);
538:
539: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
540: {
541: (*s_etat_processus).erreur_systeme = d_es_processus;
542: return;
543: }
544:
545: if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0)
546: {
547: // Le processus fils renvoie une erreur.
548:
549: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
550: {
551: if (errno != EINTR)
552: {
553: (*s_etat_processus).erreur_systeme = d_es_processus;
554: return;
555: }
556: }
557:
558: (*s_etat_processus).erreur_execution = d_ex_erreur_processus;
559: return;
560: }
561:
562: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
563: {
564: if (errno != EINTR)
565: {
566: (*s_etat_processus).erreur_systeme = d_es_processus;
567: return;
568: }
569: }
570:
571: if (close(pipes_erreur[0]) != 0)
572: {
573: (*s_etat_processus).erreur_systeme = d_es_processus;
574: return;
575: }
576: }
577:
578: return;
579: }
580:
581: static int
582: vtransliterated_sprintf(char **strp, const char *fmt, va_list ap)
583: {
584: size_t bs, s;
585: char *b = NULL;
586: va_list cap;
587:
588: va_copy(cap, ap);
589:
590: for(bs = 256;; bs *= 2)
591: {
592: va_copy(ap, cap);
593: if (b != NULL) free(b);
594: if ((b = malloc(sizeof(*b) * bs)) == NULL) return -1;
595: if (((int) (s = vsnprintf(b, bs, fmt, ap))) < 0)
596: { va_end(ap); free(b); return -1; }
597: va_end(ap);
598: if (s < bs) break;
599: }
600:
601: if (((*strp) = realloc(b, ((s = strlen(b)) + 1) * sizeof(*b)))
602: == NULL) { free(b); return -1; }
603: return s;
604: }
605:
606: int
607: transliterated_fprintf(struct_processus *s_etat_processus, file *flux,
608: const char *format, ...)
609: {
610: int ios;
611: char *tampon;
612: unsigned char *tampon2;
613: va_list arguments;
614:
615: va_start(arguments, format);
616:
617: if (vtransliterated_sprintf(&tampon, format, arguments) < 0)
618: {
619: va_end(arguments);
620:
621: if (s_etat_processus != NULL)
622: {
623: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
624: }
625:
626: return(-1);
627: }
628:
629: va_end(arguments);
630:
631: if (s_etat_processus != NULL)
632: {
633: if ((tampon2 = transliteration(s_etat_processus, tampon,
634: d_locale, (*s_etat_processus).localisation)) == NULL)
635: {
636: free(tampon);
637: return(-1);
638: }
639:
640: free(tampon);
641: }
642: else
643: {
644: tampon2 = tampon;
645: }
646:
647: # ifdef SunOS
648: while((ios = fprintf(flux, "%s", tampon2)) < 0)
649: {
650: if ((errno != EINTR) && (errno != 0))
651: {
652: break;
653: }
654: }
655: # else
656: ios = fprintf(flux, "%s", tampon2);
657: # endif
658:
659: free(tampon2);
660:
661: return(ios);
662: }
663:
664: #define fprintf NULL
665: #define printf NULL
666:
667: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>