home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / mincom15.zip / ipc.c < prev    next >
C/C++ Source or Header  |  1993-10-09  |  6KB  |  314 lines

  1. /*
  2.  * This file is part of the Minicom Communications Program,
  3.  * written by Miquel van Smoorenburg 1991/1992/1993.
  4.  *
  5.  * ipc.c - talk to the keyserv process.
  6.  * 
  7.  * Entry point:
  8.  *
  9.  * keyserv(command, arg)
  10.  *    command can be KINSTALL, KUNINSTALL, or a command for keyserv.
  11.  *    arg is a 1 byte argument.
  12.  *
  13.  */
  14. #include <sys/types.h>
  15. #if defined (_POSIX_SOURCE) || defined(_BSD43)
  16. #  include <unistd.h>
  17. #  include <stdlib.h>
  18. #endif
  19. #undef NULL
  20. #include <signal.h>
  21. #include <fcntl.h>
  22. #include <sys/stat.h>
  23. #include <sys/time.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <setjmp.h>
  27. #include <errno.h>
  28.  
  29. #include "window.h"
  30. #include "minicom.h"
  31. #include "keyboard.h"
  32. #include "vt100.h"
  33. #include "configsym.h"
  34.  
  35. #ifndef _SELECT
  36.  
  37. static int tokeyserv, fromkeyserv;    /* File desciptors of ipc pipes */
  38. static int keypid;            /* pid of keyserv          */
  39. static jmp_buf ackjmp;            /* To jump to after ACK signal  */
  40. static int waiting = 0;            /* Do we expect an ACK signal?    */
  41. static int keypress = -1;        /* A key was pressed.        */
  42.  
  43. /*
  44.  * We got the "ksigio" signal. This means that CTRL-A was pressed in
  45.  * the main terminal loop, or any key if requested by keyserv(KSIGIO).
  46.  */
  47. /*ARGSUSED*/
  48. static void ksigio(dummy)
  49. int dummy;
  50. {
  51.   unsigned char c[8];
  52.   int n;
  53.  
  54.   signal(HELLO, ksigio);
  55.   while ((n = read(fromkeyserv, c, 8)) < 0 && errno == EINTR)
  56.       errno = 0;
  57.   keypress = n ? c[n - 1] : -1;
  58. }
  59.  
  60. /*
  61.  * After we have sent a signal to "keyserv", we wait for it to signal
  62.  * us back. Otherwise "keyserv" would be swamped with signals and
  63.  * die ungracefully....
  64.  */
  65. static void sigack(dummy)
  66. int dummy;
  67. {
  68.   signal(ACK, sigack);
  69.   if (waiting) longjmp(ackjmp, 1);
  70.   printf("sigack: unexpected ACK signal &^%%$!! (pardon my French)\r\n");
  71. }
  72.  
  73. /*
  74.  * Install the keyserv process. This involves setting up the communications
  75.  * channels (pipes) and forking the child process.
  76.  */
  77. static void kinstall()
  78. {
  79. #ifdef _COH3
  80.   char mpid[8];
  81. #endif
  82.   int pipe1[2], pipe2[2];
  83.   char buf[2];
  84.   char prog[128];
  85.  
  86.   if (pipe(pipe1) < 0 || pipe(pipe2) < 0)
  87.       leave("minicom: out of file descriptors\n");
  88.   tokeyserv = pipe1[1];
  89.   fromkeyserv = pipe2[0];
  90.  
  91.   /* Set signal handler */
  92.   signal(HELLO, ksigio);
  93.   signal(ACK, sigack);
  94.  
  95. #ifdef _COH3
  96.   sprintf(mpid, "%d", getpid());
  97. #endif
  98.  
  99.   switch(keypid = fork()) {
  100.       case -1:
  101.           leave("minicom: could not fork.\n");
  102.           break;
  103.       case 0: /* Child */
  104.  
  105.           /* Set up fd #1 : stdout */
  106.           dup2(portfd, 1);
  107.           close(portfd);
  108.  
  109.         /* Set up fd #3 : minicom ---> keyserv */
  110.         dup2(pipe1[0], 3);
  111.  
  112.         /* Set up fd #4 : minicom <--- keyserv */
  113.         dup2(pipe2[1], 4);
  114.  
  115.         /* Close unused file descriptors */
  116.         close(pipe1[1]);
  117.         close(pipe2[0]);
  118.         sprintf(prog, "%s/keyserv", LIBDIR);
  119. #ifdef _COH3
  120.           execl(prog, "keyserv", mpid, (char *)NULL);
  121. #else
  122.           execl(prog, "keyserv", (char *)NULL);
  123. #endif
  124.           exit(0);
  125.       default: /* Parent */
  126.         if (setjmp(ackjmp) == 0) {
  127. #ifdef DEBUG
  128.             printf("keyserv has PID %d\r\n", keypid);
  129. #endif
  130.               sleep(2); /* Wait for keyserv to initialize */
  131.             waiting = 1;
  132.               buf[0] = KSTOP;
  133.               write(tokeyserv, buf, 2);
  134.               if (kill(keypid, HELLO) < 0) {
  135.                   leave("minicom: could not exec keyserv\n");
  136.               }
  137.             /* Do nothing 'till ACK signal */
  138.             while(1) pause();
  139.         }
  140.         waiting = 0;
  141.         /* close unused pipes */
  142.         close(pipe1[0]);
  143.         close(pipe2[1]);
  144.         break;
  145.   }
  146. }
  147.  
  148.  
  149. /*
  150.  * Install / tell /de-install "keyserv" program.
  151.  */
  152. int keyboard(cmd, arg)
  153. int cmd, arg;
  154. {
  155.   char ch[2];
  156.   int pid, stt;
  157.   static int lastcmd = -1;
  158.   int c;
  159.  
  160. #ifdef _MINIX
  161.   /* Avoid race conditions. Unfortunately, this _creates_ a race
  162.    * condition on SYSV (linux!) ....
  163.    */
  164.   if (lastcmd == KSTOP) m_flush(0);
  165. #endif
  166.   lastcmd = cmd;
  167.  
  168.   if (cmd == KINSTALL) {
  169.       kinstall();
  170.       return(0);
  171.   }
  172.  
  173.   if (cmd == KUNINSTALL) {
  174.     close(fromkeyserv);
  175.     close(tokeyserv);
  176.     (void) kill(keypid, SIGKILL);
  177.     pid = m_wait(&stt);
  178.     return(0);
  179.   }
  180.  
  181.   if (cmd == KGETKEY) {
  182.     /* Try to read a key from the keyserv process pipe. */
  183.     c = keypress;
  184.     keypress = -1;
  185.     return(c);
  186.   }
  187.  
  188.   if (cmd == KSETESC) {
  189.     /* Store this because the code expects it. */
  190.     escape = arg;
  191.   }
  192.  
  193.   if (setjmp(ackjmp) == 0) {
  194.     waiting = 1;
  195.     ch[0] = cmd;
  196.     ch[1] = arg;
  197.     write(tokeyserv, ch, 2);
  198.     (void) kill(keypid, HELLO);
  199.     /* Do nothing 'till ACK signal */
  200.     while(1) pause();
  201.   }
  202.   waiting = 0;
  203.   return(0);
  204. }
  205.  
  206. /* Dummy sigalarm handler. */
  207. static void dummy()
  208. {
  209. }
  210.  
  211. /* Wait for I/O to happen. We might get interrupted by keyserv. */
  212. int check_io(fd1, fd2, tmout, buf, buflen)
  213. int fd1;
  214. int fd2;
  215. int tmout;
  216. char *buf;
  217. int buflen;
  218. {
  219.   int n;
  220.   int x = 0;
  221.  
  222.   /* OK, set the alarm if needed. */
  223.   signal(SIGALRM, dummy);
  224.   if (tmout) alarm((tmout + 500) / 1000);
  225.  
  226.   /* We do a read on the first fd, the second one is always stdin. */
  227.   if (keypress < 0) {
  228.     if (fd1 >= 0) {
  229.         /* Read gets interrupted by keypress or alarm. */
  230.         n = read(fd1, buf, 127);
  231.         buf[n > 0 ? n : 0] = 0;
  232.         if (buflen) *buflen = n;
  233.         if (n > 0) x |= 1;
  234.     } else
  235.         /* Wait for keypress or alarm. */
  236.         pause();
  237.   }
  238.   alarm(0);
  239.  
  240.   if (keypress >= 0) x |= 2;
  241.  
  242.   return(x);
  243. }
  244.  
  245. #else
  246.  
  247. /* Check if there is IO pending. */
  248. int check_io(fd1, fd2, tmout, buf, buflen)
  249. int fd1;
  250. int fd2;
  251. int tmout;
  252. char *buf;
  253. int *buflen;
  254. {
  255.   int n = 0, i;
  256.   struct timeval tv;
  257.   fd_set fds;
  258.  
  259.   tv.tv_sec = tmout / 1000;
  260.   tv.tv_usec = (tmout % 1000) * 1000L;
  261.  
  262.   i = fd1;
  263.   if (fd2 > fd1) i = fd2;
  264.  
  265.   FD_ZERO(&fds);
  266.   if (fd1 >= 0) FD_SET(fd1, &fds);
  267.   if (fd2 >= 0) FD_SET(fd2, &fds);
  268.  
  269.   if (select(i+1, &fds, NULL, NULL, &tv))
  270.     n = 1 * (FD_ISSET(fd1, &fds) > 0) + 2 * (FD_ISSET(fd2, &fds) > 0);
  271.  
  272.   /* If there is data put it in the buffer. */
  273.   if (buf) {
  274.     i = 0;
  275.     if ((n & 1) == 1) i = read(fd1, buf, 127);
  276.     buf[i > 0 ? i : 0] = 0;
  277.     if (buflen) *buflen = i;
  278.   }
  279.  
  280.   return(n);
  281. }
  282.  
  283. int keyboard(cmd, arg)
  284. int cmd, arg;
  285. {
  286.   switch(cmd) {    
  287.     case KSTART:
  288.     case KSTOP:
  289.         break;
  290.     case KSIGIO:
  291.         break;
  292.     case KGETKEY:
  293.         return(getch());
  294.     case KSETESC:
  295.         escape = arg;
  296.         break;
  297.     case KSETBS:
  298.         vt_set(-1, -1, NULL, -1, arg, -1, -1);
  299.         break;
  300.     case KCURST:
  301.         vt_set(-1, -1, NULL, -1, -1, -1, NORMAL);
  302.         break;
  303.     case KCURAPP:
  304.         vt_set(-1, -1, NULL, -1, -1, -1, APPL);
  305.         break;
  306.     default:
  307.         /* The rest is only meaningful if a keyserv runs. */
  308.         break;
  309.   }
  310.   return(0);
  311. }
  312.  
  313. #endif
  314.