Whamcloud - gitweb
Add to the ss (subsystem) library the ability to dynamically link
authorTheodore Ts'o <tytso@mit.edu>
Sun, 16 Mar 2003 11:26:25 +0000 (06:26 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 16 Mar 2003 11:26:25 +0000 (06:26 -0500)
to the readline library if it is present in the system.

13 files changed:
ChangeLog
configure.in
debian/control
debugfs/ChangeLog
debugfs/Makefile.in
debugfs/debugfs.c
lib/ss/ChangeLog
lib/ss/Makefile.in
lib/ss/get_readline.c [new file with mode: 0644]
lib/ss/invocation.c
lib/ss/listen.c
lib/ss/ss.h
lib/ss/ss_internal.h

index 606572e..1656b93 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
index 4047f49..53bb716 100644 (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)
index 91f9ff9..f5fe2e4 100644 (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.
  .
index 88583a6..dc0a839 100644 (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), 
index 6362a93..1412f56 100644 (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:
index a9a6c63..e6bcdba 100644 (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) {
index 214f526..8a7c1c8 100644 (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
index 38c2750..19a4c9b 100644 (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
 
diff --git a/lib/ss/get_readline.c b/lib/ss/get_readline.c
new file mode 100644 (file)
index 0000000..2ec5ac2
--- /dev/null
@@ -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
+}
+
+       
index 81c70e4..748886f 100644 (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);
 }
index 04b8302..0731418 100644 (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
+
index 80f393a..805e1f1 100644 (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 */
index ab15586..ce84477 100644 (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[];