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 }