win32.c 8.5 KB

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