aboutsummaryrefslogtreecommitdiff
path: root/contrib/bootlog.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bootlog.h')
-rw-r--r--contrib/bootlog.h100
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);
+}