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