#include <9pm/u.h>
#include <9pm/libc.h>
#include "dat.h"
#include "fns.h"
static int ndev;
Dev *devtab[32];
void
adddev(Dev *d)
{
int i;
for(i=0; devtab[i]; i++)
if(devtab[i]==d)
return;
if(ndev >= nelem(devtab)-1)
pm_panic("too many devs");
devtab[ndev++] = d;
devtab[ndev] = nil;
(*d->reset)();
}
long
copyproc(Proc *p, int flag)
{
Proc *xp;
ulong arg;
long ret;
xp = up;
up = p;
arg = RFPROC|flag;
ret = sysrfork(&arg);
up = xp;
return ret;
}
Proc*
findproc(long pid)
{
int s;
Proc *p;
if(pid==0){
s = procindex(1);
if(s==-1 || (p=procalloc.arena[s])==nil)
panic("findproc");
pid = copyproc(p, RFNOTEG|RFCFDG);
}
s = procindex(pid);
if(s==-1 || (p=procalloc.arena[s])==nil || !canlock(&p->nascent))
return nil;
return p;
}
/*
* The first proc never runs. It exists only to be cloned.
*/
void
userinit(void)
{
Proc *p;
p = newproc();
p->pgrp = newpgrp();
p->egrp = smalloc(sizeof(Egrp));
p->egrp->ref.ref = 1;
p->fgrp = dupfgrp(nil);
p->rgrp = newrgrp();
p->procmode = 0640;
kstrdup(&p->text, "adam");
kstrdup(&p->user, eve);
p->state = Nascent;
lock(&p->nascent);
up = p;
}
Systab systab[Nsyscall] = {
{ sysr1, "", "Sysr1" },
{ sysbind, "ssl", "Bind" },
{ syschdir, "s", "Chdir" },
{ sysclose, "l", "Close" },
{ sysdup, "ll", "Dup" },
{ sysalarm, "l", "Alarm" },
{ sysexec, "sS", "Exec" },
{ sysexits, "s", "Exits" },
{ sysfauth, "ls", "Fauth" },
{ sysopen, "sl", "Open" },
{ syssleep, "l", "Sleep" },
{ sysrfork, "l", "Rfork" },
{ syspipe, "f", "Pipe" },
{ syscreate, "sll", "Create" },
{ sysfd2path, "lb", "Fd2path" },
{ sysfd2path, "lb", "Fd2syspath" },
{ sysremove, "s", "Remove" },
{ sysnoted, "l", "Noted" },
{ sysrendezvous, "ll", "Rendez" },
{ sysunmount, "ns", "Unmount" },
{ sysseek, "Vlvl", "Seek" },
{ sysfversion, "llb", "Fversion" },
{ syserrstr, "b", "Errstr" },
{ sysstat, "sb", "Stat" },
{ sysfstat, "lb", "Fstat" },
{ syswstat, "sb", "Wstat" },
{ sysfwstat, "lb", "Fwstat" },
{ sysmount, "llsls", "Mount" },
{ sysawait, "b", "Await" },
{ syspread, "lbv", "Pread" },
{ syspwrite, "lbv", "Pwrite" },
{ syspassfd, "ll", "Passfd" },
{ syspassdir, "s", "Passdir" },
};
static char Eaddr[] = "invalid address in system call";
void
validargs(ulong *arg, void *vs, void *ve, char *fmt)
{
char *p;
ulong *a, *b, *c, *s, *e;
ulong n;
if(fmt == nil)
error("bad fmt for system call (bug)");
s = vs;
e = ve;
for(p=fmt; *p; p++){
switch(*p){
default:
error("unknown fmt char (bug)");
case 'l': /* integer */
arg++;
break;
case 'n': /* possibly null string pointer */
if(*arg == ~0){
*arg = 0;
break;
}
/* fall through */
case 's': /* string pointer */
*arg += (ulong)s;
a = (ulong*)(*arg++);
if(a < s || a >= e || memchr(a, 0, (uchar*)e-(uchar*)a) == nil)
error(Eaddr);
break;
case 'S': /* pointer to zero-terminated array of string pointers */
*arg += (ulong)s;
a = (ulong*)(*arg++);
if(a < s || ((ulong)a&(sizeof(ulong)-1)))
error(Eaddr);
for(b=a; b<e; b++){
if(*b == ~0){
*b = 0;
break;
}
*b += (ulong)s;
c = (ulong*)*b;
if(c < s || c >= e || memchr(c, 0, (uchar*)e-(uchar*)c) == nil)
error(Eaddr);
}
if(b >= e)
error(Eaddr);
break;
case 'V': /* pointer to vlong */
case 'f': /* pointer to two integers */
*arg += (ulong)s;
a = (ulong*)(*arg++);
if(a < s || a+2 > e)
error(Eaddr);
break;
case 'v': /* vlong */
arg += 2;
break;
case 'b': /* buffer: pointer followed by length */
*arg += (ulong)s;
a = (ulong*)(*arg++);
n = *arg++;
if(a < s || (uchar*)a+n > (uchar*)e)
error(Eaddr);
break;
}
}
}
/*
* These don't have any effect on whether we can get preempted
* for another process, of course, but they do change our behavior
* when spinning for a test-and-set lock: if we are spl hi, we call
* ossched to yield the processor after glaring for a little while.
* Probably this is a kludge and what we should really do is always yield.
*/
int
splhi(void)
{
int s;
s = M->spl;
M->spl = 1;
return s;
}
int
spllo(void)
{
int s;
s = M->spl;
M->spl = 0;
return s;
}
int
islo(void)
{
return M->spl==0;
}
void
splx(int s)
{
M->spl = s;
}
syntax highlighted by Code2HTML, v. 0.9.1