File:  [local] / rpl / src / transliteration.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Jan 26 15:22:44 2010 UTC (14 years, 3 months ago) by bertrand
Branches: JKB
CVS tags: start


Commit initial.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.0.9
    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>