]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mk/plan9.c
ip/cifsd: dont return garbage in upper 32 bit of unix extension stat fields
[plan9front.git] / sys / src / cmd / mk / plan9.c
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                         snprint(nam, sizeof 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                 snprint(nam, sizeof 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                 if(buf)
203                         close(out[1]);
204                 close(in[0]);
205                 p = cmd+strlen(cmd);
206                 while(cmd < p){
207                         n = write(in[1], cmd, p-cmd);
208                         if(n < 0)
209                                 break;
210                         cmd += n;
211                 }
212                 close(in[1]);
213                 _exits(0);
214         }
215         if(buf){
216                 close(out[1]);
217                 tot = 0;
218                 for(;;){
219                         if (buf->current >= buf->end)
220                                 growbuf(buf);
221                         n = read(out[0], buf->current, buf->end-buf->current);
222                         if(n <= 0)
223                                 break;
224                         buf->current += n;
225                         tot += n;
226                 }
227                 if (tot && buf->current[-1] == '\n')
228                         buf->current--;
229                 close(out[0]);
230         }
231         return pid;
232 }
233
234 int
235 pipecmd(char *cmd, Envy *e, int *fd)
236 {
237         int pid, pfd[2];
238
239         if(DEBUG(D_EXEC))
240                 fprint(1, "pipecmd='%s'\n", cmd);/**/
241
242         if(fd && pipe(pfd) < 0){
243                 perror("pipe");
244                 Exit();
245         }
246         pid = rfork(RFPROC|RFFDG|RFENVG);
247         if(pid < 0){
248                 perror("mk fork");
249                 Exit();
250         }
251         if(pid == 0){
252                 if(fd){
253                         close(pfd[0]);
254                         dup(pfd[1], 1);
255                         close(pfd[1]);
256                 }
257                 if(e)
258                         exportenv(e);
259                 if(shflags)
260                         execl(shell, shellname, shflags, "-c", cmd, nil);
261                 else
262                         execl(shell, shellname, "-c", cmd, nil);
263                 perror(shell);
264                 _exits("exec");
265         }
266         if(fd){
267                 close(pfd[1]);
268                 *fd = pfd[0];
269         }
270         return pid;
271 }
272
273 void
274 Exit(void)
275 {
276         while(waitpid() >= 0)
277                 ;
278         exits("error");
279 }
280
281 int
282 notifyf(void *a, char *msg)
283 {
284         static int nnote;
285
286         USED(a);
287         if(++nnote > 100){      /* until andrew fixes his program */
288                 fprint(2, "mk: too many notes\n");
289                 notify(0);
290                 abort();
291         }
292         if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0)
293                 return 0;
294         killchildren(msg);
295         return -1;
296 }
297
298 void
299 catchnotes()
300 {
301         atnotify(notifyf, 1);
302 }
303
304 char*
305 maketmp(void)
306 {
307         static char temp[] = "/tmp/mkargXXXXXX";
308
309         mktemp(temp);
310         return temp;
311 }
312
313 int
314 chgtime(char *name)
315 {
316         Dir sbuf;
317
318         if(access(name, AEXIST) >= 0) {
319                 nulldir(&sbuf);
320                 sbuf.mtime = time((long *)0);
321                 return dirwstat(name, &sbuf);
322         }
323         return close(create(name, OWRITE, 0666));
324 }
325
326 void
327 rcopy(char **to, Resub *match, int n)
328 {
329         int c;
330         char *p;
331
332         *to = match->sp;                /* stem0 matches complete target */
333         for(to++, match++; --n > 0; to++, match++){
334                 if(match->sp && match->ep){
335                         p = match->ep;
336                         c = *p;
337                         *p = 0;
338                         *to = strdup(match->sp);
339                         *p = c;
340                 }
341                 else
342                         *to = 0;
343         }
344 }
345
346 void
347 dirtime(char *dir, char *path)
348 {
349         int i, fd, n;
350         long mtime;
351         Dir *d;
352         char buf[4096];
353
354         fd = open(dir, OREAD);
355         if(fd >= 0){
356                 while((n = dirread(fd, &d)) > 0){
357                         for(i=0; i<n; i++){
358                                 mtime = d[i].mtime;
359                                 /* defensive driving: this does happen */
360                                 if(mtime == 0)
361                                         mtime = 1;
362                                 snprint(buf, sizeof buf, "%s%s", path,
363                                         d[i].name);
364                                 if(symlook(buf, S_TIME, 0) == nil)
365                                         symlook(strdup(buf), S_TIME,
366                                                 (void*)mtime)->u.value = mtime;
367                         }
368                         free(d);
369                 }
370                 close(fd);
371         }
372 }
373
374 void
375 bulkmtime(char *dir)
376 {
377         char buf[4096];
378         char *ss, *s, *sym;
379
380         if(dir){
381                 sym = dir;
382                 s = dir;
383                 if(strcmp(dir, "/") == 0)
384                         strecpy(buf, buf + sizeof buf - 1, dir);
385                 else
386                         snprint(buf, sizeof buf, "%s/", dir);
387         }else{
388                 s = ".";
389                 sym = "";
390                 buf[0] = 0;
391         }
392         if(symlook(sym, S_BULKED, 0))
393                 return;
394         ss = strdup(sym);
395         symlook(ss, S_BULKED, (void*)ss);
396         dirtime(s, buf);
397 }
398
399 ulong
400 mkmtime(char *name, int force)
401 {
402         Dir *d;
403         char *s, *ss, carry;
404         ulong t;
405         Symtab *sym;
406         char buf[4096];
407
408         strecpy(buf, buf + sizeof buf - 1, name);
409         cleanname(buf);
410         name = buf;
411
412         s = utfrrune(name, '/');
413         if(s == name)
414                 s++;
415         if(s){
416                 ss = name;
417                 carry = *s;
418                 *s = 0;
419         }else{
420                 ss = 0;
421                 carry = 0;
422         }
423         bulkmtime(ss);
424         if(carry)
425                 *s = carry;
426         if(!force){
427                 sym = symlook(name, S_TIME, 0);
428                 if(sym)
429                         return sym->u.value;
430                 return 0;
431         }
432         if((d = dirstat(name)) == nil)
433                 return 0;
434         t = d->mtime;
435         free(d);
436         return t;
437 }
438