Annotation of 40BSD/cmd/error/errortouch.c, revision 1.1.1.1

1.1       root        1: static char *sccsid = "@(#)errortouch.c        1.2 (Berkeley) 10/16/80";
                      2: #include <stdio.h>
                      3: #include <ctype.h>
                      4: #include <sys/types.h>
                      5: #include <sys/stat.h>
                      6: #include <signal.h>
                      7: #include "error.h"
                      8: 
                      9: findfiles(nerrors, errors, r_nfiles, r_files)
                     10:        int     nerrors;
                     11:        struct  error_desc      **errors;
                     12:        int     *r_nfiles;
                     13:        struct  error_desc      ****r_files;
                     14: {
                     15:                        int     nfiles;
                     16:        struct  error_desc      ***files;
                     17: 
                     18:                        char    *currentfilename;
                     19:        register        int     errorindex;
                     20:                        int     fileindex;
                     21:        register        struct  error_desc      *errorp;
                     22:        /*
                     23:         *      First, go through and count all of the filenames
                     24:         */
                     25:        for (errorp = errors[errorindex = 0],nfiles = 0, currentfilename = "\1";
                     26:             errorindex < nerrors;
                     27:             errorp = errors[++errorindex]){
                     28:                if (SORTABLE(errorp->error_e_class)){
                     29:                        if (strcmp(errorp->error_text[0],currentfilename) != 0){
                     30:                                nfiles++;
                     31:                                currentfilename = errorp->error_text[0];
                     32:                        }
                     33:                }
                     34:        }
                     35:        files = (struct error_desc ***)Calloc(nfiles + 3,
                     36:                sizeof (struct error_desc**));
                     37:        touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean));
                     38:        /*
                     39:         *      Now, go through and partition off the error messages
                     40:         *      into those that are synchronization, discarded or
                     41:         *      not specific to any file, and those that were
                     42:         *      nulled or true errors.
                     43:         */
                     44:        files[0] = &errors[0];
                     45:        for (errorp = errors[errorindex = 0], fileindex = 0;
                     46:             (errorindex < nerrors) &&
                     47:                (NOTSORTABLE(errorp->error_e_class));
                     48:             errorp = errors[++errorindex]){
                     49:                continue;
                     50:        }
                     51:        /*
                     52:         *      Now, go through and partition off all error messages
                     53:         *      for a given file.
                     54:         */
                     55:        files[1] = &errors[errorindex];
                     56:        touchedfiles[0] = touchedfiles[1] = FALSE;
                     57:        for (errorp = errors[errorindex], currentfilename = "\1", fileindex = 1;
                     58:             errorindex < nerrors; errorp = errors[++errorindex]){
                     59:                if ( (errorp->error_e_class == C_NULLED) || (errorp->error_e_class == C_TRUE) ){
                     60:                        if (strcmp(errorp->error_text[0],currentfilename) != 0){
                     61:                                currentfilename = errorp->error_text[0];
                     62:                                touchedfiles[fileindex] = FALSE;
                     63:                                files[fileindex++] = &errors[errorindex];
                     64:                        }
                     65:                }
                     66:        }
                     67:        files[fileindex] = &errors[nerrors];
                     68:        *r_nfiles = nfiles;
                     69:        *r_files = files;
                     70: }
                     71: 
                     72: char   *class_table[] = {
                     73:        /*C_UNKNOWN     0       */      "Unknown",
                     74:        /*C_IGNORE      1       */      "ignore",
                     75:        /*C_SYNC        2       */      "synchronization",
                     76:        /*C_DISCARD     3       */      "discarded",
                     77:        /*C_NONSPEC     4       */      "non specific",
                     78:        /*C_THISFILE    5       */      "specific to this file",
                     79:        /*C_NULLED      6       */      "nulled",
                     80:        /*C_TRUE        7       */      "true",
                     81:        /*C_DUPL        8       */      "duplicated"
                     82: };
                     83: 
                     84: int    class_count[C_LAST - C_FIRST] = {0};
                     85: 
                     86: filenames(nfiles, files)
                     87:        int     nfiles;
                     88:        struct  error_desc      ***files;
                     89: {
                     90:        register        int     fileindex;
                     91:        register        struct  error_desc      *errorp;
                     92:        register        struct  error_desc      **erpp;
                     93:                        char    *sep = " ";
                     94:        register        int     errortype;
                     95:        extern          char    *class_table[];
                     96:                        int     someerrors = 0;
                     97: 
                     98:        /*
                     99:         *      first, go through and simply dump out errors that
                    100:         *      don't pertain to any file
                    101:         */
                    102:        if (files[1] - files[0] > 0){
                    103:            for(errortype = C_UNKNOWN; NOTSORTABLE(errortype); errortype++){
                    104:                if (class_count[errortype] > 0){
                    105:                        if (errortype > C_SYNC)
                    106:                                someerrors++;
                    107:                        fprintf(stdout, "\n\t%d %s errors follow:\n",
                    108:                                class_count[errortype], class_table[errortype]);
                    109:                        for (errorp = *(erpp = files[0]);
                    110:                             erpp < files[1];
                    111:                             errorp = (*++erpp)){
                    112:                                if (errorp->error_e_class == errortype)
                    113:                                        errorprint(stdout, errorp, TRUE);
                    114:                        }
                    115:                }
                    116:            }
                    117:        }
                    118:        if (nfiles){
                    119:                someerrors++;
                    120:                fprintf(stdout, "%d files contain errors:", nfiles);
                    121:                for (fileindex = 1; fileindex <= nfiles; fileindex++){
                    122:                        fprintf(stdout, "%s\"%s\" (%d)",
                    123:                                sep, (*files[fileindex])->error_text[0],
                    124:                                files[fileindex+1] - files[fileindex]);
                    125:                        sep = ", ";
                    126:                }
                    127:                fprintf(stdout, "\n");
                    128:        }
                    129:        if (!someerrors)
                    130:                fprintf(stdout, "No errors.\n");
                    131: }
                    132: 
                    133: extern boolean notouch;
                    134: 
                    135: boolean touchfiles(nfiles, files, r_edargc, r_edargv)
                    136:        int     nfiles;
                    137:        struct  error_desc      ***files;
                    138:        int     *r_edargc;
                    139:        char    ***r_edargv;
                    140: {
                    141:                        char    *currentfilename;
                    142:        register        struct  error_desc      *errorp;
                    143:        register        int     fileindex;
                    144:        register        struct  error_desc      **erpp;
                    145:                        int             ntrueerrors;
                    146:                        int             errordest;      /* where errors go*/
                    147:                        char            *sep;
                    148:                        boolean         scribbled;
                    149:                        int             n_pissed_on;    /* # of file touched*/
                    150:                        int             previewed;
                    151: 
                    152:        for (fileindex = 1; fileindex <= nfiles; fileindex++){
                    153:                fprintf(stdout, "\nFile \"%s\" has %d total error messages.\n",
                    154:                        currentfilename = (*files[fileindex])->error_text[0],
                    155:                        files[fileindex+1] - files[fileindex]);
                    156:                /*
                    157:                 *      First, iterate through all error messages in this file
                    158:                 *      to see how many of the error messages really will
                    159:                 *      get inserted into the file.
                    160:                 */
                    161:                for (erpp = files[fileindex], ntrueerrors = 0;
                    162:                     erpp < files[fileindex+1];
                    163:                     erpp++){
                    164:                        errorp = *erpp;
                    165:                        if (errorp->error_e_class == C_TRUE)
                    166:                                ntrueerrors++;
                    167:                }
                    168:                fprintf(stdout,"\t%d of these errors can be inserted into the file.\n",
                    169:                        ntrueerrors);
                    170: 
                    171:                /*
                    172:                 *      What does the operator want?
                    173:                 */
                    174:                previewed = 0;
                    175:                errordest = TOSTDOUT;
                    176:                if (oktotouch(currentfilename) && (ntrueerrors > 0) ){
                    177:                        if (query && inquire("Do you want to preview the errors first?")){
                    178:                                previewed = 1;
                    179:                                for (erpp = files[fileindex];
                    180:                                     erpp < files[fileindex + 1];
                    181:                                     erpp++){
                    182:                                        errorprint(stdout, *erpp, TRUE);
                    183:                                }
                    184:                                fprintf(stdout, "\n");
                    185:                        }
                    186:                        if (   !query
                    187:                            || inquire("Do you want to touch file \"%s\"? ",
                    188:                                        currentfilename)
                    189:                        ){
                    190:                                errordest = TOTHEFILE;
                    191:                                if (!probethisfile(currentfilename)){
                    192:                                        errordest = TOSTDOUT;
                    193:                                        fprintf(stdout,
                    194:                                         "Can't find file \"%s\" to insert error messages into.\n",
                    195:                                                currentfilename);
                    196:                                } else {
                    197:                                        if (edit(currentfilename))
                    198:                                                errordest = TOSTDOUT;
                    199:                                        else
                    200:                                                touchedfiles[fileindex] = TRUE;
                    201:                                }
                    202:                        }
                    203:                }
                    204:                if (previewed && (errordest == TOSTDOUT))
                    205:                        continue;               /* with the next file */
                    206:                /*
                    207:                 *      go through and print each error message,
                    208:                 *      diverting to the right place
                    209:                 */
                    210:                if ( (files[fileindex+1] - files[fileindex]) != ntrueerrors)
                    211:                        if (!previewed) fprintf(stdout,
                    212:                            ">>Uninserted error messages for file \"%s\" follow.\n",
                    213:                            currentfilename);
                    214:                for (erpp = files[fileindex];erpp < files[fileindex+1];erpp++){
                    215:                        errorp = *erpp;
                    216:                        if (errorp->error_e_class == C_TRUE){
                    217:                                switch (errordest){
                    218:                                  case TOSTDOUT:
                    219:                                        if (!previewed)
                    220:                                                errorprint(stdout,errorp, TRUE);
                    221:                                        break;
                    222:                                  case TOTHEFILE:
                    223:                                        insert(errorp->error_line);
                    224:                                        text(errorp, FALSE);
                    225:                                        break;
                    226:                                }       /* switch */
                    227:                        } else {
                    228:                                if (!previewed)
                    229:                                        errorprint(stdout, errorp, TRUE);
                    230:                        }
                    231:                }       /* end of walking through all errors*/
                    232:                if (errordest == TOTHEFILE){
                    233:                        writetouched();
                    234:                }
                    235:        }       /* end of walking through all files*/
                    236:        scribbled = FALSE;
                    237:        for (n_pissed_on = 0, fileindex = 1; fileindex <= nfiles; fileindex++){
                    238:                scribbled |= touchedfiles[fileindex];
                    239:                n_pissed_on++;
                    240:        }
                    241:        if (scribbled){
                    242:                /*
                    243:                 *      Construct an execv argument
                    244:                 *      We need 1 argument for the editor's name
                    245:                 *      We need 1 argument for the initial search string
                    246:                 *      We need n_pissed_on arguments for the file names
                    247:                 *      We need 1 argument that is a null for execv.
                    248:                 *      The caller fills in the editor's name.
                    249:                 *      We fill in the initial search string.
                    250:                 *      We fill in the arguments, and the null.
                    251:                 */
                    252:                (*r_edargv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *));
                    253:                (*r_edargc) =  n_pissed_on + 2;
                    254:                (*r_edargv)[1] = "+/###/";
                    255:                n_pissed_on = 2;
                    256:                fprintf(stdout, "You touched file(s):");
                    257:                sep = " ";
                    258:                for (fileindex = 1; fileindex <= nfiles; fileindex++){
                    259:                        if (!touchedfiles[fileindex])
                    260:                                continue;
                    261:                        errorp = *(files[fileindex]);
                    262:                        fprintf(stdout,"%s\"%s\"", sep, errorp->error_text[0]);
                    263:                        sep = ", ";
                    264:                        (*r_edargv)[n_pissed_on++] = errorp->error_text[0];
                    265:                }
                    266:                fprintf(stdout, "\n");
                    267:                (*r_edargv)[n_pissed_on] = 0;
                    268:                return(TRUE);
                    269:        } else {
                    270:                fprintf(stdout, "You didn't touch any files.\n");
                    271:                return(FALSE);
                    272:        }
                    273: 
                    274: }      /* end of touchfiles*/
                    275: int    oktotouch(filename)
                    276:        char    *filename;
                    277: {
                    278:        extern          char    *suffixlist;
                    279:        register        char    *src;
                    280:        register        char    *pat;
                    281:                        char    *osrc;
                    282: 
                    283:        pat = suffixlist;
                    284:        if (pat == 0)
                    285:                return(0);
                    286:        if (*pat == '*')
                    287:                return(1);
                    288:        while (*pat++ != '.')
                    289:                continue;
                    290:        --pat;          /* point to the period */
                    291: 
                    292:        for (src = &filename[strlen(filename)], --src;
                    293:             (src > filename) && (*src != '.'); --src)
                    294:                continue;
                    295:        if (*src != '.')
                    296:                return(0);
                    297: 
                    298:        for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){
                    299:                for (;   *src                   /* not at end of the source */
                    300:                      && *pat                   /* not off end of pattern */
                    301:                      && *pat != '.'            /* not off end of sub pattern */
                    302:                      && *pat != '*'            /* not wild card */
                    303:                      && *src == *pat;          /* and equal... */
                    304:                      src++, pat++)
                    305:                        continue;
                    306:                if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*'))
                    307:                        return(1);
                    308:                if (*src != 0 && *pat == '*')
                    309:                        return(1);
                    310:                while (*pat && *pat != '.')
                    311:                        pat++;
                    312:                if (! *pat)
                    313:                        return(0);
                    314:        }
                    315:        return(0);
                    316: }
                    317: 
                    318: FILE   *o_touchedfile; /* the old file */
                    319: FILE   *n_touchedfile; /* the new file */
                    320: char   *o_name;
                    321: char   n_name[32];
                    322: char   *canon_name = "ErrorXXXXXX";
                    323: int    o_lineno;
                    324: int    n_lineno;
                    325: boolean        tempfileopen = FALSE;
                    326: /*
                    327:  *     open the file; guaranteed to be both readable and writable
                    328:  *     Well, if it isn't, then return TRUE if something failed
                    329:  */
                    330: boolean edit(name)
                    331:        char    *name;
                    332: {
                    333:        o_name = name;
                    334:        if ( (o_touchedfile = fopen(name, "r")) == NULL){
                    335:                fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n",
                    336:                        processname, name);
                    337:                return(TRUE);
                    338:        }
                    339:        strcpy(n_name, canon_name);
                    340:        mktemp(n_name);
                    341:        if ( (n_touchedfile = fopen(n_name, "w")) == NULL){
                    342:                fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n",
                    343:                        processname, name);
                    344:                return(TRUE);
                    345:        }
                    346:        tempfileopen = TRUE;
                    347:        n_lineno = 0;
                    348:        o_lineno = 0;
                    349:        return(FALSE);
                    350: }
                    351: /*
                    352:  *     Position to the line (before, after) the line given by place
                    353:  */
                    354: char   edbuffer[BUFSIZ];
                    355: insert(place)
                    356:        int     place;
                    357: {
                    358:        --place;        /* always insert messages before the offending line*/
                    359:        for(; o_lineno < place; o_lineno++, n_lineno++){
                    360:                if(fgets(edbuffer, BUFSIZ, o_touchedfile) == NULL)
                    361:                        return;
                    362:                fputs(edbuffer, n_touchedfile);
                    363:        }
                    364: }
                    365: 
                    366: text(errorp, use_all)
                    367:        register        struct  error_desc      *errorp;
                    368:        boolean use_all;
                    369: {
                    370:        int     offset = use_all ? 0 : 2;
                    371:        fputs(lang_table[errorp->error_language].lang_incomment, n_touchedfile);
                    372:        fprintf(n_touchedfile, "%d [%s] ",
                    373:                errorp->error_line,
                    374:                lang_table[errorp->error_language].lang_name);
                    375:        wordvprint(n_touchedfile,
                    376:                errorp->error_lgtext-offset, errorp->error_text+offset);
                    377:        fputs(lang_table[errorp->error_language].lang_outcomment,n_touchedfile);
                    378:        n_lineno++;
                    379: }
                    380: 
                    381: writetouched()
                    382: {
                    383:        int     bytes_read;
                    384:        for(; (bytes_read = fread(edbuffer, 1, sizeof(edbuffer), o_touchedfile))!= NULL; ){
                    385:                fwrite(edbuffer, 1, bytes_read, n_touchedfile);
                    386:        }
                    387:        fclose(n_touchedfile);
                    388:        fclose(o_touchedfile);
                    389:        unlink(o_name);
                    390:        link(n_name, o_name);   
                    391:        unlink(n_name);
                    392:        tempfileopen = FALSE;
                    393: }
                    394: onintr()
                    395: {
                    396:        if (inquire("\nInterrupt: Do you want to continue?")){
                    397:                signal(SIGINT, onintr);
                    398:                return;
                    399:        }
                    400:        if (tempfileopen)
                    401:                writetouched();
                    402:        exit(1);
                    403: }
                    404: errorprint(place, errorp, print_all)
                    405:        FILE    *place;
                    406:        struct  error_desc      *errorp;
                    407:        boolean print_all;
                    408: {
                    409:        int     offset = print_all ? 0 : 2;
                    410: 
                    411:        if (errorp->error_e_class == C_IGNORE)
                    412:                return;
                    413:        fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name);
                    414:        wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset);
                    415:        putc('\n', place);
                    416: }
                    417: 
                    418: boolean inquire(fmt, a1, a2)
                    419:        char    *fmt;
                    420:        /*VARARGS1*/
                    421: {
                    422:        char    buffer[128];
                    423:        char    ch;
                    424:        for(;;){
                    425:                do{
                    426:                        fflush(stdout);
                    427:                        fprintf(stderr, fmt, a1, a2);
                    428:                        fflush(stderr);
                    429:                } while (fgets(buffer, 127, queryfile) == NULL);
                    430:                ch = buffer[0];
                    431:                if (ch == 'Y' || ch == 'y')
                    432:                        return(TRUE);
                    433:                if (ch == 'N' || ch == 'n')
                    434:                        return(FALSE);
                    435:                fprintf(stderr, "Yes or No only!\n");
                    436:        }
                    437: }
                    438: 
                    439: boolean probethisfile(currentfilename)
                    440:        char    *currentfilename;
                    441: {
                    442:        struct stat statbuf;
                    443:        if (stat(currentfilename, &statbuf) != 0)
                    444:                return(FALSE);
                    445:        if ( (statbuf.st_mode&S_IREAD) && (statbuf.st_mode&S_IWRITE))
                    446:                return(TRUE);
                    447:        return(FALSE);
                    448: }

unix.superglobalmegacorp.com

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