compiling.on.unix 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866
  1. From geoff@collyer.net Fri Dec 19 01:21:40 EST 2003
  2. Received: from plan9.cs.bell-labs.com ([135.104.9.2]) by plan9; Fri Dec 19 01:21:39 EST 2003
  3. Received: from collyer.net ([63.192.14.226]) by plan9; Fri Dec 19 01:21:35 EST 2003
  4. Message-ID: <c790d8b1e06b3918ad2c7848a3ae0ec7@collyer.net>
  5. subject: rc on unix, part 1
  6. From: Geoff Collyer <geoff@collyer.net>
  7. Date: Thu, 18 Dec 2003 22:21:33 -0800
  8. To: presotto@plan9.bell-labs.com, rsc@plan9.bell-labs.com, geoff@collyer.net
  9. MIME-Version: 1.0
  10. Content-Type: text/plain; charset="US-ASCII"
  11. Content-Transfer-Encoding: 7bit
  12. I got /sys/src/cmd/rc to compile under APE (in preparation for moving it
  13. to Unixes) with the following changed files. I cadged some include files
  14. from rsc but had to edit lib9.h slightly. I'll send the include files
  15. separately. I can't tell if it works yet, but it does complain about
  16. /usr/lib/rcmain being absent when I start it. Oh, and I haven't yet
  17. simulated the effect of the OCEXEC bit.
  18. # To unbundle, run this file
  19. echo mkfile
  20. sed 's/^X//' >mkfile <<'!'
  21. X</$objtype/mkfile
  22. TARG=rc
  23. COMMONOFILES=\
  24. X code.$O\
  25. X exec.$O\
  26. X getflags.$O\
  27. X glob.$O\
  28. X here.$O\
  29. X io.$O\
  30. X lex.$O\
  31. X pcmd.$O\
  32. X pfnc.$O\
  33. X simple.$O\
  34. X subr.$O\
  35. X trap.$O\
  36. X tree.$O\
  37. X var.$O\
  38. X havefork.$O\
  39. PLAN9OFILES=plan9.$O\
  40. UNIXOFILES=unix.$O\
  41. OFILES=$COMMONOFILES $UNIXOFILES y.tab.$O
  42. HFILES=rc.h\
  43. X x.tab.h\
  44. X io.h\
  45. X exec.h\
  46. X fns.h\
  47. YFILES=syn.y
  48. BIN=/$objtype/bin
  49. UPDATE=\
  50. X mkfile\
  51. X $HFILES\
  52. X ${COMMONOFILES:%.$O=%.c}\
  53. X ${UNIXOFILES:%.$O=%.c}\
  54. X ${PLAN9OFILES:%.$O=%.c}\
  55. X $YFILES\
  56. X ${TARG:%=/386/bin/%}\
  57. CC=pcc -c -B -I../include
  58. LD=pcc
  59. X</sys/src/cmd/mkone
  60. x.tab.h: y.tab.h
  61. X cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h
  62. clean:V:
  63. X rm -f [$OS].out *.[$OS] [xy].tab.? y.debug $TARG
  64. regress: $O.out
  65. X cd test
  66. X mk
  67. unregress:V:
  68. X for(test in test/*.test) rc $test >$test.out
  69. listing:
  70. X pr mkfile $HFILES $FILES $FILES9 $FILESUNIX $YFILES|lp -du
  71. !
  72. echo simple.c
  73. sed 's/^X//' >simple.c <<'!'
  74. X/*
  75. X * Maybe `simple' is a misnomer.
  76. X */
  77. X#include "rc.h"
  78. X#include "getflags.h"
  79. X#include "exec.h"
  80. X#include "io.h"
  81. X#include "fns.h"
  82. X/*
  83. X * Search through the following code to see if we're just going to exit.
  84. X */
  85. exitnext(void){
  86. X union code *c=&runq->code[runq->pc];
  87. X while(c->f==Xpopredir) c++;
  88. X return c->f==Xexit;
  89. X}
  90. void
  91. XXsimple(void)
  92. X{
  93. X word *a;
  94. X thread *p = runq;
  95. X var *v;
  96. X struct builtin *bp;
  97. X int pid;
  98. X globlist();
  99. X a = runq->argv->words;
  100. X if(a==0){
  101. X Xerror1("empty argument list");
  102. X return;
  103. X }
  104. X if(flag['x'])
  105. X pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
  106. X v = gvlook(a->word);
  107. X if(v->fn)
  108. X execfunc(v);
  109. X else{
  110. X if(strcmp(a->word, "builtin")==0){
  111. X if(count(a)==1){
  112. X pfmt(err, "builtin: empty argument list\n");
  113. X setstatus("empty arg list");
  114. X poplist();
  115. X return;
  116. X }
  117. X a = a->next;
  118. X popword();
  119. X }
  120. X for(bp = Builtin;bp->name;bp++)
  121. X if(strcmp(a->word, bp->name)==0){
  122. X (*bp->fnc)();
  123. X return;
  124. X }
  125. X if(exitnext()){
  126. X /* fork and wait is redundant */
  127. X pushword("exec");
  128. X execexec();
  129. X Xexit();
  130. X }
  131. X else{
  132. X flush(err);
  133. X Updenv(); /* necessary so changes don't go out again */
  134. X if((pid = execforkexec()) < 0){
  135. X Xerror("try again");
  136. X return;
  137. X }
  138. X /* interrupts don't get us out */
  139. X poplist();
  140. X while(Waitfor(pid, 1) < 0)
  141. X ;
  142. X }
  143. X }
  144. X}
  145. struct word nullpath = { "", 0};
  146. void
  147. doredir(redir *rp)
  148. X{
  149. X if(rp){
  150. X doredir(rp->next);
  151. X switch(rp->type){
  152. X case ROPEN:
  153. X if(rp->from!=rp->to){
  154. X Dup(rp->from, rp->to);
  155. X close(rp->from);
  156. X }
  157. X break;
  158. X case RDUP:
  159. X Dup(rp->from, rp->to);
  160. X break;
  161. X case RCLOSE:
  162. X close(rp->from);
  163. X break;
  164. X }
  165. X }
  166. X}
  167. word*
  168. searchpath(char *w)
  169. X{
  170. X word *path;
  171. X if(strncmp(w, "/", 1)==0
  172. X || strncmp(w, "#", 1)==0
  173. X || strncmp(w, "./", 2)==0
  174. X || strncmp(w, "../", 3)==0
  175. X || (path = vlook("path")->val)==0)
  176. X path=&nullpath;
  177. X return path;
  178. X}
  179. void
  180. execexec(void)
  181. X{
  182. X popword(); /* "exec" */
  183. X if(runq->argv->words==0){
  184. X Xerror1("empty argument list");
  185. X return;
  186. X }
  187. X doredir(runq->redir);
  188. X Execute(runq->argv->words, searchpath(runq->argv->words->word));
  189. X poplist();
  190. X}
  191. void
  192. execfunc(var *func)
  193. X{
  194. X word *starval;
  195. X popword();
  196. X starval = runq->argv->words;
  197. X runq->argv->words = 0;
  198. X poplist();
  199. X start(func->fn, func->pc, (struct var *)0);
  200. X runq->local = newvar(strdup("*"), runq->local);
  201. X runq->local->val = starval;
  202. X runq->local->changed = 1;
  203. X}
  204. int
  205. dochdir(char *word)
  206. X{
  207. X /* report to /dev/wdir if it exists and we're interactive */
  208. X static int wdirfd = -2;
  209. X if(chdir(word)<0) return -1;
  210. X if(flag['i']!=0){
  211. X if(wdirfd==-2) /* try only once */
  212. X /* TODO: arrange close-on-exec on Unix */
  213. X wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
  214. X if(wdirfd>=0)
  215. X write(wdirfd, word, strlen(word));
  216. X }
  217. X return 1;
  218. X}
  219. void
  220. execcd(void)
  221. X{
  222. X word *a = runq->argv->words;
  223. X word *cdpath;
  224. X char dir[512];
  225. X setstatus("can't cd");
  226. X cdpath = vlook("cdpath")->val;
  227. X switch(count(a)){
  228. X default:
  229. X pfmt(err, "Usage: cd [directory]\n");
  230. X break;
  231. X case 2:
  232. X if(a->next->word[0]=='/' || cdpath==0)
  233. X cdpath=&nullpath;
  234. X for(;cdpath;cdpath = cdpath->next){
  235. X strcpy(dir, cdpath->word);
  236. X if(dir[0])
  237. X strcat(dir, "/");
  238. X strcat(dir, a->next->word);
  239. X if(dochdir(dir)>=0){
  240. X if(strlen(cdpath->word)
  241. X && strcmp(cdpath->word, ".")!=0)
  242. X pfmt(err, "%s\n", dir);
  243. X setstatus("");
  244. X break;
  245. X }
  246. X }
  247. X if(cdpath==0)
  248. X pfmt(err, "Can't cd %s: %r\n", a->next->word);
  249. X break;
  250. X case 1:
  251. X a = vlook("home")->val;
  252. X if(count(a)>=1){
  253. X if(dochdir(a->word)>=0)
  254. X setstatus("");
  255. X else
  256. X pfmt(err, "Can't cd %s: %r\n", a->word);
  257. X }
  258. X else
  259. X pfmt(err, "Can't cd -- $home empty\n");
  260. X break;
  261. X }
  262. X poplist();
  263. X}
  264. void
  265. execexit(void)
  266. X{
  267. X switch(count(runq->argv->words)){
  268. X default:
  269. X pfmt(err, "Usage: exit [status]\nExiting anyway\n");
  270. X case 2:
  271. X setstatus(runq->argv->words->next->word);
  272. X case 1: Xexit();
  273. X }
  274. X}
  275. void
  276. execshift(void)
  277. X{
  278. X int n;
  279. X word *a;
  280. X var *star;
  281. X switch(count(runq->argv->words)){
  282. X default:
  283. X pfmt(err, "Usage: shift [n]\n");
  284. X setstatus("shift usage");
  285. X poplist();
  286. X return;
  287. X case 2:
  288. X n = atoi(runq->argv->words->next->word);
  289. X break;
  290. X case 1:
  291. X n = 1;
  292. X break;
  293. X }
  294. X star = vlook("*");
  295. X for(;n && star->val;--n){
  296. X a = star->val->next;
  297. X efree(star->val->word);
  298. X efree((char *)star->val);
  299. X star->val = a;
  300. X star->changed = 1;
  301. X }
  302. X setstatus("");
  303. X poplist();
  304. X}
  305. int
  306. octal(char *s)
  307. X{
  308. X int n = 0;
  309. X while(*s==' ' || *s=='\t' || *s=='\n') s++;
  310. X while('0'<=*s && *s<='7') n = n*8+*s++-'0';
  311. X return n;
  312. X}
  313. int
  314. mapfd(int fd)
  315. X{
  316. X redir *rp;
  317. X for(rp = runq->redir;rp;rp = rp->next){
  318. X switch(rp->type){
  319. X case RCLOSE:
  320. X if(rp->from==fd)
  321. X fd=-1;
  322. X break;
  323. X case RDUP:
  324. X case ROPEN:
  325. X if(rp->to==fd)
  326. X fd = rp->from;
  327. X break;
  328. X }
  329. X }
  330. X return fd;
  331. X}
  332. union code rdcmds[4];
  333. void
  334. execcmds(io *f)
  335. X{
  336. X static int first = 1;
  337. X if(first){
  338. X rdcmds[0].i = 1;
  339. X rdcmds[1].f = Xrdcmds;
  340. X rdcmds[2].f = Xreturn;
  341. X first = 0;
  342. X }
  343. X start(rdcmds, 1, runq->local);
  344. X runq->cmdfd = f;
  345. X runq->iflast = 0;
  346. X}
  347. void
  348. execeval(void)
  349. X{
  350. X char *cmdline, *s, *t;
  351. X int len = 0;
  352. X word *ap;
  353. X if(count(runq->argv->words)<=1){
  354. X Xerror1("Usage: eval cmd ...");
  355. X return;
  356. X }
  357. X eflagok = 1;
  358. X for(ap = runq->argv->words->next;ap;ap = ap->next)
  359. X len+=1+strlen(ap->word);
  360. X cmdline = emalloc(len);
  361. X s = cmdline;
  362. X for(ap = runq->argv->words->next;ap;ap = ap->next){
  363. X for(t = ap->word;*t;) *s++=*t++;
  364. X *s++=' ';
  365. X }
  366. X s[-1]='\n';
  367. X poplist();
  368. X execcmds(opencore(cmdline, len));
  369. X efree(cmdline);
  370. X}
  371. union code dotcmds[14];
  372. void
  373. execdot(void)
  374. X{
  375. X int iflag = 0;
  376. X int fd;
  377. X list *av;
  378. X thread *p = runq;
  379. X char *zero;
  380. X static int first = 1;
  381. X char file[512];
  382. X word *path;
  383. X if(first){
  384. X dotcmds[0].i = 1;
  385. X dotcmds[1].f = Xmark;
  386. X dotcmds[2].f = Xword;
  387. X dotcmds[3].s="0";
  388. X dotcmds[4].f = Xlocal;
  389. X dotcmds[5].f = Xmark;
  390. X dotcmds[6].f = Xword;
  391. X dotcmds[7].s="*";
  392. X dotcmds[8].f = Xlocal;
  393. X dotcmds[9].f = Xrdcmds;
  394. X dotcmds[10].f = Xunlocal;
  395. X dotcmds[11].f = Xunlocal;
  396. X dotcmds[12].f = Xreturn;
  397. X first = 0;
  398. X }
  399. X else
  400. X eflagok = 1;
  401. X popword();
  402. X if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
  403. X iflag = 1;
  404. X popword();
  405. X }
  406. X /* get input file */
  407. X if(p->argv->words==0){
  408. X Xerror1("Usage: . [-i] file [arg ...]");
  409. X return;
  410. X }
  411. X zero = strdup(p->argv->words->word);
  412. X popword();
  413. X fd=-1;
  414. X for(path = searchpath(zero);path;path = path->next){
  415. X strcpy(file, path->word);
  416. X if(file[0])
  417. X strcat(file, "/");
  418. X strcat(file, zero);
  419. X if((fd = open(file, 0))>=0) break;
  420. X if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
  421. X fd = Dup1(0);
  422. X if(fd>=0)
  423. X break;
  424. X }
  425. X }
  426. X if(fd<0){
  427. X pfmt(err, "%s: ", zero);
  428. X setstatus("can't open");
  429. X Xerror(".: can't open");
  430. X return;
  431. X }
  432. X /* set up for a new command loop */
  433. X start(dotcmds, 1, (struct var *)0);
  434. X pushredir(RCLOSE, fd, 0);
  435. X runq->cmdfile = zero;
  436. X runq->cmdfd = openfd(fd);
  437. X runq->iflag = iflag;
  438. X runq->iflast = 0;
  439. X /* push $* value */
  440. X pushlist();
  441. X runq->argv->words = p->argv->words;
  442. X /* free caller's copy of $* */
  443. X av = p->argv;
  444. X p->argv = av->next;
  445. X efree((char *)av);
  446. X /* push $0 value */
  447. X pushlist();
  448. X pushword(zero);
  449. X ndot++;
  450. X}
  451. void
  452. execflag(void)
  453. X{
  454. X char *letter, *val;
  455. X switch(count(runq->argv->words)){
  456. X case 2:
  457. X setstatus(flag[runq->argv->words->next->word[0]]?"":"flag not set");
  458. X break;
  459. X case 3:
  460. X letter = runq->argv->words->next->word;
  461. X val = runq->argv->words->next->next->word;
  462. X if(strlen(letter)==1){
  463. X if(strcmp(val, "+")==0){
  464. X flag[letter[0]] = flagset;
  465. X break;
  466. X }
  467. X if(strcmp(val, "-")==0){
  468. X flag[letter[0]] = 0;
  469. X break;
  470. X }
  471. X }
  472. X default:
  473. X Xerror1("Usage: flag [letter] [+-]");
  474. X return;
  475. X }
  476. X poplist();
  477. X}
  478. void
  479. execwhatis(void){ /* mildly wrong -- should fork before writing */
  480. X word *a, *b, *path;
  481. X var *v;
  482. X struct builtin *bp;
  483. X char file[512];
  484. X struct io out[1];
  485. X int found, sep;
  486. X a = runq->argv->words->next;
  487. X if(a==0){
  488. X Xerror1("Usage: whatis name ...");
  489. X return;
  490. X }
  491. X setstatus("");
  492. X out->fd = mapfd(1);
  493. X out->bufp = out->buf;
  494. X out->ebuf = &out->buf[NBUF];
  495. X out->strp = 0;
  496. X for(;a;a = a->next){
  497. X v = vlook(a->word);
  498. X if(v->val){
  499. X pfmt(out, "%s=", a->word);
  500. X if(v->val->next==0)
  501. X pfmt(out, "%q\n", v->val->word);
  502. X else{
  503. X sep='(';
  504. X for(b = v->val;b && b->word;b = b->next){
  505. X pfmt(out, "%c%q", sep, b->word);
  506. X sep=' ';
  507. X }
  508. X pfmt(out, ")\n");
  509. X }
  510. X found = 1;
  511. X }
  512. X else
  513. X found = 0;
  514. X v = gvlook(a->word);
  515. X if(v->fn)
  516. X pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
  517. X else{
  518. X for(bp = Builtin;bp->name;bp++)
  519. X if(strcmp(a->word, bp->name)==0){
  520. X pfmt(out, "builtin %s\n", a->word);
  521. X break;
  522. X }
  523. X if(!bp->name){
  524. X for(path = searchpath(a->word);path;path = path->next){
  525. X strcpy(file, path->word);
  526. X if(file[0])
  527. X strcat(file, "/");
  528. X strcat(file, a->word);
  529. X if(Executable(file)){
  530. X pfmt(out, "%s\n", file);
  531. X break;
  532. X }
  533. X }
  534. X if(!path && !found){
  535. X pfmt(err, "%s: not found\n", a->word);
  536. X setstatus("not found");
  537. X }
  538. X }
  539. X }
  540. X }
  541. X poplist();
  542. X flush(err);
  543. X}
  544. void
  545. execwait(void)
  546. X{
  547. X switch(count(runq->argv->words)){
  548. X default:
  549. X Xerror1("Usage: wait [pid]");
  550. X return;
  551. X case 2:
  552. X Waitfor(atoi(runq->argv->words->next->word), 0);
  553. X break;
  554. X case 1:
  555. X Waitfor(-1, 0);
  556. X break;
  557. X }
  558. X poplist();
  559. X}
  560. !
  561. echo havefork.c
  562. sed 's/^X//' >havefork.c <<'!'
  563. X#include "rc.h"
  564. X#include "getflags.h"
  565. X#include "exec.h"
  566. X#include "io.h"
  567. X#include "fns.h"
  568. int havefork = 1;
  569. void
  570. XXasync(void)
  571. X{
  572. X int null = open("/dev/null", 0);
  573. X int pid;
  574. X char npid[10];
  575. X if(null<0){
  576. X Xerror("Can't open /dev/null\n");
  577. X return;
  578. X }
  579. X#ifdef Unix
  580. X pid = fork();
  581. X#else
  582. X pid = rfork(RFFDG|RFPROC|RFNOTEG);
  583. X#endif
  584. X switch(pid){
  585. X case -1:
  586. X close(null);
  587. X Xerror("try again");
  588. X break;
  589. X case 0:
  590. X pushredir(ROPEN, null, 0);
  591. X start(runq->code, runq->pc+1, runq->local);
  592. X runq->ret = 0;
  593. X break;
  594. X default:
  595. X close(null);
  596. X runq->pc = runq->code[runq->pc].i;
  597. X inttoascii(npid, pid);
  598. X setvar("apid", newword(npid, (word *)0));
  599. X break;
  600. X }
  601. X}
  602. void
  603. XXpipe(void)
  604. X{
  605. X struct thread *p = runq;
  606. X int pc = p->pc, forkid;
  607. X int lfd = p->code[pc++].i;
  608. X int rfd = p->code[pc++].i;
  609. X int pfd[2];
  610. X if(pipe(pfd)<0){
  611. X Xerror("can't get pipe");
  612. X return;
  613. X }
  614. X switch(forkid = fork()){
  615. X case -1:
  616. X Xerror("try again");
  617. X break;
  618. X case 0:
  619. X start(p->code, pc+2, runq->local);
  620. X runq->ret = 0;
  621. X close(pfd[PRD]);
  622. X pushredir(ROPEN, pfd[PWR], lfd);
  623. X break;
  624. X default:
  625. X start(p->code, p->code[pc].i, runq->local);
  626. X close(pfd[PWR]);
  627. X pushredir(ROPEN, pfd[PRD], rfd);
  628. X p->pc = p->code[pc+1].i;
  629. X p->pid = forkid;
  630. X break;
  631. X }
  632. X}
  633. X/*
  634. X * Who should wait for the exit from the fork?
  635. X */
  636. void
  637. XXbackq(void)
  638. X{
  639. X char wd[8193];
  640. X int c;
  641. X char *s, *ewd=&wd[8192], *stop;
  642. X struct io *f;
  643. X var *ifs = vlook("ifs");
  644. X word *v, *nextv;
  645. X int pfd[2];
  646. X int pid;
  647. X stop = ifs->val?ifs->val->word:"";
  648. X if(pipe(pfd)<0){
  649. X Xerror("can't make pipe");
  650. X return;
  651. X }
  652. X switch(pid = fork()){
  653. X case -1:
  654. X Xerror("try again");
  655. X close(pfd[PRD]);
  656. X close(pfd[PWR]);
  657. X return;
  658. X case 0:
  659. X close(pfd[PRD]);
  660. X start(runq->code, runq->pc+1, runq->local);
  661. X pushredir(ROPEN, pfd[PWR], 1);
  662. X return;
  663. X default:
  664. X close(pfd[PWR]);
  665. X f = openfd(pfd[PRD]);
  666. X s = wd;
  667. X v = 0;
  668. X while((c = rchr(f))!=EOF){
  669. X if(strchr(stop, c) || s==ewd){
  670. X if(s!=wd){
  671. X *s='\0';
  672. X v = newword(wd, v);
  673. X s = wd;
  674. X }
  675. X }
  676. X else *s++=c;
  677. X }
  678. X if(s!=wd){
  679. X *s='\0';
  680. X v = newword(wd, v);
  681. X }
  682. X closeio(f);
  683. X Waitfor(pid, 0);
  684. X /* v points to reversed arglist -- reverse it onto argv */
  685. X while(v){
  686. X nextv = v->next;
  687. X v->next = runq->argv->words;
  688. X runq->argv->words = v;
  689. X v = nextv;
  690. X }
  691. X runq->pc = runq->code[runq->pc].i;
  692. X return;
  693. X }
  694. X}
  695. void
  696. XXpipefd(void)
  697. X{
  698. X struct thread *p = runq;
  699. X int pc = p->pc;
  700. X char name[40];
  701. X int pfd[2];
  702. X int sidefd, mainfd;
  703. X if(pipe(pfd)<0){
  704. X Xerror("can't get pipe");
  705. X return;
  706. X }
  707. X if(p->code[pc].i==READ){
  708. X sidefd = pfd[PWR];
  709. X mainfd = pfd[PRD];
  710. X }
  711. X else{
  712. X sidefd = pfd[PRD];
  713. X mainfd = pfd[PWR];
  714. X }
  715. X switch(fork()){
  716. X case -1:
  717. X Xerror("try again");
  718. X break;
  719. X case 0:
  720. X start(p->code, pc+2, runq->local);
  721. X close(mainfd);
  722. X pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
  723. X runq->ret = 0;
  724. X break;
  725. X default:
  726. X close(sidefd);
  727. X pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
  728. X strcpy(name, Fdprefix);
  729. X inttoascii(name+strlen(name), mainfd);
  730. X pushword(name);
  731. X p->pc = p->code[pc+1].i;
  732. X break;
  733. X }
  734. X}
  735. void
  736. XXsubshell(void)
  737. X{
  738. X int pid;
  739. X switch(pid = fork()){
  740. X case -1:
  741. X Xerror("try again");
  742. X break;
  743. X case 0:
  744. X start(runq->code, runq->pc+1, runq->local);
  745. X runq->ret = 0;
  746. X break;
  747. X default:
  748. X Waitfor(pid, 1);
  749. X runq->pc = runq->code[runq->pc].i;
  750. X break;
  751. X }
  752. X}
  753. int
  754. execforkexec(void)
  755. X{
  756. X int pid;
  757. X int n;
  758. X char buf[ERRMAX];
  759. X switch(pid = fork()){
  760. X case -1:
  761. X return -1;
  762. X case 0:
  763. X pushword("exec");
  764. X execexec();
  765. X strcpy(buf, "can't exec: ");
  766. X n = strlen(buf);
  767. X errstr(buf+n, ERRMAX-n);
  768. X Exit(buf);
  769. X }
  770. X return pid;
  771. X}
  772. !
  773. echo rc.h
  774. sed 's/^X//' >rc.h <<'!'
  775. X/*
  776. X * Plan9 is defined for plan 9
  777. X * V9 is defined for 9th edition
  778. X * Sun is defined for sun-os
  779. X * Please don't litter the code with ifdefs. The three below should be enough.
  780. X */
  781. X#define Unix
  782. X#ifdef Plan9
  783. X#include <u.h>
  784. X#include <libc.h>
  785. X#define NSIG 32
  786. X#define SIGINT 2
  787. X#define SIGQUIT 3
  788. X#endif
  789. X#ifdef Unix
  790. X#define _POSIX_SOURCE
  791. X#define _BSD_EXTENSION
  792. X#include <stdlib.h>
  793. X#include <stdarg.h>
  794. X#include <string.h>
  795. X#include <unistd.h>
  796. X#include <fcntl.h>
  797. X#include <lib9.h>
  798. X#include <signal.h>
  799. X#endif
  800. X#ifndef ERRMAX
  801. X#define ERRMAX 128
  802. X#endif
  803. X#define YYMAXDEPTH 500
  804. X#ifndef PAREN
  805. X#include "x.tab.h"
  806. X#endif
  807. typedef struct tree tree;
  808. typedef struct word word;
  809. typedef struct io io;
  810. typedef union code code;
  811. typedef struct var var;
  812. typedef struct list list;
  813. typedef struct redir redir;
  814. typedef struct thread thread;
  815. typedef struct builtin builtin;
  816. struct tree{
  817. X int type;
  818. X int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */
  819. X char *str;
  820. X int quoted;
  821. X int iskw;
  822. X tree *child[3];
  823. X tree *next;
  824. X};
  825. tree *newtree(void);
  826. tree *token(char*, int), *klook(char*), *tree1(int, tree*);
  827. tree *tree2(int, tree*, tree*), *tree3(int, tree*, tree*, tree*);
  828. tree *mung1(tree*, tree*), *mung2(tree*, tree*, tree*);
  829. tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*);
  830. tree *simplemung(tree*), *heredoc(tree*);
  831. void freetree(tree*);
  832. tree *cmdtree;
  833. X/*
  834. X * The first word of any code vector is a reference count.
  835. X * Always create a new reference to a code vector by calling codecopy(.).
  836. X * Always call codefree(.) when deleting a reference.
  837. X */
  838. union code{
  839. X void (*f)(void);
  840. X int i;
  841. X char *s;
  842. X};
  843. char *promptstr;
  844. int doprompt;
  845. X#define NTOK 8192
  846. char tok[NTOK];
  847. X#define APPEND 1
  848. X#define WRITE 2
  849. X#define READ 3
  850. X#define HERE 4
  851. X#define DUPFD 5
  852. X#define CLOSE 6
  853. struct var{
  854. X char *name; /* ascii name */
  855. X word *val; /* value */
  856. X int changed;
  857. X code *fn; /* pointer to function's code vector */
  858. X int fnchanged;
  859. X int pc; /* pc of start of function */
  860. X var *next; /* next on hash or local list */
  861. X};
  862. var *vlook(char*), *gvlook(char*), *newvar(char*, var*);
  863. X#define NVAR 521
  864. var *gvar[NVAR]; /* hash for globals */
  865. X#define new(type) ((type *)emalloc(sizeof(type)))
  866. char *emalloc(long);
  867. void *Malloc(ulong);
  868. void efree(char*);
  869. X#define NOFILE 128 /* should come from <param.h> */
  870. struct here{
  871. X tree *tag;
  872. X char *name;
  873. X struct here *next;
  874. X};
  875. int mypid;
  876. X/*
  877. X * Glob character escape in strings:
  878. X * In a string, GLOB must be followed by *?[ or GLOB.
  879. X * GLOB* matches any string
  880. X * GLOB? matches any single character
  881. X * GLOB[...] matches anything in the brackets
  882. X * GLOBGLOB matches GLOB
  883. X */
  884. X#define GLOB ((char)0x01)
  885. X/*
  886. X * onebyte(c), twobyte(c), threebyte(c)
  887. X * Is c the first character of a one- two- or three-byte utf sequence?
  888. X */
  889. X#define onebyte(c) ((c&0x80)==0x00)
  890. X#define twobyte(c) ((c&0xe0)==0xc0)
  891. X#define threebyte(c) ((c&0xf0)==0xe0)
  892. char **argp;
  893. char **args;
  894. int nerror; /* number of errors encountered during compilation */
  895. int doprompt; /* is it time for a prompt? */
  896. X/*
  897. X * Which fds are the reading/writing end of a pipe?
  898. X * Unfortunately, this can vary from system to system.
  899. X * 9th edition Unix doesn't care, the following defines
  900. X * work on plan 9.
  901. X */
  902. X#define PRD 0
  903. X#define PWR 1
  904. char Rcmain[], Fdprefix[];
  905. X#define register
  906. X/*
  907. X * How many dot commands have we executed?
  908. X * Used to ensure that -v flag doesn't print rcmain.
  909. X */
  910. int ndot;
  911. char *getstatus(void);
  912. int lastc;
  913. int lastword;
  914. !
  915. echo unix.c
  916. sed 's/^X//' >unix.c <<'!'
  917. X/*
  918. X * Unix versions of system-specific functions
  919. X * By convention, exported routines herein have names beginning with an
  920. X * upper case letter.
  921. X */
  922. X#include "rc.h"
  923. X#include "io.h"
  924. X#include "exec.h"
  925. X#include "getflags.h"
  926. X#include <errno.h>
  927. char Rcmain[]="/usr/lib/rcmain";
  928. char Fdprefix[]="/dev/fd/";
  929. void execfinit(void);
  930. struct builtin Builtin[] = {
  931. X "cd", execcd,
  932. X "whatis", execwhatis,
  933. X "eval", execeval,
  934. X "exec", execexec, /* but with popword first */
  935. X "exit", execexit,
  936. X "shift", execshift,
  937. X "wait", execwait,
  938. X "umask", execumask,
  939. X ".", execdot,
  940. X "finit", execfinit,
  941. X "flag", execflag,
  942. X 0
  943. X};
  944. X#define SEP '\1'
  945. char **environp;
  946. struct word*
  947. enval(s)
  948. register char *s;
  949. X{
  950. X char *t, c;
  951. X struct word *v;
  952. X for(t = s;*t && *t!=SEP;t++);
  953. X c=*t;
  954. X *t='\0';
  955. X v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
  956. X *t = c;
  957. X return v;
  958. X}
  959. void
  960. Vinit(void)
  961. X{
  962. X extern char **environ;
  963. X char *s;
  964. X char **env = environ;
  965. X environp = env;
  966. X for(;*env;env++){
  967. X for(s=*env;*s && *s!='(' && *s!='=';s++);
  968. X switch(*s){
  969. X case '\0':
  970. X pfmt(err, "environment %q?\n", *env);
  971. X break;
  972. X case '=':
  973. X *s='\0';
  974. X setvar(*env, enval(s+1));
  975. X *s='=';
  976. X break;
  977. X case '(': /* ignore functions for now */
  978. X break;
  979. X }
  980. X }
  981. X}
  982. char **envp;
  983. void
  984. XXrdfn(void)
  985. X{
  986. X char *s;
  987. X int len;
  988. X for(;*envp;envp++){
  989. X for(s=*envp;*s && *s!='(' && *s!='=';s++);
  990. X switch(*s){
  991. X case '\0':
  992. X pfmt(err, "environment %q?\n", *envp);
  993. X break;
  994. X case '=': /* ignore variables */
  995. X break;
  996. X case '(': /* Bourne again */
  997. X s=*envp+3;
  998. X envp++;
  999. X len = strlen(s);
  1000. X s[len]='\n';
  1001. X execcmds(opencore(s, len+1));
  1002. X s[len]='\0';
  1003. X return;
  1004. X }
  1005. X }
  1006. X Xreturn();
  1007. X}
  1008. union code rdfns[4];
  1009. void
  1010. execfinit(void)
  1011. X{
  1012. X static int first = 1;
  1013. X if(first){
  1014. X rdfns[0].i = 1;
  1015. X rdfns[1].f = Xrdfn;
  1016. X rdfns[2].f = Xjump;
  1017. X rdfns[3].i = 1;
  1018. X first = 0;
  1019. X }
  1020. X Xpopm();
  1021. X envp = environp;
  1022. X start(rdfns, 1, runq->local);
  1023. X}
  1024. int
  1025. cmpenv(const void *aa, const void *ab)
  1026. X{
  1027. X char **a = aa, **b = ab;
  1028. X return strcmp(*a, *b);
  1029. X}
  1030. char **
  1031. mkenv(void)
  1032. X{
  1033. X char **env, **ep, *p, *q;
  1034. X struct var **h, *v;
  1035. X struct word *a;
  1036. X int nvar = 0, nchr = 0, sep;
  1037. X /*
  1038. X * Slightly kludgy loops look at locals then globals.
  1039. X * locals no longer exist - geoff
  1040. X */
  1041. X for(h = gvar-1; h != &gvar[NVAR]; h++)
  1042. X for(v = h >= gvar? *h: runq->local; v ;v = v->next){
  1043. X if((v==vlook(v->name)) && v->val){
  1044. X nvar++;
  1045. X nchr+=strlen(v->name)+1;
  1046. X for(a = v->val;a;a = a->next)
  1047. X nchr+=strlen(a->word)+1;
  1048. X }
  1049. X if(v->fn){
  1050. X nvar++;
  1051. X nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
  1052. X }
  1053. X }
  1054. X env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
  1055. X ep = env;
  1056. X p = (char *)&env[nvar+1];
  1057. X for(h = gvar-1; h != &gvar[NVAR]; h++)
  1058. X for(v = h >= gvar? *h: runq->local;v;v = v->next){
  1059. X if((v==vlook(v->name)) && v->val){
  1060. X *ep++=p;
  1061. X q = v->name;
  1062. X while(*q) *p++=*q++;
  1063. X sep='=';
  1064. X for(a = v->val;a;a = a->next){
  1065. X *p++=sep;
  1066. X sep = SEP;
  1067. X q = a->word;
  1068. X while(*q) *p++=*q++;
  1069. X }
  1070. X *p++='\0';
  1071. X }
  1072. X if(v->fn){
  1073. X *ep++=p;
  1074. X *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
  1075. X *p++='f'; *p++='n'; *p++=' ';
  1076. X q = v->name;
  1077. X while(*q) *p++=*q++;
  1078. X *p++=' ';
  1079. X q = v->fn[v->pc-1].s;
  1080. X while(*q) *p++=*q++;
  1081. X *p++='\0';
  1082. X }
  1083. X }
  1084. X *ep = 0;
  1085. X qsort((void *)env, nvar, sizeof ep[0], cmpenv);
  1086. X return env;
  1087. X}
  1088. char *sigmsg[] = {
  1089. X/* 0 normal */ 0,
  1090. X/* 1 SIGHUP */ "Hangup",
  1091. X/* 2 SIGINT */ 0,
  1092. X/* 3 SIGQUIT */ "Quit",
  1093. X/* 4 SIGILL */ "Illegal instruction",
  1094. X/* 5 SIGTRAP */ "Trace/BPT trap",
  1095. X/* 6 SIGIOT */ "abort",
  1096. X/* 7 SIGEMT */ "EMT trap",
  1097. X/* 8 SIGFPE */ "Floating exception",
  1098. X/* 9 SIGKILL */ "Killed",
  1099. X/* 10 SIGBUS */ "Bus error",
  1100. X/* 11 SIGSEGV */ "Memory fault",
  1101. X/* 12 SIGSYS */ "Bad system call",
  1102. X/* 13 SIGPIPE */ 0,
  1103. X/* 14 SIGALRM */ "Alarm call",
  1104. X/* 15 SIGTERM */ "Terminated",
  1105. X/* 16 unused */ "signal 16",
  1106. X/* 17 SIGSTOP */ "Process stopped",
  1107. X/* 18 unused */ "signal 18",
  1108. X/* 19 SIGCONT */ "Process continued",
  1109. X/* 20 SIGCHLD */ "Child death",
  1110. X};
  1111. void
  1112. Waitfor(int pid, int persist)
  1113. X{
  1114. X int wpid, sig;
  1115. X struct thread *p;
  1116. X int wstat;
  1117. X char wstatstr[12];
  1118. X for(;;){
  1119. X errno = 0;
  1120. X wpid = wait(&wstat);
  1121. X if(errno==EINTR && persist)
  1122. X continue;
  1123. X if(wpid==-1)
  1124. X break;
  1125. X sig = wstat&0177;
  1126. X if(sig==0177){
  1127. X pfmt(err, "trace: ");
  1128. X sig = (wstat>>8)&0177;
  1129. X }
  1130. X if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
  1131. X if(pid!=wpid)
  1132. X pfmt(err, "%d: ", wpid);
  1133. X if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))
  1134. X pfmt(err, "%s", sigmsg[sig]);
  1135. X else if(sig==0177) pfmt(err, "stopped by ptrace");
  1136. X else pfmt(err, "signal %d", sig);
  1137. X if(wstat&0200)pfmt(err, " -- core dumped");
  1138. X pfmt(err, "\n");
  1139. X }
  1140. X wstat = sig?sig+1000:(wstat>>8)&0xFF;
  1141. X if(wpid==pid){
  1142. X inttoascii(wstatstr, wstat);
  1143. X setstatus(wstatstr);
  1144. X break;
  1145. X }
  1146. X else{
  1147. X for(p = runq->ret;p;p = p->ret)
  1148. X if(p->pid==wpid){
  1149. X p->pid=-1;
  1150. X inttoascii(p->status, wstat);
  1151. X break;
  1152. X }
  1153. X }
  1154. X }
  1155. X}
  1156. char **
  1157. mkargv(a)
  1158. register struct word *a;
  1159. X{
  1160. X char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
  1161. X char **argp = argv+1; /* leave one at front for runcoms */
  1162. X for(;a;a = a->next)
  1163. X *argp++=a->word;
  1164. X *argp = 0;
  1165. X return argv;
  1166. X}
  1167. void
  1168. Updenv(void)
  1169. X{
  1170. X}
  1171. void
  1172. Execute(struct word *args, struct word *path)
  1173. X{
  1174. X char *msg="not found";
  1175. X#ifdef ETXTBSY
  1176. X int txtbusy = 0;
  1177. X#endif
  1178. X char **env = mkenv();
  1179. X char **argv = mkargv(args);
  1180. X char file[512];
  1181. X for(;path;path = path->next){
  1182. X strcpy(file, path->word);
  1183. X if(file[0])
  1184. X strcat(file, "/");
  1185. X strcat(file, argv[1]);
  1186. X#ifdef ETXTBSY
  1187. ReExec:
  1188. X#endif
  1189. X execve(file, argv+1, env);
  1190. X switch(errno){
  1191. X case ENOEXEC:
  1192. X pfmt(err, "%s: Bourne again\n", argv[1]);
  1193. X argv[0]="sh";
  1194. X argv[1] = strdup(file);
  1195. X execve("/bin/sh", argv, env);
  1196. X goto Bad;
  1197. X#ifdef ETXTBSY
  1198. X case ETXTBSY:
  1199. X if(++txtbusy!=5){
  1200. X sleep(txtbusy);
  1201. X goto ReExec;
  1202. X }
  1203. X msg="text busy"; goto Bad;
  1204. X#endif
  1205. X case EACCES:
  1206. X msg="no access";
  1207. X break;
  1208. X case ENOMEM:
  1209. X msg="not enough memory"; goto Bad;
  1210. X case E2BIG:
  1211. X msg="too big"; goto Bad;
  1212. X }
  1213. X }
  1214. Bad:
  1215. X pfmt(err, "%s: %s\n", argv[1], msg);
  1216. X efree((char *)env);
  1217. X efree((char *)argv);
  1218. X}
  1219. X#define NDIR 14 /* should get this from param.h */
  1220. Globsize(p)
  1221. register char *p;
  1222. X{
  1223. X int isglob = 0, globlen = NDIR+1;
  1224. X for(;*p;p++){
  1225. X if(*p==GLOB){
  1226. X p++;
  1227. X if(*p!=GLOB)
  1228. X isglob++;
  1229. X globlen+=*p=='*'?NDIR:1;
  1230. X }
  1231. X else
  1232. X globlen++;
  1233. X }
  1234. X return isglob?globlen:0;
  1235. X}
  1236. X#include <sys/types.h>
  1237. X#include <dirent.h>
  1238. X#define NDIRLIST 50
  1239. DIR *dirlist[NDIRLIST];
  1240. Opendir(name)
  1241. char *name;
  1242. X{
  1243. X DIR **dp;
  1244. X for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
  1245. X if(*dp==0){
  1246. X *dp = opendir(name);
  1247. X return *dp?dp-dirlist:-1;
  1248. X }
  1249. X return -1;
  1250. X}
  1251. int
  1252. Readdir(int f, char *p, int /* onlydirs */ )
  1253. X{
  1254. X struct dirent *dp = readdir(dirlist[f]);
  1255. X if(dp==0)
  1256. X return 0;
  1257. X strcpy(p, dp->d_name);
  1258. X return 1;
  1259. X}
  1260. void
  1261. Closedir(int f)
  1262. X{
  1263. X closedir(dirlist[f]);
  1264. X dirlist[f] = 0;
  1265. X}
  1266. char *Signame[] = {
  1267. X "sigexit", "sighup", "sigint", "sigquit",
  1268. X "sigill", "sigtrap", "sigiot", "sigemt",
  1269. X "sigfpe", "sigkill", "sigbus", "sigsegv",
  1270. X "sigsys", "sigpipe", "sigalrm", "sigterm",
  1271. X "sig16", "sigstop", "sigtstp", "sigcont",
  1272. X "sigchld", "sigttin", "sigttou", "sigtint",
  1273. X "sigxcpu", "sigxfsz", "sig26", "sig27",
  1274. X "sig28", "sig29", "sig30", "sig31",
  1275. X 0,
  1276. X};
  1277. void
  1278. gettrap(int sig)
  1279. X{
  1280. X signal(sig, gettrap);
  1281. X trap[sig]++;
  1282. X ntrap++;
  1283. X if(ntrap>=NSIG){
  1284. X pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
  1285. X signal(SIGABRT, (void (*)())0);
  1286. X kill(getpid(), SIGABRT);
  1287. X }
  1288. X}
  1289. void
  1290. Trapinit(void)
  1291. X{
  1292. X int i;
  1293. X void (*sig)();
  1294. X if(1 || flag['d']){ /* wrong!!! */
  1295. X sig = signal(SIGINT, gettrap);
  1296. X if(sig==SIG_IGN)
  1297. X signal(SIGINT, SIG_IGN);
  1298. X }
  1299. X else{
  1300. X for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
  1301. X sig = signal(i, gettrap);
  1302. X if(sig==SIG_IGN)
  1303. X signal(i, SIG_IGN);
  1304. X }
  1305. X }
  1306. X}
  1307. Unlink(name)
  1308. char *name;
  1309. X{
  1310. X return unlink(name);
  1311. X}
  1312. Write(fd, buf, cnt)
  1313. char *buf;
  1314. X{
  1315. X return write(fd, buf, cnt);
  1316. X}
  1317. Read(fd, buf, cnt)
  1318. char *buf;
  1319. X{
  1320. X return read(fd, buf, cnt);
  1321. X}
  1322. Seek(fd, cnt, whence)
  1323. long cnt;
  1324. X{
  1325. X return lseek(fd, cnt, whence);
  1326. X}
  1327. Executable(file)
  1328. char *file;
  1329. X{
  1330. X return(access(file, 01)==0);
  1331. X}
  1332. Creat(file)
  1333. char *file;
  1334. X{
  1335. X return creat(file, 0666);
  1336. X}
  1337. Dup(a, b){
  1338. X return dup2(a, b);
  1339. X}
  1340. Dup1(a){
  1341. X return dup(a);
  1342. X}
  1343. X/*
  1344. X * Wrong: should go through components of a|b|c and return the maximum.
  1345. X */
  1346. void
  1347. Exit(char *stat)
  1348. X{
  1349. X int n = 0;
  1350. X while(*stat){
  1351. X if(*stat!='|'){
  1352. X if(*stat<'0' || '9'<*stat)
  1353. X exit(1);
  1354. X else n = n*10+*stat-'0';
  1355. X }
  1356. X stat++;
  1357. X }
  1358. X exit(n);
  1359. X}
  1360. Eintr(){
  1361. X return errno==EINTR;
  1362. X}
  1363. void
  1364. Noerror()
  1365. X{
  1366. X errno = 0;
  1367. X}
  1368. Isatty(fd){
  1369. X return isatty(fd);
  1370. X}
  1371. void
  1372. Abort()
  1373. X{
  1374. X abort();
  1375. X}
  1376. void
  1377. execumask(void) /* wrong -- should fork before writing */
  1378. X{
  1379. X int m;
  1380. X struct io out[1];
  1381. X switch(count(runq->argv->words)){
  1382. X default:
  1383. X pfmt(err, "Usage: umask [umask]\n");
  1384. X setstatus("umask usage");
  1385. X poplist();
  1386. X return;
  1387. X case 2:
  1388. X umask(octal(runq->argv->words->next->word));
  1389. X break;
  1390. X case 1:
  1391. X umask(m = umask(0));
  1392. X out->fd = mapfd(1);
  1393. X out->bufp = out->buf;
  1394. X out->ebuf=&out->buf[NBUF];
  1395. X out->strp = 0;
  1396. X pfmt(out, "%o\n", m);
  1397. X break;
  1398. X }
  1399. X setstatus("");
  1400. X poplist();
  1401. X}
  1402. void
  1403. Memcpy(a, b, n)
  1404. char *a, *b;
  1405. X{
  1406. X memmove(a, b, n);
  1407. X}
  1408. void*
  1409. Malloc(unsigned long n)
  1410. X{
  1411. X return (void *)malloc(n);
  1412. X}
  1413. void
  1414. errstr(char *buf, int len)
  1415. X{
  1416. X strncpy(buf, strerror(errno), len);
  1417. X}
  1418. !
  1419. From geoff@collyer.net Fri Dec 19 01:23:26 EST 2003
  1420. Received: from plan9.cs.bell-labs.com ([135.104.9.2]) by plan9; Fri Dec 19 01:23:25 EST 2003
  1421. Received: from collyer.net ([63.192.14.226]) by plan9; Fri Dec 19 01:23:22 EST 2003
  1422. Message-ID: <0b5ea130198a21a49139759d00d69939@collyer.net>
  1423. subject: rc on unix, part 2
  1424. From: Geoff Collyer <geoff@collyer.net>
  1425. Date: Thu, 18 Dec 2003 22:23:21 -0800
  1426. To: presotto@plan9.bell-labs.com, rsc@plan9.bell-labs.com, geoff@collyer.net
  1427. MIME-Version: 1.0
  1428. Content-Type: text/plain; charset="US-ASCII"
  1429. Content-Transfer-Encoding: 7bit
  1430. These are the include files I used to emulate plan 9's include
  1431. files on Unix (APE).
  1432. # To unbundle, run this file
  1433. mkdir include
  1434. echo include/bio.h
  1435. sed 's/^X//' >include/bio.h <<'!'
  1436. X#ifndef _BIOH_
  1437. X#define _BIOH_ 1
  1438. X#include <sys/types.h> /* for off_t */
  1439. X#include <fcntl.h> /* for O_RDONLY, O_WRONLY */
  1440. typedef struct Biobuf Biobuf;
  1441. enum
  1442. X{
  1443. X Bsize = 8*1024,
  1444. X Bungetsize = 4, /* space for ungetc */
  1445. X Bmagic = 0x314159,
  1446. X Beof = -1,
  1447. X Bbad = -2,
  1448. X Binactive = 0, /* states */
  1449. X Bractive,
  1450. X Bwactive,
  1451. X Bracteof,
  1452. X Bend
  1453. X};
  1454. struct Biobuf
  1455. X{
  1456. X int icount; /* neg num of bytes at eob */
  1457. X int ocount; /* num of bytes at bob */
  1458. X int rdline; /* num of bytes after rdline */
  1459. X int runesize; /* num of bytes of last getrune */
  1460. X int state; /* r/w/inactive */
  1461. X int fid; /* open file */
  1462. X int flag; /* magic if malloc'ed */
  1463. X off_t offset; /* offset of buffer in file */
  1464. X int bsize; /* size of buffer */
  1465. X unsigned char* bbuf; /* pointer to beginning of buffer */
  1466. X unsigned char* ebuf; /* pointer to end of buffer */
  1467. X unsigned char* gbuf; /* pointer to good data in buf */
  1468. X unsigned char b[Bungetsize+Bsize];
  1469. X};
  1470. X#define BGETC(bp)\
  1471. X ((bp)->icount?(bp)->bbuf[(bp)->bsize+(bp)->icount++]:Bgetc((bp)))
  1472. X#define BPUTC(bp,c)\
  1473. X ((bp)->ocount?(bp)->bbuf[(bp)->bsize+(bp)->ocount++]=(c),0:Bputc((bp),(c)))
  1474. X#define BOFFSET(bp)\
  1475. X (((bp)->state==Bractive)?\
  1476. X (bp)->offset + (bp)->icount:\
  1477. X (((bp)->state==Bwactive)?\
  1478. X (bp)->offset + ((bp)->bsize + (bp)->ocount):\
  1479. X -1))
  1480. X#define BLINELEN(bp)\
  1481. X (bp)->rdline
  1482. X#define BFILDES(bp)\
  1483. X (bp)->fid
  1484. int Bbuffered(Biobuf*);
  1485. int Bfildes(Biobuf*);
  1486. int Bflush(Biobuf*);
  1487. int Bgetc(Biobuf*);
  1488. int Bgetd(Biobuf*, double*);
  1489. int Binit(Biobuf*, int, int);
  1490. int Binits(Biobuf*, int, int, unsigned char*, int);
  1491. int Blinelen(Biobuf*);
  1492. off_t Boffset(Biobuf*);
  1493. Biobuf* Bopen(char*, int);
  1494. int Bprint(Biobuf*, char*, ...);
  1495. int Bputc(Biobuf*, int);
  1496. void* Brdline(Biobuf*, int);
  1497. long Bread(Biobuf*, void*, long);
  1498. off_t Bseek(Biobuf*, off_t, int);
  1499. int Bterm(Biobuf*);
  1500. int Bungetc(Biobuf*);
  1501. long Bwrite(Biobuf*, void*, long);
  1502. long Bgetrune(Biobuf*);
  1503. int Bputrune(Biobuf*, long);
  1504. int Bungetrune(Biobuf*);
  1505. X#endif
  1506. !
  1507. echo include/fmt.h
  1508. sed 's/^X//' >include/fmt.h <<'!'
  1509. X/*
  1510. X * The authors of this software are Rob Pike and Ken Thompson.
  1511. X * Copyright (c) 2002 by Lucent Technologies.
  1512. X * Permission to use, copy, modify, and distribute this software for any
  1513. X * purpose without fee is hereby granted, provided that this entire notice
  1514. X * is included in all copies of any software which is or includes a copy
  1515. X * or modification of this software and in all copies of the supporting
  1516. X * documentation for such software.
  1517. X * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
  1518. X * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
  1519. X * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
  1520. X * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
  1521. X */
  1522. X#ifndef _FMTH_
  1523. X#define _FMTH_ 1
  1524. X#include <stdarg.h>
  1525. X#ifndef _UTFH_
  1526. X#include <utf.h>
  1527. X#endif
  1528. typedef struct Fmt Fmt;
  1529. struct Fmt{
  1530. X unsigned char runes; /* output buffer is runes or chars? */
  1531. X void *start; /* of buffer */
  1532. X void *to; /* current place in the buffer */
  1533. X void *stop; /* end of the buffer; overwritten if flush fails */
  1534. X int (*flush)(Fmt *); /* called when to == stop */
  1535. X void *farg; /* to make flush a closure */
  1536. X int nfmt; /* num chars formatted so far */
  1537. X va_list args; /* args passed to dofmt */
  1538. X int r; /* % format Rune */
  1539. X int width;
  1540. X int prec;
  1541. X unsigned long flags;
  1542. X};
  1543. enum{
  1544. X FmtWidth = 1,
  1545. X FmtLeft = FmtWidth << 1,
  1546. X FmtPrec = FmtLeft << 1,
  1547. X FmtSharp = FmtPrec << 1,
  1548. X FmtSpace = FmtSharp << 1,
  1549. X FmtSign = FmtSpace << 1,
  1550. X FmtZero = FmtSign << 1,
  1551. X FmtUnsigned = FmtZero << 1,
  1552. X FmtShort = FmtUnsigned << 1,
  1553. X FmtLong = FmtShort << 1,
  1554. X FmtVLong = FmtLong << 1,
  1555. X FmtComma = FmtVLong << 1,
  1556. X FmtByte = FmtComma << 1,
  1557. X FmtLDouble = FmtByte << 1,
  1558. X FmtFlag = FmtLDouble << 1
  1559. X};
  1560. extern int print(char*, ...);
  1561. extern char* seprint(char*, char*, char*, ...);
  1562. extern char* vseprint(char*, char*, char*, va_list);
  1563. extern int snprint(char*, int, char*, ...);
  1564. extern int vsnprint(char*, int, char*, va_list);
  1565. extern char* smprint(char*, ...);
  1566. extern char* vsmprint(char*, va_list);
  1567. extern int sprint(char*, char*, ...);
  1568. extern int fprint(int, char*, ...);
  1569. extern int vfprint(int, char*, va_list);
  1570. extern int runesprint(Rune*, char*, ...);
  1571. extern int runesnprint(Rune*, int, char*, ...);
  1572. extern int runevsnprint(Rune*, int, char*, va_list);
  1573. extern Rune* runeseprint(Rune*, Rune*, char*, ...);
  1574. extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
  1575. extern Rune* runesmprint(char*, ...);
  1576. extern Rune* runevsmprint(char*, va_list);
  1577. extern int fmtfdinit(Fmt*, int, char*, int);
  1578. extern int fmtfdflush(Fmt*);
  1579. extern int fmtstrinit(Fmt*);
  1580. extern char* fmtstrflush(Fmt*);
  1581. extern int quotestrfmt(Fmt *f);
  1582. extern void quotefmtinstall(void);
  1583. extern int (*fmtdoquote)(int);
  1584. extern int fmtinstall(int, int (*)(Fmt*));
  1585. extern int dofmt(Fmt*, char*);
  1586. extern int fmtprint(Fmt*, char*, ...);
  1587. extern int fmtvprint(Fmt*, char*, va_list);
  1588. extern int fmtrune(Fmt*, int);
  1589. extern int fmtstrcpy(Fmt*, char*);
  1590. extern double fmtstrtod(const char *, char **);
  1591. extern double fmtcharstod(int(*)(void*), void*);
  1592. X#endif
  1593. !
  1594. echo include/lib9.h
  1595. sed 's/^X//' >include/lib9.h <<'!'
  1596. X#include <string.h>
  1597. X#include "utf.h"
  1598. X#define nil ((void*)0)
  1599. X#define uchar _fmtuchar
  1600. X#define ushort _fmtushort
  1601. X#define uint _fmtuint
  1602. X#define ulong _fmtulong
  1603. X#define vlong _fmtvlong
  1604. X#define uvlong _fmtuvlong
  1605. typedef unsigned char uchar;
  1606. typedef unsigned short ushort;
  1607. typedef unsigned int uint;
  1608. typedef unsigned long ulong;
  1609. X#define OREAD O_RDONLY
  1610. X#define OWRITE O_WRONLY
  1611. X#define ORDWR O_RDWR
  1612. X#define OCEXEC 0
  1613. !
  1614. echo include/regexp9.h
  1615. sed 's/^X//' >include/regexp9.h <<'!'
  1616. X#ifndef _REGEXP9H_
  1617. X#define _REGEXP9H_ 1
  1618. X#include <utf.h>
  1619. typedef struct Resub Resub;
  1620. typedef struct Reclass Reclass;
  1621. typedef struct Reinst Reinst;
  1622. typedef struct Reprog Reprog;
  1623. X/*
  1624. X * Sub expression matches
  1625. X */
  1626. struct Resub{
  1627. X union
  1628. X {
  1629. X char *sp;
  1630. X Rune *rsp;
  1631. X }s;
  1632. X union
  1633. X {
  1634. X char *ep;
  1635. X Rune *rep;
  1636. X }e;
  1637. X};
  1638. X/*
  1639. X * character class, each pair of rune's defines a range
  1640. X */
  1641. struct Reclass{
  1642. X Rune *end;
  1643. X Rune spans[64];
  1644. X};
  1645. X/*
  1646. X * Machine instructions
  1647. X */
  1648. struct Reinst{
  1649. X int type;
  1650. X union {
  1651. X Reclass *cp; /* class pointer */
  1652. X Rune r; /* character */
  1653. X int subid; /* sub-expression id for RBRA and LBRA */
  1654. X Reinst *right; /* right child of OR */
  1655. X }u1;
  1656. X union { /* regexp relies on these two being in the same union */
  1657. X Reinst *left; /* left child of OR */
  1658. X Reinst *next; /* next instruction for CAT & LBRA */
  1659. X }u2;
  1660. X};
  1661. X/*
  1662. X * Reprogram definition
  1663. X */
  1664. struct Reprog{
  1665. X Reinst *startinst; /* start pc */
  1666. X Reclass class[16]; /* .data */
  1667. X Reinst firstinst[5]; /* .text */
  1668. X};
  1669. extern Reprog *regcomp(char*);
  1670. extern Reprog *regcomplit(char*);
  1671. extern Reprog *regcompnl(char*);
  1672. extern void regerror(char*);
  1673. extern int regexec(Reprog*, char*, Resub*, int);
  1674. extern void regsub(char*, char*, int, Resub*, int);
  1675. extern int rregexec(Reprog*, Rune*, Resub*, int);
  1676. extern void rregsub(Rune*, Rune*, Resub*, int);
  1677. X#endif
  1678. !
  1679. echo include/utf.h
  1680. sed 's/^X//' >include/utf.h <<'!'
  1681. X#ifndef _UTFH_
  1682. X#define _UTFH_ 1
  1683. typedef unsigned short Rune; /* 16 bits */
  1684. enum
  1685. X{
  1686. X UTFmax = 3, /* maximum bytes per rune */
  1687. X Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
  1688. X Runeself = 0x80, /* rune and UTF sequences are the same (<) */
  1689. X Runeerror = 0x80, /* decoding error in UTF */
  1690. X};
  1691. X/*
  1692. X * rune routines
  1693. X */
  1694. extern int runetochar(char*, Rune*);
  1695. extern int chartorune(Rune*, char*);
  1696. extern int runelen(long);
  1697. extern int runenlen(Rune*, int);
  1698. extern int fullrune(char*, int);
  1699. extern int utflen(char*);
  1700. extern int utfnlen(char*, long);
  1701. extern char* utfrune(char*, long);
  1702. extern char* utfrrune(char*, long);
  1703. extern char* utfutf(char*, char*);
  1704. extern char* utfecpy(char*, char*, char*);
  1705. extern Rune* runestrcat(Rune*, Rune*);
  1706. extern Rune* runestrchr(Rune*, Rune);
  1707. extern int runestrcmp(Rune*, Rune*);
  1708. extern Rune* runestrcpy(Rune*, Rune*);
  1709. extern Rune* runestrncpy(Rune*, Rune*, long);
  1710. extern Rune* runestrecpy(Rune*, Rune*, Rune*);
  1711. extern Rune* runestrdup(Rune*);
  1712. extern Rune* runestrncat(Rune*, Rune*, long);
  1713. extern int runestrncmp(Rune*, Rune*, long);
  1714. extern Rune* runestrrchr(Rune*, Rune);
  1715. extern long runestrlen(Rune*);
  1716. extern Rune* runestrstr(Rune*, Rune*);
  1717. extern Rune tolowerrune(Rune);
  1718. extern Rune totitlerune(Rune);
  1719. extern Rune toupperrune(Rune);
  1720. extern int isalpharune(Rune);
  1721. extern int islowerrune(Rune);
  1722. extern int isspacerune(Rune);
  1723. extern int istitlerune(Rune);
  1724. extern int isupperrune(Rune);
  1725. X#endif
  1726. !