]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
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 606572e8418d3678842538b6ec52283c2f6e87d2..1656b939ef959f00ec5ba1fd3db409f065f98560 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 4047f49348695f18eb2b8b45850f051d134864f2..53bb7162365c550c923193ef6a2ceef35d18f5e7 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 91f9ff95e4a456be2b68a8a9a585b5b738642227..f5fe2e4096c822254e8bd342df54bd7b6afccda4 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 88583a613fcc74e407b083178f0888ef0c15852f..dc0a8399fba65ac01dd63a7a7c841f2acdd36715 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 6362a93b86220c1190d625d747e1feb12e81e0e2..1412f5697bab182260f5fde8f0a119e1d818ef70 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 a9a6c63ddb855762f118f6c8237c0912b53d03e5..e6bcdbae222c85fcedf4a9a352c72547b48063e1 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 214f5268c64e5aaae9324123aaccfd05513e0085..8a7c1c811486093117db5f4f87ee95ab8b5de1a4 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 38c2750d4098c2d64b2dbd9a84475b8a035973b3..19a4c9b67b0aa12f8c554dd8e9680f38828c2ada 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 81c70e48b87ba09665c7466a81c9b1b7ccd8eb97..748886fae1a2deff58f29bc0da69368912ce67f2 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 04b8302479ed119125c5499f5bac24ce70fece3f..073141832784032528399d3c93df36ca0ed72ebd 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 80f393ad9a7c57b9a9bc528f5f4b07264fff3218..805e1f14eefe3d4c9b5150c2ff0cbce38bb193b9 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 ab155864feb9f61f767af43d7a29fc58c19afc1e..ce84477d8e880909dacfe831b3ebaa3ad2213e04 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[];