1#define _GNU_SOURCE 2#include <unistd.h> 3#include <sys/wait.h> 4#include <errno.h> 5#include <string.h> 6#include "test.h" 7 8#define TEST(c, ...) ( (c) || (t_error(#c " failed: " __VA_ARGS__),0) ) 9 10static int w(pid_t pid) 11{ 12 int r, s; 13 r = waitpid(pid, &s, 0); 14 if (r == -1) 15 t_error("waitpid failed: %s\n", strerror(errno)); 16 else if (r != pid) 17 t_error("child pid was %d, waitpid returned %d\n", pid, r); 18 else 19 return s; 20 return -1; 21} 22 23static void test_exit(int code) 24{ 25 pid_t pid; 26 if((pid = vfork()) == 0) { 27 _exit(code); 28 t_error("exit failed: %s\n", strerror(errno)); 29 } 30 if (pid == -1) { 31 t_error("vfork failed: %s\n", strerror(errno)); 32 return; 33 } 34 int r = w(pid); 35 TEST(WIFEXITED(r), "child terminated abnormally\n"); 36 TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code); 37} 38 39static int sh(const char *cmd) 40{ 41 pid_t pid; 42 if((pid = vfork()) == 0) { 43 execl("/bin/sh", "/bin/sh", "-c", cmd, (char*)0); 44 t_error("execl failed: %s\n", strerror(errno)); 45 _exit(1); 46 } 47 if (pid == -1) { 48 t_error("vfork failed: %s\n", strerror(errno)); 49 return -1; 50 } 51 return w(pid); 52} 53 54static void test_shell_exit(const char *cmd, int code) 55{ 56 int r = sh(cmd); 57 TEST(WIFEXITED(r), "child terminated abnormally\n"); 58 TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code); 59} 60 61static void test_shell_kill(const char *cmd, int sig) 62{ 63 int r = sh(cmd); 64 TEST(WIFSIGNALED(r), "child did not get killed\n"); 65 TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig); 66} 67 68int main() { 69 test_exit(0); 70 test_exit(1); 71 test_shell_exit("exit 0", 0); 72 test_shell_exit("exit 1", 1); 73 test_shell_kill("kill -9 $$", 9); 74 return t_status; 75} 76