#include "sam.h" #include "parse.h" #ifdef SUN /* a hack to get around redef of ushort in sys/types.h . this depends on non-use of ushort in this file */ #define ushort USHORT #endif #include <sys/types.h> #include <sys/stat.h> #include <signal.h> #include <setjmp.h> extern jmp_buf mainloop; uchar errfile[64]; String unixcmd; /* null terminated */ Unix(f, type, s, nest) register File *f; register type; register String *s; { register pid, rpid; int (*onbpipe)(); int retcode; int pipe1[2], pipe2[2]; if(s->s[0]==0 && unixcmd.s[0]==0) error(Enocmd); else if(s->s[0]) strdupstr(&unixcmd, s); if(downloaded){ strcpy(errfile, (uchar *)home); strcat((char *)errfile, "/sam.err"); }else strcpy(errfile, (uchar *)"/dev/tty"); if(type!='!' && pipe(pipe1)==-1) error(Epipe); unlink((char *)errfile); if((pid=fork()) == 0){ if(downloaded){ /* also put nasty fd's into errfile */ int fd=creat((char *)errfile, 0666); if(fd<0) fd=creat("/dev/null", 0666); #ifdef V8 close(3); /* v8 /dev/tty */ open("/dev/null", 2); #endif close(2); dup(fd); close(fd); /* 2 now points at err file */ close(1); if(type == '>') dup(2); else if(type=='!'){ dup(2); fd=open("/dev/null", 0); close(0); dup(fd); close(fd); } } if(type!='!') { if(type=='<' || type=='|'){ close(1); dup(pipe1[1]); }else if(type == '>'){ close(0); dup(pipe1[0]); } close(pipe1[0]); close(pipe1[1]); } if(type=='|'){ if(pipe(pipe2)==-1) exit(1); if((pid=fork())==0){ /* * It's ok if we get SIGPIPE here */ close(pipe2[0]); io=pipe2[1]; if(retcode=!setjmp(mainloop)) /* assignment = */ (void)writeio(f); exit(retcode); } if(pid==-1){ fprint(2, "Can't fork?!\n"); exit(1); } close(0); dup(pipe2[0]); close(pipe2[0]); close(pipe2[1]); } Dclosefd(); if(type=='<'){ close(0); /* so it won't read from terminal */ open("/dev/null", 0); } execlp("sh", "sh", "-c", unixcmd.s, (char *)0); exit(-1); } if(pid==-1) error(Efork); if(type=='<' || type=='|'){ if(downloaded) outTl(Hsnarflen, addr.r.p2-addr.r.p1); snarf(f, addr.r.p1, addr.r.p2); Fdelete(f, addr.r.p1, addr.r.p2); close(pipe1[1]); io=pipe1[0]; f->dot.r.p2=addr.r.p2+readio(f, (int *)0, 0); f->dot.r.p1=addr.r.p2; closeio((Posn)-1); }else if(type=='>'){ onbpipe = signal(SIGPIPE, SIG_IGN); close(pipe1[0]); io=pipe1[1]; (void)writeio(f); closeio((Posn)-1); signal(SIGPIPE, onbpipe); } do; while ((rpid = wait(&retcode)) != pid && rpid != -1); retcode=(retcode>>8)&0377; if(type=='|' || type=='<') if(retcode!=0) warn(Wbadstatus); checkerrs(); if(!nest) dprint("!\n"); } checkerrs(){ struct stat statb; char buf[256]; register f; register n, nl; register char *p; if(stat((char *)errfile, &statb)==0 && statb.st_size){ 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 < statb.st_size-1) dprint("(sam: more in %s)\n", errfile); } close(f); } }else unlink((char *)errfile); }