Blame


1 4ee543e5 2005-03-18 devnull #include <u.h>
2 4ee543e5 2005-03-18 devnull #include <signal.h>
3 7ce3f20d 2005-07-13 devnull #if defined(PLAN9PORT) && defined(__sun__)
4 7ce3f20d 2005-07-13 devnull # define BSD_COMP /* sigh. for TIOCNOTTY */
5 7ce3f20d 2005-07-13 devnull #endif
6 0e4068e8 2005-07-26 devnull #include <sys/ioctl.h>
7 f08fdedc 2003-11-23 devnull #include "rc.h"
8 f08fdedc 2003-11-23 devnull #include "getflags.h"
9 f08fdedc 2003-11-23 devnull #include "exec.h"
10 f08fdedc 2003-11-23 devnull #include "io.h"
11 f08fdedc 2003-11-23 devnull #include "fns.h"
12 f08fdedc 2003-11-23 devnull /*
13 f08fdedc 2003-11-23 devnull * Start executing the given code at the given pc with the given redirection
14 f08fdedc 2003-11-23 devnull */
15 f08fdedc 2003-11-23 devnull char *argv0="rc";
16 f08fdedc 2003-11-23 devnull void start(code *c, int pc, var *local)
17 f08fdedc 2003-11-23 devnull {
18 f08fdedc 2003-11-23 devnull struct thread *p=new(struct thread);
19 f08fdedc 2003-11-23 devnull p->code=codecopy(c);
20 f08fdedc 2003-11-23 devnull p->pc=pc;
21 f08fdedc 2003-11-23 devnull p->argv=0;
22 f08fdedc 2003-11-23 devnull p->redir=p->startredir=runq?runq->redir:0;
23 f08fdedc 2003-11-23 devnull p->local=local;
24 f08fdedc 2003-11-23 devnull p->cmdfile=0;
25 f08fdedc 2003-11-23 devnull p->cmdfd=0;
26 f08fdedc 2003-11-23 devnull p->eof=0;
27 f08fdedc 2003-11-23 devnull p->iflag=0;
28 f08fdedc 2003-11-23 devnull p->lineno=1;
29 26a5fd57 2005-02-11 devnull p->pid=-1;
30 f08fdedc 2003-11-23 devnull p->ret=runq;
31 f08fdedc 2003-11-23 devnull runq=p;
32 f08fdedc 2003-11-23 devnull }
33 f08fdedc 2003-11-23 devnull word *newword(char *wd, word *next)
34 f08fdedc 2003-11-23 devnull {
35 f08fdedc 2003-11-23 devnull word *p=new(word);
36 f08fdedc 2003-11-23 devnull p->word=strdup(wd);
37 f08fdedc 2003-11-23 devnull p->next=next;
38 f08fdedc 2003-11-23 devnull return p;
39 f08fdedc 2003-11-23 devnull }
40 f08fdedc 2003-11-23 devnull void pushword(char *wd)
41 f08fdedc 2003-11-23 devnull {
42 f08fdedc 2003-11-23 devnull if(runq->argv==0) panic("pushword but no argv!", 0);
43 f08fdedc 2003-11-23 devnull runq->argv->words=newword(wd, runq->argv->words);
44 f08fdedc 2003-11-23 devnull }
45 f08fdedc 2003-11-23 devnull void popword(void){
46 f08fdedc 2003-11-23 devnull word *p;
47 f08fdedc 2003-11-23 devnull if(runq->argv==0) panic("popword but no argv!", 0);
48 f08fdedc 2003-11-23 devnull p=runq->argv->words;
49 f08fdedc 2003-11-23 devnull if(p==0) panic("popword but no word!", 0);
50 f08fdedc 2003-11-23 devnull runq->argv->words=p->next;
51 f08fdedc 2003-11-23 devnull efree(p->word);
52 f08fdedc 2003-11-23 devnull efree((char *)p);
53 f08fdedc 2003-11-23 devnull }
54 f08fdedc 2003-11-23 devnull void freelist(word *w)
55 f08fdedc 2003-11-23 devnull {
56 f08fdedc 2003-11-23 devnull word *nw;
57 f08fdedc 2003-11-23 devnull while(w){
58 f08fdedc 2003-11-23 devnull nw=w->next;
59 f08fdedc 2003-11-23 devnull efree(w->word);
60 f08fdedc 2003-11-23 devnull efree((char *)w);
61 f08fdedc 2003-11-23 devnull w=nw;
62 f08fdedc 2003-11-23 devnull }
63 f08fdedc 2003-11-23 devnull }
64 f08fdedc 2003-11-23 devnull void pushlist(void){
65 f08fdedc 2003-11-23 devnull list *p=new(list);
66 f08fdedc 2003-11-23 devnull p->next=runq->argv;
67 f08fdedc 2003-11-23 devnull p->words=0;
68 f08fdedc 2003-11-23 devnull runq->argv=p;
69 f08fdedc 2003-11-23 devnull }
70 f08fdedc 2003-11-23 devnull void poplist(void){
71 f08fdedc 2003-11-23 devnull list *p=runq->argv;
72 f08fdedc 2003-11-23 devnull if(p==0) panic("poplist but no argv", 0);
73 f08fdedc 2003-11-23 devnull freelist(p->words);
74 f08fdedc 2003-11-23 devnull runq->argv=p->next;
75 f08fdedc 2003-11-23 devnull efree((char *)p);
76 f08fdedc 2003-11-23 devnull }
77 f08fdedc 2003-11-23 devnull int count(word *w)
78 f08fdedc 2003-11-23 devnull {
79 f08fdedc 2003-11-23 devnull int n;
80 f08fdedc 2003-11-23 devnull for(n=0;w;n++) w=w->next;
81 f08fdedc 2003-11-23 devnull return n;
82 f08fdedc 2003-11-23 devnull }
83 f08fdedc 2003-11-23 devnull void pushredir(int type, int from, int to){
84 f08fdedc 2003-11-23 devnull redir * rp=new(redir);
85 f08fdedc 2003-11-23 devnull rp->type=type;
86 f08fdedc 2003-11-23 devnull rp->from=from;
87 f08fdedc 2003-11-23 devnull rp->to=to;
88 f08fdedc 2003-11-23 devnull rp->next=runq->redir;
89 f08fdedc 2003-11-23 devnull runq->redir=rp;
90 f08fdedc 2003-11-23 devnull }
91 f08fdedc 2003-11-23 devnull var *newvar(char *name, var *next)
92 f08fdedc 2003-11-23 devnull {
93 f08fdedc 2003-11-23 devnull var *v=new(var);
94 f08fdedc 2003-11-23 devnull v->name=name;
95 f08fdedc 2003-11-23 devnull v->val=0;
96 f08fdedc 2003-11-23 devnull v->fn=0;
97 f08fdedc 2003-11-23 devnull v->changed=0;
98 f08fdedc 2003-11-23 devnull v->fnchanged=0;
99 f08fdedc 2003-11-23 devnull v->next=next;
100 c8b6342d 2005-01-13 devnull v->changefn = 0;
101 f08fdedc 2003-11-23 devnull return v;
102 f08fdedc 2003-11-23 devnull }
103 f08fdedc 2003-11-23 devnull /*
104 f08fdedc 2003-11-23 devnull * get command line flags, initialize keywords & traps.
105 f08fdedc 2003-11-23 devnull * get values from environment.
106 f08fdedc 2003-11-23 devnull * set $pid, $cflag, $*
107 f08fdedc 2003-11-23 devnull * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*)
108 f08fdedc 2003-11-23 devnull * start interpreting code
109 f08fdedc 2003-11-23 devnull */
110 f08fdedc 2003-11-23 devnull int
111 f08fdedc 2003-11-23 devnull main(int argc, char *argv[])
112 f08fdedc 2003-11-23 devnull {
113 f08fdedc 2003-11-23 devnull code bootstrap[32];
114 f08fdedc 2003-11-23 devnull char num[12], *rcmain;
115 f08fdedc 2003-11-23 devnull int i;
116 e3ffbf3b 2005-05-19 devnull
117 e3ffbf3b 2005-05-19 devnull /* needed for rcmain later */
118 0e4068e8 2005-07-26 devnull putenv("PLAN9", unsharp("#9"));
119 f08fdedc 2003-11-23 devnull
120 f08fdedc 2003-11-23 devnull argc=getflags(argc, argv, "srdiIlxepvVc:1m:1[command]", 1);
121 f08fdedc 2003-11-23 devnull if(argc==-1) usage("[file [arg ...]]");
122 f08fdedc 2003-11-23 devnull if(argv[0][0]=='-') flag['l']=flagset;
123 f08fdedc 2003-11-23 devnull if(flag['I']) flag['i'] = 0;
124 f08fdedc 2003-11-23 devnull else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
125 f08fdedc 2003-11-23 devnull rcmain=flag['m']?flag['m'][0]:Rcmain();
126 f08fdedc 2003-11-23 devnull err=openfd(2);
127 f08fdedc 2003-11-23 devnull kinit();
128 f08fdedc 2003-11-23 devnull Trapinit();
129 f08fdedc 2003-11-23 devnull Vinit();
130 f08fdedc 2003-11-23 devnull itoa(num, mypid=getpid());
131 a9eaaa03 2005-01-12 devnull pathinit();
132 f08fdedc 2003-11-23 devnull setvar("pid", newword(num, (word *)0));
133 f08fdedc 2003-11-23 devnull setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
134 f08fdedc 2003-11-23 devnull :(word *)0);
135 f08fdedc 2003-11-23 devnull setvar("rcname", newword(argv[0], (word *)0));
136 f08fdedc 2003-11-23 devnull i=0;
137 f08fdedc 2003-11-23 devnull bootstrap[i++].i=1;
138 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xmark;
139 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xword;
140 f08fdedc 2003-11-23 devnull bootstrap[i++].s="*";
141 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xassign;
142 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xmark;
143 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xmark;
144 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xword;
145 f08fdedc 2003-11-23 devnull bootstrap[i++].s="*";
146 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xdol;
147 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xword;
148 f08fdedc 2003-11-23 devnull bootstrap[i++].s=rcmain;
149 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xword;
150 f08fdedc 2003-11-23 devnull bootstrap[i++].s=".";
151 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xsimple;
152 f08fdedc 2003-11-23 devnull bootstrap[i++].f=Xexit;
153 f08fdedc 2003-11-23 devnull bootstrap[i].i=0;
154 f08fdedc 2003-11-23 devnull start(bootstrap, 1, (var *)0);
155 f08fdedc 2003-11-23 devnull /* prime bootstrap argv */
156 f08fdedc 2003-11-23 devnull pushlist();
157 f08fdedc 2003-11-23 devnull argv0 = strdup(argv[0]);
158 f08fdedc 2003-11-23 devnull for(i=argc-1;i!=0;--i) pushword(argv[i]);
159 f08fdedc 2003-11-23 devnull for(;;){
160 f08fdedc 2003-11-23 devnull if(flag['r']) pfnc(err, runq);
161 f08fdedc 2003-11-23 devnull runq->pc++;
162 f08fdedc 2003-11-23 devnull (*runq->code[runq->pc-1].f)();
163 f08fdedc 2003-11-23 devnull if(ntrap) dotrap();
164 f08fdedc 2003-11-23 devnull }
165 f08fdedc 2003-11-23 devnull }
166 f08fdedc 2003-11-23 devnull /*
167 f08fdedc 2003-11-23 devnull * Opcode routines
168 f08fdedc 2003-11-23 devnull * Arguments on stack (...)
169 f08fdedc 2003-11-23 devnull * Arguments in line [...]
170 f08fdedc 2003-11-23 devnull * Code in line with jump around {...}
171 f08fdedc 2003-11-23 devnull *
172 f08fdedc 2003-11-23 devnull * Xappend(file)[fd] open file to append
173 f08fdedc 2003-11-23 devnull * Xassign(name, val) assign val to name
174 f08fdedc 2003-11-23 devnull * Xasync{... Xexit} make thread for {}, no wait
175 f08fdedc 2003-11-23 devnull * Xbackq{... Xreturn} make thread for {}, push stdout
176 f08fdedc 2003-11-23 devnull * Xbang complement condition
177 f08fdedc 2003-11-23 devnull * Xcase(pat, value){...} exec code on match, leave (value) on
178 f08fdedc 2003-11-23 devnull * stack
179 f08fdedc 2003-11-23 devnull * Xclose[i] close file descriptor
180 f08fdedc 2003-11-23 devnull * Xconc(left, right) concatenate, push results
181 f08fdedc 2003-11-23 devnull * Xcount(name) push var count
182 f08fdedc 2003-11-23 devnull * Xdelfn(name) delete function definition
183 f08fdedc 2003-11-23 devnull * Xdeltraps(names) delete named traps
184 f08fdedc 2003-11-23 devnull * Xdol(name) get variable value
185 f08fdedc 2003-11-23 devnull * Xqdol(name) concatenate variable components
186 f08fdedc 2003-11-23 devnull * Xdup[i j] dup file descriptor
187 f08fdedc 2003-11-23 devnull * Xexit rc exits with status
188 f08fdedc 2003-11-23 devnull * Xfalse{...} execute {} if false
189 f08fdedc 2003-11-23 devnull * Xfn(name){... Xreturn} define function
190 f08fdedc 2003-11-23 devnull * Xfor(var, list){... Xreturn} for loop
191 f08fdedc 2003-11-23 devnull * Xjump[addr] goto
192 f08fdedc 2003-11-23 devnull * Xlocal(name, val) create local variable, assign value
193 f08fdedc 2003-11-23 devnull * Xmark mark stack
194 f08fdedc 2003-11-23 devnull * Xmatch(pat, str) match pattern, set status
195 f08fdedc 2003-11-23 devnull * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads,
196 f08fdedc 2003-11-23 devnull * wait for both
197 f08fdedc 2003-11-23 devnull * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
198 f08fdedc 2003-11-23 devnull * depending on type), push /dev/fd/??
199 f08fdedc 2003-11-23 devnull * Xpopm(value) pop value from stack
200 f08fdedc 2003-11-23 devnull * Xread(file)[fd] open file to read
201 f08fdedc 2003-11-23 devnull * Xsettraps(names){... Xreturn} define trap functions
202 f08fdedc 2003-11-23 devnull * Xshowtraps print trap list
203 f08fdedc 2003-11-23 devnull * Xsimple(args) run command and wait
204 f08fdedc 2003-11-23 devnull * Xreturn kill thread
205 f08fdedc 2003-11-23 devnull * Xsubshell{... Xexit} execute {} in a subshell and wait
206 f08fdedc 2003-11-23 devnull * Xtrue{...} execute {} if true
207 f08fdedc 2003-11-23 devnull * Xunlocal delete local variable
208 f08fdedc 2003-11-23 devnull * Xword[string] push string
209 f08fdedc 2003-11-23 devnull * Xwrite(file)[fd] open file to write
210 f08fdedc 2003-11-23 devnull */
211 f08fdedc 2003-11-23 devnull void Xappend(void){
212 f08fdedc 2003-11-23 devnull char *file;
213 f08fdedc 2003-11-23 devnull int f;
214 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
215 f08fdedc 2003-11-23 devnull default: Xerror1(">> requires singleton"); return;
216 f08fdedc 2003-11-23 devnull case 0: Xerror1(">> requires file"); return;
217 f08fdedc 2003-11-23 devnull case 1: break;
218 f08fdedc 2003-11-23 devnull }
219 f08fdedc 2003-11-23 devnull file=runq->argv->words->word;
220 f08fdedc 2003-11-23 devnull if((f=open(file, 1))<0 && (f=Creat(file))<0){
221 f08fdedc 2003-11-23 devnull pfmt(err, "%s: ", file);
222 f08fdedc 2003-11-23 devnull Xerror("can't open");
223 f08fdedc 2003-11-23 devnull return;
224 f08fdedc 2003-11-23 devnull }
225 f08fdedc 2003-11-23 devnull Seek(f, 0L, 2);
226 f08fdedc 2003-11-23 devnull pushredir(ROPEN, f, runq->code[runq->pc].i);
227 f08fdedc 2003-11-23 devnull runq->pc++;
228 f08fdedc 2003-11-23 devnull poplist();
229 f08fdedc 2003-11-23 devnull }
230 f08fdedc 2003-11-23 devnull void Xasync(void){
231 f08fdedc 2003-11-23 devnull int null=open("/dev/null", 0);
232 4ee543e5 2005-03-18 devnull int tty;
233 f08fdedc 2003-11-23 devnull int pid;
234 f08fdedc 2003-11-23 devnull char npid[10];
235 f08fdedc 2003-11-23 devnull if(null<0){
236 f08fdedc 2003-11-23 devnull Xerror("Can't open /dev/null\n");
237 f08fdedc 2003-11-23 devnull return;
238 f08fdedc 2003-11-23 devnull }
239 f08fdedc 2003-11-23 devnull switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
240 f08fdedc 2003-11-23 devnull case -1:
241 f08fdedc 2003-11-23 devnull close(null);
242 f08fdedc 2003-11-23 devnull Xerror("try again");
243 f08fdedc 2003-11-23 devnull break;
244 f08fdedc 2003-11-23 devnull case 0:
245 4ee543e5 2005-03-18 devnull /*
246 4ee543e5 2005-03-18 devnull * I don't know what the right thing to do here is,
247 4ee543e5 2005-03-18 devnull * so this is all experimentally determined.
248 4ee543e5 2005-03-18 devnull * If we just dup /dev/null onto 0, then running
249 4ee543e5 2005-03-18 devnull * ssh foo & will reopen /dev/tty, try to read a password,
250 4ee543e5 2005-03-18 devnull * get a signal, and repeat, in a tight loop, forever.
251 4ee543e5 2005-03-18 devnull * Arguably this is a bug in ssh (it behaves the same
252 4ee543e5 2005-03-18 devnull * way under bash as under rc) but I'm fixing it here
253 4ee543e5 2005-03-18 devnull * anyway. If we dissociate the process from the tty,
254 4ee543e5 2005-03-18 devnull * then it won't be able to open /dev/tty ever again.
255 4ee543e5 2005-03-18 devnull * The SIG_IGN on SIGTTOU makes writing the tty
256 4ee543e5 2005-03-18 devnull * (via fd 1 or 2, for example) succeed even though
257 4ee543e5 2005-03-18 devnull * our pgrp is not the terminal's controlling pgrp.
258 4ee543e5 2005-03-18 devnull */
259 4ee543e5 2005-03-18 devnull if((tty=open("/dev/tty", OREAD)) >= 0){
260 4ee543e5 2005-03-18 devnull /*
261 4ee543e5 2005-03-18 devnull * Should make reads of tty fail, writes succeed.
262 4ee543e5 2005-03-18 devnull */
263 4ee543e5 2005-03-18 devnull signal(SIGTTIN, SIG_IGN);
264 4ee543e5 2005-03-18 devnull signal(SIGTTOU, SIG_IGN);
265 4ee543e5 2005-03-18 devnull ioctl(tty, TIOCNOTTY);
266 4ee543e5 2005-03-18 devnull close(tty);
267 4ee543e5 2005-03-18 devnull }
268 4ee543e5 2005-03-18 devnull if(isatty(0))
269 4ee543e5 2005-03-18 devnull pushredir(ROPEN, null, 0);
270 4ee543e5 2005-03-18 devnull else
271 4ee543e5 2005-03-18 devnull close(null);
272 f08fdedc 2003-11-23 devnull start(runq->code, runq->pc+1, runq->local);
273 f08fdedc 2003-11-23 devnull runq->ret=0;
274 f08fdedc 2003-11-23 devnull break;
275 f08fdedc 2003-11-23 devnull default:
276 f08fdedc 2003-11-23 devnull close(null);
277 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
278 f08fdedc 2003-11-23 devnull itoa(npid, pid);
279 f08fdedc 2003-11-23 devnull setvar("apid", newword(npid, (word *)0));
280 f08fdedc 2003-11-23 devnull break;
281 f08fdedc 2003-11-23 devnull }
282 f08fdedc 2003-11-23 devnull }
283 f08fdedc 2003-11-23 devnull void Xsettrue(void){
284 f08fdedc 2003-11-23 devnull setstatus("");
285 f08fdedc 2003-11-23 devnull }
286 f08fdedc 2003-11-23 devnull void Xbang(void){
287 f08fdedc 2003-11-23 devnull setstatus(truestatus()?"false":"");
288 f08fdedc 2003-11-23 devnull }
289 f08fdedc 2003-11-23 devnull void Xclose(void){
290 f08fdedc 2003-11-23 devnull pushredir(RCLOSE, runq->code[runq->pc].i, 0);
291 f08fdedc 2003-11-23 devnull runq->pc++;
292 f08fdedc 2003-11-23 devnull }
293 f08fdedc 2003-11-23 devnull void Xdup(void){
294 f08fdedc 2003-11-23 devnull pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
295 f08fdedc 2003-11-23 devnull runq->pc+=2;
296 f08fdedc 2003-11-23 devnull }
297 f08fdedc 2003-11-23 devnull void Xeflag(void){
298 f08fdedc 2003-11-23 devnull if(eflagok && !truestatus()) Xexit();
299 f08fdedc 2003-11-23 devnull }
300 f08fdedc 2003-11-23 devnull void Xexit(void){
301 f08fdedc 2003-11-23 devnull struct var *trapreq;
302 f08fdedc 2003-11-23 devnull struct word *starval;
303 f08fdedc 2003-11-23 devnull static int beenhere=0;
304 f08fdedc 2003-11-23 devnull if(getpid()==mypid && !beenhere){
305 f08fdedc 2003-11-23 devnull trapreq=vlook("sigexit");
306 f08fdedc 2003-11-23 devnull if(trapreq->fn){
307 f08fdedc 2003-11-23 devnull beenhere=1;
308 f08fdedc 2003-11-23 devnull --runq->pc;
309 f08fdedc 2003-11-23 devnull starval=vlook("*")->val;
310 f08fdedc 2003-11-23 devnull start(trapreq->fn, trapreq->pc, (struct var *)0);
311 f08fdedc 2003-11-23 devnull runq->local=newvar(strdup("*"), runq->local);
312 f08fdedc 2003-11-23 devnull runq->local->val=copywords(starval, (struct word *)0);
313 f08fdedc 2003-11-23 devnull runq->local->changed=1;
314 f08fdedc 2003-11-23 devnull runq->redir=runq->startredir=0;
315 f08fdedc 2003-11-23 devnull return;
316 f08fdedc 2003-11-23 devnull }
317 f08fdedc 2003-11-23 devnull }
318 f08fdedc 2003-11-23 devnull Exit(getstatus());
319 f08fdedc 2003-11-23 devnull }
320 f08fdedc 2003-11-23 devnull void Xfalse(void){
321 f08fdedc 2003-11-23 devnull if(truestatus()) runq->pc=runq->code[runq->pc].i;
322 f08fdedc 2003-11-23 devnull else runq->pc++;
323 f08fdedc 2003-11-23 devnull }
324 f08fdedc 2003-11-23 devnull int ifnot; /* dynamic if not flag */
325 f08fdedc 2003-11-23 devnull void Xifnot(void){
326 f08fdedc 2003-11-23 devnull if(ifnot)
327 f08fdedc 2003-11-23 devnull runq->pc++;
328 f08fdedc 2003-11-23 devnull else
329 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
330 f08fdedc 2003-11-23 devnull }
331 f08fdedc 2003-11-23 devnull void Xjump(void){
332 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
333 f08fdedc 2003-11-23 devnull }
334 f08fdedc 2003-11-23 devnull void Xmark(void){
335 f08fdedc 2003-11-23 devnull pushlist();
336 f08fdedc 2003-11-23 devnull }
337 f08fdedc 2003-11-23 devnull void Xpopm(void){
338 f08fdedc 2003-11-23 devnull poplist();
339 f08fdedc 2003-11-23 devnull }
340 f08fdedc 2003-11-23 devnull void Xread(void){
341 f08fdedc 2003-11-23 devnull char *file;
342 f08fdedc 2003-11-23 devnull int f;
343 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
344 f08fdedc 2003-11-23 devnull default: Xerror1("< requires singleton\n"); return;
345 f08fdedc 2003-11-23 devnull case 0: Xerror1("< requires file\n"); return;
346 f08fdedc 2003-11-23 devnull case 1: break;
347 f08fdedc 2003-11-23 devnull }
348 f08fdedc 2003-11-23 devnull file=runq->argv->words->word;
349 f08fdedc 2003-11-23 devnull if((f=open(file, 0))<0){
350 f08fdedc 2003-11-23 devnull pfmt(err, "%s: ", file);
351 f08fdedc 2003-11-23 devnull Xerror("can't open");
352 f08fdedc 2003-11-23 devnull return;
353 f08fdedc 2003-11-23 devnull }
354 f08fdedc 2003-11-23 devnull pushredir(ROPEN, f, runq->code[runq->pc].i);
355 f08fdedc 2003-11-23 devnull runq->pc++;
356 f08fdedc 2003-11-23 devnull poplist();
357 f08fdedc 2003-11-23 devnull }
358 f08fdedc 2003-11-23 devnull void turfredir(void){
359 f08fdedc 2003-11-23 devnull while(runq->redir!=runq->startredir)
360 f08fdedc 2003-11-23 devnull Xpopredir();
361 f08fdedc 2003-11-23 devnull }
362 f08fdedc 2003-11-23 devnull void Xpopredir(void){
363 f08fdedc 2003-11-23 devnull struct redir *rp=runq->redir;
364 f08fdedc 2003-11-23 devnull if(rp==0) panic("turfredir null!", 0);
365 f08fdedc 2003-11-23 devnull runq->redir=rp->next;
366 f08fdedc 2003-11-23 devnull if(rp->type==ROPEN) close(rp->from);
367 f08fdedc 2003-11-23 devnull efree((char *)rp);
368 f08fdedc 2003-11-23 devnull }
369 f08fdedc 2003-11-23 devnull void Xreturn(void){
370 f08fdedc 2003-11-23 devnull struct thread *p=runq;
371 f08fdedc 2003-11-23 devnull turfredir();
372 f08fdedc 2003-11-23 devnull while(p->argv) poplist();
373 f08fdedc 2003-11-23 devnull codefree(p->code);
374 f08fdedc 2003-11-23 devnull runq=p->ret;
375 f08fdedc 2003-11-23 devnull efree((char *)p);
376 f08fdedc 2003-11-23 devnull if(runq==0) Exit(getstatus());
377 f08fdedc 2003-11-23 devnull }
378 f08fdedc 2003-11-23 devnull void Xtrue(void){
379 f08fdedc 2003-11-23 devnull if(truestatus()) runq->pc++;
380 f08fdedc 2003-11-23 devnull else runq->pc=runq->code[runq->pc].i;
381 f08fdedc 2003-11-23 devnull }
382 f08fdedc 2003-11-23 devnull void Xif(void){
383 f08fdedc 2003-11-23 devnull ifnot=1;
384 f08fdedc 2003-11-23 devnull if(truestatus()) runq->pc++;
385 f08fdedc 2003-11-23 devnull else runq->pc=runq->code[runq->pc].i;
386 f08fdedc 2003-11-23 devnull }
387 f08fdedc 2003-11-23 devnull void Xwastrue(void){
388 f08fdedc 2003-11-23 devnull ifnot=0;
389 f08fdedc 2003-11-23 devnull }
390 f08fdedc 2003-11-23 devnull void Xword(void){
391 f08fdedc 2003-11-23 devnull pushword(runq->code[runq->pc++].s);
392 f08fdedc 2003-11-23 devnull }
393 f08fdedc 2003-11-23 devnull void Xwrite(void){
394 f08fdedc 2003-11-23 devnull char *file;
395 f08fdedc 2003-11-23 devnull int f;
396 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
397 f08fdedc 2003-11-23 devnull default: Xerror1("> requires singleton\n"); return;
398 f08fdedc 2003-11-23 devnull case 0: Xerror1("> requires file\n"); return;
399 f08fdedc 2003-11-23 devnull case 1: break;
400 f08fdedc 2003-11-23 devnull }
401 f08fdedc 2003-11-23 devnull file=runq->argv->words->word;
402 f08fdedc 2003-11-23 devnull if((f=Creat(file))<0){
403 f08fdedc 2003-11-23 devnull pfmt(err, "%s: ", file);
404 f08fdedc 2003-11-23 devnull Xerror("can't open");
405 f08fdedc 2003-11-23 devnull return;
406 f08fdedc 2003-11-23 devnull }
407 f08fdedc 2003-11-23 devnull pushredir(ROPEN, f, runq->code[runq->pc].i);
408 f08fdedc 2003-11-23 devnull runq->pc++;
409 f08fdedc 2003-11-23 devnull poplist();
410 f08fdedc 2003-11-23 devnull }
411 a9eaaa03 2005-01-12 devnull char *_list2str(word *words, int c){
412 f08fdedc 2003-11-23 devnull char *value, *s, *t;
413 f08fdedc 2003-11-23 devnull int len=0;
414 f08fdedc 2003-11-23 devnull word *ap;
415 f08fdedc 2003-11-23 devnull for(ap=words;ap;ap=ap->next)
416 f08fdedc 2003-11-23 devnull len+=1+strlen(ap->word);
417 f08fdedc 2003-11-23 devnull value=emalloc(len+1);
418 f08fdedc 2003-11-23 devnull s=value;
419 f08fdedc 2003-11-23 devnull for(ap=words;ap;ap=ap->next){
420 f08fdedc 2003-11-23 devnull for(t=ap->word;*t;) *s++=*t++;
421 a9eaaa03 2005-01-12 devnull *s++=c;
422 f08fdedc 2003-11-23 devnull }
423 f08fdedc 2003-11-23 devnull if(s==value) *s='\0';
424 f08fdedc 2003-11-23 devnull else s[-1]='\0';
425 f08fdedc 2003-11-23 devnull return value;
426 f08fdedc 2003-11-23 devnull }
427 a9eaaa03 2005-01-12 devnull char *list2str(word *words){
428 a9eaaa03 2005-01-12 devnull return _list2str(words, ' ');
429 a9eaaa03 2005-01-12 devnull }
430 f08fdedc 2003-11-23 devnull void Xmatch(void){
431 f08fdedc 2003-11-23 devnull word *p;
432 f08fdedc 2003-11-23 devnull char *subject;
433 f08fdedc 2003-11-23 devnull subject=list2str(runq->argv->words);
434 f08fdedc 2003-11-23 devnull setstatus("no match");
435 f08fdedc 2003-11-23 devnull for(p=runq->argv->next->words;p;p=p->next)
436 f08fdedc 2003-11-23 devnull if(match(subject, p->word, '\0')){
437 f08fdedc 2003-11-23 devnull setstatus("");
438 f08fdedc 2003-11-23 devnull break;
439 f08fdedc 2003-11-23 devnull }
440 f08fdedc 2003-11-23 devnull efree(subject);
441 f08fdedc 2003-11-23 devnull poplist();
442 f08fdedc 2003-11-23 devnull poplist();
443 f08fdedc 2003-11-23 devnull }
444 f08fdedc 2003-11-23 devnull void Xcase(void){
445 f08fdedc 2003-11-23 devnull word *p;
446 f08fdedc 2003-11-23 devnull char *s;
447 f08fdedc 2003-11-23 devnull int ok=0;
448 f08fdedc 2003-11-23 devnull s=list2str(runq->argv->next->words);
449 f08fdedc 2003-11-23 devnull for(p=runq->argv->words;p;p=p->next){
450 f08fdedc 2003-11-23 devnull if(match(s, p->word, '\0')){
451 f08fdedc 2003-11-23 devnull ok=1;
452 f08fdedc 2003-11-23 devnull break;
453 f08fdedc 2003-11-23 devnull }
454 f08fdedc 2003-11-23 devnull }
455 f08fdedc 2003-11-23 devnull efree(s);
456 f08fdedc 2003-11-23 devnull if(ok)
457 f08fdedc 2003-11-23 devnull runq->pc++;
458 f08fdedc 2003-11-23 devnull else
459 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
460 f08fdedc 2003-11-23 devnull poplist();
461 f08fdedc 2003-11-23 devnull }
462 f08fdedc 2003-11-23 devnull word *conclist(word *lp, word *rp, word *tail)
463 f08fdedc 2003-11-23 devnull {
464 f08fdedc 2003-11-23 devnull char *buf;
465 f08fdedc 2003-11-23 devnull word *v;
466 f08fdedc 2003-11-23 devnull if(lp->next || rp->next)
467 f08fdedc 2003-11-23 devnull tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next,
468 f08fdedc 2003-11-23 devnull tail);
469 f08fdedc 2003-11-23 devnull buf=emalloc(strlen(lp->word)+strlen(rp->word)+1);
470 f08fdedc 2003-11-23 devnull strcpy(buf, lp->word);
471 f08fdedc 2003-11-23 devnull strcat(buf, rp->word);
472 f08fdedc 2003-11-23 devnull v=newword(buf, tail);
473 f08fdedc 2003-11-23 devnull efree(buf);
474 f08fdedc 2003-11-23 devnull return v;
475 f08fdedc 2003-11-23 devnull }
476 f08fdedc 2003-11-23 devnull void Xconc(void){
477 f08fdedc 2003-11-23 devnull word *lp=runq->argv->words;
478 f08fdedc 2003-11-23 devnull word *rp=runq->argv->next->words;
479 f08fdedc 2003-11-23 devnull word *vp=runq->argv->next->next->words;
480 f08fdedc 2003-11-23 devnull int lc=count(lp), rc=count(rp);
481 f08fdedc 2003-11-23 devnull if(lc!=0 || rc!=0){
482 f08fdedc 2003-11-23 devnull if(lc==0 || rc==0){
483 f08fdedc 2003-11-23 devnull Xerror1("null list in concatenation");
484 f08fdedc 2003-11-23 devnull return;
485 f08fdedc 2003-11-23 devnull }
486 f08fdedc 2003-11-23 devnull if(lc!=1 && rc!=1 && lc!=rc){
487 f08fdedc 2003-11-23 devnull Xerror1("mismatched list lengths in concatenation");
488 f08fdedc 2003-11-23 devnull return;
489 f08fdedc 2003-11-23 devnull }
490 f08fdedc 2003-11-23 devnull vp=conclist(lp, rp, vp);
491 f08fdedc 2003-11-23 devnull }
492 f08fdedc 2003-11-23 devnull poplist();
493 f08fdedc 2003-11-23 devnull poplist();
494 f08fdedc 2003-11-23 devnull runq->argv->words=vp;
495 f08fdedc 2003-11-23 devnull }
496 f08fdedc 2003-11-23 devnull void Xassign(void){
497 f08fdedc 2003-11-23 devnull var *v;
498 f08fdedc 2003-11-23 devnull if(count(runq->argv->words)!=1){
499 f08fdedc 2003-11-23 devnull Xerror1("variable name not singleton!");
500 f08fdedc 2003-11-23 devnull return;
501 f08fdedc 2003-11-23 devnull }
502 f08fdedc 2003-11-23 devnull deglob(runq->argv->words->word);
503 f08fdedc 2003-11-23 devnull v=vlook(runq->argv->words->word);
504 f08fdedc 2003-11-23 devnull poplist();
505 f08fdedc 2003-11-23 devnull globlist();
506 f08fdedc 2003-11-23 devnull freewords(v->val);
507 f08fdedc 2003-11-23 devnull v->val=runq->argv->words;
508 f08fdedc 2003-11-23 devnull v->changed=1;
509 a9eaaa03 2005-01-12 devnull if(v->changefn)
510 a9eaaa03 2005-01-12 devnull v->changefn(v);
511 f08fdedc 2003-11-23 devnull runq->argv->words=0;
512 f08fdedc 2003-11-23 devnull poplist();
513 f08fdedc 2003-11-23 devnull }
514 f08fdedc 2003-11-23 devnull /*
515 f08fdedc 2003-11-23 devnull * copy arglist a, adding the copy to the front of tail
516 f08fdedc 2003-11-23 devnull */
517 f08fdedc 2003-11-23 devnull word *copywords(word *a, word *tail)
518 f08fdedc 2003-11-23 devnull {
519 f08fdedc 2003-11-23 devnull word *v=0, **end;
520 f08fdedc 2003-11-23 devnull for(end=&v;a;a=a->next,end=&(*end)->next)
521 f08fdedc 2003-11-23 devnull *end=newword(a->word, 0);
522 f08fdedc 2003-11-23 devnull *end=tail;
523 f08fdedc 2003-11-23 devnull return v;
524 f08fdedc 2003-11-23 devnull }
525 f08fdedc 2003-11-23 devnull void Xdol(void){
526 f08fdedc 2003-11-23 devnull word *a, *star;
527 f08fdedc 2003-11-23 devnull char *s, *t;
528 f08fdedc 2003-11-23 devnull int n;
529 f08fdedc 2003-11-23 devnull if(count(runq->argv->words)!=1){
530 f08fdedc 2003-11-23 devnull Xerror1("variable name not singleton!");
531 f08fdedc 2003-11-23 devnull return;
532 f08fdedc 2003-11-23 devnull }
533 f08fdedc 2003-11-23 devnull s=runq->argv->words->word;
534 f08fdedc 2003-11-23 devnull deglob(s);
535 f08fdedc 2003-11-23 devnull n=0;
536 f08fdedc 2003-11-23 devnull for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
537 f08fdedc 2003-11-23 devnull a=runq->argv->next->words;
538 f08fdedc 2003-11-23 devnull if(n==0 || *t)
539 f08fdedc 2003-11-23 devnull a=copywords(vlook(s)->val, a);
540 f08fdedc 2003-11-23 devnull else{
541 f08fdedc 2003-11-23 devnull star=vlook("*")->val;
542 f08fdedc 2003-11-23 devnull if(star && 1<=n && n<=count(star)){
543 f08fdedc 2003-11-23 devnull while(--n) star=star->next;
544 f08fdedc 2003-11-23 devnull a=newword(star->word, a);
545 f08fdedc 2003-11-23 devnull }
546 f08fdedc 2003-11-23 devnull }
547 f08fdedc 2003-11-23 devnull poplist();
548 f08fdedc 2003-11-23 devnull runq->argv->words=a;
549 f08fdedc 2003-11-23 devnull }
550 f08fdedc 2003-11-23 devnull void Xqdol(void){
551 f08fdedc 2003-11-23 devnull word *a, *p;
552 f08fdedc 2003-11-23 devnull char *s;
553 f08fdedc 2003-11-23 devnull int n;
554 f08fdedc 2003-11-23 devnull if(count(runq->argv->words)!=1){
555 f08fdedc 2003-11-23 devnull Xerror1("variable name not singleton!");
556 f08fdedc 2003-11-23 devnull return;
557 f08fdedc 2003-11-23 devnull }
558 f08fdedc 2003-11-23 devnull s=runq->argv->words->word;
559 f08fdedc 2003-11-23 devnull deglob(s);
560 f08fdedc 2003-11-23 devnull a=vlook(s)->val;
561 f08fdedc 2003-11-23 devnull poplist();
562 f08fdedc 2003-11-23 devnull n=count(a);
563 f08fdedc 2003-11-23 devnull if(n==0){
564 f08fdedc 2003-11-23 devnull pushword("");
565 f08fdedc 2003-11-23 devnull return;
566 f08fdedc 2003-11-23 devnull }
567 f08fdedc 2003-11-23 devnull for(p=a;p;p=p->next) n+=strlen(p->word);
568 f08fdedc 2003-11-23 devnull s=emalloc(n);
569 f08fdedc 2003-11-23 devnull if(a){
570 f08fdedc 2003-11-23 devnull strcpy(s, a->word);
571 f08fdedc 2003-11-23 devnull for(p=a->next;p;p=p->next){
572 f08fdedc 2003-11-23 devnull strcat(s, " ");
573 f08fdedc 2003-11-23 devnull strcat(s, p->word);
574 f08fdedc 2003-11-23 devnull }
575 f08fdedc 2003-11-23 devnull }
576 f08fdedc 2003-11-23 devnull else
577 f08fdedc 2003-11-23 devnull s[0]='\0';
578 f08fdedc 2003-11-23 devnull pushword(s);
579 f08fdedc 2003-11-23 devnull efree(s);
580 f08fdedc 2003-11-23 devnull }
581 f08fdedc 2003-11-23 devnull word *subwords(word *val, int len, word *sub, word *a)
582 f08fdedc 2003-11-23 devnull {
583 f08fdedc 2003-11-23 devnull int n;
584 f08fdedc 2003-11-23 devnull char *s;
585 f08fdedc 2003-11-23 devnull if(!sub) return a;
586 f08fdedc 2003-11-23 devnull a=subwords(val, len, sub->next, a);
587 f08fdedc 2003-11-23 devnull s=sub->word;
588 f08fdedc 2003-11-23 devnull deglob(s);
589 f08fdedc 2003-11-23 devnull n=0;
590 f08fdedc 2003-11-23 devnull while('0'<=*s && *s<='9') n=n*10+ *s++ -'0';
591 f08fdedc 2003-11-23 devnull if(n<1 || len<n) return a;
592 f08fdedc 2003-11-23 devnull for(;n!=1;--n) val=val->next;
593 f08fdedc 2003-11-23 devnull return newword(val->word, a);
594 f08fdedc 2003-11-23 devnull }
595 f08fdedc 2003-11-23 devnull void Xsub(void){
596 f08fdedc 2003-11-23 devnull word *a, *v;
597 f08fdedc 2003-11-23 devnull char *s;
598 f08fdedc 2003-11-23 devnull if(count(runq->argv->next->words)!=1){
599 f08fdedc 2003-11-23 devnull Xerror1("variable name not singleton!");
600 f08fdedc 2003-11-23 devnull return;
601 f08fdedc 2003-11-23 devnull }
602 f08fdedc 2003-11-23 devnull s=runq->argv->next->words->word;
603 f08fdedc 2003-11-23 devnull deglob(s);
604 f08fdedc 2003-11-23 devnull a=runq->argv->next->next->words;
605 f08fdedc 2003-11-23 devnull v=vlook(s)->val;
606 f08fdedc 2003-11-23 devnull a=subwords(v, count(v), runq->argv->words, a);
607 f08fdedc 2003-11-23 devnull poplist();
608 f08fdedc 2003-11-23 devnull poplist();
609 f08fdedc 2003-11-23 devnull runq->argv->words=a;
610 f08fdedc 2003-11-23 devnull }
611 f08fdedc 2003-11-23 devnull void Xcount(void){
612 f08fdedc 2003-11-23 devnull word *a;
613 f08fdedc 2003-11-23 devnull char *s, *t;
614 f08fdedc 2003-11-23 devnull int n;
615 f08fdedc 2003-11-23 devnull char num[12];
616 f08fdedc 2003-11-23 devnull if(count(runq->argv->words)!=1){
617 f08fdedc 2003-11-23 devnull Xerror1("variable name not singleton!");
618 f08fdedc 2003-11-23 devnull return;
619 f08fdedc 2003-11-23 devnull }
620 f08fdedc 2003-11-23 devnull s=runq->argv->words->word;
621 f08fdedc 2003-11-23 devnull deglob(s);
622 f08fdedc 2003-11-23 devnull n=0;
623 f08fdedc 2003-11-23 devnull for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
624 f08fdedc 2003-11-23 devnull if(n==0 || *t){
625 f08fdedc 2003-11-23 devnull a=vlook(s)->val;
626 f08fdedc 2003-11-23 devnull itoa(num, count(a));
627 f08fdedc 2003-11-23 devnull }
628 f08fdedc 2003-11-23 devnull else{
629 f08fdedc 2003-11-23 devnull a=vlook("*")->val;
630 f08fdedc 2003-11-23 devnull itoa(num, a && 1<=n && n<=count(a)?1:0);
631 f08fdedc 2003-11-23 devnull }
632 f08fdedc 2003-11-23 devnull poplist();
633 f08fdedc 2003-11-23 devnull pushword(num);
634 f08fdedc 2003-11-23 devnull }
635 f08fdedc 2003-11-23 devnull void Xlocal(void){
636 f08fdedc 2003-11-23 devnull if(count(runq->argv->words)!=1){
637 f08fdedc 2003-11-23 devnull Xerror1("variable name must be singleton\n");
638 f08fdedc 2003-11-23 devnull return;
639 f08fdedc 2003-11-23 devnull }
640 f08fdedc 2003-11-23 devnull deglob(runq->argv->words->word);
641 f08fdedc 2003-11-23 devnull runq->local=newvar(strdup(runq->argv->words->word), runq->local);
642 f08fdedc 2003-11-23 devnull runq->local->val=copywords(runq->argv->next->words, (word *)0);
643 f08fdedc 2003-11-23 devnull runq->local->changed=1;
644 f08fdedc 2003-11-23 devnull poplist();
645 f08fdedc 2003-11-23 devnull poplist();
646 f08fdedc 2003-11-23 devnull }
647 f08fdedc 2003-11-23 devnull void Xunlocal(void){
648 f08fdedc 2003-11-23 devnull var *v=runq->local, *hid;
649 f08fdedc 2003-11-23 devnull if(v==0) panic("Xunlocal: no locals!", 0);
650 f08fdedc 2003-11-23 devnull runq->local=v->next;
651 f08fdedc 2003-11-23 devnull hid=vlook(v->name);
652 f08fdedc 2003-11-23 devnull hid->changed=1;
653 f08fdedc 2003-11-23 devnull efree(v->name);
654 f08fdedc 2003-11-23 devnull freewords(v->val);
655 f08fdedc 2003-11-23 devnull efree((char *)v);
656 f08fdedc 2003-11-23 devnull }
657 f08fdedc 2003-11-23 devnull void freewords(word *w)
658 f08fdedc 2003-11-23 devnull {
659 f08fdedc 2003-11-23 devnull word *nw;
660 f08fdedc 2003-11-23 devnull while(w){
661 f08fdedc 2003-11-23 devnull efree(w->word);
662 f08fdedc 2003-11-23 devnull nw=w->next;
663 f08fdedc 2003-11-23 devnull efree((char *)w);
664 f08fdedc 2003-11-23 devnull w=nw;
665 f08fdedc 2003-11-23 devnull }
666 f08fdedc 2003-11-23 devnull }
667 f08fdedc 2003-11-23 devnull void Xfn(void){
668 f08fdedc 2003-11-23 devnull var *v;
669 f08fdedc 2003-11-23 devnull word *a;
670 f08fdedc 2003-11-23 devnull int end;
671 f08fdedc 2003-11-23 devnull end=runq->code[runq->pc].i;
672 f08fdedc 2003-11-23 devnull for(a=runq->argv->words;a;a=a->next){
673 f08fdedc 2003-11-23 devnull v=gvlook(a->word);
674 f08fdedc 2003-11-23 devnull if(v->fn) codefree(v->fn);
675 f08fdedc 2003-11-23 devnull v->fn=codecopy(runq->code);
676 f08fdedc 2003-11-23 devnull v->pc=runq->pc+2;
677 f08fdedc 2003-11-23 devnull v->fnchanged=1;
678 f08fdedc 2003-11-23 devnull }
679 f08fdedc 2003-11-23 devnull runq->pc=end;
680 f08fdedc 2003-11-23 devnull poplist();
681 f08fdedc 2003-11-23 devnull }
682 f08fdedc 2003-11-23 devnull void Xdelfn(void){
683 f08fdedc 2003-11-23 devnull var *v;
684 f08fdedc 2003-11-23 devnull word *a;
685 f08fdedc 2003-11-23 devnull for(a=runq->argv->words;a;a=a->next){
686 f08fdedc 2003-11-23 devnull v=gvlook(a->word);
687 f08fdedc 2003-11-23 devnull if(v->fn) codefree(v->fn);
688 f08fdedc 2003-11-23 devnull v->fn=0;
689 f08fdedc 2003-11-23 devnull v->fnchanged=1;
690 f08fdedc 2003-11-23 devnull }
691 f08fdedc 2003-11-23 devnull poplist();
692 f08fdedc 2003-11-23 devnull }
693 f08fdedc 2003-11-23 devnull void Xpipe(void){
694 f08fdedc 2003-11-23 devnull struct thread *p=runq;
695 f08fdedc 2003-11-23 devnull int pc=p->pc, forkid;
696 f08fdedc 2003-11-23 devnull int lfd=p->code[pc++].i;
697 f08fdedc 2003-11-23 devnull int rfd=p->code[pc++].i;
698 f08fdedc 2003-11-23 devnull int pfd[2];
699 f08fdedc 2003-11-23 devnull if(pipe(pfd)<0){
700 f08fdedc 2003-11-23 devnull Xerror("can't get pipe");
701 f08fdedc 2003-11-23 devnull return;
702 f08fdedc 2003-11-23 devnull }
703 f08fdedc 2003-11-23 devnull switch(forkid=fork()){
704 f08fdedc 2003-11-23 devnull case -1:
705 f08fdedc 2003-11-23 devnull Xerror("try again");
706 f08fdedc 2003-11-23 devnull break;
707 f08fdedc 2003-11-23 devnull case 0:
708 f08fdedc 2003-11-23 devnull start(p->code, pc+2, runq->local);
709 f08fdedc 2003-11-23 devnull runq->ret=0;
710 f08fdedc 2003-11-23 devnull close(pfd[PRD]);
711 f08fdedc 2003-11-23 devnull pushredir(ROPEN, pfd[PWR], lfd);
712 f08fdedc 2003-11-23 devnull break;
713 f08fdedc 2003-11-23 devnull default:
714 f08fdedc 2003-11-23 devnull start(p->code, p->code[pc].i, runq->local);
715 f08fdedc 2003-11-23 devnull close(pfd[PWR]);
716 f08fdedc 2003-11-23 devnull pushredir(ROPEN, pfd[PRD], rfd);
717 f08fdedc 2003-11-23 devnull p->pc=p->code[pc+1].i;
718 f08fdedc 2003-11-23 devnull p->pid=forkid;
719 f08fdedc 2003-11-23 devnull break;
720 f08fdedc 2003-11-23 devnull }
721 f08fdedc 2003-11-23 devnull }
722 f08fdedc 2003-11-23 devnull char *concstatus(char *s, char *t)
723 f08fdedc 2003-11-23 devnull {
724 f08fdedc 2003-11-23 devnull static char v[NSTATUS+1];
725 f08fdedc 2003-11-23 devnull int n=strlen(s);
726 f08fdedc 2003-11-23 devnull strncpy(v, s, NSTATUS);
727 f08fdedc 2003-11-23 devnull if(n<NSTATUS){
728 f08fdedc 2003-11-23 devnull v[n]='|';
729 f08fdedc 2003-11-23 devnull strncpy(v+n+1, t, NSTATUS-n-1);
730 f08fdedc 2003-11-23 devnull }
731 f08fdedc 2003-11-23 devnull v[NSTATUS]='\0';
732 f08fdedc 2003-11-23 devnull return v;
733 f08fdedc 2003-11-23 devnull }
734 f08fdedc 2003-11-23 devnull void Xpipewait(void){
735 f08fdedc 2003-11-23 devnull char status[NSTATUS+1];
736 f08fdedc 2003-11-23 devnull if(runq->pid==-1)
737 f08fdedc 2003-11-23 devnull setstatus(concstatus(runq->status, getstatus()));
738 f08fdedc 2003-11-23 devnull else{
739 f08fdedc 2003-11-23 devnull strncpy(status, getstatus(), NSTATUS);
740 f08fdedc 2003-11-23 devnull status[NSTATUS]='\0';
741 f08fdedc 2003-11-23 devnull Waitfor(runq->pid, 1);
742 f08fdedc 2003-11-23 devnull runq->pid=-1;
743 f08fdedc 2003-11-23 devnull setstatus(concstatus(getstatus(), status));
744 f08fdedc 2003-11-23 devnull }
745 f08fdedc 2003-11-23 devnull }
746 f08fdedc 2003-11-23 devnull void Xrdcmds(void){
747 f08fdedc 2003-11-23 devnull struct thread *p=runq;
748 f08fdedc 2003-11-23 devnull word *prompt;
749 f08fdedc 2003-11-23 devnull flush(err);
750 f08fdedc 2003-11-23 devnull nerror=0;
751 f08fdedc 2003-11-23 devnull if(flag['s'] && !truestatus())
752 f08fdedc 2003-11-23 devnull pfmt(err, "status=%v\n", vlook("status")->val);
753 f08fdedc 2003-11-23 devnull if(runq->iflag){
754 f08fdedc 2003-11-23 devnull prompt=vlook("prompt")->val;
755 f08fdedc 2003-11-23 devnull if(prompt)
756 f08fdedc 2003-11-23 devnull promptstr=prompt->word;
757 f08fdedc 2003-11-23 devnull else
758 f08fdedc 2003-11-23 devnull promptstr="% ";
759 f08fdedc 2003-11-23 devnull }
760 f08fdedc 2003-11-23 devnull Noerror();
761 f08fdedc 2003-11-23 devnull if(yyparse()){
762 f08fdedc 2003-11-23 devnull if(!p->iflag || p->eof && !Eintr()){
763 f08fdedc 2003-11-23 devnull if(p->cmdfile) efree(p->cmdfile);
764 f08fdedc 2003-11-23 devnull closeio(p->cmdfd);
765 f08fdedc 2003-11-23 devnull Xreturn(); /* should this be omitted? */
766 f08fdedc 2003-11-23 devnull }
767 f08fdedc 2003-11-23 devnull else{
768 f08fdedc 2003-11-23 devnull if(Eintr()){
769 f08fdedc 2003-11-23 devnull pchr(err, '\n');
770 f08fdedc 2003-11-23 devnull p->eof=0;
771 f08fdedc 2003-11-23 devnull }
772 f08fdedc 2003-11-23 devnull --p->pc; /* go back for next command */
773 f08fdedc 2003-11-23 devnull }
774 f08fdedc 2003-11-23 devnull }
775 f08fdedc 2003-11-23 devnull else{
776 f08fdedc 2003-11-23 devnull ntrap = 0; /* avoid double-interrupts during blocked writes */
777 f08fdedc 2003-11-23 devnull --p->pc; /* re-execute Xrdcmds after codebuf runs */
778 f08fdedc 2003-11-23 devnull start(codebuf, 1, runq->local);
779 f08fdedc 2003-11-23 devnull }
780 f08fdedc 2003-11-23 devnull freenodes();
781 f08fdedc 2003-11-23 devnull }
782 f08fdedc 2003-11-23 devnull void Xerror(char *s)
783 f08fdedc 2003-11-23 devnull {
784 f08fdedc 2003-11-23 devnull if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
785 f08fdedc 2003-11-23 devnull pfmt(err, "rc: %s: %r\n", s);
786 f08fdedc 2003-11-23 devnull else
787 f08fdedc 2003-11-23 devnull pfmt(err, "rc (%s): %s: %r\n", argv0, s);
788 f08fdedc 2003-11-23 devnull flush(err);
789 4ae2f414 2005-08-11 devnull setstatus("error");
790 f08fdedc 2003-11-23 devnull while(!runq->iflag) Xreturn();
791 f08fdedc 2003-11-23 devnull }
792 f08fdedc 2003-11-23 devnull void Xerror1(char *s)
793 f08fdedc 2003-11-23 devnull {
794 f08fdedc 2003-11-23 devnull if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
795 f08fdedc 2003-11-23 devnull pfmt(err, "rc: %s\n", s);
796 f08fdedc 2003-11-23 devnull else
797 f08fdedc 2003-11-23 devnull pfmt(err, "rc (%s): %s\n", argv0, s);
798 f08fdedc 2003-11-23 devnull flush(err);
799 4ae2f414 2005-08-11 devnull setstatus("error");
800 f08fdedc 2003-11-23 devnull while(!runq->iflag) Xreturn();
801 f08fdedc 2003-11-23 devnull }
802 f08fdedc 2003-11-23 devnull void Xbackq(void){
803 f08fdedc 2003-11-23 devnull char wd[8193];
804 f08fdedc 2003-11-23 devnull int c;
805 f08fdedc 2003-11-23 devnull char *s, *ewd=&wd[8192], *stop;
806 f08fdedc 2003-11-23 devnull struct io *f;
807 f08fdedc 2003-11-23 devnull var *ifs=vlook("ifs");
808 f08fdedc 2003-11-23 devnull word *v, *nextv;
809 f08fdedc 2003-11-23 devnull int pfd[2];
810 f08fdedc 2003-11-23 devnull int pid;
811 f08fdedc 2003-11-23 devnull stop=ifs->val?ifs->val->word:"";
812 f08fdedc 2003-11-23 devnull if(pipe(pfd)<0){
813 f08fdedc 2003-11-23 devnull Xerror("can't make pipe");
814 f08fdedc 2003-11-23 devnull return;
815 f08fdedc 2003-11-23 devnull }
816 f08fdedc 2003-11-23 devnull switch(pid=fork()){
817 f08fdedc 2003-11-23 devnull case -1: Xerror("try again");
818 f08fdedc 2003-11-23 devnull close(pfd[PRD]);
819 f08fdedc 2003-11-23 devnull close(pfd[PWR]);
820 f08fdedc 2003-11-23 devnull return;
821 f08fdedc 2003-11-23 devnull case 0:
822 f08fdedc 2003-11-23 devnull close(pfd[PRD]);
823 f08fdedc 2003-11-23 devnull start(runq->code, runq->pc+1, runq->local);
824 f08fdedc 2003-11-23 devnull pushredir(ROPEN, pfd[PWR], 1);
825 f08fdedc 2003-11-23 devnull return;
826 f08fdedc 2003-11-23 devnull default:
827 f08fdedc 2003-11-23 devnull close(pfd[PWR]);
828 f08fdedc 2003-11-23 devnull f=openfd(pfd[PRD]);
829 f08fdedc 2003-11-23 devnull s=wd;
830 f08fdedc 2003-11-23 devnull v=0;
831 f08fdedc 2003-11-23 devnull while((c=rchr(f))!=EOF){
832 f08fdedc 2003-11-23 devnull if(strchr(stop, c) || s==ewd){
833 f08fdedc 2003-11-23 devnull if(s!=wd){
834 f08fdedc 2003-11-23 devnull *s='\0';
835 f08fdedc 2003-11-23 devnull v=newword(wd, v);
836 f08fdedc 2003-11-23 devnull s=wd;
837 f08fdedc 2003-11-23 devnull }
838 f08fdedc 2003-11-23 devnull }
839 f08fdedc 2003-11-23 devnull else *s++=c;
840 f08fdedc 2003-11-23 devnull }
841 f08fdedc 2003-11-23 devnull if(s!=wd){
842 f08fdedc 2003-11-23 devnull *s='\0';
843 f08fdedc 2003-11-23 devnull v=newword(wd, v);
844 f08fdedc 2003-11-23 devnull }
845 f08fdedc 2003-11-23 devnull closeio(f);
846 f08fdedc 2003-11-23 devnull Waitfor(pid, 0);
847 f08fdedc 2003-11-23 devnull /* v points to reversed arglist -- reverse it onto argv */
848 f08fdedc 2003-11-23 devnull while(v){
849 f08fdedc 2003-11-23 devnull nextv=v->next;
850 f08fdedc 2003-11-23 devnull v->next=runq->argv->words;
851 f08fdedc 2003-11-23 devnull runq->argv->words=v;
852 f08fdedc 2003-11-23 devnull v=nextv;
853 f08fdedc 2003-11-23 devnull }
854 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
855 f08fdedc 2003-11-23 devnull return;
856 f08fdedc 2003-11-23 devnull }
857 f08fdedc 2003-11-23 devnull }
858 f08fdedc 2003-11-23 devnull /*
859 f08fdedc 2003-11-23 devnull * Who should wait for the exit from the fork?
860 f08fdedc 2003-11-23 devnull */
861 f08fdedc 2003-11-23 devnull void Xpipefd(void){
862 f08fdedc 2003-11-23 devnull struct thread *p=runq;
863 f08fdedc 2003-11-23 devnull int pc=p->pc;
864 f08fdedc 2003-11-23 devnull char name[40];
865 f08fdedc 2003-11-23 devnull int pfd[2];
866 f08fdedc 2003-11-23 devnull int sidefd, mainfd;
867 f08fdedc 2003-11-23 devnull if(pipe(pfd)<0){
868 f08fdedc 2003-11-23 devnull Xerror("can't get pipe");
869 f08fdedc 2003-11-23 devnull return;
870 f08fdedc 2003-11-23 devnull }
871 f08fdedc 2003-11-23 devnull if(p->code[pc].i==READ){
872 f08fdedc 2003-11-23 devnull sidefd=pfd[PWR];
873 f08fdedc 2003-11-23 devnull mainfd=pfd[PRD];
874 f08fdedc 2003-11-23 devnull }
875 f08fdedc 2003-11-23 devnull else{
876 f08fdedc 2003-11-23 devnull sidefd=pfd[PRD];
877 f08fdedc 2003-11-23 devnull mainfd=pfd[PWR];
878 f08fdedc 2003-11-23 devnull }
879 f08fdedc 2003-11-23 devnull switch(fork()){
880 f08fdedc 2003-11-23 devnull case -1:
881 f08fdedc 2003-11-23 devnull Xerror("try again");
882 f08fdedc 2003-11-23 devnull break;
883 f08fdedc 2003-11-23 devnull case 0:
884 f08fdedc 2003-11-23 devnull start(p->code, pc+2, runq->local);
885 f08fdedc 2003-11-23 devnull close(mainfd);
886 f08fdedc 2003-11-23 devnull pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
887 f08fdedc 2003-11-23 devnull runq->ret=0;
888 f08fdedc 2003-11-23 devnull break;
889 f08fdedc 2003-11-23 devnull default:
890 f08fdedc 2003-11-23 devnull close(sidefd);
891 f08fdedc 2003-11-23 devnull pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
892 f08fdedc 2003-11-23 devnull strcpy(name, Fdprefix);
893 f08fdedc 2003-11-23 devnull itoa(name+strlen(name), mainfd);
894 f08fdedc 2003-11-23 devnull pushword(name);
895 f08fdedc 2003-11-23 devnull p->pc=p->code[pc+1].i;
896 f08fdedc 2003-11-23 devnull break;
897 f08fdedc 2003-11-23 devnull }
898 f08fdedc 2003-11-23 devnull }
899 f08fdedc 2003-11-23 devnull void Xsubshell(void){
900 f08fdedc 2003-11-23 devnull int pid;
901 f08fdedc 2003-11-23 devnull switch(pid=fork()){
902 f08fdedc 2003-11-23 devnull case -1:
903 f08fdedc 2003-11-23 devnull Xerror("try again");
904 f08fdedc 2003-11-23 devnull break;
905 f08fdedc 2003-11-23 devnull case 0:
906 f08fdedc 2003-11-23 devnull start(runq->code, runq->pc+1, runq->local);
907 f08fdedc 2003-11-23 devnull runq->ret=0;
908 f08fdedc 2003-11-23 devnull break;
909 f08fdedc 2003-11-23 devnull default:
910 f08fdedc 2003-11-23 devnull Waitfor(pid, 1);
911 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
912 f08fdedc 2003-11-23 devnull break;
913 f08fdedc 2003-11-23 devnull }
914 f08fdedc 2003-11-23 devnull }
915 f08fdedc 2003-11-23 devnull void setstatus(char *s)
916 f08fdedc 2003-11-23 devnull {
917 f08fdedc 2003-11-23 devnull setvar("status", newword(s, (word *)0));
918 f08fdedc 2003-11-23 devnull }
919 f08fdedc 2003-11-23 devnull char *getstatus(void){
920 f08fdedc 2003-11-23 devnull var *status=vlook("status");
921 f08fdedc 2003-11-23 devnull return status->val?status->val->word:"";
922 f08fdedc 2003-11-23 devnull }
923 f08fdedc 2003-11-23 devnull int truestatus(void){
924 f08fdedc 2003-11-23 devnull char *s;
925 f08fdedc 2003-11-23 devnull for(s=getstatus();*s;s++)
926 f08fdedc 2003-11-23 devnull if(*s!='|' && *s!='0') return 0;
927 f08fdedc 2003-11-23 devnull return 1;
928 f08fdedc 2003-11-23 devnull }
929 f08fdedc 2003-11-23 devnull void Xdelhere(void){
930 f08fdedc 2003-11-23 devnull Unlink(runq->code[runq->pc++].s);
931 f08fdedc 2003-11-23 devnull }
932 f08fdedc 2003-11-23 devnull void Xfor(void){
933 f08fdedc 2003-11-23 devnull if(runq->argv->words==0){
934 f08fdedc 2003-11-23 devnull poplist();
935 f08fdedc 2003-11-23 devnull runq->pc=runq->code[runq->pc].i;
936 f08fdedc 2003-11-23 devnull }
937 f08fdedc 2003-11-23 devnull else{
938 f08fdedc 2003-11-23 devnull freelist(runq->local->val);
939 f08fdedc 2003-11-23 devnull runq->local->val=runq->argv->words;
940 f08fdedc 2003-11-23 devnull runq->local->changed=1;
941 f08fdedc 2003-11-23 devnull runq->argv->words=runq->argv->words->next;
942 f08fdedc 2003-11-23 devnull runq->local->val->next=0;
943 f08fdedc 2003-11-23 devnull runq->pc++;
944 f08fdedc 2003-11-23 devnull }
945 f08fdedc 2003-11-23 devnull }
946 f08fdedc 2003-11-23 devnull void Xglob(void){
947 f08fdedc 2003-11-23 devnull globlist();
948 f08fdedc 2003-11-23 devnull }