URI:
       trcstart.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       trcstart.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 }