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_getprocs implementation
26  */
27 
28 #include "psslib.h"
29 
30 #if PSS_METHOD != PSS_METHOD_getprocs
31 
32 NoN(pss_getprocs)
33 
34 #else
35 
36 #include <procinfo.h>
37 #include <sys/proc.h>
38 
39 #if _mem_pi_pri_procsinfo64
40 #define procsinfo		procsinfo64
41 #else
42 #undef	PSS_pri
43 #define PSS_pri			0
44 #endif
45 
46 #undef	PSS_gid
47 #define PSS_gid			0
48 #undef	PSS_npid
49 #define PSS_npid		0
50 #undef	PSS_proc
51 #define PSS_proc		0
52 #undef	PSS_sched
53 #define PSS_sched		0
54 #undef	PSS_tgrp
55 #define PSS_tgrp		0
56 
57 typedef struct State_s
58 {
59 	struct procsinfo	entry[64];
60 	struct procsinfo*	pr;
61 	int			last;
62 	int			index;
63 	int			count;
64 } State_t;
65 
66 static int
67 getprocs_init(Pss_t* pss)
68 {
69 	register State_t*	state;
70 
71 	if (!(state = vmnewof(pss->vm, 0, State_t, 1, 0)))
72 	{
73 		if (pss->disc->errorf)
74 			(*pss->disc->errorf)(pss, pss->disc, ERROR_SYSTEM|2, "out of space");
75 		return -1;
76 	}
77 	pss->data = state;
78 	return 1;
79 }
80 
81 static int
82 getprocs_read(Pss_t* pss, Pss_id_t pid)
83 {
84 	register State_t*	state = (State_t*)pss->data;
85 
86 	if (pid)
87 	{
88 		pss->pid = pid;
89 		state->index = 0;
90 		if ((state->count = getprocs(state->entry, sizeof(state->entry[0]), NiL, 0, &pss->pid, 1)) != 1)
91 			return -1;
92 		state->last = 0;
93 	}
94 	else
95 		while (state->index >= state->count)
96 		{
97 			if (state->last)
98 				return 0;
99 			state->index = 0;
100 			state->count = getprocs(state->entry, sizeof(state->entry[0]), NiL, 0, &pss->pid, elementsof(state->entry));
101 			if (state->count < elementsof(state->entry))
102 			{
103 				state->last = 1;
104 				if (state->count < 0)
105 					return -1;
106 				if (!state->count)
107 					return 0;
108 			}
109 			if (!state->entry[0].pi_pid)
110 				state->index++;
111 		}
112 	state->pr = state->entry + state->index++;
113 	return 1;
114 }
115 
116 static int
117 getprocs_part(register Pss_t* pss, register Pssent_t* pe)
118 {
119 	register State_t*		state = (State_t*)pss->data;
120 	register struct procsinfo*	pr;
121 
122 	pr = state->pr;
123 	pe->pid = state->pr->pi_pid;
124 	pe->pgrp = pr->pi_pgrp;
125 	pe->sid = pr->pi_sid;
126 	pe->tty = pr->pi_ttyp ? pr->pi_ttyd : PSS_NODEV;
127 	pe->uid = pr->pi_uid;
128 	switch (pr->pi_state)
129 	{
130 	case SACTIVE:
131 		pe->state = 'R';
132 		break;
133 	case SIDL:
134 		pe->state = 'I';
135 		break;
136 	case SSTOP:
137 		pe->state = 'T';
138 		break;
139 	case SSWAP:
140 		pe->state = 'W';
141 		break;
142 	case SZOMB:
143 		pe->state = 'Z';
144 		break;
145 	default:
146 		pe->state = 'O';
147 		break;
148 	}
149 	return 1;
150 }
151 
152 static int
153 getprocs_full(register Pss_t* pss, register Pssent_t* pe)
154 {
155 	register State_t*		state = (State_t*)pss->data;
156 	register struct procsinfo*	pr = state->pr;
157 	unsigned long			fields = pss->disc->fields & pss->meth->fields;
158 	char*				s;
159 	int				i;
160 
161 	if (pe->state != PSS_ZOMBIE)
162 	{
163 		if (fields & PSS_args)
164 		{
165 			s = pr->pi_comm;
166 			if (s[0] == '(' && s[i = strlen(s) - 1] == ')')
167 			{
168 				s[i] = 0;
169 				s++;
170 			}
171 			pe->args = s;
172 		}
173 		if (fields & PSS_command)
174 		{
175 			s = pr->pi_comm;
176 			if (s[0] == '(' && s[i = strlen(s) - 1] == ')')
177 			{
178 				s[i] = 0;
179 				s++;
180 			}
181 			pe->command = s;
182 		}
183 	}
184 	pe->addr = (void*)pr->pi_adspace;
185 	pe->flags = pr->pi_flags;
186 	pe->nice = pr->pi_nice;
187 	pe->ppid = pr->pi_ppid;
188 #if PSS_pri
189 	pe->pri = pr->pi_pri;
190 #endif
191 	pe->refcount = pr->pi_thcount;
192 	pe->rss = pr->pi_drss + pr->pi_trss;
193 	pe->size = pr->pi_size;
194 	pe->start = pr->pi_start;
195 	pe->time = pr->pi_ru.ru_utime.tv_sec + pr->pi_ru.ru_stime.tv_sec;
196 	return 1;
197 }
198 
199 static Pssmeth_t getprocs_method =
200 {
201 	"getprocs",
202 	"[-version?@(#)$Id: pss getprocs (AT&T Research) 2004-02-29 $\n]"
203 	"[-author?Glenn Fowler <gsf@research.att.com>]",
204 	PSS_all,
205 	getprocs_init,
206 	getprocs_read,
207 	getprocs_part,
208 	getprocs_full,
209 	0,
210 	0,
211 	0,
212 	0
213 };
214 
215 Pssmeth_t*	_pss_method = &getprocs_method;
216 
217 #endif
218