extern struct runload loadavg[];
// the system call dispatch table
+#ifdef CONFIG_LEVEL_2
+#define FUZIX_SYSCALL_COUNT 80
+#else
#define FUZIX_SYSCALL_COUNT 66
+#endif
+
typedef arg_t (*syscall_t)(void);
extern const syscall_t syscall_dispatch[FUZIX_SYSCALL_COUNT];
+extern arg_t _nosys(void);
+
#endif
#define EALREADY 39 /* Operation already in progress */
#define EADDRINUSE 40 /* Address already in use */
#define EADDRNOTAVAIL 41 /* Address not available */
+#define ENOSYS 42 /* No such system call */
/*
* ioctls for kernel internal operations start at 0x8000 and cannot be issued
extern void seladdwait(struct selmap *s);
extern void selrmwait(struct selmap *s);
extern void selwake(struct selmap *s);
-#ifdef CONFIG_SELECT
-extern int selwait_inode(inoptr i, uint8_t smask, uint8_t setit);
+#ifdef CONFIG_LEVEL_2
+extern void selwait_inode(inoptr i, uint8_t smask, uint8_t setit);
extern void selwake_inode(inoptr i, uint16_t mask);
extern void selwake_pipe(inoptr i, uint16_t mask);
extern int _select(void);
#else
#define selwait_inode(i,smask,setit) do {} while(0)
-#define selwake_inode(i,smask,setit) do {} while(0)
-#define selwake_pipe(i,smask,setit) do {} while(0)
+#define selwake_inode(i,smask) do {} while(0)
+#define selwake_pipe(i,smask) do {} while(0)
#endif
/* swap.c */
+#ifndef _LEVEL_2_H
+#define _LEVEL_2_H
+
/* Resource limits only exist on LEVEL_2 systems */
#define NRLIMIT 9
#define RLIMIT_RSS 7
#define RLIMIT_STACK 8
-typedef uint32_t rlimit_t
+typedef uint32_t rlim_t;
#define RLIM_INFINITY 0xFFFFFFFFUL
rlim_t rlim_max;
};
+struct tty;
extern int in_group(uint16_t gid);
extern void jobcontrol_in(struct tty *tty);
/* Platform must implement according to its PATH_MAX and allocators. If
you are using a 512 byte path limit then calling tmpbuf() and brelse()
is sufficient */
-extern char *pathhbuf(void);
+extern char *pathbuf(void);
extern void pathfree(char *p);
/* The first half of this always gets used with a constant so using a macro
FIXME: check for any setuid funnies */
#define can_signal(p, sig) \
- ((sig == SIGCONT && udata.u_ptab->p_session == (p)->session) \
+ ((sig == SIGCONT && udata.u_ptab->p_session == (p)->p_session) \
|| udata.u_ptab->p_uid == (p)->p_uid || super())
+extern arg_t _select(void);
extern arg_t _setgroups(void);
extern arg_t _getgroups(void);
extern arg_t _getrlimit(void);
extern arg_t _setpgid(void);
extern arg_t _setsid(void);
extern arg_t _getsid(void);
+
+#endif
"acct",
"memalloc",
"memfree",
+ "_nosys66",
+ "_nosys67",
+ "_nosys68",
+ "_nosys69",
+ "_nosys70",
+ "_nosys71",
+ "_select",
+ "setgroups",
+ "getgroups",
+ "getrlimit",
+ "setrlimit",
+ "setpgid",
+ "setsid",
+ "getsid",
};
int syscall_args[NR_SYSCALL] = {
1, //act
1, //memalloc
1, //memfree
+ 0, //nosys 66
+ 0, //nosys 67
+ 0, //nosys 68
+ 0, //nosys 69
+ 0, //nosys 70
+ 0, //nosys 71
+ 2, //_select
+ 2, //setgroups
+ 2, //getgroups
+ 2, //getrlimit
+ 2, //setrlimit
+ 2, //setpgid
+ 1, //setsid
+ 1, //getsid
};
_acct, /* FUZIX system call 63 */
_memalloc, /* FUZIX system call 64 */
_memfree, /* FUZIX system call 65 */
+ /* Level 2 calls */
+#if defined(CONFIG_LEVEL_2)
+ _nosys, /* 66-71 reserved */
+ _nosys,
+ _nosys,
+ _nosys,
+ _nosys,
+ _nosys,
+ _select, /* FUZIX system call 72 */
+ _setgroups, /* FUZIX system call 73 */
+ _getgroups, /* FUZIX system call 74 */
+ _getrlimit, /* FUZIX system call 75 */
+ _setrlimit, /* FUZIX system call 76 */
+ _setpgid, /* FUZIX system call 77 */
+ _setsid, /* FUZIX system call 78 */
+ _getsid, /* FUZIX system call 79 */
+#endif
};
#include <kernel.h>
#include <kdata.h>
#include <printf.h>
+#include <tty.h>
+
+#ifdef CONFIG_LEVEL_2
int in_group(uint16_t gid)
{
- uint16_t *g = udata.u_group;
+ uint16_t *g = udata.u_groups;
uint16_t *p = g + udata.u_ngroup;
while(g < p)
if (*g++ == gid)
void jobcontrol_in(struct tty *t)
{
- if (udata.u_proc->p_pgrp == t->pgrp)
+ if (udata.u_ptab->p_pgrp == t->pgrp)
return;
/* We probably want to special case a helper here because we need
to handle the funnier side effects ? */
- ssig(udata.u_proc, SIGTTIN);
+ ssig(udata.u_ptab, SIGTTIN);
/* So we halt */
- pause(0);
+ psleep(0);
}
void jobcontrol_out(struct tty *t)
{
- if (udata.u_proc->p_pgrp == t->pgrp)
+ if (udata.u_ptab->p_pgrp == t->pgrp)
return;
- if (!(t->termios.t_lflag & TOSTOP))
+ if (!(t->termios.c_lflag & TOSTOP))
return;
- ssig(udata.u_proc, SIGTTOU);
+ ssig(udata.u_ptab, SIGTTOU);
/* So we halt */
- pause(0);
+ psleep(0);
}
int tcsetpgrp(struct tty *t, char *data) /* data is user pointer */
/* Controlling tty check is done by caller */
/* No change -> ok */
- if (grp == tty->pgrp)
+ if (grp == t->pgrp)
return 0;
for (p = ptab; p < ptab_end; ++p) {
return -1;
}
/* So it's a valid group and in our session */
- tty->pgrp = grp;
+ t->pgrp = grp;
return 0;
}
}
udata.u_error = EINVAL;
return -1;
}
+
+#endif
* Assembly Language Function handler in lowlevel.s
*/
if (udata.u_callno >= FUZIX_SYSCALL_COUNT) {
- udata.u_error = EINVAL;
+ udata.u_error = ENOSYS;
} else {
#ifdef DEBUG
kprintf("\t\tpid %d: syscall %d\t%s(%x, %x, %x)\n",
#include <kdata.h>
#include <printf.h>
+#ifdef CONFIG_LEVEL_2
+
/*
* Logic for select
*
* Each selectable object needs 3 words of memory (assuming max
* 16 processes). If we go over that then this logic is ok but
- * we would need to trim pipe buffers slightly.
+ * we would need to trim pipe buffers slightly. Alternatively we
+ * could use separate select objects at that point since presumably
+ * we have enough memory.
*
* While they are 16bits we can instead hide them in the inode copy
* in memory for free.
* Socket: TODO
*/
+uint16_t pipesel = 0;
+
void seladdwait(struct selmap *s)
{
- uint16_t p = udata.u_ptab - ptab;
- s->map[p>>3] |= (1 << (p & 7));
+ uint16_t p = udata.u_ptab - ptab;
+ s->map[p >> 3] |= (1 << (p & 7));
}
void selrmwait(struct selmap *s)
{
- uint16_t p = udata.u_ptab - ptab;
- s->map[p>>3] &= ~(1 << (p & 7));
+ uint16_t p = udata.u_ptab - ptab;
+ s->map[p >> 3] &= ~(1 << (p & 7));
}
void selwake(struct selmap *s)
{
- p = ptab;
- for (i = 0; i < maxproc; i++) {
- if (s->map[i>>3] & (1 << (i & 7)))
- pwake(p);
- p++;
- }
+ ptptr p = ptab;
+ uint16_t i;
+
+ for (i = 0; i < maxproc; i++) {
+ if (s->map[i >> 3] & (1 << (i & 7)))
+ pwake(p);
+ p++;
+ }
}
/* Set our select bits on the inode */
-int selwait_inode(inoptr i, uint8_t smask, uint8_t setit) {
- struct selmap *s = (struct selmap *)(&i->c_node.i_addr[17]);
- uint8_t bit = udata.u_ptab - ptab;
- uint8_t mask = 1 << (bit & 7);
- uint8_t bset = bit & setit;
- bit >>= 3;
-
- if (smask & SELECT_IN) {
- s->map[mask] &= ~bit;
- s->map[mask] |= bset;
- }
- s++;
- if (smask & SELECT_OUT) {
- s->map[mask] &= ~bit;
- s->map[mask] |= bset;
- }
- s++;
- if (smask & SELECT_EX) {
- s->map[mask] &= ~bit;
- s->map[mask] |= bset;
- }
+void selwait_inode(inoptr i, uint8_t smask, uint8_t setit)
+{
+ struct selmap *s = (struct selmap *) (&i->c_node.i_addr[17]);
+ uint8_t bit = udata.u_ptab - ptab;
+ uint8_t mask = 1 << (bit & 7);
+ uint8_t bset = bit & setit;
+ bit >>= 3;
+
+ if (smask & SELECT_IN) {
+ s->map[mask] &= ~bit;
+ s->map[mask] |= bset;
+ }
+ s++;
+ if (smask & SELECT_OUT) {
+ s->map[mask] &= ~bit;
+ s->map[mask] |= bset;
+ }
+ s++;
+ if (smask & SELECT_EX) {
+ s->map[mask] &= ~bit;
+ s->map[mask] |= bset;
+ }
}
/* Wake an inode for select */
-void selwake_inode(inoptr i, uint16_t mask) {
- struct selmap *s = (struct selmap *)(&i->c_node.i_addr[17]);
- if (mask & SELECT_IN)
- selwake(s);
- s++;
- if (mask & SELECT_OUT)
- selwake(s);
- s++;
- if (mask & SELECT_EX)
- selwake(s);
+void selwake_inode(inoptr i, uint16_t mask)
+{
+ struct selmap *s = (struct selmap *) (&i->c_node.i_addr[17]);
+ if (mask & SELECT_IN)
+ selwake(s);
+ s++;
+ if (mask & SELECT_OUT)
+ selwake(s);
+ s++;
+ if (mask & SELECT_EX)
+ selwake(s);
}
static int pipesel_begin(inoptr i, uint8_t bits)
{
- uint16_t mask = 0;
- pipesel++;
- /* Data or EOF */
- if (i->c_node.i_size || !i->c_refs)
- mask |= SELECT_IN;
- /* Enough room to be worth waking - keep wakeup rate down */
- if (i->c_node.i_size < 8 * BLKSIZE)
- mask |= SELECT_OUT;
- selwait_inode(i, bits, 1);
- return mask & bits;
+ uint16_t mask = 0;
+ pipesel++;
+ /* Data or EOF */
+ if (i->c_node.i_size || !i->c_refs)
+ mask |= SELECT_IN;
+ /* Enough room to be worth waking - keep wakeup rate down */
+ if (i->c_node.i_size < 8 * BLKSIZE)
+ mask |= SELECT_OUT;
+ selwait_inode(i, bits, 1);
+ return mask & bits;
}
-static int pipesel_end(inoptr i)
+static void pipesel_end(inoptr i)
{
- pipesel--;
- /* Clear out wait masks */
- selwait(i, SELECT_IN|SELECT_OUT|SELECT_EX, 0);
+ pipesel--;
+ /* Clear out wait masks */
+ selwait_inode(i, SELECT_IN | SELECT_OUT | SELECT_EX, 0);
}
void selwake_pipe(inoptr i, uint16_t mask)
{
- if (pipesel)
- selwake_inode(i);
+ if (pipesel)
+ selwake_inode(i, mask);
}
+
+/*******************************************
+ _select (nfd, base) Function 72
+ int nfd;
+ uint16_t *base;
+ *******************************************/
#define nfd (uint16_t)udata.u_argn
-#define base (uint16_t)udata.u_argn1
+#define base (uint16_t *)udata.u_argn1
int _select(void)
{
- struct inode *iptr;
- uint16_t sumo;
- uint8_t n;
- uint16_t inr = 0, outr = 0, exr = 0;
- /* Second 16bits of each spare for expansion */
- uint16_t in = ugetw(base);
- uint16_t out = ugetw(base+4);
- uint16_t ex = ugetw(base+8);
-
- uint16_t sum = in | out | ex;
-
- /* Timeout in 1/10th of a second (BSD api mangling done by libc) */
- udata.p_tab->p_timeout = ugetw(base + 12);
-
- do {
- m = 1;
- for (i = 0; i < nfd; i++) {
- if (sum & m) {
- if (in & m)
- n = SELECT_IN;
- else
- n = 0;
- if (out & m)
- n |= SELECT_OUT;
- if (ex & m)
- n |= SELECT_EX;
- ino = getinode(i);
- if (ino == NULLINODE)
- return -1;
- switch(getmode(ino)) {
- /* Device types that automatically report some ready states */
- case F_BDEV:
- case F_REG:
- outr |= m;
- case F_DIR:
- inr |= m;
- break;
- case F_PIPE:
- n = pipesel_begin(ino, n);
- goto setbits;
- case F_CDEV:
- /* If unsupported we report the device as read/write ready */
- if (d_ioctl(ino->c_node.i_addr[0], SELECT_BEGIN, &n) == -1) {
- udata.u_error = 0;
- n = SELECT_IN|SELECT_OUT;
- }
-setbits:
- /* Set the outputs */
- if (n & SELECT_IN)
- inr |= m;
- if (n & SELECT_OUT)
- outr |= m;
- if (n & SELECT_EX)
- exr |= m;
- break;
- }
- m << = 1; /* Next fd mask */
- }
- inr &= in; /* Don't reply with bits not being selected */
- outr &= out;
- exr &= ex;
- sumo = inr | outr | exr; /* Are we there yet ? */
- if (!sumo && psleep_flags(&udata.p_tab->p_timeout, 0) == -1)
- break;
- }
- while (!sumo && udata.p_tab->p_timeout != 1);
-
- udata.p_tab->p_timeout = 0;
-
- /* Return the values to user space */
- uputw(inr, base);
- uputw(outr, base + 4);
- uputw(exr, base + 8)
-
- /* Tell the device less people care, we may want to remove all this
- and just select check. The 0 check we could do instead is cheap */
- m = 1;
- for (i = 0; i < nfd; i++) {
- if (sum & m) {
- ino = getinode(i);
- switch(getmode(ino))
- {
- case F_CDEV:
- d_ioctl(ino->c_node.i_addr[0], SELECT_END, NULL);
- break;
- case F_PIPE:
- pipesel_end(ino);
- }
- }
- m <<= 1;
- }
- return 0; /* the scan and return of highest fd is done by
- user space */
+ inoptr ino;
+ uint16_t sumo;
+ uint8_t i, m, n;
+ uint16_t inr = 0, outr = 0, exr = 0;
+ /* Second 16bits of each spare for expansion */
+ uint16_t in = ugetw(base);
+ uint16_t out = ugetw(base + 4);
+ uint16_t ex = ugetw(base + 8);
+
+ uint16_t sum = in | out | ex;
+
+ /* Timeout in 1/10th of a second (BSD api mangling done by libc) */
+ udata.u_ptab->p_timeout = ugetw(base + 12);
+
+ do {
+ m = 1;
+ for (i = 0; i < nfd; i++) {
+ if (sum & m) {
+ if (in & m)
+ n = SELECT_IN;
+ else
+ n = 0;
+ if (out & m)
+ n |= SELECT_OUT;
+ if (ex & m)
+ n |= SELECT_EX;
+ ino = getinode(i);
+ if (ino == NULLINODE)
+ return -1;
+ switch (getmode(ino)) {
+ /* Device types that automatically report some ready states */
+ case F_BDEV:
+ case F_REG:
+ outr |= m;
+ case F_DIR:
+ inr |= m;
+ break;
+ case F_PIPE:
+ n = pipesel_begin(ino, n);
+ goto setbits;
+ case F_CDEV:
+ /* If unsupported we report the device as read/write ready */
+ if (d_ioctl
+ (ino->c_node.i_addr[0],
+ SELECT_BEGIN, &n) == -1) {
+ udata.u_error = 0;
+ n = SELECT_IN | SELECT_OUT;
+ }
+ setbits:
+ /* Set the outputs */
+ if (n & SELECT_IN)
+ inr |= m;
+ if (n & SELECT_OUT)
+ outr |= m;
+ if (n & SELECT_EX)
+ exr |= m;
+ break;
+ }
+ }
+ m <<= 1; /* Next fd mask */
+ }
+ inr &= in; /* Don't reply with bits not being selected */
+ outr &= out;
+ exr &= ex;
+ sumo = inr | outr | exr; /* Are we there yet ? */
+ if (!sumo
+ && psleep_flags(&udata.u_ptab->p_timeout, 0) == -1)
+ break;
+ }
+ while (!sumo && udata.u_ptab->p_timeout != 1);
+
+ udata.u_ptab->p_timeout = 0;
+
+ /* Return the values to user space */
+ uputw(inr, base);
+ uputw(outr, base + 4);
+ uputw(exr, base + 8);
+
+ /* Tell the device less people care, we may want to remove all this
+ and just select check. The 0 check we could do instead is cheap */
+ m = 1;
+ for (i = 0; i < nfd; i++) {
+ if (sum & m) {
+ ino = getinode(i);
+ switch (getmode(ino)) {
+ case F_CDEV:
+ d_ioctl(ino->c_node.i_addr[0], SELECT_END,
+ NULL);
+ break;
+ case F_PIPE:
+ pipesel_end(ino);
+ }
+ }
+ m <<= 1;
+ }
+ return 0; /* the scan and return of highest fd is done by
+ user space */
}
#undef nfd
#undef base
+
+#endif
#undef buf
#undef nbytes
+/*******************************************
+nosys () Function: various
+********************************************/
+
+arg_t _nosys(void)
+{
+ udata.u_error = ENOSYS;
+ return -1;
+}
#include <kdata.h>
#include <printf.h>
+#ifdef CONFIG_LEVEL_2
+
/*******************************************
- setgroups (ngroup, groups) Function ??
+ setgroups (ngroup, groups) Function 73
int ngroup;
const uint16_t *groups;
*******************************************/
return -1;
if (ngroup < 0 || ngroup > NGROUP) {
udata.u_error = EINVAL;
- return -1
+ return -1;
}
if (ngroup && uget(groups, udata.u_groups, ngroup * sizeof(uint16_t)))
return -1;
#undef groups
/*******************************************
- getgroups (ngroup, groups) Function ??
+ getgroups (ngroup, groups) Function 74
int ngroup;
uint16_t *groups;
*******************************************/
return udata.u_ngroup;
if (ngroup < udata.u_ngroup) {
udata.u_error = EINVAL;
- return;
+ return -1;
}
if (uput(groups, udata.u_groups, ngroup * sizeof(uint16_t)) < 0)
return -1;
#undef groups
/*******************************************
- getrlimit (res, rlimit) Function ??
+ getrlimit (res, rlimit) Function 75
int res;
struct rlimit *rlim;
*******************************************/
#undef rlim
/*******************************************
- setrlimit (res, rlimit) Function ??
+ setrlimit (res, rlimit) Function 76
int res;
const struct rlimit *rlim;
*******************************************/
if (uget(rlim, &r, sizeof(struct rlimit)))
return -1;
- o = uata.u_rlimit + res;
+ o = udata.u_rlimit + res;
if (r.rlim_cur > r.rlim_max)
goto bad;
#undef rlim
/*******************************************
- setpgid (pid, pgid) Function ??
+ setpgid (pid, pgid) Function 77
uint16_t npid;
uint16_t npgid;
*******************************************/
arg_t _setpgid(void)
{
- ptptr p, t;
+ ptptr p, t = NULL;
uint16_t ses = udata.u_ptab->p_session;
+ uint16_t n = npgid;
/* pid 0 means "self" */
if (npid == 0)
if (t->p_session != udata.u_ptab->p_session)
goto invalid;
- if (npgid == 0)
- npgid = t->p_pid;
+ if (n == 0)
+ n = t->p_pid;
/* Check if the group is in use with a different session */
for (p = ptab; p < ptab_end; ++p)
- if (p->p_pgrp == npgid && p->p_session != ses)
+ if (p->p_pgrp == n && p->p_session != ses)
goto invalid;
- t->p_pgrp = npgid;
+ t->p_pgrp = n;
return 0;
invalid:
#undef npgid
/*******************************************
- setsid (void) Function ??
+ setsid (void) Function 78
*******************************************/
arg_t _setsid(void)
uint16_t pid = udata.u_ptab->p_pid;
for (p = ptab; p < ptab_end; ++p) {
- if (p->p_pgid == pid || p->p_session == pid) {
+ if (p->p_pgrp == pid || p->p_session == pid) {
udata.u_error = EPERM;
return -1;
}
}
/*******************************************
- getsid (pid) Function ??
+ getsid (pid) Function 79
uint16_t pid;
*******************************************/
+#define pid (uint16_t)udata.u_argn
+
arg_t _getsid(void)
{
ptptr p;
udata.u_error = ESRCH;
return -1;
}
+#undef pid
+#endif
#include <kdata.h>
#include <netdev.h>
+#ifndef CONFIG_NET
+
#define NSOCKET 8
#undef nbytes
#undef uaddr
#undef flags
+
+#endif
/* For full session management it's a shade
more complicated and we have the routine
to do the full job */
- return setsid(0,0);
+ return _setsid();
#else
udata.u_ptab->p_pgrp = udata.u_ptab->p_pid;
udata.u_ptab->p_tty = 0;
udata.u_error = ENOTTY;
return -1;
}
- return tcsetpgrp(minor, t, data);
+ return tcsetpgrp(t, data);
#endif
default:
udata.u_error = ENOTTY;