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_cygwin implementation
26  */
27 
28 #include "psslib.h"
29 
30 #if PSS_METHOD != PSS_METHOD_cygwin
31 
32 NoN(pss_cygwin)
33 
34 #else
35 
36 #ifndef PR_HZ
37 #define PR_HZ			100
38 #endif
39 #ifndef PRNODEV
40 #define PRNODEV			((Pss_dev_t)(-1))
41 #endif
42 #ifndef PID_ZOMBIE
43 #define PID_ZOMBIE		0
44 #endif
45 
46 #undef	PR_CTIME
47 #define PR_CTIME(p)		(((p)->rusage_children.ru_utime.tv_sec+(p)->rusage_children.ru_stime.tv_sec)*PR_HZ+((((p)->rusage_children.ru_utime.tv_usec+(p)->rusage_children.ru_stime.tv_usec)*PR_HZ)/1000000))
48 #undef	PR_START
49 #define PR_START(p)		((p)->start_time)
50 #undef	PR_TIME
51 #define PR_TIME(p)		(((p)->rusage_self.ru_utime.tv_sec+(p)->rusage_self.ru_stime.tv_sec)*PR_HZ+((((p)->rusage_self.ru_utime.tv_usec+(p)->rusage_self.ru_stime.tv_usec)*PR_HZ)/1000000))
52 
53 #undef	PSS_addr
54 #define PSS_addr	0
55 #undef	PSS_sched
56 #define PSS_sched	0
57 #undef	PSS_cpu
58 #define PSS_cpu		0
59 #undef	PSS_nice
60 #define PSS_nice	0
61 #undef	PSS_pri
62 #define PSS_pri		0
63 #undef	PSS_proc
64 #define PSS_proc	0
65 #undef	PSS_refcount
66 #define PSS_refcount	0
67 #undef	PSS_tgrp
68 #define PSS_tgrp	0
69 #undef	PSS_wchan
70 #define PSS_wchan	0
71 
72 static int
73 cygwin_init(Pss_t* pss)
74 {
75 	cygwin_internal(CW_LOCK_PINFO, 1000);
76 	return 1;
77 }
78 
79 static int
80 cygwin_done(Pss_t* pss)
81 {
82 	cygwin_internal(CW_UNLOCK_PINFO);
83 	return 1;
84 }
85 
86 static int
87 cygwin_read(Pss_t* pss, Pss_id_t pid)
88 {
89 	if (pid)
90 		pss->pid = pid;
91 	else
92 	{
93 		if (!pss->data)
94 			pss->pid = 0;
95 		else if (!(pss->pid = ((struct external_pinfo*)pss->data)->pid))
96 		{
97 			pss->data = 0;
98 			return 0;
99 		}
100 		pss->pid |= CW_NEXTPID;
101 	}
102 	return 1;
103 }
104 
105 static int
106 cygwin_part(register Pss_t* pss, register Pssent_t* pe)
107 {
108 	register struct external_pinfo*	pr;
109 
110 	if (!(pr = (struct external_pinfo*)cygwin_internal(CW_GETPINFO, pss->pid)) || !pr->pid)
111 		return 0;
112 	pss->data = (void*)pr;
113 	pe->gid = pr->gid;
114 	pe->pgrp = pr->pgid;
115 	pe->sid = pr->sid;
116 	pe->tty = pr->ctty == PRNODEV ? PSS_NODEV : pr->ctty;
117 	pe->uid = pr->uid;
118 	if (pr->process_state & (PID_EXITED|PID_ZOMBIE))
119 		pe->state = PSS_ZOMBIE;
120 	else if (pr->process_state & PID_STOPPED)
121 		pe->state = 'S';
122 	else if (pr->process_state & PID_TTYIN)
123 		pe->state = 'I';
124 	else if (pr->process_state & PID_TTYOU)
125 		pe->state = 'O';
126 	else
127 		pe->state = ' ';
128 	return 1;
129 }
130 
131 static int
132 cygwin_full(register Pss_t* pss, register Pssent_t* pe)
133 {
134 	register struct external_pinfo*	pr = (struct external_pinfo*)pss->data;
135 	unsigned long			fields = pss->disc->fields & pss->meth->fields;
136 	char*				s;
137 	int				i;
138 
139 	if (pe->state != PSS_ZOMBIE)
140 	{
141 		if (fields & PSS_args)
142 		{
143 			cygwin_conv_to_posix_path(pr->progname, pss->buf);
144 			s = pss->buf;
145 			if ((i = strlen(s)) > 4 && !strcasecmp(s + i - 4, ".exe"))
146 				*(s + i - 4) = 0;
147 			pe->args = s;
148 		}
149 		if (fields & PSS_command)
150 		{
151 			cygwin_conv_to_posix_path(pr->progname, pss->buf);
152 			if (s = strrchr(pss->buf, '/'))
153 				s++;
154 			else
155 				s = pss->buf;
156 			if ((i = strlen(s)) > 4 && !strcasecmp(s + i - 4, ".exe"))
157 				*(s + i - 4) = 0;
158 			pe->command = s;
159 		}
160 	}
161 	pe->flags = pr->process_state;
162 	pe->pid = pr->pid;
163 	pe->npid = pr->dwProcessId;
164 	pe->ppid = pr->ppid;
165 	pe->rss = pr->rusage_self.ru_maxrss;
166 	pe->size = pr->rusage_self.ru_idrss;
167 	pe->start = PR_START(pr);
168 	pe->time = PR_TIME(pr);
169 	return 1;
170 }
171 
172 static char*
173 cygwin_ttyname(Pss_t* pss, register Pssent_t* pe)
174 {
175 	if (pe->tty < 0)
176 		return "?";
177 	if (pe->tty == (Pss_dev_t)TTY_CONSOLE)
178 		return "con";
179 	sfsprintf(pss->buf, sizeof(pss->buf), "%I*d", sizeof(pe->tty), pe->tty);
180 	return pss->buf;
181 }
182 
183 static Pss_dev_t
184 cygwin_ttymap(Pss_t* pss, Pss_dev_t dev)
185 {
186 	return minor(dev);
187 }
188 
189 static Pssmeth_t cygwin_method =
190 {
191 	"cygwin",
192 	"[-version?@(#)$Id: pss cygwin (AT&T Research) 2003-02-01 $\n]"
193 	"[-author?Glenn Fowler <gsf@research.att.com>]",
194 	PSS_all,
195 	cygwin_init,
196 	cygwin_read,
197 	cygwin_part,
198 	cygwin_full,
199 	0,
200 	cygwin_ttyname,
201 	cygwin_ttymap,
202 	cygwin_done
203 };
204 
205 Pssmeth_t*	_pss_method = &cygwin_method;
206 
207 #endif
208