1*17212Sralph static char *sccsid = "@(#)touch.c 1.7 (Berkeley) 09/25/84"; 21460Sroot #include <stdio.h> 31460Sroot #include <ctype.h> 41460Sroot #include <sys/types.h> 51460Sroot #include <sys/stat.h> 61460Sroot #include <signal.h> 71460Sroot #include "error.h" 81460Sroot 95595Srrh /* 105595Srrh * Iterate through errors 115595Srrh */ 125595Srrh #define EITERATE(p, fv, i) for (p = fv[i]; p < fv[i+1]; p++) 135595Srrh #define ECITERATE(ei, p, lb) for (ei = lb; p = errors[ei],ei < nerrors; ei++) 145595Srrh 155595Srrh #define FILEITERATE(fi, lb) for (fi = lb; fi <= nfiles; fi++) 165595Srrh int touchstatus = Q_YES; 175595Srrh 181460Sroot findfiles(nerrors, errors, r_nfiles, r_files) 195595Srrh int nerrors; 205595Srrh Eptr *errors; 215595Srrh int *r_nfiles; 225595Srrh Eptr ***r_files; 231460Sroot { 245595Srrh int nfiles; 255595Srrh Eptr **files; 261460Sroot 275595Srrh char *name; 285595Srrh reg int ei; 295595Srrh int fi; 305595Srrh reg Eptr errorp; 315595Srrh 325595Srrh nfiles = countfiles(errors); 335595Srrh 345595Srrh files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*)); 351460Sroot touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean)); 361460Sroot /* 375595Srrh * Now, partition off the error messages 381460Sroot * into those that are synchronization, discarded or 391460Sroot * not specific to any file, and those that were 401460Sroot * nulled or true errors. 411460Sroot */ 421460Sroot files[0] = &errors[0]; 435595Srrh ECITERATE(ei, errorp, 0){ 445595Srrh if ( ! (NOTSORTABLE(errorp->error_e_class))) 455595Srrh break; 461460Sroot } 471460Sroot /* 485595Srrh * Now, and partition off all error messages 491460Sroot * for a given file. 501460Sroot */ 515595Srrh files[1] = &errors[ei]; 521460Sroot touchedfiles[0] = touchedfiles[1] = FALSE; 535595Srrh name = "\1"; 545595Srrh fi = 1; 555595Srrh ECITERATE(ei, errorp, ei){ 565595Srrh if ( (errorp->error_e_class == C_NULLED) 575595Srrh || (errorp->error_e_class == C_TRUE) ){ 585595Srrh if (strcmp(errorp->error_text[0], name) != 0){ 595595Srrh name = errorp->error_text[0]; 605595Srrh touchedfiles[fi] = FALSE; 615595Srrh files[fi] = &errors[ei]; 625595Srrh fi++; 631460Sroot } 641460Sroot } 651460Sroot } 665595Srrh files[fi] = &errors[nerrors]; 671460Sroot *r_nfiles = nfiles; 681460Sroot *r_files = files; 691460Sroot } 701460Sroot 715595Srrh int countfiles(errors) 725595Srrh Eptr *errors; 735595Srrh { 745595Srrh char *name; 755595Srrh int ei; 765595Srrh reg Eptr errorp; 775595Srrh 785595Srrh int nfiles; 795595Srrh nfiles = 0; 805595Srrh name = "\1"; 815595Srrh ECITERATE(ei, errorp, 0){ 825595Srrh if (SORTABLE(errorp->error_e_class)){ 835595Srrh if (strcmp(errorp->error_text[0],name) != 0){ 845595Srrh nfiles++; 855595Srrh name = errorp->error_text[0]; 865595Srrh } 875595Srrh } 885595Srrh } 895595Srrh return(nfiles); 905595Srrh } 911460Sroot char *class_table[] = { 921460Sroot /*C_UNKNOWN 0 */ "Unknown", 931460Sroot /*C_IGNORE 1 */ "ignore", 941460Sroot /*C_SYNC 2 */ "synchronization", 951460Sroot /*C_DISCARD 3 */ "discarded", 961460Sroot /*C_NONSPEC 4 */ "non specific", 971460Sroot /*C_THISFILE 5 */ "specific to this file", 981460Sroot /*C_NULLED 6 */ "nulled", 991460Sroot /*C_TRUE 7 */ "true", 1001460Sroot /*C_DUPL 8 */ "duplicated" 1011460Sroot }; 1021460Sroot 1031460Sroot int class_count[C_LAST - C_FIRST] = {0}; 1041460Sroot 1051460Sroot filenames(nfiles, files) 1061460Sroot int nfiles; 1075595Srrh Eptr **files; 1081460Sroot { 1095595Srrh reg int fi; 1105595Srrh char *sep = " "; 1115595Srrh extern char *class_table[]; 1125595Srrh int someerrors; 1131460Sroot 1141460Sroot /* 1155595Srrh * first, simply dump out errors that 1161460Sroot * don't pertain to any file 1171460Sroot */ 1185595Srrh someerrors = nopertain(files); 1195595Srrh 1201460Sroot if (nfiles){ 1211460Sroot someerrors++; 1225595Srrh fprintf(stdout, terse 1235595Srrh ? "%d file%s" 1245595Srrh : "%d file%s contain%s errors", 1255595Srrh nfiles, plural(nfiles), verbform(nfiles)); 1265595Srrh if (!terse){ 1275595Srrh FILEITERATE(fi, 1){ 1285595Srrh fprintf(stdout, "%s\"%s\" (%d)", 1295595Srrh sep, (*files[fi])->error_text[0], 1305595Srrh files[fi+1] - files[fi]); 1315595Srrh sep = ", "; 1325595Srrh } 1331460Sroot } 1341460Sroot fprintf(stdout, "\n"); 1351460Sroot } 1361460Sroot if (!someerrors) 1371460Sroot fprintf(stdout, "No errors.\n"); 1381460Sroot } 1391460Sroot 1405595Srrh /* 1415595Srrh * Dump out errors that don't pertain to any file 1425595Srrh */ 1435595Srrh int nopertain(files) 1445595Srrh Eptr **files; 1455595Srrh { 1465595Srrh int type; 1475595Srrh int someerrors = 0; 1485595Srrh reg Eptr *erpp; 1495595Srrh reg Eptr errorp; 1505595Srrh 1515595Srrh if (files[1] - files[0] <= 0) 1525595Srrh return(0); 1535595Srrh for(type = C_UNKNOWN; NOTSORTABLE(type); type++){ 1545595Srrh if (class_count[type] <= 0) 1555595Srrh continue; 1565595Srrh if (type > C_SYNC) 1575595Srrh someerrors++; 1585595Srrh if (terse){ 1595595Srrh fprintf(stdout, "\t%d %s errors NOT PRINTED\n", 1605595Srrh class_count[type], class_table[type]); 1615595Srrh } else { 1625595Srrh fprintf(stdout, "\n\t%d %s errors follow\n", 1635595Srrh class_count[type], class_table[type]); 1645595Srrh EITERATE(erpp, files, 0){ 1655595Srrh errorp = *erpp; 1665595Srrh if (errorp->error_e_class == type){ 1675595Srrh errorprint(stdout, errorp, TRUE); 1685595Srrh } 1695595Srrh } 1705595Srrh } 1715595Srrh } 1725595Srrh return(someerrors); 1735595Srrh } 1745595Srrh 1751460Sroot extern boolean notouch; 1761460Sroot 1771460Sroot boolean touchfiles(nfiles, files, r_edargc, r_edargv) 1781460Sroot int nfiles; 1795595Srrh Eptr **files; 1801460Sroot int *r_edargc; 1811460Sroot char ***r_edargv; 1821460Sroot { 1835595Srrh char *name; 1845595Srrh reg Eptr errorp; 1855595Srrh reg int fi; 1865595Srrh reg Eptr *erpp; 1875595Srrh int ntrueerrors; 1885595Srrh boolean scribbled; 1895595Srrh int n_pissed_on; /* # of file touched*/ 1905595Srrh int spread; 1911462Sroot 1925595Srrh FILEITERATE(fi, 1){ 1935595Srrh name = (*files[fi])->error_text[0]; 1945595Srrh spread = files[fi+1] - files[fi]; 1955595Srrh fprintf(stdout, terse 1965595Srrh ? "\"%s\" has %d error%s, " 1975595Srrh : "\nFile \"%s\" has %d error%s.\n" 1985595Srrh , name ,spread ,plural(spread)); 1991460Sroot /* 2001460Sroot * First, iterate through all error messages in this file 2011460Sroot * to see how many of the error messages really will 2021460Sroot * get inserted into the file. 2031460Sroot */ 2045595Srrh ntrueerrors = 0; 2055595Srrh EITERATE(erpp, files, fi){ 2061460Sroot errorp = *erpp; 2071460Sroot if (errorp->error_e_class == C_TRUE) 2081460Sroot ntrueerrors++; 2091460Sroot } 2105595Srrh fprintf(stdout, terse 2115595Srrh ? "insert %d\n" 2125595Srrh : "\t%d of these errors can be inserted into the file.\n", 2131460Sroot ntrueerrors); 2141460Sroot 2155595Srrh hackfile(name, files, fi, ntrueerrors); 2165595Srrh } 2171460Sroot scribbled = FALSE; 2185595Srrh n_pissed_on = 0; 2195595Srrh FILEITERATE(fi, 1){ 2205595Srrh scribbled |= touchedfiles[fi]; 2211460Sroot n_pissed_on++; 2221460Sroot } 2231460Sroot if (scribbled){ 2241460Sroot /* 2251460Sroot * Construct an execv argument 2261460Sroot */ 2275595Srrh execvarg(n_pissed_on, r_edargc, r_edargv); 2281460Sroot return(TRUE); 2291460Sroot } else { 2305595Srrh if (!terse) 2315595Srrh fprintf(stdout, "You didn't touch any files.\n"); 2321460Sroot return(FALSE); 2331460Sroot } 2345595Srrh } 2351460Sroot 2365595Srrh hackfile(name, files, ix, nerrors) 2375595Srrh char *name; 2385595Srrh Eptr **files; 2395595Srrh int ix; 2405595Srrh { 2415595Srrh boolean previewed; 2425595Srrh int errordest; /* where errors go*/ 2435595Srrh 244*17212Sralph if (!oktotouch(name)) { 245*17212Sralph previewed = FALSE; 246*17212Sralph errordest = TOSTDOUT; 247*17212Sralph } else { 248*17212Sralph previewed = preview(name, nerrors, files, ix); 249*17212Sralph errordest = settotouch(name); 250*17212Sralph } 2515595Srrh 2525595Srrh if (errordest != TOSTDOUT) 2535595Srrh touchedfiles[ix] = TRUE; 2545595Srrh 2555595Srrh if (previewed && (errordest == TOSTDOUT)) 2565595Srrh return; 2575595Srrh 2585595Srrh diverterrors(name, errordest, files, ix, previewed, nerrors); 2595595Srrh 2606612Srrh if (errordest == TOTHEFILE){ 2616612Srrh /* 2626612Srrh * overwrite the original file 2636612Srrh */ 2646612Srrh writetouched(1); 2656612Srrh } 2665595Srrh } 2675595Srrh 2685595Srrh boolean preview(name, nerrors, files, ix) 2695595Srrh char *name; 2705595Srrh int nerrors; 2715595Srrh Eptr **files; 2725595Srrh int ix; 2735595Srrh { 2745595Srrh int back; 2755595Srrh reg Eptr *erpp; 2765595Srrh 2775595Srrh if (nerrors <= 0) 278*17212Sralph return(FALSE); 279*17212Sralph back = FALSE; 2805595Srrh if(query){ 2815595Srrh switch(inquire(terse 2825595Srrh ? "Preview? " 2835595Srrh : "Do you want to preview the errors first? ")){ 2845595Srrh case Q_YES: 2855595Srrh case Q_yes: 286*17212Sralph back = TRUE; 2875595Srrh EITERATE(erpp, files, ix){ 2885595Srrh errorprint(stdout, *erpp, TRUE); 2895595Srrh } 2905595Srrh if (!terse) 2915595Srrh fprintf(stdout, "\n"); 2925595Srrh default: 2935595Srrh break; 2945595Srrh } 2955595Srrh } 2965595Srrh return(back); 2975595Srrh } 2985595Srrh 2995595Srrh int settotouch(name) 3005595Srrh char *name; 3015595Srrh { 3025595Srrh int dest = TOSTDOUT; 3035595Srrh 3045595Srrh if (query){ 3055595Srrh switch(touchstatus = inquire(terse 3065595Srrh ? "Touch? " 3075595Srrh : "Do you want to touch file \"%s\"? ", 3085595Srrh name)){ 3095595Srrh case Q_NO: 3105595Srrh case Q_no: 3115595Srrh return(dest); 3125595Srrh default: 3135595Srrh break; 3145595Srrh } 3155595Srrh } 3165595Srrh 3175595Srrh switch(probethisfile(name)){ 3185595Srrh case F_NOTREAD: 3195595Srrh dest = TOSTDOUT; 3205595Srrh fprintf(stdout, terse 3215595Srrh ? "\"%s\" unreadable\n" 3225595Srrh : "File \"%s\" is unreadable\n", 3235595Srrh name); 3245595Srrh break; 3255595Srrh case F_NOTWRITE: 3265595Srrh dest = TOSTDOUT; 3275595Srrh fprintf(stdout, terse 3285595Srrh ? "\"%s\" unwritable\n" 3295595Srrh : "File \"%s\" is unwritable\n", 3305595Srrh name); 3315595Srrh break; 3325595Srrh case F_NOTEXIST: 3335595Srrh dest = TOSTDOUT; 3345595Srrh fprintf(stdout, terse 3355595Srrh ? "\"%s\" not found\n" 3365595Srrh : "Can't find file \"%s\" to insert error messages into.\n", 3375595Srrh name); 3385595Srrh break; 3395595Srrh default: 3405595Srrh dest = edit(name) ? TOSTDOUT : TOTHEFILE; 3415595Srrh break; 3425595Srrh } 3435595Srrh return(dest); 3445595Srrh } 3455595Srrh 3465595Srrh diverterrors(name, dest, files, ix, previewed, nterrors) 3475595Srrh char *name; 3485595Srrh int dest; 3495595Srrh Eptr **files; 3505595Srrh int ix; 3515595Srrh boolean previewed; 3525595Srrh int nterrors; 3535595Srrh { 3545595Srrh int nerrors; 3555595Srrh reg Eptr *erpp; 3565595Srrh reg Eptr errorp; 3575595Srrh 3585595Srrh nerrors = files[ix+1] - files[ix]; 3595595Srrh 3605595Srrh if ( (nerrors != nterrors) 3615595Srrh && (!previewed) ){ 3625595Srrh fprintf(stdout, terse 3635595Srrh ? "Uninserted errors\n" 3645595Srrh : ">>Uninserted errors for file \"%s\" follow.\n", 3655595Srrh name); 3665595Srrh } 3675595Srrh 3685595Srrh EITERATE(erpp, files, ix){ 3695595Srrh errorp = *erpp; 3705595Srrh if (errorp->error_e_class != C_TRUE){ 3715595Srrh if (previewed || touchstatus == Q_NO) 3725595Srrh continue; 3735595Srrh errorprint(stdout, errorp, TRUE); 3745595Srrh continue; 3755595Srrh } 3765595Srrh switch (dest){ 3775595Srrh case TOSTDOUT: 3785595Srrh if (previewed || touchstatus == Q_NO) 3795595Srrh continue; 3805595Srrh errorprint(stdout,errorp, TRUE); 3815595Srrh break; 3825595Srrh case TOTHEFILE: 3835595Srrh insert(errorp->error_line); 3845595Srrh text(errorp, FALSE); 3855595Srrh break; 3865595Srrh } 3875595Srrh } 3885595Srrh } 3895595Srrh 3905595Srrh int oktotouch(filename) 3911460Sroot char *filename; 3921460Sroot { 3931460Sroot extern char *suffixlist; 3945595Srrh reg char *src; 3955595Srrh reg char *pat; 3961460Sroot char *osrc; 3971460Sroot 3981460Sroot pat = suffixlist; 3991460Sroot if (pat == 0) 4001460Sroot return(0); 4011460Sroot if (*pat == '*') 4021460Sroot return(1); 4031460Sroot while (*pat++ != '.') 4041460Sroot continue; 4051460Sroot --pat; /* point to the period */ 4061460Sroot 4071460Sroot for (src = &filename[strlen(filename)], --src; 4081460Sroot (src > filename) && (*src != '.'); --src) 4091460Sroot continue; 4101460Sroot if (*src != '.') 4111460Sroot return(0); 4121460Sroot 4131460Sroot for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){ 4141460Sroot for (; *src /* not at end of the source */ 4151460Sroot && *pat /* not off end of pattern */ 4161460Sroot && *pat != '.' /* not off end of sub pattern */ 4171460Sroot && *pat != '*' /* not wild card */ 4181460Sroot && *src == *pat; /* and equal... */ 4191460Sroot src++, pat++) 4201460Sroot continue; 4211460Sroot if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*')) 4221460Sroot return(1); 4231460Sroot if (*src != 0 && *pat == '*') 4241460Sroot return(1); 4251460Sroot while (*pat && *pat != '.') 4261460Sroot pat++; 4271460Sroot if (! *pat) 4281460Sroot return(0); 4291460Sroot } 4301460Sroot return(0); 4311460Sroot } 4325595Srrh /* 4335595Srrh * Construct an execv argument 4345595Srrh * We need 1 argument for the editor's name 4355595Srrh * We need 1 argument for the initial search string 4365595Srrh * We need n_pissed_on arguments for the file names 4375595Srrh * We need 1 argument that is a null for execv. 4385595Srrh * The caller fills in the editor's name. 4395595Srrh * We fill in the initial search string. 4405595Srrh * We fill in the arguments, and the null. 4415595Srrh */ 4425595Srrh execvarg(n_pissed_on, r_argc, r_argv) 4435595Srrh int n_pissed_on; 4445595Srrh int *r_argc; 4455595Srrh char ***r_argv; 4465595Srrh { 4475595Srrh Eptr p; 4485595Srrh char *sep; 4495595Srrh int fi; 4501460Sroot 4515595Srrh (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *)); 4525595Srrh (*r_argc) = n_pissed_on + 2; 4535595Srrh (*r_argv)[1] = "+1;/###/"; 4545595Srrh n_pissed_on = 2; 4555595Srrh if (!terse){ 4565595Srrh fprintf(stdout, "You touched file(s):"); 4575595Srrh sep = " "; 4585595Srrh } 4595595Srrh FILEITERATE(fi, 1){ 4605595Srrh if (!touchedfiles[fi]) 4615595Srrh continue; 4625595Srrh p = *(files[fi]); 4635595Srrh if (!terse){ 4645595Srrh fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]); 4655595Srrh sep = ", "; 4665595Srrh } 4675595Srrh (*r_argv)[n_pissed_on++] = p->error_text[0]; 4685595Srrh } 4695595Srrh if (!terse) 4705595Srrh fprintf(stdout, "\n"); 4715595Srrh (*r_argv)[n_pissed_on] = 0; 4725595Srrh } 4735595Srrh 4741460Sroot FILE *o_touchedfile; /* the old file */ 4751460Sroot FILE *n_touchedfile; /* the new file */ 4761460Sroot char *o_name; 4776612Srrh char n_name[64]; 4786612Srrh char *canon_name = "/tmp/ErrorXXXXXX"; 4791460Sroot int o_lineno; 4801460Sroot int n_lineno; 4811460Sroot boolean tempfileopen = FALSE; 4821460Sroot /* 4831460Sroot * open the file; guaranteed to be both readable and writable 4841460Sroot * Well, if it isn't, then return TRUE if something failed 4851460Sroot */ 4861460Sroot boolean edit(name) 4871460Sroot char *name; 4881460Sroot { 4891460Sroot o_name = name; 4901460Sroot if ( (o_touchedfile = fopen(name, "r")) == NULL){ 4911460Sroot fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n", 4921460Sroot processname, name); 4931460Sroot return(TRUE); 4941460Sroot } 4955595Srrh (void)strcpy(n_name, canon_name); 4965595Srrh (void)mktemp(n_name); 4971460Sroot if ( (n_touchedfile = fopen(n_name, "w")) == NULL){ 4981460Sroot fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n", 4991460Sroot processname, name); 5001460Sroot return(TRUE); 5011460Sroot } 5021460Sroot tempfileopen = TRUE; 5031460Sroot n_lineno = 0; 5041460Sroot o_lineno = 0; 5051460Sroot return(FALSE); 5061460Sroot } 5071460Sroot /* 5081460Sroot * Position to the line (before, after) the line given by place 5091460Sroot */ 5105595Srrh char edbuf[BUFSIZ]; 5111460Sroot insert(place) 5121460Sroot int place; 5131460Sroot { 5141460Sroot --place; /* always insert messages before the offending line*/ 5151460Sroot for(; o_lineno < place; o_lineno++, n_lineno++){ 5165595Srrh if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL) 5171460Sroot return; 5185595Srrh fputs(edbuf, n_touchedfile); 5191460Sroot } 5201460Sroot } 5211460Sroot 5225595Srrh text(p, use_all) 5235595Srrh reg Eptr p; 5245595Srrh boolean use_all; 5251460Sroot { 5261460Sroot int offset = use_all ? 0 : 2; 5275595Srrh 5285595Srrh fputs(lang_table[p->error_language].lang_incomment, n_touchedfile); 5291460Sroot fprintf(n_touchedfile, "%d [%s] ", 5305595Srrh p->error_line, 5315595Srrh lang_table[p->error_language].lang_name); 5325595Srrh wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset); 5335595Srrh fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile); 5341460Sroot n_lineno++; 5351460Sroot } 5361460Sroot 5376612Srrh /* 5386612Srrh * write the touched file to its temporary copy, 5396612Srrh * then bring the temporary in over the local file 5406612Srrh */ 5416612Srrh writetouched(overwrite) 5426612Srrh int overwrite; 5431460Sroot { 5446612Srrh reg int nread; 5456612Srrh reg FILE *localfile; 5466612Srrh reg FILE *tmpfile; 5476612Srrh int botch; 5489309Srrh int oktorm; 5495595Srrh 5509309Srrh botch = 0; 5519309Srrh oktorm = 1; 5525595Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){ 5539309Srrh if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){ 5549309Srrh /* 5559309Srrh * Catastrophe in temporary area: file system full? 5569309Srrh */ 5579309Srrh botch = 1; 5589309Srrh fprintf(stderr, 5599309Srrh "%s: write failure: No errors inserted in \"%s\"\n", 5609309Srrh processname, o_name); 5619309Srrh } 5621460Sroot } 5631460Sroot fclose(n_touchedfile); 5641460Sroot fclose(o_touchedfile); 5656612Srrh /* 5666612Srrh * Now, copy the temp file back over the original 5676612Srrh * file, thus preserving links, etc 5686612Srrh */ 5699309Srrh if (botch == 0 && overwrite){ 5706612Srrh botch = 0; 5716612Srrh localfile = NULL; 5726612Srrh tmpfile = NULL; 5736612Srrh if ((localfile = fopen(o_name, "w")) == NULL){ 5746612Srrh fprintf(stderr, 5756612Srrh "%s: Can't open file \"%s\" to overwrite.\n", 5766612Srrh processname, o_name); 5776612Srrh botch++; 5786612Srrh } 5796612Srrh if ((tmpfile = fopen(n_name, "r")) == NULL){ 5806612Srrh fprintf(stderr, "%s: Can't open file \"%s\" to read.\n", 5816612Srrh processname, n_name); 5826612Srrh botch++; 5836612Srrh } 5849309Srrh if (!botch) 5859309Srrh oktorm = mustoverwrite(localfile, tmpfile); 5866612Srrh if (localfile != NULL) 5876612Srrh fclose(localfile); 5886612Srrh if (tmpfile != NULL) 5896612Srrh fclose(tmpfile); 5906612Srrh } 5919309Srrh if (oktorm == 0){ 5929309Srrh fprintf(stderr, "%s: Catastrophe: A copy of \"%s\: was saved in \"%s\"\n", 5939309Srrh processname, o_name, n_name); 5949309Srrh exit(1); 5959309Srrh } 5966612Srrh /* 5976612Srrh * Kiss the temp file good bye 5986612Srrh */ 5991460Sroot unlink(n_name); 6001460Sroot tempfileopen = FALSE; 6016612Srrh return(TRUE); 6021460Sroot } 6039309Srrh /* 6049309Srrh * return 1 if the tmpfile can be removed after writing it out 6059309Srrh */ 6069309Srrh int mustoverwrite(preciousfile, tmpfile) 6079309Srrh FILE *preciousfile; 6089309Srrh FILE *tmpfile; 6099309Srrh { 6109309Srrh int nread; 6115595Srrh 6129309Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){ 6139309Srrh if (mustwrite(edbuf, nread, preciousfile) == 0) 6149309Srrh return(0); 6159309Srrh } 6169309Srrh return(1); 6179309Srrh } 6189309Srrh /* 6199309Srrh * return 0 on catastrophe 6209309Srrh */ 6219309Srrh mustwrite(base, n, preciousfile) 6229309Srrh char *base; 6239309Srrh int n; 6249309Srrh FILE *preciousfile; 6259309Srrh { 6269309Srrh int nwrote; 6279309Srrh 6289309Srrh if (n <= 0) 6299309Srrh return(1); 6309309Srrh nwrote = fwrite(base, 1, n, preciousfile); 6319309Srrh if (nwrote == n) 6329309Srrh return(1); 6339309Srrh perror(processname); 6349309Srrh switch(inquire(terse 6359309Srrh ? "Botch overwriting: retry? " 6369309Srrh : "Botch overwriting the source file: retry? ")){ 6379309Srrh case Q_YES: 6389309Srrh case Q_yes: 6399309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6409309Srrh return(1); 6419309Srrh case Q_NO: 6429309Srrh case Q_no: 6439309Srrh switch(inquire("Are you sure? ")){ 6449309Srrh case Q_YES: 6459309Srrh case Q_yes: 6469309Srrh return(0); 6479309Srrh case Q_NO: 6489309Srrh case Q_no: 6499309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6509309Srrh return(1); 6519309Srrh } 65216564Sralph default: 65316564Sralph return(0); 6549309Srrh } 6559309Srrh } 6569309Srrh 6571460Sroot onintr() 6581460Sroot { 6595595Srrh switch(inquire(terse 6605595Srrh ? "\nContinue? " 6615595Srrh : "\nInterrupt: Do you want to continue? ")){ 6625595Srrh case Q_YES: 6635595Srrh case Q_yes: 6641460Sroot signal(SIGINT, onintr); 6651460Sroot return; 6665595Srrh default: 6676612Srrh if (tempfileopen){ 6686612Srrh /* 6696612Srrh * Don't overwrite the original file! 6706612Srrh */ 6716612Srrh writetouched(0); 6726612Srrh } 6735595Srrh exit(1); 6741460Sroot } 6755595Srrh /*NOTREACHED*/ 6761460Sroot } 6775595Srrh 6781460Sroot errorprint(place, errorp, print_all) 6791460Sroot FILE *place; 6805595Srrh Eptr errorp; 6811460Sroot boolean print_all; 6821460Sroot { 6831460Sroot int offset = print_all ? 0 : 2; 6841460Sroot 6851460Sroot if (errorp->error_e_class == C_IGNORE) 6861460Sroot return; 6871460Sroot fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name); 6881460Sroot wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset); 6891460Sroot putc('\n', place); 6901460Sroot } 6911460Sroot 6925595Srrh int inquire(fmt, a1, a2) 6931460Sroot char *fmt; 6941460Sroot /*VARARGS1*/ 6951460Sroot { 6961460Sroot char buffer[128]; 69716564Sralph 69816564Sralph if (queryfile == NULL) 69916564Sralph return(0); 7001460Sroot for(;;){ 7011460Sroot do{ 7021460Sroot fflush(stdout); 7031460Sroot fprintf(stderr, fmt, a1, a2); 7041460Sroot fflush(stderr); 7051460Sroot } while (fgets(buffer, 127, queryfile) == NULL); 7065595Srrh switch(buffer[0]){ 7075595Srrh case 'Y': return(Q_YES); 7085595Srrh case 'y': return(Q_yes); 7095595Srrh case 'N': return(Q_NO); 7105595Srrh case 'n': return(Q_no); 7115595Srrh default: fprintf(stderr, "Yes or No only!\n"); 7125595Srrh } 7131460Sroot } 7141460Sroot } 7151460Sroot 7165595Srrh int probethisfile(name) 7175595Srrh char *name; 7181460Sroot { 7191460Sroot struct stat statbuf; 7205595Srrh if (stat(name, &statbuf) < 0) 7215595Srrh return(F_NOTEXIST); 7225595Srrh if((statbuf.st_mode & S_IREAD) == 0) 7235595Srrh return(F_NOTREAD); 7245595Srrh if((statbuf.st_mode & S_IWRITE) == 0) 7255595Srrh return(F_NOTWRITE); 7265595Srrh return(F_TOUCHIT); 7271460Sroot } 728