Ejemplo n.º 1
0
int XEClearCtrlKeys(void)
{
#ifndef vms
    signal(SIGINT,  SIG_DFL); /* CTRL-C */
    return(1L);
#else  /* vms */
    int status;

    if (dvi_characteristics & DEV$M_TRM) 
    {                 
        status = SYS$DASSGN(comm_chan);
        $CheckStatus(status);
    }
    return (SS$_NORMAL);
#endif /* vms */
}
Ejemplo n.º 2
0
/*
 * This function gets called just before we go back home to the command
 * interpreter. On VMS it puts the terminal back in a reasonable state.
 * Another no-operation on CPM.
 */
ttclose()
{
#if     AMIGA
        Close(terminal);
#endif
#if     VMS
        int     status;
        int     iosb[1];

        ttflush();
        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
                 oldmode, sizeof(oldmode), 0, 0, 0, 0);
        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
                exit(status);
        status = SYS$DASSGN(iochan);
        if (status != SS$_NORMAL)
                exit(status);
#endif
#if     CPM
#endif
#if     MSDOS && !__OS2__
        int_restore(0x23);      /* de-install control-break handler     */
#endif
#if     BSDUNIX
        stty(1, &ostate);
#if NONBLOCK
        fcntl(0,F_SETFL,oldstatus);
#endif
#endif

#if     linux || __OpenBSD__ || __APPLE__
        tcsetattr(1, TCSADRAIN, &ostate);	// return to original mode
#endif

#if NCURSES
	endwin();
#endif
}
Ejemplo n.º 3
0
static int
vms_file_stats_name (const char *dirname,
                     const char *filename,
		     long long *cdt,
		     long *siz,
		     char *rfo,
		     int *ver)
{
  char fullname[strlen (dirname) + strlen (filename) + 1];
#ifdef VMS
  struct FAB fab;
  struct NAM nam;

  unsigned long long create;
  FAT recattr;
  char ascnamebuff [256];

  ATRDEF atrlst[]
    = {
      { ATR$S_CREDATE,  ATR$C_CREDATE,  &create },
      { ATR$S_RECATTR,  ATR$C_RECATTR,  &recattr },
      { ATR$S_ASCNAME,  ATR$C_ASCNAME,  &ascnamebuff },
      { 0, 0, 0}
    };

  FIBDEF fib;
  struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};

  struct IOSB iosb;

  long status;
  unsigned short chan;

  struct vstring file;
  struct dsc$descriptor_s filedsc
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
  struct vstring device;
  struct dsc$descriptor_s devicedsc
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
  struct vstring result;
  struct dsc$descriptor_s resultdsc
    = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};

  if (strcmp (filename, "<internal>") == 0
      || strcmp (filename, "<built-in>") == 0)
    {
      if (cdt)
	*cdt = 0;

      if (siz)
	*siz = 0;

      if (rfo)
	*rfo = 0;

      if (ver)
        *ver = 0;

      return 0;
    }

  strcpy (fullname, dirname);
  strcat (fullname, filename);

  tryfile = to_vms_file_spec (fullname);

  /* Allocate and initialize a FAB and NAM structures.  */
  fab = cc$rms_fab;
  nam = cc$rms_nam;

  nam.nam$l_esa = file.string;
  nam.nam$b_ess = NAM$C_MAXRSS;
  nam.nam$l_rsa = result.string;
  nam.nam$b_rss = NAM$C_MAXRSS;
  fab.fab$l_fna = tryfile;
  fab.fab$b_fns = strlen (tryfile);
  fab.fab$l_nam = &nam;

  /* Validate filespec syntax and device existence.  */
  status = SYS$PARSE (&fab, 0, 0);
  if ((status & 1) != 1)
    return 1;

  file.string[nam.nam$b_esl] = 0;

  /* Find matching filespec.  */
  status = SYS$SEARCH (&fab, 0, 0);
  if ((status & 1) != 1)
    return 1;

  file.string[nam.nam$b_esl] = 0;
  result.string[result.length=nam.nam$b_rsl] = 0;

  /* Get the device name and assign an IO channel.  */
  strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
  devicedsc.dsc$w_length  = nam.nam$b_dev;
  chan = 0;
  status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
  if ((status & 1) != 1)
    return 1;

  /* Initialize the FIB and fill in the directory id field.  */
  memset (&fib, 0, sizeof (fib));
  fib.fib$w_did[0]  = nam.nam$w_did[0];
  fib.fib$w_did[1]  = nam.nam$w_did[1];
  fib.fib$w_did[2]  = nam.nam$w_did[2];
  fib.fib$l_acctl = 0;
  fib.fib$l_wcc = 0;
  strcpy (file.string, (strrchr (result.string, ']') + 1));
  filedsc.dsc$w_length = strlen (file.string);
  result.string[result.length = 0] = 0;

  /* Open and close the file to fill in the attributes.  */
  status
    = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
		&fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
  if ((status & 1) != 1)
    return 1;
  if ((iosb.status & 1) != 1)
    return 1;

  result.string[result.length] = 0;
  status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
		     &atrlst, 0);
  if ((status & 1) != 1)
    return 1;
  if ((iosb.status & 1) != 1)
    return 1;

  /* Deassign the channel and exit.  */
  status = SYS$DASSGN (chan);
  if ((status & 1) != 1)
    return 1;

  if (cdt) *cdt = create;
  if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) +
                  (512 * (recattr.fat$w_efblkl - 1)) +
                  recattr.fat$w_ffbyte;
  if (rfo) *rfo = recattr.fat$v_rtype;
  if (ver) *ver = strtol (strrchr (ascnamebuff, ';') + 1, 0, 10);
