view src/hftctl.c @ 1687:2bee660c3046

* configure: Don't make the top-level Makefile read-only - people may want to edit the values of the path variables. Make path specification conform to GNU coding standards. * configure (long_usage): Remove all traces of old arguments from usage messages, and document the options we do accept in more detail: -with-x... and --srcdir. (options, boolean_opts): Deleted; we don't have enough options to make this worthwhile. (prefix, bindir, lisppath, datadir, libdir, lockdir): Deleted, along with the code which supported them; these should be set as arguments to the top-level make. (config_h_opts): Since this no longer doubles as a list of option names, make them upper case; this simplifies the code which uses them to build the sed command to edit src/config.h. Change the code which sets them. (cc, g, O): Don't allow the user to set these using options; they should be specified using `CC=' and `CFLAGS=' arguments to the top-level make. Just choose reasonable default values for them, and edit them into Makefile.in's default CC and CONFIG_CFLAGS values. (gnu_malloc, rel_alloc): Don't allow the user to set these using options; use them whenever the configuration files say they're possible. Simplify the argument processing loop. Don't accept abbreviations for option names; these might conflict with other configuration options in the future. Add some support for the `--srcdir' option. Check for the sources in . and .. if `--srcdir' is omitted. If the directories we will compile in don't exist yet, create them under the current directory. Note that the rest of the build process doesn't really support this. Edit only the top Makefile. That should edit the others. Edit into the makefile: `version', from lisp/version.el, `configname' and `srcdir' from the configuration arguments, `CC' and `CONFIG_CFLAGS' as guessed from the presence or absence of GCC in the user's path, and LOADLIBES as gleaned from the system description files. Simplify the report generated; it doesn't need to include any description of paths now. Make `config.status' exec configure instead of just calling it, so there's no harm in overwriting `config.status'. * Makefile.in (version, configname): New variables, used to choose the default values for datadir and libdir. Path variables rearranged into two clearer groups: - In the first group are the variables specified by the GNU coding standards (prefix, bindir, datadir, statedir, libdir, mandir, manext, infodir, and srcdir). - In the second are the variables actually used for Emacs's paths (lispdir, locallisppath, lisppath, buildlisppath, etcdir, lockdir, archlibdir), which depend on the first category. datadir and libdir default to directories under ${prefix}/lib/emacs instead of ${prefix}/emacs, by popular demand. etcdir and lispdir default to subdirectories of datadir. archlibdir defaults to libdir. The new installation tree is a bit deeper than it used to be, so use the new make-path program in lib-src to build them all. Always build a new src/paths.h.tmp and then move-if-change it to src/paths.h, to avoid unnecessary rebuilds while responding to the right changes. Remove all mention of arch-lib. Run utility commands from lib-src, and let the executables be copied into archlibdir when Emacs is installed. Add targets for src/Makefile, lib-src/Makefile, and oldXMenu/Makefile, editing the values of the path variables into them. Let lib-src do its own installation. (datadir): Default to putting data files under ${prefix}/lib/emacs/${version}, not /usr/local/emacs. (emacsdir): Variable deleted; it would only be confusing to use. (lispdir, etcdir): Default to ${datadir}/lisp. (mkdir): Use make-path for this. (lockdir): Do this in mkdir. (Makefile): New target. * configure (usage_message): Rename to long_usage.
author Jim Blandy <jimb@redhat.com>
date Sat, 12 Dec 1992 15:42:53 +0000
parents 68111c4a3885
children b6c62e4abf59
line wrap: on
line source

/* IBM has disclaimed copyright on this module.  */

/***************************************************************/
/*                                                             */
/* Function: hftctl                                            */
/*                                                             */
/* Syntax:                                                     */
/*    #include <sys/ioctl.h>                                   */
/*    #include <sys/hft.h>                                     */
/*                                                             */
/*    int hftctl(fildes, request, arg )                        */
/*    int fildes, request;                                     */
/*    char *arg;                                               */
/*                                                             */
/* Description:                                                */
/*                                                             */
/*    Does the following:                                      */
/*      1. determines if fildes is pty                         */
/*         does normal ioctl it is not                         */
/*      2. places fildes into raw mode                         */
/*      3. converts ioctl arguments to datastream              */
/*      4. waits for 2 secs for acknowledgement before         */
/*         timimg out.                                         */
/*      5. places response in callers buffer ( just like       */
/*         ioctl.                                              */
/*      6. returns fildes to its original mode                 */
/*                                                             */
/*    User of this program should review steps 1,4, and 3.     */
/*    hftctl makes no check on the request type. It must be    */
/*    a HFT ioctl that is supported remotely.                  */
/*    This program will use the SIGALRM and alarm(2).  Any     */
/*    Previous alarms are lost.                                */
/*                                                             */
/*    Users of this program are free to modify it any way      */
/*    they want.                                               */
/*                                                             */
/* Return Value:                                               */
/*                                                             */
/*    If ioctl fails, a value of -1 is returned and errno      */
/*    is set to indicate the error.                            */
/*                                                             */
/***************************************************************/


