OSDN Git Service

Importing Egor's testsuite.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / testsuite / libltp / lib / forker.c
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., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, 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  *      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>
117 #include "forker.h"
118
119 extern int errno;
120
121 int Forker_pids[FORKER_MAX_PIDS];      /* holds pids of forked processes */
122 int Forker_npids=0;             /* number of entries in Forker_pids */
123
124 /***********************************************************************
125  *
126  * This function will fork and the parent will exit zero and
127  * the child will return.  This will orphan the returning process
128  * putting it in the background.
129  *
130  * Return Value
131  *   0 : if fork did not fail
132  *  !0 : if fork failed, the return value will be the errno.
133  ***********************************************************************/
134 int
135 background(prefix)
136 char *prefix;
137 {
138   switch (fork()) {
139   case -1:
140     if ( prefix != NULL )
141         fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n",
142             prefix, __FILE__, errno, strerror(errno));
143     exit(errno);
144
145   case 0:       /* child process */
146     break;
147
148   default:      
149     exit(0);
150   }
151
152   return 0;
153
154 }       /* end of background */
155
156 /***********************************************************************
157  * Forker will fork ncopies-1 copies of self. 
158  * 
159  ***********************************************************************/
160 int
161 forker(ncopies, mode, prefix)
162 int ncopies;
163 int mode;       /* 0 - all childern of parent, 1 - only 1 direct child */
164 char *prefix;   /* if ! NULL, an message will be printed to stderr */
165                 /* if fork fails.  The prefix (program name) will */
166                 /* preceed the message */
167 {
168     int cnt;
169     int pid;
170     static int ind = 0;
171
172     Forker_pids[ind]=0;
173
174     for ( cnt=1; cnt < ncopies; cnt++ ) {
175
176         switch ( mode ) {
177         case 1  :       /* only 1 direct child */
178             if ( (pid = fork()) == -1 ) {
179                 if ( prefix != NULL ) 
180                     fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
181                         prefix, __FILE__, errno, strerror(errno));
182                 return 0;
183             }
184             Forker_npids++;
185             
186             switch (pid ) {
187             case 0:     /* child - continues the forking */
188                 
189                 if ( Forker_npids < FORKER_MAX_PIDS )
190                     Forker_pids[Forker_npids-1]=getpid();
191                 break;
192
193             default:    /* parent - stop the forking */
194                 if ( Forker_npids < FORKER_MAX_PIDS )
195                     Forker_pids[Forker_npids-1]=pid;
196                 return cnt-1;      
197             }
198
199             break;
200
201         default :       /* all new processes are childern of parent */
202             if ( (pid = fork()) == -1 ) {
203                 if ( prefix != NULL ) 
204                     fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
205                         prefix, __FILE__, errno, strerror(errno));
206                 return cnt-1;
207             }
208             Forker_npids++;
209             
210             switch (pid ) {
211             case 0:     /* child - stops the forking */
212                 if ( Forker_npids < FORKER_MAX_PIDS )
213                     Forker_pids[Forker_npids-1]=getpid();
214                 return cnt;     
215
216             default:    /* parent - continues the forking */
217                 if ( Forker_npids < FORKER_MAX_PIDS )
218                     Forker_pids[Forker_npids-1]=pid;
219                 break;
220             }
221             break;
222         }
223     }
224
225     if ( Forker_npids < FORKER_MAX_PIDS )
226         Forker_pids[Forker_npids]=0;
227     return cnt-1;
228
229 }       /* end of forker */
230
231
232 #if UNIT_TEST
233
234 /*
235  * The following is a unit test main for the background and forker
236  * functions.
237  */
238
239 int
240 main(argc, argv)
241 int argc;
242 char **argv;
243 {
244     int ncopies=1;
245     int mode=0;
246     int ret;
247     int ind;
248
249     if ( argc == 1 ) {
250         printf("Usage: %s ncopies [mode]\n", argv[0]);
251         exit(1);
252     }
253
254     if ( sscanf(argv[1], "%i", &ncopies) != 1 ) {
255         printf("%s: ncopies argument must be integer\n", argv[0]);
256         exit(1);
257     }
258
259     if ( argc == 3 )
260         if ( sscanf(argv[2], "%i", &mode) != 1 ) {
261         printf("%s: mode argument must be integer\n", argv[0]);
262         exit(1);
263     }
264
265     printf("Starting Pid = %d\n", getpid());
266     ret=background(argv[0]);
267     printf("After background() ret:%d, pid = %d\n", ret, getpid());
268
269     ret=forker(ncopies, mode, argv[0]);
270
271     printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n", 
272         ncopies, mode, argv[0], ret, getpid());
273
274     printf("%d My version of Forker_pids[],  Forker_npids = %d\n", 
275         getpid(), Forker_npids);
276
277     for (ind=0; ind<Forker_npids; ind++){
278         printf("%d ind:%-2d pid:%d\n", getpid(), ind, Forker_pids[ind]);
279     }
280     
281     sleep(30);
282     exit(0);
283 }
284
285 #endif  /* UNIT_TEST */