blob: ad3ffbfe053d461713306e9edd36e2cae614d7b3 [file] [log] [blame]
whrb973f2b2000-05-05 19:34:50 +00001/*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
vapier45a8ba02009-07-20 10:59:32 +00003 *
whrb973f2b2000-05-05 19:34:50 +00004 * 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.
vapier45a8ba02009-07-20 10:59:32 +00007 *
whrb973f2b2000-05-05 19:34:50 +00008 * 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.
vapier45a8ba02009-07-20 10:59:32 +000011 *
whrb973f2b2000-05-05 19:34:50 +000012 * 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.
vapier45a8ba02009-07-20 10:59:32 +000018 *
whrb973f2b2000-05-05 19:34:50 +000019 * 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., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
vapier45a8ba02009-07-20 10:59:32 +000022 *
whrb973f2b2000-05-05 19:34:50 +000023 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
vapier45a8ba02009-07-20 10:59:32 +000025 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
whrb973f2b2000-05-05 19:34:50 +000030 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 */
32/**************************************************************
33 *
alaffincc2e5552000-07-27 17:13:18 +000034 * OS Testing - Silicon Graphics, Inc.
whrb973f2b2000-05-05 19:34:50 +000035 *
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 * extern int Forker_pids[];
52 * extern int Forker_npids;
53 *
54 * AUTHOR : Richard Logan
55 *
56 * CO-PILOT(s) : Dean Roehrich
57 *
58 * INITIAL RELEASE : UNICOS 8.0
59 *
60 * DESIGN DESCRIPTION
61 * The background function will do a fork of the current process.
62 * The parent process will then exit, thus orphaning the
63 * child process. Doing this will not nice the child process
64 * like executing a cmd in the background using "&" from the shell.
65 * If the fork fails and prefix is not NULL, a error message is printed
66 * to stderr and the process will exit with a value of errno.
67 *
68 * The forker function will fork <ncopies> minus one copies
69 * of the current process. There are two modes in how the forks
70 * will be done. Mode 0 (default) will have all new processes
71 * be childern of the parent process. Using Mode 1,
72 * the parent process will have one child and that child will
73 * fork the next process, if necessary, and on and on.
74 * The forker function will return the number of successful
75 * forks. This value will be different for the parent and each child.
76 * Using mode 0, the parent will get the total number of successful
77 * forks. Using mode 1, the newest child will get the total number
78 * of forks. The parent will get a return value of 1.
79 *
80 * The forker function also updates the global variables
81 * Forker_pids[] and Forker_npids. The Forker_pids array will
82 * be updated to contain the pid of each new process. The
83 * Forker_npids variable contains the number of entries
84 * in Forker_pids. Note, not all processes will have
85 * access to all pids via Forker_pids. If using mode 0, only the
86 * parent process and the last process will have all information.
87 * If using mode 1, only the last child process will have all information.
88 *
89 * If the prefix parameter is not NULL and the fork system call fails,
90 * a error message will be printed to stderr. The error message
91 * the be preceeded with prefix string. If prefix is NULL,
92 * no error message is printed.
93 *
94 * SPECIAL REQUIREMENTS
95 * None.
96 *
97 * UPDATE HISTORY
98 * This should contain the description, author, and date of any
99 * "interesting" modifications (i.e. info should helpful in
100 * maintaining/enhancing this module).
101 * username description
102 * ----------------------------------------------------------------
103 * rrl This functions will first written during
104 * the SFS testing days, 1993.
105 *
106 * BUGS/LIMITATIONS
107 * The child pids are stored in the fixed array, Forker_pids.
108 * The array only has space for 4098 pids. Only the first
109 * 4098 pids will be stored in the array.
110 *
111 **************************************************************/
112
113#include <stdio.h>
114#include <errno.h>
115#include <unistd.h> /* fork, getpid, sleep */
116#include <string.h>
nstrazd5d51ca2001-02-28 17:41:59 +0000117#include <stdlib.h> /* exit */
alaffincc2e5552000-07-27 17:13:18 +0000118#include "forker.h"
whrb973f2b2000-05-05 19:34:50 +0000119
alaffin489cc7f2000-07-31 21:51:51 +0000120int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */
alaffincc2e5552000-07-27 17:13:18 +0000121int Forker_npids=0; /* number of entries in Forker_pids */
whrb973f2b2000-05-05 19:34:50 +0000122
123/***********************************************************************
124 *
125 * This function will fork and the parent will exit zero and
126 * the child will return. This will orphan the returning process
alaffincc2e5552000-07-27 17:13:18 +0000127 * putting it in the background.
whrb973f2b2000-05-05 19:34:50 +0000128 *
129 * Return Value
130 * 0 : if fork did not fail
131 * !0 : if fork failed, the return value will be the errno.
132 ***********************************************************************/
133int
134background(prefix)
135char *prefix;
136{
137 switch (fork()) {
138 case -1:
139 if ( prefix != NULL )
140 fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n",
141 prefix, __FILE__, errno, strerror(errno));
142 exit(errno);
143
144 case 0: /* child process */
145 break;
146
vapier45a8ba02009-07-20 10:59:32 +0000147 default:
whrb973f2b2000-05-05 19:34:50 +0000148 exit(0);
149 }
150
151 return 0;
152
153} /* end of background */
154
155/***********************************************************************
vapier45a8ba02009-07-20 10:59:32 +0000156 * Forker will fork ncopies-1 copies of self.
157 *
whrb973f2b2000-05-05 19:34:50 +0000158 ***********************************************************************/
159int
160forker(ncopies, mode, prefix)
161int ncopies;
162int mode; /* 0 - all childern of parent, 1 - only 1 direct child */
163char *prefix; /* if ! NULL, an message will be printed to stderr */
164 /* if fork fails. The prefix (program name) will */
165 /* preceed the message */
166{
167 int cnt;
168 int pid;
169 static int ind = 0;
170
171 Forker_pids[ind]=0;
172
173 for ( cnt=1; cnt < ncopies; cnt++ ) {
174
175 switch ( mode ) {
176 case 1 : /* only 1 direct child */
177 if ( (pid = fork()) == -1 ) {
vapier45a8ba02009-07-20 10:59:32 +0000178 if ( prefix != NULL )
whrb973f2b2000-05-05 19:34:50 +0000179 fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
180 prefix, __FILE__, errno, strerror(errno));
181 return 0;
182 }
183 Forker_npids++;
vapier45a8ba02009-07-20 10:59:32 +0000184
whrb973f2b2000-05-05 19:34:50 +0000185 switch (pid ) {
186 case 0: /* child - continues the forking */
vapier45a8ba02009-07-20 10:59:32 +0000187
alaffin489cc7f2000-07-31 21:51:51 +0000188 if ( Forker_npids < FORKER_MAX_PIDS )
whrb973f2b2000-05-05 19:34:50 +0000189 Forker_pids[Forker_npids-1]=getpid();
190 break;
191
192 default: /* parent - stop the forking */
alaffin489cc7f2000-07-31 21:51:51 +0000193 if ( Forker_npids < FORKER_MAX_PIDS )
whrb973f2b2000-05-05 19:34:50 +0000194 Forker_pids[Forker_npids-1]=pid;
vapier45a8ba02009-07-20 10:59:32 +0000195 return cnt-1;
whrb973f2b2000-05-05 19:34:50 +0000196 }
197
198 break;
199
200 default : /* all new processes are childern of parent */
201 if ( (pid = fork()) == -1 ) {
vapier45a8ba02009-07-20 10:59:32 +0000202 if ( prefix != NULL )
whrb973f2b2000-05-05 19:34:50 +0000203 fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
204 prefix, __FILE__, errno, strerror(errno));
205 return cnt-1;
206 }
207 Forker_npids++;
vapier45a8ba02009-07-20 10:59:32 +0000208
whrb973f2b2000-05-05 19:34:50 +0000209 switch (pid ) {
210 case 0: /* child - stops the forking */
alaffin489cc7f2000-07-31 21:51:51 +0000211 if ( Forker_npids < FORKER_MAX_PIDS )
whrb973f2b2000-05-05 19:34:50 +0000212 Forker_pids[Forker_npids-1]=getpid();
vapier45a8ba02009-07-20 10:59:32 +0000213 return cnt;
whrb973f2b2000-05-05 19:34:50 +0000214
215 default: /* parent - continues the forking */
alaffin489cc7f2000-07-31 21:51:51 +0000216 if ( Forker_npids < FORKER_MAX_PIDS )
whrb973f2b2000-05-05 19:34:50 +0000217 Forker_pids[Forker_npids-1]=pid;
218 break;
219 }
220 break;
221 }
222 }
223
alaffin489cc7f2000-07-31 21:51:51 +0000224 if ( Forker_npids < FORKER_MAX_PIDS )
whrb973f2b2000-05-05 19:34:50 +0000225 Forker_pids[Forker_npids]=0;
226 return cnt-1;
227
228} /* end of forker */
229
230
231#if UNIT_TEST
232
233/*
234 * The following is a unit test main for the background and forker
235 * functions.
236 */
237
238int
239main(argc, argv)
240int argc;
241char **argv;
242{
243 int ncopies=1;
244 int mode=0;
245 int ret;
246 int ind;
247
248 if ( argc == 1 ) {
249 printf("Usage: %s ncopies [mode]\n", argv[0]);
250 exit(1);
251 }
252
253 if ( sscanf(argv[1], "%i", &ncopies) != 1 ) {
254 printf("%s: ncopies argument must be integer\n", argv[0]);
255 exit(1);
256 }
257
258 if ( argc == 3 )
259 if ( sscanf(argv[2], "%i", &mode) != 1 ) {
260 printf("%s: mode argument must be integer\n", argv[0]);
261 exit(1);
262 }
263
264 printf("Starting Pid = %d\n", getpid());
265 ret=background(argv[0]);
266 printf("After background() ret:%d, pid = %d\n", ret, getpid());
267
268 ret=forker(ncopies, mode, argv[0]);
269
vapier45a8ba02009-07-20 10:59:32 +0000270 printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n",
whrb973f2b2000-05-05 19:34:50 +0000271 ncopies, mode, argv[0], ret, getpid());
272
vapier45a8ba02009-07-20 10:59:32 +0000273 printf("%d My version of Forker_pids[], Forker_npids = %d\n",
whrb973f2b2000-05-05 19:34:50 +0000274 getpid(), Forker_npids);
275
276 for (ind=0; ind<Forker_npids; ind++){
277 printf("%d ind:%-2d pid:%d\n", getpid(), ind, Forker_pids[ind]);
278 }
vapier45a8ba02009-07-20 10:59:32 +0000279
whrb973f2b2000-05-05 19:34:50 +0000280 sleep(30);
281 exit(0);
282}
283
284#endif /* UNIT_TEST */