1: #include "EXTERN.h" 2: #include "common.h" 3: #include "INTERN.h" 4: #include "util.h" 5: 6: /* Rename a file, copying it if necessary. */ 7: 8: int 9: move_file(from,to) 10: char *from, *to; 11: { 12: char bakname[512]; 13: Reg1 char *s; 14: Reg2 int i; 15: Reg3 int fromfd; 16: 17: /* to stdout? */ 18: 19: if (strEQ(to, "-")) { 20: #ifdef DEBUGGING 21: if (debug & 4) 22: say2("Moving %s to stdout.\n", from); 23: #endif 24: fromfd = open(from, 0); 25: if (fromfd < 0) 26: fatal2("patch: internal error, can't reopen %s\n", from); 27: while ((i=read(fromfd, buf, sizeof buf)) > 0) 28: if (write(1, buf, i) != 1) 29: fatal1("patch: write failed\n"); 30: Close(fromfd); 31: return 0; 32: } 33: 34: if (origprae) { 35: Strcpy (bakname, origprae); 36: Strcat(bakname, to); 37: } else { 38: Strcpy(bakname, to); 39: Strcat(bakname, origext?origext:ORIGEXT); 40: } 41: if (stat(to, &filestat) >= 0) { /* output file exists */ 42: dev_t to_device = filestat.st_dev; 43: ino_t to_inode = filestat.st_ino; 44: char *simplename = bakname; 45: 46: for (s=bakname; *s; s++) { 47: if (*s == '/') 48: simplename = s+1; 49: } 50: /* find a backup name that is not the same file */ 51: while (stat(bakname, &filestat) >= 0 && 52: to_device == filestat.st_dev && to_inode == filestat.st_ino) { 53: for (s=simplename; *s && !islower(*s); s++) ; 54: if (*s) 55: *s = toupper(*s); 56: else 57: Strcpy(simplename, simplename+1); 58: } 59: while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice */ 60: #ifdef DEBUGGING 61: if (debug & 4) 62: say3("Moving %s to %s.\n", to, bakname); 63: #endif 64: if (link(to, bakname) < 0) { 65: say3("patch: can't backup %s, output is in %s\n", 66: to, from); 67: return -1; 68: } 69: while (unlink(to) >= 0) ; 70: } 71: #ifdef DEBUGGING 72: if (debug & 4) 73: say3("Moving %s to %s.\n", from, to); 74: #endif 75: if (link(from, to) < 0) { /* different file system? */ 76: Reg4 int tofd; 77: 78: tofd = creat(to, 0666); 79: if (tofd < 0) { 80: say3("patch: can't create %s, output is in %s.\n", 81: to, from); 82: return -1; 83: } 84: fromfd = open(from, 0); 85: if (fromfd < 0) 86: fatal2("patch: internal error, can't reopen %s\n", from); 87: while ((i=read(fromfd, buf, sizeof buf)) > 0) 88: if (write(tofd, buf, i) != i) 89: fatal1("patch: write failed\n"); 90: Close(fromfd); 91: Close(tofd); 92: } 93: Unlink(from); 94: return 0; 95: } 96: 97: /* Copy a file. */ 98: 99: void 100: copy_file(from,to) 101: char *from, *to; 102: { 103: Reg3 int tofd; 104: Reg2 int fromfd; 105: Reg1 int i; 106: 107: tofd = creat(to, 0666); 108: if (tofd < 0) 109: fatal2("patch: can't create %s.\n", to); 110: fromfd = open(from, 0); 111: if (fromfd < 0) 112: fatal2("patch: internal error, can't reopen %s\n", from); 113: while ((i=read(fromfd, buf, sizeof buf)) > 0) 114: if (write(tofd, buf, i) != i) 115: fatal2("patch: write (%s) failed\n", to); 116: Close(fromfd); 117: Close(tofd); 118: } 119: 120: /* Allocate a unique area for a string. */ 121: 122: char * 123: savestr(s) 124: Reg1 char *s; 125: { 126: Reg3 char *rv; 127: Reg2 char *t; 128: 129: if (!s) 130: s = "Oops"; 131: t = s; 132: while (*t++); 133: rv = malloc((MEM) (t - s)); 134: if (rv == Nullch) { 135: if (using_plan_a) 136: out_of_mem = TRUE; 137: else 138: fatal1("patch: out of memory (savestr)\n"); 139: } 140: else { 141: t = rv; 142: while (*t++ = *s++); 143: } 144: return rv; 145: } 146: 147: #if defined(lint) && defined(CANVARARG) 148: 149: /*VARARGS ARGSUSED*/ 150: say(pat) char *pat; { ; } 151: /*VARARGS ARGSUSED*/ 152: fatal(pat) char *pat; { ; } 153: /*VARARGS ARGSUSED*/ 154: ask(pat) char *pat; { ; } 155: 156: #else 157: 158: /* Vanilla terminal output (buffered). */ 159: 160: void 161: say(pat,arg1,arg2,arg3) 162: char *pat; 163: long arg1,arg2,arg3; 164: { 165: fprintf(stderr, pat, arg1, arg2, arg3); 166: Fflush(stderr); 167: } 168: 169: /* Terminal output, pun intended. */ 170: 171: void /* very void */ 172: fatal(pat,arg1,arg2,arg3) 173: char *pat; 174: long arg1,arg2,arg3; 175: { 176: void my_exit(); 177: 178: say(pat, arg1, arg2, arg3); 179: my_exit(1); 180: } 181: 182: /* Get a response from the user, somehow or other. */ 183: 184: void 185: ask(pat,arg1,arg2,arg3) 186: char *pat; 187: long arg1,arg2,arg3; 188: { 189: int ttyfd; 190: int r; 191: bool tty2 = isatty(2); 192: 193: Sprintf(buf, pat, arg1, arg2, arg3); 194: Fflush(stderr); 195: write(2, buf, strlen(buf)); 196: if (tty2) { /* might be redirected to a file */ 197: r = read(2, buf, sizeof buf); 198: } 199: else if (isatty(1)) { /* this may be new file output */ 200: Fflush(stdout); 201: write(1, buf, strlen(buf)); 202: r = read(1, buf, sizeof buf); 203: } 204: else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) { 205: /* might be deleted or unwriteable */ 206: write(ttyfd, buf, strlen(buf)); 207: r = read(ttyfd, buf, sizeof buf); 208: Close(ttyfd); 209: } 210: else if (isatty(0)) { /* this is probably patch input */ 211: Fflush(stdin); 212: write(0, buf, strlen(buf)); 213: r = read(0, buf, sizeof buf); 214: } 215: else { /* no terminal at all--default it */ 216: buf[0] = '\n'; 217: r = 1; 218: } 219: if (r <= 0) 220: buf[0] = 0; 221: else 222: buf[r] = '\0'; 223: if (!tty2) 224: say1(buf); 225: } 226: #endif /* lint */ 227: 228: /* How to handle certain events when not in a critical region. */ 229: 230: void 231: set_signals(reset) 232: int reset; 233: { 234: void my_exit(); 235: #ifndef lint 236: #ifdef VOIDSIG 237: static void (*hupval)(),(*intval)(); 238: #else 239: static int (*hupval)(),(*intval)(); 240: #endif 241: 242: if (!reset) { 243: hupval = signal(SIGHUP, SIG_IGN); 244: if (hupval != SIG_IGN) 245: hupval = my_exit; 246: intval = signal(SIGINT, SIG_IGN); 247: if (intval != SIG_IGN) 248: intval = my_exit; 249: } 250: Signal(SIGHUP, hupval); 251: Signal(SIGINT, intval); 252: #endif 253: } 254: 255: /* How to handle certain events when in a critical region. */ 256: 257: void 258: ignore_signals() 259: { 260: #ifndef lint 261: Signal(SIGHUP, SIG_IGN); 262: Signal(SIGINT, SIG_IGN); 263: #endif 264: } 265: 266: /* Make sure we'll have the directories to create a file. */ 267: 268: void 269: makedirs(filename,striplast) 270: Reg1 char *filename; 271: bool striplast; 272: { 273: char tmpbuf[256]; 274: Reg2 char *s = tmpbuf; 275: char *dirv[20]; 276: Reg3 int i; 277: Reg4 int dirvp = 0; 278: 279: while (*filename) { 280: if (*filename == '/') { 281: filename++; 282: dirv[dirvp++] = s; 283: *s++ = '\0'; 284: } 285: else { 286: *s++ = *filename++; 287: } 288: } 289: *s = '\0'; 290: dirv[dirvp] = s; 291: if (striplast) 292: dirvp--; 293: if (dirvp < 0) 294: return; 295: strcpy(buf, "mkdir"); 296: s = buf; 297: for (i=0; i<=dirvp; i++) { 298: while (*s) s++; 299: *s++ = ' '; 300: strcpy(s, tmpbuf); 301: *dirv[i] = '/'; 302: } 303: system(buf); 304: } 305: 306: /* Make filenames more reasonable. */ 307: 308: char * 309: fetchname(at,strip_leading,assume_exists) 310: char *at; 311: int strip_leading; 312: int assume_exists; 313: { 314: char *s; 315: char *name; 316: Reg1 char *t; 317: char tmpbuf[200]; 318: 319: if (!at) 320: return Nullch; 321: s = savestr(at); 322: for (t=s; isspace(*t); t++) ; 323: name = t; 324: #ifdef DEBUGGING 325: if (debug & 128) 326: say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); 327: #endif 328: if (strnEQ(name, "/dev/null", 9)) /* so files can be created by diffing */ 329: return Nullch; /* against /dev/null. */ 330: for (; *t && !isspace(*t); t++) 331: if (*t == '/') 332: if (--strip_leading >= 0) 333: name = t+1; 334: *t = '\0'; 335: if (name != s && *s != '/') { 336: name[-1] = '\0'; 337: if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) { 338: name[-1] = '/'; 339: name=s; 340: } 341: } 342: name = savestr(name); 343: Sprintf(tmpbuf, "RCS/%s", name); 344: free(s); 345: if (stat(name, &filestat) < 0 && !assume_exists) { 346: Strcat(tmpbuf, RCSSUFFIX); 347: if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) { 348: Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name); 349: if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) { 350: free(name); 351: name = Nullch; 352: } 353: } 354: } 355: return name; 356: }