xref: /minix3/minix/servers/pm/misc.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* Miscellaneous system calls.				Author: Kees J. Bot
2*433d6423SLionel Sambuc  *								31 Mar 2000
3*433d6423SLionel Sambuc  * The entry points into this file are:
4*433d6423SLionel Sambuc  *   do_reboot: kill all processes, then reboot system
5*433d6423SLionel Sambuc  *   do_getsysinfo: request copy of PM data structure  (Jorrit N. Herder)
6*433d6423SLionel Sambuc  *   do_getprocnr: lookup endpoint by process ID
7*433d6423SLionel Sambuc  *   do_getepinfo: get the pid/uid/gid of a process given its endpoint
8*433d6423SLionel Sambuc  *   do_getsetpriority: get/set process priority
9*433d6423SLionel Sambuc  *   do_svrctl: process manager control
10*433d6423SLionel Sambuc  */
11*433d6423SLionel Sambuc 
12*433d6423SLionel Sambuc #include "pm.h"
13*433d6423SLionel Sambuc #include <minix/callnr.h>
14*433d6423SLionel Sambuc #include <signal.h>
15*433d6423SLionel Sambuc #include <sys/svrctl.h>
16*433d6423SLionel Sambuc #include <sys/reboot.h>
17*433d6423SLionel Sambuc #include <sys/resource.h>
18*433d6423SLionel Sambuc #include <sys/utsname.h>
19*433d6423SLionel Sambuc #include <minix/com.h>
20*433d6423SLionel Sambuc #include <minix/config.h>
21*433d6423SLionel Sambuc #include <minix/sysinfo.h>
22*433d6423SLionel Sambuc #include <minix/type.h>
23*433d6423SLionel Sambuc #include <minix/ds.h>
24*433d6423SLionel Sambuc #include <machine/archtypes.h>
25*433d6423SLionel Sambuc #include <lib.h>
26*433d6423SLionel Sambuc #include <assert.h>
27*433d6423SLionel Sambuc #include "mproc.h"
28*433d6423SLionel Sambuc #include "kernel/proc.h"
29*433d6423SLionel Sambuc 
30*433d6423SLionel Sambuc struct utsname uts_val = {
31*433d6423SLionel Sambuc   OS_NAME,		/* system name */
32*433d6423SLionel Sambuc   "noname",		/* node/network name */
33*433d6423SLionel Sambuc   OS_RELEASE,		/* O.S. release (e.g. 3.3.0) */
34*433d6423SLionel Sambuc   OS_VERSION,		/* O.S. version (e.g. Minix 3.3.0 (GENERIC)) */
35*433d6423SLionel Sambuc   "xyzzy",		/* machine (cpu) type (filled in later) */
36*433d6423SLionel Sambuc #if defined(__i386__)
37*433d6423SLionel Sambuc   "i386",		/* architecture */
38*433d6423SLionel Sambuc #elif defined(__arm__)
39*433d6423SLionel Sambuc   "arm",		/* architecture */
40*433d6423SLionel Sambuc #else
41*433d6423SLionel Sambuc #error			/* oops, no 'uname -mk' */
42*433d6423SLionel Sambuc #endif
43*433d6423SLionel Sambuc };
44*433d6423SLionel Sambuc 
45*433d6423SLionel Sambuc static char *uts_tbl[] = {
46*433d6423SLionel Sambuc   uts_val.arch,
47*433d6423SLionel Sambuc   NULL,			/* No kernel architecture */
48*433d6423SLionel Sambuc   uts_val.machine,
49*433d6423SLionel Sambuc   NULL,			/* No hostname */
50*433d6423SLionel Sambuc   uts_val.nodename,
51*433d6423SLionel Sambuc   uts_val.release,
52*433d6423SLionel Sambuc   uts_val.version,
53*433d6423SLionel Sambuc   uts_val.sysname,
54*433d6423SLionel Sambuc   NULL,			/* No bus */			/* No bus */
55*433d6423SLionel Sambuc };
56*433d6423SLionel Sambuc 
57*433d6423SLionel Sambuc #if ENABLE_SYSCALL_STATS
58*433d6423SLionel Sambuc unsigned long calls_stats[NR_PM_CALLS];
59*433d6423SLionel Sambuc #endif
60*433d6423SLionel Sambuc 
61*433d6423SLionel Sambuc /*===========================================================================*
62*433d6423SLionel Sambuc  *				do_sysuname				     *
63*433d6423SLionel Sambuc  *===========================================================================*/
64*433d6423SLionel Sambuc int do_sysuname()
65*433d6423SLionel Sambuc {
66*433d6423SLionel Sambuc /* Set or get uname strings. */
67*433d6423SLionel Sambuc   int r;
68*433d6423SLionel Sambuc   size_t n;
69*433d6423SLionel Sambuc   char *string;
70*433d6423SLionel Sambuc #if 0 /* for updates */
71*433d6423SLionel Sambuc   char tmp[sizeof(uts_val.nodename)];
72*433d6423SLionel Sambuc   static short sizes[] = {
73*433d6423SLionel Sambuc 	0,	/* arch, (0 = read-only) */
74*433d6423SLionel Sambuc 	0,	/* kernel */
75*433d6423SLionel Sambuc 	0,	/* machine */
76*433d6423SLionel Sambuc 	0,	/* sizeof(uts_val.hostname), */
77*433d6423SLionel Sambuc 	sizeof(uts_val.nodename),
78*433d6423SLionel Sambuc 	0,	/* release */
79*433d6423SLionel Sambuc 	0,	/* version */
80*433d6423SLionel Sambuc 	0,	/* sysname */
81*433d6423SLionel Sambuc   };
82*433d6423SLionel Sambuc #endif
83*433d6423SLionel Sambuc 
84*433d6423SLionel Sambuc   if (m_in.m_lc_pm_sysuname.field >= _UTS_MAX) return(EINVAL);
85*433d6423SLionel Sambuc 
86*433d6423SLionel Sambuc   string = uts_tbl[m_in.m_lc_pm_sysuname.field];
87*433d6423SLionel Sambuc   if (string == NULL)
88*433d6423SLionel Sambuc 	return EINVAL;	/* Unsupported field */
89*433d6423SLionel Sambuc 
90*433d6423SLionel Sambuc   switch (m_in.m_lc_pm_sysuname.req) {
91*433d6423SLionel Sambuc   case _UTS_GET:
92*433d6423SLionel Sambuc 	/* Copy an uname string to the user. */
93*433d6423SLionel Sambuc 	n = strlen(string) + 1;
94*433d6423SLionel Sambuc 	if (n > m_in.m_lc_pm_sysuname.len) n = m_in.m_lc_pm_sysuname.len;
95*433d6423SLionel Sambuc 	r = sys_datacopy(SELF, (vir_bytes)string, mp->mp_endpoint,
96*433d6423SLionel Sambuc 		m_in.m_lc_pm_sysuname.value, (phys_bytes)n);
97*433d6423SLionel Sambuc 	if (r < 0) return(r);
98*433d6423SLionel Sambuc 	break;
99*433d6423SLionel Sambuc 
100*433d6423SLionel Sambuc #if 0	/* no updates yet */
101*433d6423SLionel Sambuc   case _UTS_SET:
102*433d6423SLionel Sambuc 	/* Set an uname string, needs root power. */
103*433d6423SLionel Sambuc 	len = sizes[m_in.m_lc_pm_sysuname.field];
104*433d6423SLionel Sambuc 	if (mp->mp_effuid != 0 || len == 0) return(EPERM);
105*433d6423SLionel Sambuc 	n = len < m_in.m_lc_pm_sysuname.len ? len : m_in.m_lc_pm_sysuname.len;
106*433d6423SLionel Sambuc 	if (n <= 0) return(EINVAL);
107*433d6423SLionel Sambuc 	r = sys_datacopy(mp->mp_endpoint, m_in.m_lc_pm_sysuname.value, SELF,
108*433d6423SLionel Sambuc 		(phys_bytes)tmp, (phys_bytes)n);
109*433d6423SLionel Sambuc 	if (r < 0) return(r);
110*433d6423SLionel Sambuc 	tmp[n-1] = 0;
111*433d6423SLionel Sambuc 	strcpy(string, tmp);
112*433d6423SLionel Sambuc 	break;
113*433d6423SLionel Sambuc #endif
114*433d6423SLionel Sambuc 
115*433d6423SLionel Sambuc   default:
116*433d6423SLionel Sambuc 	return(EINVAL);
117*433d6423SLionel Sambuc   }
118*433d6423SLionel Sambuc   /* Return the number of bytes moved. */
119*433d6423SLionel Sambuc   return(n);
120*433d6423SLionel Sambuc }
121*433d6423SLionel Sambuc 
122*433d6423SLionel Sambuc 
123*433d6423SLionel Sambuc /*===========================================================================*
124*433d6423SLionel Sambuc  *				do_getsysinfo			       	     *
125*433d6423SLionel Sambuc  *===========================================================================*/
126*433d6423SLionel Sambuc int do_getsysinfo()
127*433d6423SLionel Sambuc {
128*433d6423SLionel Sambuc   vir_bytes src_addr, dst_addr;
129*433d6423SLionel Sambuc   size_t len;
130*433d6423SLionel Sambuc 
131*433d6423SLionel Sambuc   /* This call leaks important information. In the future, requests from
132*433d6423SLionel Sambuc    * non-system processes should be denied.
133*433d6423SLionel Sambuc    */
134*433d6423SLionel Sambuc   if (mp->mp_effuid != 0)
135*433d6423SLionel Sambuc   {
136*433d6423SLionel Sambuc 	printf("PM: unauthorized call of do_getsysinfo by proc %d '%s'\n",
137*433d6423SLionel Sambuc 		mp->mp_endpoint, mp->mp_name);
138*433d6423SLionel Sambuc 	sys_diagctl_stacktrace(mp->mp_endpoint);
139*433d6423SLionel Sambuc 	return EPERM;
140*433d6423SLionel Sambuc   }
141*433d6423SLionel Sambuc 
142*433d6423SLionel Sambuc   switch(m_in.m_lsys_getsysinfo.what) {
143*433d6423SLionel Sambuc   case SI_PROC_TAB:			/* copy entire process table */
144*433d6423SLionel Sambuc         src_addr = (vir_bytes) mproc;
145*433d6423SLionel Sambuc         len = sizeof(struct mproc) * NR_PROCS;
146*433d6423SLionel Sambuc         break;
147*433d6423SLionel Sambuc #if ENABLE_SYSCALL_STATS
148*433d6423SLionel Sambuc   case SI_CALL_STATS:
149*433d6423SLionel Sambuc   	src_addr = (vir_bytes) calls_stats;
150*433d6423SLionel Sambuc   	len = sizeof(calls_stats);
151*433d6423SLionel Sambuc   	break;
152*433d6423SLionel Sambuc #endif
153*433d6423SLionel Sambuc   default:
154*433d6423SLionel Sambuc   	return(EINVAL);
155*433d6423SLionel Sambuc   }
156*433d6423SLionel Sambuc 
157*433d6423SLionel Sambuc   if (len != m_in.m_lsys_getsysinfo.size)
158*433d6423SLionel Sambuc 	return(EINVAL);
159*433d6423SLionel Sambuc 
160*433d6423SLionel Sambuc   dst_addr = m_in.m_lsys_getsysinfo.where;
161*433d6423SLionel Sambuc   return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
162*433d6423SLionel Sambuc }
163*433d6423SLionel Sambuc 
164*433d6423SLionel Sambuc /*===========================================================================*
165*433d6423SLionel Sambuc  *				do_getprocnr			             *
166*433d6423SLionel Sambuc  *===========================================================================*/
167*433d6423SLionel Sambuc int do_getprocnr(void)
168*433d6423SLionel Sambuc {
169*433d6423SLionel Sambuc   register struct mproc *rmp;
170*433d6423SLionel Sambuc 
171*433d6423SLionel Sambuc   /* This check should be replaced by per-call ACL checks. */
172*433d6423SLionel Sambuc   if (who_e != RS_PROC_NR) {
173*433d6423SLionel Sambuc 	printf("PM: unauthorized call of do_getprocnr by %d\n", who_e);
174*433d6423SLionel Sambuc 	return EPERM;
175*433d6423SLionel Sambuc   }
176*433d6423SLionel Sambuc 
177*433d6423SLionel Sambuc   if ((rmp = find_proc(m_in.m_lsys_pm_getprocnr.pid)) == NULL)
178*433d6423SLionel Sambuc 	return(ESRCH);
179*433d6423SLionel Sambuc 
180*433d6423SLionel Sambuc   mp->mp_reply.m_pm_lsys_getprocnr.endpt = rmp->mp_endpoint;
181*433d6423SLionel Sambuc   return(OK);
182*433d6423SLionel Sambuc }
183*433d6423SLionel Sambuc 
184*433d6423SLionel Sambuc /*===========================================================================*
185*433d6423SLionel Sambuc  *				do_getepinfo			             *
186*433d6423SLionel Sambuc  *===========================================================================*/
187*433d6423SLionel Sambuc int do_getepinfo(void)
188*433d6423SLionel Sambuc {
189*433d6423SLionel Sambuc   struct mproc *rmp;
190*433d6423SLionel Sambuc   endpoint_t ep;
191*433d6423SLionel Sambuc   int slot;
192*433d6423SLionel Sambuc 
193*433d6423SLionel Sambuc   ep = m_in.m_lsys_pm_getepinfo.endpt;
194*433d6423SLionel Sambuc   if (pm_isokendpt(ep, &slot) != OK)
195*433d6423SLionel Sambuc 	return(ESRCH);
196*433d6423SLionel Sambuc 
197*433d6423SLionel Sambuc   rmp = &mproc[slot];
198*433d6423SLionel Sambuc   mp->mp_reply.m_pm_lsys_getepinfo.uid = rmp->mp_effuid;
199*433d6423SLionel Sambuc   mp->mp_reply.m_pm_lsys_getepinfo.gid = rmp->mp_effgid;
200*433d6423SLionel Sambuc   return(rmp->mp_pid);
201*433d6423SLionel Sambuc }
202*433d6423SLionel Sambuc 
203*433d6423SLionel Sambuc /*===========================================================================*
204*433d6423SLionel Sambuc  *				do_reboot				     *
205*433d6423SLionel Sambuc  *===========================================================================*/
206*433d6423SLionel Sambuc int do_reboot()
207*433d6423SLionel Sambuc {
208*433d6423SLionel Sambuc   message m;
209*433d6423SLionel Sambuc 
210*433d6423SLionel Sambuc   /* Check permission to abort the system. */
211*433d6423SLionel Sambuc   if (mp->mp_effuid != SUPER_USER) return(EPERM);
212*433d6423SLionel Sambuc 
213*433d6423SLionel Sambuc   /* See how the system should be aborted. */
214*433d6423SLionel Sambuc   abort_flag = m_in.m_lc_pm_reboot.how;
215*433d6423SLionel Sambuc 
216*433d6423SLionel Sambuc   /* notify readclock (some arm systems power off via RTC alarms) */
217*433d6423SLionel Sambuc   if (abort_flag & RB_POWERDOWN) {
218*433d6423SLionel Sambuc 	endpoint_t readclock_ep;
219*433d6423SLionel Sambuc 	if (ds_retrieve_label_endpt("readclock.drv", &readclock_ep) == OK) {
220*433d6423SLionel Sambuc 		message m; /* no params to set, nothing we can do if it fails */
221*433d6423SLionel Sambuc 		_taskcall(readclock_ep, RTCDEV_PWR_OFF, &m);
222*433d6423SLionel Sambuc 	}
223*433d6423SLionel Sambuc   }
224*433d6423SLionel Sambuc 
225*433d6423SLionel Sambuc   /* Order matters here. When VFS is told to reboot, it exits all its
226*433d6423SLionel Sambuc    * processes, and then would be confused if they're exited again by
227*433d6423SLionel Sambuc    * SIGKILL. So first kill, then reboot.
228*433d6423SLionel Sambuc    */
229*433d6423SLionel Sambuc 
230*433d6423SLionel Sambuc   check_sig(-1, SIGKILL, FALSE /* ksig*/); /* kill all users except init */
231*433d6423SLionel Sambuc   sys_stop(INIT_PROC_NR);		   /* stop init, but keep it around */
232*433d6423SLionel Sambuc 
233*433d6423SLionel Sambuc   /* Tell VFS to reboot */
234*433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
235*433d6423SLionel Sambuc   m.m_type = VFS_PM_REBOOT;
236*433d6423SLionel Sambuc 
237*433d6423SLionel Sambuc   tell_vfs(&mproc[VFS_PROC_NR], &m);
238*433d6423SLionel Sambuc 
239*433d6423SLionel Sambuc   return(SUSPEND);			/* don't reply to caller */
240*433d6423SLionel Sambuc }
241*433d6423SLionel Sambuc 
242*433d6423SLionel Sambuc /*===========================================================================*
243*433d6423SLionel Sambuc  *				do_getsetpriority			     *
244*433d6423SLionel Sambuc  *===========================================================================*/
245*433d6423SLionel Sambuc int do_getsetpriority()
246*433d6423SLionel Sambuc {
247*433d6423SLionel Sambuc 	int r, arg_which, arg_who, arg_pri;
248*433d6423SLionel Sambuc 	struct mproc *rmp;
249*433d6423SLionel Sambuc 
250*433d6423SLionel Sambuc 	arg_which = m_in.m_lc_pm_priority.which;
251*433d6423SLionel Sambuc 	arg_who = m_in.m_lc_pm_priority.who;
252*433d6423SLionel Sambuc 	arg_pri = m_in.m_lc_pm_priority.prio;	/* for SETPRIORITY */
253*433d6423SLionel Sambuc 
254*433d6423SLionel Sambuc 	/* Code common to GETPRIORITY and SETPRIORITY. */
255*433d6423SLionel Sambuc 
256*433d6423SLionel Sambuc 	/* Only support PRIO_PROCESS for now. */
257*433d6423SLionel Sambuc 	if (arg_which != PRIO_PROCESS)
258*433d6423SLionel Sambuc 		return(EINVAL);
259*433d6423SLionel Sambuc 
260*433d6423SLionel Sambuc 	if (arg_who == 0)
261*433d6423SLionel Sambuc 		rmp = mp;
262*433d6423SLionel Sambuc 	else
263*433d6423SLionel Sambuc 		if ((rmp = find_proc(arg_who)) == NULL)
264*433d6423SLionel Sambuc 			return(ESRCH);
265*433d6423SLionel Sambuc 
266*433d6423SLionel Sambuc 	if (mp->mp_effuid != SUPER_USER &&
267*433d6423SLionel Sambuc 	   mp->mp_effuid != rmp->mp_effuid && mp->mp_effuid != rmp->mp_realuid)
268*433d6423SLionel Sambuc 		return EPERM;
269*433d6423SLionel Sambuc 
270*433d6423SLionel Sambuc 	/* If GET, that's it. */
271*433d6423SLionel Sambuc 	if (call_nr == PM_GETPRIORITY) {
272*433d6423SLionel Sambuc 		return(rmp->mp_nice - PRIO_MIN);
273*433d6423SLionel Sambuc 	}
274*433d6423SLionel Sambuc 
275*433d6423SLionel Sambuc 	/* Only root is allowed to reduce the nice level. */
276*433d6423SLionel Sambuc 	if (rmp->mp_nice > arg_pri && mp->mp_effuid != SUPER_USER)
277*433d6423SLionel Sambuc 		return(EACCES);
278*433d6423SLionel Sambuc 
279*433d6423SLionel Sambuc 	/* We're SET, and it's allowed.
280*433d6423SLionel Sambuc 	 *
281*433d6423SLionel Sambuc 	 * The value passed in is currently between PRIO_MIN and PRIO_MAX.
282*433d6423SLionel Sambuc 	 * We have to scale this between MIN_USER_Q and MAX_USER_Q to match
283*433d6423SLionel Sambuc 	 * the kernel's scheduling queues.
284*433d6423SLionel Sambuc 	 */
285*433d6423SLionel Sambuc 
286*433d6423SLionel Sambuc 	if ((r = sched_nice(rmp, arg_pri)) != OK) {
287*433d6423SLionel Sambuc 		return r;
288*433d6423SLionel Sambuc 	}
289*433d6423SLionel Sambuc 
290*433d6423SLionel Sambuc 	rmp->mp_nice = arg_pri;
291*433d6423SLionel Sambuc 	return(OK);
292*433d6423SLionel Sambuc }
293*433d6423SLionel Sambuc 
294*433d6423SLionel Sambuc /*===========================================================================*
295*433d6423SLionel Sambuc  *				do_svrctl				     *
296*433d6423SLionel Sambuc  *===========================================================================*/
297*433d6423SLionel Sambuc int do_svrctl()
298*433d6423SLionel Sambuc {
299*433d6423SLionel Sambuc   int s, req;
300*433d6423SLionel Sambuc   vir_bytes ptr;
301*433d6423SLionel Sambuc #define MAX_LOCAL_PARAMS 2
302*433d6423SLionel Sambuc   static struct {
303*433d6423SLionel Sambuc   	char name[30];
304*433d6423SLionel Sambuc   	char value[30];
305*433d6423SLionel Sambuc   } local_param_overrides[MAX_LOCAL_PARAMS];
306*433d6423SLionel Sambuc   static int local_params = 0;
307*433d6423SLionel Sambuc 
308*433d6423SLionel Sambuc   req = m_in.m_lsys_svrctl.request;
309*433d6423SLionel Sambuc   ptr = m_in.m_lsys_svrctl.arg;
310*433d6423SLionel Sambuc 
311*433d6423SLionel Sambuc   /* Is the request indeed for the PM? */
312*433d6423SLionel Sambuc   if (((req >> 8) & 0xFF) != 'M') return(EINVAL);
313*433d6423SLionel Sambuc 
314*433d6423SLionel Sambuc   /* Control operations local to the PM. */
315*433d6423SLionel Sambuc   switch(req) {
316*433d6423SLionel Sambuc   case PMSETPARAM:
317*433d6423SLionel Sambuc   case PMGETPARAM: {
318*433d6423SLionel Sambuc       struct sysgetenv sysgetenv;
319*433d6423SLionel Sambuc       char search_key[64];
320*433d6423SLionel Sambuc       char *val_start;
321*433d6423SLionel Sambuc       size_t val_len;
322*433d6423SLionel Sambuc       size_t copy_len;
323*433d6423SLionel Sambuc 
324*433d6423SLionel Sambuc       /* Copy sysgetenv structure to PM. */
325*433d6423SLionel Sambuc       if (sys_datacopy(who_e, ptr, SELF, (vir_bytes) &sysgetenv,
326*433d6423SLionel Sambuc               sizeof(sysgetenv)) != OK) return(EFAULT);
327*433d6423SLionel Sambuc 
328*433d6423SLionel Sambuc       /* Set a param override? */
329*433d6423SLionel Sambuc       if (req == PMSETPARAM) {
330*433d6423SLionel Sambuc   	if (local_params >= MAX_LOCAL_PARAMS) return ENOSPC;
331*433d6423SLionel Sambuc   	if (sysgetenv.keylen <= 0
332*433d6423SLionel Sambuc   	 || sysgetenv.keylen >=
333*433d6423SLionel Sambuc   	 	 sizeof(local_param_overrides[local_params].name)
334*433d6423SLionel Sambuc   	 || sysgetenv.vallen <= 0
335*433d6423SLionel Sambuc   	 || sysgetenv.vallen >=
336*433d6423SLionel Sambuc   	 	 sizeof(local_param_overrides[local_params].value))
337*433d6423SLionel Sambuc   		return EINVAL;
338*433d6423SLionel Sambuc 
339*433d6423SLionel Sambuc           if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
340*433d6423SLionel Sambuc             SELF, (vir_bytes) local_param_overrides[local_params].name,
341*433d6423SLionel Sambuc                sysgetenv.keylen)) != OK)
342*433d6423SLionel Sambuc                	return s;
343*433d6423SLionel Sambuc           if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.val,
344*433d6423SLionel Sambuc             SELF, (vir_bytes) local_param_overrides[local_params].value,
345*433d6423SLionel Sambuc               sysgetenv.vallen)) != OK)
346*433d6423SLionel Sambuc                	return s;
347*433d6423SLionel Sambuc             local_param_overrides[local_params].name[sysgetenv.keylen] = '\0';
348*433d6423SLionel Sambuc             local_param_overrides[local_params].value[sysgetenv.vallen] = '\0';
349*433d6423SLionel Sambuc 
350*433d6423SLionel Sambuc   	local_params++;
351*433d6423SLionel Sambuc 
352*433d6423SLionel Sambuc   	return OK;
353*433d6423SLionel Sambuc       }
354*433d6423SLionel Sambuc 
355*433d6423SLionel Sambuc       if (sysgetenv.keylen == 0) {	/* copy all parameters */
356*433d6423SLionel Sambuc           val_start = monitor_params;
357*433d6423SLionel Sambuc           val_len = sizeof(monitor_params);
358*433d6423SLionel Sambuc       }
359*433d6423SLionel Sambuc       else {				/* lookup value for key */
360*433d6423SLionel Sambuc       	  int p;
361*433d6423SLionel Sambuc           /* Try to get a copy of the requested key. */
362*433d6423SLionel Sambuc           if (sysgetenv.keylen > sizeof(search_key)) return(EINVAL);
363*433d6423SLionel Sambuc           if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
364*433d6423SLionel Sambuc                   SELF, (vir_bytes) search_key, sysgetenv.keylen)) != OK)
365*433d6423SLionel Sambuc               return(s);
366*433d6423SLionel Sambuc 
367*433d6423SLionel Sambuc           /* Make sure key is null-terminated and lookup value.
368*433d6423SLionel Sambuc            * First check local overrides.
369*433d6423SLionel Sambuc            */
370*433d6423SLionel Sambuc           search_key[sysgetenv.keylen-1]= '\0';
371*433d6423SLionel Sambuc           for(p = 0; p < local_params; p++) {
372*433d6423SLionel Sambuc           	if (!strcmp(search_key, local_param_overrides[p].name)) {
373*433d6423SLionel Sambuc           		val_start = local_param_overrides[p].value;
374*433d6423SLionel Sambuc           		break;
375*433d6423SLionel Sambuc           	}
376*433d6423SLionel Sambuc           }
377*433d6423SLionel Sambuc           if (p >= local_params && (val_start = find_param(search_key)) == NULL)
378*433d6423SLionel Sambuc                return(ESRCH);
379*433d6423SLionel Sambuc           val_len = strlen(val_start) + 1;
380*433d6423SLionel Sambuc       }
381*433d6423SLionel Sambuc 
382*433d6423SLionel Sambuc       /* See if it fits in the client's buffer. */
383*433d6423SLionel Sambuc       if (val_len > sysgetenv.vallen)
384*433d6423SLionel Sambuc       	return E2BIG;
385*433d6423SLionel Sambuc 
386*433d6423SLionel Sambuc       /* Value found, make the actual copy (as far as possible). */
387*433d6423SLionel Sambuc       copy_len = MIN(val_len, sysgetenv.vallen);
388*433d6423SLionel Sambuc       if ((s=sys_datacopy(SELF, (vir_bytes) val_start,
389*433d6423SLionel Sambuc               who_e, (vir_bytes) sysgetenv.val, copy_len)) != OK)
390*433d6423SLionel Sambuc           return(s);
391*433d6423SLionel Sambuc 
392*433d6423SLionel Sambuc       return OK;
393*433d6423SLionel Sambuc   }
394*433d6423SLionel Sambuc 
395*433d6423SLionel Sambuc   default:
396*433d6423SLionel Sambuc 	return(EINVAL);
397*433d6423SLionel Sambuc   }
398*433d6423SLionel Sambuc }
399*433d6423SLionel Sambuc 
400*433d6423SLionel Sambuc /*===========================================================================*
401*433d6423SLionel Sambuc  *				do_getrusage				     *
402*433d6423SLionel Sambuc  *===========================================================================*/
403*433d6423SLionel Sambuc int do_getrusage()
404*433d6423SLionel Sambuc {
405*433d6423SLionel Sambuc 	int res = 0;
406*433d6423SLionel Sambuc 	clock_t user_time = 0;
407*433d6423SLionel Sambuc 	clock_t sys_time = 0;
408*433d6423SLionel Sambuc 	struct rusage r_usage;
409*433d6423SLionel Sambuc 	u64_t usec;
410*433d6423SLionel Sambuc 	if (m_in.m_lc_pm_rusage.who != RUSAGE_SELF &&
411*433d6423SLionel Sambuc 		m_in.m_lc_pm_rusage.who != RUSAGE_CHILDREN)
412*433d6423SLionel Sambuc 		return EINVAL;
413*433d6423SLionel Sambuc 	if ((res = sys_getrusage(&r_usage, who_e)) < 0)
414*433d6423SLionel Sambuc 		return res;
415*433d6423SLionel Sambuc 
416*433d6423SLionel Sambuc 	if (m_in.m_lc_pm_rusage.who == RUSAGE_CHILDREN) {
417*433d6423SLionel Sambuc 		usec = mp->mp_child_utime * 1000000 / sys_hz();
418*433d6423SLionel Sambuc 		r_usage.ru_utime.tv_sec = usec / 1000000;
419*433d6423SLionel Sambuc 		r_usage.ru_utime.tv_usec = usec % 1000000;
420*433d6423SLionel Sambuc 		usec = mp->mp_child_stime * 1000000 / sys_hz();
421*433d6423SLionel Sambuc 		r_usage.ru_stime.tv_sec = usec / 1000000;
422*433d6423SLionel Sambuc 		r_usage.ru_stime.tv_usec = usec % 1000000;
423*433d6423SLionel Sambuc 	}
424*433d6423SLionel Sambuc 
425*433d6423SLionel Sambuc 	return sys_datacopy(SELF, (vir_bytes)&r_usage, who_e,
426*433d6423SLionel Sambuc 		m_in.m_lc_pm_rusage.addr, (vir_bytes) sizeof(r_usage));
427*433d6423SLionel Sambuc }
428