#else /* not VMS */

  struct stat buff;
  struct tm *ts;
  long long gmtoff, secs, nsecs;

  strcpy (fullname, dirname);
  strcat (fullname, filename);

  if ((stat (fullname, &buff)) != 0)
     return 1;

  if (cdt)
    {
      ts = localtime (& buff.st_mtime);

#ifdef HAVE_TM_GMTOFF
	gmtoff = ts->tm_gmtoff;
#else
	{
	  extern long timezone;

	  if (ts->tm_isdst == 1)
	    gmtoff = - (timezone - 3600);
	  else
	    gmtoff = - timezone;
	}
#endif

#ifdef HAVE_ST_MTIM_TV_SEC
      secs = buff.st_mtim.tv_sec;
#else
      secs = buff.st_mtime;
#endif

#ifdef HAVE_ST_MTIM_TV_NSEC
      nsecs = buff.st_mtim.tv_nsec;
#else
      nsecs = 0;
#endif

      /* VMS timestamps are stored in local time to 100 nsec accuracy, but by
	 experiment I found timestamps truncated to (at least) microseconds
	 on an NFS mounted filesystem, hence the adjustment below. DBR. */
      *cdt = ((secs + gmtoff) * VMS_GRANULARITY_FACTOR)
	+ (nsecs / 1000 * 10) + VMS_EPOCH_OFFSET;
    }

  if (siz)
    *siz = buff.st_size;

  if (rfo)
    *rfo = 2; /* Stream LF format.  */

  /* Returning a file version of 0 is never correct for debug info, version 1
     will be correct if file editing is done only on the Unix side.  If editing
     is done on the VMS side, then its TBD.  */
  if (ver)
    *ver = 1;
