home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / iproc-ptys.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  9KB  |  466 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* NOTE WELL:
  9.  * This file is "included" into iproc.c -- it is not compiled separately!
  10.  */
  11.  
  12. #include <sys/time.h>
  13. #include <fcntl.h>
  14. #include <signal.h>
  15. #include "ttystate.h"
  16. #include "wait.h"
  17. #ifdef BSD386
  18. #include <sys/ioctl.h>
  19. #endif
  20.  
  21. #define DEAD    1    /* dead but haven't informed user yet */
  22. #define STOPPED    2    /* job stopped */
  23. #define RUNNING    3    /* just running */
  24. #define NEW    4    /* brand new, never been ... received no input */
  25.  
  26. /* If process is dead, flags says how. */
  27. #define EXITED    1
  28. #define KILLED    2
  29.  
  30. #define isdead(p)    ((p) == NULL || proc_state((p)) == DEAD || (p)->p_fd == -1)
  31. #define makedead(p)    { proc_state((p)) = DEAD; }
  32.  
  33. #define proc_buf(p)    ((p)->p_buffer->b_name)
  34. #define proc_cmd(p)    ((p)->p_name)
  35. #define proc_state(p)    ((p)->p_state)
  36.  
  37. private Process    *procs = NULL;
  38.  
  39. fd_set    global_fd;
  40. int    NumProcs = 0;
  41.  
  42. private Process *
  43. proc_pid(pid)
  44. int    pid;
  45. {
  46.     register Process    *p;
  47.  
  48.     for (p = procs; p != NULL; p = p->p_next)
  49.         if (p->p_pid == pid)
  50.             break;
  51.  
  52.     return p;
  53. }
  54.  
  55. void
  56. read_proc(fd)
  57. register int    fd;
  58. {
  59.     register Process    *p;
  60.     int    n;
  61.     char    ibuf[1024];
  62.  
  63.     for (p = procs; p != NULL; p = p->p_next)
  64.         if (p->p_fd == fd)
  65.             break;
  66.  
  67.     if (p == NULL) {
  68.         writef("\riproc: unknown fd %d", fd);
  69.         return;
  70.     }
  71.  
  72.     n = read(fd, (UnivPtr) ibuf, sizeof(ibuf) - 1);
  73.     if (n == -1 && (errno == EIO || errno == EWOULDBLOCK)) {
  74.         if (proc_state(p) == NEW)
  75.             return;
  76.         proc_close(p);
  77.         makedead(p);
  78.         return;
  79.     } else {
  80.         if (proc_state(p) != RUNNING) {
  81.             proc_state(p) = RUNNING;
  82.             UpdModLine = YES;
  83.         }
  84.     }
  85.     if (n <= 0) {
  86.         if (n == 0)
  87.             strcpy(ibuf, "[Process EOF]");
  88.         else
  89.             swritef(ibuf, sizeof(ibuf),
  90.                 "\n[pty read error: %d]\n", errno);
  91.     } else
  92.         ibuf[n] = '\0';
  93.     proc_rec(p, ibuf);
  94. }
  95.  
  96. void
  97. ProcKill()
  98. {
  99.     register Buffer    *b;
  100.     char    *bname;
  101.  
  102.     bname = ask_buf(curbuf);
  103.  
  104.     if ((b = buf_exists(bname)) == NULL)
  105.         complain("[No such buffer]");
  106.     if (b->b_process == NULL)
  107.         complain("%s not tied to a process.", bname);
  108.     proc_kill(b->b_process, SIGKILL);
  109. }
  110.  
  111. void
  112. ProcCont()
  113. {
  114.     Process    *p;
  115.  
  116.     if ((p = curbuf->b_process) == NULL)
  117.         complain("[No process]");
  118.     if (p->p_state != DEAD) {
  119.         proc_kill(p, SIGCONT);
  120.         UpdModLine = YES;
  121.         p->p_state = RUNNING;
  122.     }
  123. }
  124.  
  125. private void
  126. send_p(c)
  127. char    c;
  128. {
  129.     Process    *p;
  130.     char    buf[2];
  131.  
  132.     if ((p = curbuf->b_process) == NULL)
  133.         complain("[No process]");
  134.     ToLast();
  135.     buf[0] = c;
  136.     buf[1] = '\0';
  137.     proc_rec(p, buf);
  138.     (void) write(p->p_fd, (UnivPtr) &c, (size_t) 1);
  139. }
  140.  
  141. void
  142. ProcEof()
  143. {
  144. #ifdef SGTTY
  145.     send_p(tc[OFF].t_eofc);
  146. #else
  147.     send_p(sg[OFF].c_cc[VEOF]);
  148. #endif
  149. }
  150.  
  151. void
  152. ProcInt()
  153. {
  154. #ifdef SGTTY
  155.     send_p(tc[OFF].t_intrc);
  156. #else
  157.     send_p(sg[OFF].c_cc[VINTR]);
  158. #endif
  159.  
  160. }
  161.  
  162. void
  163. ProcQuit()
  164. {
  165. #ifdef SGTTY
  166.     send_p(tc[OFF].t_quitc);
  167. #else
  168.     send_p(sg[OFF].c_cc[VQUIT]);
  169. #endif
  170. }
  171.  
  172. void
  173. ProcStop()
  174. {
  175. #ifdef SGTTY
  176.     send_p(ls[OFF].t_suspc);
  177. #else
  178.     send_p(sg[OFF].c_cc[VSUSP]);
  179. #endif
  180. }
  181.  
  182. void
  183. ProcDStop()
  184. {
  185. #ifdef SGTTY
  186.     send_p(ls[OFF].t_dsuspc);
  187. #else
  188.     send_p(sg[OFF].c_cc[VDSUSP]);
  189. #endif
  190. }
  191.  
  192. private void
  193. proc_close(p)
  194. Process *p;
  195. {
  196.     SigHold(SIGCHLD);    /* be mutually exclusive */
  197.  
  198.     if (p->p_fd >= 0) {
  199.         (void) close(p->p_fd);
  200.         FD_CLR(p->p_fd, &global_fd);
  201.         NumProcs -= 1;
  202.         p->p_fd = -1;
  203.     }
  204.  
  205.     SigRelse(SIGCHLD);
  206. }
  207.  
  208. private void
  209. proc_write(p, buf, nbytes)
  210. Process *p;
  211. char    *buf;
  212. size_t    nbytes;
  213. {
  214.     fd_set    mask;
  215.  
  216.     FD_ZERO(&mask);
  217.     FD_SET(p->p_fd, &mask);
  218.  
  219.     while (write(p->p_fd, (UnivPtr) buf, nbytes) <  0)
  220.         select(p->p_fd + 1, (fd_set *)0, &mask, (fd_set *)0, (struct timeval *)0);
  221. }
  222.  
  223. #ifdef    STDARGS
  224.     private void
  225. proc_strt(char *bufname, int clobber, ...)
  226. #else
  227.     private /*VARARGS2*/ void
  228. proc_strt(bufname, clobber, va_alist)
  229.     char    *bufname;
  230.     int    clobber;
  231.     va_dcl
  232. #endif
  233. {
  234.     va_list    ap;
  235.     char    *argv[32],
  236.         *cp;
  237.     Window *owind = curwind;
  238.     int    pid;
  239.     Process    *newp;
  240.     Buffer     *newbuf;
  241.     int    i,
  242.         ptyfd = -1,
  243.         ttyfd,
  244.         ldisc,
  245.         lmode;
  246.     register char    *s,
  247.             *t;
  248.     char    ttybuf[11],
  249.         ptybuf[11];
  250.     char    cmdbuf[LBSIZE];
  251. #if defined(SGTTY) || defined(BRLUNIX)
  252. #ifdef    BRLUNIX
  253.     struct sg_brl sgt;
  254. #else
  255.     struct sgttyb sgt;
  256. #endif
  257. #endif
  258. #ifdef TERMIO
  259.     struct termio    sgt;
  260. #endif
  261. #ifdef TERMIOS
  262.     struct termios    sgt;
  263. #endif
  264.  
  265. #ifdef    TIOCGWINSZ
  266.     struct winsize win;
  267. #else
  268. #  ifdef    BTL_BLIT
  269. #  include <sys/jioctl.h>
  270.     struct jwinsize jwin;
  271. #  endif
  272. #endif
  273.  
  274.     isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  275.                    or is of type B_PROCESS */
  276.     va_init(ap, clobber);
  277.     make_argv(argv, ap);
  278.     va_end(ap);
  279.     if (access(argv[0], X_OK) != 0) {
  280.         complain("[Couldn't access %s: %s]", argv[0], strerror(errno));
  281.         /* NOTREACHED */
  282.     }
  283.     for (s = "pqrs"; ptyfd<0; s++) {
  284.         if (*s == '\0')
  285.             complain("[Out of ptys!]");
  286.         for (t = "0123456789abcdef"; *t; t++) {
  287.             swritef(ptybuf, sizeof(ptybuf), "/dev/pty%c%c", *s, *t);
  288.             if ((ptyfd = open(ptybuf, 2)) >= 0) {
  289.                 strcpy(ttybuf, ptybuf);
  290.                 ttybuf[5] = 't';
  291.                 /* make sure both ends are available */
  292.                 if ((i = open(ttybuf, 2)) < 0) {
  293.                     (void) close(ptyfd);
  294.                     ptyfd = -1;
  295.                 } else {
  296.                     (void) close(i);
  297.                     break;
  298.                 }
  299.             }
  300.         }
  301.     }
  302.  
  303. #ifdef    TIOCGETD
  304.     (void) ioctl(0, TIOCGETD, (UnivPtr) &ldisc);
  305. #endif
  306. #ifdef    TIOCLGET
  307.     (void) ioctl(0, TIOCLGET, (UnivPtr) &lmode);
  308. #endif
  309. #ifdef    TIOCGWINSZ
  310.     (void) ioctl(0, TIOCGWINSZ, (UnivPtr) &win);
  311. #else
  312. #  ifdef    BTL_BLIT
  313.     (void) ioctl(0, JWINSIZE, (UnivPtr) &jwin);
  314. #  endif    /* BTL_BLIT */
  315. #endif
  316.  
  317.     SigHold(SIGCHLD);
  318. #ifdef    SIGWINCH
  319.     SigHold(SIGWINCH);
  320. #endif
  321.     switch (pid = fork()) {
  322.     case -1:
  323.         (void) close(ptyfd);
  324.         s_mess("[Fork failed! %s]", strerror(errno));
  325.         goto fail;
  326.  
  327.     case 0:
  328.         SigRelse(SIGCHLD);
  329. #ifdef    SIGWINCH
  330.         SigRelse(SIGWINCH);
  331. #endif
  332.         for (i = 0; i < 32; i++)
  333.             (void) close(i);
  334.  
  335. #ifdef    TIOCNOTTY
  336.         if ((i = open("/dev/tty", 2)) >= 0) {
  337.             (void) ioctl(i, TIOCNOTTY, (UnivPtr)NULL);
  338.             (void) close(i);
  339.         }
  340. #endif
  341.         if ((ttyfd = open(ttybuf, 2)) < 0)
  342.             exit(-1);
  343.         (void) dup2(ttyfd, 1);
  344.         (void) dup2(ttyfd, 2);
  345.  
  346. #ifdef    TIOCSETD
  347.         (void) ioctl(0, TIOCSETD, (UnivPtr) &ldisc);
  348. #endif
  349. #ifdef    TIOCLSET
  350.         (void) ioctl(0, TIOCLSET, (UnivPtr) &lmode);
  351. #endif
  352. #ifdef    TIOCSETC
  353.         (void) ioctl(0, TIOCSETC, (UnivPtr) &tc[OFF]);
  354. #endif
  355. #ifdef    TIOCSLTC
  356.         (void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[OFF]);
  357. #endif
  358.  
  359. #ifdef    TIOCGWINSZ
  360. #    ifdef    SIGWINCH
  361.         (void) signal(SIGWINCH, SIG_IGN);
  362. #    endif
  363.         win.ws_row = curwind->w_height;
  364.         (void) ioctl(0, TIOCSWINSZ, (UnivPtr) &win);
  365. #else
  366. #  ifdef    BTL_BLIT
  367.         jwin.bytesy = curwind->w_height;
  368.         (void) ioctl(0, JSWINSIZE, (UnivPtr) &jwin);
  369. #  endif
  370. #endif
  371.  
  372.         sgt = sg[OFF];
  373. #ifdef SGTTY
  374.         sgt.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
  375.         (void) stty(0, &sgt);
  376. #else
  377.         sgt.c_lflag &= ~(ISIG|ICANON|ECHO);
  378.         sgt.c_lflag |= ISIG|ICANON|IEXTEN;
  379. #ifndef OCRNL
  380. #define OCRNL 0
  381. #endif
  382.         sgt.c_oflag &= ~(OCRNL|ONLCR);
  383. # ifdef    TERMIO
  384.         (void) ioctl(0, TCSETAW, (UnivPtr) &sgt);
  385. # endif    /* TERMIO */
  386.  
  387. # ifdef    TERMIOS
  388.         (void) tcsetattr(0, TCSADRAIN, &sgt);
  389. # endif /* TERMIOS */
  390. #endif
  391.  
  392.         {
  393.             int    on = 1;
  394.  
  395.             (void) ioctl(0, TIOCREMOTE, (UnivPtr) &on);
  396.         }
  397.  
  398. #ifdef TIOCSCTTY
  399.         (void) setsid();
  400.         (void) ioctl(0, TIOCSCTTY, 0);
  401. #else
  402.         i = getpid();
  403.         (void) ioctl(0, TIOCSPGRP, (UnivPtr) &i);
  404.         (void) setpgrp(0, i);
  405. #endif
  406.         execv(argv[0], (const char **) &argv[1]);
  407.         raw_scream("execve failed! %s\n");
  408.         _exit(errno + 1);
  409.     }
  410.  
  411.     newp = (Process *) emalloc(sizeof *newp);
  412.  
  413. #ifdef    O_NDELAY
  414.     fcntl (ptyfd, F_SETFL, O_NDELAY);
  415. #endif
  416.     newp->p_fd = ptyfd;
  417.     newp->p_pid = pid;
  418.  
  419.     newbuf = do_select((Window *)NULL, bufname);
  420.     newbuf->b_type = B_PROCESS;
  421.     newp->p_buffer = newbuf;
  422.     newbuf->b_process = newp;    /* sorta circular, eh? */
  423.     pop_wind(bufname, clobber, B_PROCESS);
  424.     /* Pop_wind() after everything is set up; important!
  425.        Bindings won't work right unless newbuf->b_process is already
  426.        set up BEFORE NEWBUF is first SetBuf()'d. */
  427.     ToLast();
  428.     if (!bolp())
  429.         LineInsert(1);
  430.  
  431.     cmdbuf[0] = '\0';
  432.     va_init(ap, clobber);
  433.     while ((cp = va