diff options
Diffstat (limited to 'readline/examples/rl-fgets.c')
-rw-r--r-- | readline/examples/rl-fgets.c | 374 |
1 files changed, 0 insertions, 374 deletions
diff --git a/readline/examples/rl-fgets.c b/readline/examples/rl-fgets.c deleted file mode 100644 index 5512b94..0000000 --- a/readline/examples/rl-fgets.c +++ /dev/null @@ -1,374 +0,0 @@ -/* -Date: Tue, 16 Mar 2004 19:38:40 -0800 -From: Harold Levy <Harold.Levy@synopsys.com> -Subject: fgets(stdin) --> readline() redirector -To: chet@po.cwru.edu - -Hi Chet, - -Here is something you may find useful enough to include in the readline -distribution. It is a shared library that redirects calls to fgets(stdin) -to readline() via LD_PRELOAD, and it supports a custom prompt and list of -command names. Many people have asked me for this file, so I thought I'd -pass it your way in hope of just including it with readline to begin with. - -Best Regards, - --Harold -*/ - -/****************************************************************************** -******************************************************************************* - - FILE NAME: fgets.c TARGET: libfgets.so - AUTHOR: Harold Levy VERSION: 1.0 - hlevy@synopsys.com - - ABSTRACT: Customize fgets() behavior via LD_PRELOAD in the following ways: - - -- If fgets(stdin) is called, redirect to GNU readline() to obtain - command-line editing, file-name completion, history, etc. - - -- A list of commands for command-name completion can be configured by - setting the environment-variable FGETS_COMMAND_FILE to a file containing - the list of commands to be used. - - -- Command-line editing with readline() works best when the prompt string - is known; you can set this with the FGETS_PROMPT environment variable. - - -- There special strings that libfgets will interpret as internal commands: - - _fgets_reset_ reset the command list - - _fgets_dump_ dump status - - _fgets_debug_ toggle debug messages - - HOW TO BUILD: Here are examples of how to build libfgets.so on various - platforms; you will have to add -I and -L flags to configure access to - the readline header and library files. - - (32-bit builds with gcc) - AIX: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldl -lreadline -ltermcap - HP-UX: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldld -lreadline - Linux: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldl -lreadline - SunOS: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldl -lgen -lreadline - - (64-bit builds without gcc) - SunOS: SUNWspro/bin/cc -D_LARGEFILE64_SOURCE=1 -xtarget=ultra -xarch=v9 \ - -KPIC fgets.c -Bdynamic -lc -ldl -lgen -ltermcap -lreadline - - HOW TO USE: Different operating systems have different levels of support - for the LD_PRELOAD concept. The generic method for 32-bit platforms is to - put libtermcap.so, libfgets.so, and libreadline.so (with absolute paths) - in the LD_PRELOAD environment variable, and to put their parent directories - in the LD_LIBRARY_PATH environment variable. Unfortunately there is no - generic method for 64-bit platforms; e.g. for 64-bit SunOS, you would have - to build both 32-bit and 64-bit libfgets and libreadline libraries, and - use the LD_FLAGS_32 and LD_FLAGS_64 environment variables with preload and - library_path configurations (a mix of 32-bit and 64-bit calls are made under - 64-bit SunOS). - - EXAMPLE WRAPPER: Here is an example shell script wrapper around the - program "foo" that uses fgets() for command-line input: - - #!/bin/csh - #### replace this with the libtermcap.so directory: - set dir1 = "/usr/lib" - #### replace this with the libfgets.so directory: - set dir2 = "/usr/fgets" - #### replace this with the libreadline.so directory: - set dir3 = "/usr/local/lib" - set lib1 = "${dir1}/libtermcap.so" - set lib2 = "${dir2}/libfgets.so" - set lib3 = "${dir3}/libreadline.so" - if ( "${?LD_PRELOAD}" ) then - setenv LD_PRELOAD "${lib1}:${lib2}:${lib3}:${LD_PRELOAD}" - else - setenv LD_PRELOAD "${lib1}:${lib2}:${lib3}" - endif - if ( "${?LD_LIBRARY_PATH}" ) then - setenv LD_LIBRARY_PATH "${dir1}:${dir2}:${dir3}:${LD_LIBRARY_PATH}" - else - setenv LD_LIBRARY_PATH "${dir1}:${dir2}:${dir3}" - endif - setenv FGETS_COMMAND_FILE "${dir2}/foo.commands" - setenv FGETS_PROMPT "foo> " - exec "foo" $* - - Copyright (C)©2003-2004 Harold Levy. - - This code links to the GNU readline library, and as such is bound by 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. - - The GNU General Public License is often shipped with GNU software, and is - generally kept in a file called COPYING or LICENSE. If you do not have a - copy of the license, write to the Free Software Foundation, 59 Temple Place, - Suite 330, Boston, MA 02111 USA. - - 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. - -******************************************************************************* -******************************************************************************/ - - - -#include <dlfcn.h> -#include <stdio.h> -#include <strings.h> -#include <stdlib.h> -#include <unistd.h> - -#include <readline/readline.h> -#include <readline/history.h> - - - -/* for dynamically connecting to the native fgets() */ -#if defined(RTLD_NEXT) -#define REAL_LIBC RTLD_NEXT -#else -#define REAL_LIBC ((void *) -1L) -#endif -typedef char * ( * fgets_t ) ( char * s, int n, FILE * stream ) ; - - - -/* private data */ -/* -- writeable data is stored in the shared library's data segment - -- every process that uses the shared library gets a private memory copy of - its entire data segment - -- static data in the shared library is not copied to the application - -- only read-only (i.e. 'const') data is stored in the shared library's - text segment -*/ -static char ** my_fgets_names = NULL ; -static int my_fgets_number_of_names = 0 ; -static int my_fgets_debug_flag = 0 ; - - - -/* invoked with _fgets_reset_ */ -static void -my_fgets_reset ( - void -) { - if ( my_fgets_names && (my_fgets_number_of_names > 0) ) { - int i ; - if ( my_fgets_debug_flag ) { - printf ( "libfgets: removing command list\n" ) ; - } - for ( i = 0 ; i < my_fgets_number_of_names ; i ++ ) { - if ( my_fgets_names[i] ) free ( my_fgets_names[i] ) ; - } - free ( my_fgets_names ) ; - } - my_fgets_names = NULL ; - my_fgets_number_of_names = 0 ; -} - - - -/* invoked with _fgets_dump_ */ -static void -my_fgets_dump ( - void -) { - char * s ; - printf ( "\n" ) ; - s = getenv ( "FGETS_PROMPT" ) ; - printf ( "FGETS_PROMPT = %s\n", s ? s : "" ) ; - s = getenv ( "FGETS_COMMAND_FILE" ) ; - printf ( "FGETS_COMMAND_FILE = %s\n", s ? s : "" ) ; - printf ( "debug flag = %d\n", my_fgets_debug_flag ) ; - printf ( "#commands = %d\n", my_fgets_number_of_names ) ; - if ( my_fgets_debug_flag ) { - if ( my_fgets_names && (my_fgets_number_of_names > 0) ) { - int i ; - for ( i = 0 ; i < my_fgets_number_of_names ; i ++ ) { - printf ( "%s\n", my_fgets_names[i] ) ; - } - } - } - printf ( "\n" ) ; -} - - - -/* invoked with _fgets_debug_ */ -static void -my_fgets_debug_toggle ( - void -) { - my_fgets_debug_flag = my_fgets_debug_flag ? 0 : 1 ; - if ( my_fgets_debug_flag ) { - printf ( "libfgets: debug flag = %d\n", my_fgets_debug_flag ) ; - } -} - - - -/* read the command list if needed, return the i-th name */ -static char * -my_fgets_lookup ( - int index -) { - if ( (! my_fgets_names) || (! my_fgets_number_of_names) ) { - char * fname ; - FILE * fp ; - fgets_t _fgets ; - int i ; - char buf1[256], buf2[256] ; - fname = getenv ( "FGETS_COMMAND_FILE" ) ; - if ( ! fname ) { - if ( my_fgets_debug_flag ) { - printf ( "libfgets: empty or unset FGETS_COMMAND_FILE\n" ) ; - } - return NULL ; - } - fp = fopen ( fname, "r" ) ; - if ( ! fp ) { - if ( my_fgets_debug_flag ) { - printf ( "libfgets: cannot open '%s' for reading\n", fname ) ; - } - return NULL ; - } - _fgets = (fgets_t) dlsym ( REAL_LIBC, "fgets" ) ; - if ( ! _fgets ) { - fprintf ( stderr, - "libfgets: failed to dynamically link to native fgets()\n" - ) ; - return NULL ; - } - for ( i = 0 ; _fgets(buf1,255,fp) ; i ++ ) ; - if ( ! i ) { fclose(fp) ; return NULL ; } - my_fgets_names = (char**) calloc ( i, sizeof(char*) ) ; - rewind ( fp ) ; - i = 0 ; - while ( _fgets(buf1,255,fp) ) { - buf1[255] = 0 ; - if ( 1 == sscanf(buf1,"%s",buf2) ) { - my_fgets_names[i] = strdup(buf2) ; - i ++ ; - } - } - fclose ( fp ) ; - my_fgets_number_of_names = i ; - if ( my_fgets_debug_flag ) { - printf ( "libfgets: successfully read %d commands\n", i ) ; - } - } - if ( index < my_fgets_number_of_names ) { - return my_fgets_names[index] ; - } else { - return NULL ; - } -} - - - -/* generate a list of partial name matches for readline() */ -static char * -my_fgets_generator ( - const char * text, - int state -) -{ - static int list_index, len ; - char * name ; - if ( ! state ) { - list_index = 0 ; - len = strlen ( text ) ; - } - while ( ( name = my_fgets_lookup(list_index) ) ) { - list_index ++ ; - if ( ! strncmp ( name, text, len ) ) { - return ( strdup ( name ) ) ; - } - } - return ( NULL ) ; -} - - - -/* partial name completion callback for readline() */ -static char ** -my_fgets_completion ( - const char * text, - int start, - int end -) -{ - char ** matches ; - matches = NULL ; - if ( ! start ) { - matches = rl_completion_matches ( text, my_fgets_generator ) ; - } - return ( matches ) ; -} - - - -/* fgets() intercept */ -char * -fgets ( - char * s, - int n, - FILE * stream -) -{ - if ( ! s ) return NULL ; - if ( stream == stdin ) { - char * prompt ; - char * my_fgets_line ; - rl_already_prompted = 1 ; - rl_attempted_completion_function = my_fgets_completion ; - rl_catch_signals = 1 ; - rl_catch_sigwinch = 1 ; - rl_set_signals () ; - prompt = getenv ( "FGETS_PROMPT" ) ; - for ( - my_fgets_line = 0 ; ! my_fgets_line ; my_fgets_line=readline(prompt) - ) ; - if ( ! strncmp(my_fgets_line, "_fgets_reset_", 13) ) { - my_fgets_reset () ; - free ( my_fgets_line ) ; - strcpy ( s, "\n" ) ; - return ( s ) ; - } - if ( ! strncmp(my_fgets_line, "_fgets_dump_", 12) ) { - my_fgets_dump () ; - free ( my_fgets_line ) ; - strcpy ( s, "\n" ) ; - return ( s ) ; - } - if ( ! strncmp(my_fgets_line, "_fgets_debug_", 13) ) { - my_fgets_debug_toggle () ; - free ( my_fgets_line ) ; - strcpy ( s, "\n" ) ; - return ( s ) ; - } - (void) strncpy ( s, my_fgets_line, n-1 ) ; - (void) strcat ( s, "\n" ) ; - if ( *my_fgets_line ) add_history ( my_fgets_line ) ; - free ( my_fgets_line ) ; - return ( s ) ; - } else { - static fgets_t _fgets ; - _fgets = (fgets_t) dlsym ( REAL_LIBC, "fgets" ) ; - if ( ! _fgets ) { - fprintf ( stderr, - "libfgets: failed to dynamically link to native fgets()\n" - ) ; - strcpy ( s, "\n" ) ; - return ( s ) ; - } - return ( - _fgets ( s, n, stream ) - ) ; - } -} |