win32.c 8.9 KB

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