1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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!
}
|