unix.c (5290B)
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 i; 57 char **p; 58 static char buf[16384]; 59 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 else 66 snprint(buf, sizeof buf, "%s=", e->name); 67 p[i] = strdup(buf); 68 } 69 p[i] = 0; 70 environ = p; 71 } 72 73 int 74 waitfor(char *msg) 75 { 76 int status; 77 int pid; 78 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 else 86 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 } 92 93 void 94 expunge(int pid, char *msg) 95 { 96 if(strcmp(msg, "interrupt")) 97 kill(pid, SIGINT); 98 else 99 kill(pid, SIGHUP); 100 } 101 102 int mypid; 103 104 int 105 shargv(Word *cmd, int extra, char ***pargv) 106 { 107 char **argv; 108 int i, n; 109 Word *w; 110 111 n = 0; 112 for(w=cmd; w; w=w->next) 113 n++; 114 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 } 123 124 int 125 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]; 129 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 } 201 202 int 203 pipecmd(char *cmd, Envy *e, int *fd, Shell *sh, Word *shellcmd) 204 { 205 int pid, pfd[2]; 206 int n; 207 char **argv; 208 209 if(DEBUG(D_EXEC)) 210 fprint(1, "pipecmd='%s'\n", cmd);/**/ 211 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 } 243 244 void 245 Exit(void) 246 { 247 while(wait(0) >= 0) 248 ; 249 exits("error"); 250 } 251 252 static struct 253 { 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, 0 264 }; 265 266 static void 267 notifyf(int sig) 268 { 269 int i; 270 271 for(i = 0; sigmsgs[i].msg; i++) 272 if(sigmsgs[i].sig == sig) 273 killchildren(sigmsgs[i].msg); 274 275 /* should never happen */ 276 signal(sig, SIG_DFL); 277 kill(getpid(), sig); 278 } 279 280 void 281 catchnotes(void) 282 { 283 int i; 284 285 for(i = 0; sigmsgs[i].msg; i++) 286 signal(sigmsgs[i].sig, notifyf); 287 } 288 289 char* 290 maketmp(int *pfd) 291 { 292 static char temp[] = "/tmp/mkargXXXXXX"; 293 static char buf[100]; 294 int fd; 295 296 strcpy(buf, temp); 297 fd = mkstemp(buf); 298 if(fd < 0) 299 return 0; 300 *pfd = fd; 301 return buf; 302 } 303 304 int 305 chgtime(char *name) 306 { 307 if(access(name, 0) >= 0) 308 return utimes(name, 0); 309 return close(creat(name, 0666)); 310 } 311 312 void 313 rcopy(char **to, Resub *match, int n) 314 { 315 int c; 316 char *p; 317 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 else 328 *to = 0; 329 } 330 } 331 332 unsigned long 333 mkmtime(char *name) 334 { 335 struct stat st; 336 337 if(stat(name, &st) < 0) 338 return 0; 339 340 return st.st_mtime; 341 }