#endif /* VMS */

  return 0;
}
Ejemplo n.º 4
0
int
__gnat_expect_poll (int *fd, int num_fd, int timeout, int *is_set)
{
  int i, num, ready = 0;
  unsigned int status;
  int mbxchans [num_fd];
  struct dsc$descriptor_s mbxname;
  struct io_status_block {
    short int condition;
    short int count;
    int dev;
  } iosb;
  char buf [256];

  for (i = 0; i < num_fd; i++)
    is_set[i] = 0;

  for (i = 0; i < num_fd; i++)
    {

      /* Get name of the mailbox used in the pipe */
      getname (fd [i], buf);

      /* Assign a channel to the mailbox */
      if (strlen (buf) > 0)
	{
	  mbxname.dsc$w_length = strlen (buf);
	  mbxname.dsc$b_dtype = DSC$K_DTYPE_T;
	  mbxname.dsc$b_class = DSC$K_CLASS_S;
	  mbxname.dsc$a_pointer = buf;

	  status = SYS$ASSIGN (&mbxname, &mbxchans[i], 0, 0, 0);

	  if ((status & 1) != 1)
	    {
	      ready = -1;
	      return ready;
	    }
	}
    }

  num = timeout / 100;

  while (1)
    {
      for (i = 0; i < num_fd; i++)
	{
	  if (mbxchans[i] > 0)
	    {

	      /* Peek in the mailbox to see if there's data */
	      status = SYS$QIOW
		(0, mbxchans[i], IO$_SENSEMODE|IO$M_READERCHECK,
		 &iosb, 0, 0, 0, 0, 0, 0, 0, 0);

	      if ((status & 1) != 1)
		{
		  ready = -1;
		  goto deassign;
		}

	      if (iosb.count > 0)
		{
		  is_set[i] = 1;
		  ready = 1;
		  goto deassign;
		}
	    }
	}

      if (timeout > 0 && num == 0)
	{
	  ready = 0;
	  goto deassign;
	}

      usleep (100000);
      num--;
    }

 deassign:

  /* Deassign channels assigned above */
  for (i = 0; i < num_fd; i++)
    {
      if (mbxchans[i] > 0)
	status = SYS$DASSGN (mbxchans[i]);
    }

  return ready;
}
Ejemplo n.º 5
0
int
vms_file_stats_name (const char *filename,
		     long long *cdt,
		     long *siz,
		     char *rfo,
		     int *ver)
{
#ifdef VMS
  struct FAB fab;
  struct NAM nam;

  unsigned long long create;
  FAT recattr;
  char ascnamebuff [256];

  ATRDEF atrlst[]
    = {
      { ATR$S_CREDATE,  ATR$C_CREDATE,  &create },
      { ATR$S_RECATTR,  ATR$C_RECATTR,  &recattr },
      { ATR$S_ASCNAME,  ATR$C_ASCNAME,  &ascnamebuff },
      { 0, 0, 0}
    };

  FIBDEF fib;
  struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};

  struct IOSB iosb;

  long status;
  unsigned short chan;

  struct vstring file;
  struct dsc$descriptor_s filedsc
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
  struct vstring device;
  struct dsc$descriptor_s devicedsc
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
  struct vstring result;
  struct dsc$descriptor_s resultdsc
    = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};

  if (strcmp (filename, "<internal>") == 0
      || strcmp (filename, "<built-in>") == 0)
    {
      if (cdt)
	*cdt = 0;

      if (siz)
	*siz = 0;

      if (rfo)
	*rfo = 0;

      if (ver)
        *ver = 0;

      return 0;
    }

  tryfile = to_vms_file_spec ((char *) filename);

  /* Allocate and initialize a FAB and NAM structures.  */
  fab = cc$rms_fab;
  nam = cc$rms_nam;

  nam.nam$l_esa = file.string;
  nam.nam$b_ess = NAM$C_MAXRSS;
  nam.nam$l_rsa = result.string;
  nam.nam$b_rss = NAM$C_MAXRSS;
  fab.fab$l_fna = tryfile;
  fab.fab$b_fns = strlen (tryfile);
  fab.fab$l_nam = &nam;

  /* Validate filespec syntax and device existence.  */
  status = SYS$PARSE (&fab, 0, 0);
  if ((status & 1) != 1)
    return 1;

  file.string[nam.nam$b_esl] = 0;

  /* Find matching filespec.  */
  status = SYS$SEARCH (&fab, 0, 0);
  if ((status & 1) != 1)
    return 1;

  file.string[nam.nam$b_esl] = 0;
  result.string[result.length=nam.nam$b_rsl] = 0;

  /* Get the device name and assign an IO channel.  */
  strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
  devicedsc.dsc$w_length  = nam.nam$b_dev;
  chan = 0;
  status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
  if ((status & 1) != 1)
    return 1;

  /* Initialize the FIB and fill in the directory id field.  */
  memset (&fib, 0, sizeof (fib));
  fib.fib$w_did[0]  = nam.nam$w_did[0];
  fib.fib$w_did[1]  = nam.nam$w_did[1];
  fib.fib$w_did[2]  = nam.nam$w_did[2];
  fib.fib$l_acctl = 0;
  fib.fib$l_wcc = 0;
  strcpy (file.string, (strrchr (result.string, ']') + 1));
  filedsc.dsc$w_length = strlen (file.string);
  result.string[result.length = 0] = 0;

  /* Open and close the file to fill in the attributes.  */
  status
    = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
		&fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
  if ((status & 1) != 1)
    return 1;
  if ((iosb.status & 1) != 1)
    return 1;

  result.string[result.length] = 0;
  status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
		     &atrlst, 0);
  if ((status & 1) != 1)
    return 1;
  if ((iosb.status & 1) != 1)
    return 1;

  /* Deassign the channel and exit.  */
  status = SYS$DASSGN (chan);
  if ((status & 1) != 1)
    return 1;

  if (cdt) *cdt = create;
  if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) +
                  (512 * (recattr.fat$w_efblkl - 1)) +
                  recattr.fat$w_ffbyte;
  if (rfo) *rfo = recattr.fat$v_rtype;
  if (ver) *ver = strtol (strrchr (ascnamebuff, ';')+1, 0, 10);

  return 0;
