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