#include "EXTERN.h" #include "common.h" #include "INTERN.h" #include "util.h" /* Rename a file, copying it if necessary. */ #ifdef AMIGA #include #include /* backup & copy the file */ static void copy_file(); int move_file(from,to) char *from, *to; { register long success; register int fromfd; register int i; register struct FileLock *destlock; int curnum='0'; static char bakname[256]; /* declare us some AmigaDOS functions: */ extern long DeleteFile(); extern struct FileLock *Lock(); extern void UnLock(); extern long Rename(); if (strEQ(to, "-")) { /* cat it to stdout. */ #ifdef DEBUGGING if (debug & 4) say2("Moving %s to stdout.\n", from); #endif fromfd = open(from, 0); if (fromfd < 0) fatal2("patch: internal error, can't reopen %s\n", from); while ((i=read(fromfd, buf, sizeof buf)) > 0) if (write(1, buf, i) != 1) fatal1("patch: write failed\n"); Close(fromfd); return 0; } /* add the extension to the name */ Strcpy(bakname, to); /* see if the "to" exists. If not, don't add the extension. */ if (destlock=Lock(bakname)) { UnLock(destlock); Strcat(bakname, ORIGEXT); i = strlen(bakname); /* find the end of string */ bakname[i+1]=0; /* so that the following will work: */ /* now to see if the destination exists: */ while (destlock=Lock(bakname)) { UnLock(destlock); /* clean up after ourselves. */ bakname[i]=curnum++; } /* ok, now we can do the relinking! */ success = Rename(to,bakname); if (success==0) { say3("patch: can't backup %s, output is in %s\n", to, from); return -1; } } /* ok, now copy the from to the to file. */ /* try renaming it first, & if that don't work, then copy it. */ success = Rename(from,to); if (success==0) { /* if don't work, then copy! */ copy_file(from,to); success=DeleteFile(from); } return 0; } #endif #ifndef AMIGA int move_file(from,to) char *from, *to; { char bakname[512]; Reg1 char *s; Reg2 int i; Reg3 int fromfd; /* to stdout? */ if (strEQ(to, "-")) { #ifdef DEBUGGING if (debug & 4) say2("Moving %s to stdout.\n", from); #endif fromfd = open(from, 0); if (fromfd < 0) fatal2("patch: internal error, can't reopen %s\n", from); while ((i=read(fromfd, buf, sizeof buf)) > 0) if (write(1, buf, i) != 1) fatal1("patch: write failed\n"); Close(fromfd); return 0; } if (origprae) { Strcpy (bakname, origprae); Strcat(bakname, to); } else { Strcpy(bakname, to); Strcat(bakname, origext?origext:ORIGEXT); } if (stat(to, &filestat) >= 0) { /* output file exists */ dev_t to_device = filestat.st_dev; ino_t to_inode = filestat.st_ino; char *simplename = bakname; for (s=bakname; *s; s++) { if (*s == '/') simplename = s+1; } /* find a backup name that is not the same file */ while (stat(bakname, &filestat) >= 0 && to_device == filestat.st_dev && to_inode == filestat.st_ino) { for (s=simplename; *s && !islower(*s); s++) ; if (*s) *s = toupper(*s); else Strcpy(simplename, simplename+1); } while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice */ #ifdef DEBUGGING if (debug & 4) say3("Moving %s to %s.\n", to, bakname); #endif if (link(to, bakname) < 0) { say3("patch: can't backup %s, output is in %s\n", to, from); return -1; } while (unlink(to) >= 0) ; } #ifdef DEBUGGING if (debug & 4) say3("Moving %s to %s.\n", from, to); #endif if (link(from, to) < 0) { /* different file system? */ Reg4 int tofd; tofd = creat(to, 0666); if (tofd < 0) { say3("patch: can't create %s, output is in %s.\n", to, from); return -1; } fromfd = open(from, 0); if (fromfd < 0) fatal2("patch: internal error, can't reopen %s\n", from); while ((i=read(fromfd, buf, sizeof buf)) > 0) if (write(tofd, buf, i) != i) fatal1("patch: write failed\n"); Close(fromfd); Close(tofd); } Unlink(from); return 0; } #endif /* Copy a file. */ void copy_file(from,to) char *from, *to; { Reg3 int tofd; Reg2 int fromfd; Reg1 int i; tofd = creat(to, 0666); if (tofd < 0) fatal2("patch: can't create %s.\n", to); fromfd = open(from, 0); if (fromfd < 0) fatal2("patch: internal error, can't reopen %s\n", from); while ((i=read(fromfd, buf, sizeof buf)) > 0) if (write(tofd, buf, i) != i) fatal2("patch: write (%s) failed\n", to); Close(fromfd); Close(tofd); } /* Allocate a unique area for a string. */ char * savestr(s) Reg1 char *s; { Reg3 char *rv; Reg2 char *t; if (!s) s = "Oops"; t = s; while (*t++); rv = malloc((MEM) (t - s)); if (rv == Nullch) { if (using_plan_a) out_of_mem = TRUE; else fatal1("patch: out of memory (savestr)\n"); } else { t = rv; while (*t++ = *s++); } return rv; } #ifdef lint #ifdef CANVARARG /*VARARGS ARGSUSED*/ say(pat) char *pat; { ; } /*VARARGS ARGSUSED*/ fatal(pat) char *pat; { ; } /*VARARGS ARGSUSED*/ ask(pat) char *pat; { ; } #endif #else /* Vanilla terminal output (buffered). */ void say(pat,arg1,arg2,arg3) char *pat; long arg1,arg2,arg3; { fprintf(stderr, pat, arg1, arg2, arg3); Fflush(stderr); } /* Terminal output, pun intended. */ void /* very void */ fatal(pat,arg1,arg2,arg3) char *pat; long arg1,arg2,arg3; { void my_exit(); say(pat, arg1, arg2, arg3); my_exit(1); } #ifndef AMIGA /* Get a response from the user, somehow or other. */ void ask(pat,arg1,arg2,arg3) char *pat; long arg1,arg2,arg3; { int ttyfd; int r; bool tty2 = isatty(2); Sprintf(buf, pat, arg1, arg2, arg3); Fflush(stderr); write(2, buf, strlen(buf)); if (tty2) { /* might be redirected to a file */ r = read(2, buf, sizeof buf); } else if (isatty(1)) { /* this may be new file output */ Fflush(stdout); write(1, buf, strlen(buf)); r = read(1, buf, sizeof buf); } else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) { /* might be deleted or unwriteable */ write(ttyfd, buf, strlen(buf)); r = read(ttyfd, buf, sizeof buf); Close(ttyfd); } else if (isatty(0)) { /* this is probably patch input */ Fflush(stdin); write(0, buf, strlen(buf)); r = read(0, buf, sizeof buf); } else { /* no terminal at all--default it */ buf[0] = '\n'; r = 1; } if (r <= 0) buf[0] = 0; else buf[r] = '\0'; if (!tty2) say1(buf); } #else /* Amiga */ /* for the Amiga we're going to have to do some heavy-duty magic. We can't open /dev/tty! So open a whole new window! */ void ask(pat,arg1,arg2,arg3) char *pat; long arg1,arg2,arg3; { int rwin; long actual_read; Sprintf(buf, pat, arg1, arg2, arg3); rwin=open("CON:0/10/400/100/Patch Response Window",O_RDWR+O_CREAT); if (rwin==0) { printf("Error:No window dressing."); } write(rwin,buf,strlen(buf)); actual_read=read(rwin,buf,sizeof buf); if (actual_read==0) buf[0]=0; buf[actual_read]=0; /* printf("actual_read=%d buf=%s\n",actual_read,buf); */ Close(rwin); } #endif /* amiga */ #endif /* lint */ /* How to handle certain events when not in a critical region. */ void set_signals(reset) int reset; { void my_exit(); #ifdef AMIGA extern short Enable_Abort; Enable_Abort=1; #else #ifndef lint #ifdef VOIDSIG static void (*hupval)(),(*intval)(); #else static int (*hupval)(),(*intval)(); #endif if (!reset) { hupval = signal(SIGHUP, SIG_IGN); if (hupval != SIG_IGN) #ifdef VOIDSIG hupval = my_exit; #else hupval = (int(*)())my_exit; #endif intval = signal(SIGINT, SIG_IGN); if (intval != SIG_IGN) #ifdef VOIDSIG intval = my_exit; #else intval = (int(*)())my_exit; #endif } Signal(SIGHUP, hupval); Signal(SIGINT, intval); #endif #endif } /* How to handle certain events when in a critical region. */ void ignore_signals() { #ifdef AMIGA extern short Enable_Abort; Enable_Abort=0; #else #ifndef lint Signal(SIGHUP, SIG_IGN); Signal(SIGINT, SIG_IGN); #endif #endif } #ifdef AMIGA extern int stat(); /* This is more space-efficient than Larry's, but has the disadvantage of groking with the other person's copy of the string. Restores it before the end, but that's still nasty. */ void makedirs(filename,striplast) char *filename; bool striplast; { register char *walkptr=filename; register char temp; extern char *index(); register struct FileLock *tmplock; register int result; extern struct FileLock *CreateDir(); struct stat *buf; /* for the stat() command. */ /* first the easy part: */ buf = (struct stat *) malloc(sizeof(struct stat)); if (walkptr[0]=='.' && walkptr[1]=='/') walkptr+=2; if (walkptr[0]=='/') /* starting at root: */ walkptr[0]=':'; /* AmigaDOS root. */ /* loop: */ for(;;) { walkptr=index(walkptr,'/'); /* see if there's subdirectories. */ if (walkptr) { temp=*walkptr; *walkptr++=0; /* filename now points to dirname. */ } else if (striplast) /* top-of-loop exit, and... */ break; result = stat(filename,buf); /* If we can't create the directory, we'll sit here spinning till the end of the filename. On the other hand, it don't really matter what we do here. They won't be able to open the final file name upstairs, so they'll say "can't create file" up there. Phew. */ if (result==-1) { /* make a directory... */ tmplock=CreateDir(filename); UnLock(tmplock); } if (walkptr) *(walkptr-1)=temp; /* restore what we did to his filename. */ else break; /* bottom of loop exit. */ } free(buf); return; } #else /* Make sure we'll have the directories to create a file. */ void makedirs(filename,striplast) Reg1 char *filename; bool striplast; { char tmpbuf[256]; Reg2 char *s = tmpbuf; char *dirv[20]; Reg3 int i; Reg4 int dirvp = 0; while (*filename) { if (*filename == '/') { filename++; dirv[dirvp++] = s; *s++ = '\0'; } else { *s++ = *filename++; } } *s = '\0'; dirv[dirvp] = s; if (striplast) dirvp--; if (dirvp < 0) return; strcpy(buf, "mkdir"); s = buf; for (i=0; i<=dirvp; i++) { while (*s) s++; *s++ = ' '; strcpy(s, tmpbuf); *dirv[i] = '/'; } system(buf); } #endif #ifdef AMIGA /* chmod to satisfy us: */ void chmod() {} /* abort to satisfy us: */ void abort() { exit(1); } #endif /* Make filenames more reasonable. */ char * fetchname(at,strip_leading,assume_exists) char *at; int strip_leading; int assume_exists; { char *s; char *name; Reg1 char *t; char tmpbuf[200]; if (!at) return Nullch; 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); #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) name = t+1; *t = '\0'; if (name != s && *s != '/') { name[-1] = '\0'; if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) { name[-1] = '/'; name=s; } } name = savestr(name); Sprintf(tmpbuf, "RCS/%s", name); free(s); if (stat(name, &filestat) < 0 && !assume_exists) { #ifdef AMIGA name = Nullch; /* Amiga doesn't have RCS. */ #else Strcat(tmpbuf, RCSSUFFIX); if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) { Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name); if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) { free(name); name = Nullch; } } #endif } return name; }