#else
  struct stat buff;
  struct tm *ts;

  if ((stat (filename, &buff)) != 0)
     return 1;

  if (cdt)
    {
      ts = localtime (&buff.st_mtime);
      *cdt = (long long) ((buff.st_mtim.tv_sec * VMS_GRANULARITY_FACTOR)
                          + (buff.st_mtim.tv_nsec / 100))
                         + VMS_EPOCH_OFFSET;
    }

  if (siz)
    *siz = buff.st_size;

  if (rfo)
    *rfo = 2; /* Stream LF format.  */

  if (ver)
    *ver = 0;

  return 0;
#endif
}
Ejemplo n.º 6
0
int
SOCKconnect(char *hostname, int port)
{
#if !defined(CMUIP) && !defined(NETLIB)
     struct sockaddr_in Server;
     struct hostent *HostPtr;
     int sockfd = 0;
     unsigned int ERRinet = -1;

#ifdef _CRAY
     ERRinet = 0xFFFFFFFF;  /* -1 doesn't sign extend on 64 bit machines */
#endif

     /*** Find the hostname address ***/
     
     if (hostname == NULL || *hostname == '\0')
	  return(ErrSocketNullHost);

#ifdef DGUX
     Server.sin_addr = inet_addr(hostname);
     if (Server.sin_addr.s_addr == ERRinet)
#else
     if ((Server.sin_addr.s_addr = inet_addr(hostname)) == ERRinet)
#endif
     {
	  if ((HostPtr = gethostbyname(hostname)) != NULL) {
	       bzero((char *) &Server, sizeof(Server));
	       bcopy(HostPtr->h_addr, (char *) &Server.sin_addr, HostPtr->h_length);
	       Server.sin_family = HostPtr->h_addrtype;
	  } else
	       return (ErrSocketGetHost);
     } else
	  Server.sin_family = AF_INET;

     Server.sin_port = (unsigned short) htons(port);

     /*** Open the socket ***/

     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	  return (ErrSocketCall);

#ifndef UCX
     setsockopt(sockfd, SOL_SOCKET, ~SO_LINGER, 0, 0);
#endif

     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0);
     setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, 0, 0);

     /*** Connect ***/
     if (ControlCpressed) { /* Already interrupted */
	  return(ErrSocketInterrupted);
     }
     if (signal(SIGINT, controlcJmp) == SIG_ERR)
	  perror("signal died:\n"), exit(-1);

     if (setjmp(Jmpenv)) {
	  /* Note controlcJmp will reprime controlc and set flag*/
	  Debug("interruptable_connect triggered\r\n",NULL)
	       return(ErrSocketInterrupted);
     }

     if (connect(sockfd, (struct sockaddr *) &Server, sizeof(Server)) < 0) {
	  closenet(sockfd);
	  reprimeControlc();
	  return (ErrSocketConnect);
     }
     reprimeControlc();

     return(sockfd);

#else /* !NETLIB && !CMUIP */
#ifdef NETLIB
     int status;
     static int iSock = 0;
     struct {
          long len;
          char *adr;
     } host_desc;

#define NET_K_TCP 1
     status = NET_ASSIGN (&iSock);
     if ((status & 1) == 0)
          return (ErrSocketCall);
     status = NET_BIND (&iSock, NET_K_TCP);
     if ((status & 1) == 0)
          return (ErrSocketCall);
     host_desc.adr = hostname;
     host_desc.len = strlen (host_desc.adr);
     status = TCP_CONNECT (&iSock, &host_desc, port);
     if ((status & 1) == 0) {
          NET_DEASSIGN (&iSock);
          if (status == SS$_REJECT || status == SS$_TIMEOUT) {
	       if (status == SS$_REJECT)
		    errno = ECONNREFUSED;
	       else
		    errno = ETIMEDOUT;
	       
	       return (ErrSocketConnect);
	  }
	  if (status == SS$_ENDOFFILE)
	       return (ErrSocketGetHost);
          return (ErrSocketGetService);
     }
     return (iSock);
