source: trunk/minix/commands/patch/util.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 7.1 KB
Line 
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
8int
9move_file(from,to)
10char *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) != i)
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
99void
100copy_file(from,to)
101char *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
122char *
123savestr(s)
124Reg1 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 = (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");
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*/
150say(pat) char *pat; { ; }
151/*VARARGS ARGSUSED*/
152fatal(pat) char *pat; { ; }
153/*VARARGS ARGSUSED*/
154ask(pat) char *pat; { ; }
155
156#else
157
158/* Vanilla terminal output (buffered). */
159
160void
161say(pat,arg1,arg2,arg3)
162char *pat;
163long arg1,arg2,arg3;
164{
165 fprintf(stderr, pat, arg1, arg2, arg3);
166 Fflush(stderr);
167}
168
169/* Terminal output, pun intended. */
170
171void /* very void */
172fatal(pat,arg1,arg2,arg3)
173char *pat;
174long arg1,arg2,arg3;
175{
176 say(pat, arg1, arg2, arg3);
177 my_exit(1);
178}
179
180/* Get a response from the user, somehow or other. */
181
182void
183ask(pat,arg1,arg2,arg3)
184char *pat;
185long arg1,arg2,arg3;
186{
187 int ttyfd;
188 int r;
189 bool tty2 = isatty(2);
190
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);
196 }
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);
201 }
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);
207 }
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);
212 }
213 else { /* no terminal at all--default it */
214 buf[0] = '\n';
215 r = 1;
216 }
217 if (r <= 0)
218 buf[0] = 0;
219 else
220 buf[r] = '\0';
221 if (!tty2)
222 say1(buf);
223}
224#endif /* lint */
225
226/* How to handle certain events when not in a critical region. */
227
228void
229set_signals(reset)
230int reset;
231{
232#ifndef lint
233#ifdef VOIDSIG
234 static void (*hupval)(),(*intval)();
235#else
236 static int (*hupval)(),(*intval)();
237#endif
238
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
254 }
255 Signal(SIGHUP, hupval);
256 Signal(SIGINT, intval);
257#endif
258}
259
260/* How to handle certain events when in a critical region. */
261
262void
263ignore_signals()
264{
265#ifndef lint
266 Signal(SIGHUP, SIG_IGN);
267 Signal(SIGINT, SIG_IGN);
268#endif
269}
270
271/* Make sure we'll have the directories to create a file. */
272
273void
274makedirs(filename,striplast)
275Reg1 char *filename;
276bool striplast;
277{
278 char tmpbuf[256];
279 Reg2 char *s = tmpbuf;
280 char *dirv[20];
281 Reg3 int i;
282 Reg4 int dirvp = 0;
283
284 while (*filename) {
285 if (*filename == '/') {
286 filename++;
287 dirv[dirvp++] = s;
288 *s++ = '\0';
289 }
290 else {
291 *s++ = *filename++;
292 }
293 }
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] = '/';
307 }
308 system(buf);
309}
310
311/* Make filenames more reasonable. */
312
313char *
314fetchname(at,strip_leading,assume_exists)
315char *at;
316int strip_leading;
317int assume_exists;
318{
319 char *s;
320 char *name;
321 Reg1 char *t;
322 char tmpbuf[200];
323
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;
345 }
346 }
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;
357 }
358 }
359 }
360 return name;
361}
Note: See TracBrowser for help on using the repository browser.