1219b2ee8SDavid du Colombier #include "mk.h" 2219b2ee8SDavid du Colombier 37dd7cddfSDavid du Colombier char *shell = "/bin/rc"; 47dd7cddfSDavid du Colombier char *shellname = "rc"; 57dd7cddfSDavid du Colombier 67dd7cddfSDavid du Colombier static Word *encodenulls(char*, int); 77dd7cddfSDavid du Colombier 8219b2ee8SDavid du Colombier void 97dd7cddfSDavid du Colombier readenv(void) 10219b2ee8SDavid du Colombier { 117dd7cddfSDavid du Colombier char *p; 12219b2ee8SDavid du Colombier int envf, f; 139a747e4fSDavid du Colombier Dir *e; 149a747e4fSDavid du Colombier char nam[1024]; 15219b2ee8SDavid du Colombier int i, n, len; 16219b2ee8SDavid du Colombier Word *w; 17219b2ee8SDavid du Colombier 187dd7cddfSDavid du Colombier rfork(RFENVG); /* use copy of the current environment variables */ 197dd7cddfSDavid du Colombier 20219b2ee8SDavid du Colombier envf = open("/env", OREAD); 21219b2ee8SDavid du Colombier if(envf < 0) 22219b2ee8SDavid du Colombier return; 239a747e4fSDavid du Colombier while((n = dirread(envf, &e)) > 0){ 24219b2ee8SDavid du Colombier for(i = 0; i < n; i++){ 25219b2ee8SDavid du Colombier len = e[i].length; 267dd7cddfSDavid du Colombier /* don't import funny names, NULL values, 277dd7cddfSDavid du Colombier * or internal mk variables 287dd7cddfSDavid du Colombier */ 297dd7cddfSDavid du Colombier if(len <= 0 || *shname(e[i].name) != '\0') 307dd7cddfSDavid du Colombier continue; 317dd7cddfSDavid du Colombier if (symlook(e[i].name, S_INTERNAL, 0)) 32219b2ee8SDavid du Colombier continue; 33276e7d6dSDavid du Colombier snprint(nam, sizeof nam, "/env/%s", e[i].name); 34219b2ee8SDavid du Colombier f = open(nam, OREAD); 35219b2ee8SDavid du Colombier if(f < 0) 36219b2ee8SDavid du Colombier continue; 377dd7cddfSDavid du Colombier p = Malloc(len+1); 387dd7cddfSDavid du Colombier if(read(f, p, len) != len){ 39219b2ee8SDavid du Colombier perror(nam); 40219b2ee8SDavid du Colombier close(f); 41219b2ee8SDavid du Colombier continue; 42219b2ee8SDavid du Colombier } 43219b2ee8SDavid du Colombier close(f); 447dd7cddfSDavid du Colombier if (p[len-1] == 0) 45219b2ee8SDavid du Colombier len--; 46219b2ee8SDavid du Colombier else 477dd7cddfSDavid du Colombier p[len] = 0; 487dd7cddfSDavid du Colombier w = encodenulls(p, len); 497dd7cddfSDavid du Colombier free(p); 507dd7cddfSDavid du Colombier p = strdup(e[i].name); 517dd7cddfSDavid du Colombier setvar(p, (void *) w); 524de34a7eSDavid du Colombier symlook(p, S_EXPORTED, (void*)"")->u.ptr = ""; 53219b2ee8SDavid du Colombier } 549a747e4fSDavid du Colombier free(e); 55219b2ee8SDavid du Colombier } 56219b2ee8SDavid du Colombier close(envf); 57219b2ee8SDavid du Colombier } 58219b2ee8SDavid du Colombier 597dd7cddfSDavid du Colombier /* break string of values into words at 01's or nulls*/ 607dd7cddfSDavid du Colombier static Word * 61219b2ee8SDavid du Colombier encodenulls(char *s, int n) 62219b2ee8SDavid du Colombier { 63219b2ee8SDavid du Colombier Word *w, *head; 64219b2ee8SDavid du Colombier char *cp; 65219b2ee8SDavid du Colombier 66219b2ee8SDavid du Colombier head = w = 0; 67219b2ee8SDavid du Colombier while (n-- > 0) { 687dd7cddfSDavid du Colombier for (cp = s; *cp && *cp != '\0'; cp++) 69219b2ee8SDavid du Colombier n--; 70219b2ee8SDavid du Colombier *cp = 0; 71219b2ee8SDavid du Colombier if (w) { 72219b2ee8SDavid du Colombier w->next = newword(s); 73219b2ee8SDavid du Colombier w = w->next; 74219b2ee8SDavid du Colombier } else 75219b2ee8SDavid du Colombier head = w = newword(s); 76219b2ee8SDavid du Colombier s = cp+1; 77219b2ee8SDavid du Colombier } 78219b2ee8SDavid du Colombier if (!head) 79219b2ee8SDavid du Colombier head = newword(""); 80219b2ee8SDavid du Colombier return head; 81219b2ee8SDavid du Colombier } 82219b2ee8SDavid du Colombier 83219b2ee8SDavid du Colombier /* as well as 01's, change blanks to nulls, so that rc will 84219b2ee8SDavid du Colombier * treat the words as separate arguments 85219b2ee8SDavid du Colombier */ 86219b2ee8SDavid du Colombier void 877dd7cddfSDavid du Colombier exportenv(Envy *e) 88219b2ee8SDavid du Colombier { 897dd7cddfSDavid du Colombier int f, n, hasvalue, first; 907dd7cddfSDavid du Colombier Word *w; 917dd7cddfSDavid du Colombier Symtab *sy; 929a747e4fSDavid du Colombier char nam[256]; 93219b2ee8SDavid du Colombier 947dd7cddfSDavid du Colombier for(;e->name; e++){ 957dd7cddfSDavid du Colombier sy = symlook(e->name, S_VAR, 0); 967dd7cddfSDavid du Colombier if (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0) 977dd7cddfSDavid du Colombier hasvalue = 0; 987dd7cddfSDavid du Colombier else 997dd7cddfSDavid du Colombier hasvalue = 1; 1007dd7cddfSDavid du Colombier if(sy == 0 && !hasvalue) /* non-existant null symbol */ 1017dd7cddfSDavid du Colombier continue; 102276e7d6dSDavid du Colombier snprint(nam, sizeof nam, "/env/%s", e->name); 1037dd7cddfSDavid du Colombier if (sy != 0 && !hasvalue) { /* Remove from environment */ 10499eb86a7SDavid du Colombier /* we could remove it from the symbol table 1057dd7cddfSDavid du Colombier * too, but we're in the child copy, and it 1067dd7cddfSDavid du Colombier * would still remain in the parent's table. 1077dd7cddfSDavid du Colombier */ 1087dd7cddfSDavid du Colombier remove(nam); 1097dd7cddfSDavid du Colombier delword(e->values); 1107dd7cddfSDavid du Colombier e->values = 0; /* memory leak */ 1117dd7cddfSDavid du Colombier continue; 1127dd7cddfSDavid du Colombier } 1137dd7cddfSDavid du Colombier 1147dd7cddfSDavid du Colombier f = create(nam, OWRITE, 0666L); 115219b2ee8SDavid du Colombier if(f < 0) { 1167dd7cddfSDavid du Colombier fprint(2, "can't create %s, f=%d\n", nam, f); 1177dd7cddfSDavid du Colombier perror(nam); 1187dd7cddfSDavid du Colombier continue; 119219b2ee8SDavid du Colombier } 1207dd7cddfSDavid du Colombier first = 1; 1217dd7cddfSDavid du Colombier for (w = e->values; w; w = w->next) { 1227dd7cddfSDavid du Colombier n = strlen(w->s); 123219b2ee8SDavid du Colombier if (n) { 1247dd7cddfSDavid du Colombier if(first) 1257dd7cddfSDavid du Colombier first = 0; 1267dd7cddfSDavid du Colombier else{ 127219b2ee8SDavid du Colombier if (write (f, "\0", 1) != 1) 1287dd7cddfSDavid du Colombier perror(nam); 129219b2ee8SDavid du Colombier } 1307dd7cddfSDavid du Colombier if (write(f, w->s, n) != n) 1317dd7cddfSDavid du Colombier perror(nam); 1327dd7cddfSDavid du Colombier } 133219b2ee8SDavid du Colombier } 134219b2ee8SDavid du Colombier close(f); 135219b2ee8SDavid du Colombier } 136219b2ee8SDavid du Colombier } 137219b2ee8SDavid du Colombier 138219b2ee8SDavid du Colombier int 139219b2ee8SDavid du Colombier waitfor(char *msg) 140219b2ee8SDavid du Colombier { 1419a747e4fSDavid du Colombier Waitmsg *w; 142219b2ee8SDavid du Colombier int pid; 143219b2ee8SDavid du Colombier 1449a747e4fSDavid du Colombier if((w=wait()) == nil) 1459a747e4fSDavid du Colombier return -1; 1469a747e4fSDavid du Colombier strecpy(msg, msg+ERRMAX, w->msg); 1479a747e4fSDavid du Colombier pid = w->pid; 1489a747e4fSDavid du Colombier free(w); 149219b2ee8SDavid du Colombier return pid; 150219b2ee8SDavid du Colombier } 151219b2ee8SDavid du Colombier 152219b2ee8SDavid du Colombier void 153219b2ee8SDavid du Colombier expunge(int pid, char *msg) 154219b2ee8SDavid du Colombier { 155219b2ee8SDavid du Colombier postnote(PNPROC, pid, msg); 156219b2ee8SDavid du Colombier } 1577dd7cddfSDavid du Colombier 1587dd7cddfSDavid du Colombier int 1597dd7cddfSDavid du Colombier execsh(char *args, char *cmd, Bufblock *buf, Envy *e) 1607dd7cddfSDavid du Colombier { 1617dd7cddfSDavid du Colombier char *p; 1627dd7cddfSDavid du Colombier int tot, n, pid, in[2], out[2]; 1637dd7cddfSDavid du Colombier 1647dd7cddfSDavid du Colombier if(buf && pipe(out) < 0){ 1657dd7cddfSDavid du Colombier perror("pipe"); 1667dd7cddfSDavid du Colombier Exit(); 1677dd7cddfSDavid du Colombier } 1687dd7cddfSDavid du Colombier pid = rfork(RFPROC|RFFDG|RFENVG); 1697dd7cddfSDavid du Colombier if(pid < 0){ 1707dd7cddfSDavid du Colombier perror("mk rfork"); 1717dd7cddfSDavid du Colombier Exit(); 1727dd7cddfSDavid du Colombier } 1737dd7cddfSDavid du Colombier if(pid == 0){ 1747dd7cddfSDavid du Colombier if(buf) 1757dd7cddfSDavid du Colombier close(out[0]); 1767dd7cddfSDavid du Colombier if(pipe(in) < 0){ 1777dd7cddfSDavid du Colombier perror("pipe"); 1787dd7cddfSDavid du Colombier Exit(); 1797dd7cddfSDavid du Colombier } 1807dd7cddfSDavid du Colombier pid = fork(); 1817dd7cddfSDavid du Colombier if(pid < 0){ 1827dd7cddfSDavid du Colombier perror("mk fork"); 1837dd7cddfSDavid du Colombier Exit(); 1847dd7cddfSDavid du Colombier } 1857dd7cddfSDavid du Colombier if(pid != 0){ 1867dd7cddfSDavid du Colombier dup(in[0], 0); 1877dd7cddfSDavid du Colombier if(buf){ 1887dd7cddfSDavid du Colombier dup(out[1], 1); 1897dd7cddfSDavid du Colombier close(out[1]); 1907dd7cddfSDavid du Colombier } 1917dd7cddfSDavid du Colombier close(in[0]); 1927dd7cddfSDavid du Colombier close(in[1]); 1937dd7cddfSDavid du Colombier if (e) 1947dd7cddfSDavid du Colombier exportenv(e); 1957dd7cddfSDavid du Colombier if(shflags) 196f19e7b74SDavid du Colombier execl(shell, shellname, shflags, args, nil); 1977dd7cddfSDavid du Colombier else 198f19e7b74SDavid du Colombier execl(shell, shellname, args, nil); 1997dd7cddfSDavid du Colombier perror(shell); 2007dd7cddfSDavid du Colombier _exits("exec"); 2017dd7cddfSDavid du Colombier } 2027dd7cddfSDavid du Colombier close(out[1]); 2037dd7cddfSDavid du Colombier close(in[0]); 20499eb86a7SDavid du Colombier p = cmd+strlen(cmd); 20599eb86a7SDavid du Colombier while(cmd < p){ 2067dd7cddfSDavid du Colombier n = write(in[1], cmd, p-cmd); 2077dd7cddfSDavid du Colombier if(n < 0) 2087dd7cddfSDavid du Colombier break; 20999eb86a7SDavid du Colombier cmd += n; 2107dd7cddfSDavid du Colombier } 2117dd7cddfSDavid du Colombier close(in[1]); 2127dd7cddfSDavid du Colombier _exits(0); 2137dd7cddfSDavid du Colombier } 2147dd7cddfSDavid du Colombier if(buf){ 2157dd7cddfSDavid du Colombier close(out[1]); 2167dd7cddfSDavid du Colombier tot = 0; 2177dd7cddfSDavid du Colombier for(;;){ 2187dd7cddfSDavid du Colombier if (buf->current >= buf->end) 2197dd7cddfSDavid du Colombier growbuf(buf); 2207dd7cddfSDavid du Colombier n = read(out[0], buf->current, buf->end-buf->current); 2217dd7cddfSDavid du Colombier if(n <= 0) 2227dd7cddfSDavid du Colombier break; 2237dd7cddfSDavid du Colombier buf->current += n; 2247dd7cddfSDavid du Colombier tot += n; 2257dd7cddfSDavid du Colombier } 2267dd7cddfSDavid du Colombier if (tot && buf->current[-1] == '\n') 2277dd7cddfSDavid du Colombier buf->current--; 2287dd7cddfSDavid du Colombier close(out[0]); 2297dd7cddfSDavid du Colombier } 2307dd7cddfSDavid du Colombier return pid; 2317dd7cddfSDavid du Colombier } 2327dd7cddfSDavid du Colombier 2337dd7cddfSDavid du Colombier int 2347dd7cddfSDavid du Colombier pipecmd(char *cmd, Envy *e, int *fd) 2357dd7cddfSDavid du Colombier { 2367dd7cddfSDavid du Colombier int pid, pfd[2]; 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombier if(DEBUG(D_EXEC)) 2397dd7cddfSDavid du Colombier fprint(1, "pipecmd='%s'\n", cmd);/**/ 2407dd7cddfSDavid du Colombier 2417dd7cddfSDavid du Colombier if(fd && pipe(pfd) < 0){ 2427dd7cddfSDavid du Colombier perror("pipe"); 2437dd7cddfSDavid du Colombier Exit(); 2447dd7cddfSDavid du Colombier } 2457dd7cddfSDavid du Colombier pid = rfork(RFPROC|RFFDG|RFENVG); 2467dd7cddfSDavid du Colombier if(pid < 0){ 2477dd7cddfSDavid du Colombier perror("mk fork"); 2487dd7cddfSDavid du Colombier Exit(); 2497dd7cddfSDavid du Colombier } 2507dd7cddfSDavid du Colombier if(pid == 0){ 2517dd7cddfSDavid du Colombier if(fd){ 2527dd7cddfSDavid du Colombier close(pfd[0]); 2537dd7cddfSDavid du Colombier dup(pfd[1], 1); 2547dd7cddfSDavid du Colombier close(pfd[1]); 2557dd7cddfSDavid du Colombier } 2567dd7cddfSDavid du Colombier if(e) 2577dd7cddfSDavid du Colombier exportenv(e); 2587dd7cddfSDavid du Colombier if(shflags) 259f19e7b74SDavid du Colombier execl(shell, shellname, shflags, "-c", cmd, nil); 2607dd7cddfSDavid du Colombier else 261f19e7b74SDavid du Colombier execl(shell, shellname, "-c", cmd, nil); 2627dd7cddfSDavid du Colombier perror(shell); 2637dd7cddfSDavid du Colombier _exits("exec"); 2647dd7cddfSDavid du Colombier } 2657dd7cddfSDavid du Colombier if(fd){ 2667dd7cddfSDavid du Colombier close(pfd[1]); 2677dd7cddfSDavid du Colombier *fd = pfd[0]; 2687dd7cddfSDavid du Colombier } 2697dd7cddfSDavid du Colombier return pid; 2707dd7cddfSDavid du Colombier } 2717dd7cddfSDavid du Colombier 2727dd7cddfSDavid du Colombier void 2737dd7cddfSDavid du Colombier Exit(void) 2747dd7cddfSDavid du Colombier { 2759a747e4fSDavid du Colombier while(waitpid() >= 0) 2767dd7cddfSDavid du Colombier ; 2777dd7cddfSDavid du Colombier exits("error"); 2787dd7cddfSDavid du Colombier } 2797dd7cddfSDavid du Colombier 2807dd7cddfSDavid du Colombier int 2817dd7cddfSDavid du Colombier notifyf(void *a, char *msg) 2827dd7cddfSDavid du Colombier { 2837dd7cddfSDavid du Colombier static int nnote; 2847dd7cddfSDavid du Colombier 2857dd7cddfSDavid du Colombier USED(a); 2867dd7cddfSDavid du Colombier if(++nnote > 100){ /* until andrew fixes his program */ 2877dd7cddfSDavid du Colombier fprint(2, "mk: too many notes\n"); 2887dd7cddfSDavid du Colombier notify(0); 2897dd7cddfSDavid du Colombier abort(); 2907dd7cddfSDavid du Colombier } 2917dd7cddfSDavid du Colombier if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0) 2927dd7cddfSDavid du Colombier return 0; 2937dd7cddfSDavid du Colombier killchildren(msg); 2947dd7cddfSDavid du Colombier return -1; 2957dd7cddfSDavid du Colombier } 2967dd7cddfSDavid du Colombier 2977dd7cddfSDavid du Colombier void 2987dd7cddfSDavid du Colombier catchnotes() 2997dd7cddfSDavid du Colombier { 3007dd7cddfSDavid du Colombier atnotify(notifyf, 1); 3017dd7cddfSDavid du Colombier } 3027dd7cddfSDavid du Colombier 3037dd7cddfSDavid du Colombier char* 3047dd7cddfSDavid du Colombier maketmp(void) 3057dd7cddfSDavid du Colombier { 3067dd7cddfSDavid du Colombier static char temp[] = "/tmp/mkargXXXXXX"; 3077dd7cddfSDavid du Colombier 3087dd7cddfSDavid du Colombier mktemp(temp); 3097dd7cddfSDavid du Colombier return temp; 3107dd7cddfSDavid du Colombier } 3117dd7cddfSDavid du Colombier 3127dd7cddfSDavid du Colombier int 3137dd7cddfSDavid du Colombier chgtime(char *name) 3147dd7cddfSDavid du Colombier { 3157dd7cddfSDavid du Colombier Dir sbuf; 3167dd7cddfSDavid du Colombier 3179a747e4fSDavid du Colombier if(access(name, AEXIST) >= 0) { 3189a747e4fSDavid du Colombier nulldir(&sbuf); 3197dd7cddfSDavid du Colombier sbuf.mtime = time((long *)0); 3207dd7cddfSDavid du Colombier return dirwstat(name, &sbuf); 3217dd7cddfSDavid du Colombier } 3227dd7cddfSDavid du Colombier return close(create(name, OWRITE, 0666)); 3237dd7cddfSDavid du Colombier } 3247dd7cddfSDavid du Colombier 3257dd7cddfSDavid du Colombier void 3267dd7cddfSDavid du Colombier rcopy(char **to, Resub *match, int n) 3277dd7cddfSDavid du Colombier { 3287dd7cddfSDavid du Colombier int c; 3297dd7cddfSDavid du Colombier char *p; 3307dd7cddfSDavid du Colombier 3317dd7cddfSDavid du Colombier *to = match->sp; /* stem0 matches complete target */ 3327dd7cddfSDavid du Colombier for(to++, match++; --n > 0; to++, match++){ 3337dd7cddfSDavid du Colombier if(match->sp && match->ep){ 3347dd7cddfSDavid du Colombier p = match->ep; 3357dd7cddfSDavid du Colombier c = *p; 3367dd7cddfSDavid du Colombier *p = 0; 3377dd7cddfSDavid du Colombier *to = strdup(match->sp); 3387dd7cddfSDavid du Colombier *p = c; 3397dd7cddfSDavid du Colombier } 3407dd7cddfSDavid du Colombier else 3417dd7cddfSDavid du Colombier *to = 0; 3427dd7cddfSDavid du Colombier } 3437dd7cddfSDavid du Colombier } 3447dd7cddfSDavid du Colombier 345dc5a79c1SDavid du Colombier void 346dc5a79c1SDavid du Colombier dirtime(char *dir, char *path) 3477dd7cddfSDavid du Colombier { 348dc5a79c1SDavid du Colombier int i, fd, n; 349*7f49a7ffSDavid du Colombier ulong mtime; 350dc5a79c1SDavid du Colombier Dir *d; 351dc5a79c1SDavid du Colombier char buf[4096]; 3529a747e4fSDavid du Colombier 353dc5a79c1SDavid du Colombier fd = open(dir, OREAD); 354dc5a79c1SDavid du Colombier if(fd >= 0){ 355dc5a79c1SDavid du Colombier while((n = dirread(fd, &d)) > 0){ 356dc5a79c1SDavid du Colombier for(i=0; i<n; i++){ 357d1da931cSDavid du Colombier mtime = d[i].mtime; 358d1da931cSDavid du Colombier /* defensive driving: this does happen */ 359d1da931cSDavid du Colombier if(mtime == 0) 360d1da931cSDavid du Colombier mtime = 1; 361d1da931cSDavid du Colombier snprint(buf, sizeof buf, "%s%s", path, 362d1da931cSDavid du Colombier d[i].name); 363d1da931cSDavid du Colombier if(symlook(buf, S_TIME, 0) == nil) 364d1da931cSDavid du Colombier symlook(strdup(buf), S_TIME, 365d1da931cSDavid du Colombier (void*)mtime)->u.value = mtime; 366dc5a79c1SDavid du Colombier } 367dc5a79c1SDavid du Colombier free(d); 368dc5a79c1SDavid du Colombier } 369dc5a79c1SDavid du Colombier close(fd); 370dc5a79c1SDavid du Colombier } 371dc5a79c1SDavid du Colombier } 372dc5a79c1SDavid du Colombier 373dc5a79c1SDavid du Colombier void 374dc5a79c1SDavid du Colombier bulkmtime(char *dir) 375dc5a79c1SDavid du Colombier { 376dc5a79c1SDavid du Colombier char buf[4096]; 37707a38badSDavid du Colombier char *ss, *s, *sym; 378dc5a79c1SDavid du Colombier 379dc5a79c1SDavid du Colombier if(dir){ 38007a38badSDavid du Colombier sym = dir; 381dc5a79c1SDavid du Colombier s = dir; 382dc5a79c1SDavid du Colombier if(strcmp(dir, "/") == 0) 383d1da931cSDavid du Colombier strecpy(buf, buf + sizeof buf - 1, dir); 384dc5a79c1SDavid du Colombier else 385d1da931cSDavid du Colombier snprint(buf, sizeof buf, "%s/", dir); 386dc5a79c1SDavid du Colombier }else{ 387dc5a79c1SDavid du Colombier s = "."; 38807a38badSDavid du Colombier sym = ""; 389dc5a79c1SDavid du Colombier buf[0] = 0; 390dc5a79c1SDavid du Colombier } 39107a38badSDavid du Colombier if(symlook(sym, S_BULKED, 0)) 392dc5a79c1SDavid du Colombier return; 39307a38badSDavid du Colombier ss = strdup(sym); 394dc5a79c1SDavid du Colombier symlook(ss, S_BULKED, (void*)ss); 395dc5a79c1SDavid du Colombier dirtime(s, buf); 396dc5a79c1SDavid du Colombier } 397dc5a79c1SDavid du Colombier 398dc5a79c1SDavid du Colombier ulong 399dc5a79c1SDavid du Colombier mkmtime(char *name, int force) 400dc5a79c1SDavid du Colombier { 401dc5a79c1SDavid du Colombier Dir *d; 402dc5a79c1SDavid du Colombier char *s, *ss, carry; 403dc5a79c1SDavid du Colombier ulong t; 404dc5a79c1SDavid du Colombier Symtab *sym; 40507a38badSDavid du Colombier char buf[4096]; 40607a38badSDavid du Colombier 407d1da931cSDavid du Colombier strecpy(buf, buf + sizeof buf - 1, name); 40807a38badSDavid du Colombier cleanname(buf); 40907a38badSDavid du Colombier name = buf; 410dc5a79c1SDavid du Colombier 411dc5a79c1SDavid du Colombier s = utfrrune(name, '/'); 412dc5a79c1SDavid du Colombier if(s == name) 413dc5a79c1SDavid du Colombier s++; 414dc5a79c1SDavid du Colombier if(s){ 415dc5a79c1SDavid du Colombier ss = name; 416dc5a79c1SDavid du Colombier carry = *s; 417dc5a79c1SDavid du Colombier *s = 0; 418dc5a79c1SDavid du Colombier }else{ 419dc5a79c1SDavid du Colombier ss = 0; 420dc5a79c1SDavid du Colombier carry = 0; 421dc5a79c1SDavid du Colombier } 422dc5a79c1SDavid du Colombier bulkmtime(ss); 423dc5a79c1SDavid du Colombier if(carry) 424dc5a79c1SDavid du Colombier *s = carry; 425dc5a79c1SDavid du Colombier if(!force){ 426dc5a79c1SDavid du Colombier sym = symlook(name, S_TIME, 0); 427dc5a79c1SDavid du Colombier if(sym) 4284de34a7eSDavid du Colombier return sym->u.value; 4299a747e4fSDavid du Colombier return 0; 430dc5a79c1SDavid du Colombier } 431dc5a79c1SDavid du Colombier if((d = dirstat(name)) == nil) 432dc5a79c1SDavid du Colombier return 0; 433dc5a79c1SDavid du Colombier t = d->mtime; 434dc5a79c1SDavid du Colombier free(d); 4359a747e4fSDavid du Colombier return t; 4367dd7cddfSDavid du Colombier } 437dc5a79c1SDavid du Colombier 438