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 <glenn.s.fowler@gmail.com>                *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * Glenn Fowler
23  * AT&T Research
24  *
25  * process status stream PSS_METHOD_pstat implementation
26  */
27 
28 #include "psslib.h"
29 
30 #if PSS_METHOD != PSS_METHOD_pstat
31 
32 NoN(pss_pstat)
33 
34 #else
35 
36 #define _PSTAT64		1
37 
38 #if _sys_param
39 #include <sys/param.h>
40 #endif
41 #if _sys_pstat
42 #include <sys/pstat.h>
43 #endif
44 
45 typedef struct State_s
46 {
47 	struct pst_status	pst[256];
48 	struct pst_status*	pr;
49 	struct pst_status*	pp;
50 	struct pst_status*	pe;
51 	int			last;
52 } State_t;
53 
54 static int
55 pstat_init(Pss_t* pss)
56 {
57 	register State_t*	state;
58 
59 	if (!(state = vmnewof(pss->vm, 0, State_t, 1, 0)))
60 	{
61 		if (pss->disc->errorf)
62 			(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "out of space");
63 		return -1;
64 	}
65 	pss->data = state;
66 	return 1;
67 }
68 
69 static int
70 pstat_read(Pss_t* pss, Pss_id_t pid)
71 {
72 	register State_t*	state = (State_t*)pss->data;
73 	int			count;
74 
75 	if (pid)
76 	{
77 		if ((count = pstat_getproc(state->pst, sizeof(state->pst[0]), 0, pid)) != 1)
78 			return -1;
79 		state->pp = state->pst;
80 		state->pe = state->pp + count;
81 		state->last = 0;
82 	}
83 	else if (state->pp >= state->pe)
84 	{
85 		count = state->pe ? (state->pe-1)->pst_idx + 1 : 0;
86 		if ((count = pstat_getproc(state->pst, sizeof(state->pst[0]), elementsof(state->pst), count)) < 0)
87 			return -1;
88 		if (!count)
89 			return 0;
90 		state->pp = state->pst;
91 		state->pe = state->pp + count;
92 		state->last = 0;
93 	}
94 	state->pr = state->pp++;
95 	pss->pid = state->pr->pst_pid;
96 	return 1;
97 }
98 
99 static int
100 pstat_part(register Pss_t* pss, register Pssent_t* pe)
101 {
102 	State_t*			state = (State_t*)pss->data;
103 	register struct pst_status*	pr = state->pr;
104 
105 	pe->pid = pr->pst_pid;
106 	pe->pgrp = pr->pst_pgrp;
107 	pe->tty = pr->pst_term.psd_major == -1 && pr->pst_term.psd_minor == -1 ? PSS_NODEV : makedev(pr->pst_term.psd_major, pr->pst_term.psd_minor);
108 	pe->uid = pr->pst_uid;
109 	pe->sid = pr->pst_sid;
110 	switch ((int)pr->pst_stat)
111 	{
112 	case PS_IDLE:	pe->state = 'I'; break;
113 	case PS_RUN:	pe->state = 'R'; break;
114 	case PS_SLEEP:	pe->state = 'S'; break;
115 	case PS_STOP:	pe->state = 'T'; break;
116 	case PS_ZOMBIE:	pe->state = 'Z'; break;
117 	default:	pe->state = 'O'; break;
118 	}
119 	return 1;
120 }
121 
122 static int
123 pstat_full(register Pss_t* pss, register Pssent_t* pe)
124 {
125 	register State_t*		state = (State_t*)pss->data;
126 	register struct pst_status*	pr = state->pr;
127 	unsigned long			fields = pss->disc->fields & pss->meth->fields;
128 	char*				s;
129 	int				i;
130 
131 	if (pe->state != PSS_ZOMBIE)
132 	{
133 		if (fields & PSS_args)
134 		{
135 			s = pr->pst_cmd;
136 			if (s[0] == '(' && s[i = strlen(s) - 1] == ')')
137 			{
138 				s[i] = 0;
139 				s++;
140 			}
141 			pe->args = s;
142 		}
143 		if (fields & PSS_command)
144 		{
145 			s = pr->pst_cmd;
146 			if (s[0] == '(' && s[i = strlen(s) - 1] == ')')
147 			{
148 				s[i] = 0;
149 				s++;
150 			}
151 			pe->command = s;
152 		}
153 	}
154 	pe->addr = (void*)pr->pst_addr;
155 	pe->wchan = (void*)pr->pst_wchan;
156 	pe->flags = pr->pst_flag;
157 	pe->nice = pr->pst_nice;
158 	pe->ppid = pr->pst_ppid;
159 	pe->pri = pr->pst_pri;
160 	pe->rss = pr->pst_rssize;
161 	pe->size = pr->pst_tsize + pr->pst_dsize + pr->pst_ssize;
162 	pe->start = pr->pst_start;
163 	pe->time = pr->pst_utime + pr->pst_stime;
164 	return 1;
165 }
166 
167 static Pssmeth_t pstat_method =
168 {
169 	"pstat",
170 	"[-version?@(#)$Id: pss pstat (AT&T Research) 2003-02-01 $\n]"
171 	"[-author?Glenn Fowler <gsf@research.att.com>]",
172 	PSS_all,
173 	pstat_init,
174 	pstat_read,
175 	pstat_part,
176 	pstat_full,
177 	0,
178 	0,
179 	0,
180 	0
181 };
182 
183 Pssmeth_t*	_pss_method = &pstat_method;
184 
185 #endif
186