added "more" command
[unix-history] / usr / src / usr.bin / error / touch.c
index aae3b66..2d816ef 100644 (file)
@@ -1,4 +1,13 @@
-static char *sccsid = "@(#)touch.c     1.1 (Berkeley) %G%";
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)touch.c    5.1 (Berkeley) %G%";
+#endif not lint
+
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/types.h>
@@ -6,69 +15,88 @@ static       char *sccsid = "@(#)touch.c     1.1 (Berkeley) %G%";
 #include <signal.h>
 #include "error.h"
 
 #include <signal.h>
 #include "error.h"
 
+/*
+ *     Iterate through errors
+ */
+#define EITERATE(p, fv, i)     for (p = fv[i]; p < fv[i+1]; p++)
+#define        ECITERATE(ei, p, lb)    for (ei = lb; p = errors[ei],ei < nerrors; ei++)
+
+#define        FILEITERATE(fi, lb)     for (fi = lb; fi <= nfiles; fi++)
+int    touchstatus = Q_YES;
+
 findfiles(nerrors, errors, r_nfiles, r_files)
 findfiles(nerrors, errors, r_nfiles, r_files)
-       int     nerrors;
-       struct  error_desc      **errors;
-       int     *r_nfiles;
-       struct  error_desc      ****r_files;
+               int     nerrors;
+       Eptr    *errors;
+               int     *r_nfiles;
+       Eptr    ***r_files;
 {
 {
-                       int     nfiles;
-       struct  error_desc      ***files;
+               int     nfiles;
+       Eptr    **files;
 
 
-                       char    *currentfilename;
-       register        int     errorindex;
-                       int     fileindex;
-       register        struct  error_desc      *errorp;
-       /*
-        *      First, go through and count all of the filenames
-        */
-       for (errorp = errors[errorindex = 0],nfiles = 0, currentfilename = "\1";
-            errorindex < nerrors;
-            errorp = errors[++errorindex]){
-               if (SORTABLE(errorp->error_e_class)){
-                       if (strcmp(errorp->error_text[0],currentfilename) != 0){
-                               nfiles++;
-                               currentfilename = errorp->error_text[0];
-                       }
-               }
-       }
-       files = (struct error_desc ***)Calloc(nfiles + 3,
-               sizeof (struct error_desc**));
+               char    *name;
+       reg     int     ei;
+               int     fi;
+       reg     Eptr    errorp;
+
+       nfiles = countfiles(errors);
+
+       files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*));
        touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean));
        /*
        touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean));
        /*
-        *      Now, go through and partition off the error messages
+        *      Now, partition off the error messages
         *      into those that are synchronization, discarded or
         *      not specific to any file, and those that were
         *      nulled or true errors.
         */
        files[0] = &errors[0];
         *      into those that are synchronization, discarded or
         *      not specific to any file, and those that were
         *      nulled or true errors.
         */
        files[0] = &errors[0];
-       for (errorp = errors[errorindex = 0], fileindex = 0;
-            (errorindex < nerrors) &&
-               (NOTSORTABLE(errorp->error_e_class));
-            errorp = errors[++errorindex]){
-               continue;
+       ECITERATE(ei, errorp, 0){
+               if ( ! (NOTSORTABLE(errorp->error_e_class)))
+                       break;
        }
        /*
        }
        /*
-        *      Now, go through and partition off all error messages
+        *      Now, and partition off all error messages
         *      for a given file.
         */
         *      for a given file.
         */
-       files[1] = &errors[errorindex];
+       files[1] = &errors[ei];
        touchedfiles[0] = touchedfiles[1] = FALSE;
        touchedfiles[0] = touchedfiles[1] = FALSE;
-       for (errorp = errors[errorindex], currentfilename = "\1", fileindex = 1;
-            errorindex < nerrors; errorp = errors[++errorindex]){
-               if ( (errorp->error_e_class == C_NULLED) || (errorp->error_e_class == C_TRUE) ){
-                       if (strcmp(errorp->error_text[0],currentfilename) != 0){
-                               currentfilename = errorp->error_text[0];
-                               touchedfiles[fileindex] = FALSE;
-                               files[fileindex++] = &errors[errorindex];
+       name = "\1";
+       fi = 1;
+       ECITERATE(ei, errorp, ei){
+               if (   (errorp->error_e_class == C_NULLED)
+                   || (errorp->error_e_class == C_TRUE) ){
+                       if (strcmp(errorp->error_text[0], name) != 0){
+                               name = errorp->error_text[0];
+                               touchedfiles[fi] = FALSE;
+                               files[fi] = &errors[ei];
+                               fi++;
                        }
                }
        }
                        }
                }
        }
-       files[fileindex] = &errors[nerrors];
+       files[fi] = &errors[nerrors];
        *r_nfiles = nfiles;
        *r_files = files;
 }
 
        *r_nfiles = nfiles;
        *r_files = files;
 }
 
