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(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 }