1570af302Sopenharmony_ci#define _GNU_SOURCE 2570af302Sopenharmony_ci#include <unistd.h> 3570af302Sopenharmony_ci#include <sys/wait.h> 4570af302Sopenharmony_ci#include <errno.h> 5570af302Sopenharmony_ci#include <string.h> 6570af302Sopenharmony_ci#include "test.h" 7570af302Sopenharmony_ci 8570af302Sopenharmony_ci#define TEST(c, ...) ( (c) || (t_error(#c " failed: " __VA_ARGS__),0) ) 9570af302Sopenharmony_ci 10570af302Sopenharmony_cistatic int w(pid_t pid) 11570af302Sopenharmony_ci{ 12570af302Sopenharmony_ci int r, s; 13570af302Sopenharmony_ci r = waitpid(pid, &s, 0); 14570af302Sopenharmony_ci if (r == -1) 15570af302Sopenharmony_ci t_error("waitpid failed: %s\n", strerror(errno)); 16570af302Sopenharmony_ci else if (r != pid) 17570af302Sopenharmony_ci t_error("child pid was %d, waitpid returned %d\n", pid, r); 18570af302Sopenharmony_ci else 19570af302Sopenharmony_ci return s; 20570af302Sopenharmony_ci return -1; 21570af302Sopenharmony_ci} 22570af302Sopenharmony_ci 23570af302Sopenharmony_cistatic void test_exit(int code) 24570af302Sopenharmony_ci{ 25570af302Sopenharmony_ci pid_t pid; 26570af302Sopenharmony_ci if((pid = vfork()) == 0) { 27570af302Sopenharmony_ci _exit(code); 28570af302Sopenharmony_ci t_error("exit failed: %s\n", strerror(errno)); 29570af302Sopenharmony_ci } 30570af302Sopenharmony_ci if (pid == -1) { 31570af302Sopenharmony_ci t_error("vfork failed: %s\n", strerror(errno)); 32570af302Sopenharmony_ci return; 33570af302Sopenharmony_ci } 34570af302Sopenharmony_ci int r = w(pid); 35570af302Sopenharmony_ci TEST(WIFEXITED(r), "child terminated abnormally\n"); 36570af302Sopenharmony_ci TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code); 37570af302Sopenharmony_ci} 38570af302Sopenharmony_ci 39570af302Sopenharmony_cistatic int sh(const char *cmd) 40570af302Sopenharmony_ci{ 41570af302Sopenharmony_ci pid_t pid; 42570af302Sopenharmony_ci if((pid = vfork()) == 0) { 43570af302Sopenharmony_ci execl("/bin/sh", "/bin/sh", "-c", cmd, (char*)0); 44570af302Sopenharmony_ci t_error("execl failed: %s\n", strerror(errno)); 45570af302Sopenharmony_ci _exit(1); 46570af302Sopenharmony_ci } 47570af302Sopenharmony_ci if (pid == -1) { 48570af302Sopenharmony_ci t_error("vfork failed: %s\n", strerror(errno)); 49570af302Sopenharmony_ci return -1; 50570af302Sopenharmony_ci } 51570af302Sopenharmony_ci return w(pid); 52570af302Sopenharmony_ci} 53570af302Sopenharmony_ci 54570af302Sopenharmony_cistatic void test_shell_exit(const char *cmd, int code) 55570af302Sopenharmony_ci{ 56570af302Sopenharmony_ci int r = sh(cmd); 57570af302Sopenharmony_ci TEST(WIFEXITED(r), "child terminated abnormally\n"); 58570af302Sopenharmony_ci TEST(WEXITSTATUS(r) == code, "child exited with %d, expected %d\n", WEXITSTATUS(r), code); 59570af302Sopenharmony_ci} 60570af302Sopenharmony_ci 61570af302Sopenharmony_cistatic void test_shell_kill(const char *cmd, int sig) 62570af302Sopenharmony_ci{ 63570af302Sopenharmony_ci int r = sh(cmd); 64570af302Sopenharmony_ci TEST(WIFSIGNALED(r), "child did not get killed\n"); 65570af302Sopenharmony_ci TEST(WTERMSIG(r) == sig, "child is killed by %d, expected %d\n", WTERMSIG(r), sig); 66570af302Sopenharmony_ci} 67570af302Sopenharmony_ci 68570af302Sopenharmony_ciint main() { 69570af302Sopenharmony_ci test_exit(0); 70570af302Sopenharmony_ci test_exit(1); 71570af302Sopenharmony_ci test_shell_exit("exit 0", 0); 72570af302Sopenharmony_ci test_shell_exit("exit 1", 1); 73570af302Sopenharmony_ci test_shell_kill("kill -9 $$", 9); 74570af302Sopenharmony_ci return t_status; 75570af302Sopenharmony_ci} 76