1*5132e16eSMark Johnston /*- 2*5132e16eSMark Johnston * Copyright (c) 2023 Klara, Inc. 3*5132e16eSMark Johnston * 4*5132e16eSMark Johnston * SPDX-License-Identifier: BSD-2-Clause 5*5132e16eSMark Johnston */ 6*5132e16eSMark Johnston 7*5132e16eSMark Johnston #include <sys/wait.h> 8*5132e16eSMark Johnston 9*5132e16eSMark Johnston #include <stdio.h> 10*5132e16eSMark Johnston #include <stdlib.h> 11*5132e16eSMark Johnston #include <unistd.h> 12*5132e16eSMark Johnston 13*5132e16eSMark Johnston #include <atf-c.h> 14*5132e16eSMark Johnston 15*5132e16eSMark Johnston static void 16*5132e16eSMark Johnston func_a(void) 17*5132e16eSMark Johnston { 18*5132e16eSMark Johnston if (write(STDOUT_FILENO, "a", 1) != 1) 19*5132e16eSMark Johnston _Exit(1); 20*5132e16eSMark Johnston } 21*5132e16eSMark Johnston 22*5132e16eSMark Johnston static void 23*5132e16eSMark Johnston func_b(void) 24*5132e16eSMark Johnston { 25*5132e16eSMark Johnston if (write(STDOUT_FILENO, "b", 1) != 1) 26*5132e16eSMark Johnston _Exit(1); 27*5132e16eSMark Johnston } 28*5132e16eSMark Johnston 29*5132e16eSMark Johnston static void 30*5132e16eSMark Johnston func_c(void) 31*5132e16eSMark Johnston { 32*5132e16eSMark Johnston if (write(STDOUT_FILENO, "c", 1) != 1) 33*5132e16eSMark Johnston _Exit(1); 34*5132e16eSMark Johnston } 35*5132e16eSMark Johnston 36*5132e16eSMark Johnston static void 37*5132e16eSMark Johnston child(void) 38*5132e16eSMark Johnston { 39*5132e16eSMark Johnston /* this will be received by the parent */ 40*5132e16eSMark Johnston printf("hello, "); 41*5132e16eSMark Johnston fflush(stdout); 42*5132e16eSMark Johnston /* this won't, because quick_exit() does not flush */ 43*5132e16eSMark Johnston printf("world"); 44*5132e16eSMark Johnston /* these will be called in reverse order, producing "abc" */ 45*5132e16eSMark Johnston if (at_quick_exit(func_c) != 0 || 46*5132e16eSMark Johnston at_quick_exit(func_b) != 0 || 47*5132e16eSMark Johnston at_quick_exit(func_a) != 0) 48*5132e16eSMark Johnston _Exit(1); 49*5132e16eSMark Johnston quick_exit(0); 50*5132e16eSMark Johnston } 51*5132e16eSMark Johnston 52*5132e16eSMark Johnston ATF_TC_WITHOUT_HEAD(quick_exit); 53*5132e16eSMark Johnston ATF_TC_BODY(quick_exit, tc) 54*5132e16eSMark Johnston { 55*5132e16eSMark Johnston char buf[100] = ""; 56*5132e16eSMark Johnston ssize_t len; 57*5132e16eSMark Johnston int p[2], wstatus = 0; 58*5132e16eSMark Johnston pid_t pid; 59*5132e16eSMark Johnston 60*5132e16eSMark Johnston ATF_REQUIRE(pipe(p) == 0); 61*5132e16eSMark Johnston pid = fork(); 62*5132e16eSMark Johnston if (pid == 0) { 63*5132e16eSMark Johnston if (dup2(p[1], STDOUT_FILENO) < 0) 64*5132e16eSMark Johnston _Exit(1); 65*5132e16eSMark Johnston (void)close(p[1]); 66*5132e16eSMark Johnston (void)close(p[0]); 67*5132e16eSMark Johnston child(); 68*5132e16eSMark Johnston _Exit(1); 69*5132e16eSMark Johnston } 70*5132e16eSMark Johnston ATF_REQUIRE_MSG(pid > 0, 71*5132e16eSMark Johnston "expect fork() to succeed"); 72*5132e16eSMark Johnston ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0), 73*5132e16eSMark Johnston "expect to collect child process"); 74*5132e16eSMark Johnston ATF_CHECK_EQ_MSG(0, wstatus, 75*5132e16eSMark Johnston "expect child to exit cleanly"); 76*5132e16eSMark Johnston ATF_CHECK_MSG((len = read(p[0], buf, sizeof(buf))) > 0, 77*5132e16eSMark Johnston "expect to receive output from child"); 78*5132e16eSMark Johnston ATF_CHECK_STREQ("hello, abc", buf); 79*5132e16eSMark Johnston } 80*5132e16eSMark Johnston 81*5132e16eSMark Johnston ATF_TP_ADD_TCS(tp) 82*5132e16eSMark Johnston { 83*5132e16eSMark Johnston ATF_TP_ADD_TC(tp, quick_exit); 84*5132e16eSMark Johnston return (atf_no_error()); 85*5132e16eSMark Johnston } 86