--- a
+++ b/lib/forker.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+/**************************************************************
+ *
+ *    OS Testing - Cray Research, Inc.
+ *
+ *    FUNCTION NAME     : forker
+ *			  background
+ *
+ *    FUNCTION TITLE    : fork desired number of copies of the current process
+ *			  fork a process and return control to caller
+ *
+ *    SYNOPSIS:
+ *      int forker(ncopies, mode, prefix)
+ *      int ncopies;
+ *	int mode;
+ *	char *prefix;
+ *
+ *	int background(prefix);
+ *	char *prefix;
+ *
+ *	extern int Forker_pids[];
+ *	extern int Forker_npids;
+ *
+ *    AUTHOR            : Richard Logan
+ *
+ *    CO-PILOT(s)       : Dean Roehrich
+ *
+ *    INITIAL RELEASE   : UNICOS 8.0
+ *
+ *    DESIGN DESCRIPTION
+ *	The background function will do a fork of the current process.
+ *	The parent process will then exit, thus orphaning the
+ *	child process.  Doing this will not nice the child process
+ *	like executing a cmd in the background using "&" from the shell.
+ *	If the fork fails and prefix is not NULL, a error message is printed
+ *      to stderr and the process will exit with a value of errno.
+ *
+ *	The forker function will fork <ncopies> minus one copies
+ *	of the current process.  There are two modes in how the forks
+ *	will be done.  Mode 0 (default) will have all new processes
+ *	be childern of the parent process.    Using Mode 1,
+ *	the parent process will have one child and that child will
+ *	fork the next process, if necessary, and on and on.
+ *	The forker function will return the number of successful
+ *	forks.  This value will be different for the parent and each child.
+ *	Using mode 0, the parent will get the total number of successful
+ *	forks.  Using mode 1, the newest child will get the total number
+ *	of forks.  The parent will get a return value of 1.
+ *
+ *	The forker function also updates the global variables
+ *	Forker_pids[] and Forker_npids.  The Forker_pids array will
+ *      be updated to contain the pid of each new process.  The
+ *	Forker_npids variable contains the number of entries
+ *	in Forker_pids.  Note, not all processes will have
+ *	access to all pids via Forker_pids.  If using mode 0, only the
+ *	parent process and the last process will have all information.
+ *      If using mode 1, only the last child process will have all information.
+ *
+ *	If the prefix parameter is not NULL and the fork system call fails,
+ *      a error message will be printed to stderr.  The error message
+ *      the be preceeded with prefix string.  If prefix is NULL,
+ *      no error message is printed.
+ *
+ *    SPECIAL REQUIREMENTS
+ *	None.
+ *
+ *    UPDATE HISTORY
+ *      This should contain the description, author, and date of any
+ *      "interesting" modifications (i.e. info should helpful in
+ *      maintaining/enhancing this module).
+ *      username     description
+ *      ----------------------------------------------------------------
+ *	rrl	    This functions will first written during
+ *		the SFS testing days, 1993.
+ *
+ *    BUGS/LIMITATIONS
+ *     The child pids are stored in the fixed array, Forker_pids.
+ *     The array only has space for 4098 pids.  Only the first
+ *     4098 pids will be stored in the array.
+ *
+ **************************************************************/
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h> /* fork, getpid, sleep */
+#include <string.h>
+
+extern int errno;
+
+#define MAX_PIDS	4098
+
+int Forker_pids[MAX_PIDS];	/* holds pids of forked processes */
+int Forker_npids=0;	/* number of entries in Forker_pids */
+
+/***********************************************************************
+ *
+ * This function will fork and the parent will exit zero and
+ * the child will return.  This will orphan the returning process
+ * putting you in the background.
+ *
+ * Return Value
+ *   0 : if fork did not fail
+ *  !0 : if fork failed, the return value will be the errno.
+ ***********************************************************************/
+int
+background(prefix)
+char *prefix;
+{
+  switch (fork()) {
+  case -1:
+    if ( prefix != NULL )
+        fprintf(stderr, "%s: In %s background(), fork() failed, errno:%d %s\n",
+	    prefix, __FILE__, errno, strerror(errno));
+    exit(errno);
+
+  case 0:	/* child process */
+    break;
+
+  default:	
+    exit(0);
+  }
+
+  return 0;
+
+}	/* end of background */
+
+/***********************************************************************
+ * Forker will fork ncopies-1 copies of self. 
+ * 
+ ***********************************************************************/
+int
+forker(ncopies, mode, prefix)
+int ncopies;
+int mode;	/* 0 - all childern of parent, 1 - only 1 direct child */
+char *prefix;   /* if ! NULL, an message will be printed to stderr */
+		/* if fork fails.  The prefix (program name) will */
+	        /* preceed the message */
+{
+    int cnt;
+    int pid;
+    static int ind = 0;
+
+    Forker_pids[ind]=0;
+
+    for ( cnt=1; cnt < ncopies; cnt++ ) {
+
+	switch ( mode ) {
+        case 1  :	/* only 1 direct child */
+	    if ( (pid = fork()) == -1 ) {
+		if ( prefix != NULL ) 
+		    fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
+			prefix, __FILE__, errno, strerror(errno));
+	        return 0;
+	    }
+	    Forker_npids++;
+	    
+	    switch (pid ) {
+            case 0:     /* child - continues the forking */
+	        
+		if ( Forker_npids < MAX_PIDS )
+                    Forker_pids[Forker_npids-1]=getpid();
+                break;
+
+            default:    /* parent - stop the forking */
+		if ( Forker_npids < MAX_PIDS )
+                    Forker_pids[Forker_npids-1]=pid;
+                return cnt-1;      
+            }
+
+	    break;
+
+	default :	/* all new processes are childern of parent */
+	    if ( (pid = fork()) == -1 ) {
+		if ( prefix != NULL ) 
+		    fprintf(stderr, "%s: %s,forker(): fork() failed, errno:%d %s\n",
+			prefix, __FILE__, errno, strerror(errno));
+	        return cnt-1;
+	    }
+	    Forker_npids++;
+	    
+	    switch (pid ) {
+	    case 0:	/* child - stops the forking */
+		if ( Forker_npids < MAX_PIDS )
+                    Forker_pids[Forker_npids-1]=getpid();
+	        return cnt;	
+
+	    default:	/* parent - continues the forking */
+		if ( Forker_npids < MAX_PIDS )
+                    Forker_pids[Forker_npids-1]=pid;
+                break;
+            }
+	    break;
+	}
+    }
+
+    if ( Forker_npids < MAX_PIDS )
+        Forker_pids[Forker_npids]=0;
+    return cnt-1;
+
+}	/* end of forker */
+
+
+#if UNIT_TEST
+
+/*
+ * The following is a unit test main for the background and forker
+ * functions.
+ */
+
+int
+main(argc, argv)
+int argc;
+char **argv;
+{
+    int ncopies=1;
+    int mode=0;
+    int ret;
+    int ind;
+
+    if ( argc == 1 ) {
+	printf("Usage: %s ncopies [mode]\n", argv[0]);
+	exit(1);
+    }
+
+    if ( sscanf(argv[1], "%i", &ncopies) != 1 ) {
+	printf("%s: ncopies argument must be integer\n", argv[0]);
+	exit(1);
+    }
+
+    if ( argc == 3 )
+	if ( sscanf(argv[2], "%i", &mode) != 1 ) {
+        printf("%s: mode argument must be integer\n", argv[0]);
+        exit(1);
+    }
+
+    printf("Starting Pid = %d\n", getpid());
+    ret=background(argv[0]);
+    printf("After background() ret:%d, pid = %d\n", ret, getpid());
+
+    ret=forker(ncopies, mode, argv[0]);
+
+    printf("forker(%d, %d, %s) ret:%d, pid = %d, sleeping 30 seconds.\n", 
+	ncopies, mode, argv[0], ret, getpid());
+
+    printf("%d My version of Forker_pids[],  Forker_npids = %d\n", 
+	getpid(), Forker_npids);
+
+    for (ind=0; ind<Forker_npids; ind++){
+	printf("%d ind:%-2d pid:%d\n", getpid(), ind, Forker_pids[ind]);
+    }
+    
+    sleep(30);
+    exit(0);
+}
+
+#endif  /* UNIT_TEST */