#include "sam.h" #include "parse.h" extern jmp_buf mainloop; char errfile[64]; String plan9cmd; /* null terminated */ void checkerrs(void); Buffer plan9buf; static void procplan9pipe(void *arg) { int io, retcode; long l, m; struct { int pipe1[2]; int pipe2[2]; Channel *sync; } *a1; a1 = arg; memset(&plan9buf, 0, sizeof plan9buf); close(a1->pipe2[0]); io = a1->pipe2[1]; sendul(a1->sync, 0); a1 = nil; USED(a1); /* * It's ok if we get SIGPIPE here */ if(retcode=!setjmp(mainloop)){ /* assignment = */ char *c; for(l = 0; lBLOCKSIZE-1) m = BLOCKSIZE-1; bufread(&plan9buf, l, genbuf, m); genbuf[m] = 0; c = Strtoc(tmprstr(genbuf, m+1)); Write(io, c, strlen(c)); free(c); } } threadexits(retcode? "error" : 0); } static void procplan9(void *arg) { int fd; struct { int pipe1[2]; int type; Channel *pidc; } *a; struct { int pipe1[2]; int pipe2[2]; Channel *sync; } a1; a = arg; 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(a->type == '>') dup(2, 1); else if(a->type=='!'){ dup(2, 1); fd = open("/dev/null", 0); dup(fd, 0); close(fd); } } if(a->type != '!') { if(a->type=='<' || a->type=='|') dup(a->pipe1[1], 1); else if(a->type == '>') dup(a->pipe1[0], 0); close(a->pipe1[0]); close(a->pipe1[1]); } if(a->type == '|'){ if(pipe(a1.pipe2) == -1){ sendul(a->pidc, (ulong)-1); threadexits("pipe"); } a1.pipe1[0] = a->pipe1[0]; a1.pipe1[1] = a->pipe1[1]; a1.sync = chancreate(sizeof(ulong), 0); if(proccreate(procplan9pipe, &a1, 8192) == -1){ fprint(2, "Can't fork?!\n"); threadexits("fork"); } recvul(a1.sync); chanfree(a1.sync); dup(a1.pipe2[0], 0); close(a1.pipe2[0]); close(a1.pipe2[1]); } if(a->type=='<'){ close(0); /* so it won't read from terminal */ open("/dev/null", 0); } procexecl(a->pidc, SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0); threadexits("exec"); } int plan9(File *f, int type, String *s, int nest) { int pid, retcode; struct { int pipe1[2]; int type; Channel *pidc; } a; 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(a.pipe1)==-1) error(Epipe); if((a.pidc = chancreate(sizeof(ulong), 0)) == nil) error(Epipe); /* not quite right */ if(type=='|') snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1); a.type = type; if(proccreate(procplan9, &a, 8192) == -1){ chanfree(a.pidc); error(Efork); } pid = recvul(a.pidc); chanfree(a.pidc); 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(a.pipe1[1]); io = a.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(a.pipe1[0]); io = a.pipe1[1]; bpipeok = 1; writeio(f); bpipeok = 0; closeio((Posn)-1); } retcode = waitfor(pid); if(type=='|' || type=='<') if(retcode!=0) warn(Wbadstatus); if(downloaded) checkerrs(); if(!nest) dprint("!\n"); return retcode; } 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); }