+int countfiles(errors)
+       Eptr    *errors;
+{
+       char    *name;
+       int     ei;
+       reg     Eptr    errorp;
+
+       int     nfiles;
+       nfiles = 0;
+       name = "\1";
+       ECITERATE(ei, errorp, 0){
+               if (SORTABLE(errorp->error_e_class)){
+                       if (strcmp(errorp->error_text[0],name) != 0){
+                               nfiles++;
+                               name = errorp->error_text[0];
+                       }
+               }
+       }
+       return(nfiles);
+}
 char   *class_table[] = {
        /*C_UNKNOWN     0       */      "Unknown",
        /*C_IGNORE      1       */      "ignore",
 char   *class_table[] = {
        /*C_UNKNOWN     0       */      "Unknown",
        /*C_IGNORE      1       */      "ignore",
@@ -85,44 +113,32 @@ int        class_count[C_LAST - C_FIRST] = {0};
 
 filenames(nfiles, files)
        int     nfiles;
 
 filenames(nfiles, files)
        int     nfiles;
-       struct  error_desc      ***files;
+       Eptr    **files;
 {
 {
-       register        int     fileindex;
-       register        struct  error_desc      *errorp;
-       register        struct  error_desc      **erpp;
-                       char    *sep = " ";
-       register        int     errortype;
-       extern          char    *class_table[];
-                       int     someerrors = 0;
+       reg     int     fi;
+               char    *sep = " ";
+       extern  char    *class_table[];
+               int     someerrors;
 
        /*
 
        /*
-        *      first, go through and simply dump out errors that
+        *      first, simply dump out errors that
         *      don't pertain to any file
         */
         *      don't pertain to any file
         */
-       if (files[1] - files[0] > 0){
-           for(errortype = C_UNKNOWN; NOTSORTABLE(errortype); errortype++){
-               if (class_count[errortype] > 0){
-                       if (errortype > C_SYNC)
-                               someerrors++;
-                       fprintf(stdout, "\n\t%d %s errors follow:\n",
-                               class_count[errortype], class_table[errortype]);
-                       for (errorp = *(erpp = files[0]);
-                            erpp < files[1];
-                            errorp = (*++erpp)){
-                               if (errorp->error_e_class == errortype)
-                                       errorprint(stdout, errorp, TRUE);
-                       }
-               }
-           }
-       }
+       someerrors = nopertain(files);
+
        if (nfiles){
                someerrors++;
        if (nfiles){
                someerrors++;
-               fprintf(stdout, "%d files contain errors:", nfiles);
-               for (fileindex = 1; fileindex <= nfiles; fileindex++){
-                       fprintf(stdout, "%s\"%s\" (%d)",
-                               sep, (*files[fileindex])->error_text[0],
-                               files[fileindex+1] - files[fileindex]);
-                       sep = ", ";
+               fprintf(stdout, terse
+                       ? "%d file%s"
+                       : "%d file%s contain%s errors",
+                       nfiles, plural(nfiles), verbform(nfiles));
+               if (!terse){
+                       FILEITERATE(fi, 1){
+                               fprintf(stdout, "%s\"%s\" (%d)",
+                                       sep, (*files[fi])->error_text[0],
+                                       files[fi+1] - files[fi]);
+                               sep = ", ";
+                       }
                }
                fprintf(stdout, "\n");
        }
                }
                fprintf(stdout, "\n");
        }
@@ -130,146 +146,262 @@ filenames(nfiles, files)
                fprintf(stdout, "No errors.\n");
 }
 
                fprintf(stdout, "No errors.\n");
 }
 
+/*
+ *     Dump out errors that don't pertain to any file
+ */
+int nopertain(files)
+       Eptr    **files;
+{
+       int     type;
+       int     someerrors = 0;
+       reg     Eptr    *erpp;
+       reg     Eptr    errorp;
+
+       if (files[1] - files[0] <= 0)
+               return(0);
+       for(type = C_UNKNOWN; NOTSORTABLE(type); type++){
+               if (class_count[type] <= 0)
+                       continue;
+               if (type > C_SYNC)
+                       someerrors++;
+               if (terse){
+                       fprintf(stdout, "\t%d %s errors NOT PRINTED\n",
+                               class_count[type], class_table[type]);
+               } else {
+                       fprintf(stdout, "\n\t%d %s errors follow\n",
+                               class_count[type], class_table[type]);
+                       EITERATE(erpp, files, 0){
+                               errorp = *erpp;
+                               if (errorp->error_e_class == type){
+                                       errorprint(stdout, errorp, TRUE);
+                               }
+                       }
+               }
+       }
+       return(someerrors);
+}
+
 extern boolean notouch;
 
 boolean touchfiles(nfiles, files, r_edargc, r_edargv)
        int     nfiles;
 extern boolean notouch;
 
 boolean touchfiles(nfiles, files, r_edargc, r_edargv)
        int     nfiles;
-       struct  error_desc      ***files;
+       Eptr    **files;
        int     *r_edargc;
        char    ***r_edargv;
 {
        int     *r_edargc;
        char    ***r_edargv;
 {
-                       char    *currentfilename;
-       register        struct  error_desc      *errorp;
-       register        int     fileindex;
-       register        struct  error_desc      **erpp;
-                       int             ntrueerrors;
-                       int             errordest;      /* where errors go*/
-                       char            *sep;
-                       boolean         scribbled;
-                       int             n_pissed_on;    /* how many files touched*/
-       for (fileindex = 1; fileindex <= nfiles; fileindex++){
-               fprintf(stdout, "\nFile \"%s\" has %d total error messages.\n",
-                       currentfilename = (*files[fileindex])->error_text[0],
-                       files[fileindex+1] - files[fileindex]);
+               char    *name;
+       reg     Eptr    errorp;
+       reg     int     fi;
+       reg     Eptr    *erpp;
+               int             ntrueerrors;
+               boolean         scribbled;
+               int             n_pissed_on;    /* # of file touched*/
+               int     spread;
+
+       FILEITERATE(fi, 1){
+               name = (*files[fi])->error_text[0];
+               spread = files[fi+1] - files[fi];
+               fprintf(stdout, terse
+                       ? "\"%s\" has %d error%s, "
+                       : "\nFile \"%s\" has %d error%s.\n"
+                       , name ,spread ,plural(spread));
                /*
                 *      First, iterate through all error messages in this file
                 *      to see how many of the error messages really will
                 *      get inserted into the file.
                 */
                /*
                 *      First, iterate through all error messages in this file
                 *      to see how many of the error messages really will
                 *      get inserted into the file.
                 */
-               for (erpp = files[fileindex], ntrueerrors = 0;
-                    erpp < files[fileindex+1];
-                    erpp++){
+               ntrueerrors = 0;
+               EITERATE(erpp, files, fi){
                        errorp = *erpp;
                        if (errorp->error_e_class == C_TRUE)
                                ntrueerrors++;
                }
                        errorp = *erpp;
                        if (errorp->error_e_class == C_TRUE)
                                ntrueerrors++;
                }
-               fprintf(stdout,"\t%d of these errors can be inserted into the file.\n",
+               fprintf(stdout, terse
+                 ? "insert %d\n"
+                 : "\t%d of these errors can be inserted into the file.\n",
                        ntrueerrors);
 
                        ntrueerrors);
 
-               /*
-                *      What does the operator want?
-                */
-               errordest = TOSTDOUT;
-               if (oktotouch(currentfilename) && (ntrueerrors > 0) ){
-                       if (query && inquire("Do you want to preview the errors first?")){
-                               for (erpp = files[fileindex];
-                                    erpp < files[fileindex + 1];
-                                    erpp++){
-                                       errorprint(stdout, *erpp, TRUE);
-                               }
-                               fprintf(stdout, "\n");
-                       }
-                       if (   !query
-                           || inquire("Do you want to touch file \"%s\"? ",
-                                       currentfilename)
-                       ){
-                               errordest = TOTHEFILE;
-                               if (!probethisfile(currentfilename)){
-                                       errordest = TOSTDOUT;
-                                       fprintf(stdout,
-                                        "Can't find file \"%s\" to insert error messages into.\n",
-                                               currentfilename);
-                               } else {
-                                       if (edit(currentfilename))
-                                               errordest = TOSTDOUT;
-                                       else
-                                               touchedfiles[fileindex] = TRUE;
-                               }
-                       }
-               }
-               /*
-                *      go through and print each error message,
-                *      diverting to the right place
-                */
-               if ( (files[fileindex+1] - files[fileindex]) != ntrueerrors)
-                       fprintf(stdout,
-                           ">>Uninserted error messages for file \"%s\" follow.\n",
-                           currentfilename);
-               for (erpp = files[fileindex];erpp < files[fileindex+1];erpp++){
-                       errorp = *erpp;
-                       if (errorp->error_e_class == C_TRUE){
-                               switch (errordest){
-                                 case TOSTDOUT:
-                                       errorprint(stdout, errorp, TRUE);
-                                         break;
-                                 case TOTHEFILE:
-                                       insert(errorp->error_line);
-                                       text(errorp, FALSE);
-                                       break;
-                               }       /* switch */
-                       } else {
-                               errorprint(stdout, errorp, TRUE);
-                       }
-               }       /* end of walking through all errors*/
-               if (errordest == TOTHEFILE){
-                       writetouched();
-               }
-       }       /* end of walking through all files*/
+               hackfile(name, files, fi, ntrueerrors);
+       }
        scribbled = FALSE;
        scribbled = FALSE;
-       for (n_pissed_on = 0, fileindex = 1; fileindex <= nfiles; fileindex++){
-               scribbled |= touchedfiles[fileindex];
+       n_pissed_on = 0;
+       FILEITERATE(fi, 1){
+               scribbled |= touchedfiles[fi];
                n_pissed_on++;
        }
        if (scribbled){
                /*
                 *      Construct an execv argument
                n_pissed_on++;
        }
        if (scribbled){
                /*
                 *      Construct an execv argument
-                *      We need 1 argument for the editor's name
-                *      We need 1 argument for the initial search string
-                *      We need n_pissed_on arguments for the file names
-                *      We need 1 argument that is a null for execv.
-                *      The caller fills in the editor's name.
-                *      We fill in the initial search string.
-                *      We fill in the arguments, and the null.
                 */
                 */
-               (*r_edargv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *));
-               (*r_edargc) =  n_pissed_on + 2;
-               (*r_edargv)[1] = "+/###/";
-               n_pissed_on = 2;
-               fprintf(stdout, "You touched file(s):");
-               sep = " ";
-               for (fileindex = 1; fileindex <= nfiles; fileindex++){
-                       if (!touchedfiles[fileindex])
-                               continue;
-                       errorp = *(files[fileindex]);
-                       fprintf(stdout,"%s\"%s\"", sep, errorp->error_text[0]);
-                       sep = ", ";
-                       (*r_edargv)[n_pissed_on++] = errorp->error_text[0];
-               }
-               fprintf(stdout, "\n");
-               (*r_edargv)[n_pissed_on] = 0;
+               execvarg(n_pissed_on, r_edargc, r_edargv);
                return(TRUE);
        } else {
                return(TRUE);
        } else {
-               fprintf(stdout, "You didn't touch any files.\n");
+               if (!terse)
+                       fprintf(stdout, "You didn't touch any files.\n");
+               return(FALSE);
+       }
+}
+
+hackfile(name, files, ix, nerrors)
+       char    *name;
+       Eptr    **files;
+       int     ix;
+{
+       boolean previewed;
+       int     errordest;      /* where errors go*/
+
+       if (!oktotouch(name)) {
+               previewed = FALSE;
+               errordest = TOSTDOUT;
+       } else {
+               previewed = preview(name, nerrors, files, ix);
+               errordest = settotouch(name);
+       }
+
+       if (errordest != TOSTDOUT)
+               touchedfiles[ix] = TRUE;
+
+       if (previewed && (errordest == TOSTDOUT))
+               return;
+
+       diverterrors(name, errordest, files, ix, previewed, nerrors);
+
+       if (errordest == TOTHEFILE){
+               /*
+                *      overwrite the original file
+                */
+               writetouched(1);
+       }
+}
+
+boolean preview(name, nerrors, files, ix)
+       char    *name;
+       int     nerrors;
+       Eptr    **files;
+       int     ix;
+{
+       int     back;
+       reg     Eptr    *erpp;
+
+       if (nerrors <= 0)
                return(FALSE);
                return(FALSE);
+       back = FALSE;
+       if(query){
+               switch(inquire(terse
+                   ? "Preview? "
+                   : "Do you want to preview the errors first? ")){
+               case Q_YES:
+               case Q_yes:
+                       back = TRUE;
+                       EITERATE(erpp, files, ix){
+                               errorprint(stdout, *erpp, TRUE);
+                       }
+                       if (!terse)
+                               fprintf(stdout, "\n");
+               default:
+                       break;
+               }
        }
        }
+       return(back);
+}
+
+int settotouch(name)
+       char    *name;
+{
+       int     dest = TOSTDOUT;
+
+       if (query){
+               switch(touchstatus = inquire(terse
+                       ? "Touch? "
+                       : "Do you want to touch file \"%s\"? ",
+                       name)){
+               case Q_NO:
+               case Q_no:
+                       return(dest);
+               default:
+                       break;
+               }
+       }
+
+       switch(probethisfile(name)){
+       case F_NOTREAD:
+               dest = TOSTDOUT;
+               fprintf(stdout, terse
+                       ? "\"%s\" unreadable\n"
+                       : "File \"%s\" is unreadable\n",
+                       name);
+               break;
+       case F_NOTWRITE:
+               dest = TOSTDOUT;
+               fprintf(stdout, terse
+                       ? "\"%s\" unwritable\n"
+                       : "File \"%s\" is unwritable\n",
+                       name);
+               break;
+       case F_NOTEXIST:
+               dest = TOSTDOUT;
+               fprintf(stdout, terse
+                       ? "\"%s\" not found\n"
+                       : "Can't find file \"%s\" to insert error messages into.\n",
+                       name);
+               break;
+       default:
+               dest = edit(name) ? TOSTDOUT : TOTHEFILE;
+               break;
+       }
+       return(dest);
+}
+
+diverterrors(name, dest, files, ix, previewed, nterrors)
+       char    *name;
+       int     dest;
+       Eptr    **files;
+       int     ix;
+       boolean previewed;
+       int     nterrors;
+{
+       int     nerrors;
+       reg     Eptr    *erpp;
+       reg     Eptr    errorp;
 
 
-}      /* end of touchfiles*/
-int    oktotouch(filename)
+       nerrors = files[ix+1] - files[ix];
+
+       if (   (nerrors != nterrors)
+           && (!previewed) ){
+               fprintf(stdout, terse
+                       ? "Uninserted errors\n"
+                       : ">>Uninserted errors for file \"%s\" follow.\n",
+                       name);
+       }
+
+       EITERATE(erpp, files, ix){
+               errorp = *erpp;
+               if (errorp->error_e_class != C_TRUE){
+                       if (previewed || touchstatus == Q_NO)
+                               continue;
+                       errorprint(stdout, errorp, TRUE);
+                       continue;
+               }
+               switch (dest){
+               case TOSTDOUT:
+                       if (previewed || touchstatus == Q_NO)
+                               continue;
+                       errorprint(stdout,errorp, TRUE);
+                       break;
+               case TOTHEFILE:
+                       insert(errorp->error_line);
+                       text(errorp, FALSE);
+                       break;
+               }
+       }
+}
+
+int oktotouch(filename)
        char    *filename;
 {
        extern          char    *suffixlist;
        char    *filename;
 {
        extern          char    *suffixlist;
-       register        char    *src;
-       register        char    *pat;
+       reg     char    *src;
+       reg     char    *pat;
                        char    *osrc;
 
        pat = suffixlist;
                        char    *osrc;
 
        pat = suffixlist;
@@ -306,12 +438,53 @@ int       oktotouch(filename)
        }
        return(0);
 }
        }
        return(0);
 }
