diff options
Diffstat (limited to 'user/progTUV.c')
-rw-r--r-- | user/progTUV.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/user/progTUV.c b/user/progTUV.c new file mode 100644 index 0000000..3d5ed49 --- /dev/null +++ b/user/progTUV.c @@ -0,0 +1,169 @@ +#include <common.h> + +/** +** User function main #6: exit, fork, exec, kill, waitpid, sleep, write +** +** Reports, then loops spawing userW, sleeps, then waits for or kills +** all its children. +** +** Invoked as: main6 x c b +** where x is the ID character +** c is the child count +** b is wait/kill indicator ('w', 'W', or 'k') +*/ + +#ifndef MAX_CHILDREN +#define MAX_CHILDREN 50 +#endif + +USERMAIN( main ) { + int count = 3; // default child count + char ch = '6'; // default character to print + int nap = 8; // nap time + bool_t waiting = true; // default is waiting by PID + bool_t bypid = true; + char buf[128]; + uint_t children[MAX_CHILDREN]; + int nkids = 0; + char ch2[] = "*?*"; + + // process the command-line arguments + switch( argc ) { + case 4: waiting = argv[3][0] != 'k'; // 'w'/'W' -> wait, else -> kill + bypid = argv[3][0] != 'w'; // 'W'/'k' -> by PID + // FALL THROUGH + case 3: count = str2int( argv[2], 10 ); + // FALL THROUGH + case 2: ch = argv[1][0]; + break; + default: + sprint( buf, "main6: argc %d, args: ", argc ); + cwrites( buf ); + for( int i = 0; i <= argc; ++i ) { + sprint( buf, " %s", argv[argc] ? argv[argc] : "(null)" ); + cwrites( buf ); + } + cwrites( "\n" ); + } + + // fix the secondary output message (for indicating errors) + ch2[1] = ch; + + // announce our presence + write( CHAN_SIO, &ch, 1 ); + + // set up the argument vector + char *argsw[] = { "userW", "W", "10", "5", NULL }; + + for( int i = 0; i < count; ++i ) { + int whom = spawn( ProgW, argsw ); + if( whom < 0 ) { + swrites( ch2 ); + } else { + children[nkids++] = whom; + } + } + + // let the children start + sleep( SEC_TO_MS(nap) ); + + // collect exit status information + + // current child index + int n = 0; + + do { + int this; + int32_t status; + + // are we waiting for or killing it? + if( waiting ) { + this = waitpid( bypid ? children[n] : 0, &status ); + } else { + // always by PID + this = kill( children[n] ); + } + + // what was the result? + if( this < SUCCESS ) { + + // uh-oh - something went wrong + + // "no children" means we're all done + if( this != E_NO_CHILDREN ) { + if( waiting ) { + sprint( buf, "!! %c: waitpid(%d) status %d\n", + ch, bypid ? children[n] : 0, this ); + } else { + sprint( buf, "!! %c: kill(%d) status %d\n", + ch, children[n], this ); + } + } else { + sprint( buf, "!! %c: no children\n", ch ); + } + + // regardless, we're outta here + break; + + } else { + + // locate the child + int ix = -1; + + // were we looking by PID? + if( bypid ) { + // we should have just gotten the one we were looking for + if( this != children[n] ) { + // uh-oh + sprint( buf, "** %c: wait/kill PID %d, got %d\n", + ch, children[n], this ); + cwrites( buf ); + } else { + ix = n; + } + } + + // either not looking by PID, or the lookup failed somehow + if( ix < 0 ) { + int i; + for( i = 0; i < nkids; ++i ) { + if( children[i] == this ) { + ix = i; + break; + } + } + } + + // if ix == -1, the PID we received isn't in our list of children + + if( ix < 0 ) { + + // didn't find an entry for this PID??? + sprint( buf, "!! %c: child PID %d term, NOT FOUND\n", + ch, this ); + + } else { + + // found this PID in our list of children + if( ix != n ) { + // ... but it's out of sequence + sprint( buf, "== %c: child %d (%d,%d) status %d\n", + ch, ix, n, this, status ); + } else { + sprint( buf, "== %c: child %d (%d) status %d\n", + ch, ix, this, status ); + } + } + + } + + cwrites( buf ); + + ++n; + + } while( n < nkids ); + + exit( 0 ); + + return( 42 ); // shut the compiler up! +} |