plan9port

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

rcstart.c (3763B)


      1 #include <u.h>
      2 #include <signal.h>
      3 #include <libc.h>
      4 #include "term.h"
      5 
      6 int loginshell;
      7 
      8 static void
      9 sys(char *buf, int devnull)
     10 {
     11 	char buf2[100];
     12 	char *f[20];
     13 	int nf, pid;
     14 
     15 	notedisable("sys: child");
     16 	strcpy(buf2, buf);
     17 	nf = tokenize(buf2, f, nelem(f));
     18 	f[nf] = nil;
     19 	switch(pid = fork()){
     20 	case 0:
     21 		close(1);
     22 		open("/dev/null", OREAD);
     23 		close(2);
     24 		open("/dev/null", OREAD);
     25 		execvp(f[0], f);
     26 		_exit(2);
     27 	default:
     28 		waitpid();
     29 		noteenable("sys: child");
     30 	}
     31 }
     32 
     33 int
     34 rcstart(int argc, char **argv, int *pfd, int *tfd)
     35 {
     36 	int fd[2], i, pid;
     37 	char *cmd, *xargv[4];
     38 	char slave[256];
     39 	int sfd;
     40 
     41 	if(argc == 0){
     42 		argc = 2;
     43 		argv = xargv;
     44 		argv[0] = getenv("SHELL");
     45 		if(argv[0] == 0)
     46 			argv[0] = "rc";
     47 		argv[1] = "-i";
     48 		argv[2] = 0;
     49 		if(loginshell){
     50 			argv[2] = "-l";
     51 			argv[3] = 0;
     52 			argc = 3;
     53 		}
     54 	}
     55 	cmd = argv[0];
     56 	if(loginshell){
     57 		argv[0] = malloc(strlen(cmd)+2);
     58 		strcpy(argv[0]+1, cmd);
     59 		argv[0][0] = '-';
     60 	}
     61 
     62 	/*
     63 	 * fd0 is slave (tty), fd1 is master (pty)
     64 	 */
     65 	fd[0] = fd[1] = -1;
     66 	if(getpts(fd, slave) < 0){
     67 		exit(3);
     68 		sysfatal("getpts: %r\n");
     69 	}
     70 	/*
     71 	 * notedisable("sys: window size change");
     72 	 *
     73 	 * Can't disable because will be inherited by other programs
     74 	 * like if you run an xterm from the prompt, and then xterm's
     75 	 * resizes won't get handled right.  Sigh.
     76 	 *
     77 	 * Can't not disable because when we stty below we'll get a
     78 	 * signal, which will drop us into the thread library note handler,
     79 	 * which will get all confused because we just forked and thus
     80 	 * have an unknown pid.
     81 	 *
     82 	 * So disable it internally.  ARGH!
     83 	 */
     84 	notifyoff("sys: window size change");
     85 
     86 	// This used to be TERM=9term but we don't know of anything that cares.
     87 	// Worse, various cc have started assuming that TERM != dumb implies
     88 	// the ability to understand ANSI escape codes. 9term will squelch them
     89 	// but acme win does not.
     90 	putenv("TERM", "dumb");
     91 
     92 	// Set $termprog to 9term or win for those who care about what kind of
     93 	// dumb terminal this is.
     94 	putenv("termprog", (char*)termprog);
     95 	putenv("TERM_PROGRAM", (char*)termprog);
     96 
     97 	pid = fork();
     98 	switch(pid){
     99 	case 0:
    100 		sfd = childpty(fd, slave);
    101 		dup(sfd, 0);
    102 		dup(sfd, 1);
    103 		dup(sfd, 2);
    104 		sys("stty tabs -onlcr icanon echo erase '^h' intr '^?'", 0);
    105 		sys("stty onocr", 1);	/* not available on mac */
    106 		for(i=3; i<100; i++)
    107 			close(i);
    108 		signal(SIGINT, SIG_DFL);
    109 		signal(SIGHUP, SIG_DFL);
    110 		signal(SIGTERM, SIG_DFL);
    111 		execvp(cmd, argv);
    112 		fprint(2, "exec %s failed: %r\n", argv[0]);
    113 		_exit(2);
    114 		break;
    115 	case -1:
    116 		sysfatal("proc failed: %r");
    117 		break;
    118 	}
    119 	*pfd = fd[1];
    120 	close(fd[0]);
    121 	if(tfd){
    122 		if((*tfd = open(slave, OREAD)) < 0)
    123 			sysfatal("parent open %s: %r", slave);
    124 	}
    125 	return pid;
    126 }
    127 
    128 struct {
    129 	Lock l;
    130 	char buf[1<<20];
    131 	int r, w;
    132 } echo;
    133 
    134 void
    135 echoed(char *p, int n)
    136 {
    137 	lock(&echo.l);
    138 	if(echo.r > 0) {
    139 		memmove(echo.buf, echo.buf+echo.r, echo.w-echo.r);
    140 		echo.w -= echo.r;
    141 		echo.r = 0;
    142 	}
    143 	if(echo.w+n > sizeof echo.buf)
    144 		echo.r = echo.w = 0;
    145 	if(echo.w+n > sizeof echo.buf)
    146 		n = 0;
    147 	memmove(echo.buf+echo.w, p, n);
    148 	echo.w += n;
    149 	unlock(&echo.l);
    150 }
    151 
    152 int
    153 echocancel(char *p, int n)
    154 {
    155 	int i;
    156 
    157 	lock(&echo.l);
    158 	for(i=0; i<n; i++) {
    159 		if(echo.r < echo.w) {
    160 			if(echo.buf[echo.r] == p[i]) {
    161 				echo.r++;
    162 				continue;
    163 			}
    164 			if(echo.buf[echo.r] == '\n' && p[i] == '\r')
    165 				continue;
    166 			if(p[i] == 0x08) {
    167 				if(i+2 <= n && p[i+1] == ' ' && p[i+2] == 0x08)
    168 					i += 2;
    169 				continue;
    170 			}
    171 		}
    172 		echo.r = echo.w;
    173 		break;
    174 	}
    175 	unlock(&echo.l);
    176 	if(i > 0)
    177 		memmove(p, p+i, n-i);
    178 	return n-i;
    179 }
    180 
    181 int
    182 dropcrnl(char *p, int n)
    183 {
    184 	char *r, *w;
    185 
    186 	for(r=w=p; r<p+n; r++) {
    187 		if(r+1<p+n && *r == '\r' && *(r+1) == '\n')
    188 			continue;
    189 		if(*r == 0x08) {
    190 			if(r+2<=p+n && *(r+1) == ' ' && *(r+2) == 0x08)
    191 				r += 2;
    192 			continue;
    193 		}
    194 		*w++ = *r;
    195 	}
    196 	return w-p;
    197 }