14 typedef struct Msg Msg;
20 typedef struct Reader Reader;
36 snprint(s->buf, sizeof(s->buf), " = %r\n");
47 cwrite(Reader *r, char *cmd)
49 if (write(r->cfd, cmd, strlen(cmd)) < 0)
56 int forking = 0, newpid;
60 r.pid = (int)(uintptr)v;
63 r.msg = s = mallocz(sizeof(Msg), 1);
64 snprint(s->buf, sizeof(s->buf), "/proc/%d/ctl", r.pid);
65 if ((r.cfd = open(s->buf, OWRITE)) < 0)
67 snprint(s->buf, sizeof(s->buf), "/proc/%d/syscall", r.pid);
68 if ((r.tfd = open(s->buf, OREAD)) < 0)
72 cwrite(&r, "startsyscall");
74 while(pread(r.tfd, s->buf, sizeof(s->buf)-1, 0) > 0){
75 if (forking && s->buf[1] == '=' && s->buf[3] != '-') {
77 newpid = strtol(&s->buf[3], 0, 0);
78 sendp(forkc, (void*)newpid);
79 procrfork(reader, (void*)newpid, Stacksize, 0);
83 * There are three tests here and they (I hope) guarantee
86 if (strstr(s->buf, " Rfork") != nil) {
91 if (tokenize(rf, a, 8) == 5) {
94 flags = strtoul(a[4], 0, 16);
103 r.msg = s = mallocz(sizeof(Msg), 1);
104 cwrite(&r, "startsyscall");
133 if(s->pid != lastpid){
140 fprint(2, "%d ...", lastpid);
159 fprint(2, "Usage: ratrace [-c cmd [arg...]] | [pid]\n");
160 threadexits("usage");
164 threadmain(int argc, char **argv)
171 * don't bother with fancy arg processing, because it picks up options
172 * for the command you are starting. Just check for -c as argv[1]
173 * and then take it from there.
177 if (argv[1][0] == '-')
182 cmd = strdup(argv[2]);
193 sysfatal("fork failed: %r");
195 write(open(smprint("/proc/%d/ctl", getpid()), OWRITE|OCEXEC), "hang", 4);
198 exec(smprint("/bin/%s", cmd), args);
199 sysfatal("exec %s failed: %r", cmd);
207 out = chancreate(sizeof(Msg*), 0);
208 quit = chancreate(sizeof(Msg*), 0);
209 forkc = chancreate(sizeof(void*), 0);
210 procrfork(reader, (void*)pid, Stacksize, 0);