|
|
1.1 ! root 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: exitnext(void){ ! 13: union code *c=&runq->code[runq->pc]; ! 14: while(c->f==Xpopredir) c++; ! 15: return c->f==Xexit; ! 16: } ! 17: void Xsimple(void){ ! 18: word *a; ! 19: thread *p=runq; ! 20: var *v; ! 21: struct builtin *bp; ! 22: int pid; ! 23: globlist(); ! 24: a=runq->argv->words; ! 25: if(a==0){ ! 26: Xerror("empty argument list"); ! 27: return; ! 28: } ! 29: if(flag['x']) ! 30: pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */ ! 31: v=gvlook(a->word); ! 32: if(v->fn) ! 33: execfunc(v); ! 34: else{ ! 35: if(strcmp(a->word, "builtin")==0){ ! 36: if(count(a)==1){ ! 37: pfmt(err, "builtin: empty argument list\n"); ! 38: setstatus("empty arg list"); ! 39: poplist(); ! 40: return; ! 41: } ! 42: a=a->next; ! 43: popword(); ! 44: } ! 45: for(bp=Builtin;bp->name;bp++) ! 46: if(strcmp(a->word, bp->name)==0){ ! 47: (*bp->fnc)(); ! 48: return; ! 49: } ! 50: if(exitnext()){ ! 51: /* fork and wait is redundant */ ! 52: pushword("exec"); ! 53: execexec(); ! 54: Xexit(); ! 55: } ! 56: else{ ! 57: flush(err); ! 58: Updenv(); ! 59: switch(pid=fork()){ ! 60: case -1: ! 61: Xperror("try again"); ! 62: return; ! 63: case 0: ! 64: pushword("exec"); ! 65: execexec(); ! 66: Exit("can't exec"); ! 67: default: ! 68: poplist(); ! 69: /* interrupts don't get us out */ ! 70: while(Waitfor(pid, 1) < 0) ! 71: ; ! 72: } ! 73: } ! 74: } ! 75: } ! 76: struct word nullpath={ "", 0}; ! 77: void doredir(redir *rp) ! 78: { ! 79: if(rp){ ! 80: doredir(rp->next); ! 81: switch(rp->type){ ! 82: case ROPEN: ! 83: if(rp->from!=rp->to){ ! 84: Dup(rp->from, rp->to); ! 85: close(rp->from); ! 86: } ! 87: break; ! 88: case RDUP: Dup(rp->from, rp->to); break; ! 89: case RCLOSE: close(rp->from); break; ! 90: } ! 91: } ! 92: } ! 93: word *searchpath(char *w){ ! 94: word *path; ! 95: if(strncmp(w, "/", 1)==0 ! 96: || strncmp(w, "#", 1)==0 ! 97: || strncmp(w, "./", 2)==0 ! 98: || strncmp(w, "../", 3)==0 ! 99: || (path=vlook("path")->val)==0) ! 100: path=&nullpath; ! 101: return path; ! 102: } ! 103: void execexec(void){ ! 104: word *path; ! 105: popword(); /* "exec" */ ! 106: if(runq->argv->words==0){ ! 107: Xerror("empty argument list"); ! 108: return; ! 109: } ! 110: doredir(runq->redir); ! 111: Execute(runq->argv->words, searchpath(runq->argv->words->word)); ! 112: poplist(); ! 113: } ! 114: void execfunc(var *func) ! 115: { ! 116: word *starval; ! 117: popword(); ! 118: starval=runq->argv->words; ! 119: runq->argv->words=0; ! 120: poplist(); ! 121: start(func->fn, func->pc, (struct var *)0); ! 122: runq->local=newvar(strdup("*"), runq->local); ! 123: runq->local->val=starval; ! 124: runq->local->changed=1; ! 125: } ! 126: void execcd(void){ ! 127: word *a=runq->argv->words; ! 128: word *cdpath; ! 129: char dir[512]; ! 130: setstatus("can't cd"); ! 131: cdpath=vlook("cdpath")->val; ! 132: switch(count(a)){ ! 133: default: ! 134: pfmt(err, "Usage: cd [directory]\n"); ! 135: break; ! 136: case 2: ! 137: if(a->next->word[0]=='/' || cdpath==0) cdpath=&nullpath; ! 138: for(;cdpath;cdpath=cdpath->next){ ! 139: strcpy(dir, cdpath->word); ! 140: if(dir[0]) strcat(dir, "/"); ! 141: strcat(dir, a->next->word); ! 142: if(chdir(dir)>=0){ ! 143: if(strlen(cdpath->word) ! 144: && strcmp(cdpath->word, ".")!=0) ! 145: pfmt(err, "%s\n", dir); ! 146: setstatus(""); ! 147: break; ! 148: } ! 149: } ! 150: if(cdpath==0) pfmt(err, "Can't cd %s\n", a->next->word); ! 151: break; ! 152: case 1: ! 153: a=vlook("home")->val; ! 154: if(count(a)>=1){ ! 155: if(chdir(a->word)>=0) ! 156: setstatus(""); ! 157: else ! 158: pfmt(err, "Can't cd %s\n", a->word); ! 159: } ! 160: else ! 161: pfmt(err, "Can't cd -- $home empty\n"); ! 162: break; ! 163: } ! 164: poplist(); ! 165: } ! 166: void execexit(void){ ! 167: switch(count(runq->argv->words)){ ! 168: default: pfmt(err, "Usage: exit [status]\nExiting anyway\n"); ! 169: case 2: setstatus(runq->argv->words->next->word); ! 170: case 1: Xexit(); ! 171: } ! 172: } ! 173: void execshift(void){ ! 174: int n; ! 175: word *a; ! 176: var *star; ! 177: switch(count(runq->argv->words)){ ! 178: default: ! 179: pfmt(err, "Usage: shift [n]\n"); ! 180: setstatus("shift usage"); ! 181: poplist(); ! 182: return; ! 183: case 2: n=atoi(runq->argv->words->next->word); break; ! 184: case 1: n=1; break; ! 185: } ! 186: star=vlook("*"); ! 187: for(;n && star->val;--n){ ! 188: a=star->val->next; ! 189: efree(star->val->word); ! 190: efree((char *)star->val); ! 191: star->val=a; ! 192: star->changed=1; ! 193: } ! 194: setstatus(""); ! 195: poplist(); ! 196: } ! 197: int octal(char *s) ! 198: { ! 199: int n=0; ! 200: while(*s==' ' || *s=='\t' || *s=='\n') s++; ! 201: while('0'<=*s && *s<='7') n=n*8+*s++-'0'; ! 202: return n; ! 203: } ! 204: int mapfd(int fd) ! 205: { ! 206: redir *rp; ! 207: for(rp=runq->redir;rp;rp=rp->next){ ! 208: switch(rp->type){ ! 209: case RCLOSE: ! 210: if(rp->from==fd) fd=-1; ! 211: break; ! 212: case RDUP: ! 213: case ROPEN: ! 214: if(rp->to==fd) fd=rp->from; ! 215: break; ! 216: } ! 217: } ! 218: return fd; ! 219: } ! 220: union code rdcmds[4]; ! 221: void execcmds(io *f) ! 222: { ! 223: static int first=1; ! 224: if(first){ ! 225: rdcmds[0].i=1; ! 226: rdcmds[1].f=Xrdcmds; ! 227: rdcmds[2].f=Xreturn; ! 228: first=0; ! 229: } ! 230: start(rdcmds, 1, runq->local); ! 231: runq->cmdfd=f; ! 232: runq->iflast=0; ! 233: } ! 234: void execeval(void){ ! 235: char *cmdline, *s, *t; ! 236: int len=0; ! 237: word *ap; ! 238: if(count(runq->argv->words)<=1){ ! 239: Xerror("Usage: eval cmd ..."); ! 240: return; ! 241: } ! 242: eflagok=1; ! 243: for(ap=runq->argv->words->next;ap;ap=ap->next) ! 244: len+=1+strlen(ap->word); ! 245: cmdline=emalloc(len); ! 246: s=cmdline; ! 247: for(ap=runq->argv->words->next;ap;ap=ap->next){ ! 248: for(t=ap->word;*t;) *s++=*t++; ! 249: *s++=' '; ! 250: } ! 251: s[-1]='\n'; ! 252: poplist(); ! 253: execcmds(opencore(cmdline, len)); ! 254: efree(cmdline); ! 255: } ! 256: union code dotcmds[14]; ! 257: void execdot(void){ ! 258: int iflag=0; ! 259: int fd; ! 260: list *av; ! 261: thread *p=runq; ! 262: char *zero; ! 263: static int first=1; ! 264: char file[512]; ! 265: word *path; ! 266: if(first){ ! 267: dotcmds[0].i=1; ! 268: dotcmds[1].f=Xmark; ! 269: dotcmds[2].f=Xword; ! 270: dotcmds[3].s="0"; ! 271: dotcmds[4].f=Xlocal; ! 272: dotcmds[5].f=Xmark; ! 273: dotcmds[6].f=Xword; ! 274: dotcmds[7].s="*"; ! 275: dotcmds[8].f=Xlocal; ! 276: dotcmds[9].f=Xrdcmds; ! 277: dotcmds[10].f=Xunlocal; ! 278: dotcmds[11].f=Xunlocal; ! 279: dotcmds[12].f=Xreturn; ! 280: first=0; ! 281: } ! 282: else ! 283: eflagok=1; ! 284: popword(); ! 285: if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){ ! 286: iflag=1; ! 287: popword(); ! 288: } ! 289: /* get input file */ ! 290: if(p->argv->words==0){ ! 291: Xerror("Usage: . [-i] file [arg ...]"); ! 292: return; ! 293: } ! 294: zero=strdup(p->argv->words->word); ! 295: popword(); ! 296: strcpy(file, "**No file name**"); ! 297: for(path=searchpath(zero);path;path=path->next){ ! 298: strcpy(file, path->word); ! 299: if(file[0]) strcat(file, "/"); ! 300: strcat(file, zero); ! 301: if((fd=open(file, 0))>=0) break; ! 302: if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */ ! 303: fd=Dup1(0); ! 304: if(fd>=0) break; ! 305: } ! 306: } ! 307: if(fd<0){ ! 308: Xperror(file); ! 309: return; ! 310: } ! 311: /* set up for a new command loop */ ! 312: start(dotcmds, 1, (struct var *)0); ! 313: pushredir(RCLOSE, fd, 0); ! 314: runq->cmdfile=zero; ! 315: runq->cmdfd=openfd(fd); ! 316: runq->iflag=iflag; ! 317: runq->iflast=0; ! 318: /* push $* value */ ! 319: pushlist(); ! 320: runq->argv->words=p->argv->words; ! 321: /* free caller's copy of $* */ ! 322: av=p->argv; ! 323: p->argv=av->next; ! 324: efree((char *)av); ! 325: /* push $0 value */ ! 326: pushlist(); ! 327: pushword(zero); ! 328: ndot++; ! 329: } ! 330: void execflag(void){ ! 331: char *letter, *val; ! 332: switch(count(runq->argv->words)){ ! 333: case 2: ! 334: setstatus(flag[runq->argv->words->next->word[0]]?"":"flag not set"); ! 335: break; ! 336: case 3: ! 337: letter=runq->argv->words->next->word; ! 338: val=runq->argv->words->next->next->word; ! 339: if(strlen(letter)==1){ ! 340: if(strcmp(val, "+")==0){ ! 341: flag[letter[0]]=flagset; ! 342: break; ! 343: } ! 344: if(strcmp(val, "-")==0){ ! 345: flag[letter[0]]=0; ! 346: break; ! 347: } ! 348: } ! 349: default: ! 350: Xerror("Usage: flag [letter] [+-]"); ! 351: return; ! 352: } ! 353: poplist(); ! 354: } ! 355: void execwhatis(void){ /* mildly wrong -- should fork before writing */ ! 356: word *a, *b, *path; ! 357: var *v; ! 358: struct builtin *bp; ! 359: char file[512]; ! 360: struct io out[1]; ! 361: int found, sep; ! 362: a=runq->argv->words->next; ! 363: if(a==0){ ! 364: Xerror("Usage: whatis name ..."); ! 365: return; ! 366: } ! 367: setstatus(""); ! 368: out->fd=mapfd(1); ! 369: out->bufp=out->buf; ! 370: out->ebuf=&out->buf[NBUF]; ! 371: out->strp=0; ! 372: for(;a;a=a->next){ ! 373: v=vlook(a->word); ! 374: if(v->val){ ! 375: pfmt(out, "%s=", a->word); ! 376: if(v->val->next==0) ! 377: pfmt(out, "%q\n", v->val->word); ! 378: else{ ! 379: sep='('; ! 380: for(b=v->val;b && b->word;b=b->next){ ! 381: pfmt(out, "%c%q", sep, b->word); ! 382: sep=' '; ! 383: } ! 384: pfmt(out, ")\n"); ! 385: } ! 386: found=1; ! 387: } ! 388: else ! 389: found=0; ! 390: v=gvlook(a->word); ! 391: if(v->fn) pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s); ! 392: else{ ! 393: for(bp=Builtin;bp->name;bp++) ! 394: if(strcmp(a->word, bp->name)==0){ ! 395: pfmt(out, "builtin %s\n", a->word); ! 396: break; ! 397: } ! 398: if(!bp->name){ ! 399: for(path=searchpath(a->word);path;path=path->next){ ! 400: strcpy(file, path->word); ! 401: if(file[0]) strcat(file, "/"); ! 402: strcat(file, a->word); ! 403: if(Executable(file)){ ! 404: pfmt(out, "%s\n", file); ! 405: break; ! 406: } ! 407: } ! 408: if(!path && !found){ ! 409: pfmt(err, "%s: not found\n", a->word); ! 410: setstatus("not found"); ! 411: } ! 412: } ! 413: } ! 414: } ! 415: poplist(); ! 416: flush(err); ! 417: } ! 418: void execwait(void){ ! 419: switch(count(runq->argv->words)){ ! 420: default: Xerror("Usage: wait [pid]"); return; ! 421: case 2: Waitfor(atoi(runq->argv->words->next->word), 0); break; ! 422: case 1: Waitfor(-1, 0); break; ! 423: } ! 424: poplist(); ! 425: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.