plan9.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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. #include "mk.h"
  10. char *shell = "/bin/rc";
  11. char *shellname = "rc";
  12. static Word *encodenulls(char*, int);
  13. void
  14. readenv(void)
  15. {
  16. char *p;
  17. int envf, f;
  18. Dir *e;
  19. char nam[1024];
  20. int i, n, len;
  21. Word *w;
  22. rfork(RFENVG); /* use copy of the current environment variables */
  23. envf = open("/env", OREAD);
  24. if(envf < 0)
  25. return;
  26. while((n = dirread(envf, &e)) > 0){
  27. for(i = 0; i < n; i++){
  28. len = e[i].length;
  29. /* don't import funny names, NULL values,
  30. * or internal mk variables
  31. */
  32. if(len <= 0 || *shname(e[i].name) != '\0')
  33. continue;
  34. if (symlook(e[i].name, S_INTERNAL, 0))
  35. continue;
  36. snprint(nam, sizeof nam, "/env/%s", e[i].name);
  37. f = open(nam, OREAD);
  38. if(f < 0)
  39. continue;
  40. p = Malloc(len+1);
  41. if(read(f, p, len) != len){
  42. perror(nam);
  43. close(f);
  44. continue;
  45. }
  46. close(f);
  47. if (p[len-1] == 0)
  48. len--;
  49. else
  50. p[len] = 0;
  51. w = encodenulls(p, len);
  52. free(p);
  53. p = strdup(e[i].name);
  54. setvar(p, (void *) w);
  55. symlook(p, S_EXPORTED, (void*)"")->u.ptr = "";
  56. }
  57. free(e);
  58. }
  59. close(envf);
  60. }
  61. /* break string of values into words at 01's or nulls*/
  62. static Word *
  63. encodenulls(char *s, int n)
  64. {
  65. Word *w, *head;
  66. char *cp;
  67. head = w = 0;
  68. while (n-- > 0) {
  69. for (cp = s; *cp && *cp != '\0'; cp++)
  70. n--;
  71. *cp = 0;
  72. if (w) {
  73. w->next = newword(s);
  74. w = w->next;
  75. } else
  76. head = w = newword(s);
  77. s = cp+1;
  78. }
  79. if (!head)
  80. head = newword("");
  81. return head;
  82. }
  83. /* as well as 01's, change blanks to nulls, so that rc will
  84. * treat the words as separate arguments
  85. */
  86. void
  87. exportenv(Envy *e)
  88. {
  89. int f, n, hasvalue, first;
  90. Word *w;
  91. Symtab *sy;
  92. char nam[256];
  93. for(;e->name; e++){
  94. sy = symlook(e->name, S_VAR, 0);
  95. if (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0)
  96. hasvalue = 0;
  97. else
  98. hasvalue = 1;
  99. if(sy == 0 && !hasvalue) /* non-existant null symbol */
  100. continue;
  101. snprint(nam, sizeof nam, "/env/%s", e->name);
  102. if (sy != 0 && !hasvalue) { /* Remove from environment */
  103. /* we could remove it from the symbol table
  104. * too, but we're in the child copy, and it
  105. * would still remain in the parent's table.
  106. */
  107. remove(nam);
  108. delword(e->values);
  109. e->values = 0; /* memory leak */
  110. continue;
  111. }
  112. f = create(nam, OWRITE, 0666L);
  113. if(f < 0) {
  114. fprint(2, "can't create %s, f=%d\n", nam, f);
  115. perror(nam);
  116. continue;
  117. }
  118. first = 1;
  119. for (w = e->values; w; w = w->next) {
  120. n = strlen(w->s);
  121. if (n) {
  122. if(first)
  123. first = 0;
  124. else{
  125. if (write (f, "\0", 1) != 1)
  126. perror(nam);
  127. }
  128. if (write(f, w->s, n) != n)
  129. perror(nam);
  130. }
  131. }
  132. close(f);
  133. }
  134. }
  135. int
  136. waitfor(char *msg)
  137. {
  138. Waitmsg *w;
  139. int pid;
  140. if((w=wait()) == nil)
  141. return -1;
  142. strecpy(msg, msg+ERRMAX, w->msg);
  143. pid = w->pid;
  144. free(w);
  145. return pid;
  146. }
  147. void
  148. expunge(int pid, char *msg)
  149. {
  150. postnote(PNPROC, pid, msg);
  151. }
  152. int
  153. execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
  154. {
  155. char *p;
  156. int tot, n, pid, in[2], out[2];
  157. if(buf && pipe(out) < 0){
  158. perror("pipe");
  159. Exit();
  160. }
  161. pid = rfork(RFPROC|RFFDG|RFENVG);
  162. if(pid < 0){
  163. perror("mk rfork");
  164. Exit();
  165. }
  166. if(pid == 0){
  167. if(buf)
  168. close(out[0]);
  169. if(pipe(in) < 0){
  170. perror("pipe");
  171. Exit();
  172. }
  173. pid = fork();
  174. if(pid < 0){
  175. perror("mk fork");
  176. Exit();
  177. }
  178. if(pid != 0){
  179. dup(in[0], 0);
  180. if(buf){
  181. dup(out[1], 1);
  182. close(out[1]);
  183. }
  184. close(in[0]);
  185. close(in[1]);
  186. if (e)
  187. exportenv(e);
  188. if(shflags)
  189. execl(shell, shellname, shflags, args, nil);
  190. else
  191. execl(shell, shellname, args, nil);
  192. perror(shell);
  193. _exits("exec");
  194. }
  195. close(out[1]);
  196. close(in[0]);
  197. p = cmd+strlen(cmd);
  198. while(cmd < p){
  199. n = write(in[1], cmd, p-cmd);
  200. if(n < 0)
  201. break;
  202. cmd += n;
  203. }
  204. close(in[1]);
  205. _exits(0);
  206. }
  207. if(buf){
  208. close(out[1]);
  209. tot = 0;
  210. for(;;){
  211. if (buf->current >= buf->end)
  212. growbuf(buf);
  213. n = read(out[0], buf->current, buf->end-buf->current);
  214. if(n <= 0)
  215. break;
  216. buf->current += n;
  217. tot += n;
  218. }
  219. if (tot && buf->current[-1] == '\n')
  220. buf->current--;
  221. close(out[0]);
  222. }
  223. return pid;
  224. }
  225. int
  226. pipecmd(char *cmd, Envy *e, int *fd)
  227. {
  228. int pid, pfd[2];
  229. if(DEBUG(D_EXEC))
  230. fprint(1, "pipecmd='%s'\n", cmd);/**/
  231. if(fd && pipe(pfd) < 0){
  232. perror("pipe");
  233. Exit();
  234. }
  235. pid = rfork(RFPROC|RFFDG|RFENVG);
  236. if(pid < 0){
  237. perror("mk fork");
  238. Exit();
  239. }
  240. if(pid == 0){
  241. if(fd){
  242. close(pfd[0]);
  243. dup(pfd[1], 1);
  244. close(pfd[1]);
  245. }
  246. if(e)
  247. exportenv(e);
  248. if(shflags)
  249. execl(shell, shellname, shflags, "-c", cmd, nil);
  250. else
  251. execl(shell, shellname, "-c", cmd, nil);
  252. perror(shell);
  253. _exits("exec");
  254. }
  255. if(fd){
  256. close(pfd[1]);
  257. *fd = pfd[0];
  258. }
  259. return pid;
  260. }
  261. void
  262. Exit(void)
  263. {
  264. while(waitpid() >= 0)
  265. ;
  266. exits("error");
  267. }
  268. int
  269. notifyf(void *a, char *msg)
  270. {
  271. static int nnote;
  272. USED(a);
  273. if(++nnote > 100){ /* until andrew fixes his program */
  274. fprint(2, "mk: too many notes\n");
  275. notify(0);
  276. abort();
  277. }
  278. if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0)
  279. return 0;
  280. killchildren(msg);
  281. return -1;
  282. }
  283. void
  284. catchnotes()
  285. {
  286. atnotify(notifyf, 1);
  287. }
  288. char*
  289. maketmp(void)
  290. {
  291. static char temp[] = "/tmp/mkargXXXXXX";
  292. mktemp(temp);
  293. return temp;
  294. }
  295. int
  296. chgtime(char *name)
  297. {
  298. Dir sbuf;
  299. if(access(name, AEXIST) >= 0) {
  300. nulldir(&sbuf);
  301. sbuf.mtime = time((int32_t *)0);
  302. return dirwstat(name, &sbuf);
  303. }
  304. return close(create(name, OWRITE, 0666));
  305. }
  306. void
  307. rcopy(char **to, Resub *match, int n)
  308. {
  309. int c;
  310. char *p;
  311. *to = match->sp; /* stem0 matches complete target */
  312. for(to++, match++; --n > 0; to++, match++){
  313. if(match->sp && match->ep){
  314. p = match->ep;
  315. c = *p;
  316. *p = 0;
  317. *to = strdup(match->sp);
  318. *p = c;
  319. }
  320. else
  321. *to = 0;
  322. }
  323. }
  324. void
  325. dirtime(char *dir, char *path)
  326. {
  327. int i, fd, n;
  328. uint32_t mtime;
  329. Dir *d;
  330. char buf[4096];
  331. fd = open(dir, OREAD);
  332. if(fd >= 0){
  333. while((n = dirread(fd, &d)) > 0){
  334. for(i=0; i<n; i++){
  335. mtime = d[i].mtime;
  336. /* defensive driving: this does happen */
  337. if(mtime == 0)
  338. mtime = 1;
  339. snprint(buf, sizeof buf, "%s%s", path,
  340. d[i].name);
  341. if(symlook(buf, S_TIME, 0) == nil)
  342. symlook(strdup(buf), S_TIME,
  343. (void*)mtime)->u.value = mtime;
  344. }
  345. free(d);
  346. }
  347. close(fd);
  348. }
  349. }
  350. void
  351. bulkmtime(char *dir)
  352. {
  353. char buf[4096];
  354. char *ss, *s, *sym;
  355. if(dir){
  356. sym = dir;
  357. s = dir;
  358. if(strcmp(dir, "/") == 0)
  359. strecpy(buf, buf + sizeof buf - 1, dir);
  360. else
  361. snprint(buf, sizeof buf, "%s/", dir);
  362. }else{
  363. s = ".";
  364. sym = "";
  365. buf[0] = 0;
  366. }
  367. if(symlook(sym, S_BULKED, 0))
  368. return;
  369. ss = strdup(sym);
  370. symlook(ss, S_BULKED, (void*)ss);
  371. dirtime(s, buf);
  372. }
  373. uint32_t
  374. mkmtime(char *name, int force)
  375. {
  376. Dir *d;
  377. char *s, *ss, carry;
  378. uint32_t t;
  379. Symtab *sym;
  380. char buf[4096];
  381. strecpy(buf, buf + sizeof buf - 1, name);
  382. cleanname(buf);
  383. name = buf;
  384. s = utfrrune(name, '/');
  385. if(s == name)
  386. s++;
  387. if(s){
  388. ss = name;
  389. carry = *s;
  390. *s = 0;
  391. }else{
  392. ss = 0;
  393. carry = 0;
  394. }
  395. bulkmtime(ss);
  396. if(carry)
  397. *s = carry;
  398. if(!force){
  399. sym = symlook(name, S_TIME, 0);
  400. if(sym)
  401. return sym->u.value;
  402. return 0;
  403. }
  404. if((d = dirstat(name)) == nil)
  405. return 0;
  406. t = d->mtime;
  407. free(d);
  408. return t;
  409. }