+/*
+ *     Construct an execv argument
+ *     We need 1 argument for the editor's name
+ *     We need 1 argument for the initial search string
+ *     We need n_pissed_on arguments for the file names
+ *     We need 1 argument that is a null for execv.
+ *     The caller fills in the editor's name.
+ *     We fill in the initial search string.
+ *     We fill in the arguments, and the null.
+ */
+execvarg(n_pissed_on, r_argc, r_argv)
+       int     n_pissed_on;
+       int     *r_argc;
+       char    ***r_argv;
+{
+       Eptr    p;
+       char    *sep;
+       int     fi;
+
+       (*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *));
+       (*r_argc) =  n_pissed_on + 2;
+       (*r_argv)[1] = "+1;/###/";
+       n_pissed_on = 2;
+       if (!terse){
+               fprintf(stdout, "You touched file(s):");
+               sep = " ";
+       }
+       FILEITERATE(fi, 1){
+               if (!touchedfiles[fi])
+                       continue;
+               p = *(files[fi]);
+               if (!terse){
+                       fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]);
+                       sep = ", ";
+               }
+               (*r_argv)[n_pissed_on++] = p->error_text[0];
+       }
+       if (!terse)
+               fprintf(stdout, "\n");
+       (*r_argv)[n_pissed_on] = 0;
+}
 
 FILE   *o_touchedfile; /* the old file */
 FILE   *n_touchedfile; /* the new file */
 char   *o_name;
 
 FILE   *o_touchedfile; /* the old file */
 FILE   *n_touchedfile; /* the new file */
 char   *o_name;
