1 #include "mk.h" 2 #include <dirent.h> 3 #include <signal.h> 4 #include <sys/wait.h> 5 #include <utime.h> 6 #include <stdio.h> 7 8 char *shell = "/bin/sh"; 9 char *shellname = "sh"; 10 11 extern char **environ; 12 13 void 14 readenv(void) 15 { 16 char **p, *s; 17 Word *w; 18 19 for(p = environ; *p; p++){ 20 s = shname(*p); 21 if(*s == '=') { 22 *s = 0; 23 w = newword(s+1); 24 } else 25 w = newword(""); 26 if (symlook(*p, S_INTERNAL, 0)) 27 continue; 28 s = strdup(*p); 29 setvar(s, (void *)w); 30 symlook(s, S_EXPORTED, (void*)"")->value = (void*)""; 31 } 32 } 33 34 /* 35 * done on child side of fork, so parent's env is not affected 36 * and we don't care about freeing memory because we're going 37 * to exec immediately after this. 38 */ 39 void 40 exportenv(Envy *e) 41 { 42 int i; 43 char **p; 44 char *values; 45 46 p = 0; 47 for(i = 0; e->name; e++, i++) { 48 p = (char**) Realloc(p, (i+2)*sizeof(char*)); 49 if (e->values) 50 values = wtos(e->values, IWS); 51 else 52 values = ""; 53 p[i] = malloc(strlen(e->name) + strlen(values) + 2); 54 sprint(p[i], "%s=%s", e->name, values); 55 } 56 p[i] = 0; 57 environ = p; 58 } 59 60 int 61 waitfor(char *msg) 62 { 63 int status; 64 int pid; 65 66 *msg = 0; 67 pid = wait(&status); 68 if(pid > 0) { 69 if(status&0x7f) { 70 if(status&0x80) 71 snprint(msg, ERRMAX, "signal %d, core dumped", status&0x7f); 72 else 73 snprint(msg, ERRMAX, "signal %d", status&0x7f); 74 } else if(status&0xff00) 75 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xff); 76 } 77 return pid; 78 } 79 80 void 81 expunge(int pid, char *msg) 82 { 83 if(strcmp(msg, "interrupt")) 84 kill(pid, SIGINT); 85 else 86 kill(pid, SIGHUP); 87 } 88 89 int 90 execsh(char *args, char *cmd, Bufblock *buf, Envy *e) 91 { 92 char *p; 93 int tot, n, pid, in[2], out[2]; 94 95 if(buf && pipe(out) < 0){ 96 perror("pipe"); 97 Exit(); 98 } 99 pid = fork(); 100 if(pid < 0){ 101 perror("mk fork"); 102 Exit(); 103 } 104 if(pid == 0){ 105 if(buf) 106 close(out[0]); 107 if(pipe(in) < 0){ 108 perror("pipe"); 109 Exit(); 110 } 111 pid = fork(); 112 if(pid < 0){ 113 perror("mk fork"); 114 Exit(); 115 } 116 if(pid != 0){ 117 dup2(in[0], 0); 118 if(buf){ 119 dup2(out[1], 1); 120 close(out[1]); 121 } 122 close(in[0]); 123 close(in[1]); 124 if (e) 125 exportenv(e); 126 if(shflags) 127 execl(shell, shellname, shflags, args, nil); 128 else 129 execl(shell, shellname, args, nil); 130 perror(shell); 131 _exits("exec"); 132 } 133 close(out[1]); 134 close(in[0]); 135 if(DEBUG(D_EXEC)) 136 fprint(1, "starting: %s\n", cmd); 137 p = cmd+strlen(cmd); 138 while(cmd < p){ 139 n = write(in[1], cmd, p-cmd); 140 if(n < 0) 141 break; 142 cmd += n; 143 } 144 close(in[1]); 145 _exits(0); 146 } 147 if(buf){ 148 close(out[1]); 149 tot = 0; 150 for(;;){ 151 if (buf->current >= buf->end) 152 growbuf(buf); 153 n = read(out[0], buf->current, buf->end-buf->current); 154 if(n <= 0) 155 break; 156 buf->current += n; 157 tot += n; 158 } 159 if (tot && buf->current[-1] == '\n') 160 buf->current--; 161 close(out[0]); 162 } 163 return pid; 164 } 165 166 int 167 pipecmd(char *cmd, Envy *e, int *fd) 168 { 169 int pid, pfd[2]; 170 171 if(DEBUG(D_EXEC)) 172 fprint(1, "pipecmd='%s'\n", cmd);/**/ 173 174 if(fd && pipe(pfd) < 0){ 175 perror("pipe"); 176 Exit(); 177 } 178 pid = fork(); 179 if(pid < 0){ 180 perror("mk fork"); 181 Exit(); 182 } 183 if(pid == 0){ 184 if(fd){ 185 close(pfd[0]); 186 dup2(pfd[1], 1); 187 close(pfd[1]); 188 } 189 if(e) 190 exportenv(e); 191 if(shflags) 192 execl(shell, shellname, shflags, "-c", cmd, nil); 193 else 194 execl(shell, shellname, "-c", cmd, nil); 195 perror(shell); 196 _exits("exec"); 197 } 198 if(fd){ 199 close(pfd[1]); 200 *fd = pfd[0]; 201 } 202 return pid; 203 } 204 205 void 206 Exit(void) 207 { 208 while(wait(0) >= 0) 209 ; 210 exits("error"); 211 } 212 213 static struct 214 { 215 int sig; 216 char *msg; 217 } sigmsgs[] = 218 { 219 SIGALRM, "alarm", 220 SIGFPE, "sys: fp: fptrap", 221 SIGPIPE, "sys: write on closed pipe", 222 SIGILL, "sys: trap: illegal instruction", 223 SIGSEGV, "sys: segmentation violation", 224 0, 0 225 }; 226 227 static void 228 notifyf(int sig) 229 { 230 int i; 231 232 for(i = 0; sigmsgs[i].msg; i++) 233 if(sigmsgs[i].sig == sig) 234 killchildren(sigmsgs[i].msg); 235 236 /* should never happen */ 237 signal(sig, SIG_DFL); 238 kill(getpid(), sig); 239 } 240 241 void 242 catchnotes() 243 { 244 int i; 245 246 for(i = 0; sigmsgs[i].msg; i++) 247 signal(sigmsgs[i].sig, notifyf); 248 } 249 250 char* 251 maketmp(void) 252 { 253 static char temp[L_tmpnam]; 254 255 return tmpnam(temp); 256 } 257 258 int 259 chgtime(char *name) 260 { 261 Dir *sbuf; 262 struct utimbuf u; 263 264 if((sbuf = dirstat(name)) != nil) { 265 u.actime = sbuf->atime; 266 free(sbuf); 267 u.modtime = time(0); 268 return utime(name, &u); 269 } 270 return close(create(name, OWRITE, 0666)); 271 } 272 273 void 274 rcopy(char **to, Resub *match, int n) 275 { 276 int c; 277 char *p; 278 279 *to = match->s.sp; /* stem0 matches complete target */ 280 for(to++, match++; --n > 0; to++, match++){ 281 if(match->s.sp && match->e.ep){ 282 p = match->e.ep; 283 c = *p; 284 *p = 0; 285 *to = strdup(match->s.sp); 286 *p = c; 287 } 288 else 289 *to = 0; 290 } 291 } 292 293 ulong 294 mkmtime(char *name) 295 { 296 Dir *buf; 297 ulong t; 298 299 buf = dirstat(name); 300 if(buf == nil) 301 return 0; 302 t = buf->mtime; 303 free(buf); 304 return t; 305 } 306 307 308 char *stab; 309 310 char * 311 membername(char *s, int fd, char *sz) 312 { 313 long t; 314 char *p, *q; 315 316 if(s[0] == '/' && s[1] == '\0'){ /* long file name string table */ 317 t = atol(sz); 318 if(t&01) t++; 319 stab = malloc(t); 320 if(read(fd, stab, t) != t) 321 {} 322 return nil; 323 } 324 else if(s[0] == '/' && stab != nil) { /* index into string table */ 325 p = stab+atol(s+1); 326 q = strchr(p, '/'); 327 if (q) 328 *q = 0; /* terminate string here */ 329 return p; 330 }else 331 return s; 332 } 333