plan9port/src/cmd/9term/rcstart.c

182 lines
3.2 KiB
C
Raw Normal View History

2004-03-25 23:03:57 +00:00
#include <u.h>
#include <signal.h>
2004-04-19 23:03:46 +00:00
#include <libc.h>
2004-03-25 23:03:57 +00:00
#include "term.h"
2006-01-18 23:11:00 +00:00
int loginshell;
2004-09-21 01:11:28 +00:00
static void
2004-12-26 21:37:31 +00:00
sys(char *buf, int devnull)
2004-09-21 01:11:28 +00:00
{
char buf2[100];
char *f[20];
int nf, pid;
2004-12-26 21:37:31 +00:00
notedisable("sys: child");
2004-09-21 01:11:28 +00:00
strcpy(buf2, buf);
nf = tokenize(buf2, f, nelem(f));
f[nf] = nil;
switch(pid = fork()){
case 0:
2004-12-26 21:37:31 +00:00
close(1);
open("/dev/null", OREAD);
close(2);
open("/dev/null", OREAD);
2004-09-21 01:11:28 +00:00
execvp(f[0], f);
2004-12-26 21:37:31 +00:00
_exit(2);
2004-09-21 01:11:28 +00:00
default:
waitpid();
}
}
2004-03-25 23:03:57 +00:00
int
rcstart(int argc, char **argv, int *pfd, int *tfd)
2004-03-25 23:03:57 +00:00
{
2004-04-16 15:27:29 +00:00
int fd[2], i, pid;
2006-01-18 23:11:00 +00:00
char *cmd, *xargv[3];
2004-03-25 23:03:57 +00:00
char slave[256];
int sfd;
if(argc == 0){
argc = 2;
argv = xargv;
argv[0] = getenv("SHELL");
if(argv[0] == 0)
argv[0] = "rc";
2006-01-18 23:05:38 +00:00
argv[1] = "-i";
2004-03-25 23:03:57 +00:00
argv[2] = 0;
}
2006-01-18 23:11:00 +00:00
cmd = argv[0];
if(loginshell){
argv[0] = malloc(strlen(cmd)+2);
strcpy(argv[0]+1, cmd);
argv[0][0] = '-';
}
2004-03-25 23:03:57 +00:00
/*
* fd0 is slave (tty), fd1 is master (pty)
*/
fd[0] = fd[1] = -1;
2004-12-26 21:37:31 +00:00
if(getpts(fd, slave) < 0){
exit(3);
2004-03-26 00:09:27 +00:00
sysfatal("getpts: %r\n");
2004-12-26 21:37:31 +00:00
}
2005-07-13 03:53:17 +00:00
/*
* notedisable("sys: window size change");
*
* Can't disable because will be inherited by other programs
* like if you run an xterm from the prompt, and then xterm's
2005-07-21 15:43:51 +00:00
* resizes won't get handled right. Sigh.
*
* Can't not disable because when we stty below we'll get a
* signal, which will drop us into the thread library note handler,
* which will get all confused because we just forked and thus
* have an unknown pid.
*
* So disable it internally. ARGH!
2005-07-13 03:53:17 +00:00
*/
2005-07-21 15:43:51 +00:00
notifyoff("sys: window size change");
2009-06-09 09:26:13 -07:00
putenv("TERM", "9term");
2004-12-26 21:37:31 +00:00
pid = fork();
switch(pid){
2004-03-25 23:03:57 +00:00
case 0:
sfd = childpty(fd, slave);
dup(sfd, 0);
dup(sfd, 1);
dup(sfd, 2);
2004-12-26 21:37:31 +00:00
sys("stty tabs -onlcr icanon echo erase '^h' intr '^?'", 0);
sys("stty onocr", 1); /* not available on mac */
2004-04-16 15:27:29 +00:00
for(i=3; i<100; i++)
close(i);
2004-09-21 01:11:28 +00:00
signal(SIGINT, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGTERM, SIG_DFL);
2006-01-18 23:11:00 +00:00
execvp(cmd, argv);
2004-03-25 23:03:57 +00:00
fprint(2, "exec %s failed: %r\n", argv[0]);
2004-12-26 21:37:31 +00:00
_exit(2);
2004-03-25 23:03:57 +00:00
break;
case -1:
sysfatal("proc failed: %r");
break;
}
*pfd = fd[1];
2004-04-16 15:27:29 +00:00
close(fd[0]);
if(tfd){
if((*tfd = open(slave, OREAD)) < 0)
sysfatal("parent open %s: %r", slave);
}
2004-03-25 23:03:57 +00:00
return pid;
}
struct {
Lock l;
char buf[1<<20];
int r, w;
} echo;
void
echoed(char *p, int n)
{
lock(&echo.l);
if(echo.r > 0) {
memmove(echo.buf, echo.buf+echo.r, echo.w-echo.r);
echo.w -= echo.r;
echo.r = 0;
}
if(echo.w+n > sizeof echo.buf)
echo.r = echo.w = 0;
if(echo.w+n > sizeof echo.buf)
n = 0;
memmove(echo.buf+echo.w, p, n);
echo.w += n;
unlock(&echo.l);
}
int
echocancel(char *p, int n)
{
int i;
lock(&echo.l);
for(i=0; i<n; i++) {
if(echo.r < echo.w) {
if(echo.buf[echo.r] == p[i]) {
echo.r++;
continue;
}
if(echo.buf[echo.r] == '\n' && p[i] == '\r')
continue;
if(p[i] == 0x08) {
if(i+2 <= n && p[i+1] == ' ' && p[i+2] == 0x08)
i += 2;
continue;
}
}
echo.r = echo.w;
break;
}
unlock(&echo.l);
if(i > 0)
memmove(p, p+i, n-i);
return n-i;
}
int
dropcrnl(char *p, int n)
{
char *r, *w;
for(r=w=p; r<p+n; r++) {
if(r+1<p+n && *r == '\r' && *(r+1) == '\n')
continue;
if(*r == 0x08) {
if(r+2<=p+n && *(r+1) == ' ' && *(r+2) == 0x08)
r += 2;
continue;
}
*w++ = *r;
}
return w-p;
}