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