summaryrefslogtreecommitdiff
path: root/user/progR.c
diff options
context:
space:
mode:
Diffstat (limited to 'user/progR.c')
-rw-r--r--user/progR.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/user/progR.c b/user/progR.c
new file mode 100644
index 0000000..1d47f6b
--- /dev/null
+++ b/user/progR.c
@@ -0,0 +1,99 @@
+#include <common.h>
+
+/**
+** User function R: exit, sleep, write, fork, getpid, getppid,
+**
+** Reports itself and its sequence number, along with its PID and
+** its parent's PID. It then delays, forks, delays, reports again,
+** and exits.
+**
+** Invoked as: userR x n [ s ]
+** where x is the ID character
+** n is the sequence number of the initial incarnation
+** s is the initial delay time (defaults to 10)
+*/
+
+USERMAIN( main ) {
+ char ch = 'r'; // default character to print
+ int delay = 10; // initial delay count
+ int seq = 99; // my sequence number
+ char buf[128];
+
+ // process the command-line arguments
+ switch( argc ) {
+ case 4: delay = str2int( argv[3], 10 );
+ // FALL THROUGH
+ case 3: seq = str2int( argv[2], 10 );
+ // FALL THROUGH
+ case 2: ch = argv[1][0];
+ break;
+ default:
+ sprint( buf, "userR: 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" );
+ }
+
+ /*
+ ** C oddity: a label cannot immediately precede a declaration.
+ **
+ ** Declarations are not considered "statements" in C. Prior to
+ ** C99, all declarations had to precede any statements inside a
+ ** block. Labels can only appear before statements. C99 allowed
+ ** the mixing of declarations and statements, but did not relax
+ ** the requirement that labels precede only statements.
+ **
+ ** That's why the declarations of these variables occur before the
+ ** label, but their initializations occur after the label.
+ **
+ ** As the PSA says on TV, "The more you know..." :-)
+ */
+
+ int32_t pid;
+ int32_t ppid;
+
+ restart:
+
+ // announce our presence
+ pid = getpid();
+ ppid = getppid();
+
+ sprint( buf, " %c[%d,%d,%d]", ch, seq, pid, ppid );
+ swrites( buf );
+
+ sleep( SEC_TO_MS(delay) );
+
+ // create the next child in sequence
+ if( seq < 5 ) {
+ ++seq;
+ int32_t n = fork();
+ switch( n ) {
+ case -1:
+ // failure?
+ sprint( buf, "** R[%d] fork code %d\n", pid, n );
+ cwrites( buf );
+ break;
+ case 0:
+ // child
+ goto restart;
+ default:
+ // parent
+ --seq;
+ sleep( SEC_TO_MS(delay) );
+ }
+ }
+
+ // final report - PPID may change, but PID and seq shouldn't
+ pid = getpid();
+ ppid = getppid();
+ sprint( buf, " %c[%d,%d,%d]", ch, seq, pid, ppid );
+ swrites( buf );
+
+ exit( 0 );
+
+ return( 42 ); // shut the compiler up!
+
+}