/* ================================================================================ RPL/2 (R) version 4.0.12 Copyright (C) 1989-2010 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) { (*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(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 et EILSEQ if (errno == EILSEQ) { free(buffer_sortie); free(chaine_sortie); (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage; return(NULL); } } tampon = (unsigned char *) 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; logical1 drapeau_fin; long i; long nombre_arguments; pid_t pid; sigset_t oldset; sigset_t set; struct sigaction action_passee; unsigned char *tampon; unsigned long longueur_lecture; unsigned long nombre_iterations; unsigned long pointeur; 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; drapeau_fin = d_faux; 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; } sigfillset(&set); pthread_sigmask(SIG_BLOCK, &set, &oldset); verrouillage_threads_concurrents(s_etat_processus); pid = fork(); deverrouillage_threads_concurrents(s_etat_processus); pthread_sigmask(SIG_SETMASK, &oldset, NULL); sigpending(&set); 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é */ if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (waitpid(pid, &status, 0) == -1) { if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1) { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } (*s_etat_processus).erreur_systeme = d_es_processus; return; } if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1) { 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((longueur_lecture + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } while((ios = read_atomic(s_etat_processus, pipes_sortie[0], &(tampon[pointeur]), longueur_lecture)) > 0) { while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1) { 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, ((nombre_iterations * longueur_lecture) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1) { 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; } (*s_etat_processus).localisation = tampon; if (sigaction(SIGINT, &action_passee, NULL) != 0) { for(i = 0; i < nombre_arguments; i++) { free(arguments[i]); } free(arguments); (*s_etat_processus).erreur_systeme = d_es_signal; return; } for(i = 0; i < nombre_arguments; i++) { free(arguments[i]); } free(arguments); if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) { (*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. while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1) { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return; } } (*s_etat_processus).erreur_execution = d_ex_erreur_processus; return; } while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1) { 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); 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 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); } #define fprintf NULL #define printf NULL // vim: ts=4