Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/std/pss.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-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
* Glenn Fowler
23
* AT&T Research
24
*
25
* process status stream implementation
26
*/
27
28
static const char id[] = "\n@(#)$Id: pss library (AT&T Research) 2011-05-09 $\0\n";
29
30
static const char lib[] = "std:pss";
31
32
#include "psslib.h"
33
34
#define TTYMAP(p,d) ((p)->meth->ttymapf?(*(p)->meth->ttymapf)(p,d):(d))
35
36
/*
37
* open a pss stream
38
*/
39
40
Pss_t*
41
pssopen(Pssdisc_t* disc)
42
{
43
register Pss_t* pss;
44
Vmalloc_t* vm;
45
46
if (!disc)
47
return 0;
48
if (!(vm = vmopen(Vmdcheap, Vmbest, 0)) || !(pss = vmnewof(vm, 0, Pss_t, 1, 0)))
49
goto bad;
50
pss->id = lib;
51
pss->disc = disc;
52
pss->vm = vm;
53
pss->ttybynamedisc.key = offsetof(Tty_t, name);
54
pss->ttybynamedisc.size = 0;
55
pss->ttybynamedisc.link = offsetof(Tty_t, byname);
56
pss->ttybydevdisc.key = offsetof(Tty_t, dev);
57
pss->ttybydevdisc.size = sizeof(Pss_dev_t);
58
pss->ttybydevdisc.link = offsetof(Tty_t, bydev);
59
if (!(pss->ttybyname = dtnew(pss->vm, &pss->ttybynamedisc, Dtset)) ||
60
!(pss->ttybydev = dtnew(pss->vm, &pss->ttybydevdisc, Dtset)))
61
goto bad;
62
pss->meth = (_pss_ps && ((disc->flags & PSS_PS) || getenv("_PSS_ps"))) ? _pss_ps : _pss_method;
63
while (pss->meth->initf && (*pss->meth->initf)(pss) <= 0)
64
if (pss->meth == _pss_ps || !(pss->meth = _pss_ps))
65
{
66
vmclose(vm);
67
return 0;
68
}
69
return pss;
70
bad:
71
if (disc->errorf)
72
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
73
if (vm)
74
vmclose(vm);
75
return 0;
76
}
77
78
/*
79
* close a pss stream
80
*/
81
82
int
83
pssclose(Pss_t* pss)
84
{
85
int r;
86
87
if (!pss || !pss->vm)
88
return -1;
89
r = (pss->meth->donef && (*pss->meth->donef)(pss) <= 0) ? -1 : 0;
90
if ((pss->disc->flags & PSS_VERBOSE) && pss->disc->errorf)
91
(*pss->disc->errorf)(pss, pss->disc, 1, "%s: method done", pss->meth->name);
92
vmclose(pss->vm);
93
return r;
94
}
95
96
/*
97
* return the pss entry for pid
98
* if pid==0 then return the next pid
99
*/
100
101
Pssent_t*
102
pssread(register Pss_t* pss, Pss_id_t pid)
103
{
104
register unsigned long fields = pss->meth->fields;
105
register unsigned long flags = pss->disc->flags;
106
register Pssent_t* pe;
107
Pssmatch_t* mp;
108
Pssdata_t* dp;
109
unsigned long x;
110
int i;
111
112
for (;;)
113
{
114
if ((*pss->meth->readf)(pss, pid) <= 0)
115
return 0;
116
if (!pss->ent && !(pss->ent = vmnewof(pss->vm, 0, Pssent_t, 1, 0)))
117
{
118
if (pss->disc->errorf)
119
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "out of space");
120
return 0;
121
}
122
pe = pss->ent;
123
if ((i = (*pss->meth->partf)(pss, pe)) < 0)
124
return 0;
125
if (!i)
126
{
127
memset(pe, 0, sizeof(*pe));
128
pe->pid = pss->pid;
129
goto next;
130
}
131
if (pid)
132
pe->pss = PSS_EXPLICIT;
133
else if (flags & PSS_ALL)
134
pe->pss = PSS_MATCHED;
135
else
136
{
137
if (flags & (PSS_ATTACHED|PSS_DETACHED|PSS_LEADER|PSS_NOLEADER|PSS_TTY|PSS_UID))
138
{
139
if ((flags & PSS_TTY) && pe->tty != TTYMAP(pss, pss->disc->tty))
140
goto next;
141
if ((flags & PSS_UID) && pe->uid != pss->disc->uid)
142
goto next;
143
switch (flags & (PSS_ATTACHED|PSS_DETACHED))
144
{
145
case PSS_ATTACHED:
146
if (pe->tty == PSS_NODEV)
147
goto next;
148
break;
149
case PSS_DETACHED:
150
if (pe->tty != PSS_NODEV)
151
goto next;
152
break;
153
}
154
switch (flags & (PSS_LEADER|PSS_NOLEADER))
155
{
156
case PSS_LEADER:
157
if ((fields & PSS_sid) && pe->pid != pe->sid)
158
goto next;
159
if ((fields & PSS_tgrp) && pe->pid != pe->tgrp)
160
goto next;
161
break;
162
case PSS_NOLEADER:
163
if ((fields & PSS_sid) && pe->pid == pe->sid)
164
goto next;
165
if ((fields & PSS_tgrp) && pe->pid == pe->tgrp)
166
goto next;
167
break;
168
}
169
pe->pss = PSS_MATCHED;
170
}
171
if (mp = pss->disc->match)
172
{
173
do
174
{
175
switch (mp->field)
176
{
177
case PSS_gid:
178
x = pe->gid;
179
break;
180
case PSS_pgrp:
181
x = pe->pgrp;
182
break;
183
case PSS_sid:
184
x = pe->sid;
185
break;
186
case PSS_tgrp:
187
x = pe->tgrp;
188
break;
189
case PSS_tty:
190
x = pe->tty;
191
if (pss->meth->ttymapf)
192
for (dp = mp->data; dp; dp = dp->next)
193
dp->data = TTYMAP(pss, dp->data);
194
break;
195
case PSS_uid:
196
x = pe->uid;
197
break;
198
default:
199
if (pss->disc->errorf)
200
(*pss->disc->errorf)(pss, pss->disc, 2, "%08lx selection not implemented", mp->field);
201
return 0;
202
}
203
for (dp = mp->data; dp; dp = dp->next)
204
if (dp->data == x)
205
break;
206
} while (!dp && (mp = mp->next));
207
if (!mp)
208
goto next;
209
pe->pss = PSS_MATCHED;
210
}
211
}
212
break;
213
next:
214
if (flags & PSS_UNMATCHED)
215
{
216
pe->pss = 0;
217
break;
218
}
219
if (pid)
220
return 0;
221
}
222
if (pss->meth->fullf && (*pss->meth->fullf)(pss, pe) <= 0)
223
return 0;
224
if (pe->pid <= 1 && pe->ppid > 1)
225
{
226
pe->ppid = 0;
227
if (pe->pid == 0)
228
pe->args = pe->command = "sched";
229
}
230
return pe;
231
}
232
233
/*
234
* save entry data
235
*/
236
237
Pssent_t*
238
psssave(register Pss_t* pss, register Pssent_t* pe)
239
{
240
register unsigned long fields = pss->disc->fields & pss->meth->fields;
241
242
if ((fields & PSS_args) && pe->args)
243
pe->args = vmstrdup(pss->vm, pe->args);
244
if ((fields & PSS_command) && pe->command)
245
pe->command = vmstrdup(pss->vm, pe->command);
246
if ((fields & PSS_sched) && pe->sched)
247
pe->sched = vmstrdup(pss->vm, pe->sched);
248
if ((fields & PSS_tty) && pe->ttyname)
249
pe->ttyname = vmstrdup(pss->vm, pe->ttyname);
250
pss->ent = 0;
251
return pe;
252
}
253
254
/*
255
* add name,dev to the tty hash
256
*/
257
258
int
259
pssttyadd(register Pss_t* pss, const char* name, Pss_dev_t dev)
260
{
261
register Tty_t* tty;
262
263
if (!dtmatch(pss->ttybyname, name))
264
{
265
if (!(tty = vmnewof(pss->vm, 0, Tty_t, 1, strlen(name))))
266
{
267
if (pss->disc->errorf)
268
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "out of space");
269
return -1;
270
}
271
strcpy(tty->name, name);
272
tty->dev = dev;
273
dtinsert(pss->ttybyname, tty);
274
if (!dtmatch(pss->ttybydev, &dev))
275
dtinsert(pss->ttybydev, tty);
276
}
277
return 0;
278
}
279
280
/*
281
* scan /dev and enter in the tty hash
282
*/
283
284
static void
285
ttyscan(register Pss_t* pss)
286
{
287
register DIR* dir;
288
register struct dirent* ent;
289
DIR* sub = 0;
290
char* base;
291
char* name;
292
struct stat st;
293
char path[PATH_MAX];
294
295
pss->ttyscan = 1;
296
strcpy(path, "/dev");
297
if (!(dir = opendir(path)))
298
{
299
if (pss->disc->errorf)
300
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%s: cannot read", path);
301
return;
302
}
303
path[4] = '/';
304
name = base = path + 5;
305
for (;;)
306
{
307
while (ent = readdir(dir))
308
{
309
if (D_NAMLEN(ent) + (base - path) + 1 > sizeof(path))
310
continue;
311
if (!sub && (ent->d_name[0] != 'c' && ent->d_name[0] != 't' && ent->d_name[0] != 'p' && ent->d_name[0] != 'v' || ent->d_name[1] != 'o' && ent->d_name[1] != 't'))
312
continue;
313
strcpy(base, ent->d_name);
314
if (stat(path, &st))
315
continue;
316
if (!S_ISCHR(st.st_mode))
317
{
318
if (sub || !S_ISDIR(st.st_mode))
319
continue;
320
sub = dir;
321
if (dir = opendir(path))
322
{
323
base = path + strlen(path);
324
*base++ = '/';
325
}
326
else
327
{
328
dir = sub;
329
sub = 0;
330
}
331
continue;
332
}
333
if (pssttyadd(pss, name, st.st_rdev))
334
{
335
closedir(dir);
336
return;
337
}
338
}
339
if (!sub)
340
break;
341
closedir(dir);
342
dir = sub;
343
sub = 0;
344
base = name;
345
}
346
closedir(dir);
347
}
348
349
/*
350
* return dev given tty base name
351
*/
352
353
Pss_dev_t
354
pssttydev(register Pss_t* pss, const char* name)
355
{
356
register const char* s;
357
register Tty_t* tty;
358
struct stat st;
359
360
s = name;
361
if (*s == '?' || *s == '-')
362
return PSS_NODEV;
363
if (pss->meth->ttydevf)
364
return (*pss->meth->ttydevf)(pss, s);
365
if (tty = (Tty_t*)dtmatch(pss->ttybyname, s))
366
return tty->dev;
367
if (stat(s, &st))
368
{
369
sfsprintf(pss->buf, sizeof(pss->buf), "/dev/%s", name);
370
s = (const char*)pss->buf;
371
if (stat(s, &st))
372
{
373
sfsprintf(pss->buf, sizeof(pss->buf), "/dev/tty%s", name);
374
if (stat(s, &st))
375
{
376
if (pss->disc->errorf)
377
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%s: unknown tty", name);
378
}
379
}
380
}
381
pssttyadd(pss, name, st.st_rdev);
382
return st.st_rdev;
383
}
384
385
/*
386
* return tty base name given tty dev
387
*/
388
389
char*
390
pssttyname(register Pss_t* pss, Pssent_t* pe)
391
{
392
register Tty_t* tty;
393
Pss_dev_t dev;
394
char* s;
395
396
if (pss->meth->ttynamef && (s = (*pss->meth->ttynamef)(pss, pe)))
397
return s;
398
if (pe->ttyname)
399
return pe->ttyname;
400
dev = pe->tty;
401
if (dev == PSS_NODEV)
402
return "?";
403
if (tty = (Tty_t*)dtmatch(pss->ttybydev, &dev))
404
return tty->name;
405
if (!pss->ttyscan)
406
ttyscan(pss);
407
if (tty = (Tty_t*)dtmatch(pss->ttybydev, &dev))
408
return tty->name;
409
sfsprintf(pss->buf, sizeof(pss->buf), "%03d,%03d", major(dev), minor(dev));
410
return pss->buf;
411
}
412
413