diff options
Diffstat (limited to 'contrib/bootlog.h')
| -rw-r--r-- | contrib/bootlog.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/contrib/bootlog.h b/contrib/bootlog.h new file mode 100644 index 0000000..967ed6d --- /dev/null +++ b/contrib/bootlog.h @@ -0,0 +1,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); +} |
