diff options
| author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2025-10-15 19:46:13 +0200 |
|---|---|---|
| committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2025-10-15 19:46:13 +0200 |
| commit | 184526f3bf90e2948b1d09b9da58d66814181f4d (patch) | |
| tree | d39614e3e29fb89594d1dc52ef07805bc754c4c7 /sam/shell.c | |
| parent | fd41e6cc88f98121db5c64a0693e4169962f6c2c (diff) | |
Import sam and samterm sources
Diffstat (limited to 'sam/shell.c')
| -rw-r--r-- | sam/shell.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/sam/shell.c b/sam/shell.c new file mode 100644 index 0000000..db4db97 --- /dev/null +++ b/sam/shell.c @@ -0,0 +1,191 @@ +#include "sam.h" +#include "parse.h" + +extern jmp_buf mainloop; + +char errfile[64]; +String plan9cmd; /* null terminated */ +Buffer plan9buf; +void checkerrs(void); +Buffer cmdbuf; +int cmdbufpos; + +static void +updateenv(File *f) +{ + static int fd = -1; + int n; + char buf[64], *p, *e; + + if(f == nil){ + putenv("%", ""); + putenv("%dot", ""); + return; + } + + p = Strtoc(&f->name); + putenv("%", p); + free(p); + + p = buf; + e = buf+sizeof(buf); + p = seprint(p, e, "%lud", 1+nlcount(f, 0, f->dot.r.p1)); + p = seprint(p+1, e, "%lud", f->dot.r.p1); + p = seprint(p+1, e, "%lud", f->dot.r.p2); + n = p - buf; + if(fd == -1) + if((fd = create("/env/%dot", OWRITE, 0666)) < 0) + fprint(2, "updateenv create: %r\n"); + if(write(fd, buf, n) != n) + fprint(2, "updateenv write: %r\n"); +} + +int +plan9(File *f, int type, String *s, int nest) +{ + long l; + int m; + int pid, fd; + char *retmsg; + int pipe1[2], pipe2[2]; + + if(s->s[0]==0 && plan9cmd.s[0]==0) + error(Enocmd); + else if(s->s[0]) + Strduplstr(&plan9cmd, s); + if(downloaded){ + samerr(errfile); + remove(errfile); + } + if(type!='!' && pipe(pipe1)==-1) + error(Epipe); + if(type=='|' || type=='_') + snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1); + if((pid=fork()) == 0){ + if(downloaded){ /* also put nasty fd's into errfile */ + fd = create(errfile, 1, 0666L); + if(fd < 0) + fd = create("/dev/null", 1, 0666L); + dup(fd, 2); + close(fd); + /* 2 now points at err file */ + if(type == '>') + dup(2, 1); + else if(type=='!'){ + dup(2, 1); + fd = open("/dev/null", 0); + dup(fd, 0); + close(fd); + } + } + if(type != '!') { + if(type == '>') + dup(pipe1[0], 0); + else + dup(pipe1[1], 1); + close(pipe1[0]); + close(pipe1[1]); + } + if(type == '|' || type == '_'){ + if(pipe(pipe2) == -1) + exits("pipe"); + if((pid = fork())==0){ + /* + * It's ok if we get SIGPIPE here + */ + close(pipe2[0]); + io = pipe2[1]; + if(setjmp(mainloop)) + exits("error"); + + char *c; + for(l = 0; l<plan9buf.nc; l+=m){ + m = plan9buf.nc-l; + if(m>BLOCKSIZE-1) + m = BLOCKSIZE-1; + bufread(&plan9buf, l, genbuf, m); + genbuf[m] = 0; + c = Strtoc(tmprstr(genbuf, m+1)); + Write(pipe2[1], c, strlen(c)); + free(c); + } + exits(nil); + } + if(pid==-1){ + fprint(2, "Can't fork?!\n"); + exits("fork"); + } + dup(pipe2[0], 0); + close(pipe2[0]); + close(pipe2[1]); + } + if(type=='<' || type=='^'){ + close(0); /* so it won't read from terminal */ + open("/dev/null", 0); + } + updateenv(f); + execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), nil); + exits("exec"); + } + if(pid == -1) + error(Efork); + if(type=='<' || type=='|'){ + int nulls; + if(downloaded && addr.r.p1 != addr.r.p2) + outTl(Hsnarflen, addr.r.p2-addr.r.p1); + snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0); + logdelete(f, addr.r.p1, addr.r.p2); + close(pipe1[1]); + io = pipe1[0]; + f->tdot.p1 = -1; + f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE); + f->ndot.r.p1 = addr.r.p2; + closeio((Posn)-1); + }else if(type=='>'){ + close(pipe1[0]); + io = pipe1[1]; + bpipeok = 1; + writeio(f); + bpipeok = 0; + closeio((Posn)-1); + }else if(type == '^' || type == '_'){ + int nulls; + close(pipe1[1]); + bufload(&cmdbuf, cmdbufpos, pipe1[0], &nulls); + close(pipe1[0]); + } + retmsg = waitfor(pid); + if(type=='|' || type=='<' || type=='_' || type=='^') + if(retmsg[0]!=0) + warn_s(Wbadstatus, retmsg); + if(downloaded) + checkerrs(); + if(!nest) + dprint("!\n"); + return retmsg[0] ? -1 : 0; +} + +void +checkerrs(void) +{ + char buf[256]; + int f, n, nl; + char *p; + long l; + + if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){ + if((f=open((char *)errfile, 0)) != -1){ + if((n=read(f, buf, sizeof buf-1)) > 0){ + for(nl=0,p=buf; nl<3 && p<&buf[n]; p++) + if(*p=='\n') + nl++; + *p = 0; + dprint("%s", buf); + if(p-buf < l-1) + dprint("(sam: more in %s)\n", errfile); + } + close(f); + } + }else + remove((char *)errfile); +} |