home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / ytalk-3.0 / part01 / exec.c < prev    next >
C/C++ Source or Header  |  1993-08-20  |  4KB  |  237 lines

  1. /* exec.c -- run a command inside a window */
  2.  
  3. /*               NOTICE
  4.  *
  5.  * Copyright (c) 1990,1992,1993 Britt Yenne.  All rights reserved.
  6.  * 
  7.  * This software is provided AS-IS.  The author gives no warranty,
  8.  * real or assumed, and takes no responsibility whatsoever for any 
  9.  * use or misuse of this software, or any damage created by its use
  10.  * or misuse.
  11.  * 
  12.  * This software may be freely copied and distributed provided that
  13.  * no part of this NOTICE is deleted or edited in any manner.
  14.  * 
  15.  */
  16.  
  17. /* Mail comments or questions to ytalk@austin.eds.com */
  18.  
  19. #include "header.h"
  20. #include <fcntl.h>
  21. #include <signal.h>
  22. #include <sys/wait.h>
  23. #ifdef USE_SGTTY
  24. # include <sys/ioctl.h>
  25. # ifdef hpux
  26. #  include <sys/bsdtty.h>
  27. #  include <sgtty.h>
  28. # endif
  29. #endif
  30.  
  31. int running_process = 0;    /* flag: is process running? */
  32. static int pid;            /* currently executing process id */
  33. static int pfd;            /* currently executing process fd */
  34. static int prows, pcols;    /* saved rows, cols */
  35.  
  36. /* ---- local functions ---- */
  37.  
  38. #ifdef USE_SGTTY
  39. static int
  40. setsid()
  41. {
  42.     register int fd;
  43.  
  44.     if((fd = open("/dev/tty", O_RDWR)) >= 0)
  45.     {
  46.     ioctl(fd, TIOCNOTTY);
  47.     close(fd);
  48.     }
  49.     return fd;
  50. }
  51. #endif
  52.  
  53. static int
  54. getpty(name)
  55.   char *name;
  56. {
  57.     register int pty, tty;
  58.  
  59.     strcpy(name, "/dev/ptyp0");
  60.     while(access(name, 0) == 0)
  61.     {
  62.     if((pty = open(name, O_RDWR)) >= 0)
  63.     {
  64.         name[5] = 't';
  65.         if((tty = open(name, O_RDWR)) >= 0)
  66.         {
  67.         close(tty);
  68.         return pty;
  69.         }
  70.         name[5] = 'p';
  71.         close(pty);
  72.     }
  73.  
  74.     /* get next pty name */
  75.  
  76.     if(name[9] == 'f')
  77.     {
  78.         name[8]++;
  79.         name[9] = '0';
  80.     }
  81.     else if(name[9] == '9')
  82.         name[9] = 'a';
  83.     else
  84.         name[9]++;
  85.     }
  86.     errno = ENOENT;
  87.     return -1;
  88. }
  89.  
  90. static void
  91. exec_input(fd)
  92.   int fd;
  93. {
  94.     register int rc;
  95.     static ychar buf[MAXBUF];
  96.  
  97.     if((rc = read(fd, buf, MAXBUF)) <= 0)
  98.     {
  99.     kill_exec();
  100.     errno = 0;
  101.     show_error("command shell terminated");
  102.     return;
  103.     }
  104.     show_input(me, buf, rc);
  105.     send_users(buf, rc);
  106. }
  107.  
  108. static void
  109. calculate_size(rows, cols)
  110.   int *rows, *cols;
  111. {
  112.     register yuser *u;
  113.  
  114.     *rows = me->t_rows;
  115.     *cols = me->t_cols;
  116.  
  117.     for(u = connect_list; u; u = u->next)
  118.     if(u->remote.vmajor > 2)
  119.     {
  120.         if(u->remote.my_rows > 1 && u->remote.my_rows < *rows)
  121.         *rows = u->remote.my_rows;
  122.         if(u->remote.my_cols > 1 && u->remote.my_cols < *cols)
  123.         *cols = u->remote.my_cols;
  124.     }
  125. }
  126.  
  127. /* ---- global functions ---- */
  128.  
  129. /* Execute a command inside my window.  If command is NULL, then execute
  130.  * a shell.
  131.  */
  132. void
  133. execute(command)
  134.   char *command;
  135. {
  136.     int fd;
  137.     char name[20], *shell;
  138.  
  139.     if(me->flags & FL_LOCKED)
  140.     {
  141.     errno = 0;
  142.     show_error("alternate mode already running");
  143.     return;
  144.     }
  145.     if((fd = getpty(name)) < 0)
  146.     {
  147.     msg_term(me, "cannot get pseudo terminal");
  148.     return;
  149.     }
  150.     if((shell = getenv("SHELL")) == NULL)
  151.     shell = "/bin/sh";
  152.     calculate_size(&prows, &pcols);
  153.     if((pid = fork()) == 0)
  154.     {
  155.     close_all();
  156.         if(setsid() < 0)
  157.             exit(-1);
  158.         if((fd = open(name, O_RDWR)) < 0)
  159.             exit(-1);
  160.         dup2(fd, 0);
  161.         dup2(fd, 1);
  162.         dup2(fd, 2);
  163.  
  164.     /* set terminal characteristics */
  165.  
  166.     set_terminal_flags(fd);
  167.     set_terminal_size(fd, prows, pcols);
  168. #ifndef NeXT
  169.     putenv("TERM=vt100");
  170. #endif
  171.  
  172.     /* execute the command */
  173.  
  174.     if(command)
  175.         execl(shell, shell, "-c", command, NULL);
  176.     else
  177.         execl(shell, shell, NULL);
  178.     perror("execl");
  179.     (void)exit(-1);
  180.     }
  181.     if(pid < 0)
  182.     {
  183.     show_error("fork() failed");
  184.     return;
  185.     }
  186.     set_win_region(me, prows, pcols);
  187.     sleep(1);
  188.     pfd = fd;
  189.     running_process = 1;
  190.     lock_flags(FL_RAW | FL_SCROLL);
  191.     add_fd(fd, exec_input);
  192. }
  193.  
  194. /* Send input to the command shell.
  195.  */
  196. void
  197. update_exec()
  198. {
  199.     (void)write(pfd, io_ptr, io_len);
  200.     io_len = 0;
  201. }
  202.  
  203. /* Kill the command shell.
  204.  */
  205. void
  206. kill_exec()
  207. {
  208.     if(!running_process)
  209.     return;
  210.     remove_fd(pfd);
  211.     close(pfd);
  212.     running_process = 0;
  213.     unlock_flags();
  214.     end_win_region(me);
  215. }
  216.  
  217. /* Send a SIGWINCH to the process.
  218.  */
  219. void
  220. winch_exec()
  221. {
  222.     int rows, cols;
  223.  
  224.     if(!running_process)
  225.     return;
  226.     calculate_size(&rows, &cols);
  227.     if(rows == prows && cols == pcols)
  228.     return;
  229.     prows = rows;
  230.     pcols = cols;
  231.     set_terminal_size(pfd, prows, pcols);
  232.     set_win_region(me, prows, pcols);
  233. #ifdef SIGWINCH
  234.     kill(pid, SIGWINCH);
  235. #endif
  236. }
  237.