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