Add to the ss (subsystem) library the ability to dynamically link

to the readline library if it is present in the system.
bitmap-optimize
Theodore Ts'o 2003-03-16 06:26:25 -05:00
parent 63182203a7
commit 3ae497eab2
13 changed files with 266 additions and 26 deletions

View File

@ -1,3 +1,7 @@
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.

View File

@ -625,6 +625,14 @@ SOCKET_LIB=''
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)

40
debian/control vendored
View File

@ -11,7 +11,7 @@ Priority: optional
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.
.
@ -28,7 +28,7 @@ Depends: ${libcdev:Depends}, libcomerr2, ${misc:Depends}
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.
@ -39,7 +39,7 @@ Priority: extra
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.
@ -53,7 +53,7 @@ Depends: ${libcdev:Depends}, e2fsprogs (= ${Source-Version}), ${misc:Depends}
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:
@ -62,6 +62,32 @@ Description: Universally unique id library - headers and static libraries.
.
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
@ -91,12 +117,12 @@ Description: A stripped-down versions of e2fsprogs, for debian-installer
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.
.
@ -111,7 +137,7 @@ Suggests: doc-base
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.
.

View File

@ -1,3 +1,11 @@
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),

View File

@ -8,6 +8,7 @@ VPATH = @srcdir@
top_builddir = ..
my_dir = debugfs
INSTALL = @INSTALL@
DLOPEN_LIB = @DLOPEN_LIB@
@MCONFIG@
@ -24,7 +25,8 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
$(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:

View File

@ -1576,6 +1576,7 @@ int main(int argc, char **argv)
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) {

View File

@ -1,3 +1,23 @@
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

View File

@ -8,6 +8,7 @@ VPATH = @srcdir@
top_builddir = ../..
my_dir = lib/ss
INSTALL = @INSTALL@
DLOPEN_LIB = @DLOPEN_LIB@
@MCONFIG@
@ -20,7 +21,7 @@ DLL_GOTSIZE = 0x1000
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)
@ -29,7 +30,7 @@ ELF_SO_VERSION = 2
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
@ -51,7 +52,7 @@ XTRA_CFLAGS=-DPOSIX_SIGNALS -I$(srcdir)/../et
@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
@ -65,13 +66,13 @@ OBJS= ss_err.o \
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

65
lib/ss/get_readline.c Normal file
View File

@ -0,0 +1,65 @@
/*
* 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
}

View File

@ -16,6 +16,9 @@
#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)
@ -27,6 +30,7 @@ int ss_create_invocation(subsystem_name, version_string, info_ptr,
register int sci_idx;
register ss_data *new_table;
register ss_data **table;
void *handle;
*code_ptr = 0;
table = _ss_table;
@ -66,7 +70,16 @@ int ss_create_invocation(subsystem_name, version_string, info_ptr,
(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);
}
@ -83,5 +96,9 @@ ss_delete_invocation(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);
}

View File

@ -48,8 +48,12 @@ static sigret_t print_prompt(int sig)
}
}
#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)
@ -73,6 +77,7 @@ int ss_listen (int sci_idx)
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;
@ -93,29 +98,40 @@ int ss_listen (int sci_idx)
(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, ' ');
@ -128,6 +144,8 @@ int ss_listen (int sci_idx)
"Unknown request \"%s\". Type \"?\" for a request list.",
c);
}
if (info->readline)
free(line);
}
code = 0;
egress:
@ -148,3 +166,60 @@ void ss_quit(int argc, const char * const *argv, int sci_idx, pointer infop)
{
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

View File

@ -85,6 +85,7 @@ void ss_unimplemented(int argc, const char * const *argv,
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 ();
@ -103,6 +104,7 @@ void ss_subsystem_version();
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 */

View File

@ -95,6 +95,16 @@ typedef struct _ss_data { /* init values */
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;
@ -116,6 +126,7 @@ void ss_page_stdin(NOARGS);
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[];