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
121 return aanclient(na, aanto);121 return aanclient(na, aanto);
122}122}
123 123
124static void
125rcpuexit(void)
126{
127 char *s = getenv("rstatus");
128 if(s != nil)
129 exit(*s);
130}
131
124void132void
125rcpu(char *host, char *cmd)133rcpu(char *host, char *cmd)
126{134{
@@ -133,6 +141,7 @@ rcpu(char *host, char *cmd) · 6 unmodified lines
133" bind -q /mnt/term/dev/cons /dev/cons\n"141" bind -q /mnt/term/dev/cons /dev/cons\n"
134"}\n"142"}\n"
135"</dev/cons >/dev/cons >[2=1] service=cpu %s\n"143"</dev/cons >/dev/cons >[2=1] service=cpu %s\n"
144"echo -n $status >/mnt/term/env/rstatus >[2]/dev/null\n"
136"echo -n hangup >/proc/$pid/notepg\n";145"echo -n hangup >/proc/$pid/notepg\n";
137 int fd;146 int fd;
138 147
@@ -163,6 +172,10 @@ rcpu(char *host, char *cmd) · 24 unmodified lines
163 sysfatal("sending script: %r");172 sysfatal("sending script: %r");
164 free(cmd);173 free(cmd);
165 174
175 /* /env/rstatus is written by the remote script to communicate exit status */
176 remove("/env/rstatus");
177 atexit(rcpuexit);
178
166 /* Begin serving the namespace */179 /* Begin serving the namespace */
167 exportfs(fd);180 exportfs(fd);
168}181}
gui-x11/x11.c+2−0
@@ -19,6 +19,8 @@ typedef struct Cursor Cursor; · 18 unmodified lines
19#define Display XDisplay19#define Display XDisplay
20#define Cursor XCursor20#define Cursor XCursor
21 21
22#undef getenv
23
22#include <X11/Xlib.h>24#include <X11/Xlib.h>
23#include <X11/Xatom.h>25#include <X11/Xatom.h>
24#include <X11/Xutil.h>26#include <X11/Xutil.h>
include/user.h+2−0
@@ -26,6 +26,7 @@ · 25 unmodified lines
26#undef sleep26#undef sleep
27#define sleep osmsleep27#define sleep osmsleep
28#define iounit sysiounit28#define iounit sysiounit
29#define getenv sysgetenv
29 30
30extern int bind(char*, char*, int);31extern int bind(char*, char*, int);
31extern int chdir(char*);32extern int chdir(char*);
@@ -96,3 +97,4 @@ extern void unlock(Lock*); · 64 unmodified lines
96extern int iprint(char*, ...);97extern int iprint(char*, ...);
97extern int atexit(void (*)(void));98extern int atexit(void (*)(void));
98extern void exits(char*);99extern void exits(char*);
100extern char* getenv(char*);
kern/Makefile+1−0
@@ -13,6 +13,7 @@ OFILES=\ · 12 unmodified lines
13 devcmd.$O\13 devcmd.$O\
14 devcons.$O\14 devcons.$O\
15 devdraw.$O\15 devdraw.$O\
16 devenv.$O\
16 devfs-$(OS).$O\17 devfs-$(OS).$O\
17 devip.$O\18 devip.$O\
18 devip-$(OS).$O\19 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
7enum
8{
9 Maxenvsize = 16300,
10};
11
12static Egrp *envgrp(Chan *c);
13static int envwriteable(Chan *c);
14static void initunix();
15
16static Egrp unixegrp; /* unix environment group */
17
18static Evalue*
19envlookup(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
32static int
33envgen(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
63static Chan*
64envattach(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
77static Walkqid*
78envwalk(Chan *c, Chan *nc, char **name, int nname)
79{
80 return devwalk(c, nc, name, nname, 0, 0, envgen);
81}
82
83static int
84envstat(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
91static Chan*
92envopen(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
136static Chan*
137envcreate(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
187static void
188envremove(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
218static void
219envclose(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
230static long
231envread(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
260static long
261envwrite(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
299Dev 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
320extern char **environ;
321
322static void
323initunix()
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
369void
370envcpy(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
395void
396closeegrp(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
414static Egrp*
415envgrp(Chan *c)
416{
417 if(c->aux == nil)
418 return &unixegrp;
419 return c->aux;
420}
421
422static int
423envwriteable(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
18extern Dev audiodevtab;18extern Dev audiodevtab;
19extern Dev kbddevtab;19extern Dev kbddevtab;
20extern Dev cmddevtab;20extern Dev cmddevtab;
21extern Dev envdevtab;
21 22
22Dev *devtab[] = {23Dev *devtab[] = {
23 &rootdevtab,24 &rootdevtab,
@@ -34,6 +35,7 @@ Dev *devtab[] = { · 10 unmodified lines
34 &audiodevtab,35 &audiodevtab,
35 &kbddevtab,36 &kbddevtab,
36 &cmddevtab,37 &cmddevtab,
38 &envdevtab,
37 039 0
38};40};
39 41
libc/Makefile+1−0
@@ -33,6 +33,7 @@ OFILES=\ · 32 unmodified lines
33 fmtstr.$O\33 fmtstr.$O\
34 fmtvprint.$O\34 fmtvprint.$O\
35 fprint.$O\35 fprint.$O\
36 getenv.$O\
36 getfields.$O\37 getfields.$O\
37 getpid.$O\38 getpid.$O\
38 lock.$O\39 lock.$O\
libc/getenv.c+45−0
@@ -0,0 +1,45 @@
1#include <u.h>
2#include <libc.h>
3
4char*
5getenv(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
47 47
48 if(bind("#c", "/dev", MBEFORE) < 0)48 if(bind("#c", "/dev", MBEFORE) < 0)
49 panic("bind #c: %r");49 panic("bind #c: %r");
50 if(bind("#e", "/env", MREPL|MCREATE) < 0)
51 panic("bind #e: %r");
50 if(bind("#I", "/net", MBEFORE) < 0)52 if(bind("#I", "/net", MBEFORE) < 0)
51 panic("bind #I: %r");53 panic("bind #I: %r");
52 if(bind("#U", "/root", MREPL) < 0)54 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