home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / hftctl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-25  |  11.4 KB  |  343 lines

  1. /* IBM has disclaimed copyright on this module.  */
  2.  
  3. /* Synched up with: FSF 19.28. */
  4.  
  5. /***************************************************************/
  6. /*                                                             */
  7. /* Function: hftctl                                            */
  8. /*                                                             */
  9. /* Syntax:                                                     */
  10. /*    #include <sys/ioctl.h>                                   */
  11. /*    #include <sys/hft.h>                                     */
  12. /*                                                             */
  13. /*    int hftctl(fildes, request, arg )                        */
  14. /*    int fildes, request;                                     */
  15. /*    char *arg;                                               */
  16. /*                                                             */
  17. /* Description:                                                */
  18. /*                                                             */
  19. /*    Does the following:                                      */
  20. /*      1. determines if fildes is pty                         */
  21. /*         does normal ioctl it is not                         */
  22. /*      2. places fildes into raw mode                         */
  23. /*      3. converts ioctl arguments to datastream              */
  24. /*      4. waits for 2 secs for acknowledgement before         */
  25. /*         timing out.                                         */
  26. /*      5. places response in callers buffer ( just like       */
  27. /*         ioctl.                                              */
  28. /*      6. returns fildes to its original mode                 */
  29. /*                                                             */
  30. /*    User of this program should review steps 1,4, and 3.     */
  31. /*    hftctl makes no check on the request type. It must be    */
  32. /*    a HFT ioctl that is supported remotely.                  */
  33. /*    This program will use the SIGALRM and alarm(2).  Any     */
  34. /*    Previous alarms are lost.                                */
  35. /*                                                             */
  36. /*    Users of this program are free to modify it any way      */
  37. /*    they want.                                               */
  38. /*                                                             */
  39. /* Return Value:                                               */
  40. /*                                                             */
  41. /*    If ioctl fails, a value of -1 is returned and errno      */
  42. /*    is set to indicate the error.                            */
  43. /*                                                             */
  44. /***************************************************************/
  45.  
  46. #include <config.h>
  47. #include "lisp.h" /* encapsulated open, close, read, write */
  48.  
  49. #include <sys/signal.h>
  50. #include <errno.h>
  51.  
  52. #include <stdio.h>
  53. #include <fcntl.h>
  54. #include <setjmp.h>
  55. #include <sys/ioctl.h>
  56. #include <sys/devinfo.h>
  57. #include <termios.h>
  58. #include <termio.h>
  59. #include <sys/hft.h>
  60. #include <sys/uio.h>
  61. #include <sys/tty.h>
  62. /* #include <sys/pty.h> */
  63.  
  64. #define REMOTE 0x01
  65.  
  66. #undef ioctl
  67. static char     SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90";
  68.  
  69. /*************** LOCAL DEFINES **********************************/
  70.  
  71. #define QDEV   ((HFQPDEVCH<<8)|HFQPDEVCL)
  72. #define QLOC   ((HFQLOCCH<<8)|HFQLOCCL)
  73. #define QPS    ((HFQPRESCH<<8)|HFQPRESCL)
  74.  
  75. #ifndef TCGETS 
  76. #define TCGETS TCGETA
  77. #endif
  78. #ifndef TCSETS
  79. #define TCSETS TCSETA
  80. #endif
  81.  
  82. /*************** EXTERNAL / GLOBAL DATA AREA ********************/
  83.  
  84. static int              hfqry();
  85. static int              hfskbd();
  86.  
  87. extern int              errno;
  88. static jmp_buf          hftenv;
  89. static int              is_ack_vtd;
  90. static SIGTYPE             (*sav_alrm) ();
  91. static struct hfctlreq  req =
  92.             { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL};
  93. static struct hfctlack  ACK =
  94.             { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL};
  95.  
  96.        /* FUNC             signal(); */
  97.  
  98. /*************** LOCAL MACROS ***********************************/
  99.  
  100. #define HFTYPE(p)   ((p->hf_typehi<<8)|(p->hf_typelo))
  101.  
  102. #define BYTE4(p)    ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])
  103.  
  104.                     /* read a buffer        */
  105. #define RD_BUF(f,p,l) \
  106.         while ((l)) \
  107.           if ((j = read((f),(p),(l))) < 0) \
  108.              if (errno != EINTR) return (-1); \
  109.              else continue; \
  110.           else { (l) -= j; (p) += j; }
  111.  
  112. /*************** function prototypes ***************************/
  113. #ifdef __STDC__
  114. static GT_ACK (int fd, int req, char *buf);
  115. static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen);
  116. static void hft_alrm(int sig);
  117. #else
  118. static GT_ACK ();
  119. static WR_REQ ();
  120. static void hft_alrm ();
  121. #endif
  122.  
  123. /*************** HFTCTL FUNCTION *******************************/
  124.  
  125. hftctl (fd, request, arg)
  126.      int     fd;
  127.      int     request;
  128.      union {
  129.        struct hfintro *intro;
  130.        struct hfquery *query;
  131.        char           *c;
  132.      } arg;
  133. {
  134.  
  135.   int             i;
  136.   int             fd_flag;    /* fcntl flags          */
  137.   union {
  138.     struct hfintro         *cmd; /* p.cmd - intro des.   */
  139.     struct hfqphdevc       *ph;    /* p.ph  - physical dev.*/
  140.     char            *c;        /* p.c   - char ptr     */
  141.   }               p;        /* general pointer      */
  142.   int             pty_new;    /* pty modes            */
  143.   int             pty_old;
  144.   int             retcode;
  145.   struct termios   term_new;    /* terminal attributes  */
  146.   struct termios   term_old;
  147.   struct devinfo    devInfo; /* defined in sys/devinfo.h */
  148.  
  149.  
  150.   if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1);
  151.  
  152.   if (devInfo.devtype != DD_PSEU) /* is it a pty? */
  153.     return (ioctl(fd, request, arg)); /* no, do IOCTL */
  154.  
  155.   /******* START PTY **************/
  156.   /**  Pty found, possible HFT    */
  157.   /** set new file des as raw     */
  158.   /** as you can.                 */
  159.   /********************************/
  160.  
  161.   /* Get current state of file    */
  162.   /* descriptor & save            */
  163.   if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1);
  164.   if (ioctl (fd, TCGETS, &term_old) == -1) return (-1);
  165.   /* set terminal attr to raw     */
  166.   /* and to delay on read         */
  167.   pty_new = pty_old | REMOTE;
  168.   memcpy (&term_new, &term_old, sizeof (term_new));
  169.   term_new.c_iflag = 0;
  170.   term_new.c_oflag = 0;
  171.   term_new.c_lflag = 0;
  172.   /* term_new.c_line  = 0; */
  173.   for (i = 1; i <= 5; i++)
  174.     term_new.c_cc[i] = 0;
  175.   term_new.c_cc[0] = -1;
  176.   ioctl (fd, TCSETS, &term_new);
  177.   if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1)
  178.     return(-1);
  179.   /* call spacific function       */
  180.   if (request == HFSKBD)
  181.     retcode = hfskbd (fd, request, arg.c);
  182.   else                /* assume HFQUERY */
  183.     retcode = hfqry (fd, request, arg.c);
  184.  
  185.   fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original   */
  186.   ioctl (fd, TCSETS, &term_old);
  187.  
  188.  
  189.   return (retcode);             /* return error                 */
  190. }
  191.  
  192. /*************** HFSKBD  FUNCTION ******************************/
  193. static int
  194. hfskbd (fd, request, arg)
  195.         int     fd;
  196.         int     request;
  197.         struct hfbuf *arg;
  198. {
  199.   WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0);
  200.   return (GT_ACK(fd, request, arg->hf_bufp));
  201. }
  202.  
  203. /*************** HFQUERY FUNCTION ******************************/
  204. static int
  205. hfqry (fd, request, arg)
  206.         int     fd;
  207.         int     request;
  208.         struct hfquery *arg;
  209. {
  210.   WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen);
  211.   return (GT_ACK(fd, request, arg->hf_resp));
  212. }
  213.  
  214.  
  215. /*************** GT_ACK FUNCTION ******************************/
  216. static int
  217. GT_ACK (fd, req, buf)
  218.         int     fd;
  219.         int     req;
  220.         char   *buf;
  221. {
  222.   struct hfctlack ack;
  223.   int             i = sizeof (ack);
  224.   int             j = 0;
  225.   union {
  226.     char            *c;
  227.     struct hfctlack *ack;
  228.   }               p;
  229.  
  230.   is_ack_vtd = 0;        /* flag no ACT VTD yet         */
  231.  
  232.   if (setjmp (hftenv))        /* set environment in case     */
  233.     {                /* of time out                 */
  234.       errno = ENODEV;        /* if time out, set errno      */
  235.       return (-1);        /* flag error                  */
  236.     }
  237.  
  238.   alarm(3);            /* time out in 3 secs          */
  239.   sav_alrm = signal (SIGALRM, hft_alrm); /* prepare to catch time out   */
  240.  
  241.   p.ack = &ack;
  242.   while (! is_ack_vtd)        /* do until valid ACK VTD      */
  243.     {
  244.       RD_BUF(fd, p.c, i);    /* read until a ACK VTD is fill*/
  245.  
  246.       if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro &  */
  247.       && (ack.hf_request == req)) /* is it the response we want ?*/
  248.     {            /* yes, ACK VTD found          */
  249.       is_ack_vtd = 1;    /* quickly, flag it            */
  250.       break;        /* get the %$%#@ out of here   */
  251.     }
  252.  
  253.       p.ack = &ack;        /* no, then skip 1st           */
  254.       ++p.c;            /* char and start over         */
  255.       i = sizeof (ack) - 1;    /* one less ESC to cry over    */
  256.  
  257.       while ((*p.c != 0x1b) && i) /* scan for next ESC           */
  258.     { ++p.c; --i; }        /* if any                      */
  259.  
  260.       (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */
  261.       p.ack = &ack;        /* ESC to front of ack struct  */
  262.       p.c += i;            /* skip over whats been read   */
  263.       i = sizeof (ack) - i;    /* set whats left to be read   */
  264.     }                /***** TRY AGAIN               */
  265.  
  266.   alarm(0);            /* ACK VTD received, reset alrm*/
  267.   signal (SIGALRM, sav_alrm);    /* reset signal                */
  268.  
  269.   if (i = ack.hf_arg_len)    /* any data following ?        */
  270.     {                /* yes,                        */
  271.       RD_BUF(fd,buf,i);        /* read until it is received   */
  272.     }
  273.  
  274.   if (errno = ack.hf_retcode)    /* set errno based on returned */
  275.     return (-1);        /* code, if 0, then no error   */
  276.   else
  277.     return (0);            /* if set, then error returned */
  278. }
  279.  
  280. /*************** HFT_ALRM FUNCTION ******************************/
  281. static void
  282. hft_alrm (sig)                    /* Function hft_alrm - handle  */
  283.         int sig;        /* alarm signal               */
  284. {
  285.   signal (SIGALRM, sav_alrm);    /* reset to previous          */
  286.  
  287.   if (is_ack_vtd)        /* has ack vtd arrived ?      */
  288.     return;            /* yes, then continue         */
  289.   else                /* no, then return with error */
  290.     longjmp (hftenv, -1);
  291.  
  292. }
  293.  
  294. /*********************************************************************/
  295. /***                                                               ***/
  296. /***  NOTE: Both the HFCTLREQ and the arg structure should be      ***/
  297. /***        sent in one io write operation.  If terminal           ***/
  298. /***        emulators are in NODELAY mode then multiple writes     ***/
  299. /***        may cause bogus information to be read by the emulator ***/
  300. /***        depending on the timing.                               ***/
  301. /***                                                               ***/
  302. /*********************************************************************/
  303.  
  304. static int
  305. WR_REQ (fd, request, cmdlen, cmd, resplen)
  306.     int             fd;
  307.     int             request;
  308.     int             cmdlen;
  309.     char           *cmd;
  310.     int             resplen;
  311. {
  312.   struct {
  313.     char            *c;
  314.     struct hfctlreq *req;
  315.   }              p;
  316.   int            size;
  317.  
  318.   req.hf_request = request;
  319.   req.hf_arg_len = cmdlen;
  320.   req.hf_rsp_len = resplen;
  321.  
  322.   if (cmdlen)            /* if arg structure to pass    */
  323.     {
  324.       size = sizeof (struct hfctlreq) + cmdlen;
  325.       if ((p.c = xmalloc(size)) == NULL) /* malloc one area            */
  326.     return (-1);
  327.  
  328.       memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct         */
  329.       memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct     */
  330.     }
  331.   else
  332.     {
  333.       p.req = &req;        /* otherwise use only CTL REQ  */
  334.       size = sizeof (req);
  335.     }
  336.  
  337.   /* write request to terminal   */
  338.   if (write(fd,p.c,size) == -1) return (-1);
  339.   if (p.req != &req)        /* free if allocated           */
  340.     xfree (p.c);
  341.   return (0);
  342. }
  343.