#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/devinfo.h>
#include <termios.h>
#include <termio.h>
#include <sys/hft.h>
#include <sys/uio.h>
#include <sys/tty.h>
/* #include <sys/pty.h> */
#define REMOTE 0x01

#undef ioctl
static char     SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90";

/*************** LOCAL DEFINES **********************************/

typedef int    (*FUNC)();     /* pointer to a function        */

#define QDEV   ((HFQPDEVCH<<8)|HFQPDEVCL)
#define QLOC   ((HFQLOCCH<<8)|HFQLOCCL)
#define QPS    ((HFQPRESCH<<8)|HFQPRESCL)

#ifndef TCGETS 
#define TCGETS TCGETA
#endif
#ifndef TCSETS
#define TCSETS TCSETA
#endif

/*************** EXTERNAL / GLOBAL DATA AREA ********************/

static int              hfqry();
static int              hfskbd();
       char            *malloc();

extern int              errno;
static jmp_buf          hftenv;
static int              is_ack_vtd;
static FUNC             sav_alrm;
static struct hfctlreq  req =
			{ 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL};
static struct hfctlack  ACK =
			{ 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL};

       /* FUNC             signal(); */

/*************** LOCAL MACROS ***********************************/

#define HFTYPE(p)   ((p->hf_typehi<<8)|(p->hf_typelo))

#define BYTE4(p)    ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3])

					/* read a buffer        */
#define RD_BUF(f,p,l) \
        while ((l)) \
          if ((j = read((f),(p),(l))) < 0) \
             if (errno != EINTR) return (-1); \
             else continue; \
          else { (l) -= j; (p) += j; }

/*************** function prototypes ***************************/
#ifdef __STDC__
static GT_ACK (int fd, int req, char *buf);
static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen);
static hft_alrm(int sig);
#else
static GT_ACK ();
static WR_REQ ();
static hft_alrm ();
#endif

/*************** HFTCTL FUNCTION *******************************/

hftctl (fd, request, arg)
     int     fd;
     int     request;
     union {
       struct hfintro *intro;
       struct hfquery *query;
       char           *c;
     } arg;
{

  int             i;
  int             fd_flag;	/* fcntl flags          */
  register union {
    struct hfintro         *cmd; /* p.cmd - intro des.   */
    struct hfqphdevc       *ph;	/* p.ph  - physical dev.*/
    char            *c;		/* p.c   - char ptr     */
  }               p;		/* general pointer      */
  int             pty_new;	/* pty modes            */
  int             pty_old;
  int             retcode;
  struct termios   term_new;	/* terminal attributes  */
  struct termios   term_old;
  struct devinfo	devInfo; /* defined in sys/devinfo.h */


  if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1);

  if (devInfo.devtype != DD_PSEU) /* is it a pty? */
    return (ioctl(fd, request, arg)); /* no, do IOCTL */

  /******* START PTY **************/
  /**  Pty found, possible HFT    */
  /** set new file des as raw     */
  /** as you can.                 */
  /********************************/

  /* Get current state of file    */
  /* descriptor & save            */
  if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1);
  if (ioctl (fd, TCGETS, &term_old) == -1) return (-1);
  /* set terminal attr to raw     */
  /* and to delay on read         */
  pty_new = pty_old | REMOTE;
  memcpy (&term_new, &term_old, sizeof (term_new));
  term_new.c_iflag = 0;
  term_new.c_oflag = 0;
  term_new.c_lflag = 0;
  /* term_new.c_line  = 0; */
  for (i = 1; i <= 5; i++)
    term_new.c_cc[i] = 0;
  term_new.c_cc[0] = -1;
  ioctl (fd, TCSETS, &term_new);
  if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1)
    return(-1);
  /* call spacific function       */
  if (request == HFSKBD)
    retcode = hfskbd (fd, request, arg.c);
  else				/* assume HFQUERY */
    retcode = hfqry (fd, request, arg.c);

  fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original   */
  ioctl (fd, TCSETS, &term_old);


  return (retcode);             /* return error                 */
}

