]>
diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/miscellany/patch-2.0.12u8/util.c
5 #include "backupfile.h"
10 private_strerror (errnum
)
13 extern char *sys_errlist
[];
16 if (errnum
> 0 && errnum
<= sys_nerr
)
17 return sys_errlist
[errnum
];
18 return "Unknown system error";
20 #define strerror private_strerror
22 /* Rename a file, copying it if necessary. */
38 say2("Moving %s to stdout.\n", from
);
40 fromfd
= open(from
, 0);
42 pfatal2("internal error, can't reopen %s", from
);
43 while ((i
=read(fromfd
, buf
, sizeof buf
)) > 0)
44 if (write(1, buf
, i
) != 1)
45 pfatal1("write failed");
51 Strcpy(bakname
, origprae
);
55 char *backupname
= find_backup_file_name(to
);
56 if (backupname
== (char *) 0)
57 fatal1("out of memory\n");
58 Strcpy(bakname
, backupname
);
62 Strcat(bakname
, simple_backup_suffix
);
66 if (stat(to
, &filestat
) == 0) { /* output file exists */
67 dev_t to_device
= filestat
.st_dev
;
68 ino_t to_inode
= filestat
.st_ino
;
69 char *simplename
= bakname
;
71 for (s
=bakname
; *s
; s
++) {
75 /* Find a backup name that is not the same file.
76 Change the first lowercase char into uppercase;
77 if that isn't sufficient, chop off the first char and try again. */
78 while (stat(bakname
, &filestat
) == 0 &&
79 to_device
== filestat
.st_dev
&& to_inode
== filestat
.st_ino
) {
80 /* Skip initial non-lowercase chars. */
81 for (s
=simplename
; *s
&& !islower(*s
); s
++) ;
85 Strcpy(simplename
, simplename
+1);
87 while (unlink(bakname
) >= 0) ; /* while() is for benefit of Eunice */
90 say3("Moving %s to %s.\n", to
, bakname
);
92 if (link(to
, bakname
) < 0) {
93 /* Maybe `to' is a symlink into a different file system.
94 Copying replaces the symlink with a file; using rename
99 bakfd
= creat(bakname
, 0666);
101 say4("Can't backup %s, output is in %s: %s\n", to
, from
,
107 pfatal2("internal error, can't open %s", to
);
108 while ((i
=read(tofd
, buf
, sizeof buf
)) > 0)
109 if (write(bakfd
, buf
, i
) != i
)
110 pfatal1("write failed");
114 while (unlink(to
) >= 0) ;
118 say3("Moving %s to %s.\n", from
, to
);
120 if (link(from
, to
) < 0) { /* different file system? */
123 tofd
= creat(to
, 0666);
125 say4("Can't create %s, output is in %s: %s\n",
126 to
, from
, strerror(errno
));
129 fromfd
= open(from
, 0);
131 pfatal2("internal error, can't reopen %s", from
);
132 while ((i
=read(fromfd
, buf
, sizeof buf
)) > 0)
133 if (write(tofd
, buf
, i
) != i
)
134 pfatal1("write failed");
152 tofd
= creat(to
, 0666);
154 pfatal2("can't create %s", to
);
155 fromfd
= open(from
, 0);
157 pfatal2("internal error, can't reopen %s", from
);
158 while ((i
=read(fromfd
, buf
, sizeof buf
)) > 0)
159 if (write(tofd
, buf
, i
) != i
)
160 pfatal2("write to %s failed", to
);
165 /* Allocate a unique area for a string. */
178 rv
= malloc((MEM
) (t
- s
));
183 fatal1("out of memory\n");
192 #if defined(lint) && defined(CANVARARG)
195 say(pat
) char *pat
; { ; }
197 fatal(pat
) char *pat
; { ; }
199 pfatal(pat
) char *pat
; { ; }
201 ask(pat
) char *pat
; { ; }
205 /* Vanilla terminal output (buffered). */
208 say(pat
,arg1
,arg2
,arg3
)
212 fprintf(stderr
, pat
, arg1
, arg2
, arg3
);
216 /* Terminal output, pun intended. */
219 fatal(pat
,arg1
,arg2
,arg3
)
223 fprintf(stderr
, "patch: **** ");
224 fprintf(stderr
, pat
, arg1
, arg2
, arg3
);
228 /* Say something from patch, something from the system, then silence . . . */
231 pfatal(pat
,arg1
,arg2
,arg3
)
237 fprintf(stderr
, "patch: **** ");
238 fprintf(stderr
, pat
, arg1
, arg2
, arg3
);
239 fprintf(stderr
, ": %s\n", strerror(errnum
));
243 /* Get a response from the user, somehow or other. */
246 ask(pat
,arg1
,arg2
,arg3
)
252 bool tty2
= isatty(2);
254 Sprintf(buf
, pat
, arg1
, arg2
, arg3
);
256 write(2, buf
, strlen(buf
));
257 if (tty2
) { /* might be redirected to a file */
258 r
= read(2, buf
, sizeof buf
);
260 else if (isatty(1)) { /* this may be new file output */
262 write(1, buf
, strlen(buf
));
263 r
= read(1, buf
, sizeof buf
);
265 else if ((ttyfd
= open("/dev/tty", 2)) >= 0 && isatty(ttyfd
)) {
266 /* might be deleted or unwriteable */
267 write(ttyfd
, buf
, strlen(buf
));
268 r
= read(ttyfd
, buf
, sizeof buf
);
271 else if (isatty(0)) { /* this is probably patch input */
273 write(0, buf
, strlen(buf
));
274 r
= read(0, buf
, sizeof buf
);
276 else { /* no terminal at all--default it */
289 /* How to handle certain events when not in a critical region. */
297 static void (*hupval
)(),(*intval
)();
299 static int (*hupval
)(),(*intval
)();
303 hupval
= signal(SIGHUP
, SIG_IGN
);
304 if (hupval
!= SIG_IGN
)
308 hupval
= (int(*)())my_exit
;
310 intval
= signal(SIGINT
, SIG_IGN
);
311 if (intval
!= SIG_IGN
)
315 intval
= (int(*)())my_exit
;
318 Signal(SIGHUP
, hupval
);
319 Signal(SIGINT
, intval
);
323 /* How to handle certain events when in a critical region. */
329 Signal(SIGHUP
, SIG_IGN
);
330 Signal(SIGINT
, SIG_IGN
);
334 /* Make sure we'll have the directories to create a file.
335 If `striplast' is TRUE, ignore the last element of `filename'. */
338 makedirs(filename
,striplast
)
343 Reg2
char *s
= tmpbuf
;
344 char *dirv
[20]; /* Point to the NULs between elements. */
346 Reg4
int dirvp
= 0; /* Number of finished entries in dirv. */
348 /* Copy `filename' into `tmpbuf' with a NUL instead of a slash
349 between the directories. */
351 if (*filename
== '/') {
367 strcpy(buf
, "mkdir");
369 for (i
=0; i
<=dirvp
; i
++) {
372 if (stat(tmpbuf
, &sbuf
) && errno
== ENOENT
) {
383 /* Make filenames more reasonable. */
386 fetchname(at
,strip_leading
,assume_exists
)
395 int sleading
= strip_leading
;
403 say4("fetchname %s %d %d\n",at
,strip_leading
,assume_exists
);
405 if (strnEQ(at
, "/dev/null", 9)) /* so files can be created by diffing */
406 return Nullch
; /* against /dev/null. */
407 name
= fullname
= t
= savestr(at
);
409 /* Strip off up to `sleading' leading slashes and null terminate. */
410 for (; *t
&& !isspace(*t
); t
++)
416 /* If no -p option was given (957 is the default value!),
417 we were given a relative pathname,
418 and the leading directories that we just stripped off all exist,
420 if (strip_leading
== 957 && name
!= fullname
&& *fullname
!= '/') {
422 if (stat(fullname
, &filestat
) == 0 && S_ISDIR (filestat
.st_mode
)) {
428 name
= savestr(name
);
431 if (stat(name
, &filestat
) && !assume_exists
) {
432 char *filebase
= basename(name
);
433 int pathlen
= filebase
- name
;
435 /* Put any leading path into `tmpbuf'. */
436 strncpy(tmpbuf
, name
, pathlen
);
438 #define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
439 if ( try("RCS/%s%s", filebase
, RCSSUFFIX
)
440 || try("RCS/%s" , filebase
, 0)
441 || try( "%s%s", filebase
, RCSSUFFIX
)
442 || try("SCCS/%s%s", SCCSPREFIX
, filebase
)
443 || try( "%s%s", SCCSPREFIX
, filebase
))