Home | History | Annotate | Download | only in setsid
      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  * 	setsid01.c
     23  *
     24  * DESCRIPTION
     25  * 	Test to check the error and trivial conditions in setsid system call
     26  *
     27  * USAGE
     28  * 	setsid01
     29  *
     30  * RESTRICTIONS
     31  * 	This test doesn't follow good LTP format - PLEASE FIX!
     32  */
     33 #include <wait.h>
     34 #include <limits.h>
     35 #include <signal.h>
     36 #include <errno.h>
     37 #include <unistd.h>
     38 #include <sys/param.h>
     39 #include <sys/types.h>
     40 #include <sys/stat.h>
     41 #include "test.h"
     42 
     43 #define INVAL_FLAG	-1
     44 #define USER2		301
     45 #define INVAL_MAXGRP	NGROUPS_MAX + 1
     46 #define INVAL_USER	999999
     47 #define INVAL_PID	999999
     48 
     49 char *TCID = "setsid01";
     50 int TST_TOTAL = 1;
     51 
     52 #ifdef UCLINUX
     53 static char *argv0;
     54 #endif
     55 
     56 void do_child_1(void);
     57 void do_child_2(void);
     58 void setup(void);
     59 void cleanup(void);
     60 
     61 int main(int ac, char **av)
     62 {
     63 	int pid;
     64 	int fail = 0;
     65 	int ret, status;
     66 	int exno = 0;
     67 
     68 	int lc;
     69 
     70 	tst_parse_opts(ac, av, NULL, NULL);
     71 #ifdef UCLINUX
     72 	argv0 = av[0];
     73 
     74 	maybe_run_child(&do_child_1, "n", 1);
     75 	maybe_run_child(&do_child_2, "n", 2);
     76 #endif
     77 
     78 	/*
     79 	 * perform global setup for the test
     80 	 */
     81 	setup();
     82 
     83 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     84 
     85 		/* reset tst_count in case we are looping */
     86 		tst_count = 0;
     87 
     88 		/*
     89 		 * When the process group having forked of a child
     90 		 * and then it attached itself to another process
     91 		 * group and tries to setsid
     92 		 */
     93 		pid = FORK_OR_VFORK();
     94 
     95 		if (pid == 0) {
     96 			if ((pid = FORK_OR_VFORK()) == -1) {
     97 				tst_resm(TFAIL, "Fork failed");
     98 
     99 			}
    100 			if (pid == 0) {
    101 #ifdef UCLINUX
    102 				if (self_exec(argv0, "n", 1) < 0) {
    103 					tst_resm(TFAIL, "self_exec failed");
    104 
    105 				}
    106 #else
    107 				do_child_1();
    108 #endif
    109 			} else {
    110 				if (setpgid(0, 0) < 0) {
    111 					tst_resm(TFAIL,
    112 						 "setpgid(parent) failed: %s",
    113 						 strerror(errno));
    114 					fail = 1;
    115 				}
    116 
    117 				if ((ret = wait(&status)) > 0) {
    118 					if (status != 0) {
    119 						tst_resm(TFAIL,
    120 							 "Test {%d} exited "
    121 							 "status 0x%0x (wanted 0x0)",
    122 							 ret, status);
    123 						fail = 1;
    124 					}
    125 				}
    126 			}
    127 			exit(0);
    128 		} else {
    129 			if ((ret = wait(&status)) > 0) {
    130 				if (status != 0) {
    131 					tst_resm(TFAIL, "Test {%d} exited "
    132 						 "status 0x%0x (wanted 0x0)",
    133 						 ret, status);
    134 					fail = 1;
    135 				}
    136 			}
    137 		}
    138 
    139 		if (!(fail || exno)) {
    140 			tst_resm(TPASS, "all misc tests passed");
    141 		}
    142 	}
    143 	cleanup();
    144 	tst_exit();
    145 
    146 }
    147 
    148 /*
    149  * do_child_1()
    150  */
    151 void do_child_1(void)
    152 {
    153 	int exno = 0;
    154 	int retval, ret, status;
    155 	int pid;
    156 
    157 	sleep(1);
    158 
    159 	if (setpgid(0, 0) < 0) {
    160 		tst_resm(TFAIL, "setpgid(0,0) failed: %s", strerror(errno));
    161 		exno = 1;
    162 	}
    163 
    164 	if ((pid = FORK_OR_VFORK()) == -1) {
    165 		tst_brkm(TFAIL, NULL, "Fork failed");
    166 	}
    167 	if (pid == 0) {
    168 #ifdef UCLINUX
    169 		if (self_exec(argv0, "n", 2) < 0) {
    170 			tst_brkm(TFAIL, NULL, "self_exec failed");
    171 		}
    172 #else
    173 		do_child_2();
    174 #endif
    175 	} else {
    176 		retval = setpgid(0, getppid());
    177 		if (retval < 0) {
    178 			tst_resm(TFAIL, "setpgid failed, errno :%d", errno);
    179 			exno = 2;
    180 		}
    181 
    182 		retval = setsid();
    183 
    184 		if (errno == EPERM) {
    185 			tst_resm(TPASS, "setsid SUCCESS to set "
    186 				 "errno to EPERM");
    187 		} else {
    188 			tst_resm(TFAIL, "setsid failed, expected %d,"
    189 				 "return %d", -1, errno);
    190 			exno = 3;
    191 		}
    192 		kill(pid, SIGKILL);
    193 		if ((ret = wait(&status)) > 0) {
    194 			if (status != 9) {
    195 				tst_resm(TFAIL,
    196 					 "Test {%d} exited status 0x%-x (wanted 0x9)",
    197 					 ret, status);
    198 				exno = 4;
    199 			}
    200 		}
    201 	}
    202 	exit(exno);
    203 }
    204 
    205 /*
    206  * do_child_2()
    207  */
    208 void do_child_2(void)
    209 {
    210 	for (;;) ;
    211 }
    212 
    213 /*
    214  * setup() - performs all ONE TIME setup for this test
    215  */
    216 void setup(void)
    217 {
    218 
    219 	tst_sig(FORK, DEF_HANDLER, cleanup);
    220 
    221 	umask(0);
    222 
    223 	TEST_PAUSE;
    224 }
    225 
    226 /*
    227  * cleanup() - performs all the ONE TIME cleanup for this test at completion
    228  * 	       or premature exit
    229  */
    230 void cleanup(void)
    231 {
    232 
    233 }
    234