aboutsummaryrefslogtreecommitdiff
path: root/contrib/bootlog.h
blob: 967ed6d0efb8273b7766f1a2ffe818d14da5c764 (plain)
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);
}