URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/VER_5_3/gdb-5.3/readline/examples
- from Rev 1182 to Rev 1765
- ↔ Reverse comparison
Rev 1182 → Rev 1765
/ChangeLog.gdb
0,0 → 1,10
2002-02-24 Elena Zannoni <ezannoni@redhat.com> |
|
* ChangeLog.gdb: Rename from ChangeLog.Cygnus. |
|
2000-07-09 Elena Zannoni <ezannoni@kwikemart.cygnus.com> |
|
* Import of readline 4.1. |
|
New files: excallback.c, rlfe.c. |
|
/Makefile.in
0,0 → 1,85
# |
# This is the Makefile for the readline examples subdirectory. |
# |
# Copyright (C) 1994 Free Software Foundation, Inc. |
|
# This 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. |
|
# This program is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU General Public License for more details. |
|
# You should have received a copy of the GNU General Public License |
# along with this program; if not, write to the Free Software |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
|
SHELL = @MAKE_SHELL@ |
RM = rm -f |
|
srcdir = @srcdir@ |
VPATH = .:@srcdir@ |
top_srcdir = @top_srcdir@ |
BUILD_DIR = . |
|
DEFS = @DEFS@ |
CC = @CC@ |
CFLAGS = @CFLAGS@ |
LOCAL_CFLAGS = @LOCAL_CFLAGS@ -DREADLINE_LIBRARY |
CPPFLAGS = @CPPFLAGS@ |
|
INCLUDES = -I$(srcdir) -I$(top_srcdir) -I.. |
|
CCFLAGS = $(DEFS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $(CFLAGS) |
LDFLAGS = -g -L.. |
|
READLINE_LIB = ../libreadline.a |
HISTORY_LIB = ../libhistory.a |
|
TERMCAP_LIB = @TERMCAP_LIB@ |
|
.c.o: |
${RM} $@ |
$(CC) $(CCFLAGS) -c $< |
|
EXECUTABLES = fileman rltest rl rlversion |
OBJECTS = fileman.o rltest.o rl.o rlversion.o |
|
all: $(EXECUTABLES) |
|
rl: rl.o |
$(CC) $(LDFLAGS) -o $@ rl.o -lreadline $(TERMCAP_LIB) |
|
fileman: fileman.o |
$(CC) $(LDFLAGS) -o $@ fileman.o -lreadline $(TERMCAP_LIB) |
|
rltest: rltest.o |
$(CC) $(LDFLAGS) -o $@ rltest.o -lreadline $(TERMCAP_LIB) |
|
rlversion: rlversion.o $(READLINE_LIB) |
$(CC) $(LDFLAGS) -o $@ rlversion.o -lreadline $(TERMCAP_LIB) |
|
clean mostlyclean: |
$(RM) $(OBJECTS) |
$(RM) $(EXECUTABLES) *.exe |
|
distclean maintainer-clean: clean |
$(RM) Makefile |
|
fileman.o: fileman.c |
rltest.o: rltest.c |
rl.o: rl.c |
rlversion.o: rlversion.c |
|
# Stuff for Per Bothner's `rlfe' program |
|
rlfe: rlfe.o $(READLINE_LIB) $(HISTORY_LIB) |
$(CC) $(LDFLAGS) -o $@ rlfe.o -lreadline -lhistory ${TERMCAP_LIB} |
|
rlfe.o: rlfe.c |
|
rlfe.o: $(top_srcdir)/readline.h |
rlfe.o: $(top_srcdir)/history.h |
/histexamp.c
0,0 → 1,82
main () |
{ |
char line[1024], *t; |
int len, done = 0; |
|
line[0] = 0; |
|
using_history (); |
while (!done) |
{ |
printf ("history$ "); |
fflush (stdout); |
t = fgets (line, sizeof (line) - 1, stdin); |
if (t && *t) |
{ |
len = strlen (t); |
if (t[len - 1] == '\n') |
t[len - 1] = '\0'; |
} |
|
if (!t) |
strcpy (line, "quit"); |
|
if (line[0]) |
{ |
char *expansion; |
int result; |
|
using_history (); |
|
result = history_expand (line, &expansion); |
if (result) |
fprintf (stderr, "%s\n", expansion); |
|
if (result < 0 || result == 2) |
{ |
free (expansion); |
continue; |
} |
|
add_history (expansion); |
strncpy (line, expansion, sizeof (line) - 1); |
free (expansion); |
} |
|
if (strcmp (line, "quit") == 0) |
done = 1; |
else if (strcmp (line, "save") == 0) |
write_history ("history_file"); |
else if (strcmp (line, "read") == 0) |
read_history ("history_file"); |
else if (strcmp (line, "list") == 0) |
{ |
register HIST_ENTRY **the_list; |
register int i; |
|
the_list = history_list (); |
if (the_list) |
for (i = 0; the_list[i]; i++) |
printf ("%d: %s\n", i + history_base, the_list[i]->line); |
} |
else if (strncmp (line, "delete", 6) == 0) |
{ |
int which; |
if ((sscanf (line + 6, "%d", &which)) == 1) |
{ |
HIST_ENTRY *entry = remove_history (which); |
if (!entry) |
fprintf (stderr, "No such entry %d\n", which); |
else |
{ |
free (entry->line); |
free (entry); |
} |
} |
else |
{ |
fprintf (stderr, "non-numeric arg given to `delete'\n"); |
} |
} |
} |
} |
/Inputrc
0,0 → 1,65
# My ~/.inputrc file is in -*- text -*- for easy editing with Emacs. |
# |
# Notice the various bindings which are conditionalized depending |
# on which program is running, or what terminal is active. |
# |
|
# In all programs, all terminals, make sure this is bound. |
"\C-x\C-r": re-read-init-file |
|
# Hp terminals (and some others) have ugly default behaviour for C-h. |
"\C-h": backward-delete-char |
"\e\C-h": backward-kill-word |
"\C-xd": dump-functions |
|
# In xterm windows, make the arrow keys do the right thing. |
$if TERM=xterm |
"\e[A": previous-history |
"\e[B": next-history |
"\e[C": forward-char |
"\e[D": backward-char |
|
# alternate arrow key prefix |
"\eOA": previous-history |
"\eOB": next-history |
"\eOC": forward-char |
"\eOD": backward-char |
|
# Under Xterm in Bash, we bind local Function keys to do something useful. |
$if Bash |
"\e[11~": "Function Key 1" |
"\e[12~": "Function Key 2" |
"\e[13~": "Function Key 3" |
"\e[14~": "Function Key 4" |
"\e[15~": "Function Key 5" |
|
# I know the following escape sequence numbers are 1 greater than |
# the function key. Don't ask me why, I didn't design the xterm terminal. |
"\e[17~": "Function Key 6" |
"\e[18~": "Function Key 7" |
"\e[19~": "Function Key 8" |
"\e[20~": "Function Key 9" |
"\e[21~": "Function Key 10" |
$endif |
$endif |
|
# For Bash, all terminals, add some Bash specific hacks. |
$if Bash |
"\C-xv": show-bash-version |
"\C-x\C-e": shell-expand-line |
|
# Here is one for editing my path. |
"\C-xp": "$PATH\C-x\C-e\C-e\"\C-aPATH=\":\C-b" |
|
# Make C-x r read my mail in emacs. |
# "\C-xr": "emacs -f rmail\C-j" |
$endif |
|
# For FTP, different hacks: |
$if Ftp |
"\C-xg": "get \M-?" |
"\C-xt": "put \M-?" |
"\M-.": yank-last-arg |
$endif |
|
" ": self-insert |
/rlversion.c
0,0 → 1,23
/* |
* rlversion -- print out readline's version number |
*/ |
|
#if defined (HAVE_CONFIG_H) |
# include <config.h> |
#endif |
|
#include <stdio.h> |
#include <sys/types.h> |
#include "posixstat.h" |
|
#ifdef READLINE_LIBRARY |
# include "readline.h" |
#else |
# include <readline/readline.h> |
#endif |
|
main() |
{ |
printf ("%s\n", rl_library_version ? rl_library_version : "unknown"); |
exit (0); |
} |
/manexamp.c
0,0 → 1,94
/* manexamp.c -- The examples which appear in the documentation are here. */ |
|
#include <stdio.h> |
#include <readline/readline.h> |
|
|
/* **************************************************************** */ |
/* */ |
* How to Emulate gets () */ |
/* */ |
/* **************************************************************** */ |
|
/* A static variable for holding the line. */ |
static char *line_read = (char *)NULL; |
|
/* Read a string, and return a pointer to it. Returns NULL on EOF. */ |
char * |
rl_gets () |
{ |
/* If the buffer has already been allocated, return the memory |
to the free pool. */ |
if (line_read) |
{ |
free (line_read); |
line_read = (char *)NULL; |
} |
|
/* Get a line from the user. */ |
line_read = readline (""); |
|
/* If the line has any text in it, save it on the history. */ |
if (line_read && *line_read) |
add_history (line_read); |
|
return (line_read); |
} |
|
/* **************************************************************** */ |
/* */ |
/* Writing a Function to be Called by Readline. */ |
/* */ |
/* **************************************************************** */ |
|
/* Invert the case of the COUNT following characters. */ |
invert_case_line (count, key) |
int count, key; |
{ |
register int start, end; |
|
start = rl_point; |
|
if (count < 0) |
{ |
direction = -1; |
count = -count; |
} |
else |
direction = 1; |
|
/* Find the end of the range to modify. */ |
end = start + (count * direction); |
|
/* Force it to be within range. */ |
if (end > rl_end) |
end = rl_end; |
else if (end < 0) |
end = -1; |
|
if (start > end) |
{ |
int temp = start; |
start = end; |
end = temp; |
} |
|
if (start == end) |
return; |
|
/* Tell readline that we are modifying the line, so save the undo |
information. */ |
rl_modifying (start, end); |
|
for (; start != end; start += direction) |
{ |
if (uppercase_p (rl_line_buffer[start])) |
rl_line_buffer[start] = to_lower (rl_line_buffer[start]); |
else if (lowercase_p (rl_line_buffer[start])) |
rl_line_buffer[start] = to_upper (rl_line_buffer[start]); |
} |
|
/* Move point to on top of the last character changed. */ |
rl_point = end - direction; |
} |
|
/rlfe.c
0,0 → 1,685
/* 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> |
|
#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 |
# 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 |
|
#define APPLICATION_NAME "Fep" |
|
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 |
|
#ifdef DEBUG |
FILE *logfile = NULL; |
#define DPRINT0(FMT) (fprintf(logfile, FMT), fflush(logfile)) |
#define DPRINT1(FMT, V1) (fprintf(logfile, FMT, V1), fflush(logfile)) |
#define DPRINT2(FMT, V1, V2) (fprintf(logfile, FMT, V1, V2), fflush(logfile)) |
#else |
#define DPRINT0(FMT) /* Do nothing */ |
#define DPRINT1(FMT, V1) /* Do nothing */ |
#define DPRINT2(FMT, V1, V2) /* Do nothing */ |
#endif |
|
struct termios orig_term; |
|
/* 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; |
} |
|
int |
main(int argc, char** argv) |
{ |
char *path; |
int i; |
int master; |
char *name; |
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; |
|
#ifdef DEBUG |
logfile = fopen("LOG", "w"); |
#endif |
|
rl_readline_name = APPLICATION_NAME; |
|
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[1], &argv[1]); |
} |
|
/* 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); |
|
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; |
|
/* 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); |
} |
} |
} |
/excallback.c
0,0 → 1,188
/* |
From: Jeff Solomon <jsolomon@stanford.edu> |
Date: Fri, 9 Apr 1999 10:13:27 -0700 (PDT) |
To: chet@po.cwru.edu |
Subject: new readline example |
Message-ID: <14094.12094.527305.199695@mrclean.Stanford.EDU> |
|
Chet, |
|
I've been using readline 4.0. Specifically, I've been using the perl |
version Term::ReadLine::Gnu. It works great. |
|
Anyway, I've been playing around the alternate interface and I wanted |
to contribute a little C program, callback.c, to you that you could |
use as an example of the alternate interface in the /examples |
directory of the readline distribution. |
|
My example shows how, using the alternate interface, you can |
interactively change the prompt (which is very nice imo). Also, I |
point out that you must roll your own terminal setting when using the |
alternate interface because readline depreps (using your parlance) the |
terminal while in the user callback. I try to demostrate what I mean |
with an example. I've included the program below. |
|
To compile, I just put the program in the examples directory and made |
the appropriate changes to the EXECUTABLES and OBJECTS line and added |
an additional target 'callback'. |
|
I compiled on my Sun Solaris2.6 box using Sun's cc. |
|
Let me know what you think. |
|
Jeff |
*/ |
|
#if defined (HAVE_CONFIG_H) |
#include <config.h> |
#endif |
|
#include <stdio.h> |
#include <sys/types.h> |
|
#ifdef HAVE_UNISTD_H |
#include <unistd.h> |
#endif |
|
#include <termios.h> /* xxx - should make this more general */ |
|
#ifdef READLINE_LIBRARY |
# include "readline.h" |
#else |
# include <readline/readline.h> |
#endif |
|
/* This little examples demonstrates the alternate interface to using readline. |
* In the alternate interface, the user maintains control over program flow and |
* only calls readline when STDIN is readable. Using the alternate interface, |
* you can do anything else while still using readline (like talking to a |
* network or another program) without blocking. |
* |
* Specifically, this program highlights two importants features of the |
* alternate interface. The first is the ability to interactively change the |
* prompt, which can't be done using the regular interface since rl_prompt is |
* read-only. |
* |
* The second feature really highlights a subtle point when using the alternate |
* interface. That is, readline will not alter the terminal when inside your |
* callback handler. So let's so, your callback executes a user command that |
* takes a non-trivial amount of time to complete (seconds). While your |
* executing the command, the user continues to type keystrokes and expects them |
* to be re-echoed on the new prompt when it returns. Unfortunately, the default |
* terminal configuration doesn't do this. After the prompt returns, the user |
* must hit one additional keystroke and then will see all of his previous |
* keystrokes. To illustrate this, compile and run this program. Type "sleep" at |
* the prompt and then type "bar" before the prompt returns (you have 3 |
* seconds). Notice how "bar" is re-echoed on the prompt after the prompt |
* returns? This is what you expect to happen. Now comment out the 4 lines below |
* the line that says COMMENT LINE BELOW. Recompile and rerun the program and do |
* the same thing. When the prompt returns, you should not see "bar". Now type |
* "f", see how "barf" magically appears? This behavior is un-expected and not |
* desired. |
*/ |
|
void process_line(char *line); |
int change_prompt(void); |
char *get_prompt(void); |
|
int prompt = 1; |
char prompt_buf[40], line_buf[256]; |
tcflag_t old_lflag; |
cc_t old_vtime; |
struct termios term; |
|
int |
main() |
{ |
fd_set fds; |
|
/* Adjust the terminal slightly before the handler is installed. Disable |
* canonical mode processing and set the input character time flag to be |
* non-blocking. |
*/ |
if( tcgetattr(STDIN_FILENO, &term) < 0 ) { |
perror("tcgetattr"); |
exit(1); |
} |
old_lflag = term.c_lflag; |
old_vtime = term.c_cc[VTIME]; |
term.c_lflag &= ~ICANON; |
term.c_cc[VTIME] = 1; |
/* COMMENT LINE BELOW - see above */ |
if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) { |
perror("tcsetattr"); |
exit(1); |
} |
|
rl_add_defun("change-prompt", change_prompt, CTRL('t')); |
rl_callback_handler_install(get_prompt(), process_line); |
|
while(1) { |
FD_ZERO(&fds); |
FD_SET(fileno(stdin), &fds); |
|
if( select(FD_SETSIZE, &fds, NULL, NULL, NULL) < 0) { |
perror("select"); |
exit(1); |
} |
|
if( FD_ISSET(fileno(stdin), &fds) ) { |
rl_callback_read_char(); |
} |
} |
} |
|
void |
process_line(char *line) |
{ |
if( line == NULL ) { |
fprintf(stderr, "\n", line); |
|
/* reset the old terminal setting before exiting */ |
term.c_lflag = old_lflag; |
term.c_cc[VTIME] = old_vtime; |
if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 ) { |
perror("tcsetattr"); |
exit(1); |
} |
exit(0); |
} |
|
if( strcmp(line, "sleep") == 0 ) { |
sleep(3); |
} else { |
fprintf(stderr, "|%s|\n", line); |
} |
|
free (line); |
} |
|
int |
change_prompt(void) |
{ |
/* toggle the prompt variable */ |
prompt = !prompt; |
|
/* save away the current contents of the line */ |
strcpy(line_buf, rl_line_buffer); |
|
/* install a new handler which will change the prompt and erase the current line */ |
rl_callback_handler_install(get_prompt(), process_line); |
|
/* insert the old text on the new line */ |
rl_insert_text(line_buf); |
|
/* redraw the current line - this is an undocumented function. It invokes the |
* redraw-current-line command. |
*/ |
rl_refresh_line(0, 0); |
} |
|
char * |
get_prompt(void) |
{ |
/* The prompts can even be different lengths! */ |
sprintf(prompt_buf, "%s", |
prompt ? "Hit ctrl-t to toggle prompt> " : "Pretty cool huh?> "); |
return prompt_buf; |
} |
/fileman.c
0,0 → 1,458
/* fileman.c -- A tiny application which demonstrates how to use the |
GNU Readline library. This application interactively allows users |
to manipulate files and their modes. */ |
|
#ifdef HAVE_CONFIG_H |
# include <config.h> |
#endif |
|
#include <sys/types.h> |
#ifdef HAVE_SYS_FILE_H |
# include <sys/file.h> |
#endif |
#include <sys/stat.h> |
|
#ifdef HAVE_UNISTD_H |
# include <unistd.h> |
#endif |
|
#include <fcntl.h> |
#include <stdio.h> |
#include <errno.h> |
|
#if defined (HAVE_STRING_H) |
# include <string.h> |
#else /* !HAVE_STRING_H */ |
# include <strings.h> |
#endif /* !HAVE_STRING_H */ |
|
#ifdef HAVE_STDLIB_H |
# include <stdlib.h> |
#endif |
|
#ifdef READLINE_LIBRARY |
# include "readline.h" |
# include "history.h" |
#else |
# include <readline/readline.h> |
# include <readline/history.h> |
#endif |
|
extern char *xmalloc (); |
|
/* The names of functions that actually do the manipulation. */ |
int com_list (), com_view (), com_rename (), com_stat (), com_pwd (); |
int com_delete (), com_help (), com_cd (), com_quit (); |
|
/* A structure which contains information on the commands this program |
can understand. */ |
|
typedef struct { |
char *name; /* User printable name of the function. */ |
Function *func; /* Function to call to do the job. */ |
char *doc; /* Documentation for this function. */ |
} COMMAND; |
|
COMMAND commands[] = { |
{ "cd", com_cd, "Change to directory DIR" }, |
{ "delete", com_delete, "Delete FILE" }, |
{ "help", com_help, "Display this text" }, |
{ "?", com_help, "Synonym for `help'" }, |
{ "list", com_list, "List files in DIR" }, |
{ "ls", com_list, "Synonym for `list'" }, |
{ "pwd", com_pwd, "Print the current working directory" }, |
{ "quit", com_quit, "Quit using Fileman" }, |
{ "rename", com_rename, "Rename FILE to NEWNAME" }, |
{ "stat", com_stat, "Print out statistics on FILE" }, |
{ "view", com_view, "View the contents of FILE" }, |
{ (char *)NULL, (Function *)NULL, (char *)NULL } |
}; |
|
/* Forward declarations. */ |
char *stripwhite (); |
COMMAND *find_command (); |
|
/* The name of this program, as taken from argv[0]. */ |
char *progname; |
|
/* When non-zero, this global means the user is done using this program. */ |
int done; |
|
char * |
dupstr (s) |
char *s; |
{ |
char *r; |
|
r = xmalloc (strlen (s) + 1); |
strcpy (r, s); |
return (r); |
} |
|
main (argc, argv) |
int argc; |
char **argv; |
{ |
char *line, *s; |
|
progname = argv[0]; |
|
initialize_readline (); /* Bind our completer. */ |
|
/* Loop reading and executing lines until the user quits. */ |
for ( ; done == 0; ) |
{ |
line = readline ("FileMan: "); |
|
if (!line) |
break; |
|
/* Remove leading and trailing whitespace from the line. |
Then, if there is anything left, add it to the history list |
and execute it. */ |
s = stripwhite (line); |
|
if (*s) |
{ |
add_history (s); |
execute_line (s); |
} |
|
free (line); |
} |
exit (0); |
} |
|
/* Execute a command line. */ |
int |
execute_line (line) |
char *line; |
{ |
register int i; |
COMMAND *command; |
char *word; |
|
/* Isolate the command word. */ |
i = 0; |
while (line[i] && whitespace (line[i])) |
i++; |
word = line + i; |
|
while (line[i] && !whitespace (line[i])) |
i++; |
|
if (line[i]) |
line[i++] = '\0'; |
|
command = find_command (word); |
|
if (!command) |
{ |
fprintf (stderr, "%s: No such command for FileMan.\n", word); |
return (-1); |
} |
|
/* Get argument to command, if any. */ |
while (whitespace (line[i])) |
i++; |
|
word = line + i; |
|
/* Call the function. */ |
return ((*(command->func)) (word)); |
} |
|
/* Look up NAME as the name of a command, and return a pointer to that |
command. Return a NULL pointer if NAME isn't a command name. */ |
COMMAND * |
find_command (name) |
char *name; |
{ |
register int i; |
|
for (i = 0; commands[i].name; i++) |
if (strcmp (name, commands[i].name) == 0) |
return (&commands[i]); |
|
return ((COMMAND *)NULL); |
} |
|
/* Strip whitespace from the start and end of STRING. Return a pointer |
into STRING. */ |
char * |
stripwhite (string) |
char *string; |
{ |
register char *s, *t; |
|
for (s = string; whitespace (*s); s++) |
; |
|
if (*s == 0) |
return (s); |
|
t = s + strlen (s) - 1; |
while (t > s && whitespace (*t)) |
t--; |
*++t = '\0'; |
|
return s; |
} |
|
/* **************************************************************** */ |
/* */ |
/* Interface to Readline Completion */ |
/* */ |
/* **************************************************************** */ |
|
char *command_generator (); |
char **fileman_completion (); |
|
/* Tell the GNU Readline library how to complete. We want to try to complete |
on command names if this is the first word in the line, or on filenames |
if not. */ |
initialize_readline () |
{ |
/* Allow conditional parsing of the ~/.inputrc file. */ |
rl_readline_name = "FileMan"; |
|
/* Tell the completer that we want a crack first. */ |
rl_attempted_completion_function = (CPPFunction *)fileman_completion; |
} |
|
/* Attempt to complete on the contents of TEXT. START and END bound the |
region of rl_line_buffer that contains the word to complete. TEXT is |
the word to complete. We can use the entire contents of rl_line_buffer |
in case we want to do some simple parsing. Return the array of matches, |
or NULL if there aren't any. */ |
char ** |
fileman_completion (text, start, end) |
char *text; |
int start, end; |
{ |
char **matches; |
|
matches = (char **)NULL; |
|
/* If this word is at the start of the line, then it is a command |
to complete. Otherwise it is the name of a file in the current |
directory. */ |
if (start == 0) |
matches = completion_matches (text, command_generator); |
|
return (matches); |
} |
|
/* Generator function for command completion. STATE lets us know whether |
to start from scratch; without any state (i.e. STATE == 0), then we |
start at the top of the list. */ |
char * |
command_generator (text, state) |
char *text; |
int state; |
{ |
static int list_index, len; |
char *name; |
|
/* If this is a new word to complete, initialize now. This includes |
saving the length of TEXT for efficiency, and initializing the index |
variable to 0. */ |
if (!state) |
{ |
list_index = 0; |
len = strlen (text); |
} |
|
/* Return the next name which partially matches from the command list. */ |
while (name = commands[list_index].name) |
{ |
list_index++; |
|
if (strncmp (name, text, len) == 0) |
return (dupstr(name)); |
} |
|
/* If no names matched, then return NULL. */ |
return ((char *)NULL); |
} |
|
/* **************************************************************** */ |
/* */ |
/* FileMan Commands */ |
/* */ |
/* **************************************************************** */ |
|
/* String to pass to system (). This is for the LIST, VIEW and RENAME |
commands. */ |
static char syscom[1024]; |
|
/* List the file(s) named in arg. */ |
com_list (arg) |
char *arg; |
{ |
if (!arg) |
arg = ""; |
|
sprintf (syscom, "ls -FClg %s", arg); |
return (system (syscom)); |
} |
|
com_view (arg) |
char *arg; |
{ |
if (!valid_argument ("view", arg)) |
return 1; |
|
#if defined (__MSDOS__) |
/* more.com doesn't grok slashes in pathnames */ |
sprintf (syscom, "less %s", arg); |
#else |
sprintf (syscom, "more %s", arg); |
#endif |
return (system (syscom)); |
} |
|
com_rename (arg) |
char *arg; |
{ |
too_dangerous ("rename"); |
return (1); |
} |
|
com_stat (arg) |
char *arg; |
{ |
struct stat finfo; |
|
if (!valid_argument ("stat", arg)) |
return (1); |
|
if (stat (arg, &finfo) == -1) |
{ |
perror (arg); |
return (1); |
} |
|
printf ("Statistics for `%s':\n", arg); |
|
printf ("%s has %d link%s, and is %d byte%s in length.\n", |
arg, |
finfo.st_nlink, |
(finfo.st_nlink == 1) ? "" : "s", |
finfo.st_size, |
(finfo.st_size == 1) ? "" : "s"); |
printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime)); |
printf (" Last access at: %s", ctime (&finfo.st_atime)); |
printf (" Last modified at: %s", ctime (&finfo.st_mtime)); |
return (0); |
} |
|
com_delete (arg) |
char *arg; |
{ |
too_dangerous ("delete"); |
return (1); |
} |
|
/* Print out help for ARG, or for all of the commands if ARG is |
not present. */ |
com_help (arg) |
char *arg; |
{ |
register int i; |
int printed = 0; |
|
for (i = 0; commands[i].name; i++) |
{ |
if (!*arg || (strcmp (arg, commands[i].name) == 0)) |
{ |
printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); |
printed++; |
} |
} |
|
if (!printed) |
{ |
printf ("No commands match `%s'. Possibilties are:\n", arg); |
|
for (i = 0; commands[i].name; i++) |
{ |
/* Print in six columns. */ |
if (printed == 6) |
{ |
printed = 0; |
printf ("\n"); |
} |
|
printf ("%s\t", commands[i].name); |
printed++; |
} |
|
if (printed) |
printf ("\n"); |
} |
return (0); |
} |
|
/* Change to the directory ARG. */ |
com_cd (arg) |
char *arg; |
{ |
if (chdir (arg) == -1) |
{ |
perror (arg); |
return 1; |
} |
|
com_pwd (""); |
return (0); |
} |
|
/* Print out the current working directory. */ |
com_pwd (ignore) |
char *ignore; |
{ |
char dir[1024], *s; |
|
s = getcwd (dir, sizeof(dir) - 1); |
if (s == 0) |
{ |
printf ("Error getting pwd: %s\n", dir); |
return 1; |
} |
|
printf ("Current directory is %s\n", dir); |
return 0; |
} |
|
/* The user wishes to quit using this program. Just set DONE non-zero. */ |
com_quit (arg) |
char *arg; |
{ |
done = 1; |
return (0); |
} |
|
/* Function which tells you that you can't do this. */ |
too_dangerous (caller) |
char *caller; |
{ |
fprintf (stderr, |
"%s: Too dangerous for me to distribute. Write it yourself.\n", |
caller); |
} |
|
/* Return non-zero if ARG is a valid argument for CALLER, else print |
an error message and return zero. */ |
int |
valid_argument (caller, arg) |
char *caller, *arg; |
{ |
if (!arg || !*arg) |
{ |
fprintf (stderr, "%s: Argument required.\n", caller); |
return (0); |
} |
|
return (1); |
} |
/rl.c
0,0 → 1,131
/* |
* rl - command-line interface to read a line from the standard input |
* (or another fd) using readline. |
* |
* usage: rl [-p prompt] [-u unit] [-d default] [-n nchars] |
*/ |
|
#if defined (HAVE_CONFIG_H) |
# include <config.h> |
#endif |
|
#include <stdio.h> |
#include <sys/types.h> |
#include "posixstat.h" |
|
#if defined (READLINE_LIBRARY) |
# include "readline.h" |
# include "history.h" |
#else |
# include <readline/readline.h> |
# include <readline/history.h> |
#endif |
|
extern int optind; |
extern char *optarg; |
|
#if !defined (strchr) && !defined (__STDC__) |
extern char *strrchr(); |
#endif |
|
static char *progname; |
static char *deftext; |
|
static int |
set_deftext () |
{ |
if (deftext) |
{ |
rl_insert_text (deftext); |
deftext = (char *)NULL; |
rl_startup_hook = (Function *)NULL; |
} |
return 0; |
} |
|
static void |
usage() |
{ |
fprintf (stderr, "%s: usage: %s [-p prompt] [-u unit] [-d default] [-n nchars]\n", |
progname, progname); |
} |
|
int |
main (argc, argv) |
int argc; |
char **argv; |
{ |
char *temp, *prompt; |
struct stat sb; |
int opt, fd, nch; |
FILE *ifp; |
|
progname = strrchr(argv[0], '/'); |
if (progname == 0) |
progname = argv[0]; |
else |
progname++; |
|
/* defaults */ |
prompt = "readline$ "; |
fd = nch = 0; |
deftext = (char *)0; |
|
while ((opt = getopt(argc, argv, "p:u:d:n:")) != EOF) |
{ |
switch (opt) |
{ |
case 'p': |
prompt = optarg; |
break; |
case 'u': |
fd = atoi(optarg); |
if (fd < 0) |
{ |
fprintf (stderr, "%s: bad file descriptor `%s'\n", progname, optarg); |
exit (2); |
} |
break; |
case 'd': |
deftext = optarg; |
break; |
case 'n': |
nch = atoi(optarg); |
if (nch < 0) |
{ |
fprintf (stderr, "%s: bad value for -n: `%s'\n", progname, optarg); |
exit (2); |
} |
break; |
default: |
usage (); |
exit (2); |
} |
} |
|
if (fd != 0) |
{ |
if (fstat (fd, &sb) < 0) |
{ |
fprintf (stderr, "%s: %d: bad file descriptor\n", progname, fd); |
exit (1); |
} |
ifp = fdopen (fd, "r"); |
rl_instream = ifp; |
} |
|
if (deftext && *deftext) |
rl_startup_hook = set_deftext; |
|
if (nch > 0) |
rl_num_chars_to_read = nch; |
|
temp = readline (prompt); |
|
/* Test for EOF. */ |
if (temp == 0) |
exit (1); |
|
puts (temp); |
exit (0); |
} |
/rltest.c
0,0 → 1,67
/* **************************************************************** */ |
/* */ |
/* Testing Readline */ |
/* */ |
/* **************************************************************** */ |
|
#if defined (HAVE_CONFIG_H) |
#include <config.h> |
#endif |
|
#include <stdio.h> |
#include <sys/types.h> |
|
#ifdef READLINE_LIBRARY |
# include "readline.h" |
# include "history.h" |
#else |
# include <readline/readline.h> |
# include <readline/history.h> |
#endif |
|
extern HIST_ENTRY **history_list (); |
|
main () |
{ |
char *temp, *prompt; |
int done; |
|
temp = (char *)NULL; |
prompt = "readline$ "; |
done = 0; |
|
while (!done) |
{ |
temp = readline (prompt); |
|
/* Test for EOF. */ |
if (!temp) |
exit (1); |
|
/* If there is anything on the line, print it and remember it. */ |
if (*temp) |
{ |
fprintf (stderr, "%s\r\n", temp); |
add_history (temp); |
} |
|
/* Check for `command' that we handle. */ |
if (strcmp (temp, "quit") == 0) |
done = 1; |
|
if (strcmp (temp, "list") == 0) |
{ |
HIST_ENTRY **list; |
register int i; |
|
list = history_list (); |
if (list) |
{ |
for (i = 0; list[i]; i++) |
fprintf (stderr, "%d: %s\r\n", i, list[i]->line); |
} |
} |
free (temp); |
} |
exit (0); |
} |