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)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, 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 execsh(char *args, char *cmd, Bufblock *buf, Envy *e)106 {107 char *p;108 int tot, n, pid, in[2], out[2];110 if(buf && pipe(out) < 0){111 mkperror("pipe");112 Exit();113 }114 pid = fork();115 mypid = getpid();116 if(pid < 0){117 mkperror("mk fork");118 Exit();119 }120 if(pid == 0){121 if(buf)122 close(out[0]);123 if(pipe(in) < 0){124 mkperror("pipe");125 Exit();126 }127 pid = fork();128 if(pid < 0){129 mkperror("mk fork");130 Exit();131 }132 if(pid != 0){133 dup2(in[0], 0);134 if(buf){135 dup2(out[1], 1);136 close(out[1]);137 }138 close(in[0]);139 close(in[1]);140 if (e)141 exportenv(e);142 if(shflags)143 execl(shell, shellname, shflags, args, 0);144 else145 execl(shell, shellname, args, 0);146 mkperror(shell);147 _exit(1);148 }149 close(out[1]);150 close(in[0]);151 if(DEBUG(D_EXEC))152 fprint(1, "starting: %s\n", cmd);153 p = cmd+strlen(cmd);154 while(cmd < p){155 n = write(in[1], cmd, p-cmd);156 if(n < 0)157 break;158 cmd += n;159 }160 close(in[1]);161 _exit(0);162 }163 if(buf){164 close(out[1]);165 tot = 0;166 for(;;){167 if (buf->current >= buf->end)168 growbuf(buf);169 n = read(out[0], buf->current, buf->end-buf->current);170 if(n <= 0)171 break;172 buf->current += n;173 tot += n;174 }175 if (tot && buf->current[-1] == '\n')176 buf->current--;177 close(out[0]);178 }179 return pid;180 }182 int183 pipecmd(char *cmd, Envy *e, int *fd)184 {185 int pid, pfd[2];187 if(DEBUG(D_EXEC))188 fprint(1, "pipecmd='%s'\n", cmd);/**/190 if(fd && pipe(pfd) < 0){191 mkperror("pipe");192 Exit();193 }194 pid = fork();195 if(pid < 0){196 mkperror("mk fork");197 Exit();198 }199 if(pid == 0){200 if(fd){201 close(pfd[0]);202 dup2(pfd[1], 1);203 close(pfd[1]);204 }205 if(e)206 exportenv(e);207 if(shflags)208 execl(shell, shellname, shflags, "-c", cmd, 0);209 else210 execl(shell, shellname, "-c", cmd, 0);211 mkperror(shell);212 _exit(1);213 }214 if(fd){215 close(pfd[1]);216 *fd = pfd[0];217 }218 return pid;219 }221 void222 Exit(void)223 {224 while(wait(0) >= 0)225 ;226 exits("error");227 }229 static struct230 {231 int sig;232 char *msg;233 } sigmsgs[] =234 {235 SIGALRM, "alarm",236 SIGFPE, "sys: fp: fptrap",237 SIGPIPE, "sys: write on closed pipe",238 SIGILL, "sys: trap: illegal instruction",239 // SIGSEGV, "sys: segmentation violation",240 0, 0241 };243 static void244 notifyf(int sig)245 {246 int i;248 for(i = 0; sigmsgs[i].msg; i++)249 if(sigmsgs[i].sig == sig)250 killchildren(sigmsgs[i].msg);252 /* should never happen */253 signal(sig, SIG_DFL);254 kill(getpid(), sig);255 }257 void258 catchnotes()259 {260 int i;262 for(i = 0; sigmsgs[i].msg; i++)263 signal(sigmsgs[i].sig, notifyf);264 }266 char*267 maketmp(int *pfd)268 {269 static char temp[] = "/tmp/mkargXXXXXX";270 static char buf[100];271 int fd;273 strcpy(buf, temp);274 fd = mkstemp(buf);275 if(fd < 0)276 return 0;277 *pfd = fd;278 return buf;279 }281 int282 chgtime(char *name)283 {284 if(access(name, 0) >= 0)285 return utimes(name, 0);286 return close(creat(name, 0666));287 }289 void290 rcopy(char **to, Resub *match, int n)291 {292 int c;293 char *p;295 *to = match->s.sp; /* stem0 matches complete target */296 for(to++, match++; --n > 0; to++, match++){297 if(match->s.sp && match->e.ep){298 p = match->e.ep;299 c = *p;300 *p = 0;301 *to = strdup(match->s.sp);302 *p = c;303 }304 else305 *to = 0;306 }307 }309 ulong310 mkmtime(char *name)311 {312 struct stat st;314 if(stat(name, &st) < 0)315 return 0;317 return st.st_mtime;318 }