Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/std/pss-procfs.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 PSS_METHOD_procfs implementation
26
*/
27
28
#include "psslib.h"
29
30
#if PSS_METHOD != PSS_METHOD_procfs
31
32
NoN(pss_procfs)
33
34
#else
35
36
#if !defined(pr_clname) && !_mem_pr_clname_prpsinfo
37
#undef PSS_sched
38
#define PSS_sched 0
39
#endif
40
41
#if !defined(pr_gid) && !_mem_pr_gid_prpsinfo
42
#undef PSS_gid
43
#define PSS_gid 0
44
#endif
45
46
#if !defined(pr_lttydev) && !_mem_pr_lttydev_prpsinfo
47
#undef _mem_pr_lttydev_prpsinfo
48
#define _mem_pr_lttydev_prpsinfo 0
49
#endif
50
51
#if !_mem_pr_npid_prpsinfo
52
#if !defined(pr_ntpid) && !_mem_pr_ntpid_prpsinfo
53
#undef PSS_npid
54
#define PSS_npid 0
55
#else
56
#define pr_npid pr_ntpid
57
#endif
58
#endif
59
60
#if !defined(pr_pgrp) && !_mem_pr_pgrp_prpsinfo
61
#if _mem_pr_pgid_prpsinfo
62
#undef _mem_pr_pgrp_prpsinfo
63
#define _mem_pr_pgrp_prpsinfo 1
64
#define pr_pgrp pr_pgid
65
#else
66
#undef PSS_pgrp
67
#define PSS_pgrp 0
68
#endif
69
#endif
70
71
#if !defined(pr_psargs) && !_mem_pr_psargs_prpsinfo
72
#undef _mem_pr_psargs_prpsinfo
73
#define _mem_pr_psargs_prpsinfo 0
74
#endif
75
76
#if !defined(pr_refcount) && !_mem_pr_refcount_prpsinfo
77
#undef PSS_refcount
78
#define PSS_refcount 0
79
#endif
80
81
#if !defined(pr_rssize) && !_mem_pr_rssize_prpsinfo
82
#undef PSS_rss
83
#define PSS_rss 0
84
#endif
85
86
#if !defined(pr_sonproc) && !_mem_pr_sonproc_prpsinfo
87
#undef PSS_proc
88
#define PSS_proc 0
89
#endif
90
91
#if !defined(pr_sid) && !_mem_pr_sid_prpsinfo
92
#undef PSS_sid
93
#define PSS_sid 0
94
#define pr_sid pr_tgrp
95
#endif
96
97
#if !defined(pr_tgrp) && !_mem_pr_tgrp_prpsinfo
98
#undef PSS_tgrp
99
#define PSS_tgrp 0
100
#define pr_tgrp pr_pgrp
101
#endif
102
103
typedef struct State_s
104
{
105
struct prpsinfo pr;
106
DIR* dir;
107
} State_t;
108
109
static int
110
procfs_init(Pss_t* pss)
111
{
112
register State_t* state;
113
int fd;
114
115
sfsprintf(pss->buf, sizeof(pss->buf), _PS_path_num, (unsigned long)1, _PS_status);
116
if ((fd = open(pss->buf, O_RDONLY|O_BINARY)) < 0)
117
return -1;
118
close(fd);
119
if (!(state = vmnewof(pss->vm, 0, State_t, 1, 0)))
120
{
121
if (pss->disc->errorf)
122
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "out of space");
123
return -1;
124
}
125
if (!(state->dir = opendir(_PS_dir)))
126
{
127
if (pss->disc->errorf)
128
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|1, "%s: cannot open", _PS_dir);
129
return -1;
130
}
131
pss->data = state;
132
return 1;
133
}
134
135
static int
136
procfs_done(Pss_t* pss)
137
{
138
register State_t* state = (State_t*)pss->data;
139
140
closedir(state->dir);
141
return 1;
142
}
143
144
static int
145
procfs_read(Pss_t* pss, Pss_id_t pid)
146
{
147
register State_t* state = (State_t*)pss->data;
148
struct dirent* ent;
149
char* e;
150
151
if (pid)
152
pss->pid = pid;
153
else
154
do
155
{
156
if (!(ent = readdir(state->dir)))
157
return 0;
158
pss->pid = (Pss_id_t)strtol(ent->d_name, &e, 10);
159
} while (*e);
160
return 1;
161
}
162
163
static int
164
procfs_part(register Pss_t* pss, register Pssent_t* pe)
165
{
166
register State_t* state = (State_t*)pss->data;
167
register struct prpsinfo* pr = &state->pr;
168
register int fd;
169
int n;
170
#if defined(_PS_scan_binary) || defined(_PS_scan_format)
171
struct stat st;
172
#endif
173
174
sfsprintf(pss->buf, sizeof(pss->buf), _PS_path_num, (unsigned long)pss->pid, _PS_status);
175
if ((fd = open(pss->buf, O_RDONLY|O_BINARY)) < 0)
176
{
177
if (pss->disc->errorf && ((pss->disc->flags & PSS_VERBOSE) || errno != ENOENT))
178
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%lu: cannot stat process", pss->pid);
179
return 0;
180
}
181
#ifdef _PS_scan_format
182
if ((n = read(fd, pss->buf, sizeof(pss->buf))) <= 0 || fstat(fd, &st))
183
{
184
n = -1;
185
errno = EINVAL;
186
}
187
else
188
{
189
memset(pr, sizeof(*pr), 0);
190
n = sfsscanf(pss->buf, _PS_scan_format, _PS_scan_args(pr));
191
if (n < _PS_scan_count)
192
{
193
register char* s;
194
195
for (s = pss->buf; *s; s++)
196
if (*s == '(')
197
{
198
for (; *s && *s != ')'; s++)
199
if (isspace(*s))
200
*s = '_';
201
break;
202
}
203
n = sfsscanf(pss->buf, _PS_scan_format, _PS_scan_args(pr));
204
if (n < _PS_scan_count)
205
error(1, "%lu: scan count %d, expected at least %d", (unsigned long)pss->pid, n, _PS_scan_count);
206
}
207
#ifdef _PS_scan_fix
208
_PS_scan_fix(pr, pe);
209
#endif
210
#ifdef _PS_task
211
sfsprintf(pss->buf, sizeof(pss->buf), _PS_path_num, (unsigned long)pss->pid, _PS_task);
212
(void)stat(pss->buf, &st);
213
#endif
214
pr->pr_uid = st.st_uid;
215
pr->pr_gid = st.st_gid;
216
pr->pr_nice = pr->pr_priority - 15;
217
pr->pr_size /= 1024;
218
#if _mem_pr_rssize_prpsinfo
219
pr->pr_rssize /= 1024;
220
#endif
221
#ifdef _PS_scan_boot
222
if (!pss->boot)
223
{
224
register char* s;
225
Sfio_t* fp;
226
227
pss->boot = 1;
228
if (fp = sfopen(NiL, "/proc/stat", "r"))
229
{
230
while (s = sfgetr(fp, '\n', 0))
231
if (strneq(s, "btime ", 6))
232
{
233
pss->boot = strtol(s + 6, NiL, 10);
234
break;
235
}
236
sfclose(fp);
237
}
238
if (!(pss->hz = (int)strtol(astconf("CLK_TCK", NiL, NiL), NiL, 0)))
239
pss->hz = PR_HZ;
240
}
241
pr->pr_start = pss->boot + pr->pr_start / pss->hz;
242
#endif
243
}
244
#else
245
#ifdef _PS_scan_binary
246
n = read(fd, pr, sizeof(*pr)) == sizeof(*pr) ? 1 : -1;
247
#else
248
n = ioctl(fd, PIOCPSINFO, pr);
249
#endif
250
#endif
251
close(fd);
252
if (n < 0)
253
{
254
if (pss->disc->errorf)
255
(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "%lu: cannot get process info", pss->pid);
256
return 0;
257
}
258
#if _UTS
259
if (pr->pr_pri > 99)
260
pr->pr_pri = 99;
261
else if (pr->pr_pri < 0)
262
pr->pr_pri = 0;
263
pr->pr_ttydev = makedev((pr->pr_ttydev >> 18) & ((1<<14)-1), pr->pr_ttydev & ((1<<18)-1));
264
#endif
265
#if PSS_gid
266
pe->gid = pr->pr_gid;
267
#endif
268
#if PSS_pgrp
269
pe->pgrp = pr->pr_pgrp;
270
#endif
271
pe->pid = pr->pr_pid;
272
#if PSS_sid
273
pe->sid = pr->pr_sid;
274
#endif
275
pe->state = PR_ZOMBIE(pr) ? PSS_ZOMBIE : pr->pr_sname;
276
#if PSS_tgrp
277
pe->tgrp = pr->pr_tgrp;
278
#endif
279
pe->tty = (pr->pr_ttydev == (Pss_dev_t)PRNODEV) ? PSS_NODEV : pr->pr_ttydev;
280
pe->uid = pr->pr_uid;
281
return 1;
282
}
283
284
static int
285
procfs_full(register Pss_t* pss, register Pssent_t* pe)
286
{
287
register State_t* state = (State_t*)pss->data;
288
register struct prpsinfo* pr = &state->pr;
289
unsigned long fields = pss->disc->fields & pss->meth->fields;
290
char* s;
291
int i;
292
293
if (pe->state != PSS_ZOMBIE)
294
{
295
if (fields & PSS_args)
296
{
297
#if _mem_pr_psargs_prpsinfo
298
s = pr->pr_psargs;
299
#else
300
#ifdef _PS_args
301
s = "<unknown>";
302
sfsprintf(pss->buf, sizeof(pss->buf), _PS_path_num, pe->pid, _PS_args);
303
if ((i = open(pss->buf, O_RDONLY|O_BINARY)) >= 0)
304
{
305
int n;
306
307
n = read(i, pss->buf, sizeof(pss->buf) - 1);
308
close(i);
309
if (n > 0)
310
{
311
s = pss->buf;
312
for (i = 0; i < n; i++)
313
if (!s[i])
314
s[i] = ' ';
315
s[i] = 0;
316
}
317
}
318
#else
319
s = pr->pr_fname;
320
if (s[0] == '(' && s[i = strlen(s) - 1] == ')')
321
{
322
s[i] = 0;
323
s++;
324
}
325
#endif
326
#endif
327
pe->args = s;
328
}
329
if (fields & PSS_command)
330
{
331
s = pr->pr_fname;
332
if (s[0] == '(' && s[i = strlen(s) - 1] == ')')
333
{
334
s[i] = 0;
335
s++;
336
}
337
pe->command = s;
338
}
339
}
340
pe->addr = (void*)pr->pr_addr;
341
#if _mem_pr_clname_prpsinfo
342
pe->sched = pr->pr_clname;
343
#endif
344
pe->cpu = PR_CPU(pr);
345
pe->flags = pr->pr_flag;
346
pe->nice = pr->pr_nice;
347
#if _mem_pr_npid_prpsinfo
348
pe->npid = pr->pr_npid;
349
#else
350
#if _mem_pr_ntpid_prpsinfo
351
pe->npid = pr->pr_ntpid;
352
#endif
353
#endif
354
pe->ppid = pr->pr_ppid;
355
pe->pri = pr->pr_pri;
356
#if _mem_pr_sonproc_prpsinfo
357
pe->proc = pr->pr_sonproc;
358
#endif
359
#if _mem_pr_refcount_prpsinfo
360
pe->refcount = pr->pr_refcount;
361
#endif
362
#if _mem_pr_rssize_prpsinfo
363
pe->rss = pr->pr_rssize;
364
#endif
365
pe->size = pr->pr_size;
366
pe->start = PR_START(pr);
367
pe->time = PR_TIME(pr);
368
pe->wchan = (void*)pr->pr_wchan;
369
return 1;
370
}
371
372
static Pssmeth_t procfs_method =
373
{
374
"/proc",
375
"[-version?@(#)$Id: pss /proc (AT&T Research) 2011-12-13 $\n]"
376
"[-author?Glenn Fowler <[email protected]>]",
377
PSS_all,
378
procfs_init,
379
procfs_read,
380
procfs_part,
381
procfs_full,
382
0,
383
0,
384
0,
385
procfs_done
386
};
387
388
Pssmeth_t* _pss_method = &procfs_method;
389
390
#endif
391
392