#include "term.h" #include #include #include #include #include #include /* key that gets us out of VT52 -- ^G, for now */ #define QUITKEY '\007' extern void normal_putch(), escy_putch(); int kidpid; /* child's process id */ int kidfd; /* child's file descriptor */ int savex, savey; /* saved x, y coordinates */ void (*state)(); /* * clrfrom(x1, y1, x2, y2): clear screen from position (x1,y1) to * position (x2, y2) inclusive. It is assumed that y2 >= y1. */ void clrfrom(x1, y1, x2, y2) int x1,y1,x2,y2; { } void ignore() { state = normal_putch; } /* * putesc(v, c): handle the control sequence ESC c */ #define gotoxy(x, y) m_move(x, y) void putesc(c) int c; { int cx, cy; switch (c) { case 'A': /* cursor up */ m_up(10); /* BUG -- this scrolls; it shouldn't */ break; case 'B': /* cursor down */ m_down(10); /* BUG -- this scrolls; it shouldn't */ break; case 'C': /* cursor right */ m_right(10); break; case 'D': /* cursor left */ m_left(10); break; case 'E': /* clear home */ m_clear(); break; case 'H': /* cursor home */ gotoxy(0, 0); break; case 'I': /* cursor up, insert line */ m_up(10); break; case 'J': /* clear below cursor */ m_cleareos(); break; case 'K': /* clear remainder of line */ m_cleareol(); break; case 'L': /* insert a line */ m_addline(); break; case 'M': /* delete line */ m_deleteline(); break; case 'Y': state = escy_putch; return; /* YES, this should be 'return' */ case 'b': /* set foreground color */ case 'c': /* set background color */ state = ignore; return; case 'd': /* clear to cursor position */ get_cursor(&cx, &cy); clrfrom(0, 0, cx, cy); break; case 'e': /* enable cursor */ m_setcursor(CS_BLOCK); break; case 'f': /* cursor off */ m_setcursor(CS_INVIS); break; case 'j': /* save cursor position */ get_cursor(&savex, &savey); break; case 'k': /* restore saved position */ gotoxy(savex, savey); break; case 'l': /* clear line */ get_cursor(&cx, &cy); gotoxy(0, cy); m_cleareol(); break; case 'o': /* clear from start of line to cursor */ get_cursor(&cx, &cy); clrfrom(0, cy, cx, cy); break; case 'p': /* reverse video on */ m_standout(); break; case 'q': /* reverse video off */ m_standend(); break; case 'v': /* wrap on */ m_clearmode(M_NOWRAP); break; case 'w': m_setmode(M_NOWRAP); break; } state = normal_putch; } /* * escy1_putch(c): for when an ESC Y + char has been seen */ int escy1; void escy1_putch(c) int c; { gotoxy(c - ' ', escy1 - ' '); state = normal_putch; } /* * escy_putch(v, c): for when an ESC Y has been seen */ void escy_putch(c) int c; { escy1 = c; state = escy1_putch; } /* * normal_putch(c): put character 'c' on screen. This is the default * for when no escape, etc. is active */ void normal_putch(c) int c; { if (c == '\033') state = putesc; else m_putchar(c); } static inline void put_ch(c) int c; { (*state)(c); } int run(shell, argv) char *shell, **argv; { int fd, oldtty; long pid; static char pty[] = "Q:\\VT52@"; /* create our handle */ pid = 0; do { pty[7]++; pid++; fd = Fcreate(pty, FA_SYSTEM|FA_HIDDEN); } while (fd < 0 && pid < 8); if (fd < 0) { printf("couldn't create a pty\n"); quit(2); } kidfd = fd; /* now create the child's handle */ fd = Fopen(pty, 2); oldtty = Fdup(-1); if (oldtty < 0) { Cconws("couldn't dup control terminal!\r\n"); quit(2); } Fforce(-1, fd); /* set up new control terminal */ Fforce(0, fd); Fforce(1, fd); Fforce(2, fd); pid = spawnvp(P_NOWAIT, shell, argv); /* spawn child in background */ Fforce(-1, oldtty); Fforce(0, oldtty); Fforce(1, oldtty); Fforce(2, oldtty); if (pid < 0) { Cconws("couldn't run "); Cconws(shell); Cconws("\r\n"); quit((int)pid); } Psetpgrp((int)pid, (int)pid); /* set the child's process group */ Fcntl(fd, &pid, TIOCSPGRP); /* set the terminal process group */ Fclose(fd); kidpid = pid; return kidfd; } int quit(x) int x; { m_setnoraw(); if (kidpid) Pkill((int)-kidpid, SIGHUP); Pterm(x); } #define INBUFSIZ 256 main(argc, argv) int argc; char **argv; { int fd; long s, c; long reads, fdmask; unsigned char cbuf[INBUFSIZ], *cb; char *shell, *getenv(); struct sgttyb sg; if (argc == 3 && !strcmp(argv[1], "-f")) { fd = Fopen(argv[2], 2); if (fd < 0) { perror(argv[2]); exit(1); } s = Pgetpgrp(); Fcntl(fd, &s, TIOCSPGRP); Fcntl(fd, &sg, TIOCGETP); sg.sg_flags = RAW; Fcntl(fd, &sg, TIOCSETP); } else { if (argv[1]) { argv++; shell = argv[0]; } else { shell = getenv("SHELL"); if (!shell) shell="init.prg"; argv[0] = shell; argv[1] = 0; } fd = run(shell, argv); } m_setup(0); m_size(80, 25); m_clear(); m_setraw(); m_setmode(M_NOBUCKEY); state = normal_putch; fdmask = 1L << fd; for(;;) { reads = 1 | fdmask; Fselect(0, &reads, 0L, 0L); if (reads & fdmask) { s = Finstat(fd); if (s > 0) { if (s > INBUFSIZ) s = INBUFSIZ; cb = cbuf; s = Fread(fd, s, cb); while (s-- > 0) put_ch(*cb++); m_flush(); } else if (s < 0) { Cconws("Child exited??\r\n"); quit((int)s); } } if (reads & 1) { c = Fgetchar(0, 0); if ( (c & 0xff) == QUITKEY ) quit(0); Fputchar(fd, c, 0); } } }