/*************** HFSKBD  FUNCTION ******************************/
static int
hfskbd (fd, request, arg)
        int     fd;
        int     request;
        struct hfbuf *arg;
{
  WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0);
  return (GT_ACK(fd, request, arg->hf_bufp));
}

/*************** HFQUERY FUNCTION ******************************/
static int
hfqry (fd, request, arg)
        int     fd;
        int     request;
        struct hfquery *arg;
{
  WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen);
  return (GT_ACK(fd, request, arg->hf_resp));
}


/*************** GT_ACK FUNCTION ******************************/
static int
GT_ACK (fd, req, buf)
        int     fd;
        int     req;
        char   *buf;
{
  struct hfctlack ack;
  int             i = sizeof (ack);
  int             j = 0;
  union {
    char            *c;
    struct hfctlack *ack;
  }               p;

  is_ack_vtd = 0;		/* flag no ACT VTD yet         */

  if (setjmp (hftenv))		/* set environment in case     */
    {				/* of time out                 */
      errno = ENODEV;		/* if time out, set errno      */
      return (-1);		/* flag error                  */
    }

  alarm(3);			/* time out in 3 secs          */
  sav_alrm = signal (SIGALRM, hft_alrm); /* prepare to catch time out   */

  p.ack = &ack;
  while (! is_ack_vtd)		/* do until valid ACK VTD      */
    {
      RD_BUF(fd, p.c, i);	/* read until a ACK VTD is fill*/

      if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro &  */
	  && (ack.hf_request == req)) /* is it the response we want ?*/
	{			/* yes, ACK VTD found          */
	  is_ack_vtd = 1;	/* quickly, flag it            */
	  break;		/* get the %$%#@ out of here   */
	}

      p.ack = &ack;		/* no, then skip 1st           */
      ++p.c;			/* char and start over         */
      i = sizeof (ack) - 1;	/* one less ESC to cry over    */

      while ((*p.c != 0x1b) && i) /* scan for next ESC           */
	{ ++p.c; --i; }		/* if any                      */

      (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */
      p.ack = &ack;		/* ESC to front of ack struct  */
      p.c += i;			/* skip over whats been read   */
      i = sizeof (ack) - i;	/* set whats left to be read   */
    }				/***** TRY AGAIN               */

  alarm(0);			/* ACK VTD received, reset alrm*/
  signal (SIGALRM, sav_alrm);	/* reset signal                */

  if (i = ack.hf_arg_len)	/* any data following ?        */
    {				/* yes,                        */
      RD_BUF(fd,buf,i);		/* read until it is received   */
    }

  if (errno = ack.hf_retcode)	/* set errno based on returned */
    return (-1);		/* code, if 0, then no error   */
  else
    return (0);			/* if set, then error returned */
}

/*************** HFT_ALRM FUNCTION ******************************/
static int
hft_alrm (sig)                    /* Function hft_alrm - handle  */
        int sig;		/* alarm signal               */
{
  signal (SIGALRM, sav_alrm);	/* reset to previous          */

  if (is_ack_vtd)		/* has ack vtd arrived ?      */
    return(0);			/* yes, then continue         */
  else				/* no, then return with error */
    longjmp (hftenv, -1);

}

/*********************************************************************/
/***                                                               ***/
/***  NOTE: Both the HFCTLREQ and the arg structure should be      ***/
/***        sent in one io write operation.  If terminal           ***/
/***        emulators are in NODELAY mode then multiple writes     ***/
/***        may cause bogus information to be read by the emulator ***/
/***        depending on the timing.                               ***/
/***                                                               ***/
/*********************************************************************/

static int
WR_REQ (fd, request, cmdlen, cmd, resplen)
	int             fd;
	int             request;
	int             cmdlen;
	char           *cmd;
	int             resplen;
{
  struct {
    char            *c;
    struct hfctlreq *req;
  }              p;
  int            size;

  req.hf_request = request;
  req.hf_arg_len = cmdlen;
  req.hf_rsp_len = resplen;

  if (cmdlen)			/* if arg structure to pass    */
    {
      size = sizeof (struct hfctlreq) + cmdlen;
      if ((p.c = malloc(size)) == NULL) /* malloc one area            */
	return (-1);

      memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct         */
      memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct     */
    }
  else
    {
      p.req = &req;		/* otherwise use only CTL REQ  */
      size = sizeof (req);
    }

  /* write request to terminal   */
  if (write(fd,p.c,size) == -1) return (-1);
  if (p.req != &req)		/* free if allocated           */
    free (p.c);
  return (0);

}