-char   n_name[32];
-char   *canon_name = "ErrorXXXXXX";
+char   n_name[64];
+char   *canon_name = "/tmp/ErrorXXXXXX";
 int    o_lineno;
 int    n_lineno;
 boolean        tempfileopen = FALSE;
 int    o_lineno;
 int    n_lineno;
 boolean        tempfileopen = FALSE;
@@ -328,8 +501,8 @@ boolean edit(name)
                        processname, name);
                return(TRUE);
        }
                        processname, name);
                return(TRUE);
        }
-       strcpy(n_name, canon_name);
-       mktemp(n_name);
+       (void)strcpy(n_name, canon_name);
+       (void)mktemp(n_name);
        if ( (n_touchedfile = fopen(n_name, "w")) == NULL){
                fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n",
                        processname, name);
        if ( (n_touchedfile = fopen(n_name, "w")) == NULL){
                fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n",
                        processname, name);
@@ -343,59 +516,177 @@ boolean edit(name)
 /*
  *     Position to the line (before, after) the line given by place
  */
 /*
  *     Position to the line (before, after) the line given by place
  */
-char   edbuffer[BUFSIZ];
+char   edbuf[BUFSIZ];
 insert(place)
        int     place;
 {
        --place;        /* always insert messages before the offending line*/
        for(; o_lineno < place; o_lineno++, n_lineno++){
 insert(place)
        int     place;
 {
        --place;        /* always insert messages before the offending line*/
        for(; o_lineno < place; o_lineno++, n_lineno++){
-               if(fgets(edbuffer, BUFSIZ, o_touchedfile) == NULL)
+               if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL)
                        return;
                        return;
-               fputs(edbuffer, n_touchedfile);
+               fputs(edbuf, n_touchedfile);
        }
 }
 
        }
 }
 
