forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / patch / util.c
blob48a18b961e331d41d862a9c952d25fc59b425f70
1 #include "EXTERN.h"
2 #include "common.h"
3 #include "INTERN.h"
4 #include "util.h"
6 /* Rename a file, copying it if necessary. */
8 int
9 move_file(from,to)
10 char *from, *to;
12 char bakname[512];
13 Reg1 char *s;
14 Reg2 int i;
15 Reg3 int fromfd;
17 /* to stdout? */
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) != i)
29 fatal1("patch: write failed\n");
30 Close(fromfd);
31 return 0;
34 if (origprae) {
35 Strcpy (bakname, origprae);
36 Strcat(bakname, to);
37 } else {
38 Strcpy(bakname, to);
39 Strcat(bakname, origext?origext:ORIGEXT);
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;
46 for (s=bakname; *s; s++) {
47 if (*s == '/')
48 simplename = s+1;
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);
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;
69 while (unlink(to) >= 0) ;
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;
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;
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);
93 Unlink(from);
94 return 0;
97 /* Copy a file. */
99 void
100 copy_file(from,to)
101 char *from, *to;
103 Reg3 int tofd;
104 Reg2 int fromfd;
105 Reg1 int i;
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);
120 /* Allocate a unique area for a string. */
122 char *
123 savestr(s)
124 Reg1 char *s;
126 Reg3 char *rv;
127 Reg2 char *t;
129 if (!s)
130 s = "Oops";
131 t = s;
132 while (*t++);
133 rv = (char *)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");
140 else {
141 t = rv;
142 while (*t++ = *s++);
144 return rv;
147 #if defined(lint) && defined(CANVARARG)
149 /*VARARGS ARGSUSED*/
150 say(pat) char *pat; { ; }
151 /*VARARGS ARGSUSED*/
152 fatal(pat) char *pat; { ; }
153 /*VARARGS ARGSUSED*/
154 ask(pat) char *pat; { ; }
156 #else
158 /* Vanilla terminal output (buffered). */
160 void
161 say(pat,arg1,arg2,arg3)
162 char *pat;
163 long arg1,arg2,arg3;
165 fprintf(stderr, pat, arg1, arg2, arg3);
166 Fflush(stderr);
169 /* Terminal output, pun intended. */
171 void /* very void */
172 fatal(pat,arg1,arg2,arg3)
173 char *pat;
174 long arg1,arg2,arg3;
176 say(pat, arg1, arg2, arg3);
177 my_exit(1);
180 /* Get a response from the user, somehow or other. */
182 void
183 ask(pat,arg1,arg2,arg3)
184 char *pat;
185 long arg1,arg2,arg3;
187 int ttyfd;
188 int r;
189 bool tty2 = isatty(2);
191 Sprintf(buf, pat, arg1, arg2, arg3);
192 Fflush(stderr);
193 write(2, buf, strlen(buf));
194 if (tty2) { /* might be redirected to a file */
195 r = read(2, buf, sizeof buf);
197 else if (isatty(1)) { /* this may be new file output */
198 Fflush(stdout);
199 write(1, buf, strlen(buf));
200 r = read(1, buf, sizeof buf);
202 else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
203 /* might be deleted or unwriteable */
204 write(ttyfd, buf, strlen(buf));
205 r = read(ttyfd, buf, sizeof buf);
206 Close(ttyfd);
208 else if (isatty(0)) { /* this is probably patch input */
209 Fflush(stdin);
210 write(0, buf, strlen(buf));
211 r = read(0, buf, sizeof buf);
213 else { /* no terminal at all--default it */
214 buf[0] = '\n';
215 r = 1;
217 if (r <= 0)
218 buf[0] = 0;
219 else
220 buf[r] = '\0';
221 if (!tty2)
222 say1(buf);
224 #endif /* lint */
226 /* How to handle certain events when not in a critical region. */
228 void
229 set_signals(reset)
230 int reset;
232 #ifndef lint
233 #ifdef VOIDSIG
234 static void (*hupval)(),(*intval)();
235 #else
236 static int (*hupval)(),(*intval)();
237 #endif
239 if (!reset) {
240 hupval = signal(SIGHUP, SIG_IGN);
241 if (hupval != SIG_IGN)
242 #ifdef VOIDSIG
243 hupval = my_exit;
244 #else
245 hupval = (int(*)())my_exit;
246 #endif
247 intval = signal(SIGINT, SIG_IGN);
248 if (intval != SIG_IGN)
249 #ifdef VOIDSIG
250 intval = my_exit;
251 #else
252 intval = (int(*)())my_exit;
253 #endif
255 Signal(SIGHUP, hupval);
256 Signal(SIGINT, intval);
257 #endif
260 /* How to handle certain events when in a critical region. */
262 void
263 ignore_signals()
265 #ifndef lint
266 Signal(SIGHUP, SIG_IGN);
267 Signal(SIGINT, SIG_IGN);
268 #endif
271 /* Make sure we'll have the directories to create a file. */
273 void
274 makedirs(filename,striplast)
275 Reg1 char *filename;
276 bool striplast;
278 char tmpbuf[256];
279 Reg2 char *s = tmpbuf;
280 char *dirv[20];
281 Reg3 int i;
282 Reg4 int dirvp = 0;
284 while (*filename) {
285 if (*filename == '/') {
286 filename++;
287 dirv[dirvp++] = s;
288 *s++ = '\0';
290 else {
291 *s++ = *filename++;
294 *s = '\0';
295 dirv[dirvp] = s;
296 if (striplast)
297 dirvp--;
298 if (dirvp < 0)
299 return;
300 strcpy(buf, "mkdir");
301 s = buf;
302 for (i=0; i<=dirvp; i++) {
303 while (*s) s++;
304 *s++ = ' ';
305 strcpy(s, tmpbuf);
306 *dirv[i] = '/';
308 system(buf);
311 /* Make filenames more reasonable. */
313 char *
314 fetchname(at,strip_leading,assume_exists)
315 char *at;
316 int strip_leading;
317 int assume_exists;
319 char *s;
320 char *name;
321 Reg1 char *t;
322 char tmpbuf[200];
324 if (!at)
325 return Nullch;
326 s = savestr(at);
327 for (t=s; isspace(*t); t++) ;
328 name = t;
329 #ifdef DEBUGGING
330 if (debug & 128)
331 say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
332 #endif
333 if (strnEQ(name, "/dev/null", 9)) /* so files can be created by diffing */
334 return Nullch; /* against /dev/null. */
335 for (; *t && !isspace(*t); t++)
336 if (*t == '/')
337 if (--strip_leading >= 0)
338 name = t+1;
339 *t = '\0';
340 if (name != s && *s != '/') {
341 name[-1] = '\0';
342 if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
343 name[-1] = '/';
344 name=s;
347 name = savestr(name);
348 Sprintf(tmpbuf, "RCS/%s", name);
349 free(s);
350 if (stat(name, &filestat) < 0 && !assume_exists) {
351 Strcat(tmpbuf, RCSSUFFIX);
352 if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
353 Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
354 if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
355 free(name);
356 name = Nullch;
360 return name;