Annotation of 43BSD/ucb/error/errortouch.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)errortouch.c       5.1 (Berkeley) 5/31/85";
                      9: #endif not lint
                     10: 
                     11: #include <stdio.h>
                     12: #include <ctype.h>
                     13: #include <sys/types.h>
                     14: #include <sys/stat.h>
                     15: #include <signal.h>
                     16: #include "error.h"
                     17: 
                     18: /*
                     19:  *     Iterate through errors
                     20:  */
                     21: #define EITERATE(p, fv, i)     for (p = fv[i]; p < fv[i+1]; p++)
                     22: #define        ECITERATE(ei, p, lb)    for (ei = lb; p = errors[ei],ei < nerrors; ei++)
                     23: 
                     24: #define        FILEITERATE(fi, lb)     for (fi = lb; fi <= nfiles; fi++)
                     25: int    touchstatus = Q_YES;
                     26: 
                     27: findfiles(nerrors, errors, r_nfiles, r_files)
                     28:                int     nerrors;
                     29:        Eptr    *errors;
                     30:                int     *r_nfiles;
                     31:        Eptr    ***r_files;
                     32: {
                     33:                int     nfiles;
                     34:        Eptr    **files;
                     35: 
                     36:                char    *name;
                     37:        reg     int     ei;
                     38:                int     fi;
                     39:        reg     Eptr    errorp;
                     40: 
                     41:        nfiles = countfiles(errors);
                     42: 
                     43:        files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*));
                     44:        touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean));
                     45:        /*
                     46:         *      Now, partition off the error messages
                     47:         *      into those that are synchronization, discarded or
                     48:         *      not specific to any file, and those that were
                     49:         *      nulled or true errors.
                     50:         */
                     51:        files[0] = &errors[0];
                     52:        ECITERATE(ei, errorp, 0){
                     53:                if ( ! (NOTSORTABLE(errorp->error_e_class)))
                     54:                        break;
                     55:        }
                     56:        /*
                     57:         *      Now, and partition off all error messages
                     58:         *      for a given file.
                     59:         */
                     60:        files[1] = &errors[ei];
                     61:        touchedfiles[0] = touchedfiles[1] = FALSE;
                     62:        name = "\1";
                     63:        fi = 1;
                     64:        ECITERATE(ei, errorp, ei){
                     65:                if (   (errorp->error_e_class == C_NULLED)
                     66:                    || (errorp->error_e_class == C_TRUE) ){
                     67:                        if (strcmp(errorp->error_text[0], name) != 0){
                     68:                                name = errorp->error_text[0];
                     69:                                touchedfiles[fi] = FALSE;
                     70:                                files[fi] = &errors[ei];
                     71:                                fi++;
                     72:                        }
                     73:                }
                     74:        }
                     75:        files[fi] = &errors[nerrors];
                     76:        *r_nfiles = nfiles;
                     77:        *r_files = files;
                     78: }
                     79: 
                     80: int countfiles(errors)
                     81:        Eptr    *errors;
                     82: {
                     83:        char    *name;
                     84:        int     ei;
                     85:        reg     Eptr    errorp;
                     86: 
                     87:        int     nfiles;
                     88:        nfiles = 0;
                     89:        name = "\1";
                     90:        ECITERATE(ei, errorp, 0){
                     91:                if (SORTABLE(errorp->error_e_class)){
                     92:                        if (strcmp(errorp->error_text[0],name) != 0){
                     93:                                nfiles++;
                     94:                                name = errorp->error_text[0];
                     95:                        }
                     96:                }
                     97:        }
                     98:        return(nfiles);
                     99: }
                    100: char   *class_table[] = {
                    101:        /*C_UNKNOWN     0       */      "Unknown",
                    102:        /*C_IGNORE      1       */      "ignore",
                    103:        /*C_SYNC        2       */      "synchronization",
                    104:        /*C_DISCARD     3       */      "discarded",
                    105:        /*C_NONSPEC     4       */      "non specific",
                    106:        /*C_THISFILE    5       */      "specific to this file",
                    107:        /*C_NULLED      6       */      "nulled",
                    108:        /*C_TRUE        7       */      "true",
                    109:        /*C_DUPL        8       */      "duplicated"
                    110: };
                    111: 
                    112: int    class_count[C_LAST - C_FIRST] = {0};
                    113: 
                    114: filenames(nfiles, files)
                    115:        int     nfiles;
                    116:        Eptr    **files;
                    117: {
                    118:        reg     int     fi;
                    119:                char    *sep = " ";
                    120:        extern  char    *class_table[];
                    121:                int     someerrors;
                    122: 
                    123:        /*
                    124:         *      first, simply dump out errors that
                    125:         *      don't pertain to any file
                    126:         */
                    127:        someerrors = nopertain(files);
                    128: 
                    129:        if (nfiles){
                    130:                someerrors++;
                    131:                fprintf(stdout, terse
                    132:                        ? "%d file%s"
                    133:                        : "%d file%s contain%s errors",
                    134:                        nfiles, plural(nfiles), verbform(nfiles));
                    135:                if (!terse){
                    136:                        FILEITERATE(fi, 1){
                    137:                                fprintf(stdout, "%s\"%s\" (%d)",
                    138:                                        sep, (*files[fi])->error_text[0],
                    139:                                        files[fi+1] - files[fi]);
                    140:                                sep = ", ";
                    141:                        }
                    142:                }
                    143:                fprintf(stdout, "\n");
                    144:        }
                    145:        if (!someerrors)
                    146:                fprintf(stdout, "No errors.\n");
                    147: }
                    148: 
                    149: /*
                    150:  *     Dump out errors that don't pertain to any file
                    151:  */
                    152: int nopertain(files)
                    153:        Eptr    **files;
                    154: {
                    155:        int     type;
                    156:        int     someerrors = 0;
                    157:        reg     Eptr    *erpp;
                    158:        reg     Eptr    errorp;
                    159: 
                    160:        if (files[1] - files[0] <= 0)
                    161:                return(0);
                    162:        for(type = C_UNKNOWN; NOTSORTABLE(type); type++){
                    163:                if (class_count[type] <= 0)
                    164:                        continue;
                    165:                if (type > C_SYNC)
                    166:                        someerrors++;
                    167:                if (terse){
                    168:                        fprintf(stdout, "\t%d %s errors NOT PRINTED\n",
                    169:                                class_count[type], class_table[type]);
                    170:                } else {
                    171:                        fprintf(stdout, "\n\t%d %s errors follow\n",
                    172:                                class_count[type], class_table[type]);
                    173:                        EITERATE(erpp, files, 0){
                    174:                                errorp = *erpp;
                    175:                                if (errorp->error_e_class == type){
                    176:                                        errorprint(stdout, errorp, TRUE);
                    177:                                }
                    178:                        }
                    179:                }
                    180:        }
                    181:        return(someerrors);
                    182: }
                    183: 
                    184: extern boolean notouch;
                    185: 
                    186: boolean touchfiles(nfiles, files, r_edargc, r_edargv)
                    187:        int     nfiles;
                    188:        Eptr    **files;
                    189:        int     *r_edargc;
                    190:        char    ***r_edargv;
                    191: {
                    192:                char    *name;
                    193:        reg     Eptr    errorp;
                    194:        reg     int     fi;
                    195:        reg     Eptr    *erpp;
                    196:                int             ntrueerrors;
                    197:                boolean         scribbled;
                    198:                int             n_pissed_on;    /* # of file touched*/
                    199:                int     spread;
                    200: 
                    201:        FILEITERATE(fi, 1){
                    202:                name = (*files[fi])->error_text[0];
                    203:                spread = files[fi+1] - files[fi];
                    204:                fprintf(stdout, terse
                    205:                        ? "\"%s\" has %d error%s, "
                    206:                        : "\nFile \"%s\" has %d error%s.\n"
                    207:                        , name ,spread ,plural(spread));
                    208:                /*
                    209:                 *      First, iterate through all error messages in this file
                    210:                 *      to see how many of the error messages really will
                    211:                 *      get inserted into the file.
                    212:                 */
                    213:                ntrueerrors = 0;
                    214:                EITERATE(erpp, files, fi){
                    215:                        errorp = *erpp;
                    216:                        if (errorp->error_e_class == C_TRUE)
                    217:                                ntrueerrors++;
                    218:                }
                    219:                fprintf(stdout, terse
                    220:                  ? "insert %d\n"
                    221:                  : "\t%d of these errors can be inserted into the file.\n",
                    222:                        ntrueerrors);
                    223: 
                    224:                hackfile(name, files, fi, ntrueerrors);
                    225:        }
                    226:        scribbled = FALSE;
                    227:        n_pissed_on = 0;
                    228:        FILEITERATE(fi, 1){
                    229:                scribbled |= touchedfiles[fi];
                    230:                n_pissed_on++;
                    231:        }
                    232:        if (scribbled){
                    233:                /*
                    234:                 *      Construct an execv argument
                    235:                 */
                    236:                execvarg(n_pissed_on, r_edargc, r_edargv);
                    237:                return(TRUE);
                    238:        } else {
                    239:                if (!terse)
                    240:                        fprintf(stdout, "You didn't touch any files.\n");
                    241:                return(FALSE);
                    242:        }
                    243: }
                    244: 
                    245: hackfile(name, files, ix, nerrors)
                    246:        char    *name;
                    247:        Eptr    **files;
                    248:        int     ix;
                    249: {
                    250:        boolean previewed;
                    251:        int     errordest;      /* where errors go*/
                    252: 
                    253:        if (!oktotouch(name)) {
                    254:                previewed = FALSE;
                    255:                errordest = TOSTDOUT;
                    256:        } else {
                    257:                previewed = preview(name, nerrors, files, ix);
                    258:                errordest = settotouch(name);
                    259:        }
                    260: 
                    261:        if (errordest != TOSTDOUT)
                    262:                touchedfiles[ix] = TRUE;
                    263: 
                    264:        if (previewed && (errordest == TOSTDOUT))
                    265:                return;
                    266: 
                    267:        diverterrors(name, errordest, files, ix, previewed, nerrors);
                    268: 
                    269:        if (errordest == TOTHEFILE){
                    270:                /*
                    271:                 *      overwrite the original file
                    272:                 */
                    273:                writetouched(1);
                    274:        }
                    275: }
                    276: 
                    277: boolean preview(name, nerrors, files, ix)
                    278:        char    *name;
                    279:        int     nerrors;
                    280:        Eptr    **files;
                    281:        int     ix;
                    282: {
                    283:        int     back;
                    284:        reg     Eptr    *erpp;
                    285: 
                    286:        if (nerrors <= 0)
                    287:                return(FALSE);
                    288:        back = FALSE;
                    289:        if(query){
                    290:                switch(inquire(terse
                    291:                    ? "Preview? "
                    292:                    : "Do you want to preview the errors first? ")){
                    293:                case Q_YES:
                    294:                case Q_yes:
                    295:                        back = TRUE;
                    296:                        EITERATE(erpp, files, ix){
                    297:                                errorprint(stdout, *erpp, TRUE);
                    298:                        }
                    299:                        if (!terse)
                    300:                                fprintf(stdout, "\n");
                    301:                default:
                    302:                        break;
                    303:                }
                    304:        }
                    305:        return(back);
                    306: }
                    307: 
                    308: int settotouch(name)
                    309:        char    *name;
                    310: {
                    311:        int     dest = TOSTDOUT;
                    312: 
                    313:        if (query){
                    314:                switch(touchstatus = inquire(terse
                    315:                        ? "Touch? "
                    316:                        : "Do you want to touch file \"%s\"? ",
                    317:                        name)){
                    318:                case Q_NO:
                    319:                case Q_no:
                    320:                        return(dest);
                    321:                default:
                    322:                        break;
                    323:                }
                    324:        }
                    325: 
                    326:        switch(probethisfile(name)){
                    327:        case F_NOTREAD:
                    328:                dest = TOSTDOUT;
                    329:                fprintf(stdout, terse
                    330:                        ? "\"%s\" unreadable\n"
                    331:                        : "File \"%s\" is unreadable\n",
                    332:                        name);
                    333:                break;
                    334:        case F_NOTWRITE:
                    335:                dest = TOSTDOUT;
                    336:                fprintf(stdout, terse
                    337:                        ? "\"%s\" unwritable\n"
                    338:                        : "File \"%s\" is unwritable\n",
                    339:                        name);
                    340:                break;
                    341:        case F_NOTEXIST:
                    342:                dest = TOSTDOUT;
                    343:                fprintf(stdout, terse
                    344:                        ? "\"%s\" not found\n"
                    345:                        : "Can't find file \"%s\" to insert error messages into.\n",
                    346:                        name);
                    347:                break;
                    348:        default:
                    349:                dest = edit(name) ? TOSTDOUT : TOTHEFILE;
                    350:                break;
                    351:        }
                    352:        return(dest);
                    353: }
                    354: 
                    355: diverterrors(name, dest, files, ix, previewed, nterrors)
                    356:        char    *name;
                    357:        int     dest;
                    358:        Eptr    **files;
                    359:        int     ix;
                    360:        boolean previewed;
                    361:        int     nterrors;
                    362: {
                    363:        int     nerrors;
                    364:        reg     Eptr    *erpp;
                    365:        reg     Eptr    errorp;
                    366: 
                    367:        nerrors = files[ix+1] - files[ix];
                    368: 
                    369:        if (   (nerrors != nterrors)
                    370:            && (!previewed) ){
                    371:                fprintf(stdout, terse
                    372:                        ? "Uninserted errors\n"
                    373:                        : ">>Uninserted errors for file \"%s\" follow.\n",
                    374:                        name);
                    375:        }
                    376: 
                    377:        EITERATE(erpp, files, ix){
                    378:                errorp = *erpp;
                    379:                if (errorp->error_e_class != C_TRUE){
                    380:                        if (previewed || touchstatus == Q_NO)
                    381:                                continue;
                    382:                        errorprint(stdout, errorp, TRUE);
                    383:                        continue;
                    384:                }
                    385:                switch (dest){
                    386:                case TOSTDOUT:
                    387:                        if (previewed || touchstatus == Q_NO)
                    388:                                continue;
                    389:                        errorprint(stdout,errorp, TRUE);
                    390:                        break;
                    391:                case TOTHEFILE:
                    392:                        insert(errorp->error_line);
                    393:                        text(errorp, FALSE);
                    394:                        break;
                    395:                }
                    396:        }
                    397: }
                    398: 
                    399: int oktotouch(filename)
                    400:        char    *filename;
                    401: {
                    402:        extern          char    *suffixlist;
                    403:        reg     char    *src;
                    404:        reg     char    *pat;
                    405:                        char    *osrc;
                    406: 
                    407:        pat = suffixlist;
                    408:        if (pat == 0)
                    409:                return(0);
                    410:        if (*pat == '*')
                    411:                return(1);
                    412:        while (*pat++ != '.')
                    413:                continue;
                    414:        --pat;          /* point to the period */
                    415: 
                    416:        for (src = &filename[strlen(filename)], --src;
                    417:             (src > filename) && (*src != '.'); --src)
                    418:                continue;
                    419:        if (*src != '.')
                    420:                return(0);
                    421: 
                    422:        for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){
                    423:                for (;   *src                   /* not at end of the source */
                    424:                      && *pat                   /* not off end of pattern */
                    425:                      && *pat != '.'            /* not off end of sub pattern */
                    426:                      && *pat != '*'            /* not wild card */
                    427:                      && *src == *pat;          /* and equal... */
                    428:                      src++, pat++)
                    429:                        continue;
                    430:                if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*'))
                    431:                        return(1);
                    432:                if (*src != 0 && *pat == '*')
                    433:                        return(1);
                    434:                while (*pat && *pat != '.')
                    435:                        pat++;
                    436:                if (! *pat)
                    437:                        return(0);
                    438:        }
                    439:        return(0);
                    440: }
                    441: /*
                    442:  *     Construct an execv argument
                    443:  *     We need 1 argument for the editor's name
                    444:  *     We need 1 argument for the initial search string
                    445:  *     We need n_pissed_on arguments for the file names
                    446:  *     We need 1 argument that is a null for execv.
                    447:  *     The caller fills in the editor's name.
                    448:  *     We fill in the initial search string.
                    449:  *     We fill in the arguments, and the null.
                    450:  */
                    451: execvarg(n_pissed_on, r_argc, r_argv)
                    452:        int     n_pissed_on;
                    453:        int     *r_argc;
                    454:        char    ***r_argv;
                    455: {
                    456:        Eptr    p;
                    457:        char    *sep;
                    458:        int     fi;
                    459: 
                    460:        (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *));
                    461:        (*r_argc) =  n_pissed_on + 2;
                    462:        (*r_argv)[1] = "+1;/###/";
                    463:        n_pissed_on = 2;
                    464:        if (!terse){
                    465:                fprintf(stdout, "You touched file(s):");
                    466:                sep = " ";
                    467:        }
                    468:        FILEITERATE(fi, 1){
                    469:                if (!touchedfiles[fi])
                    470:                        continue;
                    471:                p = *(files[fi]);
                    472:                if (!terse){
                    473:                        fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]);
                    474:                        sep = ", ";
                    475:                }
                    476:                (*r_argv)[n_pissed_on++] = p->error_text[0];
                    477:        }
                    478:        if (!terse)
                    479:                fprintf(stdout, "\n");
                    480:        (*r_argv)[n_pissed_on] = 0;
                    481: }
                    482: 
                    483: FILE   *o_touchedfile; /* the old file */
                    484: FILE   *n_touchedfile; /* the new file */
                    485: char   *o_name;
                    486: char   n_name[64];
                    487: char   *canon_name = "/tmp/ErrorXXXXXX";
                    488: int    o_lineno;
                    489: int    n_lineno;
                    490: boolean        tempfileopen = FALSE;
                    491: /*
                    492:  *     open the file; guaranteed to be both readable and writable
                    493:  *     Well, if it isn't, then return TRUE if something failed
                    494:  */
                    495: boolean edit(name)
                    496:        char    *name;
                    497: {
                    498:        o_name = name;
                    499:        if ( (o_touchedfile = fopen(name, "r")) == NULL){
                    500:                fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n",
                    501:                        processname, name);
                    502:                return(TRUE);
                    503:        }
                    504:        (void)strcpy(n_name, canon_name);
                    505:        (void)mktemp(n_name);
                    506:        if ( (n_touchedfile = fopen(n_name, "w")) == NULL){
                    507:                fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n",
                    508:                        processname, name);
                    509:                return(TRUE);
                    510:        }
                    511:        tempfileopen = TRUE;
                    512:        n_lineno = 0;
                    513:        o_lineno = 0;
                    514:        return(FALSE);
                    515: }
                    516: /*
                    517:  *     Position to the line (before, after) the line given by place
                    518:  */
                    519: char   edbuf[BUFSIZ];
                    520: insert(place)
                    521:        int     place;
                    522: {
                    523:        --place;        /* always insert messages before the offending line*/
                    524:        for(; o_lineno < place; o_lineno++, n_lineno++){
                    525:                if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL)
                    526:                        return;
                    527:                fputs(edbuf, n_touchedfile);
                    528:        }
                    529: }
                    530: 
                    531: text(p, use_all)
                    532:        reg     Eptr    p;
                    533:                boolean use_all;
                    534: {
                    535:        int     offset = use_all ? 0 : 2;
                    536: 
                    537:        fputs(lang_table[p->error_language].lang_incomment, n_touchedfile);
                    538:        fprintf(n_touchedfile, "%d [%s] ",
                    539:                p->error_line,
                    540:                lang_table[p->error_language].lang_name);
                    541:        wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset);
                    542:        fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile);
                    543:        n_lineno++;
                    544: }
                    545: 
                    546: /*
                    547:  *     write the touched file to its temporary copy,
                    548:  *     then bring the temporary in over the local file
                    549:  */
                    550: writetouched(overwrite)
                    551:        int     overwrite;
                    552: {
                    553:        reg     int     nread;
                    554:        reg     FILE    *localfile;
                    555:        reg     FILE    *tmpfile;
                    556:                int     botch;
                    557:                int     oktorm;
                    558: 
                    559:        botch = 0;
                    560:        oktorm = 1;
                    561:        while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){
                    562:                if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){
                    563:                        /*
                    564:                         *      Catastrophe in temporary area: file system full?
                    565:                         */
                    566:                        botch = 1;
                    567:                        fprintf(stderr,
                    568:                          "%s: write failure: No errors inserted in \"%s\"\n",
                    569:                          processname, o_name);
                    570:                }
                    571:        }
                    572:        fclose(n_touchedfile);
                    573:        fclose(o_touchedfile);
                    574:        /*
                    575:         *      Now, copy the temp file back over the original
                    576:         *      file, thus preserving links, etc
                    577:         */
                    578:        if (botch == 0 && overwrite){
                    579:                botch = 0;
                    580:                localfile = NULL;
                    581:                tmpfile = NULL;
                    582:                if ((localfile = fopen(o_name, "w")) == NULL){
                    583:                        fprintf(stderr,
                    584:                                "%s: Can't open file \"%s\" to overwrite.\n",
                    585:                                processname, o_name);
                    586:                        botch++;
                    587:                }
                    588:                if ((tmpfile = fopen(n_name, "r")) == NULL){
                    589:                        fprintf(stderr, "%s: Can't open file \"%s\" to read.\n",
                    590:                                processname, n_name);
                    591:                        botch++;
                    592:                }
                    593:                if (!botch)
                    594:                        oktorm = mustoverwrite(localfile, tmpfile);
                    595:                if (localfile != NULL)
                    596:                        fclose(localfile);
                    597:                if (tmpfile != NULL)
                    598:                        fclose(tmpfile);
                    599:        }
                    600:        if (oktorm == 0){
                    601:                fprintf(stderr, "%s: Catastrophe: A copy of \"%s\: was saved in \"%s\"\n",
                    602:                        processname, o_name, n_name);
                    603:                exit(1);
                    604:        }
                    605:        /*
                    606:         *      Kiss the temp file good bye
                    607:         */
                    608:        unlink(n_name);
                    609:        tempfileopen = FALSE;
                    610:        return(TRUE);
                    611: }
                    612: /*
                    613:  *     return 1 if the tmpfile can be removed after writing it out
                    614:  */
                    615: int mustoverwrite(preciousfile, tmpfile)
                    616:        FILE    *preciousfile;
                    617:        FILE    *tmpfile;
                    618: {
                    619:        int     nread;
                    620: 
                    621:        while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){
                    622:                if (mustwrite(edbuf, nread, preciousfile) == 0)
                    623:                        return(0);
                    624:        }
                    625:        return(1);
                    626: }
                    627: /*
                    628:  *     return 0 on catastrophe
                    629:  */
                    630: mustwrite(base, n, preciousfile)
                    631:        char    *base;
                    632:        int     n;
                    633:        FILE    *preciousfile;
                    634: {
                    635:        int     nwrote;
                    636: 
                    637:        if (n <= 0)
                    638:                return(1);
                    639:        nwrote = fwrite(base, 1, n, preciousfile);
                    640:        if (nwrote == n)
                    641:                return(1);
                    642:        perror(processname);
                    643:        switch(inquire(terse
                    644:            ? "Botch overwriting: retry? "
                    645:            : "Botch overwriting the source file: retry? ")){
                    646:        case Q_YES:
                    647:        case Q_yes:
                    648:                mustwrite(base + nwrote, n - nwrote, preciousfile);
                    649:                return(1);
                    650:        case Q_NO:
                    651:        case Q_no:
                    652:                switch(inquire("Are you sure? ")){
                    653:                case Q_YES:
                    654:                case Q_yes:
                    655:                        return(0);
                    656:                case Q_NO:
                    657:                case Q_no:
                    658:                        mustwrite(base + nwrote, n - nwrote, preciousfile);
                    659:                        return(1);
                    660:                }
                    661:        default:
                    662:                return(0);
                    663:        }
                    664: }
                    665: 
                    666: onintr()
                    667: {
                    668:        switch(inquire(terse
                    669:            ? "\nContinue? "
                    670:            : "\nInterrupt: Do you want to continue? ")){
                    671:        case Q_YES:
                    672:        case Q_yes:
                    673:                signal(SIGINT, onintr);
                    674:                return;
                    675:        default:
                    676:                if (tempfileopen){
                    677:                        /*
                    678:                         *      Don't overwrite the original file!
                    679:                         */
                    680:                        writetouched(0);
                    681:                }
                    682:                exit(1);
                    683:        }
                    684:        /*NOTREACHED*/
                    685: }
                    686: 
                    687: errorprint(place, errorp, print_all)
                    688:        FILE    *place;
                    689:        Eptr    errorp;
                    690:        boolean print_all;
                    691: {
                    692:        int     offset = print_all ? 0 : 2;
                    693: 
                    694:        if (errorp->error_e_class == C_IGNORE)
                    695:                return;
                    696:        fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name);
                    697:        wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset);
                    698:        putc('\n', place);
                    699: }
                    700: 
                    701: int inquire(fmt, a1, a2)
                    702:        char    *fmt;
                    703:        /*VARARGS1*/
                    704: {
                    705:        char    buffer[128];
                    706: 
                    707:        if (queryfile == NULL)
                    708:                return(0);
                    709:        for(;;){
                    710:                do{
                    711:                        fflush(stdout);
                    712:                        fprintf(stderr, fmt, a1, a2);
                    713:                        fflush(stderr);
                    714:                } while (fgets(buffer, 127, queryfile) == NULL);
                    715:                switch(buffer[0]){
                    716:                case 'Y':       return(Q_YES);
                    717:                case 'y':       return(Q_yes);
                    718:                case 'N':       return(Q_NO);
                    719:                case 'n':       return(Q_no);
                    720:                default:        fprintf(stderr, "Yes or No only!\n");
                    721:                }
                    722:        }
                    723: }
                    724: 
                    725: int probethisfile(name)
                    726:        char    *name;
                    727: {
                    728:        struct stat statbuf;
                    729:        if (stat(name, &statbuf) < 0)
                    730:                return(F_NOTEXIST);
                    731:        if((statbuf.st_mode & S_IREAD) == 0)
                    732:                return(F_NOTREAD);
                    733:        if((statbuf.st_mode & S_IWRITE) == 0)
                    734:                return(F_NOTWRITE);
                    735:        return(F_TOUCHIT);
                    736: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.