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