Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/cs/pid.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* Glenn Fowler
24
* AT&T Bell Laboratories
25
*
26
* local pid monitor service
27
*/
28
29
static const char id[] = "\n@(#)$Id: cs.pid (AT&T Bell Laboratories) 11/11/93 $\0\n";
30
31
#include <ast.h>
32
#include <cs.h>
33
#include <error.h>
34
#include <hash.h>
35
#include <sig.h>
36
37
#define DECAY_MIN (EXPIRE_MIN)
38
#define DECAY (EXPIRE<<3)
39
#define DECAY_MAX (EXPIRE_MAX<<3)
40
#define EXPIRE_MIN (1)
41
#define EXPIRE EXPIRE_MIN
42
#define EXPIRE_MAX (60)
43
44
typedef struct notify Notify_t;
45
46
struct notify /* notification address list */
47
{
48
Notify_t* next; /* next in list */
49
Cs_addr_t addr; /* notification address */
50
};
51
52
typedef struct /* pid info */
53
{
54
HASH_HEADER;
55
Notify_t* notify; /* notification address list */
56
int decay; /* expiration decay */
57
unsigned long expire; /* kill poll expiration */
58
pid_t pid; /* request pid */
59
} Pid_t;
60
61
typedef struct /* server state */
62
{
63
Hash_table_t* pids; /* Pid_t hash */
64
int decay; /* max expiration decay */
65
int dormant; /* no activity */
66
int expire; /* expiration increment */
67
unsigned long active; /* number of active pids */
68
char msg[1024]; /* msg text */
69
char buf[1024]; /* work buffer */
70
} State_t;
71
72
/*
73
* initialize the state
74
*/
75
76
static void*
77
svc_init(void* handle, int fdmax)
78
{
79
register State_t* state = (State_t*)handle;
80
81
NoP(fdmax);
82
if (!(state->pids = hashalloc(NiL, HASH_set, HASH_ALLOCATE, HASH_namesize, sizeof(pid_t), HASH_name, "pids", 0)))
83
error(3, "out of space [pids]");
84
state->decay = DECAY;
85
state->dormant = 1;
86
state->expire = EXPIRE;
87
cswakeup(CS_SVC_DORMANT * 1000L);
88
return(handle);
89
}
90
91
/*
92
* service a request
93
*/
94
95
static int
96
svc_read(void* handle, int fd)
97
{
98
register Pid_t* pp;
99
register Notify_t* np;
100
register Notify_t* pn;
101
register State_t* state = (State_t*)handle;
102
char* m;
103
char* s;
104
char* e;
105
int n;
106
int c;
107
pid_t pid;
108
Cs_addr_t addr;
109
Hash_position_t* pos;
110
111
if ((n = csfrom(fd, m = state->msg, sizeof(state->msg) - 1, &addr)) <= 0)
112
return(-1);
113
m[n] = 0;
114
do
115
{
116
if (!(e = strchr(m, '\n')))
117
return(-1);
118
n = ++e - m;
119
if ((pid = strtol(m, NiL, 0)) <= 1)
120
{
121
for (s = m; *s && (*s < '0' || *s > '9'); s++);
122
switch (*m)
123
{
124
case 'd':
125
if ((c = strtol(s, NiL, 0)) >= DECAY_MIN && c <= DECAY_MAX)
126
state->decay = c;
127
break;
128
case 'e':
129
if ((c = strtol(s, NiL, 0)) >= EXPIRE_MIN && c <= EXPIRE_MAX)
130
state->expire = c;
131
break;
132
case 's':
133
case '\n':
134
m = state->buf;
135
n = sfsprintf(m, sizeof(state->buf), "active=%d decay=%d expire=%d\n", state->active, state->decay, state->expire);
136
if (pos = hashscan(state->pids, 0))
137
{
138
while (pp = (Pid_t*)hashnext(pos))
139
{
140
n += sfsprintf(m + n, sizeof(state->buf) - n, "%6d %ld", pp->pid, pp->expire - cs.time);
141
for (np = pp->notify; np; np = np->next)
142
n += sfsprintf(m + n, sizeof(state->buf) - n, " %s/%lu", csname(np->addr.addr[0]), np->addr.addr[1]);
143
n += sfsprintf(m + n, sizeof(state->buf) - n, "\n");
144
}
145
hashdone(pos);
146
}
147
break;
148
case 'v':
149
m = state->buf;
150
n = sfsprintf(m, sizeof(state->buf), "%s %s %u\n", id + 10, csname(0L), getpid());
151
break;
152
default:
153
if (*m < '0' || *m > '9')
154
{
155
if (n > 0) m[n - 1] = 0;
156
n = sfsprintf(state->buf, sizeof(state->buf), "%s [invalid command]\n", m);
157
m = state->buf;
158
}
159
break;
160
}
161
csto(fd, m, n, &addr);
162
}
163
else if (pp = (Pid_t*)hashlook(state->pids, (char*)&pid, HASH_LOOKUP, NiL))
164
{
165
if (kill(pid, 0) && errno == ESRCH)
166
{
167
csto(fd, m, n, &addr);
168
np = pp->notify;
169
while (np)
170
{
171
csto(fd, m, n, &np->addr);
172
pn = np;
173
np = np->next;
174
free(pn);
175
}
176
hashlook(state->pids, NiL, HASH_DELETE, NiL);
177
if (!--state->active)
178
{
179
state->dormant = 1;
180
cswakeup(CS_SVC_DORMANT * 1000L);
181
}
182
}
183
else if (np = newof(0, Notify_t, 1, 0))
184
{
185
np->addr = addr;
186
np->next = pp->notify;
187
pp->notify = np;
188
}
189
}
190
else if (kill(pid, 0) && errno == ESRCH)
191
csto(fd, m, n, &addr);
192
else if (pp = (Pid_t*)hashlook(state->pids, NiL, HASH_CREATE|HASH_SIZE(sizeof(Pid_t)), NiL))
193
{
194
pp->pid = pid;
195
if (np = newof(0, Notify_t, 1, 0))
196
{
197
np->addr = addr;
198
np->next = pp->notify;
199
pp->notify = np;
200
pp->expire = cs.time + (pp->decay = state->expire);
201
if (!state->active++)
202
{
203
state->dormant = 0;
204
cswakeup(pp->decay * 1000L);
205
}
206
}
207
}
208
} while (*(m = e));
209
return(0);
210
}
211
212
/*
213
* poll expired pids
214
*/
215
216
static int
217
svc_timeout(void* handle)
218
{
219
register State_t* state = (State_t*)handle;
220
register Pid_t* pp;
221
register Hash_position_t* pos;
222
register Notify_t* np;
223
register Notify_t* pn;
224
int n;
225
unsigned long wakeup;
226
227
if (state->dormant)
228
exit(0);
229
wakeup = ~0;
230
if (pos = hashscan(state->pids, 0))
231
{
232
while (pp = (Pid_t*)hashnext(pos))
233
{
234
if (pp->expire <= cs.time)
235
{
236
if (kill(pp->pid, 0) && errno == ESRCH)
237
{
238
n = sfsprintf(state->msg, sizeof(state->msg), "%u\n", pp->pid);
239
np = pp->notify;
240
while (np)
241
{
242
csto(0, state->msg, n, &np->addr);
243
pn = np;
244
np = np->next;
245
free(pn);
246
}
247
hashlook(state->pids, (char*)&pp->pid, HASH_DELETE, NiL);
248
state->active--;
249
continue;
250
}
251
if (pp->decay < state->decay)
252
pp->decay <<= 1;
253
pp->expire = cs.time + pp->decay;
254
}
255
if (pp->expire < wakeup)
256
wakeup = pp->expire;
257
}
258
hashdone(pos);
259
}
260
if (wakeup == ~0)
261
{
262
state->dormant = 1;
263
wakeup = CS_SVC_DORMANT;
264
}
265
else wakeup -= cs.time;
266
cswakeup(wakeup * 1000L);
267
return(0);
268
}
269
270
int
271
main(int argc, char** argv)
272
{
273
static State_t state;
274
275
NoP(argc);
276
csserve(&state, argv[1], svc_init, NiL, NiL, svc_read, NiL, svc_timeout);
277
exit(1);
278
}
279
280