Blob


1 #include <u.h>
2 #include <signal.h>
3 #include <libc.h>
4 #include "term.h"
6 int loginshell;
8 static void
9 sys(char *buf, int devnull)
10 {
11 char buf2[100];
12 char *f[20];
13 int nf, pid;
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 }
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;
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 }
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");
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");
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);
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;
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);
125 return pid;
128 struct {
129 Lock l;
130 char buf[1<<20];
131 int r, w;
132 } echo;
134 void
135 echoed(char *p, int n)
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;
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);
152 int
153 echocancel(char *p, int n)
155 int i;
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;
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;
172 echo.r = echo.w;
173 break;
175 unlock(&echo.l);
176 if(i > 0)
177 memmove(p, p+i, n-i);
178 return n-i;
181 int
182 dropcrnl(char *p, int n)
184 char *r, *w;
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;
194 *w++ = *r;
196 return w-p;