plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }