diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 2006-03-27 22:47:13 +0000 | 
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 2006-03-27 22:47:13 +0000 | 
| commit | 8e24aab4029c5fd838bebf7a54c015e8feef77aa (patch) | |
| tree | 68d53cc1ed741c82815ad35a24b983fef67251cd /contrib/libreadline/examples/rlfe.c | |
| parent | 7a7865ca930d05a56cd5ea0f9e563d82f2ef6b97 (diff) | |
Diffstat (limited to 'contrib/libreadline/examples/rlfe.c')
| -rw-r--r-- | contrib/libreadline/examples/rlfe.c | 1042 | 
1 files changed, 0 insertions, 1042 deletions
diff --git a/contrib/libreadline/examples/rlfe.c b/contrib/libreadline/examples/rlfe.c deleted file mode 100644 index d634d7ce878b..000000000000 --- a/contrib/libreadline/examples/rlfe.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* A front-end using readline to "cook" input lines for Kawa. - * - * Copyright (C) 1999  Per Bothner - *  - * This front-end program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * Some code from Johnson & Troan: "Linux Application Development" - * (Addison-Wesley, 1998) was used directly or for inspiration. - */ - -/* PROBLEMS/TODO: - * - * Only tested under Linux;  needs to be ported. - * - * When running mc -c under the Linux console, mc does not recognize - * mouse clicks, which mc does when not running under fep. - * - * Pasting selected text containing tabs is like hitting the tab character, - * which invokes readline completion.  We don't want this.  I don't know - * if this is fixable without integrating fep into a terminal emulator. - * - * Echo suppression is a kludge, but can only be avoided with better kernel - * support: We need a tty mode to disable "real" echoing, while still - * letting the inferior think its tty driver to doing echoing. - * Stevens's book claims SCR$ and BSD4.3+ have TIOCREMOTE. - * - * The latest readline may have some hooks we can use to avoid having - * to back up the prompt. - * - * Desirable readline feature:  When in cooked no-echo mode (e.g. password), - * echo characters are they are types with '*', but remove them when done. - * - * A synchronous output while we're editing an input line should be - * inserted in the output view *before* the input line, so that the - * lines being edited (with the prompt) float at the end of the input. - * - * A "page mode" option to emulate more/less behavior:  At each page of - * output, pause for a user command.  This required parsing the output - * to keep track of line lengths.  It also requires remembering the - * output, if we want an option to scroll back, which suggests that - * this should be integrated with a terminal emulator like xterm. - */ - -#ifdef HAVE_CONFIG_H -#  include <config.h> -#endif - -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <signal.h> -#include <netdb.h> -#include <stdlib.h> -#include <errno.h> -#include <grp.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <termios.h> -#include <limits.h> -#include <dirent.h> - -#ifdef READLINE_LIBRARY -#  include "readline.h" -#  include "history.h" -#else -#  include <readline/readline.h> -#  include <readline/history.h> -#endif - -#ifndef COMMAND -#define COMMAND "/bin/sh" -#endif -#ifndef COMMAND_ARGS -#define COMMAND_ARGS COMMAND -#endif - -#ifndef HAVE_MEMMOVE -#ifndef memmove -#  if __GNUC__ > 1 -#    define memmove(d, s, n)	__builtin_memcpy(d, s, n) -#  else -#    define memmove(d, s, n)	memcpy(d, s, n) -#  endif -#else -#  define memmove(d, s, n)	memcpy(d, s, n) -#endif -#endif - -#define APPLICATION_NAME "Rlfe" - -#ifndef errno -extern int errno; -#endif - -extern int optind; -extern char *optarg; - -static char *progname; -static char *progversion; - -static int in_from_inferior_fd; -static int out_to_inferior_fd; - -/* Unfortunately, we cannot safely display echo from the inferior process. -   The reason is that the echo bit in the pty is "owned" by the inferior, -   and if we try to turn it off, we could confuse the inferior. -   Thus, when echoing, we get echo twice:  First readline echoes while -   we're actually editing. Then we send the line to the inferior, and the -   terminal driver send back an extra echo. -   The work-around is to remember the input lines, and when we see that -   line come back, we supress the output. -   A better solution (supposedly available on SVR4) would be a smarter -   terminal driver, with more flags ... */ -#define ECHO_SUPPRESS_MAX 1024 -char echo_suppress_buffer[ECHO_SUPPRESS_MAX]; -int echo_suppress_start = 0; -int echo_suppress_limit = 0; - -/* #define DEBUG */ - -static FILE *logfile = NULL; - -#ifdef DEBUG -FILE *debugfile = NULL; -#define DPRINT0(FMT) (fprintf(debugfile, FMT), fflush(debugfile)) -#define DPRINT1(FMT, V1) (fprintf(debugfile, FMT, V1), fflush(debugfile)) -#define DPRINT2(FMT, V1, V2) (fprintf(debugfile, FMT, V1, V2), fflush(debugfile)) -#else -#define DPRINT0(FMT) /* Do nothing */ -#define DPRINT1(FMT, V1) /* Do nothing */ -#define DPRINT2(FMT, V1, V2) /* Do nothing */ -#endif - -struct termios orig_term; - -static int rlfe_directory_completion_hook __P((char **)); -static int rlfe_directory_rewrite_hook __P((char **)); -static char *rlfe_filename_completion_function __P((const char *, int)); - -/* Pid of child process. */ -static pid_t child = -1; - -static void -sig_child (int signo) -{ -  int status; -  wait (&status); -  DPRINT0 ("(Child process died.)\n"); -  tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); -  exit (0); -} - -volatile int propagate_sigwinch = 0; - -/* sigwinch_handler - * propagate window size changes from input file descriptor to - * master side of pty. - */ -void sigwinch_handler(int signal) {  -   propagate_sigwinch = 1; -} - -/* get_master_pty() takes a double-indirect character pointer in which - * to put a slave name, and returns an integer file descriptor. - * If it returns < 0, an error has occurred. - * Otherwise, it has returned the master pty file descriptor, and fills - * in *name with the name of the corresponding slave pty. - * Once the slave pty has been opened, you are responsible to free *name. - */ - -int get_master_pty(char **name) {  -   int i, j; -   /* default to returning error */ -   int master = -1; - -   /* create a dummy name to fill in */ -   *name = strdup("/dev/ptyXX"); - -   /* search for an unused pty */ -   for (i=0; i<16 && master <= 0; i++) { -      for (j=0; j<16 && master <= 0; j++) { -         (*name)[5] = 'p'; -         (*name)[8] = "pqrstuvwxyzPQRST"[i]; -         (*name)[9] = "0123456789abcdef"[j]; -         /* open the master pty */ -         if ((master = open(*name, O_RDWR)) < 0) { -            if (errno == ENOENT) { -               /* we are out of pty devices */ -               free (*name); -               return (master); -            } -         } -         else { -           /* By substituting a letter, we change the master pty -            * name into the slave pty name. -            */ -           (*name)[5] = 't'; -           if (access(*name, R_OK|W_OK) != 0) -             { -               close(master); -               master = -1; -             } -         } -      } -   } -   if ((master < 0) && (i == 16) && (j == 16)) { -      /* must have tried every pty unsuccessfully */ -      free (*name); -      return (master); -   } - -   (*name)[5] = 't'; - -   return (master); -} - -/* get_slave_pty() returns an integer file descriptor. - * If it returns < 0, an error has occurred. - * Otherwise, it has returned the slave file descriptor. - */ - -int get_slave_pty(char *name) {  -   struct group *gptr; -   gid_t gid; -   int slave = -1; - -   /* chown/chmod the corresponding pty, if possible. -    * This will only work if the process has root permissions. -    * Alternatively, write and exec a small setuid program that -    * does just this. -    */ -   if ((gptr = getgrnam("tty")) != 0) { -      gid = gptr->gr_gid; -   } else { -      /* if the tty group does not exist, don't change the -       * group on the slave pty, only the owner -       */ -      gid = -1; -   } - -   /* Note that we do not check for errors here.  If this is code -    * where these actions are critical, check for errors! -    */ -   chown(name, getuid(), gid); -   /* This code only makes the slave read/writeable for the user. -    * If this is for an interactive shell that will want to -    * receive "write" and "wall" messages, OR S_IWGRP into the -    * second argument below. -    */ -   chmod(name, S_IRUSR|S_IWUSR); - -   /* open the corresponding slave pty */ -   slave = open(name, O_RDWR); -   return (slave); -} - -/* Certain special characters, such as ctrl/C, we want to pass directly -   to the inferior, rather than letting readline handle them. */ - -static char special_chars[20]; -static int special_chars_count; - -static void -add_special_char(int ch) -{ -  if (ch != 0) -    special_chars[special_chars_count++] = ch; -} - -static int eof_char; - -static int -is_special_char(int ch) -{ -  int i; -#if 0 -  if (ch == eof_char && rl_point == rl_end) -    return 1; -#endif -  for (i = special_chars_count;  --i >= 0; ) -    if (special_chars[i] == ch) -      return 1; -  return 0; -} - -static char buf[1024]; -/* buf[0 .. buf_count-1] is the what has been emitted on the current line. -   It is used as the readline prompt. */ -static int buf_count = 0; - -int num_keys = 0; - -static void -null_prep_terminal (int meta) -{ -} - -static void -null_deprep_terminal () -{ -} - -char pending_special_char; - -static void -line_handler (char *line) -{ -  if (line == NULL) -    { -      char buf[1]; -      DPRINT0("saw eof!\n"); -      buf[0] = '\004'; /* ctrl/d */ -      write (out_to_inferior_fd, buf, 1); -    } -  else -    { -      static char enter[] = "\r"; -      /*  Send line to inferior: */ -      int length = strlen (line); -      if (length > ECHO_SUPPRESS_MAX-2) -	{ -	  echo_suppress_start = 0; -	  echo_suppress_limit = 0; -	} -      else -	{ -	  if (echo_suppress_limit + length > ECHO_SUPPRESS_MAX - 2) -	    { -	      if (echo_suppress_limit - echo_suppress_start + length -		  <= ECHO_SUPPRESS_MAX - 2) -		{ -		  memmove (echo_suppress_buffer, -			   echo_suppress_buffer + echo_suppress_start, -			   echo_suppress_limit - echo_suppress_start); -		  echo_suppress_limit -= echo_suppress_start; -		  echo_suppress_start = 0; -		} -	      else -		{ -		  echo_suppress_limit = 0; -		} -	      echo_suppress_start = 0; -	    } -	  memcpy (echo_suppress_buffer + echo_suppress_limit, -		  line, length); -	  echo_suppress_limit += length; -	  echo_suppress_buffer[echo_suppress_limit++] = '\r'; -	  echo_suppress_buffer[echo_suppress_limit++] = '\n'; -	} -      write (out_to_inferior_fd, line, length); -      if (pending_special_char == 0) -        { -          write (out_to_inferior_fd, enter, sizeof(enter)-1); -          if (*line) -            add_history (line); -        } -      free (line); -    } -  rl_callback_handler_remove (); -  buf_count = 0; -  num_keys = 0; -  if (pending_special_char != 0) -    { -      write (out_to_inferior_fd, &pending_special_char, 1); -      pending_special_char = 0; -    } -} - -/* Value of rl_getc_function. -   Use this because readline should read from stdin, not rl_instream, -   points to the pty (so readline has monitor its terminal modes). */ - -int -my_rl_getc (FILE *dummy) -{ -  int ch = rl_getc (stdin); -  if (is_special_char (ch)) -    { -      pending_special_char = ch; -      return '\r'; -    } -  return ch; -} - -static void -usage() -{ -  fprintf (stderr, "%s: usage: %s [-l filename] [-a] [-n appname] [-hv] [command [arguments...]]\n", -		   progname, progname); -} - -int -main(int argc, char** argv) -{ -  char *path; -  int i, append; -  int master; -  char *name, *logfname, *appname; -  int in_from_tty_fd; -  struct sigaction act; -  struct winsize ws; -  struct termios t; -  int maxfd; -  fd_set in_set; -  static char empty_string[1] = ""; -  char *prompt = empty_string; -  int ioctl_err = 0; - -  if ((progname = strrchr (argv[0], '/')) == 0) -    progname = argv[0]; -  else -    progname++; -  progversion = RL_LIBRARY_VERSION; - -  append = 0; -  appname = APPLICATION_NAME; -  logfname = (char *)NULL; - -  while ((i = getopt (argc, argv, "ahl:n:v")) != EOF) -    { -      switch (i) -	{ -	case 'l': -	  logfname = optarg; -	  break; -	case 'n': -	  appname = optarg; -	  break; -	case 'a': -	  append = 1; -	  break; -	case 'h': -	  usage (); -	  exit (0); -	case 'v': -	  fprintf (stderr, "%s version %s\n", progname, progversion); -	  exit (0); -	default: -	  usage (); -	  exit (2); -	} -    } - -  argc -= optind; -  argv += optind; - -  if (logfname) -    { -      logfile = fopen (logfname, append ? "a" : "w"); -      if (logfile == 0) -	fprintf (stderr, "%s: warning: could not open log file %s: %s\n", -			 progname, logfname, strerror (errno)); -    } -     -  rl_readline_name = appname; -   -#ifdef DEBUG -  debugfile = fopen("LOG", "w"); -#endif - -  if ((master = get_master_pty(&name)) < 0) -    { -      perror("ptypair: could not open master pty"); -      exit(1); -    } - -  DPRINT1("pty name: '%s'\n", name); - -  /* set up SIGWINCH handler */ -  act.sa_handler = sigwinch_handler; -  sigemptyset(&(act.sa_mask)); -  act.sa_flags = 0; -  if (sigaction(SIGWINCH, &act, NULL) < 0) -    { -      perror("ptypair: could not handle SIGWINCH "); -      exit(1); -    } - -  if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) -    { -      perror("ptypair: could not get window size"); -      exit(1); -    } - -  if ((child = fork()) < 0) -    { -      perror("cannot fork"); -      exit(1); -    } - -  if (child == 0) -    {  -      int slave;  /* file descriptor for slave pty */ - -      /* We are in the child process */ -      close(master); - -#ifdef TIOCSCTTY -      if ((slave = get_slave_pty(name)) < 0) -	{ -	  perror("ptypair: could not open slave pty"); -	  exit(1); -	} -      free(name); -#endif - -      /* We need to make this process a session group leader, because -       * it is on a new PTY, and things like job control simply will -       * not work correctly unless there is a session group leader -       * and process group leader (which a session group leader -       * automatically is). This also disassociates us from our old -       * controlling tty.  -       */ -      if (setsid() < 0) -	{ -	  perror("could not set session leader"); -	} - -      /* Tie us to our new controlling tty. */ -#ifdef TIOCSCTTY -      if (ioctl(slave, TIOCSCTTY, NULL)) -	{ -	  perror("could not set new controlling tty"); -	} -#else -      if ((slave = get_slave_pty(name)) < 0) -	{ -	  perror("ptypair: could not open slave pty"); -	  exit(1); -	} -      free(name); -#endif - -      /* make slave pty be standard in, out, and error */ -      dup2(slave, STDIN_FILENO); -      dup2(slave, STDOUT_FILENO); -      dup2(slave, STDERR_FILENO); - -      /* at this point the slave pty should be standard input */ -      if (slave > 2) -	{ -	  close(slave); -	} - -      /* Try to restore window size; failure isn't critical */ -      if (ioctl(STDOUT_FILENO, TIOCSWINSZ, &ws) < 0) -	{ -	  perror("could not restore window size"); -	} - -      /* now start the shell */ -      { -	static char* command_args[] = { COMMAND_ARGS, NULL }; -	if (argc < 1) -	  execvp(COMMAND, command_args); -	else -	  execvp(argv[0], &argv[0]); -      } - -      /* should never be reached */ -      exit(1); -    } - -  /* parent */ -  signal (SIGCHLD, sig_child); -  free(name); - -  /* Note that we only set termios settings for standard input; -   * the master side of a pty is NOT a tty. -   */ -  tcgetattr(STDIN_FILENO, &orig_term); - -  t = orig_term; -  eof_char = t.c_cc[VEOF]; -  /*  add_special_char(t.c_cc[VEOF]);*/ -  add_special_char(t.c_cc[VINTR]); -  add_special_char(t.c_cc[VQUIT]); -  add_special_char(t.c_cc[VSUSP]); -#if defined (VDISCARD) -  add_special_char(t.c_cc[VDISCARD]); -#endif - -#if 0 -  t.c_lflag |= (ICANON | ISIG | ECHO | ECHOCTL | ECHOE | \ -		ECHOK | ECHOKE | ECHONL | ECHOPRT ); -#else -  t.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOCTL | ECHOE | \ -		 ECHOK | ECHOKE | ECHONL | ECHOPRT ); -#endif -  t.c_iflag |= IGNBRK; -  t.c_cc[VMIN] = 1; -  t.c_cc[VTIME] = 0; -  tcsetattr(STDIN_FILENO, TCSANOW, &t); -  in_from_inferior_fd = master; -  out_to_inferior_fd = master; -  rl_instream = fdopen (master, "r"); -  rl_getc_function = my_rl_getc; - -  rl_prep_term_function = null_prep_terminal;  -  rl_deprep_term_function = null_deprep_terminal;  -  rl_callback_handler_install (prompt, line_handler); - -#if 1 -  rl_directory_completion_hook = rlfe_directory_completion_hook; -  rl_completion_entry_function = rlfe_filename_completion_function; -#else -  rl_directory_rewrite_hook = rlfe_directory_rewrite_hook; -#endif - -  in_from_tty_fd = STDIN_FILENO; -  FD_ZERO (&in_set); -  maxfd = in_from_inferior_fd > in_from_tty_fd ? in_from_inferior_fd -    : in_from_tty_fd; -  for (;;) -    { -      int num; -      FD_SET (in_from_inferior_fd, &in_set); -      FD_SET (in_from_tty_fd, &in_set); - -      num = select(maxfd+1, &in_set, NULL, NULL, NULL); - -      if (propagate_sigwinch) -	{ -	  struct winsize ws; -	  if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) >= 0) -	    { -	      ioctl (master, TIOCSWINSZ, &ws); -	    } -	  propagate_sigwinch = 0; -	  continue; -	} - -      if (num <= 0) -	{ -	  perror ("select"); -	  exit (-1); -	} -      if (FD_ISSET (in_from_tty_fd, &in_set)) -	{ -	  extern int readline_echoing_p; -	  struct termios term_master; -	  int do_canon = 1; -	  int ioctl_ret; - -	  DPRINT1("[tty avail num_keys:%d]\n", num_keys); - -	  /* If we can't get tty modes for the master side of the pty, we -	     can't handle non-canonical-mode programs.  Always assume the -	     master is in canonical echo mode if we can't tell. */ -	  ioctl_ret = tcgetattr(master, &term_master); - -	  if (ioctl_ret >= 0) -	    { -	      DPRINT2 ("echo:%d, canon:%d\n", -			(term_master.c_lflag & ECHO) != 0, -			(term_master.c_lflag & ICANON) != 0); -	      do_canon = (term_master.c_lflag & ICANON) != 0; -	      readline_echoing_p = (term_master.c_lflag & ECHO) != 0; -	    } -	  else -	    { -	      if (ioctl_err == 0) -		DPRINT1("tcgetattr on master fd failed: errno = %d\n", errno); -	      ioctl_err = 1; -	    } - -	  if (do_canon == 0 && num_keys == 0) -	    { -	      char ch[10]; -	      int count = read (STDIN_FILENO, ch, sizeof(ch)); -	      write (out_to_inferior_fd, ch, count); -	    } -	  else -	    { -	      if (num_keys == 0) -		{ -		  int i; -		  /* Re-install callback handler for new prompt. */ -		  if (prompt != empty_string) -		    free (prompt); -		  prompt = malloc (buf_count + 1); -		  if (prompt == NULL) -		    prompt = empty_string; -		  else -		    { -		      memcpy (prompt, buf, buf_count); -		      prompt[buf_count] = '\0'; -		      DPRINT1("New prompt '%s'\n", prompt); -#if 0 /* ifdef HAVE_RL_ALREADY_PROMPTED -- doesn't work */ -		      rl_already_prompted = buf_count > 0; -#else -		      if (buf_count > 0) -			write (1, "\r", 1); -#endif -		    } -		  rl_callback_handler_install (prompt, line_handler); -		} -	      num_keys++; -	      rl_callback_read_char (); -	    } -	} -      else /* input from inferior. */ -	{ -	  int i; -	  int count; -	  int old_count; -	  if (buf_count > (sizeof(buf) >> 2)) -	    buf_count = 0; -	  count = read (in_from_inferior_fd, buf+buf_count, -			sizeof(buf) - buf_count); -	  if (count <= 0) -	    { -	      DPRINT0 ("(Connection closed by foreign host.)\n"); -	      tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); -	      exit (0); -	    } -	  old_count = buf_count; - -	  /* Do some minimal carriage return translation and backspace -	     processing before logging the input line. */ -	  if (logfile) -	    { -#ifndef __GNUC__ -	      char *b; -#else -	      char b[count + 1]; -#endif -	      int i, j; - -#ifndef __GNUC__ -	      b = malloc (count + 1); -	      if (b) { -#endif -	      for (i = 0; i < count; i++) -	        b[i] = buf[buf_count + i]; -	      b[i] = '\0'; -	      for (i = j = 0; i <= count; i++) -		{ -		  if (b[i] == '\r') -		    { -		      if (b[i+1] != '\n') -		        b[j++] = '\n'; -		    } -		  else if (b[i] == '\b') -		    { -		      if (i) -			j--; -		    } -		  else -		    b[j++] = b[i]; -		} -	      fprintf (logfile, "%s", b); - -#ifndef __GNUC__ -	      free (b); -	      } -#endif -	    } - -          /* Look for any pending echo that we need to suppress. */ -	  while (echo_suppress_start < echo_suppress_limit -		 && count > 0 -		 && buf[buf_count] == echo_suppress_buffer[echo_suppress_start]) -	    { -	      count--; -	      buf_count++; -	      echo_suppress_start++; -	    } - -          /* Write to the terminal anything that was not suppressed. */ -          if (count > 0) -            write (1, buf + buf_count, count); - -          /* Finally, look for a prompt candidate. -           * When we get around to going input (from the keyboard), -           * we will consider the prompt to be anything since the last -           * line terminator.  So we need to save that text in the -           * initial part of buf.  However, anything before the -           * most recent end-of-line is not interesting. */ -	  buf_count += count; -#if 1 -	  for (i = buf_count;  --i >= old_count; ) -#else -	  for (i = buf_count - 1;  i-- >= buf_count - count; ) -#endif -	    { -	      if (buf[i] == '\n' || buf[i] == '\r') -		{ -		  i++; -		  memmove (buf, buf+i, buf_count - i); -		  buf_count -= i; -		  break; -		} -	    } -	  DPRINT2("-> i: %d, buf_count: %d\n", i, buf_count); -	} -    } -} - -/* - * - * FILENAME COMPLETION FOR RLFE - * - */ - -#ifndef PATH_MAX -#  define PATH_MAX 1024 -#endif - -#define DIRSEP		'/' -#define ISDIRSEP(x)	((x) == '/') -#define PATHSEP(x)	(ISDIRSEP(x) || (x) == 0) - -#define DOT_OR_DOTDOT(x) \ -	((x)[0] == '.' && (PATHSEP((x)[1]) || \ -			  ((x)[1] == '.' && PATHSEP((x)[2])))) - -#define FREE(x)		if (x) free(x) - -#define STRDUP(s, x)	do { \ -			  s = strdup (x);\ -			  if (s == 0) \ -			    return ((char *)NULL); \ -			} while (0) - -static int -get_inferior_cwd (path, psize) -     char *path; -     size_t psize; -{ -  int n; -  static char procfsbuf[PATH_MAX] = { '\0' }; - -  if (procfsbuf[0] == '\0') -    sprintf (procfsbuf, "/proc/%d/cwd", (int)child); -  n = readlink (procfsbuf, path, psize); -  if (n < 0) -    return n; -  if (n > psize) -    return -1; -  path[n] = '\0'; -  return n; -} - -static int -rlfe_directory_rewrite_hook (dirnamep) -     char **dirnamep; -{ -  char *ldirname, cwd[PATH_MAX], *retdir, *ld; -  int n, ldlen; - -  ldirname = *dirnamep; - -  if (*ldirname == '/') -    return 0; - -  n = get_inferior_cwd (cwd, sizeof(cwd) - 1); -  if (n < 0) -    return 0; -  if (n == 0)	/* current directory */ -    { -      cwd[0] = '.'; -      cwd[1] = '\0'; -      n = 1; -    } - -  /* Minimally canonicalize ldirname by removing leading `./' */ -  for (ld = ldirname; *ld; ) -    { -      if (ISDIRSEP (ld[0])) -	ld++; -      else if (ld[0] == '.' && PATHSEP(ld[1])) -	ld++; -      else -	break; -    } -  ldlen = (ld && *ld) ? strlen (ld) : 0; - -  retdir = (char *)malloc (n + ldlen + 3); -  if (retdir == 0) -    return 0; -  if (ldlen) -    sprintf (retdir, "%s/%s", cwd, ld); -  else -    strcpy (retdir, cwd); -  free (ldirname); - -  *dirnamep = retdir; - -  DPRINT1("rl_directory_rewrite_hook returns %s\n", retdir); -  return 1; -} - -/* Translate *DIRNAMEP to be relative to the inferior's CWD.  Leave a trailing -   slash on the result. */ -static int -rlfe_directory_completion_hook (dirnamep) -     char **dirnamep; -{ -  char *ldirname, *retdir; -  int n, ldlen; - -  ldirname = *dirnamep; - -  if (*ldirname == '/') -    return 0; - -  n = rlfe_directory_rewrite_hook (dirnamep); -  if (n == 0) -    return 0; - -  ldirname = *dirnamep; -  ldlen = (ldirname && *ldirname) ? strlen (ldirname) : 0; - -  if (ldlen == 0 || ldirname[ldlen - 1] != '/') -    { -      retdir = (char *)malloc (ldlen + 3); -      if (retdir == 0) -	return 0; -      if (ldlen) -	strcpy (retdir, ldirname); -      else -	retdir[ldlen++] = '.'; -      retdir[ldlen] = '/'; -      retdir[ldlen+1] = '\0'; -      free (ldirname); - -      *dirnamep = retdir; -    } - -  DPRINT1("rl_directory_completion_hook returns %s\n", retdir); -  return 1; -} - -static char * -rlfe_filename_completion_function (text, state) -     const char *text; -     int state; -{ -  static DIR *directory; -  static char *filename = (char *)NULL; -  static char *dirname = (char *)NULL, *ud = (char *)NULL; -  static int flen, udlen; -  char *temp; -  struct dirent *dentry; - -  if (state == 0) -    { -      if (directory) -	{ -	  closedir (directory); -	  directory = 0; -	} -      FREE (dirname); -      FREE (filename); -      FREE (ud); - -      if (text && *text) -        STRDUP (filename, text); -      else -	{ -	  filename = malloc(1);  -	  if (filename == 0) -	    return ((char *)NULL); -	  filename[0] = '\0'; -	} -      dirname = (text && *text) ? strdup (text) : strdup ("."); -      if (dirname == 0) -        return ((char *)NULL); - -      temp = strrchr (dirname, '/'); -      if (temp) -	{ -	  strcpy (filename, ++temp); -	  *temp = '\0'; -	} -      else -	{ -	  dirname[0] = '.'; -	  dirname[1] = '\0'; -	} - -      STRDUP (ud, dirname); -      udlen = strlen (ud); - -      rlfe_directory_completion_hook (&dirname); - -      directory = opendir (dirname); -      flen = strlen (filename); - -      rl_filename_completion_desired = 1; -    } - -  dentry = 0; -  while (directory && (dentry = readdir (directory))) -    { -      if (flen == 0) -	{ -          if (DOT_OR_DOTDOT(dentry->d_name) == 0) -            break; -	} -      else -	{ -	  if ((dentry->d_name[0] == filename[0]) && -	      (strlen (dentry->d_name) >= flen) && -	      (strncmp (filename, dentry->d_name, flen) == 0)) -	    break; -	} -    } - -  if (dentry == 0) -    { -      if (directory) -	{ -	  closedir (directory); -	  directory = 0; -	} -      FREE (dirname); -      FREE (filename); -      FREE (ud); -      dirname = filename = ud = 0; -      return ((char *)NULL); -    } - -  if (ud == 0 || (ud[0] == '.' && ud[1] == '\0')) -    temp = strdup (dentry->d_name); -  else -    { -      temp = malloc (1 + udlen + strlen (dentry->d_name)); -      strcpy (temp, ud); -      strcpy (temp + udlen, dentry->d_name); -    } -  return (temp); -}  | 
