plan9.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /*
  2. * Plan 9 versions of system-specific functions
  3. * By convention, exported routines herein have names beginning with an
  4. * upper case letter.
  5. */
  6. #include "rc.h"
  7. #include "exec.h"
  8. #include "io.h"
  9. #include "fns.h"
  10. #include "getflags.h"
  11. char *Signame[] = {
  12. "sigexit", "sighup", "sigint", "sigquit",
  13. "sigalrm", "sigkill", "sigfpe", "sigterm",
  14. 0
  15. };
  16. char *syssigname[] = {
  17. "exit", /* can't happen */
  18. "hangup",
  19. "interrupt",
  20. "quit", /* can't happen */
  21. "alarm",
  22. "kill",
  23. "sys: fp: ",
  24. "term",
  25. 0
  26. };
  27. char Rcmain[]="/rc/lib/rcmain";
  28. char Fdprefix[]="/fd/";
  29. void execfinit(void);
  30. void execbind(void);
  31. void execmount(void);
  32. void execnewpgrp(void);
  33. builtin Builtin[] = {
  34. "cd", execcd,
  35. "whatis", execwhatis,
  36. "eval", execeval,
  37. "exec", execexec, /* but with popword first */
  38. "exit", execexit,
  39. "shift", execshift,
  40. "wait", execwait,
  41. ".", execdot,
  42. "finit", execfinit,
  43. "flag", execflag,
  44. "rfork", execnewpgrp,
  45. 0
  46. };
  47. void
  48. execnewpgrp(void)
  49. {
  50. int arg;
  51. char *s;
  52. switch(count(runq->argv->words)){
  53. case 1:
  54. arg = RFENVG|RFNAMEG|RFNOTEG;
  55. break;
  56. case 2:
  57. arg = 0;
  58. for(s = runq->argv->words->next->word;*s;s++) switch(*s){
  59. default:
  60. goto Usage;
  61. case 'n':
  62. arg|=RFNAMEG; break;
  63. case 'N':
  64. arg|=RFCNAMEG;
  65. break;
  66. case 'm':
  67. arg|=RFNOMNT; break;
  68. case 'e':
  69. arg|=RFENVG; break;
  70. case 'E':
  71. arg|=RFCENVG; break;
  72. case 's':
  73. arg|=RFNOTEG; break;
  74. case 'f':
  75. arg|=RFFDG; break;
  76. case 'F':
  77. arg|=RFCFDG; break;
  78. }
  79. break;
  80. default:
  81. Usage:
  82. pfmt(err, "Usage: %s [fnesFNEm]\n", runq->argv->words->word);
  83. setstatus("rfork usage");
  84. poplist();
  85. return;
  86. }
  87. if(rfork(arg)==-1){
  88. pfmt(err, "rc: %s failed\n", runq->argv->words->word);
  89. setstatus("rfork failed");
  90. }
  91. else
  92. setstatus("");
  93. poplist();
  94. }
  95. void
  96. Vinit(void)
  97. {
  98. int dir, f, len;
  99. word *val;
  100. char *buf, *s;
  101. Dir *ent;
  102. int i, nent;
  103. char envname[256];
  104. dir = open("/env", OREAD);
  105. if(dir<0){
  106. pfmt(err, "rc: can't open /env: %r\n");
  107. return;
  108. }
  109. ent = nil;
  110. for(;;){
  111. nent = dirread(dir, &ent);
  112. if(nent <= 0)
  113. break;
  114. for(i = 0; i<nent; i++){
  115. len = ent[i].length;
  116. if(len && strncmp(ent[i].name, "fn#", 3)!=0){
  117. snprint(envname, sizeof envname, "/env/%s", ent[i].name);
  118. if((f = open(envname, 0))>=0){
  119. buf = emalloc((int)len+1);
  120. read(f, buf, (long)len);
  121. val = 0;
  122. /* Charitably add a 0 at the end if need be */
  123. if(buf[len-1])
  124. buf[len++]='\0';
  125. s = buf+len-1;
  126. for(;;){
  127. while(s!=buf && s[-1]!='\0') --s;
  128. val = newword(s, val);
  129. if(s==buf)
  130. break;
  131. --s;
  132. }
  133. setvar(ent[i].name, val);
  134. vlook(ent[i].name)->changed = 0;
  135. close(f);
  136. efree(buf);
  137. }
  138. }
  139. }
  140. free(ent);
  141. }
  142. close(dir);
  143. }
  144. int envdir;
  145. void
  146. Xrdfn(void)
  147. {
  148. int f, len;
  149. static Dir *ent, *allocent;
  150. static int nent;
  151. Dir *e;
  152. char envname[256];
  153. for(;;){
  154. if(nent == 0){
  155. free(allocent);
  156. nent = dirread(envdir, &allocent);
  157. ent = allocent;
  158. }
  159. if(nent <= 0)
  160. break;
  161. while(nent){
  162. e = ent++;
  163. nent--;
  164. len = e->length;
  165. if(len && strncmp(e->name, "fn#", 3)==0){
  166. snprint(envname, sizeof envname, "/env/%s", e->name);
  167. if((f = open(envname, 0))>=0){
  168. execcmds(openfd(f));
  169. return;
  170. }
  171. }
  172. }
  173. }
  174. close(envdir);
  175. Xreturn();
  176. }
  177. union code rdfns[4];
  178. void
  179. execfinit(void)
  180. {
  181. static int first = 1;
  182. if(first){
  183. rdfns[0].i = 1;
  184. rdfns[1].f = Xrdfn;
  185. rdfns[2].f = Xjump;
  186. rdfns[3].i = 1;
  187. first = 0;
  188. }
  189. Xpopm();
  190. envdir = open("/env", 0);
  191. if(envdir<0){
  192. pfmt(err, "rc: can't open /env: %r\n");
  193. return;
  194. }
  195. start(rdfns, 1, runq->local);
  196. }
  197. int
  198. Waitfor(int pid, int)
  199. {
  200. thread *p;
  201. Waitmsg *w;
  202. char errbuf[ERRMAX];
  203. if(pid >= 0 && !havewaitpid(pid))
  204. return 0;
  205. while((w = wait()) != nil){
  206. delwaitpid(w->pid);
  207. if(w->pid==pid){
  208. setstatus(w->msg);
  209. free(w);
  210. return 0;
  211. }
  212. for(p = runq->ret;p;p = p->ret)
  213. if(p->pid==w->pid){
  214. p->pid=-1;
  215. strcpy(p->status, w->msg);
  216. }
  217. free(w);
  218. }
  219. errstr(errbuf, sizeof errbuf);
  220. if(strcmp(errbuf, "interrupted")==0) return -1;
  221. return 0;
  222. }
  223. char*
  224. *mkargv(word *a)
  225. {
  226. char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
  227. char **argp = argv+1; /* leave one at front for runcoms */
  228. for(;a;a = a->next) *argp++=a->word;
  229. *argp = 0;
  230. return argv;
  231. }
  232. void
  233. addenv(var *v)
  234. {
  235. char envname[256];
  236. word *w;
  237. int f;
  238. io *fd;
  239. if(v->changed){
  240. v->changed = 0;
  241. snprint(envname, sizeof envname, "/env/%s", v->name);
  242. if((f = Creat(envname))<0)
  243. pfmt(err, "rc: can't open %s: %r\n", envname);
  244. else{
  245. for(w = v->val;w;w = w->next)
  246. write(f, w->word, strlen(w->word)+1L);
  247. close(f);
  248. }
  249. }
  250. if(v->fnchanged){
  251. v->fnchanged = 0;
  252. snprint(envname, sizeof envname, "/env/fn#%s", v->name);
  253. if((f = Creat(envname))<0)
  254. pfmt(err, "rc: can't open %s: %r\n", envname);
  255. else{
  256. if(v->fn){
  257. fd = openfd(f);
  258. pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
  259. closeio(fd);
  260. }
  261. close(f);
  262. }
  263. }
  264. }
  265. void
  266. updenvlocal(var *v)
  267. {
  268. if(v){
  269. updenvlocal(v->next);
  270. addenv(v);
  271. }
  272. }
  273. void
  274. Updenv(void)
  275. {
  276. var *v, **h;
  277. for(h = gvar;h!=&gvar[NVAR];h++)
  278. for(v=*h;v;v = v->next)
  279. addenv(v);
  280. if(runq)
  281. updenvlocal(runq->local);
  282. }
  283. int
  284. ForkExecute(char *file, char **argv, int sin, int sout, int serr)
  285. {
  286. int pid;
  287. if(access(file, 1) != 0)
  288. return -1;
  289. switch(pid = fork()){
  290. case -1:
  291. return -1;
  292. case 0:
  293. if(sin >= 0)
  294. dup(sin, 0);
  295. else
  296. close(0);
  297. if(sout >= 0)
  298. dup(sout, 1);
  299. else
  300. close(1);
  301. if(serr >= 0)
  302. dup(serr, 2);
  303. else
  304. close(2);
  305. exec(file, argv);
  306. exits(file);
  307. }
  308. return pid;
  309. }
  310. void
  311. Execute(word *args, word *path)
  312. {
  313. char **argv = mkargv(args);
  314. char file[1024];
  315. int nc;
  316. Updenv();
  317. for(;path;path = path->next){
  318. nc = strlen(path->word);
  319. if(nc<1024){
  320. strcpy(file, path->word);
  321. if(file[0]){
  322. strcat(file, "/");
  323. nc++;
  324. }
  325. if(nc+strlen(argv[1])<1024){
  326. strcat(file, argv[1]);
  327. exec(file, argv+1);
  328. }
  329. else werrstr("command name too long");
  330. }
  331. }
  332. rerrstr(file, sizeof file);
  333. pfmt(err, "%s: %s\n", argv[1], file);
  334. efree((char *)argv);
  335. }
  336. #define NDIR 256 /* shoud be a better way */
  337. int
  338. Globsize(char *p)
  339. {
  340. int isglob = 0, globlen = NDIR+1;
  341. for(;*p;p++){
  342. if(*p==GLOB){
  343. p++;
  344. if(*p!=GLOB)
  345. isglob++;
  346. globlen+=*p=='*'?NDIR:1;
  347. }
  348. else
  349. globlen++;
  350. }
  351. return isglob?globlen:0;
  352. }
  353. #define NFD 50
  354. #define NDBUF 32
  355. struct{
  356. Dir *dbuf;
  357. int i;
  358. int n;
  359. }dir[NFD];
  360. int
  361. Opendir(char *name)
  362. {
  363. Dir *db;
  364. int f;
  365. f = open(name, 0);
  366. if(f==-1)
  367. return f;
  368. db = dirfstat(f);
  369. if(db!=nil && (db->mode&DMDIR)){
  370. if(f<NFD){
  371. dir[f].i = 0;
  372. dir[f].n = 0;
  373. }
  374. free(db);
  375. return f;
  376. }
  377. free(db);
  378. close(f);
  379. return -1;
  380. }
  381. static int
  382. trimdirs(Dir *d, int nd)
  383. {
  384. int r, w;
  385. for(r=w=0; r<nd; r++)
  386. if(d[r].mode&DMDIR)
  387. d[w++] = d[r];
  388. return w;
  389. }
  390. /*
  391. * onlydirs is advisory -- it means you only
  392. * need to return the directories. it's okay to
  393. * return files too (e.g., on unix where you can't
  394. * tell during the readdir), but that just makes
  395. * the globber work harder.
  396. */
  397. int
  398. Readdir(int f, char *p, int onlydirs)
  399. {
  400. int n;
  401. if(f<0 || f>=NFD)
  402. return 0;
  403. Again:
  404. if(dir[f].i==dir[f].n){ /* read */
  405. free(dir[f].dbuf);
  406. dir[f].dbuf = 0;
  407. n = dirread(f, &dir[f].dbuf);
  408. if(n>0){
  409. if(onlydirs){
  410. n = trimdirs(dir[f].dbuf, n);
  411. if(n == 0)
  412. goto Again;
  413. }
  414. dir[f].n = n;
  415. }else
  416. dir[f].n = 0;
  417. dir[f].i = 0;
  418. }
  419. if(dir[f].i == dir[f].n)
  420. return 0;
  421. strcpy(p, dir[f].dbuf[dir[f].i].name);
  422. dir[f].i++;
  423. return 1;
  424. }
  425. void
  426. Closedir(int f)
  427. {
  428. if(f>=0 && f<NFD){
  429. free(dir[f].dbuf);
  430. dir[f].i = 0;
  431. dir[f].n = 0;
  432. dir[f].dbuf = 0;
  433. }
  434. close(f);
  435. }
  436. int interrupted = 0;
  437. void
  438. notifyf(void*, char *s)
  439. {
  440. int i;
  441. for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
  442. if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
  443. goto Out;
  444. }
  445. pfmt(err, "rc: note: %s\n", s);
  446. noted(NDFLT);
  447. return;
  448. Out:
  449. if(strcmp(s, "interrupt")!=0 || trap[i]==0){
  450. trap[i]++;
  451. ntrap++;
  452. }
  453. if(ntrap>=32){ /* rc is probably in a trap loop */
  454. pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
  455. abort();
  456. }
  457. noted(NCONT);
  458. }
  459. void
  460. Trapinit(void)
  461. {
  462. notify(notifyf);
  463. }
  464. void
  465. Unlink(char *name)
  466. {
  467. remove(name);
  468. }
  469. long
  470. Write(int fd, char *buf, long cnt)
  471. {
  472. return write(fd, buf, (long)cnt);
  473. }
  474. long
  475. Read(int fd, char *buf, long cnt)
  476. {
  477. return read(fd, buf, cnt);
  478. }
  479. long
  480. Seek(int fd, long cnt, long whence)
  481. {
  482. return seek(fd, cnt, whence);
  483. }
  484. int
  485. Executable(char *file)
  486. {
  487. Dir *statbuf;
  488. int ret;
  489. statbuf = dirstat(file);
  490. if(statbuf == nil)
  491. return 0;
  492. ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
  493. free(statbuf);
  494. return ret;
  495. }
  496. int
  497. Creat(char *file)
  498. {
  499. return create(file, 1, 0666L);
  500. }
  501. int
  502. Dup(int a, int b)
  503. {
  504. return dup(a, b);
  505. }
  506. int
  507. Dup1(int)
  508. {
  509. return -1;
  510. }
  511. void
  512. Exit(char *stat)
  513. {
  514. Updenv();
  515. setstatus(stat);
  516. exits(truestatus()?"":getstatus());
  517. }
  518. int
  519. Eintr(void)
  520. {
  521. return interrupted;
  522. }
  523. void
  524. Noerror(void)
  525. {
  526. interrupted = 0;
  527. }
  528. int
  529. Isatty(int fd)
  530. {
  531. char buf[64];
  532. if(fd2path(fd, buf, sizeof buf) != 0)
  533. return 0;
  534. /* might be #c/cons during boot - fixed 22 april 2005, remove this later */
  535. if(strcmp(buf, "#c/cons") == 0)
  536. return 1;
  537. /* might be /mnt/term/dev/cons */
  538. return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;
  539. }
  540. void
  541. Abort(void)
  542. {
  543. pfmt(err, "aborting\n");
  544. flush(err);
  545. Exit("aborting");
  546. }
  547. void
  548. Memcpy(char *a, char *b, long n)
  549. {
  550. memmove(a, b, (long)n);
  551. }
  552. void*
  553. Malloc(ulong n)
  554. {
  555. return malloc(n);
  556. }
  557. int *waitpids;
  558. int nwaitpids;
  559. void
  560. addwaitpid(int pid)
  561. {
  562. waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
  563. if(waitpids == 0)
  564. panic("Can't realloc %d waitpids", nwaitpids+1);
  565. waitpids[nwaitpids++] = pid;
  566. }
  567. void
  568. delwaitpid(int pid)
  569. {
  570. int r, w;
  571. for(r=w=0; r<nwaitpids; r++)
  572. if(waitpids[r] != pid)
  573. waitpids[w++] = waitpids[r];
  574. nwaitpids = w;
  575. }
  576. void
  577. clearwaitpids(void)
  578. {
  579. nwaitpids = 0;
  580. }
  581. int
  582. havewaitpid(int pid)
  583. {
  584. int i;
  585. for(i=0; i<nwaitpids; i++)
  586. if(waitpids[i] == pid)
  587. return 1;
  588. return 0;
  589. }