You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

383 lines
8.7 KiB

/* $Id: kern_syscall.c,v 1.1.1.1 2006/09/14 01:59:08 root Exp $ */
/*
* Copyright (c) 2000 Opsycon AB (www.opsycon.se)
* Copyright (c) 2000 Rtmx, Inc (www.rtmx.com)
*
* 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 for Rtmx, Inc by
* Opsycon Open System Consulting AB, Sweden.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
*/
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
#include <sys/errno.h>
#include <sys/syslog.h>
#include <sys/syscallargs.h>
#include <machine/stdarg.h>
int errno; /* has to be declared somewhere */
/*
* Some stuff taken from signal.h.
*/
static __inline int sigaddset(sigset_t *set, int signo) {
if (signo <= 0 || signo >= _NSIG) {
errno = 22; /* EINVAL */
return -1;
}
*set |= (1 << ((signo)-1)); /* sigmask(signo) */
return (0);
}
static __inline int sigdelset(sigset_t *set, int signo) {
extern int errno;
if (signo <= 0 || signo >= _NSIG) {
errno = 22; /* EINVAL */
return -1;
}
*set &= ~(1 << ((signo)-1)); /* sigmask(signo) */
return (0);
}
static __inline int sigismember(const sigset_t *set, int signo) {
extern int errno;
if (signo <= 0 || signo >= _NSIG) {
errno = 22; /* EINVAL */
return -1;
}
return ((*set & (1 << ((signo)-1))) != 0);
}
#define sigemptyset(set) (*(set) = 0, 0)
#define MAXARGS 6
static int gensyscall __P((int (*) __P((struct proc *, void *, register_t *)), int, long, va_list));
static int
gensyscall (int (*func) __P((struct proc *, void *, register_t *)), int nargs, long a1, va_list ap)
{
extern int errno;
struct args {register_t a[MAXARGS];} ua;
struct proc *p = curproc;
register_t rval[2];
int error, sig, i;
if (p->p_stat != SNOTKERN)
panic ("nested syscall");
if (nargs > 0) {
ua.a[0] = a1;
}
for (i = 1; i < nargs; i++) {
ua.a[i] = va_arg (ap, long);
}
while (1) {
p->p_stat = SRUN;
rval[0] = 0;
error = (*func) (p, &ua, rval);
while ((sig = CURSIG (p)) != 0) /* handle signals here */
psig (sig);
p->p_stat = SNOTKERN;
if (error != ERESTART) {
if (error) {
errno = error;
return -1;
}
return rval[0];
}
}
}
#define syscall(pub, pri, nargs) \
int pub __P((long, ...)); \
int pub (long a1, ...) \
{ \
int res; \
va_list ap; \
va_start (ap, a1); \
res = gensyscall (SYSCALL(pri), nargs, a1, ap); \
va_end (ap); \
return(res); \
}
syscall(soc_read, read, 3)
syscall(soc_write, write, 3)
syscall(soc_close, close, 1)
syscall(recvmsg, recvmsg, 3)
syscall(sendmsg, sendmsg, 3)
syscall(recvfrom, recvfrom, 6)
syscall(accept, accept, 3)
syscall(getpeername, getpeername, 3)
syscall(getsockname, getsockname, 3)
syscall(soc_dup, dup, 2)
syscall(soc_ioctl, ioctl, 3)
#if 0
syscall(getdtablesize, getdtablesize, 0)
#endif
syscall(soc_dup2, dup2, 2)
syscall(soc_fcntl, fcntl, 3)
syscall(select, select, 5)
syscall(socket, socket, 3)
syscall(connect, connect, 3)
syscall(bind, bind, 3)
syscall(setsockopt, setsockopt, 5)
syscall(listen, listen, 2)
syscall(getsockopt, getsockopt, 5)
syscall(readv, readv, 3)
syscall(writev, writev, 3)
syscall(sendto, sendto, 6)
syscall(shutdown, shutdown, 2)
syscall(sigaction, sigaction, 3)
syscall(kernsigprocmask, sigprocmask, 2)
syscall(sigpending, sigpending, 0)
syscall(sigsuspend, sigsuspend, 1)
syscall(gettimeofday, gettimeofday, 2)
syscall(getitimer, getitimer, 2)
syscall(setitimer, setitimer, 3)
#ifdef notyet
/*
* TBD: user callable socket system call
*/
int
soc_syscall ()
{
extern int errno;
errno = EINVAL;
return -1;
}
#endif
/*
* user callable exit (distinct from prom's exit routine)
*/
void soc_exit __P((int));
void
soc_exit (rv)
{
exit1 (curproc, rv & 0xff);
}
/*
* Dummy system calls
*/
int getuid __P((void));
int getuid() {return 0;}
int geteuid __P((void));
int geteuid() {return 0;}
int getegid __P((void));
int getegid() {return 0;}
int getgid __P((void));
int getgid() {return 0;}
int getpid __P((void));
int getpid()
{
return curproc->p_pid;
}
int getpgrp __P((int));
int getpgrp(pid)
{
/* for us pgid == pid */
return curproc->p_pid;
}
int gethostid __P((void));
int gethostid()
{
extern char *getenv __P((char *));
extern in_addr_t inet_addr __P((const char *));
char *netaddr;
int id;
netaddr = getenv ("netaddr");
if (netaddr && (id = inet_addr (netaddr)) != -1)
return id;
return 0;
}
int gethostname __P((char *buf, int n));
int
gethostname (char *buf, int n)
{
extern char *getenv __P((char *));
char *hostname;
extern int errno;
hostname = getenv ("hostname");
if (!hostname)
hostname = "pmon";
if (n < strlen (hostname) + 1) {
errno = EINVAL;
return -1;
}
strcpy (buf, hostname);
return 0;
}
/*
* User-level signal handling (4.3bsd emulation on top of POSIX)
*/
int sigvec __P((int, struct sigvec *, struct sigvec *));
int
sigvec(signo, sv, osv)
int signo;
struct sigvec *sv, *osv;
{
int ret;
if (sv)
sv->sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */
ret = sigaction(signo, (struct sigaction *)sv, (struct sigaction *)osv);
if (ret == 0 && osv)
osv->sv_flags ^= SV_INTERRUPT; /* !SA_INTERRUPT */
return (ret);
}
/*
* The real sigprocmask system call takes only two args, and returns
* the old mask. This cover function munges the arguments appropriately.
*/
int sigprocmask __P((int how, const sigset_t *set, sigset_t *oset));
int
sigprocmask (int how, const sigset_t *set, sigset_t *oset)
{
sigset_t new, old;
int oerrno;
if (!set) {
how = SIG_BLOCK;
new = 0;
} else {
new = *set;
}
oerrno = errno; errno = 0;
old = kernsigprocmask (how, new);
if (old == (sigset_t)-1 && errno)
return -1;
errno = oerrno;
if (oset)
*oset = old;
return 0;
}
int sigsetmask __P((int));
int
sigsetmask(mask)
int mask;
{
int omask, n;
n = sigprocmask(SIG_SETMASK, (sigset_t *) &mask, (sigset_t *) &omask);
if (n)
return (n);
return (omask);
}
int sigblock __P((int));
int
sigblock(mask)
int mask;
{
int omask, n;
n = sigprocmask(SIG_BLOCK, (sigset_t *) &mask, (sigset_t *) &omask);
if (n)
return (n);
return (omask);
}
int sigpause __P((int));
int
sigpause(mask)
int mask;
{
return (sigsuspend((long)&mask));
}
sigset_t _sigintr; /* shared with siginterrupt */
sig_t
signal(s, a)
int s;
sig_t a;
{
struct sigaction sa, osa;
sa.sa_handler = a;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (!sigismember(&_sigintr, s))
sa.sa_flags |= SA_RESTART;
if (sigaction(s, &sa, &osa) < 0)
return (BADSIG);
return (osa.sa_handler);
}
/*
* Set signal state to prevent restart of system calls
* after an instance of the indicated signal.
*/
int siginterrupt __P((int, int));
int
siginterrupt(sig, flag)
int sig, flag;
{
extern sigset_t _sigintr;
struct sigaction sa;
int ret;
if ((ret = sigaction(sig, (struct sigaction *)0, &sa)) < 0)
return (ret);
if (flag) {
sigaddset(&_sigintr, sig);
sa.sa_flags &= ~SA_RESTART;
} else {
sigdelset(&_sigintr, sig);
sa.sa_flags |= SA_RESTART;
}
return (sigaction(sig, &sa, (struct sigaction *)0));
}