Blob
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*)"")->value = (void*)"";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 i;57 char **p;58 static char buf[16384];60 p = 0;61 for(i = 0; e->name; e++, i++) {62 p = (char**) Realloc(p, (i+2)*sizeof(char*));63 if(e->values)64 snprint(buf, sizeof buf, "%s=%s", e->name, wtos(e->values, sh->iws));65 else66 snprint(buf, sizeof buf, "%s=", e->name);67 p[i] = strdup(buf);68 }69 p[i] = 0;70 environ = p;71 }73 int74 waitfor(char *msg)75 {76 int status;77 int pid;79 *msg = 0;80 pid = wait(&status);81 if(pid > 0) {82 if(status&0x7f) {83 if(status&0x80)84 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);85 else86 snprint(msg, ERRMAX, "signal %d", status&0x7f);87 } else if(status&0xff00)88 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);89 }90 return pid;91 }93 void94 expunge(int pid, char *msg)95 {96 if(strcmp(msg, "interrupt"))97 kill(pid, SIGINT);98 else99 kill(pid, SIGHUP);100 }102 int mypid;104 int105 shargv(Word *cmd, int extra, char ***pargv)106 {107 char **argv;108 int i, n;109 Word *w;111 n = 0;112 for(w=cmd; w; w=w->next)113 n++;115 argv = Malloc((n+extra+1)*sizeof(argv[0]));116 i = 0;117 for(w=cmd; w; w=w->next)118 argv[i++] = w->s;119 argv[n] = 0;120 *pargv = argv;121 return n;122 }124 int125 execsh(char *args, char *cmd, Bufblock *buf, Envy *e, Shell *sh, Word *shellcmd)126 {127 char *p, **argv;128 int tot, n, pid, in[2], out[2];130 if(buf && pipe(out) < 0){131 mkperror("pipe");132 Exit();133 }134 pid = fork();135 mypid = getpid();136 if(pid < 0){137 mkperror("mk fork");138 Exit();139 }140 if(pid == 0){141 if(buf)142 close(out[0]);143 if(pipe(in) < 0){144 mkperror("pipe");145 Exit();146 }147 pid = fork();148 if(pid < 0){149 mkperror("mk fork");150 Exit();151 }152 if(pid != 0){153 dup2(in[0], 0);154 if(buf){155 dup2(out[1], 1);156 close(out[1]);157 }158 close(in[0]);159 close(in[1]);160 if (e)161 exportenv(e, sh);162 n = shargv(shellcmd, 1, &argv);163 argv[n++] = args;164 argv[n] = 0;165 execvp(argv[0], argv);166 mkperror(shell);167 _exit(1);168 }169 close(out[1]);170 close(in[0]);171 if(DEBUG(D_EXEC))172 fprint(1, "starting: %s\n", cmd);173 p = cmd+strlen(cmd);174 while(cmd < p){175 n = write(in[1], cmd, p-cmd);176 if(n < 0)177 break;178 cmd += n;179 }180 close(in[1]);181 _exit(0);182 }183 if(buf){184 close(out[1]);185 tot = 0;186 for(;;){187 if (buf->current >= buf->end)188 growbuf(buf);189 n = read(out[0], buf->current, buf->end-buf->current);190 if(n <= 0)191 break;192 buf->current += n;193 tot += n;194 }195 if (tot && buf->current[-1] == '\n')196 buf->current--;197 close(out[0]);198 }199 return pid;200 }202 int203 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd)204 {205 int pid, pfd[2];206 int n;207 char **argv;209 if(DEBUG(D_EXEC))210 fprint(1, "pipecmd='%s'\n", cmd);/**/212 if(fd && pipe(pfd) < 0){213 mkperror("pipe");214 Exit();215 }216 pid = fork();217 if(pid < 0){218 mkperror("mk fork");219 Exit();220 }221 if(pid == 0){222 if(fd){223 close(pfd[0]);224 dup2(pfd[1], 1);225 close(pfd[1]);226 }227 if(e)228 exportenv(e, sh);229 n = shargv(shellcmd, 2, &argv);230 argv[n++] = "-c";231 argv[n++] = cmd;232 argv[n] = 0;233 execvp(argv[0], argv);234 mkperror(shell);235 _exit(1);236 }237 if(fd){238 close(pfd[1]);239 *fd = pfd[0];240 }241 return pid;242 }244 void245 Exit(void)246 {247 while(wait(0) >= 0)248 ;249 exits("error");250 }252 static struct253 {254 int sig;255 char *msg;256 } sigmsgs[] =257 {258 SIGALRM, "alarm",259 SIGFPE, "sys: fp: fptrap",260 SIGPIPE, "sys: write on closed pipe",261 SIGILL, "sys: trap: illegal instruction",262 // SIGSEGV, "sys: segmentation violation",263 0, 0264 };266 static void267 notifyf(int sig)268 {269 int i;271 for(i = 0; sigmsgs[i].msg; i++)272 if(sigmsgs[i].sig == sig)273 killchildren(sigmsgs[i].msg);275 /* should never happen */276 signal(sig, SIG_DFL);277 kill(getpid(), sig);278 }280 void281 catchnotes(void)282 {283 int i;285 for(i = 0; sigmsgs[i].msg; i++)286 signal(sigmsgs[i].sig, notifyf);287 }289 char*290 maketmp(int *pfd)291 {292 static char temp[] = "/tmp/mkargXXXXXX";293 static char buf[100];294 int fd;296 strcpy(buf, temp);297 fd = mkstemp(buf);298 if(fd < 0)299 return 0;300 *pfd = fd;301 return buf;302 }304 int305 chgtime(char *name)306 {307 if(access(name, 0) >= 0)308 return utimes(name, 0);309 return close(creat(name, 0666));310 }312 void313 rcopy(char **to, Resub *match, int n)314 {315 int c;316 char *p;318 *to = match->s.sp; /* stem0 matches complete target */319 for(to++, match++; --n > 0; to++, match++){320 if(match->s.sp && match->e.ep){321 p = match->e.ep;322 c = *p;323 *p = 0;324 *to = strdup(match->s.sp);325 *p = c;326 }327 else328 *to = 0;329 }330 }332 unsigned long333 mkmtime(char *name)334 {335 struct stat st;337 if(stat(name, &st) < 0)338 return 0;340 return st.st_mtime;341 }