/* ================================================================================ RPL/2 (R) version 4.1.13 Copyright (C) 1989-2013 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" #include "tex-conv.h" #include #undef fprintf #undef printf /* ================================================================================ Fonction de translitération ================================================================================ Entrées : -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ unsigned char * transliteration(struct_processus *s_etat_processus, unsigned char *chaine_entree, unsigned char *codage_entree, unsigned char *codage_sortie) { unsigned char *codage_sortie_transliteral; unsigned char *tampon; if ((codage_sortie_transliteral = malloc((strlen(codage_sortie) + strlen("//TRANSLIT") + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } sprintf(codage_sortie_transliteral, "%s//TRANSLIT", codage_sortie); tampon = reencodage(s_etat_processus, chaine_entree, codage_entree, codage_sortie_transliteral); free(codage_sortie_transliteral); return(tampon); } unsigned char * reencodage(struct_processus *s_etat_processus, unsigned char *chaine_entree, unsigned char *codage_entree, unsigned char *codage_sortie) { # define d_LONGUEUR 1024 iconv_t transcodage; size_t ios; size_t longueur_entree; size_t longueur_sortie; unsigned char *buffer_entree; unsigned char *buffer_sortie; unsigned char *chaine_sortie; unsigned char *pointeur; unsigned char *tampon; if ((transcodage = iconv_open(codage_sortie, codage_entree)) == (iconv_t) -1) { // On affiche une erreur ici car la fonction d'affichage // de l'erreur utilise la macro printf() donc une // opération de translitération qui échouera elle aussi. // Le positionnement de l'erreur permet de sortir du programme. if ((*s_etat_processus).langue == 'F') { fprintf(stderr, "+++Erreur : Erreur de transcodage\n"); } else { fprintf(stderr, "+++Error : Transcodage error\n"); } (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage; return(NULL); } buffer_entree = chaine_entree; longueur_entree = strlen(chaine_entree); if ((chaine_sortie = malloc(sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } chaine_sortie[0] = d_code_fin_chaine; if ((buffer_sortie = malloc((d_LONGUEUR + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } do { longueur_sortie = d_LONGUEUR; pointeur = buffer_sortie; if ((ios = iconv(transcodage, (char **) &buffer_entree, &longueur_entree, (char **) &pointeur, &longueur_sortie)) == (size_t) -1) { // On autorise les erreurs EINVAL si le caractère suivant est non // nul : la séquence d'entrée est continue sur le bloc suivant. if (errno == EINVAL) { if ((*(buffer_entree + 1)) == d_code_fin_chaine) { free(buffer_sortie); free(chaine_sortie); // On affiche une erreur ici car la fonction d'affichage // de l'erreur utilise la macro printf() donc une // opération de translitération qui échouera elle aussi. // Le positionnement de l'erreur permet de sortir du // programme. if ((*s_etat_processus).langue == 'F') { fprintf(stderr, "+++Erreur : Erreur de transcodage\n"); } else { fprintf(stderr, "+++Error : Transcodage error\n"); } (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage; return(NULL); } } // Si la séquence d'entrée est invalide, on reçoit une erreur // EILSEQ. else if (errno == EILSEQ) { free(buffer_sortie); free(chaine_sortie); // On affiche une erreur ici car la fonction d'affichage // de l'erreur utilise la macro printf() donc une // opération de translitération qui échouera elle aussi. // Le positionnement de l'erreur permet de sortir du programme. if ((*s_etat_processus).langue == 'F') { fprintf(stderr, "+++Erreur : Erreur de transcodage\n"); } else { fprintf(stderr, "+++Error : Transcodage error\n"); } (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage; return(NULL); } } tampon = chaine_sortie; (*pointeur) = d_code_fin_chaine; if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie); free(tampon); } while((*buffer_entree) != d_code_fin_chaine); free(buffer_sortie); iconv_close(transcodage); return(chaine_sortie); } /* ================================================================================ Fonctions spécifiques ================================================================================ Entrées : -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void localisation_courante(struct_processus *s_etat_processus) { char **arguments; int ios; int pipes_entree[2]; int pipes_erreur[2]; int pipes_sortie[2]; int status; integer8 i; integer8 longueur_lecture; integer8 nombre_arguments; integer8 nombre_iterations; integer8 pointeur; pid_t pid; unsigned char *tampon; if ((arguments = malloc(3 * sizeof(char **))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } strcpy(arguments[0], "locale"); strcpy(arguments[1], "charmap"); arguments[2] = NULL; nombre_arguments = 2; if (pipe(pipes_entree) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (pipe(pipes_sortie) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (pipe(pipes_erreur) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } verrouillage_threads_concurrents(s_etat_processus); pid = fork(); deverrouillage_threads_concurrents(s_etat_processus); if (pid < 0) { if (close(pipes_entree[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_entree[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_sortie[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_sortie[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_erreur[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_erreur[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } (*s_etat_processus).erreur_systeme = d_es_processus; return; } else if (pid == 0) { if (close(pipes_entree[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_sortie[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_erreur[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (pipes_entree[0] != STDIN_FILENO) { if (dup2(pipes_entree[0], STDIN_FILENO) == -1) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } if (pipes_sortie[1] != STDOUT_FILENO) { if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } if (pipes_sortie[1] != STDERR_FILENO) { if (dup2(pipes_sortie[1], STDERR_FILENO) == -1) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } if (nombre_arguments != 0) { execvp(arguments[0], arguments); } else { exit(EXIT_SUCCESS); } /* * L'appel système execvp() a généré une erreur et n'a pu exécuter * argument[0] (fichier non exécutable ou inexistant). */ close(pipes_entree[0]); close(pipes_sortie[1]); for(i = 0; i < nombre_arguments; i++) { free(arguments[i]); } free(arguments); (*s_etat_processus).erreur_systeme = d_es_processus; /* * Envoi d'une erreur dans le pipe idoine. On ne regarde pas * le nombre d'octets écrits car l'erreur ne pourra de toute * façon pas être traitée. */ write_atomic(s_etat_processus, pipes_erreur[1], " ", 1); close(pipes_erreur[1]); exit(EXIT_SUCCESS); } else { if (close(pipes_entree[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_sortie[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_erreur[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_entree[1]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } do { if (kill(pid, 0) != 0) { break; } /* * Récupération de la valeur de retour du processus détaché */ # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (waitpid(pid, &status, 0) == -1) { # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } (*s_etat_processus).erreur_systeme = d_es_processus; return; } # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } } while((!WIFEXITED(status)) && (!WIFSIGNALED(status))); longueur_lecture = 256; pointeur = 0; nombre_iterations = 1; if ((tampon = malloc(((size_t) (longueur_lecture + 1)) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } tampon[0] = d_code_fin_chaine; # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return; } while((ios = (int) read_atomic(s_etat_processus, pipes_sortie[0], &(tampon[pointeur]), (size_t) longueur_lecture)) > 0) { # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } tampon[pointeur + ios] = d_code_fin_chaine; pointeur += longueur_lecture; nombre_iterations++; if ((tampon = realloc(tampon, ((size_t) ((nombre_iterations * longueur_lecture) + 1)) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } if (strlen(tampon) == 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } tampon[strlen(tampon) - 1] = d_code_fin_chaine; if (ios == -1) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (close(pipes_sortie[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (strlen(tampon) > 0) { (*s_etat_processus).localisation = tampon; } else { free(tampon); if (((*s_etat_processus).localisation = malloc((strlen(d_locale) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } strcpy((*s_etat_processus).localisation, d_locale); } for(i = 0; i < nombre_arguments; i++) { free(arguments[i]); } free(arguments); # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0) { // Le processus fils renvoie une erreur. free(tampon); if (((*s_etat_processus).localisation = malloc((strlen(d_locale) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } strcpy((*s_etat_processus).localisation, d_locale); } # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } if (close(pipes_erreur[0]) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } return; } int transliterated_fprintf(struct_processus *s_etat_processus, file *flux, const char *format, ...) { int ios; unsigned char *tampon; unsigned char *tampon2; va_list arguments; va_start(arguments, format); # ifdef OS2 unsigned char *ptr_e;; unsigned char *ptr_l;; unsigned char *tampon3; unsigned long i; # endif if (valsprintf(&tampon, format, arguments) < 0) { va_end(arguments); if (s_etat_processus != NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; } return(-1); } va_end(arguments); if (s_etat_processus != NULL) { if ((tampon2 = transliteration(s_etat_processus, tampon, d_locale, (*s_etat_processus).localisation)) == NULL) { free(tampon); return(-1); } free(tampon); } else { tampon2 = tampon; } # ifdef OS2 if ((flux == stderr) || (flux == stdout)) { i = 0; ptr_l = tampon2; while((*ptr_l) != d_code_fin_chaine) { if ((*ptr_l) == '\n') { i++; } ptr_l++; } if ((tampon3 = malloc((strlen(tampon2) + i + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(-1); } ptr_e = tampon3; ptr_l = tampon2; while((*ptr_l) != d_code_fin_chaine) { (*ptr_e) = (*ptr_l); if ((*ptr_l) == '\n') { (*(++ptr_e)) = '\r'; ptr_e++; ptr_l++; } else { ptr_e++; ptr_l++; } } (*ptr_e) = d_code_fin_chaine; free(tampon2); tampon2 = tampon3; } # endif # ifdef SunOS while((ios = fprintf(flux, "%s", tampon2)) < 0) { if ((errno != EINTR) && (errno != 0)) { break; } } # else ios = fprintf(flux, "%s", tampon2); # endif free(tampon2); return(ios); } int tex_fprintf(struct_processus *s_etat_processus, file *flux, const char *format, ...) { int ios; unsigned char *tampon; unsigned char *tampon2; va_list arguments; va_start(arguments, format); if (valsprintf(&tampon, format, arguments) < 0) { va_end(arguments); if (s_etat_processus != NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; } return(-1); } va_end(arguments); if ((tampon2 = transliteration(s_etat_processus, tampon, d_locale, ds_tex_encodage_3)) == NULL) { free(tampon); return(-1); } free(tampon); # ifdef SunOS while((ios = fprintf(flux, "%s", tampon2)) < 0) { if ((errno != EINTR) && (errno != 0)) { break; } } # else ios = fprintf(flux, "%s", tampon2); # endif free(tampon2); return(ios); } #undef readline unsigned char * readline_wrapper(unsigned char *invite) { unsigned char *chaine; chaine = readline(invite); printf("\r"); return(chaine); } #define fprintf NULL #define printf NULL // vim: ts=4