plan9.c 6.8 KB

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