to the readline library if it is present in the system.
+2003-03-16 Theodore Ts'o <tytso@mit.edu>
+
+ * configure.in: Check to see if libdl exists for the sake of dlopen
+
2003-03-14 Theodore Ts'o <tytso@mit.edu>
* configure.in: Add support for Apple/Darwin shared libraries.
AC_CHECK_LIB(socket, socket, [SOCKET_LIB=-lsocket])
AC_SUBST(SOCKET_LIB)
dnl
+dnl Check to see if libdl exists for the sake of dlopen
+dnl
+DLOPEN_LIB=''
+AC_CHECK_LIB(dl, dlopen,
+[DLOPEN_LIB=-ldl
+AC_DEFINE(HAVE_DLOPEN)])
+AC_SUBST(DLOPEN_LIB)
+dnl
dnl See if optreset exists
dnl
AC_MSG_CHECKING(for optreset)
Depends: e2fsprogs (= ${Source-Version}), ${misc:Depends}
Recommends: sash | zsh-static | busybox-static | zsh30-static
Architecture: any
-Description: A statically-linked version of the ext2 filesystem checker.
+Description: A statically-linked version of the ext2 filesystem checker
This may be of some help to you if your filesystem gets corrupted enough
to break the shared libraries used by the dynamically linked checker.
.
Suggests: doc-base
Conflicts: e2fsprogs (<< 1.10-6)
Architecture: any
-Description: The Common Error Description library - headers and static libraries.
+Description: The Common Error Description library - headers and static libraries
libcomerr is an attempt to present a common error-handling mechanism to
manipulate the most common form of error code in a fashion that does not
have the problems identified with mechanisms commonly in use.
Depends: ${libcdev:Depends}, libss2, ${misc:Depends}
Conflicts: e2fsprogs (<< 1.10-6)
Architecture: any
-Description: Command-line interface parsing library - headers and static libraries.
+Description: Command-line interface parsing library - headers and static libraries
This package includes a tool that parses a command table to generate
a simple command-line interface parser, the include files needed to
compile and use it, and the static libs.
Conflicts: e2fsprogs (<< 1.10-6)
Replaces: e2fslibs-dev (<< 1.15)
Architecture: any
-Description: Universally unique id library - headers and static libraries.
+Description: Universally unique id library - headers and static libraries
libuuid generates and parses 128-bit universally unique id's (UUID's),
using a standard which is blessed by both Microsoft and DCE, and is
being proposed as an internet standard. See the internet-draft:
.
for more information.
+Package: libblkid
+Section: libs
+Priority: required
+Depends: ${libcdev:Depends}
+Architecture: any
+Description: Block device id library
+ The blkid library which allows system programs like fsck and
+ mount to quickly and easily find block devices by filesystem UUID and
+ LABEL. This allows system administrators to avoid specifiying
+ filesystems by hard-coded device names, but via a logical naming
+ system instead.
+
+Package: libblkid-dev
+Section: devel
+Priority: extra
+Depends: libblkid (= ${Source-Version})
+Architecture: any
+Description: Block device id library - headers and static libraries
+ The blkid library which allows system programs like fsck and
+ mount to quickly and easily find block devices by filesystem UUID and
+ LABEL. This allows system administrators to avoid specifiying
+ filesystems by hard-coded device names, but via a logical naming
+ system instead.
+ .
+ This package contains the development environment for the blkid library.
+
Package: e2fsprogs-bf
Section: devel
Priority: extra
Package: e2fsprogs
Essential: yes
Pre-Depends: ${shlibs:Depends}
-Depends: ${misc:Depends}
+Depends: ${misc:Depends}, libblkid
Suggests: gpart, parted, e2fsck-static
Conflicts: e2fslibsg, dump (<< 0.4b4-4), quota (<< 1.55-8.1)
Provides: libcomerr2, libss2, libext2fs2, libe2p2, libuuid1
Architecture: any
-Description: The EXT2 file system utilities and libraries.
+Description: The EXT2 file system utilities and libraries
EXT2 stands for "Extended Filesystem", version 2. It's the main
filesystem type used for hard disks on Debian and other Linux systems.
.
Provides: ext2fs-dev, e2p-dev
Conflicts: e2fsprogs (<< 1.10-6)
Architecture: any
-Description: The headers and static libraries for ext2fs-aware tools-development.
+Description: The headers and static libraries for ext2fs-aware tools-development
EXT2FS stands for "Extended Filesystem", version 2. It's the filesystem
type used for hard disks on Debian and other Linux systems.
.
+2003-03-16 Theodore Ts'o <tytso@mit.edu>
+
+ * Makefile.in (DLOPEN_LIB): Link in the libdl library if it is
+ present on the system.
+
+ * debugfs.c (main): Call ss_get_readline() to attempt to pull in
+ the readline library.
+
2003-03-06 Theodore Tso <tytso@mit.edu>
* debugfs.c (do_open_filesys, do_show_super_stats),
top_builddir = ..
my_dir = debugfs
INSTALL = @INSTALL@
+DLOPEN_LIB = @DLOPEN_LIB@
@MCONFIG@
$(srcdir)/dump.c $(srcdir)/setsuper.c ${srcdir}/logdump.c \
$(srcdir)/htree.c
-LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID)
+LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
+ $(LIBUUID) $(DLOPEN_LIB)
DEPLIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) $(DEPLIBUUID)
.c.o:
ss_perror(sci_idx, retval, "creating invocation");
exit(1);
}
+ ss_get_readline(sci_idx);
(void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval);
if (retval) {
+2003-03-16 Theodore Ts'o <tytso@mit.edu>
+
+ * Makefile.in (DLOPEN_LIB): Include the dlopen library if it is
+ present on shared libraries.
+
+ * ss_internal.h: Add pointers to dynamic readline functions in the
+ ss_info data structure.
+
+ * listen.c (ss_listen): Use readline instead of fgets if the
+ readline library is present. Define helper functions to
+ provide command completion from the ss request tables.
+
+ * invocation.c (ss_create_invocation, ss_delete_invocation): If
+ HAVE_DLOPEN is defined, call ss_get_readline() to automatically
+ try to load the readline library.
+
+ * get_readline.c (ss_get_readline): New function which uses dlopen()
+ to dynamically load the readline library if it is present
+ on the system.
+
2002-11-09 Theodore Ts'o <tytso@mit.edu>
* Release of E2fsprogs 1.32
top_builddir = ../..
my_dir = lib/ss
INSTALL = @INSTALL@
+DLOPEN_LIB = @DLOPEN_LIB@
@MCONFIG@
DLL_VERSION = 1.0
DLL_IMAGE = libss
DLL_STUB = libss
-DLL_LIBS = -L../.. -lcom_err
+DLL_LIBS = -L../.. -lcom_err $(DLOPEN_LIB)
DLL_MYDIR = ss
DLL_INSTALL_DIR = $(root_libdir)
ELF_IMAGE = libss
ELF_MYDIR = ss
ELF_INSTALL_DIR = $(root_libdir)
-ELF_OTHER_LIBS = -L../.. -lcom_err
+ELF_OTHER_LIBS = -L../.. -lcom_err $(DLOPEN_LIB)
BSDLIB_VERSION = 1.0
BSDLIB_IMAGE = libss
@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) \
@DLL_CMT@ $(ALL_CFLAGS) -o jump/$*.o -c $<)
-@ELF_CMT@ $(CC) $(ALL_CFLAGS) -fPIC -o elfshared/$*.o -c $<
+@ELF_CMT@ $(CC) $(ALL_CFLAGS) -DSHARED_ELF_LIB -fPIC -o elfshared/$*.o -c $<
@BSDLIB_CMT@ $(CC) $(ALL_CFLAGS) -fpic -o pic/$*.o -c $<
# for the library
invocation.o help.o \
execute_cmd.o listen.o parse.o error.o prompt.o \
request_tbl.o list_rqs.o pager.o requests.o \
- data.o
+ data.o get_readline.o
SRCS= $(srcdir)/invocation.c $(srcdir)/help.c \
$(srcdir)/execute_cmd.c $(srcdir)/listen.c $(srcdir)/parse.c \
$(srcdir)/error.c $(srcdir)/prompt.c $(srcdir)/request_tbl.c \
$(srcdir)/list_rqs.c $(srcdir)/pager.c $(srcdir)/requests.c \
- $(srcdir)/data.c
+ $(srcdir)/data.c $(srcdir)/get_readline.c
all:: mk_cmds
--- /dev/null
+/*
+ * Copyright 2003 by MIT Student Information Processing Board
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose is hereby granted, provided that
+ * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. M.I.T. and the
+ * M.I.T. S.I.P.B. make no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ */
+
+#ifdef HAS_STDLIB_H
+#include <stdlib.h>
+#endif
+#include "ss_internal.h"
+#define size sizeof(ss_data *)
+#ifdef HAVE_DLOPEN
+#include <dlfcn.h>
+#endif
+
+static void ss_release_readline(ss_data *info)
+{
+#ifdef HAVE_DLOPEN
+ if (!info->readline_handle)
+ return;
+
+ info->readline = 0;
+ info->add_history = 0;
+ info->redisplay = 0;
+ info->rl_completion_matches = 0;
+ dlclose(info->readline_handle);
+ info->readline_handle = 0;
+#endif
+}
+
+void ss_get_readline(int sci_idx)
+{
+#ifdef HAVE_DLOPEN
+ void *handle;
+ ss_data *info = ss_info(sci_idx);
+ const char **t;
+ char **(**completion_func)(const char *, int, int);
+
+ if (info->readline_handle ||
+ getenv("SS_NO_READLINE") ||
+ ((handle = dlopen("libreadline.so", RTLD_NOW)) == NULL))
+ return;
+
+ info->readline_handle = handle;
+ info->readline = dlsym(handle, "readline");
+ info->add_history = dlsym(handle, "add_history");
+ info->redisplay = dlsym(handle, "rl_forced_update_display");
+ info->rl_completion_matches = dlsym(handle, "rl_completion_matches");
+ if ((t = dlsym(handle, "rl_readline_name")) != NULL)
+ *t = info->subsystem_name;
+ if ((completion_func =
+ dlsym(handle, "rl_attempted_completion_function")) != NULL)
+ *completion_func = ss_rl_completion;
+ info->readline_shutdown = ss_release_readline;
+#endif
+}
+
+
#endif
#include "ss_internal.h"
#define size sizeof(ss_data *)
+#ifdef HAVE_DLOPEN
+#include <dlfcn.h>
+#endif
int ss_create_invocation(subsystem_name, version_string, info_ptr,
request_table_ptr, code_ptr)
register int sci_idx;
register ss_data *new_table;
register ss_data **table;
+ void *handle;
*code_ptr = 0;
table = _ss_table;
(ss_request_table **) calloc(2, sizeof(ss_request_table *));
*(new_table->rqt_tables) = request_table_ptr;
*(new_table->rqt_tables+1) = (ss_request_table *) NULL;
+
+ new_table->readline_handle = 0;
+ new_table->readline = 0;
+ new_table->add_history = 0;
+ new_table->redisplay = 0;
+ new_table->rl_completion_matches = 0;
_ss_table = table;
+#if defined(HAVE_DLOPEN) && defined(SHARED_ELF_LIB)
+ ss_get_readline(sci_idx);
+#endif
return(sci_idx);
}
while(t->info_dirs[0] != (char *)NULL)
ss_delete_info_dir(sci_idx, t->info_dirs[0], &ignored_code);
free((char *)t->info_dirs);
+#if defined(HAVE_DLOPEN) && defined(SHARED_ELF_LIB)
+ if (t->readline_shutdown)
+ (*t->readline_shutdown)(t);
+#endif
free((char *)t);
}
}
}
#endif
- (void) fputs(current_info->prompt, stdout);
- (void) fflush(stdout);
+ if (current_info->redisplay)
+ (*current_info->redisplay)();
+ else {
+ (void) fputs(current_info->prompt, stdout);
+ (void) fflush(stdout);
+ }
}
static sigret_t listen_int_handler(int sig)
int code;
jmp_buf old_jmpb;
ss_data *old_info = current_info;
+ char *line;
current_info = info = ss_info(sci_idx);
sig_cont = (sigret_t (*)(int)) 0;
(void) sigsetmask(mask);
#endif
while(!info->abort) {
- print_prompt(0);
old_sig_cont = sig_cont;
sig_cont = signal(SIGCONT, print_prompt);
if (sig_cont == print_prompt)
sig_cont = old_sig_cont;
- if (fgets(input, BUFSIZ, stdin) != input) {
- code = SS_ET_EOF;
- (void) signal(SIGCONT, sig_cont);
- goto egress;
- }
- input[BUFSIZ-1] = 0;
+ if (info->readline) {
+ line = (*info->readline)(current_info->prompt);
+ } else {
+ print_prompt(0);
+ if (fgets(input, BUFSIZ, stdin) == input)
+ line = input;
+ else
+ line = NULL;
- cp = strchr(input, '\n');
+ input[BUFSIZ-1] = 0;
+ }
+ if (line == NULL) {
+ code = SS_ET_EOF;
+ (void) signal(SIGCONT, sig_cont);
+ goto egress;
+ }
+
+ cp = strchr(line, '\n');
if (cp) {
*cp = '\0';
- if (cp == input)
+ if (cp == line)
continue;
}
(void) signal(SIGCONT, sig_cont);
+ if (info->add_history)
+ (*info->add_history)(line);
- code = ss_execute_line (sci_idx, input);
+ code = ss_execute_line (sci_idx, line);
if (code == SS_ET_COMMAND_NOT_FOUND) {
- register char *c = input;
+ register char *c = line;
while (*c == ' ' || *c == '\t')
c++;
cp = strchr (c, ' ');
"Unknown request \"%s\". Type \"?\" for a request list.",
c);
}
+ if (info->readline)
+ free(line);
}
code = 0;
egress:
{
ss_abort_subsystem(sci_idx, 0);
}
+
+#ifdef HAVE_DLOPEN
+#define get_request(tbl,idx) ((tbl) -> requests + (idx))
+
+static char *cmd_generator(const char *text, int state)
+{
+ static int len;
+ static ss_request_table **rqtbl;
+ static int curr_rqt;
+ static char const * const * name;
+ ss_request_entry *request;
+ char *ret;
+
+ if (state == 0) {
+ len = strlen(text);
+ rqtbl = current_info->rqt_tables;
+ if (!rqtbl || !*rqtbl)
+ return 0;
+ curr_rqt = 0;
+ name = 0;
+ }
+
+ while (1) {
+ if (!name || !*name) {
+ request = get_request(*rqtbl, curr_rqt++);
+ name = request->command_names;
+ if (!name) {
+ rqtbl++;
+ if (*rqtbl) {
+ curr_rqt = 0;
+ continue;
+ } else
+ break;
+ }
+ }
+ if (strncmp(*name, text, len) == 0) {
+ ret = malloc(strlen(*name)+1);
+ if (ret)
+ strcpy(ret, *name);
+ name++;
+ return ret;
+ }
+ name++;
+ }
+
+ return 0;
+}
+
+char **ss_rl_completion(const char *text, int start, int end)
+{
+ if ((start == 0) && current_info->rl_completion_matches)
+ return (*current_info->rl_completion_matches)
+ (text, cmd_generator);
+ return 0;
+}
+#endif
+
int sci_idx, void *infop);
void ss_set_prompt(int sci_idx, char *new_prompt);
char *ss_get_prompt(int sci_idx);
+void ss_get_readline(int sci_idx);
#else
char *ss_name();
void ss_error ();
void ss_unimplemented();
void ss_set_prompt;
char *ss_get_prompt;
+void ss_get_readline();
#endif
extern ss_request_table ss_std_requests;
#endif /* _ss_h */
unsigned int escape_disabled : 1,
abbrevs_disabled : 1;
} flags;
+ /*
+ * Dynamic usage of readline library if present
+ */
+ void *readline_handle;
+ void (*readline_shutdown)(struct _ss_data *info);
+ char *(*readline)(const char *);
+ void (*add_history)(const char *);
+ void (*redisplay)();
+ char **(*rl_completion_matches)(const char *,
+ char *(*completer)(const char *, int));
/* to get out */
int abort; /* exit subsystem */
int exit_status;
void ss_list_requests PROTOTYPE((int, char const * const *, int, pointer));
int ss_execute_command PROTOTYPE((int sci_idx, char *argv[]));
int ss_pager_create(NOARGS);
+char **ss_rl_completion(const char *text, int start, int end);
extern ss_data **_ss_table;
extern char *ss_et_msgs[];