conslt32@ZEUS.UNL.EDU (Tim Russell) (08/04/89)
+-+-+-+ Beginning of part 7 +-+-+-+ X/* Return where in the patch file this hunk began, for error messages. */ X XLINENUM Xpch_hunk_beg() X`123 X return p_hunk_beg; X`125 X X/* Apply an ed script by feeding ed itself. */ X Xvoid Xdo_ed_script() X`123 X#ifdef VMS X printf ("Sorry, there's no ed on VMS.\n"); X exit(0); X#else X Reg1 char *t; X Reg2 long beginning_of_this_line; X Reg3 bool this_line_is_command = FALSE; X Reg4 FILE *pipefp; X FILE *popen(); X X if (!skip_rest_of_patch) `123 X`009while (unlink(TMPOUTNAME) >= 0); X`009copy_file(filearg[0], TMPOUTNAME); X`009if (verbose) X`009 Sprintf(buf, "/bin/ed %s", TMPOUTNAME); X`009else X`009 Sprintf(buf, "/bin/ed - %s", TMPOUTNAME); X`009pipefp = popen(buf, "w"); X `125 X for (;;) `123 X`009beginning_of_this_line = ftell(pfp); X`009if (pgets(buf, sizeof buf, pfp) == Nullch) `123 X`009 next_intuit_at(beginning_of_this_line,p_input_line); X`009 break; X`009`125 X`009p_input_line++; X`009for (t=buf; isdigit(*t) `124`124 *t == ','; t++) ; X`009this_line_is_command = (isdigit(*buf) && X`009 (*t == 'd' `124`124 *t == 'c' `124`124 *t == 'a') ); X`009if (this_line_is_command) `123 X`009 if (!skip_rest_of_patch) X`009`009fputs(buf, pipefp); X`009 if (*t != 'd') `123 X`009`009while (pgets(buf, sizeof buf, pfp) != Nullch) `123 X`009`009 p_input_line++; X`009`009 if (!skip_rest_of_patch) X`009`009`009fputs(buf, pipefp); X`009`009 if (strEQ(buf, ".\n")) X`009`009`009break; X`009`009`125 X`009 `125 X`009`125 X`009else `123 X`009 next_intuit_at(beginning_of_this_line,p_input_line); X`009 break; X`009`125 X `125 X if (skip_rest_of_patch) X`009return; X fprintf(pipefp, "w\n"); X fprintf(pipefp, "q\n"); X Fflush(pipefp); X Pclose(pipefp); X ignore_signals(); X if (move_file(TMPOUTNAME, outname) < 0) `123 X`009toutkeep = TRUE; X`009chmod(TMPOUTNAME, filemode); X `125 X else X`009chmod(outname, filemode); X set_signals(); X#endif /* VMS */ X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "PCH.H" $ CHECKSUM_IS = 1832979341 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $ X * X * $Log:`009pch.h,v $ X * Revision 2.0.1.1 87/01/30 22:47:16 lwall X * Added do_ed_script(). X *`032 X * Revision 2.0 86/09/17 15:39:57 lwall X * Baseline for netwide release. X *`032 X */ X XEXT FILE *pfp INIT(Nullfp);`009`009/* patch file pointer */ X Xvoid re_patch(); Xvoid open_patch_file(); Xvoid set_hunkmax(); Xvoid grow_hunkmax(); Xbool there_is_another_patch(); Xint intuit_diff_type(); Xvoid next_intuit_at(); Xvoid skip_to(); Xbool another_hunk(); Xbool pch_swap(); Xchar *pfetch(); Xshort pch_line_len(); XLINENUM pch_first(); XLINENUM pch_ptrn_lines(); XLINENUM pch_newfirst(); XLINENUM pch_repl_lines(); XLINENUM pch_end(); XLINENUM pch_context(); XLINENUM pch_hunk_beg(); Xchar pch_char(); Xchar *pfetch(); Xchar *pgets(); Xvoid do_ed_script(); $ GOSUB UNPACK_FILE $ FILE_IS = "README." $ CHECKSUM_IS = 1413047131 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X`009`009`009Patch Kit, Version 2.0 X X`009`009 Copyright (c) 1986, Larry Wall X XYou may copy the patch kit in whole or in part as long as you don't try to Xmake money off it, or pretend that you wrote it. X XNEW FEATURES IN THIS RELEASE X X(Correct) support for 4.3bsd-style context diffs. XFiles can be created from scratch. XYou can specify a fuzz-factor for context matching. XYou can force patch to ask no questions. XYou can specify how much of the leading pathname to strip off filenames. XUses a Configure script for greater portability. XYou are now asked if you want to apply a reversed patch. XNo limit (apart from memory) on the size of hunks. X XFeatures added by Tim Russell (russell@zeus.unl.edu) X XAdded support for VMS from earlier version to patchlevel 9. XAdded parsing support for "patch <patchfile" syntax. $ GOSUB UNPACK_FILE $ FILE_IS = "UTIL.C" $ CHECKSUM_IS = 438711646 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X#include "EXTERN.h" X#include "common.h" X#include "INTERN.h" X#include "util.h" X X/* Rename a file, copying it if necessary. */ X Xint Xmove_file(from,to) Xchar *from, *to; X`123 X char bakname[512]; X Reg1 char *s; X Reg2 int i; X Reg3 int fromfd; X X /* to stdout? */ X X if (strEQ(to, "-")) `123 X#ifdef DEBUGGING X`009if (debug & 4) X`009 say2("Moving %s to stdout.\n", from); X#endif X`009fromfd = open(from, 0); X`009if (fromfd < 0) X`009 fatal2("patch: internal error, can't reopen %s\n", from); X`009while ((i=read(fromfd, buf, sizeof buf)) > 0) X`009 if (write(1, buf, i) != 1) X`009`009fatal1("patch: write failed\n"); X`009Close(fromfd); X`009return 0; X `125 X X#ifdef VMS X /* This is not robust -- we just rename the file, hoping for the best. */ X if (*to == '/') Strcpy(bakname, to); X else `123 X`009Strcpy(bakname, "./"); X`009Strcat(bakname, to); X `125 X i=rename (from, bakname); V/* printf ("Attempted to rename %s to %s; status %d\n", from, bakname, i); X */ X#else X Strcpy(bakname, to); X Strcat(bakname, origext?origext:ORIGEXT); X if (stat(to, &filestat) >= 0) `123`009/* output file exists */ X`009dev_t to_device = filestat.st_dev; X`009ino_t to_inode = filestat.st_ino; X`009char *simplename = bakname; X`009 X`009for (s=bakname; *s; s++) `123 X`009 if (*s == '/') X`009`009simplename = s+1; X`009`125 X`009/* find a backup name that is not the same file */ X`009while (stat(bakname, &filestat) >= 0 && X`009`009to_device == filestat.st_dev && to_inode == filestat.st_ino) `123 X`009 for (s=simplename; *s && !islower(*s); s++) ; X`009 if (*s) X`009`009*s = toupper(*s); X`009 else X`009`009Strcpy(simplename, simplename+1); X`009`125 X`009while (unlink(bakname) >= 0) ;`009/* while() is for benefit of Eunice */ X#ifdef DEBUGGING X`009if (debug & 4) X`009 say3("Moving %s to %s.\n", to, bakname); X#endif X`009if (link(to, bakname) < 0) `123 X`009 say3("patch: can't backup %s, output is in %s\n", X`009`009to, from); X`009 return -1; X`009`125 X`009while (unlink(to) >= 0) ; X `125 X#ifdef DEBUGGING X if (debug & 4) X`009say3("Moving %s to %s.\n", from, to); X#endif X if (link(from, to) < 0) `123`009`009/* different file system? */ X`009Reg4 int tofd; X`009 X`009tofd = creat(to, 0666); X`009if (tofd < 0) `123 X`009 say3("patch: can't create %s, output is in %s.\n", X`009 to, from); X`009 return -1; X`009`125 X`009fromfd = open(from, 0); X`009if (fromfd < 0) X`009 fatal2("patch: internal error, can't reopen %s\n", from); X`009while ((i=read(fromfd, buf, sizeof buf)) > 0) X`009 if (write(tofd, buf, i) != i) X`009`009fatal1("patch: write failed\n"); X`009Close(fromfd); X`009Close(tofd); X `125 X Unlink(from); X#endif /* VMS */ X return 0; X`125 X X/* Copy a file. */ X Xvoid Xcopy_file(from,to) Xchar *from, *to; X`123 X Reg3 int tofd; X Reg2 int fromfd; X Reg1 int i; X `032 X tofd = creat(to, 0666); X if (tofd < 0) X`009fatal2("patch: can't create %s.\n", to); X fromfd = open(from, 0); X if (fromfd < 0) X`009fatal2("patch: internal error, can't reopen %s\n", from); X while ((i=read(fromfd, buf, sizeof buf)) > 0) X`009if (write(tofd, buf, i) != i) X`009 fatal2("patch: write (%s) failed\n", to); X Close(fromfd); X Close(tofd); X`125 X X/* Allocate a unique area for a string. */ X Xchar * Xsavestr(s) XReg1 char *s; X`123 X Reg3 char *rv; X Reg2 char *t; X X if (!s) X`009s = "Oops"; X t = s; X while (*t++); X rv = malloc((MEM) (t - s)); X if (rv == Nullch) `123 X`009if (using_plan_a) X`009 out_of_mem = TRUE; X`009else X`009 fatal1("patch: out of memory (savestr)\n"); X `125 X else `123 X`009t = rv; X`009while (*t++ = *s++); X `125 X return rv; X`125 X X#if defined(lint) && defined(CANVARARG) X X/*VARARGS ARGSUSED*/ Xsay(pat) char *pat; `123 ; `125 X/*VARARGS ARGSUSED*/ Xfatal(pat) char *pat; `123 ; `125 X/*VARARGS ARGSUSED*/ Xask(pat) char *pat; `123 ; `125 X X#else X X/* Vanilla terminal output (buffered). */ X Xvoid Xsay(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`123 X fprintf(stderr, pat, arg1, arg2, arg3); X Fflush(stderr); X`125 X X/* Terminal output, pun intended. */ X Xvoid`009`009`009`009/* very void */ Xfatal(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`123 X void my_exit(); X X say(pat, arg1, arg2, arg3); X my_exit(1); X`125 X X/* Get a response from the user, somehow or other. */ X Xvoid Xask(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`123 X int ttyfd; X int r; X bool tty2 = isatty(2); X X Sprintf(buf, pat, arg1, arg2, arg3); X Fflush(stderr); X write(2, buf, strlen(buf)); X if (tty2) `123`009`009`009`009/* might be redirected to a file */ X`009r = read(2, buf, sizeof buf); X `125 X else if (isatty(1)) `123`009`009/* this may be new file output */ X`009Fflush(stdout); X`009write(1, buf, strlen(buf)); X`009r = read(1, buf, sizeof buf); X `125 X else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) `123 X`009`009`009`009`009/* might be deleted or unwriteable */ X`009write(ttyfd, buf, strlen(buf)); X`009r = read(ttyfd, buf, sizeof buf); X`009Close(ttyfd); X `125 X else if (isatty(0)) `123`009`009/* this is probably patch input */ X`009Fflush(stdin); X`009write(0, buf, strlen(buf)); X`009r = read(0, buf, sizeof buf); X `125 X else `123`009`009`009`009/* no terminal at all--default it */ X`009buf[0] = '\n'; X`009r = 1; X `125 X if (r <= 0) X`009buf[0] = 0; X else X`009buf[r] = '\0'; X if (!tty2) X`009say1(buf); X`125 X#endif lint X X/* How to handle certain events when not in a critical region. */ X Xvoid Xset_signals() X`123 X void my_exit(); X X#ifndef lint X if (signal(SIGHUP, SIG_IGN) != SIG_IGN) X`009Signal(SIGHUP, my_exit); X if (signal(SIGINT, SIG_IGN) != SIG_IGN) X`009Signal(SIGINT, my_exit); X#endif X`125 X X/* How to handle certain events when in a critical region. */ X Xvoid Xignore_signals() X`123 X#ifndef lint X Signal(SIGHUP, SIG_IGN); X Signal(SIGINT, SIG_IGN); X#endif X`125 X X/* Make sure we'll have the directories to create a file. */ X Xvoid Xmakedirs(filename,striplast) XReg1 char *filename; Xbool striplast; X`123 X char tmpbuf[256]; X Reg2 char *s = tmpbuf; X char *dirv[20]; X Reg3 int i; X Reg4 int dirvp = 0; X X while (*filename) `123 X`009if (*filename == '/') `123 X`009 filename++; X`009 dirv[dirvp++] = s; X`009 *s++ = '\0'; X`009`125 X`009else `123 X`009 *s++ = *filename++; X`009`125 X `125 X *s = '\0'; X dirv[dirvp] = s; X if (striplast) X`009dirvp--; X if (dirvp < 0) X`009return; X strcpy(buf, "mkdir"); X s = buf; X for (i=0; i<=dirvp; i++) `123 X`009while (*s) s++; X`009*s++ = ' '; X`009strcpy(s, tmpbuf); X`009*dirv[i] = '/'; X `125 X system(buf); X`125 X X/* Make filenames more reasonable. */ X Xchar * Xfetchname(at,strip_leading,assume_exists) Xchar *at; Xint strip_leading; Xint assume_exists; X`123 X char *s; X char *name; X Reg1 char *t; X char tmpbuf[200]; X X if (!at) X`009return Nullch; X s = savestr(at); X for (t=s; isspace(*t); t++) ; X name = t; X#ifdef DEBUGGING X if (debug & 128) X`009say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); X#endif V if (strnEQ(name, "/dev/null", 9))`009/* so files can be created by diffin Xg */ X`009return Nullch;`009`009`009/* against /dev/null. */ X for (; *t && !isspace(*t); t++) X`009if (*t == '/') X`009 if (--strip_leading >= 0) X`009`009name = t+1; X *t = '\0'; X if (name != s && *s != '/') `123 X`009name[-1] = '\0'; X`009if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) `123 X`009 name[-1] = '/'; X`009 name=s; X`009`125 X `125 X name = savestr(name); X Sprintf(tmpbuf, "RCS/%s", name); X free(s); X if (stat(name, &filestat) < 0 && !assume_exists) `123 X#ifdef VMS X`009free(name); X`009name = Nullch; X `125 X#else X`009Strcat(tmpbuf, RCSSUFFIX); X`009if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) `123 X`009 Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name); V`009 if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) `12 X3 X`009`009free(name); X`009`009name = Nullch; X`009 `125 X`009`125 X `125 X#endif /* VMS */ X return name; X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "UTIL.H" $ CHECKSUM_IS = 1802118602 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $ X * X * $Log:`009util.h,v $ X * Revision 2.0 86/09/17 15:40:06 lwall X * Baseline for netwide release. X *`032 X */ X X/* and for those machine that can't handle a variable argument list */ X X#ifdef CANVARARG X X#define say1 say X#define say2 say X#define say3 say X#define say4 say X#define ask1 ask X#define ask2 ask X#define ask3 ask X#define ask4 ask X#define fatal1 fatal X#define fatal2 fatal X#define fatal3 fatal X#define fatal4 fatal X X#else /* hope they allow multi-line macro actual arguments */ X X#ifdef lint X X#define say1(a) say(a, 0, 0, 0) X#define say2(a,b) say(a, (b)==(b), 0, 0) X#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0) X#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d)) X#define ask1(a) ask(a, 0, 0, 0) X#define ask2(a,b) ask(a, (b)==(b), 0, 0) X#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0) X#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d)) X#define fatal1(a) fatal(a, 0, 0, 0) X#define fatal2(a,b) fatal(a, (b)==(b), 0, 0) X#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0) X#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d)) X X#else /* lint */ X /* if this doesn't work, try defining CANVARARG above */ X#define say1(a) say(a, Nullch, Nullch, Nullch) X#define say2(a,b) say(a, b, Nullch, Nullch) X#define say3(a,b,c) say(a, b, c, Nullch) X#define say4 say X#define ask1(a) ask(a, Nullch, Nullch, Nullch) X#define ask2(a,b) ask(a, b, Nullch, Nullch) X#define ask3(a,b,c) ask(a, b, c, Nullch) X#define ask4 ask X#define fatal1(a) fatal(a, Nullch, Nullch, Nullch) X#define fatal2(a,b) fatal(a, b, Nullch, Nullch) X#define fatal3(a,b,c) fatal(a, b, c, Nullch) X#define fatal4 fatal X X#endif /* lint */ X X/* if neither of the above work, join all multi-line macro calls. */ X#endif X XEXT char serrbuf[BUFSIZ];`009`009/* buffer for stderr */ X Xchar *fetchname(); Xint move_file(); Xvoid copy_file(); Xvoid say(); Xvoid fatal(); Xvoid ask(); Xchar *savestr(); Xvoid set_signals(); Xvoid ignore_signals(); Xvoid makedirs(); $ GOSUB UNPACK_FILE $ FILE_IS = "VERSION.C" $ CHECKSUM_IS = 1661809282 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $ X * X * $Log:`009version.c,v $ X * Revision 2.0 86/09/17 15:40:11 lwall X * Baseline for netwide release. X *`032 X */ X X#include "EXTERN.h" X#include "common.h" X#include "util.h" X#include "INTERN.h" X#include "patchlevel.h" X#include "version.h" X X/* Print out the version number and die. */ X Xvoid Xversion() X`123 X extern char rcsid[]; X X#ifdef lint X rcsid[0] = rcsid[0]; X#else X fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL); X#endif X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "VERSION.H" $ CHECKSUM_IS = 122769530 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $ X * X * $Log:`009version.h,v $ X * Revision 2.0 86/09/17 15:40:14 lwall X * Baseline for netwide release. X *`032 X */ X Xvoid version(); $ GOSUB UNPACK_FILE $ EXIT
fritz@unocss.UUCP (Tim Russell) (08/27/89)
+-+-+-+ Beginning of part 7 +-+-+-+ X/* Return where in the patch file this hunk began, for error messages. */ X XLINENUM Xpch_hunk_beg() X`123 X return p_hunk_beg; X`125 X X/* Apply an ed script by feeding ed itself. */ X Xvoid Xdo_ed_script() X`123 X#ifdef VMS X printf ("Sorry, there's no ed on VMS.\n"); X exit(0); X#else X Reg1 char *t; X Reg2 long beginning_of_this_line; X Reg3 bool this_line_is_command = FALSE; X Reg4 FILE *pipefp; X FILE *popen(); X X if (!skip_rest_of_patch) `123 X`009while (unlink(TMPOUTNAME) >= 0); X`009copy_file(filearg[0], TMPOUTNAME); X`009if (verbose) X`009 Sprintf(buf, "/bin/ed %s", TMPOUTNAME); X`009else X`009 Sprintf(buf, "/bin/ed - %s", TMPOUTNAME); X`009pipefp = popen(buf, "w"); X `125 X for (;;) `123 X`009beginning_of_this_line = ftell(pfp); X`009if (pgets(buf, sizeof buf, pfp) == Nullch) `123 X`009 next_intuit_at(beginning_of_this_line,p_input_line); X`009 break; X`009`125 X`009p_input_line++; X`009for (t=buf; isdigit(*t) `124`124 *t == ','; t++) ; X`009this_line_is_command = (isdigit(*buf) && X`009 (*t == 'd' `124`124 *t == 'c' `124`124 *t == 'a') ); X`009if (this_line_is_command) `123 X`009 if (!skip_rest_of_patch) X`009`009fputs(buf, pipefp); X`009 if (*t != 'd') `123 X`009`009while (pgets(buf, sizeof buf, pfp) != Nullch) `123 X`009`009 p_input_line++; X`009`009 if (!skip_rest_of_patch) X`009`009`009fputs(buf, pipefp); X`009`009 if (strEQ(buf, ".\n")) X`009`009`009break; X`009`009`125 X`009 `125 X`009`125 X`009else `123 X`009 next_intuit_at(beginning_of_this_line,p_input_line); X`009 break; X`009`125 X `125 X if (skip_rest_of_patch) X`009return; X fprintf(pipefp, "w\n"); X fprintf(pipefp, "q\n"); X Fflush(pipefp); X Pclose(pipefp); X ignore_signals(); X if (move_file(TMPOUTNAME, outname) < 0) `123 X`009toutkeep = TRUE; X`009chmod(TMPOUTNAME, filemode); X `125 X else X`009chmod(outname, filemode); X set_signals(); X#endif /* VMS */ X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "PCH.H" $ CHECKSUM_IS = 1832979341 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $ X * X * $Log:`009pch.h,v $ X * Revision 2.0.1.1 87/01/30 22:47:16 lwall X * Added do_ed_script(). X *`032 X * Revision 2.0 86/09/17 15:39:57 lwall X * Baseline for netwide release. X *`032 X */ X XEXT FILE *pfp INIT(Nullfp);`009`009/* patch file pointer */ X Xvoid re_patch(); Xvoid open_patch_file(); Xvoid set_hunkmax(); Xvoid grow_hunkmax(); Xbool there_is_another_patch(); Xint intuit_diff_type(); Xvoid next_intuit_at(); Xvoid skip_to(); Xbool another_hunk(); Xbool pch_swap(); Xchar *pfetch(); Xshort pch_line_len(); XLINENUM pch_first(); XLINENUM pch_ptrn_lines(); XLINENUM pch_newfirst(); XLINENUM pch_repl_lines(); XLINENUM pch_end(); XLINENUM pch_context(); XLINENUM pch_hunk_beg(); Xchar pch_char(); Xchar *pfetch(); Xchar *pgets(); Xvoid do_ed_script(); $ GOSUB UNPACK_FILE $ FILE_IS = "README." $ CHECKSUM_IS = 1413047131 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X`009`009`009Patch Kit, Version 2.0 X X`009`009 Copyright (c) 1986, Larry Wall X XYou may copy the patch kit in whole or in part as long as you don't try to Xmake money off it, or pretend that you wrote it. X XNEW FEATURES IN THIS RELEASE X X(Correct) support for 4.3bsd-style context diffs. XFiles can be created from scratch. XYou can specify a fuzz-factor for context matching. XYou can force patch to ask no questions. XYou can specify how much of the leading pathname to strip off filenames. XUses a Configure script for greater portability. XYou are now asked if you want to apply a reversed patch. XNo limit (apart from memory) on the size of hunks. X XFeatures added by Tim Russell (russell@zeus.unl.edu) X XAdded support for VMS from earlier version to patchlevel 9. XAdded parsing support for "patch <patchfile" syntax. $ GOSUB UNPACK_FILE $ FILE_IS = "UTIL.C" $ CHECKSUM_IS = 438711646 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X#include "EXTERN.h" X#include "common.h" X#include "INTERN.h" X#include "util.h" X X/* Rename a file, copying it if necessary. */ X Xint Xmove_file(from,to) Xchar *from, *to; X`123 X char bakname[512]; X Reg1 char *s; X Reg2 int i; X Reg3 int fromfd; X X /* to stdout? */ X X if (strEQ(to, "-")) `123 X#ifdef DEBUGGING X`009if (debug & 4) X`009 say2("Moving %s to stdout.\n", from); X#endif X`009fromfd = open(from, 0); X`009if (fromfd < 0) X`009 fatal2("patch: internal error, can't reopen %s\n", from); X`009while ((i=read(fromfd, buf, sizeof buf)) > 0) X`009 if (write(1, buf, i) != 1) X`009`009fatal1("patch: write failed\n"); X`009Close(fromfd); X`009return 0; X `125 X X#ifdef VMS X /* This is not robust -- we just rename the file, hoping for the best. */ X if (*to == '/') Strcpy(bakname, to); X else `123 X`009Strcpy(bakname, "./"); X`009Strcat(bakname, to); X `125 X i=rename (from, bakname); V/* printf ("Attempted to rename %s to %s; status %d\n", from, bakname, i); X */ X#else X Strcpy(bakname, to); X Strcat(bakname, origext?origext:ORIGEXT); X if (stat(to, &filestat) >= 0) `123`009/* output file exists */ X`009dev_t to_device = filestat.st_dev; X`009ino_t to_inode = filestat.st_ino; X`009char *simplename = bakname; X`009 X`009for (s=bakname; *s; s++) `123 X`009 if (*s == '/') X`009`009simplename = s+1; X`009`125 X`009/* find a backup name that is not the same file */ X`009while (stat(bakname, &filestat) >= 0 && X`009`009to_device == filestat.st_dev && to_inode == filestat.st_ino) `123 X`009 for (s=simplename; *s && !islower(*s); s++) ; X`009 if (*s) X`009`009*s = toupper(*s); X`009 else X`009`009Strcpy(simplename, simplename+1); X`009`125 X`009while (unlink(bakname) >= 0) ;`009/* while() is for benefit of Eunice */ X#ifdef DEBUGGING X`009if (debug & 4) X`009 say3("Moving %s to %s.\n", to, bakname); X#endif X`009if (link(to, bakname) < 0) `123 X`009 say3("patch: can't backup %s, output is in %s\n", X`009`009to, from); X`009 return -1; X`009`125 X`009while (unlink(to) >= 0) ; X `125 X#ifdef DEBUGGING X if (debug & 4) X`009say3("Moving %s to %s.\n", from, to); X#endif X if (link(from, to) < 0) `123`009`009/* different file system? */ X`009Reg4 int tofd; X`009 X`009tofd = creat(to, 0666); X`009if (tofd < 0) `123 X`009 say3("patch: can't create %s, output is in %s.\n", X`009 to, from); X`009 return -1; X`009`125 X`009fromfd = open(from, 0); X`009if (fromfd < 0) X`009 fatal2("patch: internal error, can't reopen %s\n", from); X`009while ((i=read(fromfd, buf, sizeof buf)) > 0) X`009 if (write(tofd, buf, i) != i) X`009`009fatal1("patch: write failed\n"); X`009Close(fromfd); X`009Close(tofd); X `125 X Unlink(from); X#endif /* VMS */ X return 0; X`125 X X/* Copy a file. */ X Xvoid Xcopy_file(from,to) Xchar *from, *to; X`123 X Reg3 int tofd; X Reg2 int fromfd; X Reg1 int i; X `032 X tofd = creat(to, 0666); X if (tofd < 0) X`009fatal2("patch: can't create %s.\n", to); X fromfd = open(from, 0); X if (fromfd < 0) X`009fatal2("patch: internal error, can't reopen %s\n", from); X while ((i=read(fromfd, buf, sizeof buf)) > 0) X`009if (write(tofd, buf, i) != i) X`009 fatal2("patch: write (%s) failed\n", to); X Close(fromfd); X Close(tofd); X`125 X X/* Allocate a unique area for a string. */ X Xchar * Xsavestr(s) XReg1 char *s; X`123 X Reg3 char *rv; X Reg2 char *t; X X if (!s) X`009s = "Oops"; X t = s; X while (*t++); X rv = malloc((MEM) (t - s)); X if (rv == Nullch) `123 X`009if (using_plan_a) X`009 out_of_mem = TRUE; X`009else X`009 fatal1("patch: out of memory (savestr)\n"); X `125 X else `123 X`009t = rv; X`009while (*t++ = *s++); X `125 X return rv; X`125 X X#if defined(lint) && defined(CANVARARG) X X/*VARARGS ARGSUSED*/ Xsay(pat) char *pat; `123 ; `125 X/*VARARGS ARGSUSED*/ Xfatal(pat) char *pat; `123 ; `125 X/*VARARGS ARGSUSED*/ Xask(pat) char *pat; `123 ; `125 X X#else X X/* Vanilla terminal output (buffered). */ X Xvoid Xsay(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`123 X fprintf(stderr, pat, arg1, arg2, arg3); X Fflush(stderr); X`125 X X/* Terminal output, pun intended. */ X Xvoid`009`009`009`009/* very void */ Xfatal(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`123 X void my_exit(); X X say(pat, arg1, arg2, arg3); X my_exit(1); X`125 X X/* Get a response from the user, somehow or other. */ X Xvoid Xask(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`123 X int ttyfd; X int r; X bool tty2 = isatty(2); X X Sprintf(buf, pat, arg1, arg2, arg3); X Fflush(stderr); X write(2, buf, strlen(buf)); X if (tty2) `123`009`009`009`009/* might be redirected to a file */ X`009r = read(2, buf, sizeof buf); X `125 X else if (isatty(1)) `123`009`009/* this may be new file output */ X`009Fflush(stdout); X`009write(1, buf, strlen(buf)); X`009r = read(1, buf, sizeof buf); X `125 X else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) `123 X`009`009`009`009`009/* might be deleted or unwriteable */ X`009write(ttyfd, buf, strlen(buf)); X`009r = read(ttyfd, buf, sizeof buf); X`009Close(ttyfd); X `125 X else if (isatty(0)) `123`009`009/* this is probably patch input */ X`009Fflush(stdin); X`009write(0, buf, strlen(buf)); X`009r = read(0, buf, sizeof buf); X `125 X else `123`009`009`009`009/* no terminal at all--default it */ X`009buf[0] = '\n'; X`009r = 1; X `125 X if (r <= 0) X`009buf[0] = 0; X else X`009buf[r] = '\0'; X if (!tty2) X`009say1(buf); X`125 X#endif lint X X/* How to handle certain events when not in a critical region. */ X Xvoid Xset_signals() X`123 X void my_exit(); X X#ifndef lint X if (signal(SIGHUP, SIG_IGN) != SIG_IGN) X`009Signal(SIGHUP, my_exit); X if (signal(SIGINT, SIG_IGN) != SIG_IGN) X`009Signal(SIGINT, my_exit); X#endif X`125 X X/* How to handle certain events when in a critical region. */ X Xvoid Xignore_signals() X`123 X#ifndef lint X Signal(SIGHUP, SIG_IGN); X Signal(SIGINT, SIG_IGN); X#endif X`125 X X/* Make sure we'll have the directories to create a file. */ X Xvoid Xmakedirs(filename,striplast) XReg1 char *filename; Xbool striplast; X`123 X char tmpbuf[256]; X Reg2 char *s = tmpbuf; X char *dirv[20]; X Reg3 int i; X Reg4 int dirvp = 0; X X while (*filename) `123 X`009if (*filename == '/') `123 X`009 filename++; X`009 dirv[dirvp++] = s; X`009 *s++ = '\0'; X`009`125 X`009else `123 X`009 *s++ = *filename++; X`009`125 X `125 X *s = '\0'; X dirv[dirvp] = s; X if (striplast) X`009dirvp--; X if (dirvp < 0) X`009return; X strcpy(buf, "mkdir"); X s = buf; X for (i=0; i<=dirvp; i++) `123 X`009while (*s) s++; X`009*s++ = ' '; X`009strcpy(s, tmpbuf); X`009*dirv[i] = '/'; X `125 X system(buf); X`125 X X/* Make filenames more reasonable. */ X Xchar * Xfetchname(at,strip_leading,assume_exists) Xchar *at; Xint strip_leading; Xint assume_exists; X`123 X char *s; X char *name; X Reg1 char *t; X char tmpbuf[200]; X X if (!at) X`009return Nullch; X s = savestr(at); X for (t=s; isspace(*t); t++) ; X name = t; X#ifdef DEBUGGING X if (debug & 128) X`009say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); X#endif V if (strnEQ(name, "/dev/null", 9))`009/* so files can be created by diffin Xg */ X`009return Nullch;`009`009`009/* against /dev/null. */ X for (; *t && !isspace(*t); t++) X`009if (*t == '/') X`009 if (--strip_leading >= 0) X`009`009name = t+1; X *t = '\0'; X if (name != s && *s != '/') `123 X`009name[-1] = '\0'; X`009if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) `123 X`009 name[-1] = '/'; X`009 name=s; X`009`125 X `125 X name = savestr(name); X Sprintf(tmpbuf, "RCS/%s", name); X free(s); X if (stat(name, &filestat) < 0 && !assume_exists) `123 X#ifdef VMS X`009free(name); X`009name = Nullch; X `125 X#else X`009Strcat(tmpbuf, RCSSUFFIX); X`009if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) `123 X`009 Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name); V`009 if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) `12 X3 X`009`009free(name); X`009`009name = Nullch; X`009 `125 X`009`125 X `125 X#endif /* VMS */ X return name; X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "UTIL.H" $ CHECKSUM_IS = 1802118602 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $ X * X * $Log:`009util.h,v $ X * Revision 2.0 86/09/17 15:40:06 lwall X * Baseline for netwide release. X *`032 X */ X X/* and for those machine that can't handle a variable argument list */ X X#ifdef CANVARARG X X#define say1 say X#define say2 say X#define say3 say X#define say4 say X#define ask1 ask X#define ask2 ask X#define ask3 ask X#define ask4 ask X#define fatal1 fatal X#define fatal2 fatal X#define fatal3 fatal X#define fatal4 fatal X X#else /* hope they allow multi-line macro actual arguments */ X X#ifdef lint X X#define say1(a) say(a, 0, 0, 0) X#define say2(a,b) say(a, (b)==(b), 0, 0) X#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0) X#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d)) X#define ask1(a) ask(a, 0, 0, 0) X#define ask2(a,b) ask(a, (b)==(b), 0, 0) X#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0) X#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d)) X#define fatal1(a) fatal(a, 0, 0, 0) X#define fatal2(a,b) fatal(a, (b)==(b), 0, 0) X#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0) X#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d)) X X#else /* lint */ X /* if this doesn't work, try defining CANVARARG above */ X#define say1(a) say(a, Nullch, Nullch, Nullch) X#define say2(a,b) say(a, b, Nullch, Nullch) X#define say3(a,b,c) say(a, b, c, Nullch) X#define say4 say X#define ask1(a) ask(a, Nullch, Nullch, Nullch) X#define ask2(a,b) ask(a, b, Nullch, Nullch) X#define ask3(a,b,c) ask(a, b, c, Nullch) X#define ask4 ask X#define fatal1(a) fatal(a, Nullch, Nullch, Nullch) X#define fatal2(a,b) fatal(a, b, Nullch, Nullch) X#define fatal3(a,b,c) fatal(a, b, c, Nullch) X#define fatal4 fatal X X#endif /* lint */ X X/* if neither of the above work, join all multi-line macro calls. */ X#endif X XEXT char serrbuf[BUFSIZ];`009`009/* buffer for stderr */ X Xchar *fetchname(); Xint move_file(); Xvoid copy_file(); Xvoid say(); Xvoid fatal(); Xvoid ask(); Xchar *savestr(); Xvoid set_signals(); Xvoid ignore_signals(); Xvoid makedirs(); $ GOSUB UNPACK_FILE $ FILE_IS = "VERSION.C" $ CHECKSUM_IS = 1661809282 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $ X * X * $Log:`009version.c,v $ X * Revision 2.0 86/09/17 15:40:11 lwall X * Baseline for netwide release. X *`032 X */ X X#include "EXTERN.h" X#include "common.h" X#include "util.h" X#include "INTERN.h" X#include "patchlevel.h" X#include "version.h" X X/* Print out the version number and die. */ X Xvoid Xversion() X`123 X extern char rcsid[]; X X#ifdef lint X rcsid[0] = rcsid[0]; X#else X fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL); X#endif X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "VERSION.H" $ CHECKSUM_IS = 122769530 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $ X * X * $Log:`009version.h,v $ X * Revision 2.0 86/09/17 15:40:14 lwall X * Baseline for netwide release. X *`032 X */ X Xvoid version(); $ GOSUB UNPACK_FILE $ EXIT -- ---------------------------------+-------------------------------------------- Tim Russell, Computer Operator | Internet: russell@zeus.unl.edu Campus Computing | Bitnet: russell@unoma1 University of Nebraska at Omaha | UUCP: uunet!zeus.unl.edu!russell