unix.c (5469B)
1 #define NOPLAN9DEFINES 2 #include "mk.h" 3 #include <sys/wait.h> 4 #include <signal.h> 5 #include <sys/stat.h> 6 #include <sys/time.h> 7 8 char *shell = "/bin/sh"; 9 char *shellname = "sh"; 10 11 extern char **environ; 12 13 static void 14 mkperror(char *s) 15 { 16 fprint(2, "%s: %r\n", s); 17 } 18 19 void 20 readenv(void) 21 { 22 char **p, *s; 23 Word *w; 24 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 } else 32 w = newword(""); 33 */ 34 s = strchr(*p, '='); 35 if(s){ 36 *s = 0; 37 w = newword(s+1); 38 } else 39 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 } 47 48 /* 49 * done on child side of fork, so parent's env is not affected 50 * and we don't care about freeing memory because we're going 51 * to exec immediately after this. 52 */ 53 void 54 exportenv(Envy *e, Shell *sh) 55 { 56 int w, n; 57 char **p; 58 Envy *e1; 59 static char buf[16384]; 60 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 else 72 snprint(buf, sizeof buf, "%s=", e->name); 73 p[w++] = strdup(buf); 74 } 75 p[w] = 0; 76 environ = p; 77 } 78 79 int 80 waitfor(char *msg) 81 { 82 int status; 83 int pid; 84 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 else 92 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 } 98 99 void 100 expunge(int pid, char *msg) 101 { 102 if(strcmp(msg, "interrupt")) 103 kill(pid, SIGINT); 104 else 105 kill(pid, SIGHUP); 106 } 107 108 int mypid; 109 110 int 111 shargv(Word *cmd, int extra, char ***pargv) 112 { 113 char **argv; 114 int i, n; 115 Word *w; 116 117 n = 0; 118 for(w=cmd; w; w=w->next) 119 n++; 120 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 } 129 130 int 131 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]; 135 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 } 207 208 int 209 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd) 210 { 211 int pid, pfd[2]; 212 int n; 213 char **argv; 214 215 if(DEBUG(D_EXEC)) 216 fprint(1, "pipecmd='%s'\n", cmd);/**/ 217 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 } 249 250 void 251 Exit(void) 252 { 253 while(wait(0) >= 0) 254 ; 255 exits("error"); 256 } 257 258 static struct 259 { 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, 0 270 }; 271 272 static void 273 notifyf(int sig) 274 { 275 int i; 276 277 for(i = 0; sigmsgs[i].msg; i++) 278 if(sigmsgs[i].sig == sig) 279 killchildren(sigmsgs[i].msg); 280 281 /* should never happen */ 282 signal(sig, SIG_DFL); 283 kill(getpid(), sig); 284 } 285 286 void 287 catchnotes(void) 288 { 289 int i; 290 291 for(i = 0; sigmsgs[i].msg; i++) 292 signal(sigmsgs[i].sig, notifyf); 293 } 294 295 char* 296 maketmp(int *pfd) 297 { 298 static char temp[] = "/tmp/mkargXXXXXX"; 299 static char buf[100]; 300 int fd; 301 302 strcpy(buf, temp); 303 fd = mkstemp(buf); 304 if(fd < 0) 305 return 0; 306 *pfd = fd; 307 return buf; 308 } 309 310 int 311 chgtime(char *name) 312 { 313 if(access(name, 0) >= 0) 314 return utimes(name, 0); 315 return close(creat(name, 0666)); 316 } 317 318 void 319 rcopy(char **to, Resub *match, int n) 320 { 321 int c; 322 char *p; 323 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 else 334 *to = 0; 335 } 336 } 337 338 unsigned long 339 mkmtime(char *name) 340 { 341 struct stat st; 342 343 if(stat(name, &st) < 0) 344 return 0; 345 346 return st.st_mtime; 347 }