exec.c 16 KB

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