1570af302Sopenharmony_ci#include <stdlib.h> 2570af302Sopenharmony_ci#include <string.h> 3570af302Sopenharmony_ci#include <errno.h> 4570af302Sopenharmony_ci#include <signal.h> 5570af302Sopenharmony_ci#include <time.h> 6570af302Sopenharmony_ci#include <sys/types.h> 7570af302Sopenharmony_ci#include <sys/wait.h> 8570af302Sopenharmony_ci#include <sys/time.h> 9570af302Sopenharmony_ci#include <sys/resource.h> 10570af302Sopenharmony_ci#include <unistd.h> 11570af302Sopenharmony_ci#include "test.h" 12570af302Sopenharmony_ci 13570af302Sopenharmony_cistatic void handler(int s) 14570af302Sopenharmony_ci{ 15570af302Sopenharmony_ci} 16570af302Sopenharmony_ci 17570af302Sopenharmony_cistatic int start(char *wrap, char *argv[]) 18570af302Sopenharmony_ci{ 19570af302Sopenharmony_ci int pid; 20570af302Sopenharmony_ci 21570af302Sopenharmony_ci pid = fork(); 22570af302Sopenharmony_ci if (pid == 0) { 23570af302Sopenharmony_ci t_setrlim(RLIMIT_STACK, 100*1024); 24570af302Sopenharmony_ci if (*wrap) { 25570af302Sopenharmony_ci argv--; 26570af302Sopenharmony_ci argv[0] = wrap; 27570af302Sopenharmony_ci } 28570af302Sopenharmony_ci execv(argv[0], argv); 29570af302Sopenharmony_ci t_error("%s exec failed: %s\n", argv[0], strerror(errno)); 30570af302Sopenharmony_ci exit(1); 31570af302Sopenharmony_ci } 32570af302Sopenharmony_ci return pid; 33570af302Sopenharmony_ci} 34570af302Sopenharmony_ci 35570af302Sopenharmony_cistatic void usage(char *argv[]) 36570af302Sopenharmony_ci{ 37570af302Sopenharmony_ci t_error("usage: %s [-t timeoutsec] [-w wrapcmd] cmd [args..]\n", argv[0]); 38570af302Sopenharmony_ci exit(-1); 39570af302Sopenharmony_ci} 40570af302Sopenharmony_ci 41570af302Sopenharmony_ciint main(int argc, char *argv[]) 42570af302Sopenharmony_ci{ 43570af302Sopenharmony_ci char *wrap = ""; 44570af302Sopenharmony_ci int timeoutsec = 5; 45570af302Sopenharmony_ci int timeout = 0; 46570af302Sopenharmony_ci int status; 47570af302Sopenharmony_ci sigset_t set; 48570af302Sopenharmony_ci int opt; 49570af302Sopenharmony_ci int pid; 50570af302Sopenharmony_ci 51570af302Sopenharmony_ci while ((opt = getopt(argc, argv, "w:t:")) != -1) { 52570af302Sopenharmony_ci switch (opt) { 53570af302Sopenharmony_ci case 'w': 54570af302Sopenharmony_ci wrap = optarg; 55570af302Sopenharmony_ci break; 56570af302Sopenharmony_ci case 't': 57570af302Sopenharmony_ci timeoutsec = atoi(optarg); 58570af302Sopenharmony_ci break; 59570af302Sopenharmony_ci default: 60570af302Sopenharmony_ci usage(argv); 61570af302Sopenharmony_ci } 62570af302Sopenharmony_ci } 63570af302Sopenharmony_ci if (optind >= argc) 64570af302Sopenharmony_ci usage(argv); 65570af302Sopenharmony_ci argv += optind; 66570af302Sopenharmony_ci sigemptyset(&set); 67570af302Sopenharmony_ci sigaddset(&set, SIGCHLD); 68570af302Sopenharmony_ci sigprocmask(SIG_BLOCK, &set, 0); 69570af302Sopenharmony_ci signal(SIGCHLD, handler); 70570af302Sopenharmony_ci pid = start(wrap, argv); 71570af302Sopenharmony_ci if (pid == -1) { 72570af302Sopenharmony_ci t_error("%s fork failed: %s\n", argv[0], strerror(errno)); 73570af302Sopenharmony_ci t_printf("FAIL %s [internal]\n", argv[0]); 74570af302Sopenharmony_ci return -1; 75570af302Sopenharmony_ci } 76570af302Sopenharmony_ci if (sigtimedwait(&set, 0, &(struct timespec){timeoutsec,0}) == -1) { 77570af302Sopenharmony_ci if (errno == EAGAIN) 78570af302Sopenharmony_ci timeout = 1; 79570af302Sopenharmony_ci else 80570af302Sopenharmony_ci t_error("%s sigtimedwait failed: %s\n", argv[0], strerror(errno)); 81570af302Sopenharmony_ci if (kill(pid, SIGKILL) == -1) 82570af302Sopenharmony_ci t_error("%s kill failed: %s\n", argv[0], strerror(errno)); 83570af302Sopenharmony_ci } 84570af302Sopenharmony_ci if (waitpid(pid, &status, 0) != pid) { 85570af302Sopenharmony_ci t_error("%s waitpid failed: %s\n", argv[0], strerror(errno)); 86570af302Sopenharmony_ci t_printf("FAIL %s [internal]\n", argv[0]); 87570af302Sopenharmony_ci return -1; 88570af302Sopenharmony_ci } 89570af302Sopenharmony_ci if (WIFEXITED(status)) { 90570af302Sopenharmony_ci if (WEXITSTATUS(status) == 0) 91570af302Sopenharmony_ci return t_status; 92570af302Sopenharmony_ci t_printf("FAIL %s [status %d]\n", argv[0], WEXITSTATUS(status)); 93570af302Sopenharmony_ci } else if (timeout) { 94570af302Sopenharmony_ci t_printf("FAIL %s [timed out]\n", argv[0]); 95570af302Sopenharmony_ci } else if (WIFSIGNALED(status)) { 96570af302Sopenharmony_ci t_printf("FAIL %s [signal %s]\n", argv[0], strsignal(WTERMSIG(status))); 97570af302Sopenharmony_ci } else 98570af302Sopenharmony_ci t_printf("FAIL %s [unknown]\n", argv[0]); 99570af302Sopenharmony_ci return 1; 100570af302Sopenharmony_ci} 101