| unix.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| 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… | |
| 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 du… | |
| 85 else | |
| 86 snprint(msg, ERRMAX, "signal %d", status… | |
| 87 } else if(status&0xff00) | |
| 88 snprint(msg, ERRMAX, "exit(%d)", (status>>8)&0xf… | |
| 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 *s… | |
| 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->cur… | |
| 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 targ… | |
| 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 } |