#else /* ifdef NETLIB:  assume CMUIP */
     short channel;
     int status;
     struct {
          short status;
          short size;
          long xxx;
     } cmu_iosb;
     static struct {long l; char *a;} ip_dev = {12, "INET$DEVICE:"};
     globalvalue NET$_CREF;           /* Connection refused */
     globalvalue NET$_FTO;            /* Function timedout */
     globalvalue NET$_DSNAMERR;       /* Domain server name error */
     status = SYS$ASSIGN (&ip_dev, &channel, 0, 0);
     if ((status & 1) == 0)
          return (ErrSocketCall);
     status = SYS$QIOW (0, channel, IO$_CREATE, &cmu_iosb, 0, 0,
          hostname, port, 0, 1, 0, 0);
     if ((status & 1) == 0 || (cmu_iosb.status & 1) == 0) {
          SYS$DASSGN (channel);
          if (cmu_iosb.status == SS$_ABORT || cmu_iosb.xxx == NET$_FTO) {
               if (cmu_iosb.xxx == NET$_CREF)
		    errno = ECONNREFUSED;
	       else
		    errno = ETIMEDOUT;

	       return(ErrSocketConnect);
	  }
	  if (cmu_iosb.xxx == NET$_DSNAMERR)
	       return (ErrSocketGetHost);
     }
     return (channel);
