plan9.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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 execnewpgrp(void){
  48. int arg;
  49. char *s;
  50. switch(count(runq->argv->words)){
  51. case 1: arg=RFENVG|RFNAMEG|RFNOTEG; break;
  52. case 2:
  53. arg=0;
  54. for(s=runq->argv->words->next->word;*s;s++) switch(*s){
  55. default:
  56. goto Usage;
  57. case 'n': arg|=RFNAMEG; break;
  58. case 'N': arg|=RFCNAMEG; break;
  59. case 'm': arg|=RFNOMNT; break;
  60. case 'e': arg|=RFENVG; break;
  61. case 'E': arg|=RFCENVG; break;
  62. case 's': arg|=RFNOTEG; break;
  63. case 'f': arg|=RFFDG; break;
  64. case 'F': arg|=RFCFDG; break;
  65. }
  66. break;
  67. default:
  68. Usage:
  69. pfmt(err, "Usage: %s [fnesFNEm]\n", runq->argv->words->word);
  70. setstatus("rfork usage");
  71. poplist();
  72. return;
  73. }
  74. if(rfork(arg)==-1){
  75. pfmt(err, "rc: %s failed\n", runq->argv->words->word);
  76. setstatus("rfork failed");
  77. }
  78. else
  79. setstatus("");
  80. poplist();
  81. }
  82. void Vinit(void){
  83. int dir, f, len;
  84. word *val;
  85. char *buf, *s;
  86. Dir *ent;
  87. int i, nent;
  88. char envname[256];
  89. dir=open("/env", OREAD);
  90. if(dir<0){
  91. pfmt(err, "rc: can't open /env: %r\n");
  92. return;
  93. }
  94. ent = nil;
  95. for(;;){
  96. nent = dirread(dir, &ent);
  97. if(nent <= 0)
  98. break;
  99. for(i=0; i<nent; i++){
  100. len=ent[i].length;
  101. if(len && strncmp(ent[i].name, "fn#", 3)!=0){
  102. snprint(envname, sizeof envname, "/env/%s", ent[i].name);
  103. if((f=open(envname, 0))>=0){
  104. buf=emalloc((int)len+1);
  105. read(f, buf, (long)len);
  106. val=0;
  107. /* Charitably add a 0 at the end if need be */
  108. if(buf[len-1]) buf[len++]='\0';
  109. s=buf+len-1;
  110. for(;;){
  111. while(s!=buf && s[-1]!='\0') --s;
  112. val=newword(s, val);
  113. if(s==buf) break;
  114. --s;
  115. }
  116. setvar(ent[i].name, val);
  117. vlook(ent[i].name)->changed=0;
  118. close(f);
  119. efree(buf);
  120. }
  121. }
  122. }
  123. free(ent);
  124. }
  125. close(dir);
  126. }
  127. int envdir;
  128. void Xrdfn(void){
  129. int f, len;
  130. static Dir *ent, *allocent;
  131. static int nent;
  132. Dir *e;
  133. char envname[256];
  134. for(;;){
  135. if(nent == 0){
  136. free(allocent);
  137. nent = dirread(envdir, &allocent);
  138. ent = allocent;
  139. }
  140. if(nent <= 0)
  141. break;
  142. while(nent){
  143. e = ent++;
  144. nent--;
  145. len=e->length;
  146. if(len && strncmp(e->name, "fn#", 3)==0){
  147. snprint(envname, sizeof envname, "/env/%s", e->name);
  148. if((f=open(envname, 0))>=0){
  149. execcmds(openfd(f));
  150. return;
  151. }
  152. }
  153. }
  154. }
  155. close(envdir);
  156. Xreturn();
  157. }
  158. union code rdfns[4];
  159. void execfinit(void){
  160. static int first=1;
  161. if(first){
  162. rdfns[0].i=1;
  163. rdfns[1].f=Xrdfn;
  164. rdfns[2].f=Xjump;
  165. rdfns[3].i=1;
  166. first=0;
  167. }
  168. Xpopm();
  169. envdir=open("/env", 0);
  170. if(envdir<0){
  171. pfmt(err, "rc: can't open /env: %r\n");
  172. return;
  173. }
  174. start(rdfns, 1, runq->local);
  175. }
  176. int Waitfor(int pid, int){
  177. thread *p;
  178. Waitmsg *w;
  179. char errbuf[ERRMAX];
  180. while((w = wait()) != nil){
  181. if(w->pid==pid){
  182. setstatus(w->msg);
  183. free(w);
  184. return 0;
  185. }
  186. for(p=runq->ret;p;p=p->ret)
  187. if(p->pid==w->pid){
  188. p->pid=-1;
  189. strcpy(p->status, w->msg);
  190. }
  191. free(w);
  192. }
  193. errstr(errbuf, sizeof errbuf);
  194. if(strcmp(errbuf, "interrupted")==0) return -1;
  195. return 0;
  196. }
  197. char **mkargv(word *a)
  198. {
  199. char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
  200. char **argp=argv+1; /* leave one at front for runcoms */
  201. for(;a;a=a->next) *argp++=a->word;
  202. *argp=0;
  203. return argv;
  204. }
  205. void addenv(var *v)
  206. {
  207. char envname[256];
  208. word *w;
  209. int f;
  210. io *fd;
  211. if(v->changed){
  212. v->changed=0;
  213. snprint(envname, sizeof envname, "/env/%s", v->name);
  214. if((f=Creat(envname))<0)
  215. pfmt(err, "rc: can't open %s: %r\n", envname);
  216. else{
  217. for(w=v->val;w;w=w->next)
  218. write(f, w->word, strlen(w->word)+1L);
  219. close(f);
  220. }
  221. }
  222. if(v->fnchanged){
  223. v->fnchanged=0;
  224. snprint(envname, sizeof envname, "/env/fn#%s", v->name);
  225. if((f=Creat(envname))<0)
  226. pfmt(err, "rc: can't open %s: %r\n", envname);
  227. else{
  228. if(v->fn){
  229. fd=openfd(f);
  230. pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
  231. closeio(fd);
  232. }
  233. close(f);
  234. }
  235. }
  236. }
  237. void updenvlocal(var *v)
  238. {
  239. if(v){
  240. updenvlocal(v->next);
  241. addenv(v);
  242. }
  243. }
  244. void Updenv(void){
  245. var *v, **h;
  246. for(h=gvar;h!=&gvar[NVAR];h++)
  247. for(v=*h;v;v=v->next)
  248. addenv(v);
  249. if(runq) updenvlocal(runq->local);
  250. }
  251. void Execute(word *args, word *path)
  252. {
  253. char **argv=mkargv(args);
  254. char file[1024];
  255. int nc;
  256. Updenv();
  257. for(;path;path=path->next){
  258. nc=strlen(path->word);
  259. if(nc<1024){
  260. strcpy(file, path->word);
  261. if(file[0]){
  262. strcat(file, "/");
  263. nc++;
  264. }
  265. if(nc+strlen(argv[1])<1024){
  266. strcat(file, argv[1]);
  267. exec(file, argv+1);
  268. }
  269. else werrstr("command name too long");
  270. }
  271. }
  272. rerrstr(file, sizeof file);
  273. pfmt(err, "%s: %s\n", argv[1], file);
  274. efree((char *)argv);
  275. }
  276. #define NDIR 256 /* shoud be a better way */
  277. int Globsize(char *p)
  278. {
  279. ulong isglob=0, globlen=NDIR+1;
  280. for(;*p;p++){
  281. if(*p==GLOB){
  282. p++;
  283. if(*p!=GLOB) isglob++;
  284. globlen+=*p=='*'?NDIR:1;
  285. }
  286. else
  287. globlen++;
  288. }
  289. return isglob?globlen:0;
  290. }
  291. #define NFD 50
  292. #define NDBUF 32
  293. struct{
  294. Dir *dbuf;
  295. int i;
  296. int n;
  297. }dir[NFD];
  298. int Opendir(char *name)
  299. {
  300. Dir *db;
  301. int f;
  302. f=open(name, 0);
  303. if(f==-1)
  304. return f;
  305. db = dirfstat(f);
  306. if(db!=nil && (db->mode&DMDIR)){
  307. if(f<NFD){
  308. dir[f].i=0;
  309. dir[f].n=0;
  310. }
  311. free(db);
  312. return f;
  313. }
  314. free(db);
  315. close(f);
  316. return -1;
  317. }
  318. int Readdir(int f, char *p)
  319. {
  320. int n;
  321. if(f<0 || f>=NFD)
  322. return 0;
  323. if(dir[f].i==dir[f].n){ /* read */
  324. free(dir[f].dbuf);
  325. dir[f].dbuf=0;
  326. n=dirread(f, &dir[f].dbuf);
  327. if(n>=0)
  328. dir[f].n=n;
  329. else
  330. dir[f].n=0;
  331. dir[f].i=0;
  332. }
  333. if(dir[f].i==dir[f].n)
  334. return 0;
  335. strcpy(p, dir[f].dbuf[dir[f].i].name);
  336. dir[f].i++;
  337. return 1;
  338. }
  339. void Closedir(int f){
  340. if(f>=0 && f<NFD){
  341. free(dir[f].dbuf);
  342. dir[f].i=0;
  343. dir[f].n=0;
  344. dir[f].dbuf=0;
  345. }
  346. close(f);
  347. }
  348. int interrupted = 0;
  349. void
  350. notifyf(void*, char *s)
  351. {
  352. int i;
  353. for(i=0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
  354. if(strncmp(s, "sys: ", 5)!=0) interrupted=1;
  355. goto Out;
  356. }
  357. pfmt(err, "rc: note: %s\n", s);
  358. noted(NDFLT);
  359. return;
  360. Out:
  361. if(strcmp(s, "interrupt")!=0 || trap[i]==0){
  362. trap[i]++;
  363. ntrap++;
  364. }
  365. if(ntrap>=32){ /* rc is probably in a trap loop */
  366. pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
  367. abort();
  368. }
  369. noted(NCONT);
  370. }
  371. void Trapinit(void){
  372. notify(notifyf);
  373. }
  374. void Unlink(char *name)
  375. {
  376. remove(name);
  377. }
  378. long Write(int fd, char *buf, long cnt)
  379. {
  380. return write(fd, buf, (long)cnt);
  381. }
  382. long Read(int fd, char *buf, long cnt)
  383. {
  384. return read(fd, buf, cnt);
  385. }
  386. long Seek(int fd, long cnt, long whence)
  387. {
  388. return seek(fd, cnt, whence);
  389. }
  390. int Executable(char *file)
  391. {
  392. Dir *statbuf;
  393. int ret;
  394. statbuf = dirstat(file);
  395. if(statbuf == nil) return 0;
  396. ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
  397. free(statbuf);
  398. return ret;
  399. }
  400. int Creat(char *file)
  401. {
  402. return create(file, 1, 0666L);
  403. }
  404. int Dup(int a, int b){
  405. return dup(a, b);
  406. }
  407. int Dup1(int){
  408. return -1;
  409. }
  410. void Exit(char *stat)
  411. {
  412. Updenv();
  413. setstatus(stat);
  414. exits(truestatus()?"":getstatus());
  415. }
  416. int Eintr(void){
  417. return interrupted;
  418. }
  419. void Noerror(void){
  420. interrupted=0;
  421. }
  422. int Isatty(int fd){
  423. Dir *d1, *d2;
  424. int ret;
  425. d1 = dirfstat(fd);
  426. if(d1 == nil) return 0;
  427. if(strncmp(d1->name, "ptty", 4)==0){ /* fwd complaints to philw */
  428. free(d1);
  429. return 1;
  430. }
  431. d2 = dirstat("/dev/cons");
  432. if(d2 == nil){
  433. free(d1);
  434. return 0;
  435. }
  436. ret = (d1->type==d2->type&&d1->dev==d2->dev&&d1->qid.path==d2->qid.path);
  437. free(d1);
  438. free(d2);
  439. return ret;
  440. }
  441. void Abort(void){
  442. pfmt(err, "aborting\n");
  443. flush(err);
  444. Exit("aborting");
  445. }
  446. void Memcpy(char *a, char *b, long n)
  447. {
  448. memmove(a, b, (long)n);
  449. }
  450. void *Malloc(ulong n){
  451. return malloc(n);
  452. }