1: /*
2: ================================================================================
3: RPL/2 (R) version 4.1.13
4: Copyright (C) 1989-2013 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 "tex-conv.h"
25:
26: #include <stdarg.h>
27:
28: #undef fprintf
29: #undef printf
30:
31:
32: /*
33: ================================================================================
34: Fonction de translitération
35: ================================================================================
36: Entrées :
37: --------------------------------------------------------------------------------
38: Sorties :
39: --------------------------------------------------------------------------------
40: Effets de bord : néant
41: ================================================================================
42: */
43:
44: unsigned char *
45: transliteration(struct_processus *s_etat_processus,
46: unsigned char *chaine_entree,
47: unsigned char *codage_entree,
48: unsigned char *codage_sortie)
49: {
50: unsigned char *codage_sortie_transliteral;
51: unsigned char *tampon;
52:
53: if ((codage_sortie_transliteral = malloc((strlen(codage_sortie)
54: + strlen("//TRANSLIT") + 1) * sizeof(unsigned char))) == NULL)
55: {
56: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
57: return(NULL);
58: }
59:
60: sprintf(codage_sortie_transliteral, "%s//TRANSLIT", codage_sortie);
61:
62: tampon = reencodage(s_etat_processus, chaine_entree,
63: codage_entree, codage_sortie_transliteral);
64: free(codage_sortie_transliteral);
65:
66: return(tampon);
67: }
68:
69:
70: unsigned char *
71: reencodage(struct_processus *s_etat_processus,
72: unsigned char *chaine_entree,
73: unsigned char *codage_entree,
74: unsigned char *codage_sortie)
75: {
76: # define d_LONGUEUR 1024
77:
78: iconv_t transcodage;
79:
80: size_t ios;
81: size_t longueur_entree;
82: size_t longueur_sortie;
83:
84: unsigned char *buffer_entree;
85: unsigned char *buffer_sortie;
86: unsigned char *chaine_sortie;
87: unsigned char *pointeur;
88: unsigned char *tampon;
89:
90: if ((transcodage = iconv_open(codage_sortie, codage_entree)) ==
91: (iconv_t) -1)
92: {
93: // On affiche une erreur ici car la fonction d'affichage
94: // de l'erreur utilise la macro printf() donc une
95: // opération de translitération qui échouera elle aussi.
96: // Le positionnement de l'erreur permet de sortir du programme.
97:
98: if ((*s_etat_processus).langue == 'F')
99: {
100: fprintf(stderr, "+++Erreur : Erreur de transcodage\n");
101: }
102: else
103: {
104: fprintf(stderr, "+++Error : Transcodage error\n");
105: }
106:
107: (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
108: return(NULL);
109: }
110:
111: buffer_entree = chaine_entree;
112: longueur_entree = strlen(chaine_entree);
113:
114: if ((chaine_sortie = malloc(sizeof(unsigned char))) == NULL)
115: {
116: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
117: return(NULL);
118: }
119:
120: chaine_sortie[0] = d_code_fin_chaine;
121:
122: if ((buffer_sortie = malloc((d_LONGUEUR + 1) * sizeof(unsigned char)))
123: == NULL)
124: {
125: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
126: return(NULL);
127: }
128:
129: do
130: {
131: longueur_sortie = d_LONGUEUR;
132: pointeur = buffer_sortie;
133:
134: if ((ios = iconv(transcodage, (char **) &buffer_entree,
135: &longueur_entree, (char **) &pointeur, &longueur_sortie))
136: == (size_t) -1)
137: {
138: // On autorise les erreurs EINVAL si le caractère suivant est non
139: // nul : la séquence d'entrée est continue sur le bloc suivant.
140:
141: if (errno == EINVAL)
142: {
143: if ((*(buffer_entree + 1)) == d_code_fin_chaine)
144: {
145: free(buffer_sortie);
146: free(chaine_sortie);
147:
148: // On affiche une erreur ici car la fonction d'affichage
149: // de l'erreur utilise la macro printf() donc une
150: // opération de translitération qui échouera elle aussi.
151: // Le positionnement de l'erreur permet de sortir du
152: // programme.
153:
154: if ((*s_etat_processus).langue == 'F')
155: {
156: fprintf(stderr, "+++Erreur : Erreur de transcodage\n");
157: }
158: else
159: {
160: fprintf(stderr, "+++Error : Transcodage error\n");
161: }
162:
163: (*s_etat_processus).erreur_execution =
164: d_ex_erreur_transcodage;
165: return(NULL);
166: }
167: }
168:
169: // Si la séquence d'entrée est invalide, on reçoit une erreur
170: // EILSEQ.
171: else if (errno == EILSEQ)
172: {
173: free(buffer_sortie);
174: free(chaine_sortie);
175:
176: // On affiche une erreur ici car la fonction d'affichage
177: // de l'erreur utilise la macro printf() donc une
178: // opération de translitération qui échouera elle aussi.
179: // Le positionnement de l'erreur permet de sortir du programme.
180:
181: if ((*s_etat_processus).langue == 'F')
182: {
183: fprintf(stderr, "+++Erreur : Erreur de transcodage\n");
184: }
185: else
186: {
187: fprintf(stderr, "+++Error : Transcodage error\n");
188: }
189:
190: (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
191: return(NULL);
192: }
193: }
194:
195: tampon = chaine_sortie;
196: (*pointeur) = d_code_fin_chaine;
197:
198: if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1)
199: * sizeof(unsigned char))) == NULL)
200: {
201: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
202: return(NULL);
203: }
204:
205: sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie);
206: free(tampon);
207: } while((*buffer_entree) != d_code_fin_chaine);
208:
209: free(buffer_sortie);
210: iconv_close(transcodage);
211:
212: return(chaine_sortie);
213: }
214:
215:
216: /*
217: ================================================================================
218: Fonctions spécifiques
219: ================================================================================
220: Entrées :
221: --------------------------------------------------------------------------------
222: Sorties :
223: --------------------------------------------------------------------------------
224: Effets de bord : néant
225: ================================================================================
226: */
227:
228: void
229: localisation_courante(struct_processus *s_etat_processus)
230: {
231: char **arguments;
232:
233: int ios;
234: int pipes_entree[2];
235: int pipes_erreur[2];
236: int pipes_sortie[2];
237: int status;
238:
239: integer8 i;
240: integer8 longueur_lecture;
241: integer8 nombre_arguments;
242: integer8 nombre_iterations;
243: integer8 pointeur;
244:
245:
246: pid_t pid;
247:
248: unsigned char *tampon;
249:
250: if ((arguments = malloc(3 * sizeof(char **))) == NULL)
251: {
252: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
253: return;
254: }
255:
256: if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL)
257: {
258: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
259: return;
260: }
261:
262: if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL)
263: {
264: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
265: return;
266: }
267:
268: strcpy(arguments[0], "locale");
269: strcpy(arguments[1], "charmap");
270: arguments[2] = NULL;
271:
272: nombre_arguments = 2;
273:
274: if (pipe(pipes_entree) != 0)
275: {
276: (*s_etat_processus).erreur_systeme = d_es_processus;
277: return;
278: }
279:
280: if (pipe(pipes_sortie) != 0)
281: {
282: (*s_etat_processus).erreur_systeme = d_es_processus;
283: return;
284: }
285:
286: if (pipe(pipes_erreur) != 0)
287: {
288: (*s_etat_processus).erreur_systeme = d_es_processus;
289: return;
290: }
291:
292: verrouillage_threads_concurrents(s_etat_processus);
293: pid = fork();
294: deverrouillage_threads_concurrents(s_etat_processus);
295:
296: if (pid < 0)
297: {
298: if (close(pipes_entree[0]) != 0)
299: {
300: (*s_etat_processus).erreur_systeme = d_es_processus;
301: return;
302: }
303:
304: if (close(pipes_entree[1]) != 0)
305: {
306: (*s_etat_processus).erreur_systeme = d_es_processus;
307: return;
308: }
309:
310: if (close(pipes_sortie[0]) != 0)
311: {
312: (*s_etat_processus).erreur_systeme = d_es_processus;
313: return;
314: }
315:
316: if (close(pipes_sortie[1]) != 0)
317: {
318: (*s_etat_processus).erreur_systeme = d_es_processus;
319: return;
320: }
321:
322: if (close(pipes_erreur[0]) != 0)
323: {
324: (*s_etat_processus).erreur_systeme = d_es_processus;
325: return;
326: }
327:
328: if (close(pipes_erreur[1]) != 0)
329: {
330: (*s_etat_processus).erreur_systeme = d_es_processus;
331: return;
332: }
333:
334: (*s_etat_processus).erreur_systeme = d_es_processus;
335: return;
336: }
337: else if (pid == 0)
338: {
339: if (close(pipes_entree[1]) != 0)
340: {
341: (*s_etat_processus).erreur_systeme = d_es_processus;
342: return;
343: }
344:
345: if (close(pipes_sortie[0]) != 0)
346: {
347: (*s_etat_processus).erreur_systeme = d_es_processus;
348: return;
349: }
350:
351: if (close(pipes_erreur[0]) != 0)
352: {
353: (*s_etat_processus).erreur_systeme = d_es_processus;
354: return;
355: }
356:
357: if (pipes_entree[0] != STDIN_FILENO)
358: {
359: if (dup2(pipes_entree[0], STDIN_FILENO) == -1)
360: {
361: (*s_etat_processus).erreur_systeme = d_es_processus;
362: return;
363: }
364: }
365:
366: if (pipes_sortie[1] != STDOUT_FILENO)
367: {
368: if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1)
369: {
370: (*s_etat_processus).erreur_systeme = d_es_processus;
371: return;
372: }
373: }
374:
375: if (pipes_sortie[1] != STDERR_FILENO)
376: {
377: if (dup2(pipes_sortie[1], STDERR_FILENO) == -1)
378: {
379: (*s_etat_processus).erreur_systeme = d_es_processus;
380: return;
381: }
382: }
383:
384: if (nombre_arguments != 0)
385: {
386: execvp(arguments[0], arguments);
387: }
388: else
389: {
390: exit(EXIT_SUCCESS);
391: }
392:
393: /*
394: * L'appel système execvp() a généré une erreur et n'a pu exécuter
395: * argument[0] (fichier non exécutable ou inexistant).
396: */
397:
398: close(pipes_entree[0]);
399: close(pipes_sortie[1]);
400:
401: for(i = 0; i < nombre_arguments; i++)
402: {
403: free(arguments[i]);
404: }
405:
406: free(arguments);
407: (*s_etat_processus).erreur_systeme = d_es_processus;
408:
409: /*
410: * Envoi d'une erreur dans le pipe idoine. On ne regarde pas
411: * le nombre d'octets écrits car l'erreur ne pourra de toute
412: * façon pas être traitée.
413: */
414:
415: write_atomic(s_etat_processus, pipes_erreur[1], " ", 1);
416: close(pipes_erreur[1]);
417:
418: exit(EXIT_SUCCESS);
419: }
420: else
421: {
422: if (close(pipes_entree[0]) != 0)
423: {
424: (*s_etat_processus).erreur_systeme = d_es_processus;
425: return;
426: }
427:
428: if (close(pipes_sortie[1]) != 0)
429: {
430: (*s_etat_processus).erreur_systeme = d_es_processus;
431: return;
432: }
433:
434: if (close(pipes_erreur[1]) != 0)
435: {
436: (*s_etat_processus).erreur_systeme = d_es_processus;
437: return;
438: }
439:
440: if (close(pipes_entree[1]) != 0)
441: {
442: (*s_etat_processus).erreur_systeme = d_es_processus;
443: return;
444: }
445:
446: do
447: {
448: if (kill(pid, 0) != 0)
449: {
450: break;
451: }
452:
453: /*
454: * Récupération de la valeur de retour du processus détaché
455: */
456:
457: # ifndef SEMAPHORES_NOMMES
458: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
459: # else
460: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
461: # endif
462: {
463: (*s_etat_processus).erreur_systeme = d_es_processus;
464: return;
465: }
466:
467: if (waitpid(pid, &status, 0) == -1)
468: {
469: # ifndef SEMAPHORES_NOMMES
470: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
471: # else
472: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
473: # endif
474: {
475: if (errno != EINTR)
476: {
477: (*s_etat_processus).erreur_systeme = d_es_processus;
478: return;
479: }
480: }
481:
482: (*s_etat_processus).erreur_systeme = d_es_processus;
483: return;
484: }
485:
486: # ifndef SEMAPHORES_NOMMES
487: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
488: # else
489: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
490: # endif
491: {
492: if (errno != EINTR)
493: {
494: (*s_etat_processus).erreur_systeme = d_es_processus;
495: return;
496: }
497: }
498: } while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
499:
500: longueur_lecture = 256;
501: pointeur = 0;
502: nombre_iterations = 1;
503:
504: if ((tampon = malloc(((size_t) (longueur_lecture + 1)) *
505: sizeof(unsigned char))) == NULL)
506: {
507: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
508: return;
509: }
510:
511: tampon[0] = d_code_fin_chaine;
512:
513: # ifndef SEMAPHORES_NOMMES
514: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
515: # else
516: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
517: # endif
518: {
519: (*s_etat_processus).erreur_systeme = d_es_processus;
520: return;
521: }
522:
523: while((ios = (int) read_atomic(s_etat_processus,
524: pipes_sortie[0], &(tampon[pointeur]),
525: (size_t) longueur_lecture)) > 0)
526: {
527: # ifndef SEMAPHORES_NOMMES
528: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
529: # else
530: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
531: # endif
532: {
533: if (errno != EINTR)
534: {
535: (*s_etat_processus).erreur_systeme = d_es_processus;
536: return;
537: }
538: }
539:
540: tampon[pointeur + ios] = d_code_fin_chaine;
541: pointeur += longueur_lecture;
542: nombre_iterations++;
543:
544: if ((tampon = realloc(tampon,
545: ((size_t) ((nombre_iterations * longueur_lecture) + 1)) *
546: sizeof(unsigned char))) == NULL)
547: {
548: (*s_etat_processus).erreur_systeme =
549: d_es_allocation_memoire;
550: return;
551: }
552:
553: # ifndef SEMAPHORES_NOMMES
554: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
555: # else
556: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
557: # endif
558: {
559: (*s_etat_processus).erreur_systeme = d_es_processus;
560: return;
561: }
562: }
563:
564: # ifndef SEMAPHORES_NOMMES
565: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
566: # else
567: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
568: # endif
569: {
570: if (errno != EINTR)
571: {
572: (*s_etat_processus).erreur_systeme = d_es_processus;
573: return;
574: }
575: }
576:
577: if (strlen(tampon) == 0)
578: {
579: (*s_etat_processus).erreur_systeme = d_es_processus;
580: return;
581: }
582:
583: tampon[strlen(tampon) - 1] = d_code_fin_chaine;
584:
585: if (ios == -1)
586: {
587: (*s_etat_processus).erreur_systeme = d_es_processus;
588: return;
589: }
590:
591: if (close(pipes_sortie[0]) != 0)
592: {
593: (*s_etat_processus).erreur_systeme = d_es_processus;
594: return;
595: }
596:
597: if (strlen(tampon) > 0)
598: {
599: (*s_etat_processus).localisation = tampon;
600: }
601: else
602: {
603: free(tampon);
604:
605: if (((*s_etat_processus).localisation = malloc((strlen(d_locale)
606: + 1) * sizeof(unsigned char))) == NULL)
607: {
608: (*s_etat_processus).erreur_systeme = d_es_processus;
609: return;
610: }
611:
612: strcpy((*s_etat_processus).localisation, d_locale);
613: }
614:
615: for(i = 0; i < nombre_arguments; i++)
616: {
617: free(arguments[i]);
618: }
619:
620: free(arguments);
621:
622: # ifndef SEMAPHORES_NOMMES
623: if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
624: # else
625: if (sem_post((*s_etat_processus).semaphore_fork) != 0)
626: # endif
627: {
628: (*s_etat_processus).erreur_systeme = d_es_processus;
629: return;
630: }
631:
632: if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0)
633: {
634: // Le processus fils renvoie une erreur.
635:
636: free(tampon);
637:
638: if (((*s_etat_processus).localisation = malloc((strlen(d_locale)
639: + 1) * sizeof(unsigned char))) == NULL)
640: {
641: (*s_etat_processus).erreur_systeme = d_es_processus;
642: return;
643: }
644:
645: strcpy((*s_etat_processus).localisation, d_locale);
646: }
647:
648: # ifndef SEMAPHORES_NOMMES
649: while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0)
650: # else
651: while(sem_wait((*s_etat_processus).semaphore_fork) != 0)
652: # endif
653: {
654: if (errno != EINTR)
655: {
656: (*s_etat_processus).erreur_systeme = d_es_processus;
657: return;
658: }
659: }
660:
661: if (close(pipes_erreur[0]) != 0)
662: {
663: (*s_etat_processus).erreur_systeme = d_es_processus;
664: return;
665: }
666: }
667:
668: return;
669: }
670:
671:
672: int
673: transliterated_fprintf(struct_processus *s_etat_processus, file *flux,
674: const char *format, ...)
675: {
676: int ios;
677:
678: unsigned char *tampon;
679: unsigned char *tampon2;
680:
681: va_list arguments;
682:
683: va_start(arguments, format);
684:
685: # ifdef OS2
686: unsigned char *ptr_e;;
687: unsigned char *ptr_l;;
688: unsigned char *tampon3;
689:
690: unsigned long i;
691: # endif
692:
693: if (valsprintf(&tampon, format, arguments) < 0)
694: {
695: va_end(arguments);
696:
697: if (s_etat_processus != NULL)
698: {
699: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
700: }
701:
702: return(-1);
703: }
704:
705: va_end(arguments);
706:
707: if (s_etat_processus != NULL)
708: {
709: if ((tampon2 = transliteration(s_etat_processus, tampon,
710: d_locale, (*s_etat_processus).localisation)) == NULL)
711: {
712: free(tampon);
713: return(-1);
714: }
715:
716: free(tampon);
717: }
718: else
719: {
720: tampon2 = tampon;
721: }
722:
723: # ifdef OS2
724: if ((flux == stderr) || (flux == stdout))
725: {
726: i = 0;
727: ptr_l = tampon2;
728:
729: while((*ptr_l) != d_code_fin_chaine)
730: {
731: if ((*ptr_l) == '\n')
732: {
733: i++;
734: }
735:
736: ptr_l++;
737: }
738:
739: if ((tampon3 = malloc((strlen(tampon2) + i + 1) *
740: sizeof(unsigned char))) == NULL)
741: {
742: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
743: return(-1);
744: }
745:
746: ptr_e = tampon3;
747: ptr_l = tampon2;
748:
749: while((*ptr_l) != d_code_fin_chaine)
750: {
751: (*ptr_e) = (*ptr_l);
752:
753: if ((*ptr_l) == '\n')
754: {
755: (*(++ptr_e)) = '\r';
756: ptr_e++;
757: ptr_l++;
758: }
759: else
760: {
761: ptr_e++;
762: ptr_l++;
763: }
764: }
765:
766: (*ptr_e) = d_code_fin_chaine;
767:
768: free(tampon2);
769: tampon2 = tampon3;
770: }
771: # endif
772:
773: # ifdef SunOS
774: while((ios = fprintf(flux, "%s", tampon2)) < 0)
775: {
776: if ((errno != EINTR) && (errno != 0))
777: {
778: break;
779: }
780: }
781: # else
782: ios = fprintf(flux, "%s", tampon2);
783: # endif
784:
785: free(tampon2);
786:
787: return(ios);
788: }
789:
790:
791: int
792: tex_fprintf(struct_processus *s_etat_processus,
793: file *flux, const char *format, ...)
794: {
795: int ios;
796:
797: unsigned char *tampon;
798: unsigned char *tampon2;
799:
800: va_list arguments;
801:
802: va_start(arguments, format);
803:
804: if (valsprintf(&tampon, format, arguments) < 0)
805: {
806: va_end(arguments);
807:
808: if (s_etat_processus != NULL)
809: {
810: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
811: }
812:
813: return(-1);
814: }
815:
816: va_end(arguments);
817:
818: if ((tampon2 = transliteration(s_etat_processus, tampon,
819: d_locale, ds_tex_encodage_3)) == NULL)
820: {
821: free(tampon);
822: return(-1);
823: }
824:
825: free(tampon);
826:
827: # ifdef SunOS
828: while((ios = fprintf(flux, "%s", tampon2)) < 0)
829: {
830: if ((errno != EINTR) && (errno != 0))
831: {
832: break;
833: }
834: }
835: # else
836: ios = fprintf(flux, "%s", tampon2);
837: # endif
838:
839: free(tampon2);
840:
841: return(ios);
842: }
843:
844: #undef readline
845:
846: unsigned char *
847: readline_wrapper(unsigned char *invite)
848: {
849: unsigned char *chaine;
850:
851: chaine = readline(invite);
852: printf("\r");
853:
854: return(chaine);
855: }
856:
857:
858: #define fprintf NULL
859: #define printf NULL
860:
861: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>