#endif
#endif

}
Ejemplo n.º 7
0
char *
readpassphrase(const char *prompt, char *pbuf, size_t buflen, int flags)
{

	static unsigned long keyboard_id, keytable_id = 0;
	unsigned long ctrl_mask, saved_ctrl_mask = 0;
	int timeout_secs = 0;
	int *timeout_ptr = NULL;
	unsigned long status = 0;
	unsigned short iosb[4];
	unsigned short ttchan, result_len = 0, stdin_is_tty;

	$DESCRIPTOR(ttdsc, "");
	$DESCRIPTOR(pbuf_dsc, "");
	$DESCRIPTOR(prompt_dsc, "");
	char *retval = NULL;
	char *myprompt = NULL;
	char input_fspec[MY_PASSWORD_LEN + 1];

	if (pbuf == NULL || buflen == 0) {
		errno = EINVAL;
		return NULL;
	}
	bzero(pbuf, buflen);
	pbuf_dsc.dsc$a_pointer = pbuf;
	pbuf_dsc.dsc$w_length = buflen - 1;


	/*
	 * If stdin is not a terminal and only reading from a terminal is allowed, we
	 * stop here.  
	 */
	stdin_is_tty = isatty(fileno(stdin));
	if (stdin_is_tty != 1 && (flags & RPP_REQUIRE_TTY)) {
		errno = ENOTTY;
		return NULL;
	}

	/*
	 * We need the file or device associated with stdin in VMS format.
	 */
	if (fgetname(stdin, input_fspec, 1)) {
		ttdsc.dsc$a_pointer = (char *)&input_fspec;
		ttdsc.dsc$w_length = strlen(input_fspec);
	} else {
		errno = EMFILE;
		return NULL;
	}

	/* 
	 * The prompt is expected to provide its own leading newline.
	 */
	myprompt = malloc(strlen(prompt) + 1);
	if (myprompt == NULL) {
		errno = ENOMEM;
		return NULL;
	}
	sprintf(myprompt, "\n%s", prompt);
	prompt_dsc.dsc$a_pointer = myprompt;
	prompt_dsc.dsc$w_length = strlen(myprompt);

	if (!(flags & RPP_ECHO_ON) && (stdin_is_tty)) {
		/* Disable Ctrl-T and Ctrl-Y */
		ctrl_mask = LIB$M_CLI_CTRLT | LIB$M_CLI_CTRLY;
		status = LIB$DISABLE_CTRL(&ctrl_mask, &saved_ctrl_mask);
		if (!$VMS_STATUS_SUCCESS(status)) {
			errno = EVMSERR;
			vaxc$errno = status;
			free(myprompt);
			return NULL;
		}
	}

	/* 
	 * Unless timeouts are disabled, find out how long should we wait for input
	 * before giving up.
	 */
	if (!(flags & RPP_TIMEOUT_OFF)) {
		unsigned long tmo_item = SYI$_LGI_PWD_TMO;

		status = LIB$GETSYI(&tmo_item, &timeout_secs);
		if (!$VMS_STATUS_SUCCESS(status))
			timeout_secs = DEFAULT_TIMEOUT;
		timeout_ptr = &timeout_secs;
	}

	if (!(flags & RPP_ECHO_ON) && (stdin_is_tty)) {
		/* 
		 * If we are suppressing echoing, get a line of input with $QIOW.  
		 * Non-echoed lines are not stored for recall.  (The same thing
		 * could be done with SMG but would require maintenance of a virtual 
		 * display and pasteboard.)
		 */
		status = SYS$ASSIGN(&ttdsc, &ttchan, 0, 0, 0);
		if ($VMS_STATUS_SUCCESS(status)) {

			unsigned long qio_func = IO$_READPROMPT | IO$M_NOECHO | IO$M_PURGE;

			if (!(flags & RPP_TIMEOUT_OFF))
				qio_func |= IO$M_TIMED;
			bzero(iosb, sizeof(iosb));

			status = SYS$QIOW(0,
					  (unsigned long) ttchan,
					  qio_func, &iosb, 0, 0, pbuf, buflen - 1, timeout_secs, 0, myprompt, strlen(myprompt));

			if ($VMS_STATUS_SUCCESS(status)) {
				status = iosb[0];
				result_len = iosb[1];	/* bytes actually read */
			}
			(void) SYS$DASSGN(ttchan);
		}
	} else {
		/* 
		 * We are not suppressing echoing because echoing has been explicitly 
		 * enabled and/or we are not reading from a terminal.  In this case we 
		 * use SMG, which will store commands for recall.  The virtual keyboard 
		 * and key table are static and will only be created if we haven't been 
		 * here before.
		 */
		status = SS$_NORMAL;
		if (keyboard_id == 0) {
			unsigned char recall_size = RECALL_SIZE;

			status = SMG$CREATE_VIRTUAL_KEYBOARD(&keyboard_id, &ttdsc, 0, 0, &recall_size);
		}
		if ($VMS_STATUS_SUCCESS(status) && keytable_id == 0) {
			status = SMG$CREATE_KEY_TABLE(&keytable_id);
		}

		if ($VMS_STATUS_SUCCESS(status)) {
			status = SMG$READ_COMPOSED_LINE(&keyboard_id,
							&keytable_id, &pbuf_dsc, &prompt_dsc, &result_len, 0, 0, 0, timeout_ptr);
		}
	}

	/* 
	 * Process return value from SYS$QIOW or SMG$READ_COMPOSED_LINE.
	 */
	switch (status) {
	case SS$_TIMEOUT:
		errno = ETIMEDOUT;
		break;
	case SMG$_EOF:
		if (result_len != 0) {
			status = SS$_NORMAL;
		}
		/* fall through */
	default:
		if ($VMS_STATUS_SUCCESS(status)) {
			int i;

			if (flags & RPP_FORCELOWER) {
				for (i = 0; i < result_len; i++)
					pbuf[i] = tolower(pbuf[i]);
			}
			if (flags & RPP_FORCEUPPER) {
				for (i = 0; i < result_len; i++)
					pbuf[i] = toupper(pbuf[i]);
			}
			if (flags & RPP_SEVENBIT) {
				for (i = 0; i < result_len; i++)
					pbuf[i] &= 0x7f;
			}
			pbuf[result_len] = '\0';
			retval = pbuf;
		} else {
			errno = EVMSERR;
			vaxc$errno = status;
		}
	}			/* end switch */

	free(myprompt);

	if (!(flags & RPP_ECHO_ON) && (stdin_is_tty)) {
		/*
		 * Reenable previous control processing.
		 */
		status = LIB$ENABLE_CTRL(&saved_ctrl_mask);

		if (!$VMS_STATUS_SUCCESS(status)) {
			errno = EVMSERR;
			vaxc$errno = status;
			return NULL;
		}
	}

	return retval;

}				/* getpassphrase */