15 typedef struct Msg Msg;
29 cwrite(int fd, char *path, char *cmd, int len)
31 if (write(fd, cmd, len) < len) {
32 fprint(2, "cwrite: %s: failed %d bytes: %r\n", path, len);
41 int cfd, tfd, forking = 0, pid, newpid;
45 pid = (int)(uintptr)v;
46 ctl = smprint("/proc/%d/ctl", pid);
47 if ((cfd = open(ctl, OWRITE)) < 0)
48 die(smprint("%s: %r", ctl));
49 truss = smprint("/proc/%d/syscall", pid);
50 if ((tfd = open(truss, OREAD)) < 0)
51 die(smprint("%s: %r", truss));
53 cwrite(cfd, ctl, "stop", 4);
54 cwrite(cfd, truss, "startsyscall", 12);
56 s = mallocz(sizeof(Msg) + Bufsize, 1);
58 s->buf = (char *)&s[1];
59 while(pread(tfd, s->buf, Bufsize - 1, 0) > 0){
60 if (forking && s->buf[1] == '=' && s->buf[3] != '-') {
62 newpid = strtol(&s->buf[3], 0, 0);
63 sendp(forkc, (void*)newpid);
64 procrfork(reader, (void*)newpid, Stacksize, 0);
68 * There are three tests here and they (I hope) guarantee
71 if (strstr(s->buf, " Rfork") != nil) {
76 if (tokenize(rf, a, 8) == 5) {
79 flags = strtoul(a[4], 0, 16);
86 cwrite(cfd, truss, "startsyscall", 12);
87 s = mallocz(sizeof(Msg) + Bufsize, 1);
89 s->buf = (char *)&s[1];
102 lastpid = (int)(uintptr)arg;
123 if(s->pid != lastpid){
125 fprint(2, s->buf[1]=='='? "\n%d ...": "\n", lastpid);
127 fprint(2, "%s", s->buf);
141 fprint(2, "Usage: ratrace [-c cmd [arg...]] | [pid]\n");
146 threadmain(int argc, char **argv)
153 * don't bother with fancy arg processing, because it picks up options
154 * for the command you are starting. Just check for -c as argv[1]
155 * and then take it from there.
159 if (argv[1][0] == '-')
164 cmd = strdup(argv[2]);
175 sysfatal("fork failed: %r");
179 exec(smprint("/bin/%s", cmd), args);
180 sysfatal("exec %s failed: %r", cmd);
188 out = chancreate(sizeof(char*), 0);
189 quit = chancreate(sizeof(char*), 0);
190 forkc = chancreate(sizeof(ulong *), 0);
192 procrfork(writer, (void*)pid, Stacksize, 0);