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