Blob
- Date:
- Message:
- mk: treat X= as empty list in rc shell This brings mk's behavior when using rc in line with Plan 9's. The existing code is for Unix environment data structures but also was assuming Unix shell semantics where empty and missing variables are mostly equivalent. The Plan 9 code (/sys/src/cmd/mk/plan9.c in the distribution) explicitly removes /env/name (creating an empty list) when the value is missing or an empty string. Fixes #255.
- Actions:
- History | Blame | Raw File
1 #define NOPLAN9DEFINES2 #include "mk.h"3 #include <sys/wait.h>4 #include <signal.h>5 #include <sys/stat.h>6 #include <sys/time.h>8 char *shell = "/bin/sh";9 char *shellname = "sh";11 extern char **environ;13 static void14 mkperror(char *s)15 {16 fprint(2, "%s: %r\n", s);17 }19 void20 readenv(void)21 {22 char **p, *s;23 Word *w;25 for(p = environ; *p; p++){26 /* rsc 5/5/2004 -- This misparses fn#cd={whatever}27 s = shname(*p);28 if(*s == '=') {29 *s = 0;30 w = newword(s+1);31 } else32 w = newword("");33 */34 s = strchr(*p, '=');35 if(s){36 *s = 0;37 w = newword(s+1);38 } else39 w = newword("");40 if (symlook(*p, S_INTERNAL, 0))41 continue;42 s = strdup(*p);43 setvar(s, (void *)w);44 symlook(s, S_EXPORTED, (void*)"")->u.ptr = "";45 }46 }48 /*49 * done on child side of fork, so parent's env is not affected50 * and we don't care about freeing memory because we're going51 * to exec immediately after this.52 */53 void54 exportenv(Envy *e, Shell *sh)55 {56 int w, n;57 char **p;58 Envy *e1;59 static char buf[16384];61 n = 0;62 for(e1 = e; e1->name; e1++)63 n++;64 p = Malloc((n+1)*sizeof(char*));65 w = 0;66 for(; e->name; e++) {67 if(sh == &rcshell && (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0))68 continue; /* do not write empty string for empty list */69 if(e->values)70 snprint(buf, sizeof buf, "%s=%s", e->name, wtos(e->values, sh->iws));71 else72 snprint(buf, sizeof buf, "%s=", e->name);73 p[w++] = strdup(buf);74 }75 p[w] = 0;76 environ = p;77 }79 int80 waitfor(char *msg)81 {82 int status;83 int pid;85 *msg = 0;86 pid = wait(&status);87 if(pid > 0) {88 if(status&0x7f) {89 if(status&0x80)90 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);91 else92 snprint(msg, ERRMAX, "signal %d", status&0x7f);93 } else if(status&0xff00)94 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);95 }96 return pid;97 }99 void100 expunge(int pid, char *msg)101 {102 if(strcmp(msg, "interrupt"))103 kill(pid, SIGINT);104 else105 kill(pid, SIGHUP);106 }108 int mypid;110 int111 shargv(Word *cmd, int extra, char ***pargv)112 {113 char **argv;114 int i, n;115 Word *w;117 n = 0;118 for(w=cmd; w; w=w->next)119 n++;121 argv = Malloc((n+extra+1)*sizeof(argv[0]));122 i = 0;123 for(w=cmd; w; w=w->next)124 argv[i++] = w->s;125 argv[n] = 0;126 *pargv = argv;127 return n;128 }130 int131 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)132 {133 char *p, **argv;134 int tot, n, pid, in[2], out[2];136 if(buf && pipe(out) < 0){137 mkperror("pipe");138 Exit();139 }140 pid = fork();141 mypid = getpid();142 if(pid < 0){143 mkperror("mk fork");144 Exit();145 }146 if(pid == 0){147 if(buf)148 close(out[0]);149 if(pipe(in) < 0){150 mkperror("pipe");151 Exit();152 }153 pid = fork();154 if(pid < 0){155 mkperror("mk fork");156 Exit();157 }158 if(pid != 0){159 dup2(in[0], 0);160 if(buf){161 dup2(out[1], 1);162 close(out[1]);163 }164 close(in[0]);165 close(in[1]);166 if (e)167 exportenv(e, sh);168 n = shargv(shellcmd, 1, &argv);169 argv[n++] = args;170 argv[n] = 0;171 execvp(argv[0], argv);172 mkperror(shell);173 _exit(1);174 }175 close(out[1]);176 close(in[0]);177 if(DEBUG(D_EXEC))178 fprint(1, "starting: %s\n", cmd);179 p = cmd+strlen(cmd);180 while(cmd < p){181 n = write(in[1], cmd, p-cmd);182 if(n < 0)183 break;184 cmd += n;185 }186 close(in[1]);187 _exit(0);188 }189 if(buf){190 close(out[1]);191 tot = 0;192 for(;;){193 if (buf->current >= buf->end)194 growbuf(buf);195 n = read(out[0], buf->current, buf->end-buf->current);196 if(n <= 0)197 break;198 buf->current += n;199 tot += n;200 }201 if (tot && buf->current[-1] == '\n')202 buf->current--;203 close(out[0]);204 }205 return pid;206 }208 int209 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)210 {211 int pid, pfd[2];212 int n;213 char **argv;215 if(DEBUG(D_EXEC))216 fprint(1, "pipecmd='%s'\n", cmd);/**/218 if(fd && pipe(pfd) < 0){219 mkperror("pipe");220 Exit();221 }222 pid = fork();223 if(pid < 0){224 mkperror("mk fork");225 Exit();226 }227 if(pid == 0){228 if(fd){229 close(pfd[0]);230 dup2(pfd[1], 1);231 close(pfd[1]);232 }233 if(e)234 exportenv(e, sh);235 n = shargv(shellcmd, 2, &argv);236 argv[n++] = "-c";237 argv[n++] = cmd;238 argv[n] = 0;239 execvp(argv[0], argv);240 mkperror(shell);241 _exit(1);242 }243 if(fd){244 close(pfd[1]);245 *fd = pfd[0];246 }247 return pid;248 }250 void251 Exit(void)252 {253 while(wait(0) >= 0)254 ;255 exits("error");256 }258 static struct259 {260 int sig;261 char *msg;262 } sigmsgs[] =263 {264 SIGALRM, "alarm",265 SIGFPE, "sys: fp: fptrap",266 SIGPIPE, "sys: write on closed pipe",267 SIGILL, "sys: trap: illegal instruction",268 /* SIGSEGV, "sys: segmentation violation", */269 0, 0270 };272 static void273 notifyf(int sig)274 {275 int i;277 for(i = 0; sigmsgs[i].msg; i++)278 if(sigmsgs[i].sig == sig)279 killchildren(sigmsgs[i].msg);281 /* should never happen */282 signal(sig, SIG_DFL);283 kill(getpid(), sig);284 }286 void287 catchnotes(void)288 {289 int i;291 for(i = 0; sigmsgs[i].msg; i++)292 signal(sigmsgs[i].sig, notifyf);293 }295 char*296 maketmp(int *pfd)297 {298 static char temp[] = "/tmp/mkargXXXXXX";299 static char buf[100];300 int fd;302 strcpy(buf, temp);303 fd = mkstemp(buf);304 if(fd < 0)305 return 0;306 *pfd = fd;307 return buf;308 }310 int311 chgtime(char *name)312 {313 if(access(name, 0) >= 0)314 return utimes(name, 0);315 return close(creat(name, 0666));316 }318 void319 rcopy(char **to, Resub *match, int n)320 {321 int c;322 char *p;324 *to = match->s.sp; /* stem0 matches complete target */325 for(to++, match++; --n > 0; to++, match++){326 if(match->s.sp && match->e.ep){327 p = match->e.ep;328 c = *p;329 *p = 0;330 *to = strdup(match->s.sp);331 *p = c;332 }333 else334 *to = 0;335 }336 }338 unsigned long339 mkmtime(char *name)340 {341 struct stat st;343 if(stat(name, &st) < 0)344 return 0;346 return st.st_mtime;347 }