|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.