summaryrefslogtreecommitdiff
path: root/sys/src/cmd/mk/plan9.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/mk/plan9.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/mk/plan9.c')
-rwxr-xr-xsys/src/cmd/mk/plan9.c437
1 files changed, 437 insertions, 0 deletions
diff --git a/sys/src/cmd/mk/plan9.c b/sys/src/cmd/mk/plan9.c
new file mode 100755
index 000000000..d87fcfa4d
--- /dev/null
+++ b/sys/src/cmd/mk/plan9.c
@@ -0,0 +1,437 @@
+#include "mk.h"
+
+char *shell = "/bin/rc";
+char *shellname = "rc";
+
+static Word *encodenulls(char*, int);
+
+void
+readenv(void)
+{
+ char *p;
+ int envf, f;
+ Dir *e;
+ char nam[1024];
+ int i, n, len;
+ Word *w;
+
+ rfork(RFENVG); /* use copy of the current environment variables */
+
+ envf = open("/env", OREAD);
+ if(envf < 0)
+ return;
+ while((n = dirread(envf, &e)) > 0){
+ for(i = 0; i < n; i++){
+ len = e[i].length;
+ /* don't import funny names, NULL values,
+ * or internal mk variables
+ */
+ if(len <= 0 || *shname(e[i].name) != '\0')
+ continue;
+ if (symlook(e[i].name, S_INTERNAL, 0))
+ continue;
+ snprint(nam, sizeof nam, "/env/%s", e[i].name);
+ f = open(nam, OREAD);
+ if(f < 0)
+ continue;
+ p = Malloc(len+1);
+ if(read(f, p, len) != len){
+ perror(nam);
+ close(f);
+ continue;
+ }
+ close(f);
+ if (p[len-1] == 0)
+ len--;
+ else
+ p[len] = 0;
+ w = encodenulls(p, len);
+ free(p);
+ p = strdup(e[i].name);
+ setvar(p, (void *) w);
+ symlook(p, S_EXPORTED, (void*)"")->u.ptr = "";
+ }
+ free(e);
+ }
+ close(envf);
+}
+
+/* break string of values into words at 01's or nulls*/
+static Word *
+encodenulls(char *s, int n)
+{
+ Word *w, *head;
+ char *cp;
+
+ head = w = 0;
+ while (n-- > 0) {
+ for (cp = s; *cp && *cp != '\0'; cp++)
+ n--;
+ *cp = 0;
+ if (w) {
+ w->next = newword(s);
+ w = w->next;
+ } else
+ head = w = newword(s);
+ s = cp+1;
+ }
+ if (!head)
+ head = newword("");
+ return head;
+}
+
+/* as well as 01's, change blanks to nulls, so that rc will
+ * treat the words as separate arguments
+ */
+void
+exportenv(Envy *e)
+{
+ int f, n, hasvalue, first;
+ Word *w;
+ Symtab *sy;
+ char nam[256];
+
+ for(;e->name; e++){
+ sy = symlook(e->name, S_VAR, 0);
+ if (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0)
+ hasvalue = 0;
+ else
+ hasvalue = 1;
+ if(sy == 0 && !hasvalue) /* non-existant null symbol */
+ continue;
+ snprint(nam, sizeof nam, "/env/%s", e->name);
+ if (sy != 0 && !hasvalue) { /* Remove from environment */
+ /* we could remove it from the symbol table
+ * too, but we're in the child copy, and it
+ * would still remain in the parent's table.
+ */
+ remove(nam);
+ delword(e->values);
+ e->values = 0; /* memory leak */
+ continue;
+ }
+
+ f = create(nam, OWRITE, 0666L);
+ if(f < 0) {
+ fprint(2, "can't create %s, f=%d\n", nam, f);
+ perror(nam);
+ continue;
+ }
+ first = 1;
+ for (w = e->values; w; w = w->next) {
+ n = strlen(w->s);
+ if (n) {
+ if(first)
+ first = 0;
+ else{
+ if (write (f, "\0", 1) != 1)
+ perror(nam);
+ }
+ if (write(f, w->s, n) != n)
+ perror(nam);
+ }
+ }
+ close(f);
+ }
+}
+
+int
+waitfor(char *msg)
+{
+ Waitmsg *w;
+ int pid;
+
+ if((w=wait()) == nil)
+ return -1;
+ strecpy(msg, msg+ERRMAX, w->msg);
+ pid = w->pid;
+ free(w);
+ return pid;
+}
+
+void
+expunge(int pid, char *msg)
+{
+ postnote(PNPROC, pid, msg);
+}
+
+int
+execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
+{
+ char *p;
+ int tot, n, pid, in[2], out[2];
+
+ if(buf && pipe(out) < 0){
+ perror("pipe");
+ Exit();
+ }
+ pid = rfork(RFPROC|RFFDG|RFENVG);
+ if(pid < 0){
+ perror("mk rfork");
+ Exit();
+ }
+ if(pid == 0){
+ if(buf)
+ close(out[0]);
+ if(pipe(in) < 0){
+ perror("pipe");
+ Exit();
+ }
+ pid = fork();
+ if(pid < 0){
+ perror("mk fork");
+ Exit();
+ }
+ if(pid != 0){
+ dup(in[0], 0);
+ if(buf){
+ dup(out[1], 1);
+ close(out[1]);
+ }
+ close(in[0]);
+ close(in[1]);
+ if (e)
+ exportenv(e);
+ if(shflags)
+ execl(shell, shellname, shflags, args, nil);
+ else
+ execl(shell, shellname, args, nil);
+ perror(shell);
+ _exits("exec");
+ }
+ close(out[1]);
+ close(in[0]);
+ p = cmd+strlen(cmd);
+ while(cmd < p){
+ n = write(in[1], cmd, p-cmd);
+ if(n < 0)
+ break;
+ cmd += n;
+ }
+ close(in[1]);
+ _exits(0);
+ }
+ if(buf){
+ close(out[1]);
+ tot = 0;
+ for(;;){
+ if (buf->current >= buf->end)
+ growbuf(buf);
+ n = read(out[0], buf->current, buf->end-buf->current);
+ if(n <= 0)
+ break;
+ buf->current += n;
+ tot += n;
+ }
+ if (tot && buf->current[-1] == '\n')
+ buf->current--;
+ close(out[0]);
+ }
+ return pid;
+}
+
+int
+pipecmd(char *cmd, Envy *e, int *fd)
+{
+ int pid, pfd[2];
+
+ if(DEBUG(D_EXEC))
+ fprint(1, "pipecmd='%s'\n", cmd);/**/
+
+ if(fd && pipe(pfd) < 0){
+ perror("pipe");
+ Exit();
+ }
+ pid = rfork(RFPROC|RFFDG|RFENVG);
+ if(pid < 0){
+ perror("mk fork");
+ Exit();
+ }
+ if(pid == 0){
+ if(fd){
+ close(pfd[0]);
+ dup(pfd[1], 1);
+ close(pfd[1]);
+ }
+ if(e)
+ exportenv(e);
+ if(shflags)
+ execl(shell, shellname, shflags, "-c", cmd, nil);
+ else
+ execl(shell, shellname, "-c", cmd, nil);
+ perror(shell);
+ _exits("exec");
+ }
+ if(fd){
+ close(pfd[1]);
+ *fd = pfd[0];
+ }
+ return pid;
+}
+
+void
+Exit(void)
+{
+ while(waitpid() >= 0)
+ ;
+ exits("error");
+}
+
+int
+notifyf(void *a, char *msg)
+{
+ static int nnote;
+
+ USED(a);
+ if(++nnote > 100){ /* until andrew fixes his program */
+ fprint(2, "mk: too many notes\n");
+ notify(0);
+ abort();
+ }
+ if(strcmp(msg, "interrupt")!=0 && strcmp(msg, "hangup")!=0)
+ return 0;
+ killchildren(msg);
+ return -1;
+}
+
+void
+catchnotes()
+{
+ atnotify(notifyf, 1);
+}
+
+char*
+maketmp(void)
+{
+ static char temp[] = "/tmp/mkargXXXXXX";
+
+ mktemp(temp);
+ return temp;
+}
+
+int
+chgtime(char *name)
+{
+ Dir sbuf;
+
+ if(access(name, AEXIST) >= 0) {
+ nulldir(&sbuf);
+ sbuf.mtime = time((long *)0);
+ return dirwstat(name, &sbuf);
+ }
+ return close(create(name, OWRITE, 0666));
+}
+
+void
+rcopy(char **to, Resub *match, int n)
+{
+ int c;
+ char *p;
+
+ *to = match->sp; /* stem0 matches complete target */
+ for(to++, match++; --n > 0; to++, match++){
+ if(match->sp && match->ep){
+ p = match->ep;
+ c = *p;
+ *p = 0;
+ *to = strdup(match->sp);
+ *p = c;
+ }
+ else
+ *to = 0;
+ }
+}
+
+void
+dirtime(char *dir, char *path)
+{
+ int i, fd, n;
+ long mtime;
+ Dir *d;
+ char buf[4096];
+
+ fd = open(dir, OREAD);
+ if(fd >= 0){
+ while((n = dirread(fd, &d)) > 0){
+ for(i=0; i<n; i++){
+ mtime = d[i].mtime;
+ /* defensive driving: this does happen */
+ if(mtime == 0)
+ mtime = 1;
+ snprint(buf, sizeof buf, "%s%s", path,
+ d[i].name);
+ if(symlook(buf, S_TIME, 0) == nil)
+ symlook(strdup(buf), S_TIME,
+ (void*)mtime)->u.value = mtime;
+ }
+ free(d);
+ }
+ close(fd);
+ }
+}
+
+void
+bulkmtime(char *dir)
+{
+ char buf[4096];
+ char *ss, *s, *sym;
+
+ if(dir){
+ sym = dir;
+ s = dir;
+ if(strcmp(dir, "/") == 0)
+ strecpy(buf, buf + sizeof buf - 1, dir);
+ else
+ snprint(buf, sizeof buf, "%s/", dir);
+ }else{
+ s = ".";
+ sym = "";
+ buf[0] = 0;
+ }
+ if(symlook(sym, S_BULKED, 0))
+ return;
+ ss = strdup(sym);
+ symlook(ss, S_BULKED, (void*)ss);
+ dirtime(s, buf);
+}
+
+ulong
+mkmtime(char *name, int force)
+{
+ Dir *d;
+ char *s, *ss, carry;
+ ulong t;
+ Symtab *sym;
+ char buf[4096];
+
+ strecpy(buf, buf + sizeof buf - 1, name);
+ cleanname(buf);
+ name = buf;
+
+ s = utfrrune(name, '/');
+ if(s == name)
+ s++;
+ if(s){
+ ss = name;
+ carry = *s;
+ *s = 0;
+ }else{
+ ss = 0;
+ carry = 0;
+ }
+ bulkmtime(ss);
+ if(carry)
+ *s = carry;
+ if(!force){
+ sym = symlook(name, S_TIME, 0);
+ if(sym)
+ return sym->u.value;
+ return 0;
+ }
+ if((d = dirstat(name)) == nil)
+ return 0;
+ t = d->mtime;
+ free(d);
+ return t;
+}
+