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