From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qt1-f176.google.com ([209.85.160.176]) by ewsd; Fri Jun 19 13:31:14 EDT 2020 Received: by mail-qt1-f176.google.com with SMTP id h23so656977qtr.0 for <9front@9front.org>; Fri, 19 Jun 2020 10:31:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:subject:message-id:mime-version:content-disposition; bh=Qves7fEex3pr42zm/DvfNLvmQuLH3JgmLSHc7bgFCgs=; b=Sr7GQgthD7eS8elkIQB5RlvS1M3+a5hMH6qrrnabjRBHgdtCPtzLknXmkPS+pnCSrV w6LKIJiQzTTy+Gsc2iBp07M80Oc8TWf5fpEfsE+2spYryAm6LrJCnjDzJSWKUXvDPgGz Do0nSay48XLMQX1w1aVbdLjODuMerzxk2BTaGosx3wRoko7cBOW1IlVC06ICKcNOZVmZ 9otxyZ7YQBN+IUnUU3m6wINwHJQPxrPnvh7RGx/56Kg37sz0Di4Q42+qC7iC+OfZMQoe RL8klXTL7h5RYtCRtjl9MwJR71kzLuvQgHwjrOt1At4elolhwr/qGQOlozNGsCl3YrT1 /Rrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mime-version :content-disposition; bh=Qves7fEex3pr42zm/DvfNLvmQuLH3JgmLSHc7bgFCgs=; b=NCbPsrakITNgLpibLZIxw2hYV3/bt9dv9CkRkU5To2f7qwYQ76DSjXCti8gNRk0vh8 79tjlWdFnh57+gxqLSAJKABybXX5WAaFOhwTLyDB886ZyalkoQy55F5x9Fk5Kz2EEceG wq97pyd01f5E4mQtGtkJl72SD14Jo7WPs5sKCyDg9+NO5/gaEs+hPklMcVaC+/bKepjx LUCQF0uUVPpeFRMQ4NzxUEDgD4x+PYX+XP8SXbb+4Mnl+sbjYAhIfpu0CS1qD4aEbGNj VdxuC9wIxiKt2PXc2YoAVWEZygY8QEZqOxM4s4g1yJy0Kt6Ew8Sa+O+trwSqzNJFAupR dl8Q== X-Gm-Message-State: AOAM533rcgIT1frQQANh/3JZT/SaZgp63FdOMm5ZUcPM0H+b7butsZM5 aP3AEL7ycMXl1IahB1hah6qEyxq8LA4= X-Google-Smtp-Source: ABdhPJyqiQF0xXViuiMK1XWr0zqlQUrQ8TR6piYkGYM6534bxylCtcp1ptEGzuy/j3XnWXyqcifm0A== X-Received: by 2002:ac8:7a9a:: with SMTP id x26mr23046qtr.161.1592587868566; Fri, 19 Jun 2020 10:31:08 -0700 (PDT) Return-Path: Received: from delta.localdomain (pool-96-246-81-93.nycmny.fios.verizon.net. [96.246.81.93]) by smtp.gmail.com with ESMTPSA id b4sm6145787qka.133.2020.06.19.10.31.07 for <9front@9front.org> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 19 Jun 2020 10:31:07 -0700 (PDT) Date: Fri, 19 Jun 2020 13:31:06 -0400 From: Fazlul Shahriar To: 9front@9front.org Subject: [PATCH] [drawterm] Add devenv and fix exit status for -G flag Message-ID: <20200619173106.GA576387@delta.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline List-ID: <9front.9front.org> List-Help: X-Glyph: ➈ X-Bullshit: basic strategy Currently drawterm doesn't exit with a non-zero exit status if the command run with -G flag fails. This issue came up while using sr.ht CI (see https://todo.sr.ht/~sircmpwn/builds.sr.ht/287). This problem does not exist in rcpu(1), which saves the exit status of the remote command in /mnt/term/env/rstatus and then later uses that for its own exit status. However, drawterm doesn't have devenv. This patch adds devenv to drawterm and fixes the exit status issue. Devenv also initializes /mnt/term/env with environment variables from the client machine (see kern/devenv.c:/^initunix), which can be useful even if it's not strictly necessary to solve the issue. diff -r cdbacd80f61a cpu.c --- a/cpu.c Wed May 27 00:21:41 2020 +0200 +++ b/cpu.c Fri Jun 19 13:22:19 2020 -0400 @@ -133,6 +133,7 @@ " bind -q /mnt/term/dev/cons /dev/cons\n" "}\n" "/dev/cons >[2=1] service=cpu %s\n" +"echo -n $status >/mnt/term/env/rstatus >[2]/dev/null\n" "echo -n hangup >/proc/$pid/notepg\n"; int fd; @@ -152,6 +153,12 @@ } memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ + /* $rstatus is used by exportfs to determine exit status */ + putenv("rstatus="); + + if(bind("#e", "/env", MREPL|MCREATE) < 0) + panic("bind #e: %r"); + if(cmd == nil) cmd = smprint(script, "rc -li"); else { diff -r cdbacd80f61a exportfs/exportfs.c --- a/exportfs/exportfs.c Wed May 27 00:21:41 2020 +0200 +++ b/exportfs/exportfs.c Fri Jun 19 13:22:19 2020 -0400 @@ -80,7 +80,7 @@ DEBUG(DFD, "read9p..."); n = read9pmsg(netfd, r->buf, messagesize); if(n <= 0) - fatal(nil); + exitrstatus(); if(convM2S(r->buf, n, &r->work) == 0){ iprint("convM2S %d byte message\n", n); @@ -483,6 +483,23 @@ return q; } +/* + * Exit using the rstatus environment variable, set by the cpu script. + */ +void +exitrstatus() +{ + char buf[100]; + int fd; + + memset(buf, 0, sizeof buf); + if((fd = open("/env/rstatus", OREAD)) >= 0){ + read(fd, buf, (sizeof buf)-1); + close(fd); + } + exits(buf); +} + void fatal(char *s, ...) { diff -r cdbacd80f61a exportfs/exportfs.h --- a/exportfs/exportfs.h Wed May 27 00:21:41 2020 +0200 +++ b/exportfs/exportfs.h Fri Jun 19 13:22:19 2020 -0400 @@ -125,6 +125,7 @@ Fid *newfid(int); Fsrpc *getsbuf(void); void initroot(void); +void exitrstatus(); void fatal(char*, ...); char* makepath(File*, char*); File *file(File*, char*); diff -r cdbacd80f61a kern/Makefile --- a/kern/Makefile Wed May 27 00:21:41 2020 +0200 +++ b/kern/Makefile Fri Jun 19 13:22:19 2020 -0400 @@ -13,6 +13,7 @@ devcmd.$O\ devcons.$O\ devdraw.$O\ + devenv.$O\ devfs-$(OS).$O\ devip.$O\ devip-$(OS).$O\ diff -r cdbacd80f61a kern/devenv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kern/devenv.c Fri Jun 19 13:22:19 2020 -0400 @@ -0,0 +1,427 @@ +#include "u.h" +#include "lib.h" +#include "dat.h" +#include "fns.h" +#include "error.h" + +enum +{ + Maxenvsize = 16300, +}; + +static Egrp *envgrp(Chan *c); +static int envwriteable(Chan *c); +static void initunix(); + +static Egrp unixegrp; /* unix environment group */ + +static Evalue* +envlookup(Egrp *eg, char *name, ulong qidpath) +{ + Evalue *e; + int i; + + for(i=0; inent; i++){ + e = eg->ent[i]; + if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0)) + return e; + } + return nil; +} + +static int +envgen(Chan *c, char *name, Dirtab *_1, int _2, int s, Dir *dp) +{ + Egrp *eg; + Evalue *e; + + if(s == DEVDOTDOT){ + devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp); + return 1; + } + + eg = envgrp(c); + rlock(&eg->lk); + e = 0; + if(name) + e = envlookup(eg, name, -1); + else if(s < eg->nent) + e = eg->ent[s]; + + if(e == 0) { + runlock(&eg->lk); + return -1; + } + + /* make sure name string continues to exist after we release lock */ + kstrcpy(up->genbuf, e->name, sizeof up->genbuf); + devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp); + runlock(&eg->lk); + return 1; +} + +static Chan* +envattach(char *spec) +{ + Chan *c; + + if(spec && *spec) { + error(Ebadarg); + } + initunix(); + c = devattach('e', spec); + c->aux = &unixegrp; + return c; +} + +static Walkqid* +envwalk(Chan *c, Chan *nc, char **name, int nname) +{ + return devwalk(c, nc, name, nname, 0, 0, envgen); +} + +static int +envstat(Chan *c, uchar *db, int n) +{ + if(c->qid.type & QTDIR) + c->qid.vers = envgrp(c)->vers; + return devstat(c, db, n, 0, 0, envgen); +} + +static Chan* +envopen(Chan *c, int omode) +{ + Egrp *eg; + Evalue *e; + int trunc; + + eg = envgrp(c); + if(c->qid.type & QTDIR) { + if(omode != OREAD) + error(Eperm); + } + else { + trunc = omode & OTRUNC; + if(omode != OREAD && !envwriteable(c)) + error(Eperm); + if(trunc) + wlock(&eg->lk); + else + rlock(&eg->lk); + e = envlookup(eg, nil, c->qid.path); + if(e == 0) { + if(trunc) + wunlock(&eg->lk); + else + runlock(&eg->lk); + error(Enonexist); + } + if(trunc && e->value) { + e->qid.vers++; + free(e->value); + e->value = 0; + e->len = 0; + } + if(trunc) + wunlock(&eg->lk); + else + runlock(&eg->lk); + } + c->mode = openmode(omode); + c->flag |= COPEN; + c->offset = 0; + return c; +} + +static Chan* +envcreate(Chan *c, char *name, int omode, ulong _) +{ + Egrp *eg; + Evalue *e; + Evalue **ent; + + if(c->qid.type != QTDIR) + error(Eperm); + if(strlen(name) >= sizeof up->genbuf) + error("name too long"); /* protect envgen */ + + omode = openmode(omode); + eg = envgrp(c); + + wlock(&eg->lk); + if(waserror()) { + wunlock(&eg->lk); + nexterror(); + } + + if(envlookup(eg, name, -1)) + error(Eexist); + + e = smalloc(sizeof(Evalue)); + e->name = smalloc(strlen(name)+1); + strcpy(e->name, name); + + if(eg->nent == eg->ment){ + eg->ment += 32; + ent = smalloc(sizeof(eg->ent[0])*eg->ment); + if(eg->nent) + memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent); + free(eg->ent); + eg->ent = ent; + } + e->qid.path = ++eg->path; + e->qid.vers = 0; + eg->vers++; + eg->ent[eg->nent++] = e; + c->qid = e->qid; + + wunlock(&eg->lk); + poperror(); + + c->offset = 0; + c->mode = omode; + c->flag |= COPEN; + return c; +} + +static void +envremove(Chan *c) +{ + int i; + Egrp *eg; + Evalue *e; + + if(c->qid.type & QTDIR) + error(Eperm); + + eg = envgrp(c); + wlock(&eg->lk); + e = 0; + for(i=0; inent; i++){ + if(eg->ent[i]->qid.path == c->qid.path){ + e = eg->ent[i]; + eg->nent--; + eg->ent[i] = eg->ent[eg->nent]; + eg->vers++; + break; + } + } + wunlock(&eg->lk); + if(e == 0) + error(Enonexist); + free(e->name); + if(e->value) + free(e->value); + free(e); +} + +static void +envclose(Chan *c) +{ + /* + * cclose can't fail, so errors from remove will be ignored. + * since permissions aren't checked, + * envremove can't not remove it if its there. + */ + if(c->flag & CRCLOSE) + envremove(c); +} + +static long +envread(Chan *c, void *a, long n, vlong off) +{ + Egrp *eg; + Evalue *e; + ulong offset = off; + + if(c->qid.type & QTDIR) + return devdirread(c, a, n, 0, 0, envgen); + + eg = envgrp(c); + rlock(&eg->lk); + e = envlookup(eg, nil, c->qid.path); + if(e == 0) { + runlock(&eg->lk); + error(Enonexist); + } + + if(offset > e->len) /* protects against overflow converting vlong to ulong */ + n = 0; + else if(offset + n > e->len) + n = e->len - offset; + if(n <= 0) + n = 0; + else + memmove(a, e->value+offset, n); + runlock(&eg->lk); + return n; +} + +static long +envwrite(Chan *c, void *a, long n, vlong off) +{ + char *s; + ulong len; + Egrp *eg; + Evalue *e; + ulong offset = off; + + if(n <= 0) + return 0; + if(offset > Maxenvsize || n > (Maxenvsize - offset)) + error(Etoobig); + + eg = envgrp(c); + wlock(&eg->lk); + e = envlookup(eg, nil, c->qid.path); + if(e == 0) { + wunlock(&eg->lk); + error(Enonexist); + } + + len = offset+n; + if(len > e->len) { + s = smalloc(len); + if(e->value){ + memmove(s, e->value, e->len); + free(e->value); + } + e->value = s; + e->len = len; + } + memmove(e->value+offset, a, n); + e->qid.vers++; + eg->vers++; + wunlock(&eg->lk); + return n; +} + +Dev envdevtab = { + 'e', + "env", + + devreset, + devinit, + devshutdown, + envattach, + envwalk, + envstat, + envopen, + envcreate, + envclose, + envread, + devbread, + envwrite, + devbwrite, + envremove, + devwstat, +}; + +extern char **environ; + +static void +initunix() +{ + Egrp *eg = &unixegrp; + Evalue **ent, *e; + char *eq, **envp, *line; + int n; + + wlock(&eg->lk); + + if(eg->path > 0 || eg->ment > 0 || !environ){ + // already initialized or nothing in environent + wunlock(&eg->lk); + return; + } + + for(envp = environ; *envp != nil; envp++) + eg->ment++; + ent = smalloc(sizeof(eg->ent[0])*eg->ment); + eg->ent = ent; + + for(envp = environ; *envp != nil; envp++){ + line = *envp; + n = strlen(line); + + eq = strchr(line, '='); + if(eq == nil) + eq = &line[n]; + e = smalloc(sizeof(Evalue)); + e->name = smalloc(eq-line+1); + strncpy(e->name, line, eq-line); + + + if(eq[0] != '\0') + eq++; + e->len = line+n-eq; + e->value = smalloc(e->len); + memmove(e->value, eq, e->len); + + e->qid.path = ++eg->path; + e->qid.vers = 0; + eg->vers++; + eg->ent[eg->nent++] = e; + } + + wunlock(&eg->lk); +} + +void +envcpy(Egrp *to, Egrp *from) +{ + int i; + Evalue *ne, *e; + + rlock(&from->lk); + to->ment = (from->nent+31)&~31; + to->ent = smalloc(to->ment*sizeof(to->ent[0])); + for(i=0; inent; i++){ + e = from->ent[i]; + ne = smalloc(sizeof(Evalue)); + ne->name = smalloc(strlen(e->name)+1); + strcpy(ne->name, e->name); + if(e->value){ + ne->value = smalloc(e->len); + memmove(ne->value, e->value, e->len); + ne->len = e->len; + } + ne->qid.path = ++to->path; + to->ent[i] = ne; + } + to->nent = from->nent; + runlock(&from->lk); +} + +void +closeegrp(Egrp *eg) +{ + int i; + Evalue *e; + + if(decref(&eg->ref) == 0){ + for(i=0; inent; i++){ + e = eg->ent[i]; + free(e->name); + if(e->value) + free(e->value); + free(e); + } + free(eg->ent); + free(eg); + } +} + +static Egrp* +envgrp(Chan *c) +{ + if(c->aux == nil) + return &unixegrp; + return c->aux; +} + +static int +envwriteable(Chan *c) +{ + return iseve() || c->aux == nil; +} diff -r cdbacd80f61a kern/devtab.c --- a/kern/devtab.c Wed May 27 00:21:41 2020 +0200 +++ b/kern/devtab.c Fri Jun 19 13:22:19 2020 -0400 @@ -18,6 +18,7 @@ extern Dev audiodevtab; extern Dev kbddevtab; extern Dev cmddevtab; +extern Dev envdevtab; Dev *devtab[] = { &rootdevtab, @@ -34,6 +35,7 @@ &audiodevtab, &kbddevtab, &cmddevtab, + &envdevtab, 0 };