ipc.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:6k
源码类别:

Modem编程

开发平台:

Unix_Linux

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