home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / xmail / part02 / callMail.c next >
C/C++ Source or Header  |  1991-06-15  |  9KB  |  291 lines

  1. /*
  2.  * xmail - X window system interface to the mail program
  3.  *
  4.  * Copyright 1989 The University of Texas at Austin
  5.  *
  6.  * Author:    Po Cheung
  7.  * Date:    March 10, 1989
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and
  10.  * its documentation for any purpose and without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and that
  12.  * both that copyright notice and this permission notice appear in
  13.  * supporting documentation.  The University of Texas at Austin makes no 
  14.  * representations about the suitability of this software for any purpose.  
  15.  * It is provided "as is" without express or implied warranty.
  16.  *
  17.  * Copyright 1990 by National Semiconductor Corporation
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software and its
  20.  * documentation for any purpose is hereby granted without fee, provided that
  21.  * the above copyright notice appear in all copies and that both that
  22.  * copyright notice and this permission notice appear in supporting
  23.  * documentation, and that the name of National Semiconductor Corporation not
  24.  * be used in advertising or publicity pertaining to distribution of the
  25.  * software without specific, written prior permission.
  26.  *
  27.  * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  28.  * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  29.  * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  30.  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  31.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  32.  * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  33.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  34.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  35.  * OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  36.  * PERFORMANCE OF THIS SOFTWARE.
  37.  *
  38.  * Author:  Michael C. Wagnitz - National Semiconductor Corporation
  39.  *
  40. **  Xmail talks to mail through a pseudo terminal which is a pair of master
  41. **  and slave devices: /dev/pty?? and /dev/tty??, where ?? goes from p0 to
  42. **  zf (system dependent).  The terminal is opened for both read and write.
  43. **
  44. */
  45.  
  46. #include    "global.h"
  47. #include    <sgtty.h>
  48. #include    <sys/stat.h>
  49.  
  50. #ifdef    SYSV
  51. #include    <sys/termio.h>
  52. #ifdef    att
  53. #include    <fcntl.h>
  54. #include    <sys/stropts.h>
  55. #endif
  56. #else    /* if not SYSV */
  57. #include    <sgtty.h>
  58. #endif
  59.  
  60. #ifndef TTYDEV
  61. #ifdef        hpux
  62. #define TTYDEV        "/dev/pty/ptyxx"
  63. #else    /* !hpux */
  64. #define    TTYDEV        "/dev/ptyxx"
  65. #endif    /* !hpux */
  66. #endif    /* !TTYDEV */
  67.  
  68. #ifndef PTYCHAR1
  69. #ifdef        hpux
  70. #define PTYCHAR1    "zyxwvutsrqp"
  71. #else    /* !hpux */
  72. #define    PTYCHAR1    "pqrstuvwxyz"
  73. #endif    /* !hpux */
  74. #endif    /* !PTYCHAR1 */
  75.  
  76. #ifndef PTYCHAR2
  77. #ifdef        hpux
  78. #define    PTYCHAR2    "fedcba9876543210"
  79. #else    /* !hpux */
  80. #define    PTYCHAR2    "0123456789abcdef"
  81. #endif    /* !hpux */
  82. #endif    /* !PTYCHAR2 */
  83.  
  84. int                mail_fd;        /* mail process master tty id */
  85. int                mailpid;        /* mail process id */
  86. int                mailInputId;        /* mail input id */
  87. char        pseudo_tty[20];
  88.  
  89.  
  90. /*
  91. ** @(#) openMaster - searches for and opens a pty master.  If it finds one,
  92. **             it returns the value of the file descriptor.  If not,
  93. **             it reports an error and terminates.  Portions of this
  94. **             routine were stolen from X11R4 xterm get_pty() sources.
  95. */
  96. int
  97. openMaster()
  98. {
  99.  static int    devindex = 0;
  100.  static int    letter = 0;
  101.  struct    stat    st_buf;
  102.  int        master;
  103.  
  104.  
  105. #ifdef att
  106.  strcpy(pseudo_tty, "/dev/ptmx");
  107.  if ((master = open(pseudo_tty, O_RDWR)) >= 0)
  108.     return(master);
  109. #else /* !att, need lots of code */
  110. #if defined(umips) && defined (SYSV)
  111.  strcpy(pseudo_tty, "/dev/ptc");
  112.  master = open(pseudo_tty, O_RDWR);
  113.  if (master >= 0 && (fstat(master, &st_buf)) == 0) {
  114.     (void) sprintf(pseudo_tty, "/dev/ttyq%d", minor(st_buf.st_rdev));
  115.     if ((c = open(pseudo_tty, O_RDWR)) < 0) {
  116.        close (master);
  117.       } else {                /* got one! */
  118.        close (c);
  119.        return(master);
  120.       }
  121.    }
  122. #else /* not (umips && SYSV) */
  123.  strcpy(pseudo_tty, TTYDEV);
  124.  while (PTYCHAR1[letter]) {
  125.        pseudo_tty[strlen(pseudo_tty) - 2] = PTYCHAR1[letter];
  126.        pseudo_tty[strlen(pseudo_tty) - 1] = PTYCHAR2[0];
  127.  
  128.        if (stat(pseudo_tty, &st_buf) == 0)
  129.           while (PTYCHAR2[devindex]) {
  130.                 pseudo_tty[strlen(pseudo_tty) - 1] = PTYCHAR2[devindex];
  131.                 if ((master = open(pseudo_tty, O_RDWR)) >= 0)
  132.                    return(master);
  133.  
  134.                 devindex++;
  135.                }
  136.        devindex = 0;
  137.        (void) letter++;
  138.       }
  139. #endif /* umips && SYSV */
  140. #endif /* att */
  141. /*
  142. ** We were unable to allocate a pty master!  Report the error and terminate.
  143. */
  144.  XtError("xmail cannot open master side of pty");
  145. } /* end - openMaster */
  146.  
  147.  
  148. /*
  149. ** @(#)openSlave() - open slave side of pipe
  150. */
  151. int
  152. openSlave(master)
  153. int    master;
  154. {
  155.  int        slave;
  156.  
  157.  
  158. #ifdef att
  159.  char    *slaveName;
  160.  int    grantpt(), unlockpt();
  161.  char    *ptsname();
  162.  
  163.  if (grantpt(master) >= 0 &&
  164.     unlockpt(master) >= 0 &&
  165.     (slavename = ptsname(master)) != NULL &&
  166.     (slave = open(slavename, O_RDWR)) >= 0 &&
  167.     ioctl(slave, I_PUSH, "ptem") >= 0 &&
  168.     ioctl(slave, I_PUSH, "ldterm") >= 0)
  169.     return(slave);
  170. #else /* !att */
  171. #if defined(umips) && defined (SYSV)
  172.  fstat(master, &st_buf);
  173.  (void) sprintf(pseudo_tty, "/dev/ttyq%d", minor(st_buf.st_rdev));
  174.  if ((slave = open(pseudo_tty, O_RDWR)) >= 0)
  175.     return(slave);                /* got one! */
  176. #else /* not (umips && SYSV) */
  177.  pseudo_tty[strlen(pseudo_tty) - 5] = 't';
  178.  if ((slave = open(pseudo_tty, O_RDWR)) >= 0)
  179.     return(slave);
  180. #endif
  181. #endif
  182.  XtError("xmail cannot open slave side of pty");
  183. } /* openSlave */
  184.  
  185.  
  186. /*
  187. ** @(#)callMail() - fork child to execute mail and attach to xmail input
  188. */
  189. /* ARGSUSED */
  190. void
  191. callMail(argc, argv)
  192. int argc;
  193. char *argv[];
  194. {
  195. #ifdef    SYSV
  196.  struct termio    tio;
  197. #else    /* if not SYSV */
  198.  struct sgttyb    Sgtty;
  199. #endif
  200.  int        slave;            /* file descriptor to slave pty */
  201.  char        *Mailpgm;        /* name of executable Mailpgm */
  202.  
  203.  
  204.  if (! (Mailpgm = (char *)getenv("XMAILER")))    /* first looks up env var */
  205.     Mailpgm = "/usr/ucb/Mail";
  206.   
  207.  mail_fd = openMaster();
  208.  slave = openSlave(mail_fd);
  209.  
  210. /*
  211. ** Set minimal requirements for slave connection (no echo, no NL->CR, keep TABS)
  212. */
  213. #ifdef SYSV
  214.  if (ioctl (tty, TCGETA, &tio) == -1)
  215.     XtError("xmail cannot obtain terminal settings");
  216.  
  217.  tio.c_oflag &= ~(OCRNL|ONLRET|TABDLY);
  218.  
  219.  if (ioctl (tty, TCSETA, &tio) == -1)
  220.     XtError("xmail cannot establish terminal settings");
  221. #else    /* if not SYSV */
  222.  if (ioctl(slave, TIOCGETP, (char *)&Sgtty) == -1)
  223.     XtError("xmail cannot obtain terminal settings");
  224.  
  225.  Sgtty.sg_flags &= ~(ECHO|CRMOD|XTABS);
  226.  
  227.  if (ioctl (slave, TIOCSETP, (char *)&Sgtty) == -1)
  228.     XtError("xmail cannot establish terminal settings");
  229. #endif
  230.  
  231.  mailpid = fork();
  232.  if (mailpid == -1) {
  233.     XtError("callMail could not fork the child process");
  234.    } else if (mailpid) { 
  235.              /* 
  236.               * Parent : close the slave side of pty
  237.               *          set the mail file descriptor to append mode
  238.               *          register mail input with X
  239.               */
  240.              close(slave);
  241.              fcntl(mail_fd, F_SETFL, FAPPEND);
  242.              mailInputId = XtAddInput(mail_fd, XtInputReadMask, readMail, NULL);
  243.             } else { 
  244.              /* 
  245.               * Child : close X connection and mail_fd side of pty
  246.               *         redirect stdin, stdout, stderr of mail to pty
  247.               *         unbuffer output data from mail
  248.               *         exec mail with arguments
  249.               *
  250.               *         Use a select() call to delay starting the mail process
  251.               *         until our parent can close its slave side of the pipe.
  252.               *         Eliminates the parent hanging (for approximately 15
  253.               *         seconds) on the close because the child terminated for
  254.               *         lack of mail before the parent could issue its close.
  255.               */
  256.              int        readfds, width;
  257.              struct timeval    timeout;
  258.  
  259.              close(ConnectionNumber(XtDisplay(toplevel)));
  260.  
  261.              timeout.tv_sec = 0; timeout.tv_usec = 250000; /* 0.25 seconds */
  262.              readfds = 1 << slave; width = slave + 1;
  263.  
  264.              select(width, &readfds, (int *) NULL, (int *) NULL, &timeout);
  265.  
  266.              close(mail_fd);
  267.              dup2(slave, 0);
  268.              dup2(slave, 1);
  269.              dup2(slave, 2);
  270.              if (slave > 2)
  271.                  close(slave);
  272.              fcntl(1, F_SETFL, FAPPEND);
  273.              setbuf(stdout, NULL);
  274.              argv[0] = Mailpgm;
  275.              execvp(Mailpgm, argv);
  276.              /*
  277.               * If we fail to make contact, we must re-establish access to
  278.               * the terminal screen that started us for our error message,
  279.               * because we don't want to send it up the xmail pipe.
  280.               * Also terminate our parent.
  281.               */
  282.              if ((slave = open("/dev/tty", O_RDWR)) != -1) {
  283.                 dup2(slave, 1);
  284.                 dup2(slave, 2);
  285.                 perror(Mailpgm);
  286.                }
  287.              kill(getppid(), SIGKILL);             /* kill our parent */
  288.              exit(1);
  289.             }
  290. } /* callMail */
  291.