121639Sdist /* 221639Sdist * Copyright (c) 1980 Regents of the University of California. 334664Sbostic * All rights reserved. 434664Sbostic * 534664Sbostic * Redistribution and use in source and binary forms are permitted 634874Sbostic * provided that the above copyright notice and this paragraph are 734874Sbostic * duplicated in all such forms and that any documentation, 834874Sbostic * advertising materials, and other materials related to such 934874Sbostic * distribution and use acknowledge that the software was developed 1034874Sbostic * by the University of California, Berkeley. The name of the 1134874Sbostic * University may not be used to endorse or promote products derived 1234874Sbostic * from this software without specific prior written permission. 1334874Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434874Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534874Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621639Sdist */ 1721639Sdist 1821639Sdist #ifndef lint 19*37791Sbostic static char sccsid[] = "@(#)touch.c 5.5 (Berkeley) 05/10/89"; 2034664Sbostic #endif /* not lint */ 2121639Sdist 22*37791Sbostic #include <sys/types.h> 23*37791Sbostic #include <sys/stat.h> 24*37791Sbostic #include <sys/signal.h> 251460Sroot #include <stdio.h> 261460Sroot #include <ctype.h> 271460Sroot #include "error.h" 28*37791Sbostic #include "pathnames.h" 291460Sroot 305595Srrh /* 315595Srrh * Iterate through errors 325595Srrh */ 335595Srrh #define EITERATE(p, fv, i) for (p = fv[i]; p < fv[i+1]; p++) 345595Srrh #define ECITERATE(ei, p, lb) for (ei = lb; p = errors[ei],ei < nerrors; ei++) 355595Srrh 365595Srrh #define FILEITERATE(fi, lb) for (fi = lb; fi <= nfiles; fi++) 375595Srrh int touchstatus = Q_YES; 385595Srrh 391460Sroot findfiles(nerrors, errors, r_nfiles, r_files) 405595Srrh int nerrors; 415595Srrh Eptr *errors; 425595Srrh int *r_nfiles; 435595Srrh Eptr ***r_files; 441460Sroot { 455595Srrh int nfiles; 465595Srrh Eptr **files; 471460Sroot 485595Srrh char *name; 495595Srrh reg int ei; 505595Srrh int fi; 515595Srrh reg Eptr errorp; 525595Srrh 535595Srrh nfiles = countfiles(errors); 545595Srrh 555595Srrh files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*)); 561460Sroot touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean)); 571460Sroot /* 585595Srrh * Now, partition off the error messages 591460Sroot * into those that are synchronization, discarded or 601460Sroot * not specific to any file, and those that were 611460Sroot * nulled or true errors. 621460Sroot */ 631460Sroot files[0] = &errors[0]; 645595Srrh ECITERATE(ei, errorp, 0){ 655595Srrh if ( ! (NOTSORTABLE(errorp->error_e_class))) 665595Srrh break; 671460Sroot } 681460Sroot /* 695595Srrh * Now, and partition off all error messages 701460Sroot * for a given file. 711460Sroot */ 725595Srrh files[1] = &errors[ei]; 731460Sroot touchedfiles[0] = touchedfiles[1] = FALSE; 745595Srrh name = "\1"; 755595Srrh fi = 1; 765595Srrh ECITERATE(ei, errorp, ei){ 775595Srrh if ( (errorp->error_e_class == C_NULLED) 785595Srrh || (errorp->error_e_class == C_TRUE) ){ 795595Srrh if (strcmp(errorp->error_text[0], name) != 0){ 805595Srrh name = errorp->error_text[0]; 815595Srrh touchedfiles[fi] = FALSE; 825595Srrh files[fi] = &errors[ei]; 835595Srrh fi++; 841460Sroot } 851460Sroot } 861460Sroot } 875595Srrh files[fi] = &errors[nerrors]; 881460Sroot *r_nfiles = nfiles; 891460Sroot *r_files = files; 901460Sroot } 911460Sroot 925595Srrh int countfiles(errors) 935595Srrh Eptr *errors; 945595Srrh { 955595Srrh char *name; 965595Srrh int ei; 975595Srrh reg Eptr errorp; 985595Srrh 995595Srrh int nfiles; 1005595Srrh nfiles = 0; 1015595Srrh name = "\1"; 1025595Srrh ECITERATE(ei, errorp, 0){ 1035595Srrh if (SORTABLE(errorp->error_e_class)){ 1045595Srrh if (strcmp(errorp->error_text[0],name) != 0){ 1055595Srrh nfiles++; 1065595Srrh name = errorp->error_text[0]; 1075595Srrh } 1085595Srrh } 1095595Srrh } 1105595Srrh return(nfiles); 1115595Srrh } 1121460Sroot char *class_table[] = { 1131460Sroot /*C_UNKNOWN 0 */ "Unknown", 1141460Sroot /*C_IGNORE 1 */ "ignore", 1151460Sroot /*C_SYNC 2 */ "synchronization", 1161460Sroot /*C_DISCARD 3 */ "discarded", 1171460Sroot /*C_NONSPEC 4 */ "non specific", 1181460Sroot /*C_THISFILE 5 */ "specific to this file", 1191460Sroot /*C_NULLED 6 */ "nulled", 1201460Sroot /*C_TRUE 7 */ "true", 1211460Sroot /*C_DUPL 8 */ "duplicated" 1221460Sroot }; 1231460Sroot 1241460Sroot int class_count[C_LAST - C_FIRST] = {0}; 1251460Sroot 1261460Sroot filenames(nfiles, files) 1271460Sroot int nfiles; 1285595Srrh Eptr **files; 1291460Sroot { 1305595Srrh reg int fi; 1315595Srrh char *sep = " "; 1325595Srrh extern char *class_table[]; 1335595Srrh int someerrors; 1341460Sroot 1351460Sroot /* 1365595Srrh * first, simply dump out errors that 1371460Sroot * don't pertain to any file 1381460Sroot */ 1395595Srrh someerrors = nopertain(files); 1405595Srrh 1411460Sroot if (nfiles){ 1421460Sroot someerrors++; 1435595Srrh fprintf(stdout, terse 1445595Srrh ? "%d file%s" 1455595Srrh : "%d file%s contain%s errors", 1465595Srrh nfiles, plural(nfiles), verbform(nfiles)); 1475595Srrh if (!terse){ 1485595Srrh FILEITERATE(fi, 1){ 1495595Srrh fprintf(stdout, "%s\"%s\" (%d)", 1505595Srrh sep, (*files[fi])->error_text[0], 1515595Srrh files[fi+1] - files[fi]); 1525595Srrh sep = ", "; 1535595Srrh } 1541460Sroot } 1551460Sroot fprintf(stdout, "\n"); 1561460Sroot } 1571460Sroot if (!someerrors) 1581460Sroot fprintf(stdout, "No errors.\n"); 1591460Sroot } 1601460Sroot 1615595Srrh /* 1625595Srrh * Dump out errors that don't pertain to any file 1635595Srrh */ 1645595Srrh int nopertain(files) 1655595Srrh Eptr **files; 1665595Srrh { 1675595Srrh int type; 1685595Srrh int someerrors = 0; 1695595Srrh reg Eptr *erpp; 1705595Srrh reg Eptr errorp; 1715595Srrh 1725595Srrh if (files[1] - files[0] <= 0) 1735595Srrh return(0); 1745595Srrh for(type = C_UNKNOWN; NOTSORTABLE(type); type++){ 1755595Srrh if (class_count[type] <= 0) 1765595Srrh continue; 1775595Srrh if (type > C_SYNC) 1785595Srrh someerrors++; 1795595Srrh if (terse){ 1805595Srrh fprintf(stdout, "\t%d %s errors NOT PRINTED\n", 1815595Srrh class_count[type], class_table[type]); 1825595Srrh } else { 1835595Srrh fprintf(stdout, "\n\t%d %s errors follow\n", 1845595Srrh class_count[type], class_table[type]); 1855595Srrh EITERATE(erpp, files, 0){ 1865595Srrh errorp = *erpp; 1875595Srrh if (errorp->error_e_class == type){ 1885595Srrh errorprint(stdout, errorp, TRUE); 1895595Srrh } 1905595Srrh } 1915595Srrh } 1925595Srrh } 1935595Srrh return(someerrors); 1945595Srrh } 1955595Srrh 1961460Sroot extern boolean notouch; 1971460Sroot 1981460Sroot boolean touchfiles(nfiles, files, r_edargc, r_edargv) 1991460Sroot int nfiles; 2005595Srrh Eptr **files; 2011460Sroot int *r_edargc; 2021460Sroot char ***r_edargv; 2031460Sroot { 2045595Srrh char *name; 2055595Srrh reg Eptr errorp; 2065595Srrh reg int fi; 2075595Srrh reg Eptr *erpp; 2085595Srrh int ntrueerrors; 2095595Srrh boolean scribbled; 2105595Srrh int n_pissed_on; /* # of file touched*/ 2115595Srrh int spread; 2121462Sroot 2135595Srrh FILEITERATE(fi, 1){ 2145595Srrh name = (*files[fi])->error_text[0]; 2155595Srrh spread = files[fi+1] - files[fi]; 2165595Srrh fprintf(stdout, terse 2175595Srrh ? "\"%s\" has %d error%s, " 2185595Srrh : "\nFile \"%s\" has %d error%s.\n" 2195595Srrh , name ,spread ,plural(spread)); 2201460Sroot /* 2211460Sroot * First, iterate through all error messages in this file 2221460Sroot * to see how many of the error messages really will 2231460Sroot * get inserted into the file. 2241460Sroot */ 2255595Srrh ntrueerrors = 0; 2265595Srrh EITERATE(erpp, files, fi){ 2271460Sroot errorp = *erpp; 2281460Sroot if (errorp->error_e_class == C_TRUE) 2291460Sroot ntrueerrors++; 2301460Sroot } 2315595Srrh fprintf(stdout, terse 2325595Srrh ? "insert %d\n" 2335595Srrh : "\t%d of these errors can be inserted into the file.\n", 2341460Sroot ntrueerrors); 2351460Sroot 2365595Srrh hackfile(name, files, fi, ntrueerrors); 2375595Srrh } 2381460Sroot scribbled = FALSE; 2395595Srrh n_pissed_on = 0; 2405595Srrh FILEITERATE(fi, 1){ 2415595Srrh scribbled |= touchedfiles[fi]; 2421460Sroot n_pissed_on++; 2431460Sroot } 2441460Sroot if (scribbled){ 2451460Sroot /* 2461460Sroot * Construct an execv argument 2471460Sroot */ 2485595Srrh execvarg(n_pissed_on, r_edargc, r_edargv); 2491460Sroot return(TRUE); 2501460Sroot } else { 2515595Srrh if (!terse) 2525595Srrh fprintf(stdout, "You didn't touch any files.\n"); 2531460Sroot return(FALSE); 2541460Sroot } 2555595Srrh } 2561460Sroot 2575595Srrh hackfile(name, files, ix, nerrors) 2585595Srrh char *name; 2595595Srrh Eptr **files; 2605595Srrh int ix; 2615595Srrh { 2625595Srrh boolean previewed; 2635595Srrh int errordest; /* where errors go*/ 2645595Srrh 26517212Sralph if (!oktotouch(name)) { 26617212Sralph previewed = FALSE; 26717212Sralph errordest = TOSTDOUT; 26817212Sralph } else { 26917212Sralph previewed = preview(name, nerrors, files, ix); 27017212Sralph errordest = settotouch(name); 27117212Sralph } 2725595Srrh 2735595Srrh if (errordest != TOSTDOUT) 2745595Srrh touchedfiles[ix] = TRUE; 2755595Srrh 2765595Srrh if (previewed && (errordest == TOSTDOUT)) 2775595Srrh return; 2785595Srrh 2795595Srrh diverterrors(name, errordest, files, ix, previewed, nerrors); 2805595Srrh 2816612Srrh if (errordest == TOTHEFILE){ 2826612Srrh /* 2836612Srrh * overwrite the original file 2846612Srrh */ 2856612Srrh writetouched(1); 2866612Srrh } 2875595Srrh } 2885595Srrh 2895595Srrh boolean preview(name, nerrors, files, ix) 2905595Srrh char *name; 2915595Srrh int nerrors; 2925595Srrh Eptr **files; 2935595Srrh int ix; 2945595Srrh { 2955595Srrh int back; 2965595Srrh reg Eptr *erpp; 2975595Srrh 2985595Srrh if (nerrors <= 0) 29917212Sralph return(FALSE); 30017212Sralph back = FALSE; 3015595Srrh if(query){ 3025595Srrh switch(inquire(terse 3035595Srrh ? "Preview? " 3045595Srrh : "Do you want to preview the errors first? ")){ 3055595Srrh case Q_YES: 3065595Srrh case Q_yes: 30717212Sralph back = TRUE; 3085595Srrh EITERATE(erpp, files, ix){ 3095595Srrh errorprint(stdout, *erpp, TRUE); 3105595Srrh } 3115595Srrh if (!terse) 3125595Srrh fprintf(stdout, "\n"); 3135595Srrh default: 3145595Srrh break; 3155595Srrh } 3165595Srrh } 3175595Srrh return(back); 3185595Srrh } 3195595Srrh 3205595Srrh int settotouch(name) 3215595Srrh char *name; 3225595Srrh { 3235595Srrh int dest = TOSTDOUT; 3245595Srrh 3255595Srrh if (query){ 3265595Srrh switch(touchstatus = inquire(terse 3275595Srrh ? "Touch? " 3285595Srrh : "Do you want to touch file \"%s\"? ", 3295595Srrh name)){ 3305595Srrh case Q_NO: 3315595Srrh case Q_no: 3325595Srrh return(dest); 3335595Srrh default: 3345595Srrh break; 3355595Srrh } 3365595Srrh } 3375595Srrh 3385595Srrh switch(probethisfile(name)){ 3395595Srrh case F_NOTREAD: 3405595Srrh dest = TOSTDOUT; 3415595Srrh fprintf(stdout, terse 3425595Srrh ? "\"%s\" unreadable\n" 3435595Srrh : "File \"%s\" is unreadable\n", 3445595Srrh name); 3455595Srrh break; 3465595Srrh case F_NOTWRITE: 3475595Srrh dest = TOSTDOUT; 3485595Srrh fprintf(stdout, terse 3495595Srrh ? "\"%s\" unwritable\n" 3505595Srrh : "File \"%s\" is unwritable\n", 3515595Srrh name); 3525595Srrh break; 3535595Srrh case F_NOTEXIST: 3545595Srrh dest = TOSTDOUT; 3555595Srrh fprintf(stdout, terse 3565595Srrh ? "\"%s\" not found\n" 3575595Srrh : "Can't find file \"%s\" to insert error messages into.\n", 3585595Srrh name); 3595595Srrh break; 3605595Srrh default: 3615595Srrh dest = edit(name) ? TOSTDOUT : TOTHEFILE; 3625595Srrh break; 3635595Srrh } 3645595Srrh return(dest); 3655595Srrh } 3665595Srrh 3675595Srrh diverterrors(name, dest, files, ix, previewed, nterrors) 3685595Srrh char *name; 3695595Srrh int dest; 3705595Srrh Eptr **files; 3715595Srrh int ix; 3725595Srrh boolean previewed; 3735595Srrh int nterrors; 3745595Srrh { 3755595Srrh int nerrors; 3765595Srrh reg Eptr *erpp; 3775595Srrh reg Eptr errorp; 3785595Srrh 3795595Srrh nerrors = files[ix+1] - files[ix]; 3805595Srrh 3815595Srrh if ( (nerrors != nterrors) 3825595Srrh && (!previewed) ){ 3835595Srrh fprintf(stdout, terse 3845595Srrh ? "Uninserted errors\n" 3855595Srrh : ">>Uninserted errors for file \"%s\" follow.\n", 3865595Srrh name); 3875595Srrh } 3885595Srrh 3895595Srrh EITERATE(erpp, files, ix){ 3905595Srrh errorp = *erpp; 3915595Srrh if (errorp->error_e_class != C_TRUE){ 3925595Srrh if (previewed || touchstatus == Q_NO) 3935595Srrh continue; 3945595Srrh errorprint(stdout, errorp, TRUE); 3955595Srrh continue; 3965595Srrh } 3975595Srrh switch (dest){ 3985595Srrh case TOSTDOUT: 3995595Srrh if (previewed || touchstatus == Q_NO) 4005595Srrh continue; 4015595Srrh errorprint(stdout,errorp, TRUE); 4025595Srrh break; 4035595Srrh case TOTHEFILE: 4045595Srrh insert(errorp->error_line); 4055595Srrh text(errorp, FALSE); 4065595Srrh break; 4075595Srrh } 4085595Srrh } 4095595Srrh } 4105595Srrh 4115595Srrh int oktotouch(filename) 4121460Sroot char *filename; 4131460Sroot { 4141460Sroot extern char *suffixlist; 4155595Srrh reg char *src; 4165595Srrh reg char *pat; 4171460Sroot char *osrc; 4181460Sroot 4191460Sroot pat = suffixlist; 4201460Sroot if (pat == 0) 4211460Sroot return(0); 4221460Sroot if (*pat == '*') 4231460Sroot return(1); 4241460Sroot while (*pat++ != '.') 4251460Sroot continue; 4261460Sroot --pat; /* point to the period */ 4271460Sroot 4281460Sroot for (src = &filename[strlen(filename)], --src; 4291460Sroot (src > filename) && (*src != '.'); --src) 4301460Sroot continue; 4311460Sroot if (*src != '.') 4321460Sroot return(0); 4331460Sroot 4341460Sroot for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){ 4351460Sroot for (; *src /* not at end of the source */ 4361460Sroot && *pat /* not off end of pattern */ 4371460Sroot && *pat != '.' /* not off end of sub pattern */ 4381460Sroot && *pat != '*' /* not wild card */ 4391460Sroot && *src == *pat; /* and equal... */ 4401460Sroot src++, pat++) 4411460Sroot continue; 4421460Sroot if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*')) 4431460Sroot return(1); 4441460Sroot if (*src != 0 && *pat == '*') 4451460Sroot return(1); 4461460Sroot while (*pat && *pat != '.') 4471460Sroot pat++; 4481460Sroot if (! *pat) 4491460Sroot return(0); 4501460Sroot } 4511460Sroot return(0); 4521460Sroot } 4535595Srrh /* 4545595Srrh * Construct an execv argument 4555595Srrh * We need 1 argument for the editor's name 4565595Srrh * We need 1 argument for the initial search string 4575595Srrh * We need n_pissed_on arguments for the file names 4585595Srrh * We need 1 argument that is a null for execv. 4595595Srrh * The caller fills in the editor's name. 4605595Srrh * We fill in the initial search string. 4615595Srrh * We fill in the arguments, and the null. 4625595Srrh */ 4635595Srrh execvarg(n_pissed_on, r_argc, r_argv) 4645595Srrh int n_pissed_on; 4655595Srrh int *r_argc; 4665595Srrh char ***r_argv; 4675595Srrh { 4685595Srrh Eptr p; 4695595Srrh char *sep; 4705595Srrh int fi; 4711460Sroot 4725595Srrh (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *)); 4735595Srrh (*r_argc) = n_pissed_on + 2; 4745595Srrh (*r_argv)[1] = "+1;/###/"; 4755595Srrh n_pissed_on = 2; 4765595Srrh if (!terse){ 4775595Srrh fprintf(stdout, "You touched file(s):"); 4785595Srrh sep = " "; 4795595Srrh } 4805595Srrh FILEITERATE(fi, 1){ 4815595Srrh if (!touchedfiles[fi]) 4825595Srrh continue; 4835595Srrh p = *(files[fi]); 4845595Srrh if (!terse){ 4855595Srrh fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]); 4865595Srrh sep = ", "; 4875595Srrh } 4885595Srrh (*r_argv)[n_pissed_on++] = p->error_text[0]; 4895595Srrh } 4905595Srrh if (!terse) 4915595Srrh fprintf(stdout, "\n"); 4925595Srrh (*r_argv)[n_pissed_on] = 0; 4935595Srrh } 4945595Srrh 4951460Sroot FILE *o_touchedfile; /* the old file */ 4961460Sroot FILE *n_touchedfile; /* the new file */ 4971460Sroot char *o_name; 4986612Srrh char n_name[64]; 499*37791Sbostic char *canon_name = _PATH_TMP; 5001460Sroot int o_lineno; 5011460Sroot int n_lineno; 5021460Sroot boolean tempfileopen = FALSE; 5031460Sroot /* 5041460Sroot * open the file; guaranteed to be both readable and writable 5051460Sroot * Well, if it isn't, then return TRUE if something failed 5061460Sroot */ 5071460Sroot boolean edit(name) 5081460Sroot char *name; 5091460Sroot { 5101460Sroot o_name = name; 5111460Sroot if ( (o_touchedfile = fopen(name, "r")) == NULL){ 5121460Sroot fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n", 5131460Sroot processname, name); 5141460Sroot return(TRUE); 5151460Sroot } 5165595Srrh (void)strcpy(n_name, canon_name); 5175595Srrh (void)mktemp(n_name); 5181460Sroot if ( (n_touchedfile = fopen(n_name, "w")) == NULL){ 5191460Sroot fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n", 5201460Sroot processname, name); 5211460Sroot return(TRUE); 5221460Sroot } 5231460Sroot tempfileopen = TRUE; 5241460Sroot n_lineno = 0; 5251460Sroot o_lineno = 0; 5261460Sroot return(FALSE); 5271460Sroot } 5281460Sroot /* 5291460Sroot * Position to the line (before, after) the line given by place 5301460Sroot */ 5315595Srrh char edbuf[BUFSIZ]; 5321460Sroot insert(place) 5331460Sroot int place; 5341460Sroot { 5351460Sroot --place; /* always insert messages before the offending line*/ 5361460Sroot for(; o_lineno < place; o_lineno++, n_lineno++){ 5375595Srrh if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL) 5381460Sroot return; 5395595Srrh fputs(edbuf, n_touchedfile); 5401460Sroot } 5411460Sroot } 5421460Sroot 5435595Srrh text(p, use_all) 5445595Srrh reg Eptr p; 5455595Srrh boolean use_all; 5461460Sroot { 5471460Sroot int offset = use_all ? 0 : 2; 5485595Srrh 5495595Srrh fputs(lang_table[p->error_language].lang_incomment, n_touchedfile); 5501460Sroot fprintf(n_touchedfile, "%d [%s] ", 5515595Srrh p->error_line, 5525595Srrh lang_table[p->error_language].lang_name); 5535595Srrh wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset); 5545595Srrh fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile); 5551460Sroot n_lineno++; 5561460Sroot } 5571460Sroot 5586612Srrh /* 5596612Srrh * write the touched file to its temporary copy, 5606612Srrh * then bring the temporary in over the local file 5616612Srrh */ 5626612Srrh writetouched(overwrite) 5636612Srrh int overwrite; 5641460Sroot { 5656612Srrh reg int nread; 5666612Srrh reg FILE *localfile; 5676612Srrh reg FILE *tmpfile; 5686612Srrh int botch; 5699309Srrh int oktorm; 5705595Srrh 5719309Srrh botch = 0; 5729309Srrh oktorm = 1; 5735595Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){ 5749309Srrh if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){ 5759309Srrh /* 5769309Srrh * Catastrophe in temporary area: file system full? 5779309Srrh */ 5789309Srrh botch = 1; 5799309Srrh fprintf(stderr, 5809309Srrh "%s: write failure: No errors inserted in \"%s\"\n", 5819309Srrh processname, o_name); 5829309Srrh } 5831460Sroot } 5841460Sroot fclose(n_touchedfile); 5851460Sroot fclose(o_touchedfile); 5866612Srrh /* 5876612Srrh * Now, copy the temp file back over the original 5886612Srrh * file, thus preserving links, etc 5896612Srrh */ 5909309Srrh if (botch == 0 && overwrite){ 5916612Srrh botch = 0; 5926612Srrh localfile = NULL; 5936612Srrh tmpfile = NULL; 5946612Srrh if ((localfile = fopen(o_name, "w")) == NULL){ 5956612Srrh fprintf(stderr, 5966612Srrh "%s: Can't open file \"%s\" to overwrite.\n", 5976612Srrh processname, o_name); 5986612Srrh botch++; 5996612Srrh } 6006612Srrh if ((tmpfile = fopen(n_name, "r")) == NULL){ 6016612Srrh fprintf(stderr, "%s: Can't open file \"%s\" to read.\n", 6026612Srrh processname, n_name); 6036612Srrh botch++; 6046612Srrh } 6059309Srrh if (!botch) 6069309Srrh oktorm = mustoverwrite(localfile, tmpfile); 6076612Srrh if (localfile != NULL) 6086612Srrh fclose(localfile); 6096612Srrh if (tmpfile != NULL) 6106612Srrh fclose(tmpfile); 6116612Srrh } 6129309Srrh if (oktorm == 0){ 61335266Sbostic fprintf(stderr, "%s: Catastrophe: A copy of \"%s\": was saved in \"%s\"\n", 6149309Srrh processname, o_name, n_name); 6159309Srrh exit(1); 6169309Srrh } 6176612Srrh /* 6186612Srrh * Kiss the temp file good bye 6196612Srrh */ 6201460Sroot unlink(n_name); 6211460Sroot tempfileopen = FALSE; 6226612Srrh return(TRUE); 6231460Sroot } 6249309Srrh /* 6259309Srrh * return 1 if the tmpfile can be removed after writing it out 6269309Srrh */ 6279309Srrh int mustoverwrite(preciousfile, tmpfile) 6289309Srrh FILE *preciousfile; 6299309Srrh FILE *tmpfile; 6309309Srrh { 6319309Srrh int nread; 6325595Srrh 6339309Srrh while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){ 6349309Srrh if (mustwrite(edbuf, nread, preciousfile) == 0) 6359309Srrh return(0); 6369309Srrh } 6379309Srrh return(1); 6389309Srrh } 6399309Srrh /* 6409309Srrh * return 0 on catastrophe 6419309Srrh */ 6429309Srrh mustwrite(base, n, preciousfile) 6439309Srrh char *base; 6449309Srrh int n; 6459309Srrh FILE *preciousfile; 6469309Srrh { 6479309Srrh int nwrote; 6489309Srrh 6499309Srrh if (n <= 0) 6509309Srrh return(1); 6519309Srrh nwrote = fwrite(base, 1, n, preciousfile); 6529309Srrh if (nwrote == n) 6539309Srrh return(1); 6549309Srrh perror(processname); 6559309Srrh switch(inquire(terse 6569309Srrh ? "Botch overwriting: retry? " 6579309Srrh : "Botch overwriting the source file: retry? ")){ 6589309Srrh case Q_YES: 6599309Srrh case Q_yes: 6609309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6619309Srrh return(1); 6629309Srrh case Q_NO: 6639309Srrh case Q_no: 6649309Srrh switch(inquire("Are you sure? ")){ 6659309Srrh case Q_YES: 6669309Srrh case Q_yes: 6679309Srrh return(0); 6689309Srrh case Q_NO: 6699309Srrh case Q_no: 6709309Srrh mustwrite(base + nwrote, n - nwrote, preciousfile); 6719309Srrh return(1); 6729309Srrh } 67316564Sralph default: 67416564Sralph return(0); 6759309Srrh } 6769309Srrh } 6779309Srrh 6781460Sroot onintr() 6791460Sroot { 6805595Srrh switch(inquire(terse 6815595Srrh ? "\nContinue? " 6825595Srrh : "\nInterrupt: Do you want to continue? ")){ 6835595Srrh case Q_YES: 6845595Srrh case Q_yes: 6851460Sroot signal(SIGINT, onintr); 6861460Sroot return; 6875595Srrh default: 6886612Srrh if (tempfileopen){ 6896612Srrh /* 6906612Srrh * Don't overwrite the original file! 6916612Srrh */ 6926612Srrh writetouched(0); 6936612Srrh } 6945595Srrh exit(1); 6951460Sroot } 6965595Srrh /*NOTREACHED*/ 6971460Sroot } 6985595Srrh 6991460Sroot errorprint(place, errorp, print_all) 7001460Sroot FILE *place; 7015595Srrh Eptr errorp; 7021460Sroot boolean print_all; 7031460Sroot { 7041460Sroot int offset = print_all ? 0 : 2; 7051460Sroot 7061460Sroot if (errorp->error_e_class == C_IGNORE) 7071460Sroot return; 7081460Sroot fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name); 7091460Sroot wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset); 7101460Sroot putc('\n', place); 7111460Sroot } 7121460Sroot 7135595Srrh int inquire(fmt, a1, a2) 7141460Sroot char *fmt; 7151460Sroot /*VARARGS1*/ 7161460Sroot { 7171460Sroot char buffer[128]; 71816564Sralph 71916564Sralph if (queryfile == NULL) 72016564Sralph return(0); 7211460Sroot for(;;){ 7221460Sroot do{ 7231460Sroot fflush(stdout); 7241460Sroot fprintf(stderr, fmt, a1, a2); 7251460Sroot fflush(stderr); 7261460Sroot } while (fgets(buffer, 127, queryfile) == NULL); 7275595Srrh switch(buffer[0]){ 7285595Srrh case 'Y': return(Q_YES); 7295595Srrh case 'y': return(Q_yes); 7305595Srrh case 'N': return(Q_NO); 7315595Srrh case 'n': return(Q_no); 7325595Srrh default: fprintf(stderr, "Yes or No only!\n"); 7335595Srrh } 7341460Sroot } 7351460Sroot } 7361460Sroot 7375595Srrh int probethisfile(name) 7385595Srrh char *name; 7391460Sroot { 7401460Sroot struct stat statbuf; 7415595Srrh if (stat(name, &statbuf) < 0) 7425595Srrh return(F_NOTEXIST); 7435595Srrh if((statbuf.st_mode & S_IREAD) == 0) 7445595Srrh return(F_NOTREAD); 7455595Srrh if((statbuf.st_mode & S_IWRITE) == 0) 7465595Srrh return(F_NOTWRITE); 7475595Srrh return(F_TOUCHIT); 7481460Sroot } 749