home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / e20313sr.zip / emacs / 20.3.1 / src / hftctl.c < prev    next >
C/C++ Source or Header  |  1999-07-31  |  12KB  |  342 lines

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