/*- * Copyright (c) 1994 Søren Schmidt * Copyright (c) 1994 Sean Eric Fagan * All rights reserved. * * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: ibcs2_misc.c,v 1.4 1995/05/02 17:14:38 ache Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int ibcs2_trace = 0; struct ibcs2_traceemu_args { int options; }; int ibcs2_traceemu(struct proc *p, struct ibcs2_traceemu_args *args, int *retval) { *retval = ibcs2_trace; ibcs2_trace = args->options; return 0; } int ibcs2_access(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'access'\n"); return access(p, args, retval); } struct ibcs2_alarm_args { unsigned int secs; }; int ibcs2_alarm(struct proc *p, struct ibcs2_alarm_args *args, int *retval) { extern struct timeval time; struct itimerval it, oit; int s; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'alarm' secs=%d\n", args->secs); it.it_value.tv_sec = (long)args->secs; it.it_value.tv_usec = 0; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 0; s = splclock(); oit = p->p_realtimer; if (timerisset(&oit.it_value)) if (timercmp(&oit.it_value, &time, <)) timerclear(&oit.it_value); else timevalsub(&oit.it_value, &time); splx(s); if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) return EINVAL; s = splclock(); untimeout(realitexpire, (caddr_t)p); if (timerisset(&it.it_value)) { timevaladd(&it.it_value, &time); timeout(realitexpire, (caddr_t)p, hzto(&it.it_value)); } p->p_realtimer = it; splx(s); if (oit.it_value.tv_usec) oit.it_value.tv_sec++; *retval = oit.it_value.tv_sec; return 0; } struct ibcs2_break_args { char *dsend; }; int ibcs2_break(struct proc *p, struct ibcs2_break_args *args, int *retval) { struct vmspace *vm = p->p_vmspace; vm_offset_t new, old; int rv, diff; extern int swap_pager_full; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'break' dsend=%x\n", (unsigned int)args->dsend); if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) return EINVAL; if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) > p->p_rlimit[RLIMIT_DATA].rlim_cur) return ENOMEM; old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); new = round_page((vm_offset_t)args->dsend); diff = new - old; if (diff > 0) { if (swap_pager_full) { return ENOMEM; } rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE); if (rv != KERN_SUCCESS) { return ENOMEM; } vm->vm_dsize += btoc(diff); } else if (diff < 0) { diff = -diff; rv = vm_map_remove(&vm->vm_map, new, new + diff); if (rv != KERN_SUCCESS) return ENOMEM; vm->vm_dsize -= btoc(diff); } return 0; } int ibcs2_chdir(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'chdir'\n"); return chdir(p, args, retval); } int ibcs2_chmod(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'chmod'\n"); return chmod(p, args, retval); } int ibcs2_chown(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'chown'\n"); return chown(p, args, retval); } int ibcs2_chroot(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'chroot'\n"); return chroot(p, args, retval); } struct exec_args { char *name; char **argv; }; int ibcs2_exec(struct proc *p, struct exec_args *args, int *retval) { struct execve_args { char *name; char **argv; char **envp; } execve_args; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'exec' name=%s\n", args->name); execve_args.name = args->name; execve_args.argv = args->argv; execve_args.envp = 0; return execve(p, &execve_args, retval); } struct ibcs2_exece_args { char *name; char **argv; char **envp; }; int ibcs2_exece(struct proc *p, struct ibcs2_exece_args *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'exece' name=%s\n", args->name); return execve(p, args, retval); } int ibcs2_exit(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'exit'\n"); return exit(p, args, retval); } int ibcs2_fork(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'fork'\n"); return fork(p, args, retval); } int ibcs2_fsync(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'fsync'\n"); return fsync(p, args, retval); } int ibcs2_getgid(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'getgid'\n"); return getgid(p, args, retval); } struct ibcs2_getgroups_args { int gidsetsize; ibcs2_gid_t *gidset; }; int ibcs2_getgroups(struct proc *p, struct ibcs2_getgroups_args *args, int *retval) { struct getgroups_args { u_int gidsetsize; gid_t *gidset; } tmp; ibcs2_gid_t *ibcs2_gidset; int i, error; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'getgroups'\n"); tmp.gidsetsize = args->gidsetsize; tmp.gidset = (gid_t *)UA_ALLOC(); ibcs2_gidset = (ibcs2_gid_t *)&tmp.gidset[NGROUPS_MAX]; if (error = getgroups(p, &tmp, retval)) return error; for (i = 0; i < retval[0]; i++) ibcs2_gidset[i] = (ibcs2_gid_t)tmp.gidset[i]; return copyout((caddr_t)ibcs2_gidset, (caddr_t)args->gidset, sizeof(ibcs2_gid_t) * retval[0]); } int ibcs2_getpid(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'getpid'\n"); return getpid(p, args, retval); } int ibcs2_getuid(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'getuid'\n"); return getuid(p, args, retval); } struct gtime_args { long *timeptr; }; int ibcs2_gtime(struct proc *p, struct gtime_args *args, int *retval) { int error = 0; struct timeval tv; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'gtime'\n"); microtime(&tv); *retval = tv.tv_sec; if (args) (long)args->timeptr = tv.tv_sec; return error; } int ibcs2_link(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'link'\n"); return link(p, args, retval); } int ibcs2_mkdir(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'mkdir'\n"); return mkdir(p, args, retval); } struct ibcs2_mknod_args { char *fname; int fmode; ibcs2_dev_t dev; }; int ibcs2_mknod(struct proc *p, struct ibcs2_mknod_args *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'mknod'\n"); if (S_ISFIFO(args->fmode)) return mkfifo(p, args, retval); return mknod(p, args, retval); } struct ibcs2_nice_args { int niceval; }; int ibcs2_nice(struct proc *p, struct ibcs2_nice_args *args, int *retval) { int error; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'nice'\n"); error = donice(p, p, args->niceval); *retval = p->p_nice; return error; } struct ibcs2_pathconf_args { long unused; int cmd; }; int ibcs2_pathconf(struct proc *p, struct ibcs2_pathconf_args *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: '(f)pathconf'\n"); switch (args->cmd) { case 0: /* _PC_LINK_MAX */ *retval = (LINK_MAX); break; case 1: /* _PC_MAX_CANON */ *retval = (MAX_CANON); break; case 2: /* _PC_MAX_INPUT */ *retval = (MAX_INPUT); break; case 5: /* _PC_PATH_MAX */ *retval = (PATH_MAX); break; case 8: /* _PC_VDISABLE */ *retval = (_POSIX_VDISABLE); break; case 3: /* _PC_NAME_MAX */ *retval = (NAME_MAX); break; case 4: /* _PC_PATH_MAX */ *retval = (PATH_MAX); break; case 6: /* _PC_CHOWN_RESTRICTED */ #ifdef _POSIX_CHOWN_RESTRICTED *retval = (1); #else *retval = (-1); #endif break; case 7: /* _PC_NO_TRUNC */ #ifdef _POSIX_NO_TRUNC *retval = (1); #else *retval = (-1); #endif break; default: *retval = -1; return EINVAL; } return 0; } int ibcs2_pause(struct proc *p, void *args, int *retval) { int mask = 0; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'pause'\n"); return sigsuspend(p, &mask, retval); } int ibcs2_pipe(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'pipe'\n"); return pipe(p, args, retval); } struct ibcs2_poll { int fd; short events; short revents; }; struct ibcs2_poll_args { struct ibcs2_poll *fds; unsigned long nfds; int timeout; }; int ibcs2_poll(struct proc *p, struct ibcs2_poll_args *args, int *retval) { struct ibcs2_poll conv; fd_set *readfds, *writefds, *exceptfds; struct timeval *timeout; struct select_args { u_int nd; fd_set *in, *ou, *ex; struct timeval *tv; } tmp_select; int i, error; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'poll'\n"); if (args->nfds > FD_SETSIZE) return EINVAL; readfds = (fd_set *)UA_ALLOC(); FD_ZERO(readfds); writefds = (fd_set *)UA_ALLOC() + sizeof(fd_set *); FD_ZERO(writefds); exceptfds = (fd_set *)UA_ALLOC() + 2*sizeof(fd_set *); FD_ZERO(exceptfds); timeout = (struct timeval *)UA_ALLOC() + 3*sizeof(fd_set *); if (args->timeout == -1) timeout = NULL; else { timeout->tv_usec = (args->timeout % 1000)*1000; timeout->tv_sec = args->timeout / 1000; } tmp_select.nd = 0; tmp_select.in = readfds; tmp_select.ou = writefds; tmp_select.ex = exceptfds; tmp_select.tv = timeout; for (i = 0; i < args->nfds; i++) { if (error = copyin(args->fds + i*sizeof(struct ibcs2_poll), &conv, sizeof(conv))) return error; conv.revents = 0; if (conv.fd < 0 || conv.fd > FD_SETSIZE) continue; if (conv.fd >= tmp_select.nd) tmp_select.nd = conv.fd + 1; if (conv.events & IBCS2_READPOLL) FD_SET(conv.fd, readfds); if (conv.events & IBCS2_WRITEPOLL) FD_SET(conv.fd, writefds); FD_SET(conv.fd, exceptfds); } if (error = select(p, &tmp_select, retval)) return error; if (*retval == 0) return 0; *retval = 0; for (*retval = 0, i = 0; i < args->nfds; i++) { copyin(args->fds + i*sizeof(struct ibcs2_poll), &conv, sizeof(conv)); conv.revents = 0; if (conv.fd < 0 || conv.fd > FD_SETSIZE) /* should check for open as well */ conv.revents |= IBCS2_POLLNVAL; else { if (FD_ISSET(conv.fd, readfds)) conv.revents |= IBCS2_POLLIN; if (FD_ISSET(conv.fd, writefds)) conv.revents |= IBCS2_POLLOUT; if (FD_ISSET(conv.fd, exceptfds)) conv.revents |= IBCS2_POLLERR; if (conv.revents) ++*retval; } if (error = copyout(&conv, args->fds + i*sizeof(struct ibcs2_poll), sizeof(conv))) return error; } return 0; } struct ibcs2_procids_args { int req; int eax; }; int ibcs2_procids(struct proc *p, struct ibcs2_procids_args *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'procids' request=%d, eax=%x\n", args->req, args->eax); switch (args->req) { case 0: /* getpgrp */ return getpgrp(p, args, retval); case 1: /* setpgrp */ { struct setpgid_args { int pid; int pgid; } tmp; tmp.pid = tmp.pgid = 0; return setpgid(p, &tmp, retval); } case 2: /* setpgid */ return setpgid(p, args, retval); case 3: /* setsid */ return setsid(p, args, retval); default: return EINVAL; } } int ibcs2_profil(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'profil'\n"); return profil(p, args, retval); } int ibcs2_ptrace(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'ptrace'\n"); return ptrace(p, args, retval); } int ibcs2_readlink(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'readlink'\n"); return readlink(p, args, retval); } int ibcs2_rename(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'rename'\n"); return rename(p, args, retval); } int ibcs2_rmdir(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'rmdir'\n"); return rmdir(p, args, retval); } struct ibcs2_secure_args { int cmd; int arg1; int arg2; int arg3; int arg4; int arg5; }; int ibcs2_secure(struct proc *p, struct ibcs2_secure_args *args, int *retval) { struct trapframe *tf = (struct trapframe *)p->p_md.md_regs; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'secure'\n"); switch (args->cmd) { case 1: /* get login uid */ *retval = p->p_ucred->cr_uid; return EPERM; case 2: /* set login uid */ default: printf("IBCS2: 'secure' cmd=%d not implemented\n",args->cmd); } return EINVAL; } struct ibcs2_setgid_args { ibcs2_gid_t gid; }; int ibcs2_setgid(struct proc *p, struct ibcs2_setgid_args *args, int *retval) { struct setgid_args { gid_t gid; } tmp; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'setgid'\n"); tmp.gid = (gid_t) args->gid; return setgid(p, &tmp, retval); } struct ibcs2_setgroups_args { int gidsetsize; ibcs2_gid_t *gidset; }; int ibcs2_setgroups(struct proc *p, struct ibcs2_setgroups_args *args, int *retval) { struct setgroups_args { u_int gidsetsize; gid_t *gidset; } tmp; ibcs2_gid_t *ibcs2_gidset; int i, error; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'setgroups'\n"); tmp.gidsetsize = args->gidsetsize; tmp.gidset = (gid_t *)UA_ALLOC(); ibcs2_gidset = (ibcs2_gid_t *)&tmp.gidset[NGROUPS_MAX]; if (error = copyin((caddr_t)args->gidset, (caddr_t)ibcs2_gidset, sizeof(ibcs2_gid_t) * tmp.gidsetsize)) return error; for (i = 0; i < tmp.gidsetsize; i++) tmp.gidset[i] = (gid_t)ibcs2_gidset[i]; return setgroups(p, &tmp, retval); } struct ibcs2_setuid_args { ibcs2_uid_t uid; }; int ibcs2_setuid(struct proc *p, struct ibcs2_setuid_args *args, int *retval) { struct setuid_args { uid_t uid; } tmp; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'setuid'\n"); tmp.uid = (uid_t) args->uid; return setuid(p, &tmp, retval); } int ibcs2_smount(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'smount'\n"); return mount(p, args, retval); } struct ibcs2_stime_args { long *timeptr; }; int ibcs2_stime(struct proc *p, struct ibcs2_stime_args *args, int *retval) { int error; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'stime'\n"); if (error = suser(p->p_ucred, &p->p_acflag)) return error; if (args->timeptr) { #if 0 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ boottime.tv_sec += (long)args->timeptr - time.tv_sec; s = splhigh(); time.tv_sec = (long)args->timeptr; time.tv_usec = 0; splx(s); resettodr(); #else printf("IBCS2: trying to set system time %d\n", (long)args->timeptr); #endif } return 0; } int ibcs2_sumount(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'sumount'\n"); return unmount(p, args, retval); } int ibcs2_symlink(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'symlink'\n"); return symlink(p, args, retval); } int ibcs2_sync(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'sync'\n"); return sync(p, args, retval); } int ibcs2_sysacct(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'sysacct'\n"); return acct(p, args, retval); } struct ibcs2_tms { long tms_utime; long tms_stime; long tms_cutime; long tms_cstime; }; int ibcs2_times(struct proc *p, struct ibcs2_tms *args, int *retval) { extern int hz; struct timeval tv; struct ibcs2_tms tms; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'times'\n"); tms.tms_utime = p->p_uticks; tms.tms_stime = p->p_sticks; tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz + ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000); tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz + ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000); microtime(&tv); *retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000; return (copyout((caddr_t)&tms, (caddr_t)args->tms_utime, sizeof(struct ibcs2_tms))); } struct ibcs2_ulimit_args { int cmd; long limit; }; int ibcs2_ulimit(struct proc *p, struct ibcs2_ulimit_args *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'ulimit'\n"); switch (args->cmd) { case IBCS2_GETFSIZE: *retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur; return 0; case IBCS2_SETFSIZE: return EINVAL; case IBCS2_GETPSIZE: *retval = p->p_rlimit[RLIMIT_RSS].rlim_cur; return 0; case IBCS2_GETMOPEN: *retval = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; return 0; } return EINVAL; } int ibcs2_umask(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'umask'\n"); return umask(p, args, retval); } int ibcs2_unlink(struct proc *p, void *args, int *retval) { if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'unlink'\n"); return unlink(p, args, retval); } struct ibcs2_utime_args { char *fname; ibcs2_time_t *timeptr; }; int ibcs2_utime(struct proc *p, struct ibcs2_utime_args *args, int *retval) { struct bsd_utimes_args { char *fname; struct timeval *tptr; } bsdutimes; struct timeval tv; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'utime'\n"); tv.tv_sec = (long)args->timeptr; tv.tv_usec = 0; bsdutimes.tptr = &tv; bsdutimes.fname = args->fname; return utimes(p, &bsdutimes, retval); } struct ibcs2_utssys_args { char *buf; int mv; int cmd; }; int ibcs2_utssys(struct proc *p, struct ibcs2_utssys_args *args, int *retval) { struct ibcs2_utsname { char sysname[9]; char nodename[9]; char release[9]; char version[9]; char machine[9]; } ibcs2_uname; extern char ostype[], hostname[], osrelease[], machine[]; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'utssys' cmd=%d\n", args->cmd); switch(args->cmd) { case 0: /* uname */ bzero(&ibcs2_uname, sizeof(struct ibcs2_utsname)); strncpy(ibcs2_uname.sysname, ostype, 8); strncpy(ibcs2_uname.nodename, hostname, 8); strncpy(ibcs2_uname.release, osrelease, 8); strncpy(ibcs2_uname.version, version, 8); strncpy(ibcs2_uname.machine, machine, 8); return (copyout((caddr_t)&ibcs2_uname, (caddr_t)args->buf, sizeof(struct ibcs2_utsname))); case 2: /* ustat */ printf("IBCS2: utssys(ustat) not implemented yet\n"); return EINVAL; case 1: /* umask, obsolete */ default: printf("IBCS2: 'utssys cmd (%d) not implemented yet'\n", args->cmd); return EINVAL; } } int ibcs2_wait(struct proc *p, void *args, int *retval) { struct trapframe *tf = (struct trapframe *)p->p_md.md_regs; struct ibcs2_waitpid_args { int pid; int *status; int options; } *t = args; struct wait4_args { int pid; int *status; int options; struct rusage *rusage; int compat; } tmp; tmp.compat = 1; tmp.rusage = 0; if (ibcs2_trace & IBCS2_TRACE_MISC) printf("IBCS2: 'wait'\n"); if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V)) == (PSL_Z|PSL_PF|PSL_N|PSL_V)) { tmp.pid = t->pid; tmp.status = t->status; tmp.options = 0; if (t->options & 02) tmp.options |= WUNTRACED; if (t->options & 01) tmp.options |= WNOHANG; tmp.options = t->options; } else { tmp.pid = WAIT_ANY; tmp.status = (int*)t->pid; tmp.options = 0; } return wait1(p, &tmp, retval); }