File:  [local] / rpl / src / transliteration.c
Revision 1.41: download - view: text, annotated - select for diffs - revision graph
Thu Sep 15 17:51:44 2011 UTC (12 years, 7 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Suite des patches. Attention, il reste une 'race condition' quelque part...

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.3
    4:   Copyright (C) 1989-2011 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 "tex-conv.h"
   25: 
   26: #include <stdarg.h>
   27: 
   28: #undef fprintf
   29: #undef printf
   30: 
   31: 
   32: /*
   33: ================================================================================
   34:   Fonction de translitération
   35: ================================================================================
   36:   Entrées :
   37: --------------------------------------------------------------------------------
   38:   Sorties :
   39: --------------------------------------------------------------------------------
   40:   Effets de bord : néant
   41: ================================================================================
   42: */
   43: 
   44: unsigned char *
   45: transliteration(struct_processus *s_etat_processus,
   46:         unsigned char *chaine_entree,
   47:         unsigned char *codage_entree,
   48:         unsigned char *codage_sortie)
   49: {
   50:     unsigned char       *codage_sortie_transliteral;
   51:     unsigned char       *tampon;
   52: 
   53:     if ((codage_sortie_transliteral = malloc((strlen(codage_sortie)
   54:             + strlen("//TRANSLIT") + 1) * sizeof(unsigned char))) == NULL)
   55:     {
   56:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   57:         return(NULL);
   58:     }
   59: 
   60:     sprintf(codage_sortie_transliteral, "%s//TRANSLIT", codage_sortie);
   61: 
   62:     tampon = reencodage(s_etat_processus, chaine_entree,
   63:             codage_entree, codage_sortie_transliteral);
   64:     free(codage_sortie_transliteral);
   65: 
   66:     return(tampon);
   67: }
   68: 
   69: 
   70: unsigned char *
   71: reencodage(struct_processus *s_etat_processus,
   72:         unsigned char *chaine_entree,
   73:         unsigned char *codage_entree,
   74:         unsigned char *codage_sortie)
   75: {
   76: #   define              d_LONGUEUR  1024
   77: 
   78:     iconv_t             transcodage;
   79: 
   80:     size_t              ios;
   81:     size_t              longueur_entree;
   82:     size_t              longueur_sortie;
   83: 
   84:     unsigned char       *buffer_entree;
   85:     unsigned char       *buffer_sortie;
   86:     unsigned char       *chaine_sortie;
   87:     unsigned char       *pointeur;
   88:     unsigned char       *tampon;
   89: 
   90:     if ((transcodage = iconv_open(codage_sortie, codage_entree)) ==
   91:             (iconv_t) -1)
   92:     {
   93:         (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
   94:         return(NULL);
   95:     }
   96: 
   97:     buffer_entree = chaine_entree;
   98:     longueur_entree = strlen(chaine_entree);
   99: 
  100:     if ((chaine_sortie = malloc(sizeof(unsigned char))) == NULL)
  101:     {
  102:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  103:         return(NULL);
  104:     }
  105: 
  106:     chaine_sortie[0] = d_code_fin_chaine;
  107: 
  108:     if ((buffer_sortie = malloc((d_LONGUEUR + 1) * sizeof(unsigned char)))
  109:             == NULL)
  110:     {
  111:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  112:         return(NULL);
  113:     }
  114: 
  115:     do
  116:     {
  117:         longueur_sortie = d_LONGUEUR;
  118:         pointeur = buffer_sortie;
  119: 
  120:         if ((ios = iconv(transcodage, (char **) &buffer_entree,
  121:                 &longueur_entree, (char **) &pointeur, &longueur_sortie))
  122:                 == (size_t) -1)
  123:         {
  124:             // On autorise les erreurs EINVAL et EILSEQ
  125:             if (errno == EILSEQ)
  126:             {
  127:                 free(buffer_sortie);
  128:                 free(chaine_sortie);
  129: 
  130:                 (*s_etat_processus).erreur_execution = d_ex_erreur_transcodage;
  131:                 return(NULL);
  132:             }
  133:         }
  134: 
  135:         tampon = chaine_sortie;
  136:         (*pointeur) = d_code_fin_chaine;
  137: 
  138:         if ((chaine_sortie = malloc((strlen(tampon) + strlen(buffer_sortie) + 1)
  139:                 * sizeof(unsigned char))) == NULL)
  140:         {
  141:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  142:             return(NULL);
  143:         }
  144: 
  145:         sprintf(chaine_sortie, "%s%s", tampon, buffer_sortie);
  146:         free(tampon);
  147:     } while((*buffer_entree) != d_code_fin_chaine);
  148: 
  149:     free(buffer_sortie);
  150:     iconv_close(transcodage);
  151: 
  152:     return(chaine_sortie);
  153: }
  154: 
  155: 
  156: /*
  157: ================================================================================
  158:   Fonctions spécifiques
  159: ================================================================================
  160:   Entrées :
  161: --------------------------------------------------------------------------------
  162:   Sorties :
  163: --------------------------------------------------------------------------------
  164:   Effets de bord : néant
  165: ================================================================================
  166: */
  167: 
  168: void
  169: localisation_courante(struct_processus *s_etat_processus)
  170: {
  171:     char                        **arguments;
  172: 
  173:     int                         ios;
  174:     int                         pipes_entree[2];
  175:     int                         pipes_erreur[2];
  176:     int                         pipes_sortie[2];
  177:     int                         status;
  178: 
  179:     long                        i;
  180:     long                        nombre_arguments;
  181: 
  182:     pid_t                       pid;
  183: 
  184:     struct sigaction            action_passee;
  185: 
  186:     unsigned char               *tampon;
  187: 
  188:     unsigned long               longueur_lecture;
  189:     unsigned long               nombre_iterations;
  190:     unsigned long               pointeur;
  191: 
  192:     if ((arguments = malloc(3 * sizeof(char **))) == NULL)
  193:     {
  194:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  195:         return;
  196:     }
  197: 
  198:     if ((arguments[0] = malloc((strlen("locale") + 1) * sizeof(char))) == NULL)
  199:     {
  200:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  201:         return;
  202:     }
  203: 
  204:     if ((arguments[1] = malloc((strlen("charmap") + 1) * sizeof(char))) == NULL)
  205:     {
  206:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  207:         return;
  208:     }
  209: 
  210:     strcpy(arguments[0], "locale");
  211:     strcpy(arguments[1], "charmap");
  212:     arguments[2] = NULL;
  213: 
  214:     nombre_arguments = 2;
  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:     verrouillage_threads_concurrents(s_etat_processus);
  235:     pid = fork();
  236:     deverrouillage_threads_concurrents(s_etat_processus);
  237: 
  238:     if (pid < 0)
  239:     {
  240:         if (close(pipes_entree[0]) != 0)
  241:         {
  242:             (*s_etat_processus).erreur_systeme = d_es_processus;
  243:             return;
  244:         }
  245: 
  246:         if (close(pipes_entree[1]) != 0)
  247:         {
  248:             (*s_etat_processus).erreur_systeme = d_es_processus;
  249:             return;
  250:         }
  251: 
  252:         if (close(pipes_sortie[0]) != 0)
  253:         {
  254:             (*s_etat_processus).erreur_systeme = d_es_processus;
  255:             return;
  256:         }
  257: 
  258:         if (close(pipes_sortie[1]) != 0)
  259:         {
  260:             (*s_etat_processus).erreur_systeme = d_es_processus;
  261:             return;
  262:         }
  263: 
  264:         if (close(pipes_erreur[0]) != 0)
  265:         {
  266:             (*s_etat_processus).erreur_systeme = d_es_processus;
  267:             return;
  268:         }
  269: 
  270:         if (close(pipes_erreur[1]) != 0)
  271:         {
  272:             (*s_etat_processus).erreur_systeme = d_es_processus;
  273:             return;
  274:         }
  275: 
  276:         (*s_etat_processus).erreur_systeme = d_es_processus;
  277:         return;
  278:     }
  279:     else if (pid == 0)
  280:     {
  281:         if (close(pipes_entree[1]) != 0)
  282:         {
  283:             (*s_etat_processus).erreur_systeme = d_es_processus;
  284:             return;
  285:         }
  286: 
  287:         if (close(pipes_sortie[0]) != 0)
  288:         {
  289:             (*s_etat_processus).erreur_systeme = d_es_processus;
  290:             return;
  291:         }
  292: 
  293:         if (close(pipes_erreur[0]) != 0)
  294:         {
  295:             (*s_etat_processus).erreur_systeme = d_es_processus;
  296:             return;
  297:         }
  298: 
  299:         if (pipes_entree[0] != STDIN_FILENO)
  300:         {
  301:             if (dup2(pipes_entree[0], STDIN_FILENO) == -1)
  302:             {
  303:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  304:                 return;
  305:             }
  306:         }
  307: 
  308:         if (pipes_sortie[1] != STDOUT_FILENO)
  309:         {
  310:             if (dup2(pipes_sortie[1], STDOUT_FILENO) == -1)
  311:             {
  312:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  313:                 return;
  314:             }
  315:         }
  316: 
  317:         if (pipes_sortie[1] != STDERR_FILENO)
  318:         {
  319:             if (dup2(pipes_sortie[1], STDERR_FILENO) == -1)
  320:             {
  321:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  322:                 return;
  323:             }
  324:         }
  325: 
  326:         if (nombre_arguments != 0)
  327:         {
  328:             execvp(arguments[0], arguments);
  329:         }
  330:         else
  331:         {
  332:             exit(EXIT_SUCCESS);
  333:         }
  334: 
  335:         /*
  336:          * L'appel système execvp() a généré une erreur et n'a pu exécuter
  337:          * argument[0] (fichier non exécutable ou inexistant).
  338:          */
  339: 
  340:         close(pipes_entree[0]);
  341:         close(pipes_sortie[1]);
  342: 
  343:         for(i = 0; i < nombre_arguments; i++)
  344:         {
  345:             free(arguments[i]);
  346:         }
  347: 
  348:         free(arguments);
  349:         (*s_etat_processus).erreur_systeme = d_es_processus;
  350: 
  351:         /*
  352:          * Envoi d'une erreur dans le pipe idoine. On ne regarde pas
  353:          * le nombre d'octets écrits car l'erreur ne pourra de toute
  354:          * façon pas être traitée.
  355:          */
  356: 
  357:         write_atomic(s_etat_processus, pipes_erreur[1], " ", 1);
  358:         close(pipes_erreur[1]);
  359: 
  360:         exit(EXIT_SUCCESS);
  361:     }
  362:     else
  363:     {
  364:         if (close(pipes_entree[0]) != 0)
  365:         {
  366:             (*s_etat_processus).erreur_systeme = d_es_processus;
  367:             return;
  368:         }
  369: 
  370:         if (close(pipes_sortie[1]) != 0)
  371:         {
  372:             (*s_etat_processus).erreur_systeme = d_es_processus;
  373:             return;
  374:         }
  375: 
  376:         if (close(pipes_erreur[1]) != 0)
  377:         {
  378:             (*s_etat_processus).erreur_systeme = d_es_processus;
  379:             return;
  380:         }
  381: 
  382:         if (close(pipes_entree[1]) != 0)
  383:         {
  384:             (*s_etat_processus).erreur_systeme = d_es_processus;
  385:             return;
  386:         }
  387: 
  388:         do
  389:         {
  390:             if (kill(pid, 0) != 0)
  391:             {
  392:                 break;
  393:             }
  394: 
  395:             /*
  396:              * Récupération de la valeur de retour du processus détaché
  397:              */
  398: 
  399:             if (pthread_mutex_unlock(&((*s_etat_processus).mutex_fork)) != 0)
  400:             {
  401:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  402:                 return;
  403:             }
  404: 
  405:             if (waitpid(pid, &status, 0) == -1)
  406:             {
  407:                 if (pthread_mutex_lock(&((*s_etat_processus).mutex_fork)) != 0)
  408:                 {
  409:                     (*s_etat_processus).erreur_systeme = d_es_processus;
  410:                     return;
  411:                 }
  412: 
  413:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  414:                 return;
  415:             }
  416: 
  417:             if (pthread_mutex_lock(&((*s_etat_processus).mutex_fork)) != 0)
  418:             {
  419:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  420:                 return;
  421:             }
  422:         } while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
  423: 
  424:         longueur_lecture = 256;
  425:         pointeur = 0;
  426:         nombre_iterations = 1;
  427: 
  428:         if ((tampon = malloc((longueur_lecture + 1) *
  429:                 sizeof(unsigned char))) == NULL)
  430:         {
  431:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  432:             return;
  433:         }
  434: 
  435:         tampon[0] = d_code_fin_chaine;
  436: 
  437:         if (pthread_mutex_unlock(&((*s_etat_processus).mutex_fork)) != 0)
  438:         {
  439:             (*s_etat_processus).erreur_systeme = d_es_processus;
  440:             return;
  441:         }
  442: 
  443:         while((ios = read_atomic(s_etat_processus,
  444:                 pipes_sortie[0], &(tampon[pointeur]),
  445:                 longueur_lecture)) > 0)
  446:         {
  447:             if (pthread_mutex_lock(&((*s_etat_processus).mutex_fork)) != 0)
  448:             {
  449:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  450:                 return;
  451:             }
  452: 
  453:             tampon[pointeur + ios] = d_code_fin_chaine;
  454:             pointeur += longueur_lecture;
  455:             nombre_iterations++;
  456: 
  457:             if ((tampon = realloc(tampon,
  458:                     ((nombre_iterations * longueur_lecture) + 1) *
  459:                     sizeof(unsigned char))) == NULL)
  460:             {
  461:                 (*s_etat_processus).erreur_systeme =
  462:                         d_es_allocation_memoire;
  463:                 return;
  464:             }
  465: 
  466:             if (pthread_mutex_unlock(&((*s_etat_processus).mutex_fork)) != 0)
  467:             {
  468:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  469:                 return;
  470:             }
  471:         }
  472: 
  473:         if (pthread_mutex_lock(&((*s_etat_processus).mutex_fork)) != 0)
  474:         {
  475:             (*s_etat_processus).erreur_systeme = d_es_processus;
  476:             return;
  477:         }
  478: 
  479:         if (strlen(tampon) == 0)
  480:         {
  481:             (*s_etat_processus).erreur_systeme = d_es_processus;
  482:             return;
  483:         }
  484: 
  485:         tampon[strlen(tampon) - 1] = d_code_fin_chaine;
  486: 
  487:         if (ios == -1)
  488:         {
  489:             (*s_etat_processus).erreur_systeme = d_es_processus;
  490:             return;
  491:         }
  492: 
  493:         if (close(pipes_sortie[0]) != 0)
  494:         {
  495:             (*s_etat_processus).erreur_systeme = d_es_processus;
  496:             return;
  497:         }
  498: 
  499:         if (strlen(tampon) > 0)
  500:         {
  501:             (*s_etat_processus).localisation = tampon;
  502:         }
  503:         else
  504:         {
  505:             free(tampon);
  506: 
  507:             if (((*s_etat_processus).localisation = malloc((strlen(d_locale)
  508:                     + 1) * sizeof(unsigned char))) == NULL)
  509:             {
  510:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  511:                 return;
  512:             }
  513: 
  514:             strcpy((*s_etat_processus).localisation, d_locale);
  515:         }
  516: 
  517:         if (sigaction(SIGINT, &action_passee, NULL) != 0)
  518:         {
  519:             for(i = 0; i < nombre_arguments; i++)
  520:             {
  521:                 free(arguments[i]);
  522:             }
  523: 
  524:             free(arguments);
  525:             (*s_etat_processus).erreur_systeme = d_es_signal;
  526:             return;
  527:         }
  528: 
  529:         for(i = 0; i < nombre_arguments; i++)
  530:         {
  531:             free(arguments[i]);
  532:         }
  533: 
  534:         free(arguments);
  535: 
  536:         if (pthread_mutex_unlock(&((*s_etat_processus).mutex_fork)) != 0)
  537:         {
  538:             (*s_etat_processus).erreur_systeme = d_es_processus;
  539:             return;
  540:         }
  541: 
  542:         if (read_atomic(s_etat_processus, pipes_erreur[0], tampon, 1) > 0)
  543:         {
  544:             // Le processus fils renvoie une erreur.
  545: 
  546:             free(tampon);
  547: 
  548:             if (((*s_etat_processus).localisation = malloc((strlen(d_locale)
  549:                     + 1) * sizeof(unsigned char))) == NULL)
  550:             {
  551:                 (*s_etat_processus).erreur_systeme = d_es_processus;
  552:                 return;
  553:             }
  554: 
  555:             strcpy((*s_etat_processus).localisation, d_locale);
  556:         }
  557: 
  558:         if (pthread_mutex_lock(&((*s_etat_processus).mutex_fork)) != 0)
  559:         {
  560:             (*s_etat_processus).erreur_systeme = d_es_processus;
  561:             return;
  562:         }
  563: 
  564:         if (close(pipes_erreur[0]) != 0)
  565:         {
  566:             (*s_etat_processus).erreur_systeme = d_es_processus;
  567:             return;
  568:         }
  569:     }
  570: 
  571:     return;
  572: }
  573: 
  574: 
  575: int
  576: transliterated_fprintf(struct_processus *s_etat_processus, file *flux,
  577:         const char *format, ...)
  578: {
  579:     int             ios;
  580: 
  581:     unsigned char   *tampon;
  582:     unsigned char   *tampon2;
  583: 
  584:     va_list         arguments;
  585: 
  586:     va_start(arguments, format);
  587: 
  588: #   ifdef OS2
  589:     unsigned char       *ptr_e;;
  590:     unsigned char       *ptr_l;;
  591:     unsigned char       *tampon3;
  592: 
  593:     unsigned long       i;
  594: #   endif
  595: 
  596:     if (valsprintf(&tampon, format, arguments) < 0)
  597:     {
  598:         va_end(arguments);
  599: 
  600:         if (s_etat_processus != NULL)
  601:         {
  602:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  603:         }
  604: 
  605:         return(-1);
  606:     }
  607: 
  608:     va_end(arguments);
  609: 
  610:     if (s_etat_processus != NULL)
  611:     {
  612:         if ((tampon2 = transliteration(s_etat_processus, tampon,
  613:                 d_locale, (*s_etat_processus).localisation)) == NULL)
  614:         {
  615:             free(tampon);
  616:             return(-1);
  617:         }
  618: 
  619:         free(tampon);
  620:     }
  621:     else
  622:     {
  623:         tampon2 = tampon;
  624:     }
  625: 
  626: #   ifdef OS2
  627:     if ((flux == stdin) || (flux == stdout))
  628:     {
  629:         i = 0;
  630:         ptr_l = tampon2;
  631: 
  632:         while((*ptr_l) != d_code_fin_chaine)
  633:         {
  634:             if ((*ptr_l) == '\n')
  635:             {
  636:                 i++;
  637:             }
  638: 
  639:             ptr_l++;
  640:         }
  641: 
  642:         if ((tampon3 = malloc((strlen(tampon2) + i + 1) *
  643:                 sizeof(unsigned char))) == NULL)
  644:         {
  645:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  646:             return(NULL);
  647:         }
  648: 
  649:         ptr_e = tampon3;
  650:         ptr_l = tampon2;
  651: 
  652:         while((*ptr_l) != d_code_fin_chaine)
  653:         {
  654:             (*ptr_e) = (*ptr_l);
  655: 
  656:             if ((*ptr_l) == '\n')
  657:             {
  658:                 (*(++ptr_e)) = '\r';
  659:                 ptr_e++;
  660:                 ptr_l++;
  661:             }
  662:             else
  663:             {
  664:                 ptr_e++;
  665:                 ptr_l++;
  666:             }
  667:         }
  668: 
  669:         (*ptr_e) = d_code_fin_chaine;
  670: 
  671:         free(tampon2);
  672:         tampon2 = tampon3;
  673:     }
  674: #   endif
  675: 
  676: #   ifdef SunOS
  677:     while((ios = fprintf(flux, "%s", tampon2)) < 0)
  678:     {
  679:         if ((errno != EINTR) && (errno != 0))
  680:         {
  681:             break;
  682:         }
  683:     }
  684: #   else
  685:     ios = fprintf(flux, "%s", tampon2);
  686: #   endif
  687: 
  688:     free(tampon2);
  689: 
  690:     return(ios);
  691: }
  692: 
  693: 
  694: int
  695: tex_fprintf(struct_processus *s_etat_processus,
  696:         file *flux, const char *format, ...)
  697: {
  698:     int             ios;
  699: 
  700:     unsigned char   *tampon;
  701:     unsigned char   *tampon2;
  702: 
  703:     va_list         arguments;
  704: 
  705:     va_start(arguments, format);
  706: 
  707:     if (valsprintf(&tampon, format, arguments) < 0)
  708:     {
  709:         va_end(arguments);
  710: 
  711:         if (s_etat_processus != NULL)
  712:         {
  713:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  714:         }
  715: 
  716:         return(-1);
  717:     }
  718: 
  719:     va_end(arguments);
  720: 
  721:     if ((tampon2 = transliteration(s_etat_processus, tampon,
  722:             d_locale, ds_tex_encodage_3)) == NULL)
  723:     {
  724:         free(tampon);
  725:         return(-1);
  726:     }
  727: 
  728:     free(tampon);
  729: 
  730: #   ifdef SunOS
  731:     while((ios = fprintf(flux, "%s", tampon2)) < 0)
  732:     {
  733:         if ((errno != EINTR) && (errno != 0))
  734:         {
  735:             break;
  736:         }
  737:     }
  738: #   else
  739:     ios = fprintf(flux, "%s", tampon2);
  740: #   endif
  741: 
  742:     free(tampon2);
  743: 
  744:     return(ios);
  745: }
  746: 
  747: #undef readline
  748: 
  749: unsigned char *
  750: readline_wrapper(unsigned char *invite)
  751: {
  752:     unsigned char       *chaine;
  753: 
  754:     chaine = readline(invite);
  755:     printf("\r");
  756: 
  757:     return(chaine);
  758: }
  759: 
  760: 
  761: #define fprintf NULL
  762: #define printf NULL
  763: 
  764: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>