121639Sdist /* 221639Sdist * Copyright (c) 1980 Regents of the University of California. 334664Sbostic * All rights reserved. 434664Sbostic * 5*42683Sbostic * %sccs.include.redist.c% 621639Sdist */ 721639Sdist 821639Sdist #ifndef lint 9*42683Sbostic static char sccsid[] = "@(#)touch.c 5.6 (Berkeley) 06/01/90"; 1034664Sbostic #endif /* not lint */ 1121639Sdist 1237791Sbostic #include <sys/types.h> 1337791Sbostic #include <sys/stat.h> 1437791Sbostic #include <sys/signal.h> 151460Sroot #include <stdio.h> 161460Sroot #include <ctype.h> 171460Sroot #include "error.h" 1837791Sbostic #include "pathnames.h" 191460Sroot 205595Srrh /* 215595Srrh * Iterate through errors 225595Srrh */ 235595Srrh #define EITERATE(p, fv, i) for (p = fv[i]; p < fv[i+1]; p++) 245595Srrh #define ECITERATE(ei, p, lb) for (ei = lb; p = errors[ei],ei < nerrors; ei++) 255595Srrh 265595Srrh #define FILEITERATE(fi, lb) for (fi = lb; fi <= nfiles; fi++) 275595Srrh int touchstatus = Q_YES; 285595Srrh 291460Sroot findfiles(nerrors, errors, r_nfiles, r_files) 305595Srrh int nerrors; 315595Srrh Eptr *errors; 325595Srrh int *r_nfiles; 335595Srrh Eptr ***r_files; 341460Sroot { 355595Srrh int nfiles; 365595Srrh Eptr **files; 371460Sroot 385595Srrh char *name; 395595Srrh reg int ei; 405595Srrh int fi; 415595Srrh reg Eptr errorp; 425595Srrh 435595Srrh nfiles = countfiles(errors); 445595Srrh 455595Srrh files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*)); 461460Sroot touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean)); 471460Sroot /* 485595Srrh * Now, partition off the error messages 491460Sroot * into those that are synchronization, discarded or 501460Sroot * not specific to any file, and those that were 511460Sroot * nulled or true errors. 521460Sroot */ 531460Sroot files[0] = &errors[0]; 545595Srrh ECITERATE(ei, errorp, 0){ 555595Srrh if ( ! (NOTSORTABLE(errorp->error_e_class))) 565595Srrh break; 571460Sroot } 581460Sroot /* 595595Srrh * Now, and partition off all error messages 601460Sroot * for a given file. 611460Sroot */ 625595Srrh files[1] = &errors[ei]; 631460Sroot touchedfiles[0] = touchedfiles[1] = FALSE; 645595Srrh name = "\1"; 655595Srrh fi = 1; 665595Srrh ECITERATE(ei, errorp, ei){ 675595Srrh if ( (errorp->error_e_class == C_NULLED) 685595Srrh || (errorp->error_e_class == C_TRUE) ){ 695595Srrh if (strcmp(errorp->error_text[0], name) != 0){ 705595Srrh name = errorp->error_text[0]; 715595Srrh touchedfiles[fi] = FALSE; 725595Srrh files[fi] = &errors[ei]; 735595Srrh fi++; 741460Sroot } 751460Sroot } 761460Sroot } 775595Srrh files[fi] = &errors[nerrors]; 781460Sroot *r_nfiles = nfiles; 791460Sroot *r_files = files; 801460Sroot } 811460Sroot 825595Srrh int countfiles(errors) 835595Srrh Eptr *errors; 845595Srrh { 855595Srrh char *name; 865595Srrh int ei; 875595Srrh reg Eptr errorp; 885595Srrh 895595Srrh int nfiles; 905595Srrh nfiles = 0; 915595Srrh name = "\1"; 925595Srrh ECITERATE(ei, errorp, 0){ 935595Srrh if (SORTABLE(errorp->error_e_class)){ 945595Srrh if (strcmp(errorp->error_text[0],name) != 0){ 955595Srrh nfiles++; 965595Srrh name = errorp->error_text[0]; 975595Srrh } 985595Srrh } 995595Srrh } 1005595Srrh return(nfiles); 1015595Srrh } 1021460Sroot char *class_table[] = { 1031460Sroot /*C_UNKNOWN 0 */ "Unknown", 1041460Sroot /*C_IGNORE 1 */ "ignore", 1051460Sroot /*C_SYNC 2 */ "synchronization", 1061460Sroot /*C_DISCARD 3 */ "discarded", 1071460Sroot /*C_NONSPEC 4 */ "non specific", 1081460Sroot /*C_THISFILE 5 */ "specific to this file", 1091460Sroot /*C_NULLED 6 */ "nulled", 1101460Sroot /*C_TRUE 7 */ "true", 1111460Sroot /*C_DUPL 8 */ "duplicated" 1121460Sroot }; 1131460Sroot 1141460Sroot int class_count[C_LAST - C_FIRST] = {0}; 1151460Sroot 1161460Sroot filenames(nfiles, files) 1171460Sroot int nfiles; 1185595Srrh Eptr **files; 1191460Sroot { 1205595Srrh reg int fi; 1215595Srrh char *sep = " "; 1225595Srrh extern char *class_table[]; 1235595Srrh int someerrors; 1241460Sroot 1251460Sroot /* 1265595Srrh * first, simply dump out errors that 1271460Sroot * don't pertain to any file 1281460Sroot */ 1295595Srrh someerrors = nopertain(files); 1305595Srrh 1311460Sroot if (nfiles){ 1321460Sroot someerrors++; 1335595Srrh fprintf(stdout, terse 1345595Srrh ? "%d file%s" 1355595Srrh : "%d file%s contain%s errors", 1365595Srrh nfiles, plural(nfiles), verbform(nfiles)); 1375595Srrh if (!terse){ 1385595Srrh FILEITERATE(fi, 1){ 1395595Srrh fprintf(stdout, "%s\"%s\" (%d)", 1405595Srrh sep, (*files[fi])->error_text[0], 1415595Srrh files[fi+1] - files[fi]); 1425595Srrh sep = ", "; 1435595Srrh } 1441460Sroot } 1451460Sroot fprintf(stdout, "\n"); 1461460Sroot } 1471460Sroot if (!someerrors) 1481460Sroot fprintf(stdout, "No errors.\n"); 1491460Sroot } 1501460Sroot 1515595Srrh /* 1525595Srrh * Dump out errors that don't pertain to any file 1535595Srrh */ 1545595Srrh int nopertain(files) 1555595Srrh Eptr **files; 1565595Srrh { 1575595Srrh int type; 1585595Srrh int someerrors = 0; 1595595Srrh reg Eptr *erpp; 1605595Srrh reg Eptr errorp; 1615595Srrh 1625595Srrh if (files[1] - files[0] <= 0) 1635595Srrh return(0); 1645595Srrh for(type = C_UNKNOWN; NOTSORTABLE(type); type++){ 1655595Srrh if (class_count[type] <= 0) 1665595Srrh continue; 1675595Srrh if (type > C_SYNC) 1685595Srrh someerrors++; 1695595Srrh if (terse){ 1705595Srrh fprintf(stdout, "\t%d %s errors NOT PRINTED\n", 1715595Srrh class_count[type], class_table[type]); 1725595Srrh } else { 1735595Srrh fprintf(stdout, "\n\t%d %s errors follow\n", 1745595Srrh class_count[type], class_table[type]); 1755595Srrh EITERATE(erpp, files, 0){ 1765595Srrh errorp = *erpp; 1775595Srrh if (errorp->error_e_class == type){ 1785595Srrh errorprint(stdout, errorp, TRUE); 1795595Srrh } 1805595Srrh } 1815595Srrh } 1825595Srrh } 1835595Srrh return(someerrors); 1845595Srrh } 1855595Srrh 1861460Sroot extern boolean notouch; 1871460Sroot 1881460Sroot boolean touchfiles(nfiles, files, r_edargc, r_edargv) 1891460Sroot int nfiles; 1905595Srrh Eptr **files; 1911460Sroot int *r_edargc; 1921460Sroot char ***r_edargv; 1931460Sroot { 1945595Srrh char *name; 1955595Srrh reg Eptr errorp; 1965595Srrh reg int fi; 1975595Srrh reg Eptr *erpp; 1985595Srrh int ntrueerrors; 1995595Srrh boolean scribbled; 2005595Srrh int n_pissed_on; /* # of file touched*/ 2015595Srrh int spread; 2021462Sroot 2035595Srrh FILEITERATE(fi, 1){ 2045595Srrh name = (*files[fi])->error_text[0]; 2055595Srrh spread = files[fi+1] - files[fi]; 2065595Srrh fprintf(stdout, terse 2075595Srrh ? "\"%s\" has %d error%s, " 2085595Srrh : "\nFile \"%s\" has %d error%s.\n" 2095595Srrh , name ,spread ,plural(spread)); 2101460Sroot /* 2111460Sroot * First, iterate through all error messages in this file 2121460Sroot * to see how many of the error messages really will 2131460Sroot * get inserted into the file. 2141460Sroot */ 2155595Srrh ntrueerrors = 0; 2165595Srrh EITERATE(erpp, files, fi){ 2171460Sroot errorp = *erpp; 2181460Sroot if (errorp->error_e_class == C_TRUE) 2191460Sroot ntrueerrors++; 2201460Sroot } 2215595Srrh fprintf(stdout, terse 2225595Srrh ? "insert %d\n" 2235595Srrh : "\t%d of these errors can be inserted into the file.\n", 2241460Sroot ntrueerrors); 2251460Sroot 2265595Srrh hackfile(name, files, fi, ntrueerrors); 2275595Srrh } 2281460Sroot scribbled = FALSE; 2295595Srrh n_pissed_on = 0; 2305595Srrh FILEITERATE(fi, 1){ 2315595Srrh scribbled |= touchedfiles[fi]; 2321460Sroot n_pissed_on++; 2331460Sroot } 2341460Sroot if (scribbled){ 2351460Sroot /* 2361460Sroot * Construct an execv argument 2371460Sroot */ 2385595Srrh execvarg(n_pissed_on, r_edargc, r_edargv); 2391460Sroot return(TRUE); 2401460Sroot } else { 2415595Srrh if (!terse) 2425595Srrh fprintf(stdout, "You didn't touch any files.\n"); 2431460Sroot return(FALSE); 2441460Sroot } 2455595Srrh } 2461460Sroot 2475595Srrh hackfile(name, files, ix, nerrors) 2485595Srrh char *name; 2495595Srrh Eptr **files; 2505595Srrh int ix; 2515595Srrh { 2525595Srrh boolean previewed; 2535595Srrh int errordest; /* where errors go*/ 2545595Srrh 25517212Sralph if (!oktotouch(name)) { 25617212Sralph previewed = FALSE; 25717212Sralph errordest = TOSTDOUT; 25817212Sralph } else { 25917212Sralph previewed = preview(name, nerrors, files, ix); 26017212Sralph errordest = settotouch(name); 26117212Sralph } 2625595Srrh 2635595Srrh if (errordest != TOSTDOUT) 2645595Srrh touchedfiles[ix] = TRUE; 2655595Srrh 2665595Srrh if (previewed && (errordest == TOSTDOUT)) 2675595Srrh return; 2685595Srrh 2695595Srrh diverterrors(name, errordest, files, ix, previewed, nerrors); 2705595Srrh 2716612Srrh if (errordest == TOTHEFILE){ 2726612Srrh /* 2736612Srrh * overwrite the original file 2746612Srrh */ 2756612Srrh writetouched(1); 2766612Srrh } 2775595Srrh } 2785595Srrh 2795595Srrh boolean preview(name, nerrors, files, ix) 2805595Srrh char *name; 2815595Srrh int nerrors; 2825595Srrh Eptr **files; 2835595Srrh int ix; 2845595Srrh { 2855595Srrh int back; 2865595Srrh reg Eptr *erpp; 2875595Srrh 2885595Srrh if (nerrors <= 0) 28917212Sralph return(FALSE); 29017212Sralph back = FALSE; 2915595Srrh if(query){ 2925595Srrh switch(inquire(terse 2935595Srrh ? "Preview? " 2945595Srrh : "Do you want to preview the errors first? ")){ 2955595Srrh case Q_YES: 2965595Srrh case Q_yes: 29717212Sralph back = TRUE; 2985595Srrh EITERATE(erpp, files, ix){ 2995595Srrh errorprint(stdout, *erpp, TRUE); 3005595Srrh } 3015595Srrh if (!terse) 3025595Srrh fprintf(stdout, "\n"); 3035595Srrh default: 3045595Srrh break; 3055595Srrh } 3065595Srrh } 3075595Srrh return(back); 3085595Srrh } 3095595Srrh 3105595Srrh int settotouch(name) 3115595Srrh char *name; 3125595Srrh { 3135595Srrh int dest = TOSTDOUT; 3145595Srrh 3155595Srrh if (query){ 3165595Srrh switch(touchstatus = inquire(terse 3175595Srrh ? "Touch? " 3185595Srrh : "Do you want to touch file \"%s\"? ", 3195595Srrh name)){ 3205595Srrh case Q_NO: 3215595Srrh case Q_no: 3225595Srrh return(dest); 3235595Srrh default: 3245595Srrh break; 3255595Srrh } 3265595Srrh } 3275595Srrh 3285595Srrh switch(probethisfile(name)){ 3295595Srrh case F_NOTREAD: 3305595Srrh dest = TOSTDOUT; 3315595Srrh fprintf(stdout, terse 3325595Srrh ? "\"%s\" unreadable\n" 3335595Srrh : "File \"%s\" is unreadable\n", 3345595Srrh name); 3355595Srrh break; 3365595Srrh case F_NOTWRITE: 3375595Srrh dest = TOSTDOUT; 3385595Srrh fprintf(stdout, terse 3395595Srrh ? "\"%s\" unwritable\n" 3405595Srrh : "File \"%s\" is unwritable\n", 3415595Srrh name); 3425595Srrh break; 3435595Srrh case F_NOTEXIST: 3445595Srrh dest = TOSTDOUT; 3455595Srrh fprintf(stdout, terse 3465595Srrh ? "\"%s\" not found\n" 3475595Srrh : "Can't find file \"%s\" to insert error messages into.\n", 3485595Srrh name); 3495595Srrh break; 3505595Srrh default: 3515595Srrh dest = edit(name) ? TOSTDOUT : TOTHEFILE; 3525595Srrh break; 3535595Srrh } 3545595Srrh return(dest); 3555595Srrh } 3565595Srrh 3575595Srrh diverterrors(name, dest, files, ix, previewed, nterrors) 3585595Srrh char *name; 3595595Srrh int dest; 3605595Srrh Eptr **files; 3615595Srrh int ix; 3625595Srrh boolean previewed; 3635595Srrh int nterrors; 3645595Srrh { 3655595Srrh int nerrors; 3665595Srrh reg Eptr *erpp; 3675595Srrh reg Eptr errorp; 3685595Srrh 3695595Srrh nerrors = files[ix+1] - files[ix]; 3705595Srrh 3715595Srrh if ( (nerrors != nterrors) 3725595Srrh && (!previewed) ){ 3735595Srrh fprintf(stdout, terse 3745595Srrh ? "Uninserted errors\n" 3755595Srrh : ">>Uninserted errors for file \"%s\" follow.\n", 3765595Srrh name); 3775595Srrh } 3785595Srrh 3795595Srrh EITERATE(erpp, files, ix){ 3805595Srrh errorp = *erpp; 3815595Srrh if (errorp->error_e_class != C_TRUE){ 3825595Srrh if (previewed || touchstatus == Q_NO) 3835595Srrh continue; 3845595Srrh errorprint(stdout, errorp, TRUE); 3855595Srrh continue; 3865595Srrh } 3875595Srrh switch (dest){ 3885595Srrh case TOSTDOUT: 3895595Srrh if (previewed || touchstatus == Q_NO) 3905595Srrh continue; 3915595Srrh errorprint(stdout,errorp, TRUE); 3925595Srrh break; 3935595Srrh case TOTHEFILE: 3945595Srrh insert(errorp->error_line); 3955595Srrh text(errorp, FALSE); 3965595Srrh break; 3975595Srrh } 3985595Srrh } 3995595Srrh } 4005595Srrh 4015595Srrh int oktotouch(filename) 4021460Sroot char *filename; 4031460Sroot { 4041460Sroot extern char *suffixlist; 4055595Srrh reg char *src; 4065595Srrh reg char *pat; 4071460Sroot char *osrc; 4081460Sroot 4091460Sroot pat = suffixlist; 4101460Sroot if (pat == 0) 4111460Sroot return(0); 4121460Sroot if (*pat == '*') 4131460Sroot return(1); 4141460Sroot while (*pat++ != '.') 4151460Sroot continue; 4161460Sroot --pat; /* point to the period */ 4171460Sroot 4181460Sroot for (src = &filename[strlen(filename)], --src; 4191460Sroot (src > filename) && (*src != '.'); --src) 4201460Sroot continue; 4211460Sroot if (*src != '.') 4221460Sroot return(0); 4231460Sroot 4241460Sroot for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){ 4251460Sroot for (; *src /* not at end of the source */ 4261460Sroot && *pat /* not off end of pattern */ 4271460Sroot && *pat != '.' /* not off end of sub pattern */ 4281460Sroot && *pat != '*' /* not wild card */ 4291460Sroot && *src == *pat; /* and equal... */ 4301460Sroot src++, pat++) 4311460Sroot continue; 4321460Sroot if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*')) 4331460Sroot return(1); 4341460Sroot if (*src != 0 && *pat == '*') 4351460Sroot return(1); 4361460Sroot while (*pat && *pat != '.') 4371460Sroot pat++; 4381460Sroot if (! *pat) 4391460Sroot return(0); 4401460Sroot } 4411460Sroot return(0); 4421460Sroot } 4435595Srrh /* 4445595Srrh * Construct an execv argument 4455595Srrh * We need 1 argument for the editor's name 4465595Srrh * We need 1 argument for the initial search string 4475595Srrh * We need n_pissed_on arguments for the file names 4485595Srrh * We need 1 argument that is a null for execv. 4495595Srrh * The caller fills in the editor's name. 4505595Srrh * We fill in the initial search string. 4515595Srrh * We fill in the arguments, and the null. 4525595Srrh */ 4535595Srrh execvarg(n_pissed_on, r_argc, r_argv) 4545595Srrh int n_pissed_on; 4555595Srrh int *r_argc; 4565595Srrh char ***r_argv; 4575595Srrh { 4585595Srrh Eptr p; 4595595Srrh char *sep; 4605595Srrh int fi; 4611460Sroot 4625595Srrh (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *)); 4635595Srrh (*r_argc) = n_pissed_on + 2; 4645595Srrh (*r_argv)[1] = "+1;/###/"; 4655595Srrh n_pissed_on = 2; 4665595Srrh if (!terse){ 4675595Srrh fprintf(stdout, "You touched file(s):"); 4685595Srrh sep = " "; 4695595Srrh } 4705595Srrh FILEITERATE(fi, 1){ 4715595Srrh if (!touchedfiles[fi]) 4725595Srrh continue; 4735595Srrh p = *(files[fi]); 4745595Srrh if (!terse){ 4755595Srrh fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]); 4765595Srrh sep = ", "; 4775595Srrh } 4785595Srrh (*r_argv)[n_pissed_on++] = p->error_text[0]; 4795595Srrh } 4805595Srrh if (!terse) 4815595Srrh fprintf(stdout, "\n"); 4825595Srrh (*r_argv)[n_pissed_on] = 0; 4835595Srrh } 4845595Srrh 4851460Sroot FILE *o_touchedfile; /* the old file */ 4861460Sroot FILE *n_touchedfile; /* the new file */ 4871460Sroot char *o_name; 4886612Srrh char n_name[64]; 48937791Sbostic char *canon_name = _PATH_TMP; 4901460Sroot int o_lineno; 4911460Sroot int n_lineno; 4921460Sroot boolean tempfileopen = FALSE; 4931460Sroot /* 4941460Sroot * open the file; guaranteed to be both readable and writable 4951460Sroot * Well, if it isn't, then return TRUE if something failed 4961460Sroot */ 4971460Sroot boolean edit(name) 4981460Sroot char *name; 4991460Sroot { 5001460Sroot o_name = name; 5011460Sroot if ( (o_touchedfile = fopen(name, "r")) == NULL){ 5021460Sroot fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n", 5031460Sroot processname, name); 5041460Sroot return(TRUE); 5051460Sroot } 5065595Srrh (void)strcpy(n_name, canon_name); 5075595Srrh (void)mktemp(n_name); 5081460Sroot if ( (n_touchedfile = fopen(n_name, "w")) == NULL){ 5091460Sroot fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n", 5101460Sroot processname, name); 5111460Sroot return(TRUE); 5121460Sroot } 5131460Sroot tempfileopen = TRUE; 5141460Sroot n_lineno = 0; 5151460Sroot o_lineno = 0; 5161460Sroot return(FALSE); 5171460Sroot } 5181460Sroot /* 5191460Sroot * Position to the line (before, after) the line given by place 5201460Sroot */ 5215595Srrh char edbuf[BUFSIZ]; 5221460Sroot insert(place) 5231460Sroot int place; 5241460Sroot { 5251460Sroot --place; /* always insert messages before the offending line*/ 5261460Sroot for(; o_lineno < place; o_lineno++, n_lineno++){ 5275595Srrh if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL) 5281460Sroot return; 5295595Srrh fputs(edbuf, n_touchedfile); 5301460Sroot } 5311460Sroot } 5321460Sroot 5335595Srrh text(p, use_all) 5345595Srrh reg Eptr p; 5355595Srrh boolean use_all; 5361460Sroot { 5371460Sroot int offset = use_all ? 0 : 2; 5385595Srrh 5395595Srrh fputs(lang_table[p->error_language].lang_incomment, n_touchedfile); 5401460Sroot fprintf(n_touchedfile, "%d [%s] ", 5415595Srrh p->error_line, 5425595Srrh lang_table[p->error_language].lang_name); 5435595Srrh wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset); 5445595Srrh fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile); 5451460Sroot n_lineno++; 5461460Sroot } 5471460Sroot 5486612Srrh /* 5496612Srrh * write the touched file to its temporary copy, 5506612Srrh * then bring the temporary in over the local file 5516612Srrh */ 5526612Srrh writetouched(overwrite) 5536612Srrh int overwrite; 5541460Sroot { 5556612Srrh reg int nread; 5566612Srrh reg FILE *localfile; 5576612Srrh reg FILE *tmpfile; 5586612Srrh int botch; 5599309Srrh int oktorm; 5605595Srrh 5619309Srrh botch = 0; 5629309Srrh oktorm = 1; 5635595Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){ 5649309Srrh if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){ 5659309Srrh /* 5669309Srrh * Catastrophe in temporary area: file system full? 5679309Srrh */ 5689309Srrh botch = 1; 5699309Srrh fprintf(stderr, 5709309Srrh "%s: write failure: No errors inserted in \"%s\"\n", 5719309Srrh processname, o_name); 5729309Srrh } 5731460Sroot } 5741460Sroot fclose(n_touchedfile); 5751460Sroot fclose(o_touchedfile); 5766612Srrh /* 5776612Srrh * Now, copy the temp file back over the original 5786612Srrh * file, thus preserving links, etc 5796612Srrh */ 5809309Srrh if (botch == 0 && overwrite){ 5816612Srrh botch = 0; 5826612Srrh localfile = NULL; 5836612Srrh tmpfile = NULL; 5846612Srrh if ((localfile = fopen(o_name, "w")) == NULL){ 5856612Srrh fprintf(stderr, 5866612Srrh "%s: Can't open file \"%s\" to overwrite.\n", 5876612Srrh processname, o_name); 5886612Srrh botch++; 5896612Srrh } 5906612Srrh if ((tmpfile = fopen(n_name, "r")) == NULL){ 5916612Srrh fprintf(stderr, "%s: Can't open file \"%s\" to read.\n", 5926612Srrh processname, n_name); 5936612Srrh botch++; 5946612Srrh } 5959309Srrh if (!botch) 5969309Srrh oktorm = mustoverwrite(localfile, tmpfile); 5976612Srrh if (localfile != NULL) 5986612Srrh fclose(localfile); 5996612Srrh if (tmpfile != NULL) 6006612Srrh fclose(tmpfile); 6016612Srrh } 6029309Srrh if (oktorm == 0){ 60335266Sbostic fprintf(stderr, "%s: Catastrophe: A copy of \"%s\": was saved in \"%s\"\n", 6049309Srrh processname, o_name, n_name); 6059309Srrh exit(1); 6069309Srrh } 6076612Srrh /* 6086612Srrh * Kiss the temp file good bye 6096612Srrh */ 6101460Sroot unlink(n_name); 6111460Sroot tempfileopen = FALSE; 6126612Srrh return(TRUE); 6131460Sroot } 6149309Srrh /* 6159309Srrh * return 1 if the tmpfile can be removed after writing it out 6169309Srrh */ 6179309Srrh int mustoverwrite(preciousfile, tmpfile) 6189309Srrh FILE *preciousfile; 6199309Srrh FILE *tmpfile; 6209309Srrh { 6219309Srrh int nread; 6225595Srrh 6239309Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){ 6249309Srrh if (mustwrite(edbuf, nread, preciousfile) == 0) 6259309Srrh return(0); 6269309Srrh } 6279309Srrh return(1); 6289309Srrh } 6299309Srrh /* 6309309Srrh * return 0 on catastrophe 6319309Srrh */ 6329309Srrh mustwrite(base, n, preciousfile) 6339309Srrh char *base; 6349309Srrh int n; 6359309Srrh FILE *preciousfile; 6369309Srrh { 6379309Srrh int nwrote; 6389309Srrh 6399309Srrh if (n <= 0) 6409309Srrh return(1); 6419309Srrh nwrote = fwrite(base, 1, n, preciousfile); 6429309Srrh if (nwrote == n) 6439309Srrh return(1); 6449309Srrh perror(processname); 6459309Srrh switch(inquire(terse 6469309Srrh ? "Botch overwriting: retry? " 6479309Srrh : "Botch overwriting the source file: retry? ")){ 6489309Srrh case Q_YES: 6499309Srrh case Q_yes: 6509309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6519309Srrh return(1); 6529309Srrh case Q_NO: 6539309Srrh case Q_no: 6549309Srrh switch(inquire("Are you sure? ")){ 6559309Srrh case Q_YES: 6569309Srrh case Q_yes: 6579309Srrh return(0); 6589309Srrh case Q_NO: 6599309Srrh case Q_no: 6609309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6619309Srrh return(1); 6629309Srrh } 66316564Sralph default: 66416564Sralph return(0); 6659309Srrh } 6669309Srrh } 6679309Srrh 6681460Sroot onintr() 6691460Sroot { 6705595Srrh switch(inquire(terse 6715595Srrh ? "\nContinue? " 6725595Srrh : "\nInterrupt: Do you want to continue? ")){ 6735595Srrh case Q_YES: 6745595Srrh case Q_yes: 6751460Sroot signal(SIGINT, onintr); 6761460Sroot return; 6775595Srrh default: 6786612Srrh if (tempfileopen){ 6796612Srrh /* 6806612Srrh * Don't overwrite the original file! 6816612Srrh */ 6826612Srrh writetouched(0); 6836612Srrh } 6845595Srrh exit(1); 6851460Sroot } 6865595Srrh /*NOTREACHED*/ 6871460Sroot } 6885595Srrh 6891460Sroot errorprint(place, errorp, print_all) 6901460Sroot FILE *place; 6915595Srrh Eptr errorp; 6921460Sroot boolean print_all; 6931460Sroot { 6941460Sroot int offset = print_all ? 0 : 2; 6951460Sroot 6961460Sroot if (errorp->error_e_class == C_IGNORE) 6971460Sroot return; 6981460Sroot fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name); 6991460Sroot wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset); 7001460Sroot putc('\n', place); 7011460Sroot } 7021460Sroot 7035595Srrh int inquire(fmt, a1, a2) 7041460Sroot char *fmt; 7051460Sroot /*VARARGS1*/ 7061460Sroot { 7071460Sroot char buffer[128]; 70816564Sralph 70916564Sralph if (queryfile == NULL) 71016564Sralph return(0); 7111460Sroot for(;;){ 7121460Sroot do{ 7131460Sroot fflush(stdout); 7141460Sroot fprintf(stderr, fmt, a1, a2); 7151460Sroot fflush(stderr); 7161460Sroot } while (fgets(buffer, 127, queryfile) == NULL); 7175595Srrh switch(buffer[0]){ 7185595Srrh case 'Y': return(Q_YES); 7195595Srrh case 'y': return(Q_yes); 7205595Srrh case 'N': return(Q_NO); 7215595Srrh case 'n': return(Q_no); 7225595Srrh default: fprintf(stderr, "Yes or No only!\n"); 7235595Srrh } 7241460Sroot } 7251460Sroot } 7261460Sroot 7275595Srrh int probethisfile(name) 7285595Srrh char *name; 7291460Sroot { 7301460Sroot struct stat statbuf; 7315595Srrh if (stat(name, &statbuf) < 0) 7325595Srrh return(F_NOTEXIST); 7335595Srrh if((statbuf.st_mode & S_IREAD) == 0) 7345595Srrh return(F_NOTREAD); 7355595Srrh if((statbuf.st_mode & S_IWRITE) == 0) 7365595Srrh return(F_NOTWRITE); 7375595Srrh return(F_TOUCHIT); 7381460Sroot } 739