]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/sam/shell.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / sam / shell.c
1 #include "sam.h"
2 #include "parse.h"
3
4 extern  jmp_buf mainloop;
5
6 char    errfile[64];
7 String  plan9cmd;       /* null terminated */
8 Buffer  plan9buf;
9 void    checkerrs(void);
10
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         char *retmsg;
19         int pipe1[2], pipe2[2];
20
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), nil);
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);
118         }
119         retmsg = waitfor(pid);
120         if(type=='|' || type=='<')
121                 if(retmsg[0]!=0)
122                         warn_s(Wbadstatus, retmsg);
123         if(downloaded)
124                 checkerrs();
125         if(!nest)
126                 dprint("!\n");
127         return retmsg[0] ? -1 : 0;
128 }
129
130 void
131 checkerrs(void)
132 {
133         char buf[256];
134         int f, n, nl;
135         char *p;
136         long l;
137
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);
148                         }
149                         close(f);
150                 }
151         }else
152                 remove((char *)errfile);
153 }