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: (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
125: return(NULL);
126: }
127: }
128:
129: tampon = (unsigned char *) chaine_sortie;
130: (*pointeur) = d_code_fin_chaine;
131:
132: if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1)
133: * sizeof(unsigned char))) == NULL)
134: {
135: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
136: return(NULL);
137: }
138:
139: sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie);
140: free(tampon);
141: } while((*buffer_entree) != d_code_fin_chaine);
142:
143: free(buffer_sortie);
144: iconv_close(transcodage);
145:
146: return(chaine_sortie);
147: }
148:
149:
150: /*
151: ================================================================================
152: Fonctions spécifiques
153: ================================================================================
154: Entrées :
155: --------------------------------------------------------------------------------
156: Sorties :
157: --------------------------------------------------------------------------------
158: Effets de bord : néant
159: ================================================================================
160: */
161:
162: void
163: localisation_courante(struct_processus *s_etat_processus)
164: {
165: char **arguments;
166:
167: int ios;
168: int pipes_entree[2];
169: int pipes_erreur[2];
170: int pipes_sortie[2];
171: int status;
172:
173: logical1 drapeau_fin;
174:
175: long i;
176: long nombre_arguments;
177:
178: pid_t pid;
179:
180: sigset_t oldset;
181: sigset_t set;
182:
183: struct sigaction action_passee;
184:
185: unsigned char *tampon;
186:
187: unsigned long longueur_lecture;
188: unsigned long nombre_iterations;
189: unsigned long pointeur;
190:
191: if ((arguments = malloc(3 * sizeof(char **))) == NULL)
192: {
193: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
194: return;
195: }
196:
197: if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL)
198: {
199: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
200: return;
201: }
202:
203: if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL)
204: {
205: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
206: return;
207: }
208:
209: strcpy(arguments[0], "locale");
210: strcpy(arguments[1], "charmap");
211: arguments[2] = NULL;
212:
213: nombre_arguments = 2;
214: drapeau_fin = d_faux;
215:
216: if (pipe(pipes_entree) != 0)
217: {
218: (*s_etat_processus).erreur_systeme = d_es_processus;
219: return;
220: }
221:
222: if (pipe(pipes_sortie) != 0)
223: {
224: (*s_etat_processus).erreur_systeme = d_es_processus;
225: return;
226: }
227:
228: if (pipe(pipes_erreur) != 0)
229: {
230: (*s_etat_processus).erreur_systeme = d_es_processus;
231: return;
232: }
233:
234: sigfillset(&set);
235: pthread_sigmask(SIG_BLOCK, &set, &oldset);
236:
237: verrouillage_threads_concurrents(s_etat_processus);
238: pid = fork();
239: deverrouillage_threads_concurrents(s_etat_processus);
240:
241: pthread_sigmask(SIG_SETMASK, &oldset, NULL);
242: sigpending(&set);
243:
244: if (pid < 0)
245: {
246: if (close(pipes_entree[0]) != 0)
247: {
248: (*s_etat_processus).erreur_systeme = d_es_processus;
249: return;
250: }
251:
252: if (close(pipes_entree[1]) != 0)
253: {
254: (*s_etat_processus).erreur_systeme = d_es_processus;
255: return;
256: }
257:
258: if (close(pipes_sortie[0]) != 0)
259: {
260: (*s_etat_processus).erreur_systeme = d_es_processus;
261: return;
262: }
263:
264: if (close(pipes_sortie[1]) != 0)
265: {
266: (*s_etat_processus).erreur_systeme = d_es_processus;
267: return;
268: }
269:
270: if (close(pipes_erreur[0]) != 0)
271: {
272: (*s_etat_processus).erreur_systeme = d_es_processus;
273: return;
274: }
275:
276: if (close(pipes_erreur[1]) != 0)
277: {
278: (*s_etat_processus).erreur_systeme = d_es_processus;
279: return;
280: }
281:
282: (*s_etat_processus).erreur_systeme = d_es_processus;
283: return;
284: }
285: else if (pid == 0)
286: {
287: if (close(pipes_entree[1]) != 0)
288: {
289: (*s_etat_processus).erreur_systeme = d_es_processus;
290: return;
291: }
292:
293: if (close(pipes_sortie[0]) != 0)
294: {
295: (*s_etat_processus).erreur_systeme = d_es_processus;
296: return;
297: }
298:
299: if (close(pipes_erreur[0]) != 0)
300: {
301: (*s_etat_processus).erreur_systeme = d_es_processus;
302: return;
303: }
304:
305: if (pipes_entree[0] != STDIN_FILENO)
306: {
307: if (dup2(pipes_entree[0], STDIN_FILENO) == -1)
308: {
309: (*s_etat_processus).erreur_systeme = d_es_processus;
310: return;
311: }
312: }
313:
314: if (pipes_sortie[1] != STDOUT_FILENO)
315: {
316: if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1)
317: {
318: (*s_etat_processus).erreur_systeme = d_es_processus;
319: return;
320: }
321: }
322:
323: if (pipes_sortie[1] != STDERR_FILENO)
324: {
325: if (dup2(pipes_sortie[1], STDERR_FILENO) == -1)
326: {
327: (*s_etat_processus).erreur_systeme = d_es_processus;
328: return;
329: }
330: }
331:
332: if (nombre_arguments != 0)
333: {
334: execvp(arguments[0], arguments);
335: }
336: else
337: {
338: exit(EXIT_SUCCESS);
339: }
340:
341: /*
342: * L'appel système execvp() a généré une erreur et n'a pu exécuter
343: * argument[0] (fichier non exécutable ou inexistant).
344: */
345:
346: close(pipes_entree[0]);
347: close(pipes_sortie[1]);
348:
349: for(i = 0; i < nombre_arguments; i++)
350: {
351: free(arguments[i]);
352: }
353:
354: free(arguments);
355: (*s_etat_processus).erreur_systeme = d_es_processus;
356:
357: /*
358: * Envoi d'une erreur dans le pipe idoine. On ne regarde pas
359: * le nombre d'octets écrits car l'erreur ne pourra de toute
360: * façon pas être traitée.
361: */
362:
363: write_atomic(s_etat_processus, pipes_erreur[1], " ", 1);
364: close(pipes_erreur[1]);
365:
366: exit(EXIT_SUCCESS);
367: }
368: else
369: {
370: if (close(pipes_entree[0]) != 0)
371: {
372: (*s_etat_processus).erreur_systeme = d_es_processus;
373: return;
374: }
375:
376: if (close(pipes_sortie[1]) != 0)
377: {
378: (*s_etat_processus).erreur_systeme = d_es_processus;
379: return;
380: }
381:
382: if (close(pipes_erreur[1]) != 0)
383: {
384: (*s_etat_processus).erreur_systeme = d_es_processus;
385: return;
386: }
387:
388: if (close(pipes_entree[1]) != 0)
389: {
390: (*s_etat_processus).erreur_systeme = d_es_processus;
391: return;
392: }
393:
394: do
395: {
396: if (kill(pid, 0) != 0)
397: {
398: break;
399: }
400:
401: /*
402: * Récupération de la valeur de retour du processus détaché
403: */
404:
405: if (sem_post(&((*s_etat_processus).semaphore_fork))
406: != 0)
407: {
408: (*s_etat_processus).erreur_systeme = d_es_processus;
409: return;
410: }
411:
412: if (waitpid(pid, &status, 0) == -1)
413: {
414: if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
415: {
416: if (errno != EINTR)
417: {
418: (*s_etat_processus).erreur_systeme = d_es_processus;
419: return;
420: }
421: }
422:
423: (*s_etat_processus).erreur_systeme = d_es_processus;
424: return;
425: }
426:
427: if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
428: {
429: if (errno != EINTR)
430: {
431: (*s_etat_processus).erreur_systeme = d_es_processus;
432: return;
433: }
434: }
435: } while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
436:
437: longueur_lecture = 256;
438: pointeur = 0;
439: nombre_iterations = 1;
440:
441: if ((tampon = malloc((longueur_lecture + 1) *
442: sizeof(unsigned char))) == NULL)
443: {
444: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
445: return;
446: }
447:
448: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
449: {
450: (*s_etat_processus).erreur_systeme = d_es_processus;
451: return;
452: }
453:
454: while((ios = read_atomic(s_etat_processus,
455: pipes_sortie[0], &(tampon[pointeur]),
456: longueur_lecture)) > 0)
457: {
458: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
459: {
460: if (errno != EINTR)
461: {
462: (*s_etat_processus).erreur_systeme = d_es_processus;
463: return;
464: }
465: }
466:
467: tampon[pointeur + ios] = d_code_fin_chaine;
468: pointeur += longueur_lecture;
469: nombre_iterations++;
470:
471: if ((tampon = realloc(tampon,
472: ((nombre_iterations * longueur_lecture) + 1) *
473: sizeof(unsigned char))) == NULL)
474: {
475: (*s_etat_processus).erreur_systeme =
476: d_es_allocation_memoire;
477: return;
478: }
479:
480: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
481: {
482: (*s_etat_processus).erreur_systeme = d_es_processus;
483: return;
484: }
485: }
486:
487: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
488: {
489: if (errno != EINTR)
490: {
491: (*s_etat_processus).erreur_systeme = d_es_processus;
492: return;
493: }
494: }
495:
496: if (strlen(tampon) == 0)
497: {
498: (*s_etat_processus).erreur_systeme = d_es_processus;
499: return;
500: }
501:
502: tampon[strlen(tampon) - 1] = d_code_fin_chaine;
503:
504: if (ios == -1)
505: {
506: (*s_etat_processus).erreur_systeme = d_es_processus;
507: return;
508: }
509:
510: if (close(pipes_sortie[0]) != 0)
511: {
512: (*s_etat_processus).erreur_systeme = d_es_processus;
513: return;
514: }
515:
516: (*s_etat_processus).localisation = tampon;
517:
518: if (sigaction(SIGINT, &action_passee, NULL) != 0)
519: {
520: for(i = 0; i < nombre_arguments; i++)
521: {
522: free(arguments[i]);
523: }
524:
525: free(arguments);
526: (*s_etat_processus).erreur_systeme = d_es_signal;
527: return;
528: }
529:
530: for(i = 0; i < nombre_arguments; i++)
531: {
532: free(arguments[i]);
533: }
534:
535: free(arguments);
536:
537: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
538: {
539: (*s_etat_processus).erreur_systeme = d_es_processus;
540: return;
541: }
542:
543: if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0)
544: {
545: // Le processus fils renvoie une erreur.
546:
547: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
548: {
549: if (errno != EINTR)
550: {
551: (*s_etat_processus).erreur_systeme = d_es_processus;
552: return;
553: }
554: }
555:
556: (*s_etat_processus).erreur_execution = d_ex_erreur_processus;
557: return;
558: }
559:
560: while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
561: {
562: if (errno != EINTR)
563: {
564: (*s_etat_processus).erreur_systeme = d_es_processus;
565: return;
566: }
567: }
568:
569: if (close(pipes_erreur[0]) != 0)
570: {
571: (*s_etat_processus).erreur_systeme = d_es_processus;
572: return;
573: }
574: }
575:
576: return;
577: }
578:
579: static int
580: vtransliterated_sprintf(char **strp, const char *fmt, va_list ap)
581: {
582: size_t bs, s;
583: char *b = NULL;
584: va_list cap;
585:
586: va_copy(cap, ap);
587:
588: for(bs = 256;; bs *= 2)
589: {
590: va_copy(ap, cap);
591: if (b != NULL) free(b);
592: if ((b = malloc(sizeof(*b) * bs)) == NULL) return -1;
593: if (((int) (s = vsnprintf(b, bs, fmt, ap))) < 0)
594: { va_end(ap); free(b); return -1; }
595: va_end(ap);
596: if (s < bs) break;
597: }
598:
599: if (((*strp) = realloc(b, ((s = strlen(b)) + 1) * sizeof(*b)))
600: == NULL) { free(b); return -1; }
601: return s;
602: }
603:
604: int
605: transliterated_fprintf(struct_processus *s_etat_processus, file *flux,
606: const char *format, ...)
607: {
608: int ios;
609: char *tampon;
610: unsigned char *tampon2;
611: va_list arguments;
612:
613: va_start(arguments, format);
614:
615: if (vtransliterated_sprintf(&tampon, format, arguments) < 0)
616: {
617: va_end(arguments);
618:
619: if (s_etat_processus != NULL)
620: {
621: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
622: }
623:
624: return(-1);
625: }
626:
627: va_end(arguments);
628:
629: if (s_etat_processus != NULL)
630: {
631: if ((tampon2 = transliteration(s_etat_processus, tampon,
632: d_locale, (*s_etat_processus).localisation)) == NULL)
633: {
634: free(tampon);
635: return(-1);
636: }
637:
638: free(tampon);
639: }
640: else
641: {
642: tampon2 = tampon;
643: }
644:
645: # ifdef SunOS
646: while((ios = fprintf(flux, "%s", tampon2)) < 0)
647: {
648: if ((errno != EINTR) && (errno != 0))
649: {
650: break;
651: }
652: }
653: # else
654: ios = fprintf(flux, "%s", tampon2);
655: # endif
656:
657: free(tampon2);
658:
659: return(ios);
660: }
661:
662: #define fprintf NULL
663: #define printf NULL
664:
665: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>