History

Add devenv to provide exit status for rcpu (thanks Fazlul)

Original change applied, but with different handling of $rstatus using atexit() handler instead of modifying exportfs read loop. Also importing plan9 libc getenv().

cinap_lenrek committed 6 years ago

Commit 566f2771 parent 11729e29 files · +494 −0Browse files

Unified · Split

9 files
  1. cpu.c +13 −0
  2. gui-x11/x11.c +2 −0
  3. include/user.h +2 −0
  4. kern/Makefile +1 −0
  5. kern/devenv.c +426 −0
  6. kern/devtab.c +2 −0
  7. libc/Makefile +1 −0
  8. libc/getenv.c +45 −0
  9. main.c +2 −0
cpu.c+13−0
@@ -121,6 +121,14 @@ startaan(char *host, int fd) · 120 unmodified lines
121121 return aanclient(na, aanto);
122122 }
123123
124+static void
125+rcpuexit(void)
126+{
127+ char *s = getenv("rstatus");
128+ if(s != nil)
129+ exit(*s);
130+}
131+
124132 void
125133 rcpu(char *host, char *cmd)
126134 {
@@ -133,6 +141,7 @@ rcpu(char *host, char *cmd) · 6 unmodified lines
133141 " bind -q /mnt/term/dev/cons /dev/cons\n"
134142 "}\n"
135143 "</dev/cons >/dev/cons >[2=1] service=cpu %s\n"
144+"echo -n $status >/mnt/term/env/rstatus >[2]/dev/null\n"
136145 "echo -n hangup >/proc/$pid/notepg\n";
137146 int fd;
138147
@@ -163,6 +172,10 @@ rcpu(char *host, char *cmd) · 24 unmodified lines
163172 sysfatal("sending script: %r");
164173 free(cmd);
165174
175+ /* /env/rstatus is written by the remote script to communicate exit status */
176+ remove("/env/rstatus");
177+ atexit(rcpuexit);
178+
166179 /* Begin serving the namespace */
167180 exportfs(fd);
168181 }
gui-x11/x11.c+2−0
@@ -19,6 +19,8 @@ typedef struct Cursor Cursor; · 18 unmodified lines
1919 #define Display XDisplay
2020 #define Cursor XCursor
2121
22+#undef getenv
23+
2224 #include <X11/Xlib.h>
2325 #include <X11/Xatom.h>
2426 #include <X11/Xutil.h>
include/user.h+2−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
2626 #undef sleep
2727 #define sleep osmsleep
2828 #define iounit sysiounit
29+#define getenv sysgetenv
2930
3031 extern int bind(char*, char*, int);
3132 extern int chdir(char*);
@@ -96,3 +97,4 @@ extern void unlock(Lock*); · 64 unmodified lines
9697 extern int iprint(char*, ...);
9798 extern int atexit(void (*)(void));
9899 extern void exits(char*);
100+extern char* getenv(char*);
kern/Makefile+1−0
@@ -13,6 +13,7 @@ OFILES=\ · 12 unmodified lines
1313 devcmd.$O\
1414 devcons.$O\
1515 devdraw.$O\
16+ devenv.$O\
1617 devfs-$(OS).$O\
1718 devip.$O\
1819 devip-$(OS).$O\
kern/devenv.c+426−0
@@ -0,0 +1,426 @@
1+#include "u.h"
2+#include "lib.h"
3+#include "dat.h"
4+#include "fns.h"
5+#include "error.h"
6+
7+enum
8+{
9+ Maxenvsize = 16300,
10+};
11+
12+static Egrp *envgrp(Chan *c);
13+static int envwriteable(Chan *c);
14+static void initunix();
15+
16+static Egrp unixegrp; /* unix environment group */
17+
18+static Evalue*
19+envlookup(Egrp *eg, char *name, ulong qidpath)
20+{
21+ Evalue *e;
22+ int i;
23+
24+ for(i=0; i<eg->nent; i++){
25+ e = eg->ent[i];
26+ if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0))
27+ return e;
28+ }
29+ return nil;
30+}
31+
32+static int
33+envgen(Chan *c, char *name, Dirtab *_1, int _2, int s, Dir *dp)
34+{
35+ Egrp *eg;
36+ Evalue *e;
37+
38+ if(s == DEVDOTDOT){
39+ devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp);
40+ return 1;
41+ }
42+
43+ eg = envgrp(c);
44+ rlock(&eg->lk);
45+ e = 0;
46+ if(name)
47+ e = envlookup(eg, name, -1);
48+ else if(s < eg->nent)
49+ e = eg->ent[s];
50+
51+ if(e == 0) {
52+ runlock(&eg->lk);
53+ return -1;
54+ }
55+
56+ /* make sure name string continues to exist after we release lock */
57+ kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
58+ devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
59+ runlock(&eg->lk);
60+ return 1;
61+}
62+
63+static Chan*
64+envattach(char *spec)
65+{
66+ Chan *c;
67+
68+ if(spec && *spec) {
69+ error(Ebadarg);
70+ }
71+ initunix();
72+ c = devattach('e', spec);
73+ c->aux = &unixegrp;
74+ return c;
75+}
76+
77+static Walkqid*
78+envwalk(Chan *c, Chan *nc, char **name, int nname)
79+{
80+ return devwalk(c, nc, name, nname, 0, 0, envgen);
81+}
82+
83+static int
84+envstat(Chan *c, uchar *db, int n)
85+{
86+ if(c->qid.type & QTDIR)
87+ c->qid.vers = envgrp(c)->vers;
88+ return devstat(c, db, n, 0, 0, envgen);
89+}
90+
91+static Chan*
92+envopen(Chan *c, int omode)
93+{
94+ Egrp *eg;
95+ Evalue *e;
96+ int trunc;
97+
98+ eg = envgrp(c);
99+ if(c->qid.type & QTDIR) {
100+ if(omode != OREAD)
101+ error(Eperm);
102+ }
103+ else {
104+ trunc = omode & OTRUNC;
105+ if(omode != OREAD && !envwriteable(c))
106+ error(Eperm);
107+ if(trunc)
108+ wlock(&eg->lk);
109+ else
110+ rlock(&eg->lk);
111+ e = envlookup(eg, nil, c->qid.path);
112+ if(e == 0) {
113+ if(trunc)
114+ wunlock(&eg->lk);
115+ else
116+ runlock(&eg->lk);
117+ error(Enonexist);
118+ }
119+ if(trunc && e->value) {
120+ e->qid.vers++;
121+ free(e->value);
122+ e->value = 0;
123+ e->len = 0;
124+ }
125+ if(trunc)
126+ wunlock(&eg->lk);
127+ else
128+ runlock(&eg->lk);
129+ }
130+ c->mode = openmode(omode);
131+ c->flag |= COPEN;
132+ c->offset = 0;
133+ return c;
134+}
135+
136+static Chan*
137+envcreate(Chan *c, char *name, int omode, ulong _)
138+{
139+ Egrp *eg;
140+ Evalue *e;
141+ Evalue **ent;
142+
143+ if(c->qid.type != QTDIR)
144+ error(Eperm);
145+ if(strlen(name) >= sizeof up->genbuf)
146+ error("name too long"); /* protect envgen */
147+
148+ omode = openmode(omode);
149+ eg = envgrp(c);
150+
151+ wlock(&eg->lk);
152+ if(waserror()) {
153+ wunlock(&eg->lk);
154+ nexterror();
155+ }
156+
157+ if(envlookup(eg, name, -1))
158+ error(Eexist);
159+
160+ e = smalloc(sizeof(Evalue));
161+ e->name = smalloc(strlen(name)+1);
162+ strcpy(e->name, name);
163+
164+ if(eg->nent == eg->ment){
165+ eg->ment += 32;
166+ ent = smalloc(sizeof(eg->ent[0])*eg->ment);
167+ if(eg->nent)
168+ memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent);
169+ free(eg->ent);
170+ eg->ent = ent;
171+ }
172+ e->qid.path = ++eg->path;
173+ e->qid.vers = 0;
174+ eg->vers++;
175+ eg->ent[eg->nent++] = e;
176+ c->qid = e->qid;
177+
178+ wunlock(&eg->lk);
179+ poperror();
180+
181+ c->offset = 0;
182+ c->mode = omode;
183+ c->flag |= COPEN;
184+ return c;
185+}
186+
187+static void
188+envremove(Chan *c)
189+{
190+ int i;
191+ Egrp *eg;
192+ Evalue *e;
193+
194+ if(c->qid.type & QTDIR)
195+ error(Eperm);
196+
197+ eg = envgrp(c);
198+ wlock(&eg->lk);
199+ e = 0;
200+ for(i=0; i<eg->nent; i++){
201+ if(eg->ent[i]->qid.path == c->qid.path){
202+ e = eg->ent[i];
203+ eg->nent--;
204+ eg->ent[i] = eg->ent[eg->nent];
205+ eg->vers++;
206+ break;
207+ }
208+ }
209+ wunlock(&eg->lk);
210+ if(e == 0)
211+ error(Enonexist);
212+ free(e->name);
213+ if(e->value)
214+ free(e->value);
215+ free(e);
216+}
217+
218+static void
219+envclose(Chan *c)
220+{
221+ /*
222+ * cclose can't fail, so errors from remove will be ignored.
223+ * since permissions aren't checked,
224+ * envremove can't not remove it if its there.
225+ */
226+ if(c->flag & CRCLOSE)
227+ envremove(c);
228+}
229+
230+static long
231+envread(Chan *c, void *a, long n, vlong off)
232+{
233+ Egrp *eg;
234+ Evalue *e;
235+ ulong offset = off;
236+
237+ if(c->qid.type & QTDIR)
238+ return devdirread(c, a, n, 0, 0, envgen);
239+
240+ eg = envgrp(c);
241+ rlock(&eg->lk);
242+ e = envlookup(eg, nil, c->qid.path);
243+ if(e == 0) {
244+ runlock(&eg->lk);
245+ error(Enonexist);
246+ }
247+
248+ if(offset > e->len) /* protects against overflow converting vlong to ulong */
249+ n = 0;
250+ else if(offset + n > e->len)
251+ n = e->len - offset;
252+ if(n <= 0)
253+ n = 0;
254+ else
255+ memmove(a, e->value+offset, n);
256+ runlock(&eg->lk);
257+ return n;
258+}
259+
260+static long
261+envwrite(Chan *c, void *a, long n, vlong off)
262+{
263+ char *s;
264+ ulong len;
265+ Egrp *eg;
266+ Evalue *e;
267+ ulong offset = off;
268+
269+ if(n <= 0)
270+ return 0;
271+ if(offset > Maxenvsize || n > (Maxenvsize - offset))
272+ error(Etoobig);
273+
274+ eg = envgrp(c);
275+ wlock(&eg->lk);
276+ e = envlookup(eg, nil, c->qid.path);
277+ if(e == 0) {
278+ wunlock(&eg->lk);
279+ error(Enonexist);
280+ }
281+
282+ len = offset+n;
283+ if(len > e->len) {
284+ s = smalloc(len);
285+ if(e->value){
286+ memmove(s, e->value, e->len);
287+ free(e->value);
288+ }
289+ e->value = s;
290+ e->len = len;
291+ }
292+ memmove(e->value+offset, a, n);
293+ e->qid.vers++;
294+ eg->vers++;
295+ wunlock(&eg->lk);
296+ return n;
297+}
298+
299+Dev envdevtab = {
300+ 'e',
301+ "env",
302+
303+ devreset,
304+ devinit,
305+ devshutdown,
306+ envattach,
307+ envwalk,
308+ envstat,
309+ envopen,
310+ envcreate,
311+ envclose,
312+ envread,
313+ devbread,
314+ envwrite,
315+ devbwrite,
316+ envremove,
317+ devwstat,
318+};
319+
320+extern char **environ;
321+
322+static void
323+initunix()
324+{
325+ Egrp *eg = &unixegrp;
326+ Evalue **ent, *e;
327+ char *eq, **envp, *line;
328+ int n;
329+
330+ wlock(&eg->lk);
331+
332+ if(eg->path > 0 || eg->ment > 0 || !environ){
333+ // already initialized or nothing in environent
334+ wunlock(&eg->lk);
335+ return;
336+ }
337+
338+ for(envp = environ; *envp != nil; envp++)
339+ eg->ment++;
340+ ent = smalloc(sizeof(eg->ent[0])*eg->ment);
341+ eg->ent = ent;
342+
343+ for(envp = environ; *envp != nil; envp++){
344+ line = *envp;
345+ n = strlen(line);
346+
347+ eq = strchr(line, '=');
348+ if(eq == nil)
349+ eq = &line[n];
350+ e = smalloc(sizeof(Evalue));
351+ e->name = smalloc(eq-line+1);
352+ strncpy(e->name, line, eq-line);
353+
354+ if(eq[0] != '\0')
355+ eq++;
356+ e->len = line+n-eq;
357+ e->value = smalloc(e->len);
358+ memmove(e->value, eq, e->len);
359+
360+ e->qid.path = ++eg->path;
361+ e->qid.vers = 0;
362+ eg->vers++;
363+ eg->ent[eg->nent++] = e;
364+ }
365+
366+ wunlock(&eg->lk);
367+}
368+
369+void
370+envcpy(Egrp *to, Egrp *from)
371+{
372+ int i;
373+ Evalue *ne, *e;
374+
375+ rlock(&from->lk);
376+ to->ment = (from->nent+31)&~31;
377+ to->ent = smalloc(to->ment*sizeof(to->ent[0]));
378+ for(i=0; i<from->nent; i++){
379+ e = from->ent[i];
380+ ne = smalloc(sizeof(Evalue));
381+ ne->name = smalloc(strlen(e->name)+1);
382+ strcpy(ne->name, e->name);
383+ if(e->value){
384+ ne->value = smalloc(e->len);
385+ memmove(ne->value, e->value, e->len);
386+ ne->len = e->len;
387+ }
388+ ne->qid.path = ++to->path;
389+ to->ent[i] = ne;
390+ }
391+ to->nent = from->nent;
392+ runlock(&from->lk);
393+}
394+
395+void
396+closeegrp(Egrp *eg)
397+{
398+ int i;
399+ Evalue *e;
400+
401+ if(decref(&eg->ref) == 0){
402+ for(i=0; i<eg->nent; i++){
403+ e = eg->ent[i];
404+ free(e->name);
405+ if(e->value)
406+ free(e->value);
407+ free(e);
408+ }
409+ free(eg->ent);
410+ free(eg);
411+ }
412+}
413+
414+static Egrp*
415+envgrp(Chan *c)
416+{
417+ if(c->aux == nil)
418+ return &unixegrp;
419+ return c->aux;
420+}
421+
422+static int
423+envwriteable(Chan *c)
424+{
425+ return iseve() || c->aux == nil;
426+}
kern/devtab.c+2−0
@@ -18,6 +18,7 @@ extern Dev lfddevtab; · 17 unmodified lines
1818 extern Dev audiodevtab;
1919 extern Dev kbddevtab;
2020 extern Dev cmddevtab;
21+extern Dev envdevtab;
2122
2223 Dev *devtab[] = {
2324 &rootdevtab,
@@ -34,6 +35,7 @@ Dev *devtab[] = { · 10 unmodified lines
3435 &audiodevtab,
3536 &kbddevtab,
3637 &cmddevtab,
38+ &envdevtab,
3739 0
3840 };
3941
libc/Makefile+1−0
@@ -33,6 +33,7 @@ OFILES=\ · 32 unmodified lines
3333 fmtstr.$O\
3434 fmtvprint.$O\
3535 fprint.$O\
36+ getenv.$O\
3637 getfields.$O\
3738 getpid.$O\
3839 lock.$O\
libc/getenv.c+45−0
@@ -0,0 +1,45 @@
1+#include <u.h>
2+#include <libc.h>
3+
4+char*
5+getenv(char *name)
6+{
7+ enum { HUNK = 100, };
8+ char *s, *p;
9+ int f, r, n;
10+
11+ if(name[0]=='\0' || strcmp(name, ".")==0 || strcmp(name, "..")==0 || strchr(name, '/')!=nil
12+ || strlen(name) >= HUNK-5){
13+ werrstr("bad env name: %s", name);
14+ return nil;
15+ }
16+ if((s = malloc(HUNK)) == nil)
17+ return nil;
18+ snprint(s, HUNK, "/env/%s", name);
19+ n = 0;
20+ r = -1;
21+ if((f = open(s, OREAD)) >= 0){
22+ while((r = read(f, s+n, HUNK)) > 0){
23+ n += r;
24+ r = -1;
25+ if((p = realloc(s, n+HUNK)) == nil)
26+ break;
27+ s = p;
28+ }
29+ close(f);
30+ }
31+ if(r < 0 || (p = realloc(s, n+1)) == nil){
32+ free(s);
33+ return nil;
34+ }
35+ s = p;
36+ setmalloctag(s, getcallerpc(&name));
37+ while(n > 0 && s[n-1] == '\0')
38+ n--;
39+ s[n] = '\0';
40+ while(--n >= 0){
41+ if(s[n] == '\0')
42+ s[n] = ' ';
43+ }
44+ return s;
45+}
main.c+2−0
@@ -47,6 +47,8 @@ main(int argc, char **argv) · 46 unmodified lines
4747
4848 if(bind("#c", "/dev", MBEFORE) < 0)
4949 panic("bind #c: %r");
50+ if(bind("#e", "/env", MREPL|MCREATE) < 0)
51+ panic("bind #e: %r");
5052 if(bind("#I", "/net", MBEFORE) < 0)
5153 panic("bind #I: %r");
5254 if(bind("#U", "/root", MREPL) < 0)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t