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