Introduction
Introduction Statistics Contact Development Disclaimer Help
simple.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
simple.c (9019B)
---
1 /*
2 * Maybe `simple' is a misnomer.
3 */
4 #include "rc.h"
5 #include "getflags.h"
6 #include "exec.h"
7 #include "io.h"
8 #include "fns.h"
9 /*
10 * Search through the following code to see if we're just going to exit.
11 */
12 int
13 exitnext(void){
14 union code *c=&runq->code[runq->pc];
15 while(c->f==Xpopredir) c++;
16 return c->f==Xexit;
17 }
18
19 void
20 Xsimple(void)
21 {
22 word *a;
23 thread *p = runq;
24 var *v;
25 struct builtin *bp;
26 int pid;
27 globlist();
28 a = runq->argv->words;
29 if(a==0){
30 Xerror1("empty argument list");
31 return;
32 }
33 if(flag['x'])
34 pfmt(err, "%v\n", p->argv->words); /* wrong, should do r…
35 v = gvlook(a->word);
36 if(v->fn)
37 execfunc(v);
38 else{
39 if(strcmp(a->word, "builtin")==0){
40 if(count(a)==1){
41 pfmt(err, "builtin: empty argument list\…
42 setstatus("empty arg list");
43 poplist();
44 return;
45 }
46 a = a->next;
47 popword();
48 }
49 for(bp = Builtin;bp->name;bp++)
50 if(strcmp(a->word, bp->name)==0){
51 (*bp->fnc)();
52 return;
53 }
54 if(exitnext()){
55 /* fork and wait is redundant */
56 pushword("exec");
57 execexec();
58 Xexit();
59 }
60 else{
61 flush(err);
62 Updenv(); /* necessary so changes don't g…
63 if((pid = execforkexec()) < 0){
64 Xerror("try again");
65 return;
66 }
67
68 /* interrupts don't get us out */
69 poplist();
70 while(Waitfor(pid, 1) < 0)
71 ;
72 }
73 }
74 }
75 struct word nullpath = { "", 0};
76
77 void
78 doredir(redir *rp)
79 {
80 if(rp){
81 doredir(rp->next);
82 switch(rp->type){
83 case ROPEN:
84 if(rp->from!=rp->to){
85 Dup(rp->from, rp->to);
86 close(rp->from);
87 }
88 break;
89 case RDUP:
90 Dup(rp->from, rp->to);
91 break;
92 case RCLOSE:
93 close(rp->from);
94 break;
95 }
96 }
97 }
98
99 word*
100 searchpath(char *w)
101 {
102 word *path;
103 if(strncmp(w, "/", 1)==0
104 /* || strncmp(w, "#", 1)==0 */
105 || strncmp(w, "./", 2)==0
106 || strncmp(w, "../", 3)==0
107 || (path = vlook("path")->val)==0)
108 path=&nullpath;
109 return path;
110 }
111
112 void
113 execexec(void)
114 {
115 popword(); /* "exec" */
116 if(runq->argv->words==0){
117 Xerror1("empty argument list");
118 return;
119 }
120 doredir(runq->redir);
121 Execute(runq->argv->words, searchpath(runq->argv->words->word));
122 poplist();
123 }
124
125 void
126 execfunc(var *func)
127 {
128 word *starval;
129 popword();
130 starval = runq->argv->words;
131 runq->argv->words = 0;
132 poplist();
133 start(func->fn, func->pc, runq->local);
134 runq->local = newvar(strdup("*"), runq->local);
135 runq->local->val = starval;
136 runq->local->changed = 1;
137 }
138
139 int
140 dochdir(char *word)
141 {
142 /* report to /dev/wdir if it exists and we're interactive */
143 static int wdirfd = -2;
144 if(chdir(word)<0) return -1;
145 if(flag['i']!=0){
146 if(wdirfd==-2) /* try only once */
147 wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
148 if(wdirfd>=0)
149 write(wdirfd, word, strlen(word));
150 }
151 return 1;
152 }
153
154 void
155 execcd(void)
156 {
157 word *a = runq->argv->words;
158 word *cdpath;
159 char dir[512];
160 setstatus("can't cd");
161 cdpath = vlook("cdpath")->val;
162 switch(count(a)){
163 default:
164 pfmt(err, "Usage: cd [directory]\n");
165 break;
166 case 2:
167 if(a->next->word[0]=='/' || cdpath==0)
168 cdpath=&nullpath;
169 for(;cdpath;cdpath = cdpath->next){
170 strcpy(dir, cdpath->word);
171 if(dir[0])
172 strcat(dir, "/");
173 strcat(dir, a->next->word);
174 if(dochdir(dir)>=0){
175 if(strlen(cdpath->word)
176 && strcmp(cdpath->word, ".")!=0)
177 pfmt(err, "%s\n", dir);
178 setstatus("");
179 break;
180 }
181 }
182 if(cdpath==0)
183 pfmt(err, "Can't cd %s: %r\n", a->next->word);
184 break;
185 case 1:
186 a = vlook("home")->val;
187 if(count(a)>=1){
188 if(dochdir(a->word)>=0)
189 setstatus("");
190 else
191 pfmt(err, "Can't cd %s: %r\n", a->word);
192 }
193 else
194 pfmt(err, "Can't cd -- $home empty\n");
195 break;
196 }
197 poplist();
198 }
199
200 void
201 execexit(void)
202 {
203 switch(count(runq->argv->words)){
204 default:
205 pfmt(err, "Usage: exit [status]\nExiting anyway\n");
206 case 2:
207 setstatus(runq->argv->words->next->word);
208 case 1: Xexit();
209 }
210 }
211
212 void
213 execshift(void)
214 {
215 int n;
216 word *a;
217 var *star;
218 switch(count(runq->argv->words)){
219 default:
220 pfmt(err, "Usage: shift [n]\n");
221 setstatus("shift usage");
222 poplist();
223 return;
224 case 2:
225 n = atoi(runq->argv->words->next->word);
226 break;
227 case 1:
228 n = 1;
229 break;
230 }
231 star = vlook("*");
232 for(;n && star->val;--n){
233 a = star->val->next;
234 efree(star->val->word);
235 efree((char *)star->val);
236 star->val = a;
237 star->changed = 1;
238 }
239 setstatus("");
240 poplist();
241 }
242
243 int
244 octal(char *s)
245 {
246 int n = 0;
247 while(*s==' ' || *s=='\t' || *s=='\n') s++;
248 while('0'<=*s && *s<='7') n = n*8+*s++-'0';
249 return n;
250 }
251
252 int
253 mapfd(int fd)
254 {
255 redir *rp;
256 for(rp = runq->redir;rp;rp = rp->next){
257 switch(rp->type){
258 case RCLOSE:
259 if(rp->from==fd)
260 fd=-1;
261 break;
262 case RDUP:
263 case ROPEN:
264 if(rp->to==fd)
265 fd = rp->from;
266 break;
267 }
268 }
269 return fd;
270 }
271 union code rdcmds[4];
272
273 void
274 execcmds(io *f)
275 {
276 static int first = 1;
277 if(first){
278 rdcmds[0].i = 1;
279 rdcmds[1].f = Xrdcmds;
280 rdcmds[2].f = Xreturn;
281 first = 0;
282 }
283 start(rdcmds, 1, runq->local);
284 runq->cmdfd = f;
285 runq->iflast = 0;
286 }
287
288 void
289 execeval(void)
290 {
291 char *cmdline, *s, *t;
292 int len = 0;
293 word *ap;
294 if(count(runq->argv->words)<=1){
295 Xerror1("Usage: eval cmd ...");
296 return;
297 }
298 eflagok = 1;
299 for(ap = runq->argv->words->next;ap;ap = ap->next)
300 len+=1+strlen(ap->word);
301 cmdline = emalloc(len);
302 s = cmdline;
303 for(ap = runq->argv->words->next;ap;ap = ap->next){
304 for(t = ap->word;*t;) *s++=*t++;
305 *s++=' ';
306 }
307 s[-1]='\n';
308 poplist();
309 execcmds(opencore(cmdline, len));
310 efree(cmdline);
311 }
312 union code dotcmds[14];
313
314 void
315 execdot(void)
316 {
317 int iflag = 0;
318 int fd;
319 list *av;
320 thread *p = runq;
321 char *zero;
322 static int first = 1;
323 char file[512];
324 word *path;
325 if(first){
326 dotcmds[0].i = 1;
327 dotcmds[1].f = Xmark;
328 dotcmds[2].f = Xword;
329 dotcmds[3].s="0";
330 dotcmds[4].f = Xlocal;
331 dotcmds[5].f = Xmark;
332 dotcmds[6].f = Xword;
333 dotcmds[7].s="*";
334 dotcmds[8].f = Xlocal;
335 dotcmds[9].f = Xrdcmds;
336 dotcmds[10].f = Xunlocal;
337 dotcmds[11].f = Xunlocal;
338 dotcmds[12].f = Xreturn;
339 first = 0;
340 }
341 else
342 eflagok = 1;
343 popword();
344 if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
345 iflag = 1;
346 popword();
347 }
348 /* get input file */
349 if(p->argv->words==0){
350 Xerror1("Usage: . [-i] file [arg ...]");
351 return;
352 }
353 zero = strdup(p->argv->words->word);
354 popword();
355 fd=-1;
356 for(path = searchpath(zero);path;path = path->next){
357 strcpy(file, path->word);
358 if(file[0])
359 strcat(file, "/");
360 strcat(file, zero);
361 if((fd = open(file, 0))>=0) break;
362 if(strcmp(file, "/dev/stdin")==0){ /* for sun & u…
363 fd = Dup1(0);
364 if(fd>=0)
365 break;
366 }
367 }
368 if(fd<0){
369 pfmt(err, "%s: ", zero);
370 setstatus("can't open");
371 Xerror(".: can't open");
372 return;
373 }
374 /* set up for a new command loop */
375 start(dotcmds, 1, (struct var *)0);
376 pushredir(RCLOSE, fd, 0);
377 runq->cmdfile = zero;
378 runq->cmdfd = openfd(fd);
379 runq->iflag = iflag;
380 runq->iflast = 0;
381 /* push $* value */
382 pushlist();
383 runq->argv->words = p->argv->words;
384 /* free caller's copy of $* */
385 av = p->argv;
386 p->argv = av->next;
387 efree((char *)av);
388 /* push $0 value */
389 pushlist();
390 pushword(zero);
391 ndot++;
392 }
393
394 void
395 execflag(void)
396 {
397 char *letter, *val;
398 switch(count(runq->argv->words)){
399 case 2:
400 setstatus(flag[(uchar)runq->argv->words->next->word[0]]?…
401 break;
402 case 3:
403 letter = runq->argv->words->next->word;
404 val = runq->argv->words->next->next->word;
405 if(strlen(letter)==1){
406 if(strcmp(val, "+")==0){
407 flag[(uchar)letter[0]] = flagset;
408 break;
409 }
410 if(strcmp(val, "-")==0){
411 flag[(uchar)letter[0]] = 0;
412 break;
413 }
414 }
415 default:
416 Xerror1("Usage: flag [letter] [+-]");
417 return;
418 }
419 poplist();
420 }
421
422 void
423 execwhatis(void){ /* mildly wrong -- should fork before writing */
424 word *a, *b, *path;
425 var *v;
426 struct builtin *bp;
427 char file[512];
428 struct io out[1];
429 int found, sep;
430 a = runq->argv->words->next;
431 if(a==0){
432 Xerror1("Usage: whatis name ...");
433 return;
434 }
435 setstatus("");
436 out->fd = mapfd(1);
437 out->bufp = out->buf;
438 out->ebuf = &out->buf[NBUF];
439 out->strp = 0;
440 for(;a;a = a->next){
441 v = vlook(a->word);
442 if(v->val){
443 pfmt(out, "%s=", a->word);
444 if(v->val->next==0)
445 pfmt(out, "%q\n", v->val->word);
446 else{
447 sep='(';
448 for(b = v->val;b && b->word;b = b->next){
449 pfmt(out, "%c%q", sep, b->word);
450 sep=' ';
451 }
452 pfmt(out, ")\n");
453 }
454 found = 1;
455 }
456 else
457 found = 0;
458 v = gvlook(a->word);
459 if(v->fn)
460 pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].…
461 else{
462 for(bp = Builtin;bp->name;bp++)
463 if(strcmp(a->word, bp->name)==0){
464 pfmt(out, "builtin %s\n", a->wor…
465 break;
466 }
467 if(!bp->name){
468 for(path = searchpath(a->word);path;path…
469 strcpy(file, path->word);
470 if(file[0])
471 strcat(file, "/");
472 strcat(file, a->word);
473 if(Executable(file)){
474 pfmt(out, "%s\n", file);
475 break;
476 }
477 }
478 if(!path && !found){
479 pfmt(err, "%s: not found\n", a->…
480 setstatus("not found");
481 }
482 }
483 }
484 }
485 poplist();
486 flush(err);
487 }
488
489 void
490 execwait(void)
491 {
492 switch(count(runq->argv->words)){
493 default:
494 Xerror1("Usage: wait [pid]");
495 return;
496 case 2:
497 Waitfor(atoi(runq->argv->words->next->word), 0);
498 break;
499 case 1:
500 Waitfor(-1, 0);
501 break;
502 }
503 poplist();
504 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.