]> mj.ucw.cz Git - moe.git/blob - src/iwrapper.c
Detect selbstmort.
[moe.git] / src / iwrapper.c
1 /*
2  *      A Wrapper for Interactive Tests
3  *
4  *      (c) 2001 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <unistd.h>
14 #include <getopt.h>
15 #include <time.h>
16 #include <sys/wait.h>
17 #include <sys/user.h>
18 #include <sys/time.h>
19 #include <sys/ptrace.h>
20 #include <sys/signal.h>
21 #include <sys/sysinfo.h>
22 #include <sys/syscall.h>
23 #include <sys/resource.h>
24
25 #define NONRET __attribute__((noreturn))
26 #define UNUSED __attribute__((unused))
27
28 static void NONRET __attribute__((format(printf,1,2)))
29 die(char *msg, ...)
30 {
31   va_list args;
32   va_start(args, msg);
33   vfprintf(stderr, msg, args);
34   fputc('\n', stderr);
35   exit(1);
36 }
37
38 static void
39 copy(int fd)
40 {
41   char buf[4096];
42   int c;
43
44   while (c = read(fd, buf, sizeof(buf)))
45     write(2, buf, c);
46 }
47
48 int
49 main(int argc, char **argv)
50 {
51   int sep, nbox, nchk;
52   char **abox, **achk;
53   pid_t pbox, pchk;
54   int inpipe[2], outpipe[2], boxepipe[2], chkepipe[2];
55   int exited = 0, sbox, schk;
56
57   for (sep=1; sep < argc; sep++)
58     if (!strcmp(argv[sep], "@@"))
59       break;
60   if (sep >= argc - 1)
61     die("Usage: iwrapper <testee> @@ <tester>");
62   nbox = sep - 1;
63   abox = alloca((nbox+1) * sizeof(char *));
64   memcpy(abox, argv+1, nbox*sizeof(char *));
65   abox[nbox] = NULL;
66   nchk = argc - sep - 1;
67   achk = alloca((nchk+1) * sizeof(char *));
68   memcpy(achk, argv+sep+1, nchk*sizeof(char *));
69   achk[nchk] = NULL;
70
71   if (pipe(inpipe) < 0 ||
72       pipe(outpipe) < 0 ||
73       pipe(boxepipe) < 0 ||
74       pipe(chkepipe) < 0)
75     die("pipe: %m");
76
77   pbox = fork();
78   if (pbox < 0)
79     die("fork: %m");
80   if (!pbox)
81     {
82       close(inpipe[1]);
83       close(0);
84       dup(inpipe[0]);
85       close(inpipe[0]);
86       close(outpipe[0]);
87       close(1);
88       dup(outpipe[1]);
89       close(outpipe[1]);
90       close(boxepipe[0]);
91       close(2);
92       dup(boxepipe[1]);
93       close(boxepipe[1]);
94       close(chkepipe[0]);
95       close(chkepipe[1]);
96       execv(abox[0], abox);
97       die("exec: %m");
98     }
99
100   pchk = fork();
101   if (pchk < 0)
102     die("fork: %m");
103   if (!pchk)
104     {
105       close(inpipe[0]);
106       close(1);
107       dup(inpipe[1]);
108       close(inpipe[1]);
109       close(outpipe[1]);
110       close(0);
111       dup(outpipe[0]);
112       close(outpipe[0]);
113       close(chkepipe[0]);
114       close(2);
115       dup(chkepipe[1]);
116       close(chkepipe[1]);
117       close(boxepipe[0]);
118       close(boxepipe[1]);
119       execv(achk[0], achk);
120       die("exec: %m");
121     }
122
123   close(inpipe[0]);
124   close(inpipe[1]);
125   close(outpipe[0]);
126   close(outpipe[1]);
127   close(chkepipe[1]);
128   close(boxepipe[1]);
129
130   sbox = schk = 0;
131   while (exited != 3)
132     {
133       int st;
134       pid_t p = wait(&st);
135       if (p < 0)
136         die("wait: %m");
137       if (p == pbox)
138         {
139           exited |= 1;
140           sbox = st;
141         }
142       else if (p == pchk)
143         {
144           exited |= 2;
145           schk = st;
146         }
147       else
148         die("Unknown process %d died", p);
149     }
150
151   if (!WIFEXITED(sbox))
152     die("Sandbox fault, status=%x", sbox);
153   if (!WIFEXITED(schk) || WEXITSTATUS(schk) >= 100)
154     die("Checker fault, status=%x", schk);
155   if (WEXITSTATUS(sbox))
156     {
157       copy(boxepipe[0]);
158       copy(chkepipe[0]);
159       return 1;
160     }
161   else if (WEXITSTATUS(schk))
162     {
163       copy(chkepipe[0]);
164       copy(boxepipe[0]);
165       return 1;
166     }
167   copy(boxepipe[0]);
168   copy(chkepipe[0]);
169   return 0;
170 }