1*21639Sdist /* 2*21639Sdist * Copyright (c) 1980 Regents of the University of California. 3*21639Sdist * All rights reserved. The Berkeley software License Agreement 4*21639Sdist * specifies the terms and conditions for redistribution. 5*21639Sdist */ 6*21639Sdist 7*21639Sdist #ifndef lint 8*21639Sdist static char sccsid[] = "@(#)touch.c 5.1 (Berkeley) 05/31/85"; 9*21639Sdist #endif not lint 10*21639Sdist 111460Sroot #include <stdio.h> 121460Sroot #include <ctype.h> 131460Sroot #include <sys/types.h> 141460Sroot #include <sys/stat.h> 151460Sroot #include <signal.h> 161460Sroot #include "error.h" 171460Sroot 185595Srrh /* 195595Srrh * Iterate through errors 205595Srrh */ 215595Srrh #define EITERATE(p, fv, i) for (p = fv[i]; p < fv[i+1]; p++) 225595Srrh #define ECITERATE(ei, p, lb) for (ei = lb; p = errors[ei],ei < nerrors; ei++) 235595Srrh 245595Srrh #define FILEITERATE(fi, lb) for (fi = lb; fi <= nfiles; fi++) 255595Srrh int touchstatus = Q_YES; 265595Srrh 271460Sroot findfiles(nerrors, errors, r_nfiles, r_files) 285595Srrh int nerrors; 295595Srrh Eptr *errors; 305595Srrh int *r_nfiles; 315595Srrh Eptr ***r_files; 321460Sroot { 335595Srrh int nfiles; 345595Srrh Eptr **files; 351460Sroot 365595Srrh char *name; 375595Srrh reg int ei; 385595Srrh int fi; 395595Srrh reg Eptr errorp; 405595Srrh 415595Srrh nfiles = countfiles(errors); 425595Srrh 435595Srrh files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*)); 441460Sroot touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean)); 451460Sroot /* 465595Srrh * Now, partition off the error messages 471460Sroot * into those that are synchronization, discarded or 481460Sroot * not specific to any file, and those that were 491460Sroot * nulled or true errors. 501460Sroot */ 511460Sroot files[0] = &errors[0]; 525595Srrh ECITERATE(ei, errorp, 0){ 535595Srrh if ( ! (NOTSORTABLE(errorp->error_e_class))) 545595Srrh break; 551460Sroot } 561460Sroot /* 575595Srrh * Now, and partition off all error messages 581460Sroot * for a given file. 591460Sroot */ 605595Srrh files[1] = &errors[ei]; 611460Sroot touchedfiles[0] = touchedfiles[1] = FALSE; 625595Srrh name = "\1"; 635595Srrh fi = 1; 645595Srrh ECITERATE(ei, errorp, ei){ 655595Srrh if ( (errorp->error_e_class == C_NULLED) 665595Srrh || (errorp->error_e_class == C_TRUE) ){ 675595Srrh if (strcmp(errorp->error_text[0], name) != 0){ 685595Srrh name = errorp->error_text[0]; 695595Srrh touchedfiles[fi] = FALSE; 705595Srrh files[fi] = &errors[ei]; 715595Srrh fi++; 721460Sroot } 731460Sroot } 741460Sroot } 755595Srrh files[fi] = &errors[nerrors]; 761460Sroot *r_nfiles = nfiles; 771460Sroot *r_files = files; 781460Sroot } 791460Sroot 805595Srrh int countfiles(errors) 815595Srrh Eptr *errors; 825595Srrh { 835595Srrh char *name; 845595Srrh int ei; 855595Srrh reg Eptr errorp; 865595Srrh 875595Srrh int nfiles; 885595Srrh nfiles = 0; 895595Srrh name = "\1"; 905595Srrh ECITERATE(ei, errorp, 0){ 915595Srrh if (SORTABLE(errorp->error_e_class)){ 925595Srrh if (strcmp(errorp->error_text[0],name) != 0){ 935595Srrh nfiles++; 945595Srrh name = errorp->error_text[0]; 955595Srrh } 965595Srrh } 975595Srrh } 985595Srrh return(nfiles); 995595Srrh } 1001460Sroot char *class_table[] = { 1011460Sroot /*C_UNKNOWN 0 */ "Unknown", 1021460Sroot /*C_IGNORE 1 */ "ignore", 1031460Sroot /*C_SYNC 2 */ "synchronization", 1041460Sroot /*C_DISCARD 3 */ "discarded", 1051460Sroot /*C_NONSPEC 4 */ "non specific", 1061460Sroot /*C_THISFILE 5 */ "specific to this file", 1071460Sroot /*C_NULLED 6 */ "nulled", 1081460Sroot /*C_TRUE 7 */ "true", 1091460Sroot /*C_DUPL 8 */ "duplicated" 1101460Sroot }; 1111460Sroot 1121460Sroot int class_count[C_LAST - C_FIRST] = {0}; 1131460Sroot 1141460Sroot filenames(nfiles, files) 1151460Sroot int nfiles; 1165595Srrh Eptr **files; 1171460Sroot { 1185595Srrh reg int fi; 1195595Srrh char *sep = " "; 1205595Srrh extern char *class_table[]; 1215595Srrh int someerrors; 1221460Sroot 1231460Sroot /* 1245595Srrh * first, simply dump out errors that 1251460Sroot * don't pertain to any file 1261460Sroot */ 1275595Srrh someerrors = nopertain(files); 1285595Srrh 1291460Sroot if (nfiles){ 1301460Sroot someerrors++; 1315595Srrh fprintf(stdout, terse 1325595Srrh ? "%d file%s" 1335595Srrh : "%d file%s contain%s errors", 1345595Srrh nfiles, plural(nfiles), verbform(nfiles)); 1355595Srrh if (!terse){ 1365595Srrh FILEITERATE(fi, 1){ 1375595Srrh fprintf(stdout, "%s\"%s\" (%d)", 1385595Srrh sep, (*files[fi])->error_text[0], 1395595Srrh files[fi+1] - files[fi]); 1405595Srrh sep = ", "; 1415595Srrh } 1421460Sroot } 1431460Sroot fprintf(stdout, "\n"); 1441460Sroot } 1451460Sroot if (!someerrors) 1461460Sroot fprintf(stdout, "No errors.\n"); 1471460Sroot } 1481460Sroot 1495595Srrh /* 1505595Srrh * Dump out errors that don't pertain to any file 1515595Srrh */ 1525595Srrh int nopertain(files) 1535595Srrh Eptr **files; 1545595Srrh { 1555595Srrh int type; 1565595Srrh int someerrors = 0; 1575595Srrh reg Eptr *erpp; 1585595Srrh reg Eptr errorp; 1595595Srrh 1605595Srrh if (files[1] - files[0] <= 0) 1615595Srrh return(0); 1625595Srrh for(type = C_UNKNOWN; NOTSORTABLE(type); type++){ 1635595Srrh if (class_count[type] <= 0) 1645595Srrh continue; 1655595Srrh if (type > C_SYNC) 1665595Srrh someerrors++; 1675595Srrh if (terse){ 1685595Srrh fprintf(stdout, "\t%d %s errors NOT PRINTED\n", 1695595Srrh class_count[type], class_table[type]); 1705595Srrh } else { 1715595Srrh fprintf(stdout, "\n\t%d %s errors follow\n", 1725595Srrh class_count[type], class_table[type]); 1735595Srrh EITERATE(erpp, files, 0){ 1745595Srrh errorp = *erpp; 1755595Srrh if (errorp->error_e_class == type){ 1765595Srrh errorprint(stdout, errorp, TRUE); 1775595Srrh } 1785595Srrh } 1795595Srrh } 1805595Srrh } 1815595Srrh return(someerrors); 1825595Srrh } 1835595Srrh 1841460Sroot extern boolean notouch; 1851460Sroot 1861460Sroot boolean touchfiles(nfiles, files, r_edargc, r_edargv) 1871460Sroot int nfiles; 1885595Srrh Eptr **files; 1891460Sroot int *r_edargc; 1901460Sroot char ***r_edargv; 1911460Sroot { 1925595Srrh char *name; 1935595Srrh reg Eptr errorp; 1945595Srrh reg int fi; 1955595Srrh reg Eptr *erpp; 1965595Srrh int ntrueerrors; 1975595Srrh boolean scribbled; 1985595Srrh int n_pissed_on; /* # of file touched*/ 1995595Srrh int spread; 2001462Sroot 2015595Srrh FILEITERATE(fi, 1){ 2025595Srrh name = (*files[fi])->error_text[0]; 2035595Srrh spread = files[fi+1] - files[fi]; 2045595Srrh fprintf(stdout, terse 2055595Srrh ? "\"%s\" has %d error%s, " 2065595Srrh : "\nFile \"%s\" has %d error%s.\n" 2075595Srrh , name ,spread ,plural(spread)); 2081460Sroot /* 2091460Sroot * First, iterate through all error messages in this file 2101460Sroot * to see how many of the error messages really will 2111460Sroot * get inserted into the file. 2121460Sroot */ 2135595Srrh ntrueerrors = 0; 2145595Srrh EITERATE(erpp, files, fi){ 2151460Sroot errorp = *erpp; 2161460Sroot if (errorp->error_e_class == C_TRUE) 2171460Sroot ntrueerrors++; 2181460Sroot } 2195595Srrh fprintf(stdout, terse 2205595Srrh ? "insert %d\n" 2215595Srrh : "\t%d of these errors can be inserted into the file.\n", 2221460Sroot ntrueerrors); 2231460Sroot 2245595Srrh hackfile(name, files, fi, ntrueerrors); 2255595Srrh } 2261460Sroot scribbled = FALSE; 2275595Srrh n_pissed_on = 0; 2285595Srrh FILEITERATE(fi, 1){ 2295595Srrh scribbled |= touchedfiles[fi]; 2301460Sroot n_pissed_on++; 2311460Sroot } 2321460Sroot if (scribbled){ 2331460Sroot /* 2341460Sroot * Construct an execv argument 2351460Sroot */ 2365595Srrh execvarg(n_pissed_on, r_edargc, r_edargv); 2371460Sroot return(TRUE); 2381460Sroot } else { 2395595Srrh if (!terse) 2405595Srrh fprintf(stdout, "You didn't touch any files.\n"); 2411460Sroot return(FALSE); 2421460Sroot } 2435595Srrh } 2441460Sroot 2455595Srrh hackfile(name, files, ix, nerrors) 2465595Srrh char *name; 2475595Srrh Eptr **files; 2485595Srrh int ix; 2495595Srrh { 2505595Srrh boolean previewed; 2515595Srrh int errordest; /* where errors go*/ 2525595Srrh 25317212Sralph if (!oktotouch(name)) { 25417212Sralph previewed = FALSE; 25517212Sralph errordest = TOSTDOUT; 25617212Sralph } else { 25717212Sralph previewed = preview(name, nerrors, files, ix); 25817212Sralph errordest = settotouch(name); 25917212Sralph } 2605595Srrh 2615595Srrh if (errordest != TOSTDOUT) 2625595Srrh touchedfiles[ix] = TRUE; 2635595Srrh 2645595Srrh if (previewed && (errordest == TOSTDOUT)) 2655595Srrh return; 2665595Srrh 2675595Srrh diverterrors(name, errordest, files, ix, previewed, nerrors); 2685595Srrh 2696612Srrh if (errordest == TOTHEFILE){ 2706612Srrh /* 2716612Srrh * overwrite the original file 2726612Srrh */ 2736612Srrh writetouched(1); 2746612Srrh } 2755595Srrh } 2765595Srrh 2775595Srrh boolean preview(name, nerrors, files, ix) 2785595Srrh char *name; 2795595Srrh int nerrors; 2805595Srrh Eptr **files; 2815595Srrh int ix; 2825595Srrh { 2835595Srrh int back; 2845595Srrh reg Eptr *erpp; 2855595Srrh 2865595Srrh if (nerrors <= 0) 28717212Sralph return(FALSE); 28817212Sralph back = FALSE; 2895595Srrh if(query){ 2905595Srrh switch(inquire(terse 2915595Srrh ? "Preview? " 2925595Srrh : "Do you want to preview the errors first? ")){ 2935595Srrh case Q_YES: 2945595Srrh case Q_yes: 29517212Sralph back = TRUE; 2965595Srrh EITERATE(erpp, files, ix){ 2975595Srrh errorprint(stdout, *erpp, TRUE); 2985595Srrh } 2995595Srrh if (!terse) 3005595Srrh fprintf(stdout, "\n"); 3015595Srrh default: 3025595Srrh break; 3035595Srrh } 3045595Srrh } 3055595Srrh return(back); 3065595Srrh } 3075595Srrh 3085595Srrh int settotouch(name) 3095595Srrh char *name; 3105595Srrh { 3115595Srrh int dest = TOSTDOUT; 3125595Srrh 3135595Srrh if (query){ 3145595Srrh switch(touchstatus = inquire(terse 3155595Srrh ? "Touch? " 3165595Srrh : "Do you want to touch file \"%s\"? ", 3175595Srrh name)){ 3185595Srrh case Q_NO: 3195595Srrh case Q_no: 3205595Srrh return(dest); 3215595Srrh default: 3225595Srrh break; 3235595Srrh } 3245595Srrh } 3255595Srrh 3265595Srrh switch(probethisfile(name)){ 3275595Srrh case F_NOTREAD: 3285595Srrh dest = TOSTDOUT; 3295595Srrh fprintf(stdout, terse 3305595Srrh ? "\"%s\" unreadable\n" 3315595Srrh : "File \"%s\" is unreadable\n", 3325595Srrh name); 3335595Srrh break; 3345595Srrh case F_NOTWRITE: 3355595Srrh dest = TOSTDOUT; 3365595Srrh fprintf(stdout, terse 3375595Srrh ? "\"%s\" unwritable\n" 3385595Srrh : "File \"%s\" is unwritable\n", 3395595Srrh name); 3405595Srrh break; 3415595Srrh case F_NOTEXIST: 3425595Srrh dest = TOSTDOUT; 3435595Srrh fprintf(stdout, terse 3445595Srrh ? "\"%s\" not found\n" 3455595Srrh : "Can't find file \"%s\" to insert error messages into.\n", 3465595Srrh name); 3475595Srrh break; 3485595Srrh default: 3495595Srrh dest = edit(name) ? TOSTDOUT : TOTHEFILE; 3505595Srrh break; 3515595Srrh } 3525595Srrh return(dest); 3535595Srrh } 3545595Srrh 3555595Srrh diverterrors(name, dest, files, ix, previewed, nterrors) 3565595Srrh char *name; 3575595Srrh int dest; 3585595Srrh Eptr **files; 3595595Srrh int ix; 3605595Srrh boolean previewed; 3615595Srrh int nterrors; 3625595Srrh { 3635595Srrh int nerrors; 3645595Srrh reg Eptr *erpp; 3655595Srrh reg Eptr errorp; 3665595Srrh 3675595Srrh nerrors = files[ix+1] - files[ix]; 3685595Srrh 3695595Srrh if ( (nerrors != nterrors) 3705595Srrh && (!previewed) ){ 3715595Srrh fprintf(stdout, terse 3725595Srrh ? "Uninserted errors\n" 3735595Srrh : ">>Uninserted errors for file \"%s\" follow.\n", 3745595Srrh name); 3755595Srrh } 3765595Srrh 3775595Srrh EITERATE(erpp, files, ix){ 3785595Srrh errorp = *erpp; 3795595Srrh if (errorp->error_e_class != C_TRUE){ 3805595Srrh if (previewed || touchstatus == Q_NO) 3815595Srrh continue; 3825595Srrh errorprint(stdout, errorp, TRUE); 3835595Srrh continue; 3845595Srrh } 3855595Srrh switch (dest){ 3865595Srrh case TOSTDOUT: 3875595Srrh if (previewed || touchstatus == Q_NO) 3885595Srrh continue; 3895595Srrh errorprint(stdout,errorp, TRUE); 3905595Srrh break; 3915595Srrh case TOTHEFILE: 3925595Srrh insert(errorp->error_line); 3935595Srrh text(errorp, FALSE); 3945595Srrh break; 3955595Srrh } 3965595Srrh } 3975595Srrh } 3985595Srrh 3995595Srrh int oktotouch(filename) 4001460Sroot char *filename; 4011460Sroot { 4021460Sroot extern char *suffixlist; 4035595Srrh reg char *src; 4045595Srrh reg char *pat; 4051460Sroot char *osrc; 4061460Sroot 4071460Sroot pat = suffixlist; 4081460Sroot if (pat == 0) 4091460Sroot return(0); 4101460Sroot if (*pat == '*') 4111460Sroot return(1); 4121460Sroot while (*pat++ != '.') 4131460Sroot continue; 4141460Sroot --pat; /* point to the period */ 4151460Sroot 4161460Sroot for (src = &filename[strlen(filename)], --src; 4171460Sroot (src > filename) && (*src != '.'); --src) 4181460Sroot continue; 4191460Sroot if (*src != '.') 4201460Sroot return(0); 4211460Sroot 4221460Sroot for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){ 4231460Sroot for (; *src /* not at end of the source */ 4241460Sroot && *pat /* not off end of pattern */ 4251460Sroot && *pat != '.' /* not off end of sub pattern */ 4261460Sroot && *pat != '*' /* not wild card */ 4271460Sroot && *src == *pat; /* and equal... */ 4281460Sroot src++, pat++) 4291460Sroot continue; 4301460Sroot if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*')) 4311460Sroot return(1); 4321460Sroot if (*src != 0 && *pat == '*') 4331460Sroot return(1); 4341460Sroot while (*pat && *pat != '.') 4351460Sroot pat++; 4361460Sroot if (! *pat) 4371460Sroot return(0); 4381460Sroot } 4391460Sroot return(0); 4401460Sroot } 4415595Srrh /* 4425595Srrh * Construct an execv argument 4435595Srrh * We need 1 argument for the editor's name 4445595Srrh * We need 1 argument for the initial search string 4455595Srrh * We need n_pissed_on arguments for the file names 4465595Srrh * We need 1 argument that is a null for execv. 4475595Srrh * The caller fills in the editor's name. 4485595Srrh * We fill in the initial search string. 4495595Srrh * We fill in the arguments, and the null. 4505595Srrh */ 4515595Srrh execvarg(n_pissed_on, r_argc, r_argv) 4525595Srrh int n_pissed_on; 4535595Srrh int *r_argc; 4545595Srrh char ***r_argv; 4555595Srrh { 4565595Srrh Eptr p; 4575595Srrh char *sep; 4585595Srrh int fi; 4591460Sroot 4605595Srrh (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *)); 4615595Srrh (*r_argc) = n_pissed_on + 2; 4625595Srrh (*r_argv)[1] = "+1;/###/"; 4635595Srrh n_pissed_on = 2; 4645595Srrh if (!terse){ 4655595Srrh fprintf(stdout, "You touched file(s):"); 4665595Srrh sep = " "; 4675595Srrh } 4685595Srrh FILEITERATE(fi, 1){ 4695595Srrh if (!touchedfiles[fi]) 4705595Srrh continue; 4715595Srrh p = *(files[fi]); 4725595Srrh if (!terse){ 4735595Srrh fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]); 4745595Srrh sep = ", "; 4755595Srrh } 4765595Srrh (*r_argv)[n_pissed_on++] = p->error_text[0]; 4775595Srrh } 4785595Srrh if (!terse) 4795595Srrh fprintf(stdout, "\n"); 4805595Srrh (*r_argv)[n_pissed_on] = 0; 4815595Srrh } 4825595Srrh 4831460Sroot FILE *o_touchedfile; /* the old file */ 4841460Sroot FILE *n_touchedfile; /* the new file */ 4851460Sroot char *o_name; 4866612Srrh char n_name[64]; 4876612Srrh char *canon_name = "/tmp/ErrorXXXXXX"; 4881460Sroot int o_lineno; 4891460Sroot int n_lineno; 4901460Sroot boolean tempfileopen = FALSE; 4911460Sroot /* 4921460Sroot * open the file; guaranteed to be both readable and writable 4931460Sroot * Well, if it isn't, then return TRUE if something failed 4941460Sroot */ 4951460Sroot boolean edit(name) 4961460Sroot char *name; 4971460Sroot { 4981460Sroot o_name = name; 4991460Sroot if ( (o_touchedfile = fopen(name, "r")) == NULL){ 5001460Sroot fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n", 5011460Sroot processname, name); 5021460Sroot return(TRUE); 5031460Sroot } 5045595Srrh (void)strcpy(n_name, canon_name); 5055595Srrh (void)mktemp(n_name); 5061460Sroot if ( (n_touchedfile = fopen(n_name, "w")) == NULL){ 5071460Sroot fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n", 5081460Sroot processname, name); 5091460Sroot return(TRUE); 5101460Sroot } 5111460Sroot tempfileopen = TRUE; 5121460Sroot n_lineno = 0; 5131460Sroot o_lineno = 0; 5141460Sroot return(FALSE); 5151460Sroot } 5161460Sroot /* 5171460Sroot * Position to the line (before, after) the line given by place 5181460Sroot */ 5195595Srrh char edbuf[BUFSIZ]; 5201460Sroot insert(place) 5211460Sroot int place; 5221460Sroot { 5231460Sroot --place; /* always insert messages before the offending line*/ 5241460Sroot for(; o_lineno < place; o_lineno++, n_lineno++){ 5255595Srrh if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL) 5261460Sroot return; 5275595Srrh fputs(edbuf, n_touchedfile); 5281460Sroot } 5291460Sroot } 5301460Sroot 5315595Srrh text(p, use_all) 5325595Srrh reg Eptr p; 5335595Srrh boolean use_all; 5341460Sroot { 5351460Sroot int offset = use_all ? 0 : 2; 5365595Srrh 5375595Srrh fputs(lang_table[p->error_language].lang_incomment, n_touchedfile); 5381460Sroot fprintf(n_touchedfile, "%d [%s] ", 5395595Srrh p->error_line, 5405595Srrh lang_table[p->error_language].lang_name); 5415595Srrh wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset); 5425595Srrh fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile); 5431460Sroot n_lineno++; 5441460Sroot } 5451460Sroot 5466612Srrh /* 5476612Srrh * write the touched file to its temporary copy, 5486612Srrh * then bring the temporary in over the local file 5496612Srrh */ 5506612Srrh writetouched(overwrite) 5516612Srrh int overwrite; 5521460Sroot { 5536612Srrh reg int nread; 5546612Srrh reg FILE *localfile; 5556612Srrh reg FILE *tmpfile; 5566612Srrh int botch; 5579309Srrh int oktorm; 5585595Srrh 5599309Srrh botch = 0; 5609309Srrh oktorm = 1; 5615595Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){ 5629309Srrh if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){ 5639309Srrh /* 5649309Srrh * Catastrophe in temporary area: file system full? 5659309Srrh */ 5669309Srrh botch = 1; 5679309Srrh fprintf(stderr, 5689309Srrh "%s: write failure: No errors inserted in \"%s\"\n", 5699309Srrh processname, o_name); 5709309Srrh } 5711460Sroot } 5721460Sroot fclose(n_touchedfile); 5731460Sroot fclose(o_touchedfile); 5746612Srrh /* 5756612Srrh * Now, copy the temp file back over the original 5766612Srrh * file, thus preserving links, etc 5776612Srrh */ 5789309Srrh if (botch == 0 && overwrite){ 5796612Srrh botch = 0; 5806612Srrh localfile = NULL; 5816612Srrh tmpfile = NULL; 5826612Srrh if ((localfile = fopen(o_name, "w")) == NULL){ 5836612Srrh fprintf(stderr, 5846612Srrh "%s: Can't open file \"%s\" to overwrite.\n", 5856612Srrh processname, o_name); 5866612Srrh botch++; 5876612Srrh } 5886612Srrh if ((tmpfile = fopen(n_name, "r")) == NULL){ 5896612Srrh fprintf(stderr, "%s: Can't open file \"%s\" to read.\n", 5906612Srrh processname, n_name); 5916612Srrh botch++; 5926612Srrh } 5939309Srrh if (!botch) 5949309Srrh oktorm = mustoverwrite(localfile, tmpfile); 5956612Srrh if (localfile != NULL) 5966612Srrh fclose(localfile); 5976612Srrh if (tmpfile != NULL) 5986612Srrh fclose(tmpfile); 5996612Srrh } 6009309Srrh if (oktorm == 0){ 6019309Srrh fprintf(stderr, "%s: Catastrophe: A copy of \"%s\: was saved in \"%s\"\n", 6029309Srrh processname, o_name, n_name); 6039309Srrh exit(1); 6049309Srrh } 6056612Srrh /* 6066612Srrh * Kiss the temp file good bye 6076612Srrh */ 6081460Sroot unlink(n_name); 6091460Sroot tempfileopen = FALSE; 6106612Srrh return(TRUE); 6111460Sroot } 6129309Srrh /* 6139309Srrh * return 1 if the tmpfile can be removed after writing it out 6149309Srrh */ 6159309Srrh int mustoverwrite(preciousfile, tmpfile) 6169309Srrh FILE *preciousfile; 6179309Srrh FILE *tmpfile; 6189309Srrh { 6199309Srrh int nread; 6205595Srrh 6219309Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){ 6229309Srrh if (mustwrite(edbuf, nread, preciousfile) == 0) 6239309Srrh return(0); 6249309Srrh } 6259309Srrh return(1); 6269309Srrh } 6279309Srrh /* 6289309Srrh * return 0 on catastrophe 6299309Srrh */ 6309309Srrh mustwrite(base, n, preciousfile) 6319309Srrh char *base; 6329309Srrh int n; 6339309Srrh FILE *preciousfile; 6349309Srrh { 6359309Srrh int nwrote; 6369309Srrh 6379309Srrh if (n <= 0) 6389309Srrh return(1); 6399309Srrh nwrote = fwrite(base, 1, n, preciousfile); 6409309Srrh if (nwrote == n) 6419309Srrh return(1); 6429309Srrh perror(processname); 6439309Srrh switch(inquire(terse 6449309Srrh ? "Botch overwriting: retry? " 6459309Srrh : "Botch overwriting the source file: retry? ")){ 6469309Srrh case Q_YES: 6479309Srrh case Q_yes: 6489309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6499309Srrh return(1); 6509309Srrh case Q_NO: 6519309Srrh case Q_no: 6529309Srrh switch(inquire("Are you sure? ")){ 6539309Srrh case Q_YES: 6549309Srrh case Q_yes: 6559309Srrh return(0); 6569309Srrh case Q_NO: 6579309Srrh case Q_no: 6589309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6599309Srrh return(1); 6609309Srrh } 66116564Sralph default: 66216564Sralph return(0); 6639309Srrh } 6649309Srrh } 6659309Srrh 6661460Sroot onintr() 6671460Sroot { 6685595Srrh switch(inquire(terse 6695595Srrh ? "\nContinue? " 6705595Srrh : "\nInterrupt: Do you want to continue? ")){ 6715595Srrh case Q_YES: 6725595Srrh case Q_yes: 6731460Sroot signal(SIGINT, onintr); 6741460Sroot return; 6755595Srrh default: 6766612Srrh if (tempfileopen){ 6776612Srrh /* 6786612Srrh * Don't overwrite the original file! 6796612Srrh */ 6806612Srrh writetouched(0); 6816612Srrh } 6825595Srrh exit(1); 6831460Sroot } 6845595Srrh /*NOTREACHED*/ 6851460Sroot } 6865595Srrh 6871460Sroot errorprint(place, errorp, print_all) 6881460Sroot FILE *place; 6895595Srrh Eptr errorp; 6901460Sroot boolean print_all; 6911460Sroot { 6921460Sroot int offset = print_all ? 0 : 2; 6931460Sroot 6941460Sroot if (errorp->error_e_class == C_IGNORE) 6951460Sroot return; 6961460Sroot fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name); 6971460Sroot wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset); 6981460Sroot putc('\n', place); 6991460Sroot } 7001460Sroot 7015595Srrh int inquire(fmt, a1, a2) 7021460Sroot char *fmt; 7031460Sroot /*VARARGS1*/ 7041460Sroot { 7051460Sroot char buffer[128]; 70616564Sralph 70716564Sralph if (queryfile == NULL) 70816564Sralph return(0); 7091460Sroot for(;;){ 7101460Sroot do{ 7111460Sroot fflush(stdout); 7121460Sroot fprintf(stderr, fmt, a1, a2); 7131460Sroot fflush(stderr); 7141460Sroot } while (fgets(buffer, 127, queryfile) == NULL); 7155595Srrh switch(buffer[0]){ 7165595Srrh case 'Y': return(Q_YES); 7175595Srrh case 'y': return(Q_yes); 7185595Srrh case 'N': return(Q_NO); 7195595Srrh case 'n': return(Q_no); 7205595Srrh default: fprintf(stderr, "Yes or No only!\n"); 7215595Srrh } 7221460Sroot } 7231460Sroot } 7241460Sroot 7255595Srrh int probethisfile(name) 7265595Srrh char *name; 7271460Sroot { 7281460Sroot struct stat statbuf; 7295595Srrh if (stat(name, &statbuf) < 0) 7305595Srrh return(F_NOTEXIST); 7315595Srrh if((statbuf.st_mode & S_IREAD) == 0) 7325595Srrh return(F_NOTREAD); 7335595Srrh if((statbuf.st_mode & S_IWRITE) == 0) 7345595Srrh return(F_NOTWRITE); 7355595Srrh return(F_TOUCHIT); 7361460Sroot } 737