]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mk/plan9.c
mothra: fix alt display resizing, filter control characters in panel entries, use...
[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                 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         long mtime;
350         Dir *d;
351         char buf[4096];
352
353         fd = open(dir, OREAD);
354         if(fd >= 0){
355                 while((n = dirread(fd, &d)) > 0){
356                         for(i=0; i<n; i++){
357                                 mtime = d[i].mtime;
358                                 /* defensive driving: this does happen */
359                                 if(mtime == 0)
360                                         mtime = 1;
361                                 snprint(buf, sizeof buf, "%s%s", path,
362                                         d[i].name);
363                                 if(symlook(buf, S_TIME, 0) == nil)
364                                         symlook(strdup(buf), S_TIME,
365                                                 (void*)mtime)->u.value = mtime;
366                         }
367                         free(d);
368                 }
369                 close(fd);
370         }
371 }
372
373 void
374 bulkmtime(char *dir)
375 {
376         char buf[4096];
377         char *ss, *s, *sym;
378
379         if(dir){
380                 sym = dir;
381                 s = dir;
382                 if(strcmp(dir, "/") == 0)
383                         strecpy(buf, buf + sizeof buf - 1, dir);
384                 else
385                         snprint(buf, sizeof buf, "%s/", dir);
386         }else{
387                 s = ".";
388                 sym = "";
389                 buf[0] = 0;
390         }
391         if(symlook(sym, S_BULKED, 0))
392                 return;
393         ss = strdup(sym);
394         symlook(ss, S_BULKED, (void*)ss);
395         dirtime(s, buf);
396 }
397
398 ulong
399 mkmtime(char *name, int force)
400 {
401         Dir *d;
402         char *s, *ss, carry;
403         ulong t;
404         Symtab *sym;
405         char buf[4096];
406
407         strecpy(buf, buf + sizeof buf - 1, name);
408         cleanname(buf);
409         name = buf;
410
411         s = utfrrune(name, '/');
412         if(s == name)
413                 s++;
414         if(s){
415                 ss = name;
416                 carry = *s;
417                 *s = 0;
418         }else{
419                 ss = 0;
420                 carry = 0;
421         }
422         bulkmtime(ss);
423         if(carry)
424                 *s = carry;
425         if(!force){
426                 sym = symlook(name, S_TIME, 0);
427                 if(sym)
428                         return sym->u.value;
429                 return 0;
430         }
431         if((d = dirstat(name)) == nil)
432                 return 0;
433         t = d->mtime;
434         free(d);
435         return t;
436 }
437