1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/* return -1 on error */
static int xx_write(int fd, void *buf, size_t len) {
char *x = buf;
ssize_t w;
while (len) {
w = write(fd, buf, len);
if (w <= 0) {
if (w < 0 && errno == EINTR) continue;
return -1;
}
x += w;
len -= w;
}
return 0;
}
/* return 0 if closed or error, -1 temporary error */
static int do_io(void *buf, int len) {
int r = read(0,buf,len);
if (r<0)
if (errno != EINTR) r = 0;
if (r>0) xx_write(1,buf,r);
return r;
}
static int mk_backup() {
if (flag_rename) {
if (rename(name, flag_rename) && errno != ENOENT) return -1;
flag_rename = 0;
}
return 0;
}
static void write2(char *s) { write(2,s,str_len(s)); }
int main(int argc, char **argv) {
unsigned long len=0;
int pid, pi[2];
for (;;) {
char *p;
argc--;
argv++;
if ((p=argv[0]) == 0 || *p != '-') break;
while (*++p)
switch (*p) {
case 'a': m |= O_APPEND; break;
case 't': m |= O_TRUNC; break;
case 'c': m |= O_CREAT; break;
case 'r': ++flag_rename; break;
case '2': ++flagstderr; break;
case '1': ++flagstdout; break;
default:
goto usage;
}
}
if (argc<3) {
usage:
write2("usage: bootlog [-12ctar] size logfile program args...\n");
_exit(1);
}
if (scan_ulong(argv[0], &len) == 0) goto usage;
if ((flagstderr | flagstdout) == 0) {
++flagstdout;
++flagstderr;
}
name=argv[1];
for (pid=0; pid<3; pid++)
if (fcntl(pid,F_GETFL,0) == -1) goto do_it;
if (pipe(pi)) goto do_it;
while ((pid=fork()) < 0);
if (pid==0) {
close(pi[1]);
while ((pid=fork()) < 0);
if (pid==0) {
dup2(pi[0],0);
close(pi[0]);
loop(len);
}
_exit(0);
} else {
close(pi[0]);
waitpid(pid, 0, 0);
if (flagstdout) { dup2(pi[1],1); }
if (flagstderr) { dup2(pi[1],2); }
close(pi[1]);
}
do_it:
argv += 2;
pathexec_run(argv[0], argv, environ);
write2("bootlog: ");
write2(argv[0]);
write2(": exec error\n");
_exit(127);
}
|