The patches included below incorporate the following changes into the Wall patch program: - fixed a minor bug in generation of reject filenames under VMS which caused an illegal name to be generated when a version was explicitly specified for the input file. - changed fetchname() in util.c so that nla0: is recognized as the null device as well as /dev/null - added -a command line switch, which causes the run to be aborted, if errors are encountered while applying patch (see file patch.doc for details). - changed exit patch to return a warning status on VMS if an error is encountered while applying a patch, so calling procedure will be aware of potential problems - added a line to version printout noting my responsibility for changes, so any grief about them won't be directed to lwall or whoever's maintaining patch these days. If I can find the maintainers, I'll try to get a formal patchlevel assigned to these changes, and get rid of this message. All of these changes were made by Charles Bailey (bailey@genetics.upenn.edu). Any comments or suggestions you may have about these changes is welcome; constructive flames only, please. Rev. 08-Mar-1993 *** common_orig.h --- common.h ************** *** 1,6 /* $Header: common.h,v 2.0 86/09/17 15:36:39 lwall Exp $ * * $Log: common.h,v $ * Revision 2.0 86/09/17 15:36:39 lwall * Baseline for netwide release. * --- 1,10 ----- /* $Header: common.h,v 2.0 86/09/17 15:36:39 lwall Exp $ * * $Log: common.h,v $ + * 02-Mar-1993 Charles Bailey bailey@genetics.upenn.edu + * added abort_on_error global flag to handle -a switch + * added #define FAILURE so -a failures dtrt for VMS and maybe Unix + * * Revision 2.0 86/09/17 15:36:39 lwall * Baseline for netwide release. * ************** *** 48,53 #define TRUE (1) #define FALSE (0) #define MAXHUNKSIZE 100000 /* is this enough lines? */ #define INITHUNKMAX 125 /* initial dynamic allocation size */ #define MAXLINELEN 1024 --- 52,68 ----- #define TRUE (1) #define FALSE (0) + #ifdef VMS + /* this is SS$_Abort, but with severity --> W, so it doesn't halt any scripts + which depend on previous versions of patch exiting normally no matter what + happened during the application of patches */ + #define FAILURE 40 + #else + /* this is just a 'safe' (I hope) nonzero status; feel free to modify it to + suit your system */ + #define FAILURE -1 + #endif + #define MAXHUNKSIZE 100000 /* is this enough lines? */ #define INITHUNKMAX 125 /* initial dynamic allocation size */ #define MAXLINELEN 1024 ************** *** 131,136 EXT bool reverse INIT(FALSE); EXT bool noreverse INIT(FALSE); EXT bool skip_rest_of_patch INIT(FALSE); EXT int strippath INIT(957); EXT bool canonicalize INIT(FALSE); --- 146,152 ----- EXT bool reverse INIT(FALSE); EXT bool noreverse INIT(FALSE); EXT bool skip_rest_of_patch INIT(FALSE); + EXT bool abort_on_error INIT(FALSE); EXT int strippath INIT(957); EXT bool canonicalize INIT(FALSE); *** patch_orig.c --- patch.c ************** *** 8,13 * This program may be copied as long as you don't try to make any * money off of it, or pretend that you wrote it. * * $Log: patch.c,v $ * Revision 2.0.1.4 87/02/16 14:00:04 lwall * Short replacement caused spurious "Out of sync" message. --- 8,19 ----- * This program may be copied as long as you don't try to make any * money off of it, or pretend that you wrote it. * + * 93/03/02 Charles Bailey bailey@genetics.upenn.edu + * Fixed VMS-specific code for generation of rejfile name to handle + * output file names with explicit versions. + * Added -a switch to junk all changes if an error is encountered in applying + * any part of a patch + * * $Log: patch.c,v $ * Revision 2.0.1.4 87/02/16 14:00:04 lwall * Short replacement caused spurious "Out of sync" message. ************** *** 115,120 LINENUM newwhere; LINENUM fuzz; LINENUM mymaxfuzz; int hunk = 0; int failed = 0; int i; --- 121,127 ----- LINENUM newwhere; LINENUM fuzz; LINENUM mymaxfuzz; + int ever_failed = 0; int hunk = 0; int failed = 0; int i; ************** *** 118,123 int hunk = 0; int failed = 0; int i; setbuf(stderr, serrbuf); for (i = 0; i0) && (rejname[lastdot] != '.') ! && (rejname[lastdot] != ';')); ! lastdot--); ! if (lastdot==0) Strcat(rejname, ".rej"); ! else { ! if (lastdot>firstdot) rejname[lastdot] = '_'; ! Strcat(rejname, "_rej"); ! } #else Strcat(rejname, ".rej"); #endif ************** *** 287,294 #endif } if (skip_rest_of_patch) { ! say4("%d out of %d hunks ignored--saving rejects to %s\n", ! failed, hunk, rejname); } else { say4("%d out of %d hunks failed--saving rejects to %s\n", --- 311,322 ----- #endif } if (skip_rest_of_patch) { ! if (abort_on_error & 2) { ! say3("%d out of %d hunks ignored--bailing out\n", failed, hunk); ! my_exit(FAILURE); ! } ! else say4("%d out of %d hunks ignored--saving rejects to %s\n", ! failed, hunk, rejname); } else { if (abort_on_error & 1) { ************** *** 291,298 failed, hunk, rejname); } else { ! say4("%d out of %d hunks failed--saving rejects to %s\n", ! failed, hunk, rejname); } if (move_file(TMPREJNAME, rejname) < 0) trejkeep = TRUE; --- 319,330 ----- failed, hunk, rejname); } else { ! if (abort_on_error & 1) { ! say3("%d out of %d hunks failed--bailing out\n", failed, hunk); ! my_exit(FAILURE); ! } ! else say4("%d out of %d hunks failed--saving rejects to %s\n", ! failed, hunk, rejname); } if (move_file(TMPREJNAME, rejname) < 0) trejkeep = TRUE; ************** *** 299,305 } set_signals(); } ! my_exit(0); } /* Prepare to find the next patch to do in the patch file. */ --- 331,337 ----- } set_signals(); } ! my_exit(ever_failed ? FAILURE : 0); } /* Prepare to find the next patch to do in the patch file. */ ************** *** 376,381 else { #endif switch (*++s) { case 'b': origext = savestr(Argv[1]); Argc--,Argv++; --- 408,420 ----- else { #endif switch (*++s) { + case 'a': + #ifdef VMS + case 'A': + #endif + abort_on_error = 7; + if isdigit(*(s+1)) abort_on_error = atoi(++s); + break; case 'b': origext = savestr(Argv[1]); Argc--,Argv++; ************** *** 617,623 say3("oldchar = '%c', newchar = '%c'\n", pch_char(old), pch_char(new)); #endif ! my_exit(1); } if (pch_char(new) == '!') { copy_till(where + old - 1); --- 656,662 ----- say3("oldchar = '%c', newchar = '%c'\n", pch_char(old), pch_char(new)); #endif ! my_exit(FAILURE); } if (pch_char(new) == '!') { copy_till(where + old - 1); ************** *** 802,807 int status; { while (unlink(TMPINNAME) >= 0); if (!toutkeep) { while (unlink(TMPOUTNAME) >= 0); } --- 841,847 ----- int status; { while (unlink(TMPINNAME) >= 0); + if (abort_on_error) really_move_files(FALSE); if (!toutkeep) { while (unlink(TMPOUTNAME) >= 0); } *** patch_orig.doc --- patch.doc ************** *** 150,155 Patch recognizes the following switches: -b causes the next argument to be interpreted as the backup extension, to be used in place of ".orig". --- 150,162 ----- Patch recognizes the following switches: + -a[] (default==7) + causes the run to be aborted, with read as the + inclusive OR of: + 1 - abort if any hunk fails + 2 - abort if any hunk is ignored + 4 - delete temporary files when aborting + -b causes the next argument to be interpreted as the backup extension, to be used in place of ".orig". *** pch_orig.c --- pch.c ************** *** 139,144 there_is_another_patch() { if (p_base != 0L && p_base >= p_filesize) { if (verbose) say1("done\n"); return FALSE; --- 139,148 ----- there_is_another_patch() { if (p_base != 0L && p_base >= p_filesize) { + if (abort_on_error) { + if (verbose) say1("moving temporary files to final locations...\n"); + really_move_files(TRUE); + } if (verbose) say1("done\n"); return FALSE; ************** *** 1050,1056 { #ifdef VMS printf ("Sorry, there's no ed on VMS.\n"); ! exit(0); #else Reg1 char *t; Reg2 long beginning_of_this_line; --- 1054,1060 ----- { #ifdef VMS printf ("Sorry, there's no ed on VMS.\n"); ! exit(FAILURE); #else Reg1 char *t; Reg2 long beginning_of_this_line; *** util_orig.c --- util.c ************** *** 3,9 #include "INTERN.h" #include "util.h" - /* Rename a file, copying it if necessary. */ int move_file(from,to) --- 3,8 ----- #include "INTERN.h" #include "util.h" struct filenames { char *fromname; ************** *** 5,10 /* Rename a file, copying it if necessary. */ int move_file(from,to) char *from, *to; --- 4,19 ----- #include "util.h" + struct filenames { + char *fromname; + char *toname; + struct filenames *next; + }; + static struct filenames *nameroot = NULL; + + /* Either rename a file now, or save the info for later, depending on whether + the -a switch was set. */ + int move_file(from,to) char *from, *to; ************** *** 9,14 move_file(from,to) char *from, *to; { #ifdef VMS char toname[512]; #else --- 18,99 ----- move_file(from,to) char *from, *to; { + struct filenames *nextelmt, *newelmt; + char *number; + int i; + + if ( (newelmt = malloc(sizeof(struct filenames))) == NULL ) + fatal1("patch: out of memory (move_file)\n"); + if (nameroot == NULL) nameroot = newelmt; + else { + for (nextelmt = nameroot; nextelmt->next != NULL; + nextelmt = nextelmt->next); + nextelmt->next = newelmt; + } + newelmt->next = NULL; + if ( ((newelmt->fromname = savestr(from)) == NULL) + || ((newelmt->toname = savestr(to)) == NULL) ) + fatal1("patch: out of memory (move_file)\n"); + if (!abort_on_error) return really_move_files(TRUE); + else { + #ifdef DEBUGGING + if (debug & 4) + say2("-a specified: deferring write of %s.\n", from); + #endif + /* Make a new temp name for the next time this file is used. The one we + just added to the list is our problem now; the caller thinks it's + been written out. */ + number = from + strlen(from) - 5; + sscanf(number,"%x",&i); + sprintf(number,"%5x",i+1); + for (i=0;i<5;i++) if (number[i]==' ') number[i]='0'; + return 0; + } + } + + /* Actually move all the files in the pending list if move is TRUE, or just + delete them if move is FALSE */ + + int + really_move_files(move) + bool move; + { + struct filenames *nextelmt; + Reg1 int stat = 0; + + for (nextelmt = nameroot; nextelmt != NULL; nextelmt = nextelmt->next) { + if (move) { + if (do_move_file(nextelmt->fromname,nextelmt->toname) < 0) stat = -1; + else { + chmod(nextelmt->toname, filemode); + while (unlink(nextelmt->fromname)>=0); + } + } + else { + #ifdef DEBUGGING + if (debug & 4) + say2("-a active: aborting move of %s.\n",nextelmt->fromname); + #endif + if (abort_on_error & 4) { + #ifdef DEBUGGING + if (debug & 4) + say2("-a & 4 specified: deleting %s.\n",nextelmt->fromname); + #endif + while (unlink(nextelmt->fromname)>=0); + } + } + free(nextelmt); + } + nameroot = NULL; + return stat; + } + + /* Rename a file, copying it if necessary. */ + + int + do_move_file(from,to) + char *from, *to; + { #ifdef VMS char toname[512]; #else ************** *** 42,47 Strcpy(toname, "./"); Strcat(toname, to); } i=rename (from, toname); if (i) { say3("Could not rename from %s to %s,\n", from, toname); --- 127,136 ----- Strcpy(toname, "./"); Strcat(toname, to); } + #ifdef DEBUGGING + if (debug & 4) + say3("Moving %s to %s.\n", from, toname); + #endif i=rename (from, toname); if (i) { say3("Could not rename from %s to %s,\n", from, toname); ************** *** 189,195 void my_exit(); say(pat, arg1, arg2, arg3); ! my_exit(1); } /* Get a response from the user, somehow or other. */ --- 278,284 ----- void my_exit(); say(pat, arg1, arg2, arg3); ! my_exit(FAILURE); } /* Get a response from the user, somehow or other. */ ************** *** 322,327 s = savestr(at); for (t=s; isspace(*t); t++) ; name = t; #ifdef DEBUGGING if (debug & 128) say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); --- 411,420 ----- s = savestr(at); for (t=s; isspace(*t); t++) ; name = t; + #ifdef VMS + for (; *t; t++) if (isalpha(*t)) *t = tolower(*t); + t = name; + #endif #ifdef DEBUGGING if (debug & 128) say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); ************** *** 326,333 if (debug & 128) say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); #endif ! if (strnEQ(name, "/dev/null", 9)) /* so files can be created by diffing */ ! return Nullch; /* against /dev/null. */ for (; *t && !isspace(*t); t++) if (*t == '/') if (--strip_leading >= 0) --- 419,427 ----- if (debug & 128) say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); #endif ! if (strnEQ(name, "/dev/null", 9) /* so files can be created by diffing */ ! || strnEQ(name, "nla0:", 5)) /* against /dev/null (nla0: on VMS). */ ! return Nullch; for (; *t && !isspace(*t); t++) if (*t == '/') if (--strip_leading >= 0) *** version_orig.c --- version.c ************** *** 1,6 /* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $ * * $Log: version.c,v $ * Revision 2.0 86/09/17 15:40:11 lwall * Baseline for netwide release. * --- 1,13 ----- /* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $ * * $Log: version.c,v $ + * + * 03-Mar-1993 Charles Bailey bailey@genetics.upenn.edu + * added note for -a & VMS patches until I can find lwall or current maintainer + * and get them integrated with normal distribution + * changed fatal3() to say3() + exit(0) so VMS doesn't see error code on + * successful invocation with -v + * * Revision 2.0 86/09/17 15:40:11 lwall * Baseline for netwide release. * ************** *** 23,28 #ifdef lint rcsid[0] = rcsid[0]; #else ! fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL); #endif } --- 30,37 ----- #ifdef lint rcsid[0] = rcsid[0]; #else ! say3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL); ! say1("-a switch & VMS patches: bailey@genetics.upenn.edu\n"); ! exit(0); #endif }