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

1.1       bertrand    1: /*
                      2: ================================================================================
1.2     ! bertrand    3:   RPL/2 (R) version 4.0.10
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);
                    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>