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 s = shname(*p);27 if(*s == '=') {28 *s = 0;29 w = newword(s+1);30 } else31 w = newword("");32 if (symlook(*p, S_INTERNAL, 0))33 continue;34 s = strdup(*p);35 setvar(s, (void *)w);36 symlook(s, S_EXPORTED, (void*)"")->value = (void*)"";37 }38 }40 /*41 * done on child side of fork, so parent's env is not affected42 * and we don't care about freeing memory because we're going43 * to exec immediately after this.44 */45 void46 exportenv(Envy *e)47 {48 int i;49 char **p;50 char buf[4096];52 p = 0;53 for(i = 0; e->name; e++, i++) {54 p = (char**) Realloc(p, (i+2)*sizeof(char*));55 if(e->values)56 sprint(buf, "%s=%s", e->name, wtos(e->values, IWS));57 else58 sprint(buf, "%s=", e->name);59 p[i] = strdup(buf);60 }61 p[i] = 0;62 environ = p;63 }65 int66 waitfor(char *msg)67 {68 int status;69 int pid;71 *msg = 0;72 pid = wait(&status);73 if(pid > 0) {74 if(status&0x7f) {75 if(status&0x80)76 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f);77 else78 snprint(msg, ERRMAX, "signal %d", status&0x7f);79 } else if(status&0xff00)80 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff);81 }82 return pid;83 }85 void86 expunge(int pid, char *msg)87 {88 if(strcmp(msg, "interrupt"))89 kill(pid, SIGINT);90 else91 kill(pid, SIGHUP);92 }94 int95 execsh(char *args, char *cmd, Bufblock *buf, Envy *e)96 {97 char *p;98 int tot, n, pid, in[2], out[2];100 if(buf && pipe(out) < 0){101 mkperror("pipe");102 Exit();103 }104 pid = fork();105 if(pid < 0){106 mkperror("mk fork");107 Exit();108 }109 if(pid == 0){110 if(buf)111 close(out[0]);112 if(pipe(in) < 0){113 mkperror("pipe");114 Exit();115 }116 pid = fork();117 if(pid < 0){118 mkperror("mk fork");119 Exit();120 }121 if(pid != 0){122 dup2(in[0], 0);123 if(buf){124 dup2(out[1], 1);125 close(out[1]);126 }127 close(in[0]);128 close(in[1]);129 if (e)130 exportenv(e);131 if(shflags)132 execl(shell, shellname, shflags, args, 0);133 else134 execl(shell, shellname, args, 0);135 mkperror(shell);136 _exit(1);137 }138 close(out[1]);139 close(in[0]);140 if(DEBUG(D_EXEC))141 fprint(1, "starting: %s\n", cmd);142 p = cmd+strlen(cmd);143 while(cmd < p){144 n = write(in[1], cmd, p-cmd);145 if(n < 0)146 break;147 cmd += n;148 }149 close(in[1]);150 _exit(0);151 }152 if(buf){153 close(out[1]);154 tot = 0;155 for(;;){156 if (buf->current >= buf->end)157 growbuf(buf);158 n = read(out[0], buf->current, buf->end-buf->current);159 if(n <= 0)160 break;161 buf->current += n;162 tot += n;163 }164 if (tot && buf->current[-1] == '\n')165 buf->current--;166 close(out[0]);167 }168 return pid;169 }171 int172 pipecmd(char *cmd, Envy *e, int *fd)173 {174 int pid, pfd[2];176 if(DEBUG(D_EXEC))177 fprint(1, "pipecmd='%s'\n", cmd);/**/179 if(fd && pipe(pfd) < 0){180 mkperror("pipe");181 Exit();182 }183 pid = fork();184 if(pid < 0){185 mkperror("mk fork");186 Exit();187 }188 if(pid == 0){189 if(fd){190 close(pfd[0]);191 dup2(pfd[1], 1);192 close(pfd[1]);193 }194 if(e)195 exportenv(e);196 if(shflags)197 execl(shell, shellname, shflags, "-c", cmd, 0);198 else199 execl(shell, shellname, "-c", cmd, 0);200 mkperror(shell);201 _exit(1);202 }203 if(fd){204 close(pfd[1]);205 *fd = pfd[0];206 }207 return pid;208 }210 void211 Exit(void)212 {213 while(wait(0) >= 0)214 ;215 exits("error");216 }218 static struct219 {220 int sig;221 char *msg;222 } sigmsgs[] =223 {224 SIGALRM, "alarm",225 SIGFPE, "sys: fp: fptrap",226 SIGPIPE, "sys: write on closed pipe",227 SIGILL, "sys: trap: illegal instruction",228 SIGSEGV, "sys: segmentation violation",229 0, 0230 };232 static void233 notifyf(int sig)234 {235 int i;237 for(i = 0; sigmsgs[i].msg; i++)238 if(sigmsgs[i].sig == sig)239 killchildren(sigmsgs[i].msg);241 /* should never happen */242 signal(sig, SIG_DFL);243 kill(getpid(), sig);244 }246 void247 catchnotes()248 {249 int i;251 for(i = 0; sigmsgs[i].msg; i++)252 signal(sigmsgs[i].sig, notifyf);253 }255 char*256 maketmp(int *pfd)257 {258 static char temp[] = "/tmp/mkargXXXXXX";259 static char buf[100];260 int fd;262 strcpy(buf, temp);263 fd = mkstemp(buf);264 if(fd < 0)265 return 0;266 *pfd = fd;267 return buf;268 }270 int271 chgtime(char *name)272 {273 if(access(name, 0) >= 0)274 return utimes(name, 0);275 return close(creat(name, 0666));276 }278 void279 rcopy(char **to, Resub *match, int n)280 {281 int c;282 char *p;284 *to = match->s.sp; /* stem0 matches complete target */285 for(to++, match++; --n > 0; to++, match++){286 if(match->s.sp && match->e.ep){287 p = match->e.ep;288 c = *p;289 *p = 0;290 *to = strdup(match->s.sp);291 *p = c;292 }293 else294 *to = 0;295 }296 }298 ulong299 mkmtime(char *name)300 {301 struct stat st;303 if(stat(name, &st) < 0)304 return 0;306 return st.st_mtime;307 }