-text(errorp, use_all)
-       register        struct  error_desc      *errorp;
-       boolean use_all;
+text(p, use_all)
+       reg     Eptr    p;
+               boolean use_all;
 {
        int     offset = use_all ? 0 : 2;
 {
        int     offset = use_all ? 0 : 2;
-       fputs(lang_table[errorp->error_language].lang_incomment, n_touchedfile);
+
+       fputs(lang_table[p->error_language].lang_incomment, n_touchedfile);
        fprintf(n_touchedfile, "%d [%s] ",
        fprintf(n_touchedfile, "%d [%s] ",
-               errorp->error_line,
-               lang_table[errorp->error_language].lang_name);
-       wordvprint(n_touchedfile,
-               errorp->error_lgtext-offset, errorp->error_text+offset);
-       fputs(lang_table[errorp->error_language].lang_outcomment,n_touchedfile);
+               p->error_line,
+               lang_table[p->error_language].lang_name);
+       wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset);
+       fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile);
        n_lineno++;
 }
 
        n_lineno++;
 }
 
-writetouched()
+/*
+ *     write the touched file to its temporary copy,
+ *     then bring the temporary in over the local file
+ */
+writetouched(overwrite)
+       int     overwrite;
 {
 {
-       int     bytes_read;
-       for(; (bytes_read = fread(edbuffer, 1, sizeof(edbuffer), o_touchedfile))!= NULL; ){
-               fwrite(edbuffer, 1, bytes_read, n_touchedfile);
+       reg     int     nread;
+       reg     FILE    *localfile;
+       reg     FILE    *tmpfile;
+               int     botch;
+               int     oktorm;
+
+       botch = 0;
+       oktorm = 1;
+       while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != NULL){
+               if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){
+                       /*
+                        *      Catastrophe in temporary area: file system full?
+                        */
+                       botch = 1;
+                       fprintf(stderr,
+                         "%s: write failure: No errors inserted in \"%s\"\n",
+                         processname, o_name);
+               }
        }
        fclose(n_touchedfile);
        fclose(o_touchedfile);
        }
        fclose(n_touchedfile);
        fclose(o_touchedfile);
