blob: 5e6ac48a83d6e347c332cd35054861e0193dfbba [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
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 *
whrb973f2b2000-05-05 19:34:50 +000051 * 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>
Wanlong Gao354ebb42012-12-07 10:10:04 +0800112#include <unistd.h> /* fork, getpid, sleep */
whrb973f2b2000-05-05 19:34:50 +0000113#include <string.h>
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114#include <stdlib.h> /* exit */
alaffincc2e5552000-07-27 17:13:18 +0000115#include "forker.h"
whrb973f2b2000-05-05 19:34:50 +0000116
Wanlong Gao354ebb42012-12-07 10:10:04 +0800117int Forker_pids[FORKER_MAX_PIDS]; /* holds pids of forked processes */
118int Forker_npids = 0; /* number of entries in Forker_pids */
whrb973f2b2000-05-05 19:34:50 +0000119
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
alaffincc2e5552000-07-27 17:13:18 +0000124 * putting it in the background.
whrb973f2b2000-05-05 19:34:50 +0000125 *
126 * Return Value
127 * 0 : if fork did not fail
128 * !0 : if fork failed, the return value will be the errno.
129 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800130int background(prefix)
whrb973f2b2000-05-05 19:34:50 +0000131char *prefix;
132{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800133 switch (fork()) {
134 case -1:
135 if (prefix != NULL)
136 fprintf(stderr,
137 "%s: In %s background(), fork() failed, errno:%d %s\n",
138 prefix, __FILE__, errno, strerror(errno));
139 exit(errno);
whrb973f2b2000-05-05 19:34:50 +0000140
Wanlong Gao354ebb42012-12-07 10:10:04 +0800141 case 0: /* child process */
142 break;
whrb973f2b2000-05-05 19:34:50 +0000143
Wanlong Gao354ebb42012-12-07 10:10:04 +0800144 default:
145 exit(0);
146 }
whrb973f2b2000-05-05 19:34:50 +0000147
Wanlong Gao354ebb42012-12-07 10:10:04 +0800148 return 0;
whrb973f2b2000-05-05 19:34:50 +0000149
Wanlong Gao354ebb42012-12-07 10:10:04 +0800150} /* end of background */
whrb973f2b2000-05-05 19:34:50 +0000151
152/***********************************************************************
vapier45a8ba02009-07-20 10:59:32 +0000153 * Forker will fork ncopies-1 copies of self.
154 *
whrb973f2b2000-05-05 19:34:50 +0000155 ***********************************************************************/
Wanlong Gao354ebb42012-12-07 10:10:04 +0800156int forker(ncopies, mode, prefix)
whrb973f2b2000-05-05 19:34:50 +0000157int ncopies;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800158int mode; /* 0 - all childern of parent, 1 - only 1 direct child */
159char *prefix; /* if ! NULL, an message will be printed to stderr */
whrb973f2b2000-05-05 19:34:50 +0000160 /* if fork fails. The prefix (program name) will */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800161 /* preceed the message */
whrb973f2b2000-05-05 19:34:50 +0000162{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800163 int cnt;
164 int pid;
165 static int ind = 0;
whrb973f2b2000-05-05 19:34:50 +0000166
Wanlong Gao354ebb42012-12-07 10:10:04 +0800167 Forker_pids[ind] = 0;
whrb973f2b2000-05-05 19:34:50 +0000168
Wanlong Gao354ebb42012-12-07 10:10:04 +0800169 for (cnt = 1; cnt < ncopies; cnt++) {
whrb973f2b2000-05-05 19:34:50 +0000170
Wanlong Gao354ebb42012-12-07 10:10:04 +0800171 switch (mode) {
172 case 1: /* only 1 direct child */
173 if ((pid = fork()) == -1) {
174 if (prefix != NULL)
175 fprintf(stderr,
176 "%s: %s,forker(): fork() failed, errno:%d %s\n",
177 prefix, __FILE__, errno,
178 strerror(errno));
179 return 0;
180 }
181 Forker_npids++;
vapier45a8ba02009-07-20 10:59:32 +0000182
Wanlong Gao354ebb42012-12-07 10:10:04 +0800183 switch (pid) {
184 case 0: /* child - continues the forking */
vapier45a8ba02009-07-20 10:59:32 +0000185
Wanlong Gao354ebb42012-12-07 10:10:04 +0800186 if (Forker_npids < FORKER_MAX_PIDS)
187 Forker_pids[Forker_npids - 1] =
188 getpid();
189 break;
whrb973f2b2000-05-05 19:34:50 +0000190
Wanlong Gao354ebb42012-12-07 10:10:04 +0800191 default: /* parent - stop the forking */
192 if (Forker_npids < FORKER_MAX_PIDS)
193 Forker_pids[Forker_npids - 1] = pid;
194 return cnt - 1;
195 }
whrb973f2b2000-05-05 19:34:50 +0000196
Wanlong Gao354ebb42012-12-07 10:10:04 +0800197 break;
whrb973f2b2000-05-05 19:34:50 +0000198
Wanlong Gao354ebb42012-12-07 10:10:04 +0800199 default: /* all new processes are childern of parent */
200 if ((pid = fork()) == -1) {
201 if (prefix != NULL)
202 fprintf(stderr,
203 "%s: %s,forker(): fork() failed, errno:%d %s\n",
204 prefix, __FILE__, errno,
205 strerror(errno));
206 return cnt - 1;
207 }
208 Forker_npids++;
vapier45a8ba02009-07-20 10:59:32 +0000209
Wanlong Gao354ebb42012-12-07 10:10:04 +0800210 switch (pid) {
211 case 0: /* child - stops the forking */
212 if (Forker_npids < FORKER_MAX_PIDS)
213 Forker_pids[Forker_npids - 1] =
214 getpid();
215 return cnt;
whrb973f2b2000-05-05 19:34:50 +0000216
Wanlong Gao354ebb42012-12-07 10:10:04 +0800217 default: /* parent - continues the forking */
218 if (Forker_npids < FORKER_MAX_PIDS)
219 Forker_pids[Forker_npids - 1] = pid;
220 break;
221 }
222 break;
223 }
whrb973f2b2000-05-05 19:34:50 +0000224 }
whrb973f2b2000-05-05 19:34:50 +0000225
Wanlong Gao354ebb42012-12-07 10:10:04 +0800226 if (Forker_npids < FORKER_MAX_PIDS)
227 Forker_pids[Forker_npids] = 0;
228 return cnt - 1;
whrb973f2b2000-05-05 19:34:50 +0000229
Wanlong Gao354ebb42012-12-07 10:10:04 +0800230} /* end of forker */
whrb973f2b2000-05-05 19:34:50 +0000231
232#if UNIT_TEST
233
234/*
235 * The following is a unit test main for the background and forker
236 * functions.
237 */
238
Wanlong Gao354ebb42012-12-07 10:10:04 +0800239int main(argc, argv)
whrb973f2b2000-05-05 19:34:50 +0000240int argc;
241char **argv;
242{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800243 int ncopies = 1;
244 int mode = 0;
245 int ret;
246 int ind;
whrb973f2b2000-05-05 19:34:50 +0000247
Wanlong Gao354ebb42012-12-07 10:10:04 +0800248 if (argc == 1) {
249 printf("Usage: %s ncopies [mode]\n", argv[0]);
250 exit(1);
251 }
whrb973f2b2000-05-05 19:34:50 +0000252
Wanlong Gao354ebb42012-12-07 10:10:04 +0800253 if (sscanf(argv[1], "%i", &ncopies) != 1) {
254 printf("%s: ncopies argument must be integer\n", argv[0]);
255 exit(1);
256 }
whrb973f2b2000-05-05 19:34:50 +0000257
Wanlong Gao354ebb42012-12-07 10:10:04 +0800258 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 }
whrb973f2b2000-05-05 19:34:50 +0000263
Wanlong Gao354ebb42012-12-07 10:10:04 +0800264 printf("Starting Pid = %d\n", getpid());
265 ret = background(argv[0]);
266 printf("After background() ret:%d, pid = %d\n", ret, getpid());
whrb973f2b2000-05-05 19:34:50 +0000267
Wanlong Gao354ebb42012-12-07 10:10:04 +0800268 ret = forker(ncopies, mode, argv[0]);
whrb973f2b2000-05-05 19:34:50 +0000269
Wanlong Gao354ebb42012-12-07 10:10:04 +0800270 printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n",
271 ncopies, mode, argv[0], ret, getpid());
whrb973f2b2000-05-05 19:34:50 +0000272
Wanlong Gao354ebb42012-12-07 10:10:04 +0800273 printf("%d My version of Forker_pids[], Forker_npids = %d\n",
274 getpid(), Forker_npids);
whrb973f2b2000-05-05 19:34:50 +0000275
Wanlong Gao354ebb42012-12-07 10:10:04 +0800276 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
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280 sleep(30);
281 exit(0);
whrb973f2b2000-05-05 19:34:50 +0000282}
283
Wanlong Gao354ebb42012-12-07 10:10:04 +0800284#endif /* UNIT_TEST */