/* $NetBSD: kern_xxx.c,v 1.22 1995/03/09 08:54:37 mycroft Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 * The 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. * 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. * * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93 */ #include #include #include #include #include #include #include #include #include /* ARGSUSED */ int reboot(p, uap, retval) struct proc *p; struct reboot_args /* { syscallarg(int) opt; } */ *uap; register_t *retval; { int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); boot(SCARG(uap, opt)); return (0); } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) /* ARGSUSED */ int compat_43_gethostname(p, uap, retval) struct proc *p; struct compat_43_gethostname_args /* { syscallarg(char *) hostname; syscallarg(u_int) len; } */ *uap; register_t *retval; { int name; name = KERN_HOSTNAME; return (kern_sysctl(&name, 1, SCARG(uap, hostname), &SCARG(uap, len), 0, 0)); } /* ARGSUSED */ int compat_43_sethostname(p, uap, retval) struct proc *p; register struct compat_43_sethostname_args *uap; register_t *retval; { int name; int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); name = KERN_HOSTNAME; return (kern_sysctl(&name, 1, 0, 0, SCARG(uap, hostname), SCARG(uap, len))); } /* ARGSUSED */ int compat_43_gethostid(p, uap, retval) struct proc *p; void *uap; register_t *retval; { *(int32_t *)retval = hostid; return (0); } #endif /* COMPAT_43 || COMPAT_SUNOS || COMPAT_LINUX */ #ifdef COMPAT_43 /* ARGSUSED */ int compat_43_sethostid(p, uap, retval) struct proc *p; struct compat_43_sethostid_args /* { syscallarg(int32_t) hostid; } */ *uap; register_t *retval; { int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); hostid = SCARG(uap, hostid); return (0); } int compat_43_quota(p, uap, retval) struct proc *p; void *uap; register_t *retval; { return (ENOSYS); } #endif /* COMPAT_43 */ #if defined(COMPAT_09) || defined(COMPAT_SUNOS) ||defined(COMPAT_HPUX) \ || defined(COMPAT_ULTRIX) || defined(COMPAT_LINUX) /* ARGSUSED */ int compat_09_getdomainname(p, uap, retval) struct proc *p; struct compat_09_getdomainname_args /* { syscallarg(char *) domainname; syscallarg(int) len; } */ *uap; register_t *retval; { int name; name = KERN_DOMAINNAME; return (kern_sysctl(&name, 1, SCARG(uap, domainname), &SCARG(uap, len), 0, 0)); } /* ARGSUSED */ int compat_09_setdomainname(p, uap, retval) struct proc *p; struct compat_09_setdomainname_args /* { syscallarg(char *) domainname; syscallarg(int) len; } */ *uap; register_t *retval; { int name; int error; if (error = suser(p->p_ucred, &p->p_acflag)) return (error); name = KERN_DOMAINNAME; return (kern_sysctl(&name, 1, 0, 0, SCARG(uap, domainname), SCARG(uap, len))); } #endif /* COMPAT_09 || COMPAT_SUNOS || COMPAT_HPUX || COMPAT_ULTRIX COMPAT_LINUX */ #ifdef COMPAT_09 struct outsname { char sysname[32]; char nodename[32]; char release[32]; char version[32]; char machine[32]; }; /* ARGSUSED */ int compat_09_uname(p, uap, retval) struct proc *p; struct compat_09_uname_args /* { syscallarg(struct outsname *) name; } */ *uap; register_t *retval; { struct outsname outsname; char *cp, *dp, *ep; extern char ostype[], osrelease[]; strncpy(outsname.sysname, ostype, sizeof(outsname.sysname)); strncpy(outsname.nodename, hostname, sizeof(outsname.nodename)); strncpy(outsname.release, osrelease, sizeof(outsname.release)); dp = outsname.version; ep = &outsname.version[sizeof(outsname.version) - 1]; for (cp = version; *cp && *cp != '('; cp++) ; for (cp++; *cp && *cp != ')' && dp < ep; cp++) *dp++ = *cp; for (; *cp && *cp != '#'; cp++) ; for (; *cp && *cp != ':' && dp < ep; cp++) *dp++ = *cp; *dp = '\0'; strncpy(outsname.machine, MACHINE, sizeof(outsname.machine)); return (copyout((caddr_t)&outsname, (caddr_t)SCARG(uap, name), sizeof(struct outsname))); } #endif /* COMPAT_09 */ #ifdef SYSCALL_DEBUG #define SCDEBUG_CALLS 0x0001 /* show calls */ #define SCDEBUG_RETURNS 0x0002 /* show returns */ #define SCDEBUG_ALL 0x0004 /* even syscalls that are implemented */ #define SCDEBUG_SHOWARGS 0x0008 /* show arguments to calls */ int scdebug = SCDEBUG_CALLS|SCDEBUG_RETURNS|SCDEBUG_SHOWARGS; extern int nsysent; extern char *syscallnames[]; #ifdef COMPAT_SUNOS extern int nsunos_sysent; extern struct sysent sunos_sysent[]; extern char *sunos_syscallnames[]; #endif /* COMPAT_SUNOS */ #ifdef COMPAT_HPUX extern int nhpux_sysent; extern struct sysent hpux_sysent[]; extern char *hpux_syscallnames[]; #endif /* COMPAT_HPUX */ #ifdef COMPAT_ULTRIX extern int nultrix_sysent; extern struct sysent ultrix_sysent[]; extern char *ultrix_syscallnames[]; #endif /* COMPAT_ULTRIX */ #ifdef COMPAT_SVR4 extern int nsvr4_sysent; extern struct sysent svr4_sysent[]; extern char *svr4_syscallnames[]; #endif /* COMPAT_SVR4 */ #ifdef COMPAT_IBCS2 extern int nibcs2_sysent; extern struct sysent ibcs2_sysent[]; extern char *ibcs2_syscallnames[]; #endif /* COMPAT_IBCS2 */ #ifdef COMPAT_OSF1 extern int nosf1_sysent; extern struct sysent osf1_sysent[]; extern char *osf1_syscallnames[]; #endif /* COMPAT_OSF1 */ #ifdef COMPAT_LINUX extern int nlinux_sysent; extern struct sysent linux_sysent[]; extern char *linux_syscallnames[]; #endif /* COMPAT_LINUX */ static struct os_syscall { char *name; int *nsysent; struct sysent *sysent; char **syscallnames; } os_syscall[] = { { "NetBSD", &nsysent, sysent, syscallnames }, #ifdef COMPAT_SUNOS { "SunOS", &nsunos_sysent, sunos_sysent, sunos_syscallnames }, #else { NULL, }, #endif #ifdef COMPAT_HPUX { "HP-UX", &nhpux_sysent, hpux_sysent, hpux_syscallnames }, #else { NULL, }, #endif #ifdef COMPAT_ULTRIX { "Ultrix", &nultrix_sysent, ultrix_sysent, ultrix_syscallnames }, #else { NULL, }, #endif #ifdef COMPAT_SVR4 { "SVR4", &nsvr4_sysent, svr4_sysent, svr4_syscallnames }, #else { NULL, }, #endif #ifdef COMPAT_IBCS2 { "iBCS2/COFF", &nibcs2_sysent, ibcs2_sysent, ibcs2_syscallnames }, { "iBCS2/x.out", &nibcs2_sysent, ibcs2_sysent, ibcs2_syscallnames }, #else { NULL, }, { NULL, }, #endif #ifdef COMPAT_OSF1 { "OSF/1", &nosf1_sysent, osf1_sysent, osf1_syscallnames }, #else { NULL, }, #endif { NULL, }, #ifdef COMPAT_LINUX { "Linux", &nlinux_sysent, linux_sysent, linux_syscallnames }, #else { NULL, }, #endif }; void scdebug_call(p, code, args) struct proc *p; register_t code, args[]; { struct os_syscall *os; struct sysent *sy; int i; if (!(scdebug & SCDEBUG_CALLS)) return; #ifdef DIAGNOSTIC if (p->p_emul > sizeof os_syscall/sizeof os_syscall[0] || os_syscall[p->p_emul].name == NULL) panic("bogus p_emul"); #endif os = &os_syscall[p->p_emul]; sy = &os->sysent[code]; if (!(scdebug & SCDEBUG_ALL || code < 0 || code >= *os->nsysent || sy->sy_call == nosys)) return; printf("proc %d (%s): %s syscall ", p->p_pid, p->p_comm, os->name); if (code < 0 || code >= *os->nsysent) { printf("OUT OF RANGE (%d)", code); code = 0; } else printf("%d", code); printf(" called: %s", os->syscallnames[code]); if (scdebug & SCDEBUG_SHOWARGS) { printf("("); for (i = 0; i < sy->sy_argsize / sizeof(register_t); i++) printf("%s0x%lx", i == 0 ? "" : ", ", (long)args[i]); printf(")"); } printf("\n"); } void scdebug_ret(p, code, error, retval) struct proc *p; register_t code; int error; register_t retval[]; { struct os_syscall *os; struct sysent *sy; if (!(scdebug & SCDEBUG_RETURNS)) return; #ifdef DIAGNOSTIC if (p->p_emul > sizeof os_syscall/sizeof os_syscall[0] || os_syscall[p->p_emul].name == NULL) panic("bogus p_emul"); #endif os = &os_syscall[p->p_emul]; sy = &os->sysent[code]; if (!(scdebug & SCDEBUG_ALL || code < 0 || code >= *os->nsysent || sy->sy_call == nosys)) return; printf("proc %d (%s): %s syscall ", p->p_pid, p->p_comm, os->name); if (code < 0 || code >= *os->nsysent) { printf("OUT OF RANGE (%d)", code); code = 0; } else printf("%d", code); printf(" return: error = %d, retval = 0x%lx,0x%lx\n", error, (long)retval[0], (long)retval[1]); } #endif /* SYSCALL_DEBUG */