-       unlink(o_name);
-       link(n_name, o_name);   
+       /*
+        *      Now, copy the temp file back over the original
+        *      file, thus preserving links, etc
+        */
+       if (botch == 0 && overwrite){
+               botch = 0;
+               localfile = NULL;
+               tmpfile = NULL;
+               if ((localfile = fopen(o_name, "w")) == NULL){
+                       fprintf(stderr,
+                               "%s: Can't open file \"%s\" to overwrite.\n",
+                               processname, o_name);
+                       botch++;
+               }
+               if ((tmpfile = fopen(n_name, "r")) == NULL){
+                       fprintf(stderr, "%s: Can't open file \"%s\" to read.\n",
+                               processname, n_name);
+                       botch++;
+               }
+               if (!botch)
+                       oktorm = mustoverwrite(localfile, tmpfile);
+               if (localfile != NULL)
+                       fclose(localfile);
+               if (tmpfile != NULL)
+                       fclose(tmpfile);
+       }
+       if (oktorm == 0){
+               fprintf(stderr, "%s: Catastrophe: A copy of \"%s\: was saved in \"%s\"\n",
+                       processname, o_name, n_name);
+               exit(1);
+       }
+       /*
+        *      Kiss the temp file good bye
+        */
        unlink(n_name);
        tempfileopen = FALSE;
        unlink(n_name);
        tempfileopen = FALSE;
