avoid path search in runtest and make abs paths work
[libc-test] / src / common / runtest.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <signal.h>
5 #include <time.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <sys/time.h>
9 #include <sys/resource.h>
10 #include <unistd.h>
11 #include "test.h"
12
13 static void handler(int s)
14 {
15 }
16
17 static int start(char *wrap, char *argv[])
18 {
19         int pid;
20
21         pid = fork();
22         if (pid == 0) {
23                 t_setrlim(RLIMIT_STACK, 100*1024);
24                 if (*wrap) {
25                         argv--;
26                         argv[0] = wrap;
27                 }
28                 execv(argv[0], argv);
29                 t_error("%s exec failed: %s\n", argv[0], strerror(errno));
30                 exit(1);
31         }
32         return pid;
33 }
34
35 static void usage(char *argv[])
36 {
37         t_error("usage: %s [-t timeoutsec] [-w wrapcmd] cmd [args..]\n", argv[0]);
38         exit(-1);
39 }
40
41 int main(int argc, char *argv[])
42 {
43         char *wrap = "";
44         int timeoutsec = 5;
45         int timeout = 0;
46         int status;
47         sigset_t set;
48         int opt;
49         int pid;
50
51         while ((opt = getopt(argc, argv, "w:t:")) != -1) {
52                 switch (opt) {
53                 case 'w':
54                         wrap = optarg;
55                         break;
56                 case 't':
57                         timeoutsec = atoi(optarg);
58                         break;
59                 default:
60                         usage(argv);
61                 }
62         }
63         if (optind >= argc)
64                 usage(argv);
65         argv += optind;
66         sigemptyset(&set);
67         sigaddset(&set, SIGCHLD);
68         sigprocmask(SIG_BLOCK, &set, 0);
69         signal(SIGCHLD, handler);
70         pid = start(wrap, argv);
71         if (pid == -1) {
72                 t_error("%s fork failed: %s\n", argv[0], strerror(errno));
73                 t_printf("FAIL %s [internal]\n", argv[0]);
74                 return -1;
75         }
76         if (sigtimedwait(&set, 0, &(struct timespec){timeoutsec,0}) == -1) {
77                 if (errno == EAGAIN)
78                         timeout = 1;
79                 else
80                         t_error("%s sigtimedwait failed: %s\n", argv[0], strerror(errno));
81                 if (kill(pid, SIGKILL) == -1)
82                         t_error("%s kill failed: %s\n", argv[0], strerror(errno));
83         }
84         if (waitpid(pid, &status, 0) != pid) {
85                 t_error("%s waitpid failed: %s\n", argv[0], strerror(errno));
86                 t_printf("FAIL %s [internal]\n", argv[0]);
87                 return -1;
88         }
89         if (WIFEXITED(status)) {
90                 if (WEXITSTATUS(status) == 0)
91                         return t_status;
92                 t_printf("FAIL %s [status %d]\n", argv[0], WEXITSTATUS(status));
93         } else if (timeout) {
94                 t_printf("FAIL %s [timed out]\n", argv[0]);
95         } else if (WIFSIGNALED(status)) {
96                 t_printf("FAIL %s [signal %s]\n", argv[0], strsignal(WTERMSIG(status)));
97         } else
98                 t_printf("FAIL %s [unknown]\n", argv[0]);
99         return 1;
100 }