Annotation of rpl/src/transliteration.c, revision 1.4

1.1       bertrand    1: /*
                      2: ================================================================================
1.4     ! bertrand    3:   RPL/2 (R) version 4.0.11
1.1       bertrand    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);
1.3       bertrand  124:                free(chaine_sortie);
                    125: 
1.1       bertrand  126:                (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
                    127:                return(NULL);
                    128:            }
                    129:        }
                    130: 
                    131:        tampon = (unsigned char *) chaine_sortie;
                    132:        (*pointeur) = d_code_fin_chaine;
                    133: 
                    134:        if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1)
                    135:                * sizeof(unsigned char))) == NULL)
                    136:        {
                    137:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    138:            return(NULL);
                    139:        }
                    140: 
                    141:        sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie);
                    142:        free(tampon);
                    143:    } while((*buffer_entree) != d_code_fin_chaine);
                    144: 
                    145:    free(buffer_sortie);
                    146:    iconv_close(transcodage);
                    147: 
                    148:    return(chaine_sortie);
                    149: }
                    150: 
                    151: 
                    152: /*
                    153: ================================================================================
                    154:   Fonctions spécifiques
                    155: ================================================================================
                    156:   Entrées :
                    157: --------------------------------------------------------------------------------
                    158:   Sorties :
                    159: --------------------------------------------------------------------------------
                    160:   Effets de bord : néant
                    161: ================================================================================
                    162: */
                    163: 
                    164: void
                    165: localisation_courante(struct_processus *s_etat_processus)
                    166: {
                    167:    char                        **arguments;
                    168: 
                    169:    int                         ios;
                    170:    int                         pipes_entree[2];
                    171:    int                         pipes_erreur[2];
                    172:    int                         pipes_sortie[2];
                    173:    int                         status;
                    174: 
                    175:    logical1                    drapeau_fin;
                    176: 
                    177:    long                        i;
                    178:    long                        nombre_arguments;
                    179: 
                    180:    pid_t                       pid;
                    181: 
                    182:    sigset_t                    oldset;
                    183:    sigset_t                    set;
                    184: 
                    185:    struct sigaction            action_passee;
                    186: 
                    187:    unsigned char               *tampon;
                    188: 
                    189:    unsigned long               longueur_lecture;
                    190:    unsigned long               nombre_iterations;
                    191:    unsigned long               pointeur;
                    192: 
                    193:    if ((arguments = malloc(3 * sizeof(char **))) == NULL)
                    194:    {
                    195:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    196:        return;
                    197:    }
                    198: 
                    199:    if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL)
                    200:    {
                    201:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    202:        return;
                    203:    }
                    204: 
                    205:    if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL)
                    206:    {
                    207:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    208:        return;
                    209:    }
                    210: 
                    211:    strcpy(arguments[0], "locale");
                    212:    strcpy(arguments[1], "charmap");
                    213:    arguments[2] = NULL;
                    214: 
                    215:    nombre_arguments = 2;
                    216:    drapeau_fin = d_faux;
                    217: 
                    218:    if (pipe(pipes_entree) != 0)
                    219:    {
                    220:        (*s_etat_processus).erreur_systeme = d_es_processus;
                    221:        return;
                    222:    }
                    223:        
                    224:    if (pipe(pipes_sortie) != 0)
                    225:    {
                    226:        (*s_etat_processus).erreur_systeme = d_es_processus;
                    227:        return;
                    228:    }
                    229: 
                    230:    if (pipe(pipes_erreur) != 0)
                    231:    {
                    232:        (*s_etat_processus).erreur_systeme = d_es_processus;
                    233:        return;
                    234:    }
                    235: 
                    236:    sigfillset(&set);
                    237:    pthread_sigmask(SIG_BLOCK, &set, &oldset);
                    238: 
                    239:    verrouillage_threads_concurrents(s_etat_processus);
                    240:    pid = fork();
                    241:    deverrouillage_threads_concurrents(s_etat_processus);
                    242: 
                    243:    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                    244:    sigpending(&set);
                    245: 
                    246:    if (pid < 0)
                    247:    {
                    248:        if (close(pipes_entree[0]) != 0)
                    249:        {
                    250:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    251:            return;
                    252:        }
                    253: 
                    254:        if (close(pipes_entree[1]) != 0)
                    255:        {
                    256:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    257:            return;
                    258:        }
                    259: 
                    260:        if (close(pipes_sortie[0]) != 0)
                    261:        {
                    262:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    263:            return;
                    264:        }
                    265: 
                    266:        if (close(pipes_sortie[1]) != 0)
                    267:        {
                    268:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    269:            return;
                    270:        }
                    271: 
                    272:        if (close(pipes_erreur[0]) != 0)
                    273:        {
                    274:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    275:            return;
                    276:        }
                    277: 
                    278:        if (close(pipes_erreur[1]) != 0)
                    279:        {
                    280:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    281:            return;
                    282:        }
                    283: 
                    284:        (*s_etat_processus).erreur_systeme = d_es_processus;
                    285:        return;
                    286:    }
                    287:    else if (pid == 0)
                    288:    {
                    289:        if (close(pipes_entree[1]) != 0)
                    290:        {
                    291:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    292:            return;
                    293:        }
                    294: 
                    295:        if (close(pipes_sortie[0]) != 0)
                    296:        {
                    297:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    298:            return;
                    299:        }
                    300: 
                    301:        if (close(pipes_erreur[0]) != 0)
                    302:        {
                    303:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    304:            return;
                    305:        }
                    306: 
                    307:        if (pipes_entree[0] != STDIN_FILENO)
                    308:        {
                    309:            if (dup2(pipes_entree[0], STDIN_FILENO) == -1)
                    310:            {
                    311:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    312:                return;
                    313:            }
                    314:        }
                    315: 
                    316:        if (pipes_sortie[1] != STDOUT_FILENO)
                    317:        {
                    318:            if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1)
                    319:            {
                    320:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    321:                return;
                    322:            }
                    323:        }
                    324: 
                    325:        if (pipes_sortie[1] != STDERR_FILENO)
                    326:        {
                    327:            if (dup2(pipes_sortie[1], STDERR_FILENO) == -1)
                    328:            {
                    329:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    330:                return;
                    331:            }
                    332:        }
                    333: 
                    334:        if (nombre_arguments != 0)
                    335:        {
                    336:            execvp(arguments[0], arguments);
                    337:        }
                    338:        else
                    339:        {
                    340:            exit(EXIT_SUCCESS);
                    341:        }
                    342: 
                    343:        /*
                    344:         * L'appel système execvp() a généré une erreur et n'a pu exécuter
                    345:         * argument[0] (fichier non exécutable ou inexistant).
                    346:         */
                    347: 
                    348:        close(pipes_entree[0]);
                    349:        close(pipes_sortie[1]);
                    350: 
                    351:        for(i = 0; i < nombre_arguments; i++)
                    352:        {
                    353:            free(arguments[i]);
                    354:        }
                    355: 
                    356:        free(arguments);
                    357:        (*s_etat_processus).erreur_systeme = d_es_processus;
                    358: 
                    359:        /*
                    360:         * Envoi d'une erreur dans le pipe idoine. On ne regarde pas
                    361:         * le nombre d'octets écrits car l'erreur ne pourra de toute
                    362:         * façon pas être traitée.
                    363:         */
                    364: 
                    365:        write_atomic(s_etat_processus, pipes_erreur[1], " ", 1);
                    366:        close(pipes_erreur[1]);
                    367: 
                    368:        exit(EXIT_SUCCESS);
                    369:    }
                    370:    else
                    371:    {
                    372:        if (close(pipes_entree[0]) != 0)
                    373:        {
                    374:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    375:            return;
                    376:        }
                    377: 
                    378:        if (close(pipes_sortie[1]) != 0)
                    379:        {
                    380:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    381:            return;
                    382:        }
                    383: 
                    384:        if (close(pipes_erreur[1]) != 0)
                    385:        {
                    386:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    387:            return;
                    388:        }
                    389: 
                    390:        if (close(pipes_entree[1]) != 0)
                    391:        {
                    392:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    393:            return;
                    394:        }
                    395: 
                    396:        do
                    397:        {
                    398:            if (kill(pid, 0) != 0)
                    399:            {
                    400:                break;
                    401:            }
                    402: 
                    403:            /*
                    404:             * Récupération de la valeur de retour du processus détaché
                    405:             */
                    406: 
                    407:            if (sem_post(&((*s_etat_processus).semaphore_fork))
                    408:                    != 0)
                    409:            {
                    410:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    411:                return;
                    412:            }
                    413: 
                    414:            if (waitpid(pid, &status, 0) == -1)
                    415:            {
                    416:                if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
                    417:                {
                    418:                    if (errno != EINTR)
                    419:                    {
                    420:                        (*s_etat_processus).erreur_systeme = d_es_processus;
                    421:                        return;
                    422:                    }
                    423:                }
                    424: 
                    425:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    426:                return;
                    427:            }
                    428: 
                    429:            if (sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
                    430:            {
                    431:                if (errno != EINTR)
                    432:                {
                    433:                    (*s_etat_processus).erreur_systeme = d_es_processus;
                    434:                    return;
                    435:                }
                    436:            }
                    437:        } while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
                    438: 
                    439:        longueur_lecture = 256;
                    440:        pointeur = 0;
                    441:        nombre_iterations = 1;
                    442: 
                    443:        if ((tampon = malloc((longueur_lecture + 1) *
                    444:                sizeof(unsigned char))) == NULL)
                    445:        {
                    446:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    447:            return;
                    448:        }
                    449: 
                    450:        if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
                    451:        {
                    452:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    453:            return;
                    454:        }
                    455: 
                    456:        while((ios = read_atomic(s_etat_processus,
                    457:                pipes_sortie[0], &(tampon[pointeur]),
                    458:                longueur_lecture)) > 0)
                    459:        {
                    460:            while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
                    461:            {
                    462:                if (errno != EINTR)
                    463:                {
                    464:                    (*s_etat_processus).erreur_systeme = d_es_processus;
                    465:                    return;
                    466:                }
                    467:            }
                    468: 
                    469:            tampon[pointeur + ios] = d_code_fin_chaine;
                    470:            pointeur += longueur_lecture;
                    471:            nombre_iterations++;
                    472: 
                    473:            if ((tampon = realloc(tampon,
                    474:                    ((nombre_iterations * longueur_lecture) + 1) *
                    475:                    sizeof(unsigned char))) == NULL)
                    476:            {
                    477:                (*s_etat_processus).erreur_systeme =
                    478:                        d_es_allocation_memoire;
                    479:                return;
                    480:            }
                    481: 
                    482:            if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
                    483:            {
                    484:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    485:                return;
                    486:            }
                    487:        }
                    488: 
                    489:        while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
                    490:        {
                    491:            if (errno != EINTR)
                    492:            {
                    493:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    494:                return;
                    495:            }
                    496:        }
                    497: 
                    498:        if (strlen(tampon) == 0)
                    499:        {
                    500:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    501:            return;
                    502:        }
                    503: 
                    504:        tampon[strlen(tampon) - 1] = d_code_fin_chaine;
                    505: 
                    506:        if (ios == -1)
                    507:        {
                    508:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    509:            return;
                    510:        }
                    511: 
                    512:        if (close(pipes_sortie[0]) != 0)
                    513:        {
                    514:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    515:            return;
                    516:        }
                    517: 
                    518:        (*s_etat_processus).localisation = tampon;
                    519: 
                    520:        if (sigaction(SIGINT, &action_passee, NULL) != 0)
                    521:        {
                    522:            for(i = 0; i < nombre_arguments; i++)
                    523:            {
                    524:                free(arguments[i]);
                    525:            }
                    526: 
                    527:            free(arguments);
                    528:            (*s_etat_processus).erreur_systeme = d_es_signal;
                    529:            return;
                    530:        }
                    531: 
                    532:        for(i = 0; i < nombre_arguments; i++)
                    533:        {
                    534:            free(arguments[i]);
                    535:        }
                    536: 
                    537:        free(arguments);
                    538: 
                    539:        if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0)
                    540:        {
                    541:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    542:            return;
                    543:        }
                    544: 
                    545:        if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0)
                    546:        {
                    547:            // Le processus fils renvoie une erreur.
                    548: 
                    549:            while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
                    550:            {
                    551:                if (errno != EINTR)
                    552:                {
                    553:                    (*s_etat_processus).erreur_systeme = d_es_processus;
                    554:                    return;
                    555:                }
                    556:            }
                    557: 
                    558:            (*s_etat_processus).erreur_execution = d_ex_erreur_processus;
                    559:            return;
                    560:        }
                    561: 
                    562:        while(sem_wait(&((*s_etat_processus).semaphore_fork)) == -1)
                    563:        {
                    564:            if (errno != EINTR)
                    565:            {
                    566:                (*s_etat_processus).erreur_systeme = d_es_processus;
                    567:                return;
                    568:            }
                    569:        }
                    570: 
                    571:        if (close(pipes_erreur[0]) != 0)
                    572:        {
                    573:            (*s_etat_processus).erreur_systeme = d_es_processus;
                    574:            return;
                    575:        }
                    576:    }
                    577: 
                    578:    return;
                    579: }
                    580: 
                    581: static int
                    582: vtransliterated_sprintf(char **strp, const char *fmt, va_list ap)
                    583: {
                    584:    size_t bs, s;
                    585:    char *b = NULL;
                    586:    va_list cap;
                    587: 
                    588:    va_copy(cap, ap);
                    589: 
                    590:    for(bs = 256;; bs *= 2)
                    591:    {
                    592:        va_copy(ap, cap);
                    593:        if (b != NULL) free(b);
                    594:        if ((b = malloc(sizeof(*b) * bs)) == NULL) return -1;
                    595:        if (((int) (s = vsnprintf(b, bs, fmt, ap))) < 0)
                    596:                { va_end(ap); free(b); return -1; }
                    597:        va_end(ap);
                    598:        if (s < bs) break;
                    599:    }
                    600: 
                    601:    if (((*strp) = realloc(b, ((s = strlen(b)) + 1) * sizeof(*b)))
                    602:            == NULL) { free(b); return -1; }
                    603:    return s;
                    604: }
                    605: 
                    606: int
                    607: transliterated_fprintf(struct_processus *s_etat_processus, file *flux,
                    608:        const char *format, ...)
                    609: {
                    610:    int             ios;
                    611:    char            *tampon;
                    612:    unsigned char   *tampon2;
                    613:    va_list         arguments;
                    614: 
                    615:    va_start(arguments, format);
                    616: 
                    617:    if (vtransliterated_sprintf(&tampon, format, arguments) < 0)
                    618:    {
                    619:        va_end(arguments);
                    620: 
                    621:        if (s_etat_processus != NULL)
                    622:        {
                    623:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    624:        }
                    625: 
                    626:        return(-1);
                    627:    }
                    628: 
                    629:    va_end(arguments);
                    630: 
                    631:    if (s_etat_processus != NULL)
                    632:    {
                    633:        if ((tampon2 = transliteration(s_etat_processus, tampon,
                    634:                d_locale, (*s_etat_processus).localisation)) == NULL)
                    635:        {
                    636:            free(tampon);
                    637:            return(-1);
                    638:        }
                    639: 
                    640:        free(tampon);
                    641:    }
                    642:    else
                    643:    {
                    644:        tampon2 = tampon;
                    645:    }
                    646: 
                    647: #  ifdef SunOS
                    648:    while((ios = fprintf(flux, "%s", tampon2)) < 0)
                    649:    {
                    650:        if ((errno != EINTR) && (errno != 0))
                    651:        {
                    652:            break;
                    653:        }
                    654:    }
                    655: #  else
                    656:    ios = fprintf(flux, "%s", tampon2);
                    657: #  endif
                    658: 
                    659:    free(tampon2);
                    660: 
                    661:    return(ios);
                    662: }
                    663: 
                    664: #define fprintf NULL
                    665: #define printf NULL
                    666: 
                    667: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>