+       return(TRUE);
 }
 }
+/*
+ *     return 1 if the tmpfile can be removed after writing it out
+ */
+int mustoverwrite(preciousfile, tmpfile)
+       FILE    *preciousfile;
+       FILE    *tmpfile;
+{
+       int     nread;
+
+       while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != NULL){
+               if (mustwrite(edbuf, nread, preciousfile) == 0)
+                       return(0);
+       }
+       return(1);
+}
+/*
+ *     return 0 on catastrophe
+ */
+mustwrite(base, n, preciousfile)
+       char    *base;
+       int     n;
+       FILE    *preciousfile;
+{
+       int     nwrote;
+
+       if (n <= 0)
+               return(1);
+       nwrote = fwrite(base, 1, n, preciousfile);
+       if (nwrote == n)
+               return(1);
+       perror(processname);
+       switch(inquire(terse
+           ? "Botch overwriting: retry? "
+           : "Botch overwriting the source file: retry? ")){
+       case Q_YES:
+       case Q_yes:
+               mustwrite(base + nwrote, n - nwrote, preciousfile);
+               return(1);
+       case Q_NO:
+       case Q_no:
+               switch(inquire("Are you sure? ")){
+               case Q_YES:
+               case Q_yes:
+                       return(0);
+               case Q_NO:
+               case Q_no:
+                       mustwrite(base + nwrote, n - nwrote, preciousfile);
+                       return(1);
+               }
+       default:
+               return(0);
+       }
+}
+
 onintr()
 {
 onintr()
 {
-       if (inquire("\nInterrupt: Do you want to continue?")){
+       switch(inquire(terse
+           ? "\nContinue? "
+           : "\nInterrupt: Do you want to continue? ")){
+       case Q_YES:
+       case Q_yes:
                signal(SIGINT, onintr);
                return;
                signal(SIGINT, onintr);
                return;
+       default:
+               if (tempfileopen){
+                       /*
+                        *      Don't overwrite the original file!
+                        */
+                       writetouched(0);
+               }
+               exit(1);
        }
        }
-       if (tempfileopen)
-               writetouched();
-       exit(1);
+       /*NOTREACHED*/
 }
 }
