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