Blob


1 #include "sam.h"
2 #include "parse.h"
4 extern jmp_buf mainloop;
6 char errfile[64];
7 String plan9cmd; /* null terminated */
8 Buffer plan9buf;
9 void checkerrs(void);
11 int
12 plan9(File *f, int type, String *s, int nest)
13 {
14 long l;
15 int m;
16 int volatile pid;
17 int fd;
18 int retcode;
19 int pipe1[2], pipe2[2];
21 if(s->s[0]==0 && plan9cmd.s[0]==0)
22 error(Enocmd);
23 else if(s->s[0])
24 Strduplstr(&plan9cmd, s);
25 if(downloaded){
26 samerr(errfile);
27 remove(errfile);
28 }
29 if(type!='!' && pipe(pipe1)==-1)
30 error(Epipe);
31 if(type=='|')
32 snarf(f, addr.r.p1, addr.r.p2, &plan9buf, 1);
33 if((pid=fork()) == 0){
34 if(downloaded){ /* also put nasty fd's into errfile */
35 fd = create(errfile, 1, 0666L);
36 if(fd < 0)
37 fd = create("/dev/null", 1, 0666L);
38 dup(fd, 2);
39 close(fd);
40 /* 2 now points at err file */
41 if(type == '>')
42 dup(2, 1);
43 else if(type=='!'){
44 dup(2, 1);
45 fd = open("/dev/null", 0);
46 dup(fd, 0);
47 close(fd);
48 }
49 }
50 if(type != '!') {
51 if(type=='<' || type=='|')
52 dup(pipe1[1], 1);
53 else if(type == '>')
54 dup(pipe1[0], 0);
55 close(pipe1[0]);
56 close(pipe1[1]);
57 }
58 if(type == '|'){
59 if(pipe(pipe2) == -1)
60 exits("pipe");
61 if((pid = fork())==0){
62 /*
63 * It's ok if we get SIGPIPE here
64 */
65 close(pipe2[0]);
66 io = pipe2[1];
67 if(retcode=!setjmp(mainloop)){ /* assignment = */
68 char *c;
69 for(l = 0; l<plan9buf.nc; l+=m){
70 m = plan9buf.nc-l;
71 if(m>BLOCKSIZE-1)
72 m = BLOCKSIZE-1;
73 bufread(&plan9buf, l, genbuf, m);
74 genbuf[m] = 0;
75 c = Strtoc(tmprstr(genbuf, m+1));
76 Write(pipe2[1], c, strlen(c));
77 free(c);
78 }
79 }
80 exits(retcode? "error" : 0);
81 }
82 if(pid==-1){
83 fprint(2, "Can't fork?!\n");
84 exits("fork");
85 }
86 dup(pipe2[0], 0);
87 close(pipe2[0]);
88 close(pipe2[1]);
89 }
90 if(type=='<'){
91 close(0); /* so it won't read from terminal */
92 open("/dev/null", 0);
93 }
94 execl(SHPATH, SH, "-c", Strtoc(&plan9cmd), (char *)0);
95 exits("exec");
96 }
97 if(pid == -1)
98 error(Efork);
99 if(type=='<' || type=='|'){
100 int nulls;
101 if(downloaded && addr.r.p1 != addr.r.p2)
102 outTl(Hsnarflen, addr.r.p2-addr.r.p1);
103 snarf(f, addr.r.p1, addr.r.p2, &snarfbuf, 0);
104 logdelete(f, addr.r.p1, addr.r.p2);
105 close(pipe1[1]);
106 io = pipe1[0];
107 f->tdot.p1 = -1;
108 f->ndot.r.p2 = addr.r.p2+readio(f, &nulls, 0, FALSE);
109 f->ndot.r.p1 = addr.r.p2;
110 closeio((Posn)-1);
111 }else if(type=='>'){
112 close(pipe1[0]);
113 io = pipe1[1];
114 bpipeok = 1;
115 writeio(f);
116 bpipeok = 0;
117 closeio((Posn)-1);
119 retcode = waitfor(pid);
120 if(type=='|' || type=='<')
121 if(retcode!=0)
122 warn(Wbadstatus);
123 if(downloaded)
124 checkerrs();
125 if(!nest)
126 dprint("!\n");
127 return retcode;
130 void
131 checkerrs(void)
133 char buf[256];
134 int f, n, nl;
135 char *p;
136 long l;
138 if(statfile(errfile, 0, 0, 0, &l, 0) > 0 && l != 0){
139 if((f=open((char *)errfile, 0)) != -1){
140 if((n=read(f, buf, sizeof buf-1)) > 0){
141 for(nl=0,p=buf; nl<3 && p<&buf[n]; p++)
142 if(*p=='\n')
143 nl++;
144 *p = 0;
145 dprint("%s", buf);
146 if(p-buf < l-1)
147 dprint("(sam: more in %s)\n", errfile);
149 close(f);
151 }else
152 remove((char *)errfile);