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: #ifdef VOIDSIG 177: void my_exit(); 178: #else 179: int my_exit(); 180: #endif 181: 182: say(pat, arg1, arg2, arg3); 183: my_exit(1); 184: } 185: 186: /* Get a response from the user, somehow or other. */ 187: 188: void 189: ask(pat,arg1,arg2,arg3) 190: char *pat; 191: long arg1,arg2,arg3; 192: { 193: int ttyfd; 194: int r; 195: bool tty2 = isatty(2); 196: 197: Sprintf(buf, pat, arg1, arg2, arg3); 198: Fflush(stderr); 199: write(2, buf, strlen(buf)); 200: if (tty2) { /* might be redirected to a file */ 201: r = read(2, buf, sizeof buf); 202: } 203: else if (isatty(1)) { /* this may be new file output */ 204: Fflush(stdout); 205: write(1, buf, strlen(buf)); 206: r = read(1, buf, sizeof buf); 207: } 208: else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) { 209: /* might be deleted or unwriteable */ 210: write(ttyfd, buf, strlen(buf)); 211: r = read(ttyfd, buf, sizeof buf); 212: Close(ttyfd); 213: } 214: else if (isatty(0)) { /* this is probably patch input */ 215: Fflush(stdin); 216: write(0, buf, strlen(buf)); 217: r = read(0, buf, sizeof buf); 218: } 219: else { /* no terminal at all--default it */ 220: buf[0] = '\n'; 221: r = 1; 222: } 223: if (r <= 0) 224: buf[0] = 0; 225: else 226: buf[r] = '\0'; 227: if (!tty2) 228: say1(buf); 229: } 230: #endif /* lint */ 231: 232: /* How to handle certain events when not in a critical region. */ 233: 234: void 235: set_signals(reset) 236: int reset; 237: { 238: #ifndef lint 239: #ifdef VOIDSIG 240: void my_exit(); 241: static void (*hupval)(),(*intval)(); 242: #else 243: int my_exit(); 244: static int (*hupval)(),(*intval)(); 245: #endif 246: 247: if (!reset) { 248: hupval = signal(SIGHUP, SIG_IGN); 249: if (hupval != SIG_IGN) 250: #ifdef VOIDSIG 251: hupval = my_exit; 252: #else 253: hupval = (int(*)())my_exit; 254: #endif 255: intval = signal(SIGINT, SIG_IGN); 256: if (intval != SIG_IGN) 257: #ifdef VOIDSIG 258: intval = my_exit; 259: #else 260: intval = (int(*)())my_exit; 261: #endif 262: } 263: Signal(SIGHUP, hupval); 264: Signal(SIGINT, intval); 265: #endif 266: } 267: 268: /* How to handle certain events when in a critical region. */ 269: 270: void 271: ignore_signals() 272: { 273: #ifndef lint 274: Signal(SIGHUP, SIG_IGN); 275: Signal(SIGINT, SIG_IGN); 276: #endif 277: } 278: 279: /* Make sure we'll have the directories to create a file. */ 280: 281: void 282: makedirs(filename,striplast) 283: Reg1 char *filename; 284: bool striplast; 285: { 286: char tmpbuf[256]; 287: Reg2 char *s = tmpbuf; 288: char *dirv[20]; 289: Reg3 int i; 290: Reg4 int dirvp = 0; 291: 292: while (*filename) { 293: if (*filename == '/') { 294: filename++; 295: dirv[dirvp++] = s; 296: *s++ = '\0'; 297: } 298: else { 299: *s++ = *filename++; 300: } 301: } 302: *s = '\0'; 303: dirv[dirvp] = s; 304: if (striplast) 305: dirvp--; 306: if (dirvp < 0) 307: return; 308: strcpy(buf, "mkdir"); 309: s = buf; 310: for (i=0; i<=dirvp; i++) { 311: while (*s) s++; 312: *s++ = ' '; 313: strcpy(s, tmpbuf); 314: *dirv[i] = '/'; 315: } 316: system(buf); 317: } 318: 319: /* Make filenames more reasonable. */ 320: 321: char * 322: fetchname(at,strip_leading,assume_exists) 323: char *at; 324: int strip_leading; 325: int assume_exists; 326: { 327: char *s; 328: char *name; 329: Reg1 char *t; 330: char tmpbuf[200]; 331: 332: if (!at) 333: return Nullch; 334: s = savestr(at); 335: for (t=s; isspace(*t); t++) ; 336: name = t; 337: #ifdef DEBUGGING 338: if (debug & 128) 339: say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); 340: #endif 341: if (strnEQ(name, "/dev/null", 9)) /* so files can be created by diffing */ 342: return Nullch; /* against /dev/null. */ 343: for (; *t && !isspace(*t); t++) 344: if (*t == '/') 345: if (--strip_leading >= 0) 346: name = t+1; 347: *t = '\0'; 348: if (name != s && *s != '/') { 349: name[-1] = '\0'; 350: if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) { 351: name[-1] = '/'; 352: name=s; 353: } 354: } 355: name = savestr(name); 356: Sprintf(tmpbuf, "RCS/%s", name); 357: free(s); 358: if (stat(name, &filestat) < 0 && !assume_exists) { 359: Strcat(tmpbuf, RCSSUFFIX); 360: if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) { 361: Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name); 362: if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) { 363: free(name); 364: name = Nullch; 365: } 366: } 367: } 368: return name; 369: }