1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * NAME 22 * exit02.c 23 * 24 * DESCRIPTION 25 * Check that exit flushes output file buffers and closes files upon 26 * exitting 27 * 28 * ALGORITHM 29 * Fork a process that creates a file and writes a few bytes, and 30 * calls exit WITHOUT calling close(). The parent then reads the 31 * file. If everything that was written is present in the file, then 32 * the test passes. 33 * 34 * USAGE 35 * exit02 36 * 37 * HISTORY 38 * 07/2001 Ported by Wayne Boyer 39 * 40 * RESTRICTIONS 41 * None 42 */ 43 #include <sys/types.h> 44 #include <sys/wait.h> 45 #include <sys/stat.h> 46 #include <stdio.h> 47 #include <string.h> 48 #include <errno.h> 49 #include <signal.h> 50 #include <fcntl.h> 51 #include <string.h> 52 #include "test.h" 53 54 void cleanup(void); 55 void setup(void); 56 57 char *TCID = "exit02"; 58 int TST_TOTAL = 1; 59 60 #define READ 0 61 #define WRITE 1 62 #define MODE 0666 63 64 char filen[40]; 65 66 int main(int ac, char **av) 67 { 68 int pid, npid, sig, nsig, exno, nexno, status; 69 int filed; 70 char wbuf[BUFSIZ], rbuf[BUFSIZ]; 71 int len, rlen; 72 int rval = 0; 73 int lc; 74 75 /* 76 * parse standard options 77 */ 78 tst_parse_opts(ac, av, NULL, NULL); 79 80 setup(); /* global setup for test */ 81 82 /* 83 * The following loop checks looping state if -i option given 84 */ 85 for (lc = 0; TEST_LOOPING(lc); lc++) { 86 /* 87 * reset tst_count in case we are looping. 88 */ 89 tst_count = 0; 90 91 strcpy(wbuf, "abcd"); 92 len = strlen(wbuf); 93 94 exno = sig = 0; 95 96 if ((pid = FORK_OR_VFORK()) == -1) 97 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed"); 98 99 if (pid == 0) { /* child */ 100 sleep(1); 101 if ((filed = creat(filen, MODE)) == -1) { 102 tst_resm(TINFO, "creat error: unable to" 103 "open output file"); 104 exit(2); 105 } 106 if (write(filed, wbuf, len) != len) { 107 tst_resm(TINFO, "write error"); 108 exit(2); 109 } 110 exit(exno); 111 } else { /* parent */ 112 npid = wait(&status); 113 114 if (npid != pid) { 115 tst_resm(TFAIL, "wait error: " 116 "unexpected pid returned"); 117 rval = 1; 118 } 119 120 nsig = status % 256; 121 122 /* 123 * to check if the core dump bit has been 124 * set, bit # 7 125 */ 126 if (nsig >= 128) 127 nsig = nsig - 128; 128 129 /* 130 * nsig is the signal number returned by 131 * wait 132 */ 133 if (nsig != sig) { 134 tst_resm(TFAIL, "wait error: unexpected " 135 "signal returned %d", nsig); 136 rval = 1; 137 } 138 139 /* 140 * nexno is the exit number returned by wait 141 */ 142 nexno = status / 256; 143 if (nexno != exno) { 144 tst_resm(TFAIL, "wait error: unexpected exit " 145 "number %d", nexno); 146 rval = 1; 147 } 148 149 sleep(2); /* let child's exit close opened file */ 150 151 filed = open(filen, O_RDONLY, READ); 152 if (filed == -1) { 153 tst_resm(TFAIL, "open error: " 154 "unable to open input file"); 155 rval = 1; 156 } else { 157 rlen = read(filed, rbuf, len); 158 if (len != rlen) { 159 tst_resm(TFAIL, "exit error: file " 160 "buffer was not flushed"); 161 rval = 1; 162 } else if (strncmp(rbuf, wbuf, len) != 0) { 163 tst_resm(TFAIL, "exit error: file " 164 "buffer was not flushed"); 165 rval = 1; 166 } 167 } 168 close(filed); 169 unlink(filen); 170 } 171 if (!rval) { 172 tst_resm(TPASS, "exit() test PASSED"); 173 } 174 } 175 cleanup(); 176 tst_exit(); 177 } 178 179 /* 180 * setup() - perform all ONE TIME setup for this test 181 */ 182 void setup(void) 183 { 184 185 tst_sig(FORK, DEF_HANDLER, cleanup); 186 187 umask(0); 188 189 TEST_PAUSE; 190 191 tst_tmpdir(); 192 193 sprintf(filen, "tfile_%d", getpid()); 194 } 195 196 /* 197 * cleanup() - performs all ONE TIME cleanup for this test at completion or 198 * premature exit. 199 */ 200 void cleanup(void) 201 { 202 203 /* 204 * Remove tmp dir and all files in it 205 */ 206 tst_rmdir(); 207 208 /* 209 * exit with return code appropriate for results 210 */ 211 212 } 213