• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31  */
32 /**************************************************************
33  *
34  *    OS Testing - Silicon Graphics, Inc.
35  *
36  *    FUNCTION NAME     : forker
37  *			  background
38  *
39  *    FUNCTION TITLE    : fork desired number of copies of the current process
40  *			  fork a process and return control to caller
41  *
42  *    SYNOPSIS:
43  *      int forker(ncopies, mode, prefix)
44  *      int ncopies;
45  *	int mode;
46  *	char *prefix;
47  *
48  *	int background(prefix);
49  *	char *prefix;
50  *
51  *    AUTHOR            : Richard Logan
52  *
53  *    CO-PILOT(s)       : Dean Roehrich
54  *
55  *    INITIAL RELEASE   : UNICOS 8.0
56  *
57  *    DESIGN DESCRIPTION
58  *	The background function will do a fork of the current process.
59  *	The parent process will then exit, thus orphaning the
60  *	child process.  Doing this will not nice the child process
61  *	like executing a cmd in the background using "&" from the shell.
62  *	If the fork fails and prefix is not NULL, a error message is printed
63  *      to stderr and the process will exit with a value of errno.
64  *
65  *	The forker function will fork <ncopies> minus one copies
66  *	of the current process.  There are two modes in how the forks
67  *	will be done.  Mode 0 (default) will have all new processes
68  *	be childern of the parent process.    Using Mode 1,
69  *	the parent process will have one child and that child will
70  *	fork the next process, if necessary, and on and on.
71  *	The forker function will return the number of successful
72  *	forks.  This value will be different for the parent and each child.
73  *	Using mode 0, the parent will get the total number of successful
74  *	forks.  Using mode 1, the newest child will get the total number
75  *	of forks.  The parent will get a return value of 1.
76  *
77  *	The forker function also updates the global variables
78  *	Forker_pids[] and Forker_npids.  The Forker_pids array will
79  *      be updated to contain the pid of each new process.  The
80  *	Forker_npids variable contains the number of entries
81  *	in Forker_pids.  Note, not all processes will have
82  *	access to all pids via Forker_pids.  If using mode 0, only the
83  *	parent process and the last process will have all information.
84  *      If using mode 1, only the last child process will have all information.
85  *
86  *	If the prefix parameter is not NULL and the fork system call fails,
87  *      a error message will be printed to stderr.  The error message
88  *      the be preceeded with prefix string.  If prefix is NULL,
89  *      no error message is printed.
90  *
91  *    SPECIAL REQUIREMENTS
92  *	None.
93  *
94  *    UPDATE HISTORY
95  *      This should contain the description, author, and date of any
96  *      "interesting" modifications (i.e. info should helpful in
97  *      maintaining/enhancing this module).
98  *      username     description
99  *      ----------------------------------------------------------------
100  *	rrl	    This functions will first written during
101  *		the SFS testing days, 1993.
102  *
103  *    BUGS/LIMITATIONS
104  *     The child pids are stored in the fixed array, Forker_pids.
105  *     The array only has space for 4098 pids.  Only the first
106  *     4098 pids will be stored in the array.
107  *
108  **************************************************************/
109 
110 #include <stdio.h>
111 #include <errno.h>
112 #include <unistd.h>		/* fork, getpid, sleep */
113 #include <string.h>
114 #include <stdlib.h>		/* exit */
115 #include "forker.h"
116 
117 int Forker_pids[FORKER_MAX_PIDS];	/* holds pids of forked processes */
118 int Forker_npids = 0;		/* number of entries in Forker_pids */
119 
120 /***********************************************************************
121  *
122  * This function will fork and the parent will exit zero and
123  * the child will return.  This will orphan the returning process
124  * putting it in the background.
125  *
126  * Return Value
127  *   0 : if fork did not fail
128  *  !0 : if fork failed, the return value will be the errno.
129  ***********************************************************************/
background(char * prefix)130 int background(char *prefix)
131 {
132 	switch (fork()) {
133 	case -1:
134 		if (prefix != NULL)
135 			fprintf(stderr,
136 				"%s: In %s background(), fork() failed, errno:%d %s\n",
137 				prefix, __FILE__, errno, strerror(errno));
138 		exit(errno);
139 
140 	case 0:		/* child process */
141 		break;
142 
143 	default:
144 		exit(0);
145 	}
146 
147 	return 0;
148 
149 }				/* end of background */
150 
151 /***********************************************************************
152  * Forker will fork ncopies-1 copies of self.
153  *
154  ***********************************************************************/
forker(int ncopies,int mode,char * prefix)155 int forker(int ncopies,
156 	int mode,	/* 0 - all children of parent, 1 - only 1 direct child */
157 	char *prefix)	/* if ! NULL, an message will be printed to stderr */
158 			/* if fork fails. The prefix (program name) will */
159 			/* preceed the message */
160 {
161 	int cnt;
162 	int pid;
163 	static int ind = 0;
164 
165 	Forker_pids[ind] = 0;
166 
167 	for (cnt = 1; cnt < ncopies; cnt++) {
168 
169 		switch (mode) {
170 		case 1:	/* only 1 direct child */
171 			if ((pid = fork()) == -1) {
172 				if (prefix != NULL)
173 					fprintf(stderr,
174 						"%s: %s,forker(): fork() failed, errno:%d %s\n",
175 						prefix, __FILE__, errno,
176 						strerror(errno));
177 				return 0;
178 			}
179 			Forker_npids++;
180 
181 			switch (pid) {
182 			case 0:	/* child - continues the forking */
183 
184 				if (Forker_npids < FORKER_MAX_PIDS)
185 					Forker_pids[Forker_npids - 1] =
186 					    getpid();
187 				break;
188 
189 			default:	/* parent - stop the forking */
190 				if (Forker_npids < FORKER_MAX_PIDS)
191 					Forker_pids[Forker_npids - 1] = pid;
192 				return cnt - 1;
193 			}
194 
195 			break;
196 
197 		default:	/* all new processes are childern of parent */
198 			if ((pid = fork()) == -1) {
199 				if (prefix != NULL)
200 					fprintf(stderr,
201 						"%s: %s,forker(): fork() failed, errno:%d %s\n",
202 						prefix, __FILE__, errno,
203 						strerror(errno));
204 				return cnt - 1;
205 			}
206 			Forker_npids++;
207 
208 			switch (pid) {
209 			case 0:	/* child - stops the forking */
210 				if (Forker_npids < FORKER_MAX_PIDS)
211 					Forker_pids[Forker_npids - 1] =
212 					    getpid();
213 				return cnt;
214 
215 			default:	/* parent - continues the forking */
216 				if (Forker_npids < FORKER_MAX_PIDS)
217 					Forker_pids[Forker_npids - 1] = pid;
218 				break;
219 			}
220 			break;
221 		}
222 	}
223 
224 	if (Forker_npids < FORKER_MAX_PIDS)
225 		Forker_pids[Forker_npids] = 0;
226 	return cnt - 1;
227 
228 }				/* end of forker */
229 
230 #if UNIT_TEST
231 
232 /*
233  * The following is a unit test main for the background and forker
234  * functions.
235  */
236 
main(argc,argv)237 int main(argc, argv)
238 int argc;
239 char **argv;
240 {
241 	int ncopies = 1;
242 	int mode = 0;
243 	int ret;
244 	int ind;
245 
246 	if (argc == 1) {
247 		printf("Usage: %s ncopies [mode]\n", argv[0]);
248 		exit(1);
249 	}
250 
251 	if (sscanf(argv[1], "%i", &ncopies) != 1) {
252 		printf("%s: ncopies argument must be integer\n", argv[0]);
253 		exit(1);
254 	}
255 
256 	if (argc == 3)
257 		if (sscanf(argv[2], "%i", &mode) != 1) {
258 			printf("%s: mode argument must be integer\n", argv[0]);
259 			exit(1);
260 		}
261 
262 	printf("Starting Pid = %d\n", getpid());
263 	ret = background(argv[0]);
264 	printf("After background() ret:%d, pid = %d\n", ret, getpid());
265 
266 	ret = forker(ncopies, mode, argv[0]);
267 
268 	printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n",
269 	       ncopies, mode, argv[0], ret, getpid());
270 
271 	printf("%d My version of Forker_pids[],  Forker_npids = %d\n",
272 	       getpid(), Forker_npids);
273 
274 	for (ind = 0; ind < Forker_npids; ind++) {
275 		printf("%d ind:%-2d pid:%d\n", getpid(), ind, Forker_pids[ind]);
276 	}
277 
278 	sleep(30);
279 	exit(0);
280 }
281 
282 #endif /* UNIT_TEST */
283