+
 errorprint(place, errorp, print_all)
        FILE    *place;
 errorprint(place, errorp, print_all)
        FILE    *place;
-       struct  error_desc      *errorp;
+       Eptr    errorp;
        boolean print_all;
 {
        int     offset = print_all ? 0 : 2;
        boolean print_all;
 {
        int     offset = print_all ? 0 : 2;
@@ -407,34 +698,39 @@ errorprint(place, errorp, print_all)
        putc('\n', place);
 }
 
        putc('\n', place);
 }
 
-boolean inquire(fmt, a1, a2)
+int inquire(fmt, a1, a2)
        char    *fmt;
        /*VARARGS1*/
 {
        char    buffer[128];
        char    *fmt;
        /*VARARGS1*/
 {
        char    buffer[128];
-       char    ch;
+
+       if (queryfile == NULL)
+               return(0);
        for(;;){
                do{
                        fflush(stdout);
                        fprintf(stderr, fmt, a1, a2);
                        fflush(stderr);
                } while (fgets(buffer, 127, queryfile) == NULL);
        for(;;){
                do{
                        fflush(stdout);
                        fprintf(stderr, fmt, a1, a2);
                        fflush(stderr);
                } while (fgets(buffer, 127, queryfile) == NULL);
-               ch = buffer[0];
-               if (ch == 'Y' || ch == 'y')
-                       return(TRUE);
-               if (ch == 'N' || ch == 'n')
-                       return(FALSE);
-               fprintf(stderr, "Yes or No only!\n");
+               switch(buffer[0]){
+               case 'Y':       return(Q_YES);
+               case 'y':       return(Q_yes);
+               case 'N':       return(Q_NO);
+               case 'n':       return(Q_no);
+               default:        fprintf(stderr, "Yes or No only!\n");
+               }
        }
 }
 
        }
 }
 
-boolean probethisfile(currentfilename)
-       char    *currentfilename;
+int probethisfile(name)
+       char    *name;
 {
        struct stat statbuf;
 {
        struct stat statbuf;
-       if (stat(currentfilename, &statbuf) != 0)
-               return(FALSE);
-       if ( (statbuf.st_mode&S_IREAD) && (statbuf.st_mode&S_IWRITE))
-               return(TRUE);
-       return(FALSE);
+       if (stat(name, &statbuf) < 0)
+               return(F_NOTEXIST);
+       if((statbuf.st_mode & S_IREAD) == 0)
+               return(F_NOTREAD);
+       if((statbuf.st_mode & S_IWRITE) == 0)
+               return(F_NOTWRITE);
+       return(F_TOUCHIT);
 }
 }