00001
00017 #include "pm.h"
00018 #include <minix/callnr.h>
00019 #include <signal.h>
00020 #include <sys/svrctl.h>
00021 #include <sys/resource.h>
00022 #include <minix/com.h>
00023 #include <minix/config.h>
00024 #include <minix/type.h>
00025 #include <string.h>
00026 #include <lib.h>
00027 #include "mproc.h"
00028 #include "param.h"
00029 #include "../../kernel/proc.h"
00030
00031
00032
00033
00034 PUBLIC int do_allocmem()
00035 {
00036 vir_clicks mem_clicks;
00037 phys_clicks mem_base;
00038
00039 mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
00040 mem_base = alloc_mem(mem_clicks);
00041 if (mem_base == NO_MEM) return(ENOMEM);
00042 mp->mp_reply.membase = (phys_bytes) (mem_base << CLICK_SHIFT);
00043 return(OK);
00044 }
00045
00046
00047
00048
00049 PUBLIC int do_freemem()
00050 {
00051 vir_clicks mem_clicks;
00052 phys_clicks mem_base;
00053
00054 mem_clicks = (m_in.memsize + CLICK_SIZE -1 ) >> CLICK_SHIFT;
00055 mem_base = (m_in.membase + CLICK_SIZE -1 ) >> CLICK_SHIFT;
00056 free_mem(mem_base, mem_clicks);
00057 return(OK);
00058 }
00059
00060
00061
00062
00063 PUBLIC int do_procstat()
00064 {
00065
00066
00067
00068
00069
00070
00071 if (m_in.stat_nr == SELF) {
00072 mp->mp_reply.sig_set = mp->mp_sigpending;
00073 sigemptyset(&mp->mp_sigpending);
00074 }
00075 else {
00076 return(ENOSYS);
00077 }
00078 return(OK);
00079 }
00080
00081
00082
00083
00084 PUBLIC int do_getsysinfo()
00085 {
00086 struct mproc *proc_addr;
00087 vir_bytes src_addr, dst_addr;
00088 struct kinfo kinfo;
00089 struct loadinfo loadinfo;
00090 static struct proc proctab[NR_PROCS+NR_TASKS];
00091 size_t len;
00092 static struct pm_mem_info pmi;
00093 int s, r;
00094 size_t holesize;
00095
00096 switch(m_in.info_what) {
00097 case SI_KINFO:
00098 sys_getkinfo(&kinfo);
00099 src_addr = (vir_bytes) &kinfo;
00100 len = sizeof(struct kinfo);
00101 break;
00102 case SI_PROC_ADDR:
00103 proc_addr = &mproc[0];
00104 src_addr = (vir_bytes) &proc_addr;
00105 len = sizeof(struct mproc *);
00106 break;
00107 case SI_PROC_TAB:
00108 src_addr = (vir_bytes) mproc;
00109 len = sizeof(struct mproc) * NR_PROCS;
00110 break;
00111 case SI_KPROC_TAB:
00112 if((r=sys_getproctab(proctab)) != OK)
00113 return r;
00114 src_addr = (vir_bytes) proctab;
00115 len = sizeof(proctab);
00116 break;
00117 case SI_MEM_ALLOC:
00118 holesize = sizeof(pmi.pmi_holes);
00119 if((r=mem_holes_copy(pmi.pmi_holes, &holesize,
00120 &pmi.pmi_hi_watermark)) != OK)
00121 return r;
00122 src_addr = (vir_bytes) &pmi;
00123 len = sizeof(pmi);
00124 break;
00125 case SI_LOADINFO:
00126 sys_getloadinfo(&loadinfo);
00127 src_addr = (vir_bytes) &loadinfo;
00128 len = sizeof(struct loadinfo);
00129 break;
00130 default:
00131 return(EINVAL);
00132 }
00133
00134 dst_addr = (vir_bytes) m_in.info_where;
00135 if (OK != (s=sys_datacopy(SELF, src_addr, who_e, dst_addr, len)))
00136 return(s);
00137 return(OK);
00138 }
00139
00140
00141
00142
00143 PUBLIC int do_getprocnr()
00144 {
00145 register struct mproc *rmp;
00146 static char search_key[PROC_NAME_LEN+1];
00147 int key_len;
00148 int s;
00149
00150 if (m_in.pid >= 0) {
00151 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
00152 if ((rmp->mp_flags & IN_USE) && (rmp->mp_pid==m_in.pid)) {
00153 mp->mp_reply.endpt = rmp->mp_endpoint;
00154 return(OK);
00155 }
00156 }
00157 return(ESRCH);
00158 } else if (m_in.namelen > 0) {
00159 key_len = MIN(m_in.namelen, PROC_NAME_LEN);
00160 if (OK != (s=sys_datacopy(who_e, (vir_bytes) m_in.addr,
00161 SELF, (vir_bytes) search_key, key_len)))
00162 return(s);
00163 search_key[key_len] = '\0';
00164 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
00165 if (((rmp->mp_flags & (IN_USE | ZOMBIE)) == IN_USE) &&
00166 strncmp(rmp->mp_name, search_key, key_len)==0) {
00167 mp->mp_reply.endpt = rmp->mp_endpoint;
00168 return(OK);
00169 }
00170 }
00171 return(ESRCH);
00172 } else {
00173 mp->mp_reply.endpt = who_e;
00174 mp->mp_reply.pendpt = mproc[mp->mp_parent].mp_endpoint;
00175 }
00176
00177 return(OK);
00178 }
00179
00180
00181
00182
00183 PUBLIC int do_reboot()
00184 {
00185 char monitor_code[256];
00186 vir_bytes code_addr;
00187 int code_size;
00188 int abort_flag;
00189
00190
00191 if (mp->mp_effuid != SUPER_USER) return(EPERM);
00192
00193
00194 abort_flag = (unsigned) m_in.reboot_flag;
00195 if (abort_flag >= RBT_INVALID) return(EINVAL);
00196 if (RBT_MONITOR == abort_flag) {
00197 int r;
00198 if(m_in.reboot_strlen >= sizeof(monitor_code))
00199 return EINVAL;
00200 if((r = sys_datacopy(who_e, (vir_bytes) m_in.reboot_code,
00201 SELF, (vir_bytes) monitor_code, m_in.reboot_strlen)) != OK)
00202 return r;
00203 code_addr = (vir_bytes) monitor_code;
00204 monitor_code[m_in.reboot_strlen] = '\0';
00205 code_size = m_in.reboot_strlen + 1;
00206 }
00207
00208
00209
00210
00211
00212
00213 check_sig(-1, SIGKILL);
00214 sys_nice(INIT_PROC_NR, PRIO_STOP);
00215 tell_fs(REBOOT, 0, 0, 0);
00216
00217
00218
00219
00220 sys_abort(abort_flag, PM_PROC_NR, code_addr, code_size);
00221 return(SUSPEND);
00222 }
00223
00224
00225
00226
00227 PUBLIC int do_getsetpriority()
00228 {
00229 int arg_which, arg_who, arg_pri;
00230 int rmp_nr;
00231 struct mproc *rmp;
00232
00233 arg_which = m_in.m1_i1;
00234 arg_who = m_in.m1_i2;
00235 arg_pri = m_in.m1_i3;
00236
00237
00238
00239
00240 if (arg_which != PRIO_PROCESS)
00241 return(EINVAL);
00242
00243 if (arg_who == 0)
00244 rmp_nr = who_p;
00245 else
00246 if ((rmp_nr = proc_from_pid(arg_who)) < 0)
00247 return(ESRCH);
00248
00249 rmp = &mproc[rmp_nr];
00250
00251 if (mp->mp_effuid != SUPER_USER &&
00252 mp->mp_effuid != rmp->mp_effuid && mp->mp_effuid != rmp->mp_realuid)
00253 return EPERM;
00254
00255
00256 if (call_nr == GETPRIORITY) {
00257 return(rmp->mp_nice - PRIO_MIN);
00258 }
00259
00260
00261 if (rmp->mp_nice > arg_pri && mp->mp_effuid != SUPER_USER)
00262 return(EACCES);
00263
00264
00265 rmp->mp_nice = arg_pri;
00266 return sys_nice(rmp->mp_endpoint, arg_pri);
00267 }
00268
00269
00270
00271
00272 PUBLIC int do_svrctl()
00273 {
00274 int s, req;
00275 vir_bytes ptr;
00276 #define MAX_LOCAL_PARAMS 2
00277 static struct {
00278 char name[30];
00279 char value[30];
00280 } local_param_overrides[MAX_LOCAL_PARAMS];
00281 static int local_params = 0;
00282
00283 req = m_in.svrctl_req;
00284 ptr = (vir_bytes) m_in.svrctl_argp;
00285
00286
00287 if (((req >> 8) & 0xFF) != 'M') return(EINVAL);
00288
00289
00290 switch(req) {
00291 case MMSETPARAM:
00292 case MMGETPARAM: {
00293 struct sysgetenv sysgetenv;
00294 char search_key[64];
00295 char *val_start;
00296 size_t val_len;
00297 size_t copy_len;
00298
00299
00300 if (sys_datacopy(who_e, ptr, SELF, (vir_bytes) &sysgetenv,
00301 sizeof(sysgetenv)) != OK) return(EFAULT);
00302
00303
00304 if (req == MMSETPARAM) {
00305 if (local_params >= MAX_LOCAL_PARAMS) return ENOSPC;
00306 if (sysgetenv.keylen <= 0
00307 || sysgetenv.keylen >=
00308 sizeof(local_param_overrides[local_params].name)
00309 || sysgetenv.vallen <= 0
00310 || sysgetenv.vallen >=
00311 sizeof(local_param_overrides[local_params].value))
00312 return EINVAL;
00313
00314 if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
00315 SELF, (vir_bytes) local_param_overrides[local_params].name,
00316 sysgetenv.keylen)) != OK)
00317 return s;
00318 if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.val,
00319 SELF, (vir_bytes) local_param_overrides[local_params].value,
00320 sysgetenv.keylen)) != OK)
00321 return s;
00322 local_param_overrides[local_params].name[sysgetenv.keylen] = '\0';
00323 local_param_overrides[local_params].value[sysgetenv.vallen] = '\0';
00324
00325 local_params++;
00326
00327 return OK;
00328 }
00329
00330 if (sysgetenv.keylen == 0) {
00331 val_start = monitor_params;
00332 val_len = sizeof(monitor_params);
00333 }
00334 else {
00335 int p;
00336
00337 if (sysgetenv.keylen > sizeof(search_key)) return(EINVAL);
00338 if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
00339 SELF, (vir_bytes) search_key, sysgetenv.keylen)) != OK)
00340 return(s);
00341
00342
00343
00344
00345 search_key[sysgetenv.keylen-1]= '\0';
00346 for(p = 0; p < local_params; p++) {
00347 if (!strcmp(search_key, local_param_overrides[p].name)) {
00348 val_start = local_param_overrides[p].value;
00349 break;
00350 }
00351 }
00352 if (p >= local_params && (val_start = find_param(search_key)) == NULL)
00353 return(ESRCH);
00354 val_len = strlen(val_start) + 1;
00355 }
00356
00357
00358 if (val_len > sysgetenv.vallen)
00359 return E2BIG;
00360
00361
00362 copy_len = MIN(val_len, sysgetenv.vallen);
00363 if ((s=sys_datacopy(SELF, (vir_bytes) val_start,
00364 who_e, (vir_bytes) sysgetenv.val, copy_len)) != OK)
00365 return(s);
00366
00367 return OK;
00368 }
00369
00370 #if ENABLE_SWAP
00371 case MMSWAPON: {
00372 struct mmswapon swapon;
00373
00374 if (mp->mp_effuid != SUPER_USER) return(EPERM);
00375
00376 if (sys_datacopy(who_e, (phys_bytes) ptr,
00377 PM_PROC_NR, (phys_bytes) &swapon,
00378 (phys_bytes) sizeof(swapon)) != OK) return(EFAULT);
00379
00380 return(swap_on(swapon.file, swapon.offset, swapon.size)); }
00381
00382 case MMSWAPOFF: {
00383 if (mp->mp_effuid != SUPER_USER) return(EPERM);
00384
00385 return(swap_off()); }
00386 #endif
00387
00388 default:
00389 return(EINVAL);
00390 }
00391 }
00392
00393
00394
00395
00396 PUBLIC ssize_t _read_pm(fd, buffer, nbytes, seg, ep)
00397 int fd;
00398 void *buffer;
00399 size_t nbytes;
00400 int seg;
00401 int ep;
00402 {
00403 message m;
00404
00405 m.m1_i1 = _PM_SEG_FLAG | fd;
00406 m.m1_i2 = nbytes;
00407 m.m1_p1 = (char *) buffer;
00408 m.m1_p2 = (char *) seg;
00409 m.m1_p3 = (char *) ep;
00410 return(_syscall(FS_PROC_NR, READ, &m));
00411 }
00412
00413
00414
00415
00416 PUBLIC ssize_t _write_pm(fd, buffer, nbytes, seg, ep)
00417 int fd;
00418 void *buffer;
00419 size_t nbytes;
00420 int seg;
00421 int ep;
00422 {
00423 message m;
00424
00425 m.m1_i1 = _PM_SEG_FLAG | fd;
00426 m.m1_i2 = nbytes;
00427 m.m1_p1 = (char *) buffer;
00428 m.m1_p2 = (char *) seg;
00429 m.m1_p3 = (char *) ep;
00430 return(_syscall(FS_PROC_NR, WRITE, &m));
00431 }
00432