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