From 51aa617463fb27a435745860b6211b36ea42dbd9 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 18 Nov 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-11-18 --- port/chan.c | 4 +- port/devcons.c | 10 +++ port/devproc.c | 175 +++++++++++++++++++++++++++++-------------------- port/error.h | 1 + port/parse.c | 21 ++++++ port/portdat.h | 8 +++ port/portfns.h | 1 + port/sysfile.c | 2 +- 8 files changed, 147 insertions(+), 75 deletions(-) diff --git a/port/chan.c b/port/chan.c index fdf428807e62e6dbc3a8d7eab10f1bdaefe41615..a1fda70d5d7fe1c4526b037a9b23d9d41f89a480 100644 --- a/port/chan.c +++ b/port/chan.c @@ -1161,10 +1161,8 @@ if(c->umh != nil){ */ e.nelems++; if(walk(&c, e.elems+e.nelems-1, 1, nomount) == 0){ - if(omode&OEXCL){ - cclose(c); + if(omode&OEXCL) error(Eexist); - } omode |= OTRUNC; goto Open; } diff --git a/port/devcons.c b/port/devcons.c index 88a71ec71c7ca12b78da0fb13975cd18d7bb8885..357f6eb432af8662a731794f6c6fe4e49d3e741b 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -801,8 +801,13 @@ consread(Chan *c, void *buf, long n, vlong off) *bp++ = '\n'; } } + if(waserror()){ + free(b); + nexterror(); + } n = readstr((ulong)offset, buf, n, b); free(b); + poperror(); return n; case Qswap: @@ -827,8 +832,13 @@ consread(Chan *c, void *buf, long n, vlong off) n = 0; for(i = 0; devtab[i] != nil; i++) n += snprint(b+n, READSTR-n, "#%C %s\n", devtab[i]->dc, devtab[i]->name); + if(waserror()){ + free(b); + nexterror(); + } n = readstr((ulong)offset, buf, n, b); free(b); + poperror(); return n; case Qzero: diff --git a/port/devproc.c b/port/devproc.c index 385b89dc0f3b065861cbe7897cf8b65defab6810..e016d428cec2fb52b32050fcbebf097756707549 100644 --- a/port/devproc.c +++ b/port/devproc.c @@ -28,6 +28,24 @@ enum Qprofile, }; +enum +{ + PCclose, + PCclosefiles, + PCfixedpri, + PChang, + PCkill, + PCnohang, + PCpri, + PCprivate, + PCprofile, + PCstart, + PCstartstop, + PCstop, + PCwaitstop, + PCwired, +}; + #define STATSIZE (2*KNAMELEN+12+9*12) /* * Status, fd, and ns are left fully readable (0444) because of their use in debugging, @@ -55,6 +73,23 @@ Dirtab procdir[] = "profile", {Qprofile}, 0, 0400, }; +Cmdtab proccmd[] = { + PCclose, "close", 2, + PCclosefiles, "closefiles", 1, + PCfixedpri, "fixedpri", 2, + PChang, "hang", 1, + PCnohang, "nohang", 1, + PCkill, "kill", 1, + PCpri, "pri", 2, + PCprivate, "private", 1, + PCprofile, "profile", 1, + PCstart, "start", 1, + PCstartstop, "startstop", 1, + PCstop, "stop", 1, + PCwaitstop, "waitstop", 1, + PCwired, "wired", 2, +}; + /* Segment type from portdat.h */ static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", }; @@ -1013,17 +1048,45 @@ procctlreq(Proc *p, char *va, int n) { Segment *s; int i, npc; - char buf[64]; + Cmdbuf *cb; + Cmdtab *ct; if(p->kp) /* no ctl requests to kprocs */ error(Eperm); - kstrcpy(buf, va, sizeof buf); + cb = parsecmd(va, n); + if(waserror()){ + free(cb); + nexterror(); + } - if(strncmp(buf, "stop", 4) == 0) - procstopwait(p, Proc_stopme); - else - if(strncmp(buf, "kill", 4) == 0) { + if(cb->nf <= 0) + error(Ebadctl); + + ct = lookupcmd(cb, proccmd, nelem(proccmd)); + + switch(ct->index){ + case PCclose: + procctlclosefiles(p, 0, atoi(cb->f[1])); + break; + case PCclosefiles: + procctlclosefiles(p, 1, 0); + break; + case PCfixedpri: + i = atoi(cb->f[1]); + if(i < 0) + i = 0; + if(i >= Nrq) + i = Nrq - 1; + if(i > p->basepri && !iseve()) + error(Eperm); + p->basepri = i; + p->fixedpri = 1; + break; + case PChang: + p->hang = 1; + break; + case PCkill: switch(p->state) { case Broken: unbreak(p); @@ -1037,46 +1100,12 @@ procctlreq(Proc *p, char *va, int n) postnote(p, 0, "sys: killed", NExit); p->procctl = Proc_exitme; } - } - else - if(strncmp(buf, "hang", 4) == 0) - p->hang = 1; - else - if(strncmp(buf, "nohang", 6) == 0) + break; + case PCnohang: p->hang = 0; - else - if(strncmp(buf, "waitstop", 8) == 0) - procstopwait(p, 0); - else - if(strncmp(buf, "startstop", 9) == 0) { - if(p->state != Stopped) - error(Ebadctl); - p->procctl = Proc_traceme; - ready(p); - procstopwait(p, Proc_traceme); - } - else - if(strncmp(buf, "start", 5) == 0) { - if(p->state != Stopped) - error(Ebadctl); - ready(p); - } - else - if(strncmp(buf, "closefiles", 10) == 0) - procctlclosefiles(p, 1, 0); - else - if(strncmp(buf, "close", 5) == 0){ - if(n < 6) - error(Ebadctl); - procctlclosefiles(p, 0, atoi(buf+6)); - }else - if(strncmp(buf, "private", 7) == 0) - p->privatemem = 1; - else - if(strncmp(buf, "pri", 3) == 0) { - if(n < 4) - error(Ebadctl); - i = atoi(buf+4); + break; + case PCpri: + i = atoi(cb->f[1]); if(i < 0) i = 0; if(i >= Nrq) @@ -1085,30 +1114,11 @@ procctlreq(Proc *p, char *va, int n) error(Eperm); p->basepri = i; p->fixedpri = 0; - } - else - if(strncmp(buf, "fixedpri", 8) == 0) { - if(n < 9) - error(Ebadctl); - i = atoi(buf+9); - if(i < 0) - i = 0; - if(i >= Nrq) - i = Nrq - 1; - if(i > p->basepri && !iseve()) - error(Eperm); - p->basepri = i; - p->fixedpri = 1; - } - else - if(strncmp(buf, "wired", 5) == 0) { - if(n < 6) - error(Ebadctl); - i = atoi(buf+6); - procwired(p, i); - } - else - if(strncmp(buf, "profile", 7) == 0) { + break; + case PCprivate: + p->privatemem = 1; + break; + case PCprofile: s = p->seg[TSEG]; if(s == 0 || (s->type&SG_TYPE) != SG_TEXT) error(Ebadctl); @@ -1118,9 +1128,32 @@ procctlreq(Proc *p, char *va, int n) s->profile = malloc(npc*sizeof(*s->profile)); if(s->profile == 0) error(Enomem); + break; + case PCstart: + if(p->state != Stopped) + error(Ebadctl); + ready(p); + break; + case PCstartstop: + if(p->state != Stopped) + error(Ebadctl); + p->procctl = Proc_traceme; + ready(p); + procstopwait(p, Proc_traceme); + break; + case PCstop: + procstopwait(p, Proc_stopme); + break; + case PCwaitstop: + procstopwait(p, 0); + break; + case PCwired: + procwired(p, atoi(cb->f[1])); + break; } - else - error(Ebadctl); + + poperror(); + free(cb); } int diff --git a/port/error.h b/port/error.h index 5447e9b77ba5601af7481f6eed05ea00d52b40a7..f08af6c09f8bdd18b9c22249fd1544f70cfd8571 100644 --- a/port/error.h +++ b/port/error.h @@ -22,6 +22,7 @@ extern char Etoosmall[]; /* read or write too small */ extern char Enoport[]; /* network port not available */ extern char Ehungup[]; /* i/o on hungup channel */ extern char Ebadctl[]; /* bad process or channel control request */ +extern char Eargctl[]; /* wrong number of arguments in control request */ extern char Enodev[]; /* no free devices */ extern char Eprocdied[]; /* process exited */ extern char Enochild[]; /* no living children */ diff --git a/port/parse.c b/port/parse.c index 333374170585b790b9caba0408573b9db52aaaf8..bb589366bffa3d3a288b65fb0075067a1c6c63b2 100644 --- a/port/parse.c +++ b/port/parse.c @@ -67,3 +67,24 @@ parsecmd(char *p, int n) return cb; } +/* + * Look up entry in table + */ +Cmdtab* +lookupcmd(Cmdbuf *cb, Cmdtab *ct, int nct) +{ + int i; + + if(cb->nf == 0) + error(Ebadctl); + + for(i=0; if[0], ct->cmd) != 0) + continue; + if(ct->narg!=0 && ct->narg!=cb->nf) + error(Eargctl); + return ct; + } + error(Ebadctl); + return nil; +} diff --git a/port/portdat.h b/port/portdat.h index 86add7aca762e1376fd63675ece58a2beb29ff90..091bc3ee6c3dc959229412d01b05919a422d8fba 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -2,6 +2,7 @@ typedef struct Alarms Alarms; typedef struct Block Block; typedef struct Chan Chan; typedef struct Cmdbuf Cmdbuf; +typedef struct Cmdtab Cmdtab; typedef struct Cname Cname; typedef struct Crypt Crypt; typedef struct Dev Dev; @@ -721,6 +722,13 @@ struct Cmdbuf int nf; }; +struct Cmdtab +{ + int index; /* used by client to switch on result */ + char *cmd; /* command name */ + int narg; /* expected #args; 0 ==> variadic */ +}; + /* * routines to access UART hardware */ diff --git a/port/portfns.h b/port/portfns.h index fd682af17a7796b02e54db2a481f8eda9314eea2..a4d81102b00764ca094f59193540134effa941b4 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -153,6 +153,7 @@ char* logctl(Log*, int, char**, Logflag*); void logn(Log*, int, void*, int); long logread(Log*, void*, ulong, long); void log(Log*, int, char*, ...); +Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int); void vlog(Log*, int, char*, va_list); Page* lookpage(Image*, ulong); void machinit(void); diff --git a/port/sysfile.c b/port/sysfile.c index 4bb23ca9da7603752ce386f826a8a15c36116414..5bb3711ef1b5692cb3868451b0143efc75443469 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -820,7 +820,7 @@ syscreate(ulong *arg) int fd; Chan *c = 0; - openmode(arg[1]); /* error check only */ + openmode(arg[1]&~OEXCL); /* error check only; OEXCL okay here */ if(waserror()) { if(c) cclose(c);