OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [readline/] [examples/] [rl-fgets.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*
2
Date: Tue, 16 Mar 2004 19:38:40 -0800
3
From: Harold Levy <Harold.Levy@synopsys.com>
4
Subject: fgets(stdin) --> readline() redirector
5
To: chet@po.cwru.edu
6
 
7
Hi Chet,
8
 
9
Here is something you may find useful enough to include in the readline
10
distribution.  It is a shared library that redirects calls to fgets(stdin)
11
to readline() via LD_PRELOAD, and it supports a custom prompt and list of
12
command names.  Many people have asked me for this file, so I thought I'd
13
pass it your way in hope of just including it with readline to begin with.
14
 
15
Best Regards,
16
 
17
-Harold
18
*/
19
 
20
/******************************************************************************
21
*******************************************************************************
22
 
23
  FILE NAME:    fgets.c                  TARGET:   libfgets.so
24
  AUTHOR:       Harold Levy              VERSION:  1.0
25
                hlevy@synopsys.com
26
 
27
  ABSTRACT:  Customize fgets() behavior via LD_PRELOAD in the following ways:
28
 
29
    -- If fgets(stdin) is called, redirect to GNU readline() to obtain
30
       command-line editing, file-name completion, history, etc.
31
 
32
    -- A list of commands for command-name completion can be configured by
33
       setting the environment-variable FGETS_COMMAND_FILE to a file containing
34
       the list of commands to be used.
35
 
36
    -- Command-line editing with readline() works best when the prompt string
37
       is known; you can set this with the FGETS_PROMPT environment variable.
38
 
39
    -- There special strings that libfgets will interpret as internal commands:
40
 
41
           _fgets_reset_    reset the command list
42
 
43
           _fgets_dump_     dump status
44
 
45
           _fgets_debug_    toggle debug messages
46
 
47
  HOW TO BUILD:  Here are examples of how to build libfgets.so on various
48
  platforms; you will have to add -I and -L flags to configure access to
49
  the readline header and library files.
50
 
51
  (32-bit builds with gcc)
52
  AIX:   gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldl -lreadline -ltermcap
53
  HP-UX: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldld -lreadline
54
  Linux: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldl -lreadline
55
  SunOS: gcc -fPIC fgets.c -shared -o libfgets.so -lc -ldl -lgen -lreadline
56
 
57
  (64-bit builds without gcc)
58
  SunOS: SUNWspro/bin/cc -D_LARGEFILE64_SOURCE=1 -xtarget=ultra -xarch=v9 \
59
           -KPIC fgets.c -Bdynamic -lc -ldl -lgen -ltermcap -lreadline
60
 
61
  HOW TO USE:  Different operating systems have different levels of support
62
  for the LD_PRELOAD concept.  The generic method for 32-bit platforms is to
63
  put libtermcap.so, libfgets.so, and libreadline.so (with absolute paths)
64
  in the LD_PRELOAD environment variable, and to put their parent directories
65
  in the LD_LIBRARY_PATH environment variable.  Unfortunately there is no
66
  generic method for 64-bit platforms; e.g. for 64-bit SunOS, you would have
67
  to build both 32-bit and 64-bit libfgets and libreadline libraries, and
68
  use the LD_FLAGS_32 and LD_FLAGS_64 environment variables with preload and
69
  library_path configurations (a mix of 32-bit and 64-bit calls are made under
70
  64-bit SunOS).
71
 
72
  EXAMPLE WRAPPER:  Here is an example shell script wrapper around the
73
  program "foo" that uses fgets() for command-line input:
74
 
75
      #!/bin/csh
76
      #### replace this with the libtermcap.so directory:
77
      set dir1 = "/usr/lib"
78
      #### replace this with the libfgets.so directory:
79
      set dir2 = "/usr/fgets"
80
      #### replace this with the libreadline.so directory:
81
      set dir3 = "/usr/local/lib"
82
      set lib1 = "${dir1}/libtermcap.so"
83
      set lib2 = "${dir2}/libfgets.so"
84
      set lib3 = "${dir3}/libreadline.so"
85
      if ( "${?LD_PRELOAD}" ) then
86
        setenv LD_PRELOAD "${lib1}:${lib2}:${lib3}:${LD_PRELOAD}"
87
      else
88
        setenv LD_PRELOAD "${lib1}:${lib2}:${lib3}"
89
      endif
90
      if ( "${?LD_LIBRARY_PATH}" ) then
91
        setenv LD_LIBRARY_PATH "${dir1}:${dir2}:${dir3}:${LD_LIBRARY_PATH}"
92
      else
93
        setenv LD_LIBRARY_PATH "${dir1}:${dir2}:${dir3}"
94
      endif
95
      setenv FGETS_COMMAND_FILE "${dir2}/foo.commands"
96
      setenv FGETS_PROMPT       "foo> "
97
      exec "foo" $*
98
 
99
  Copyright (C)©2003-2004 Harold Levy.
100
 
101
  This code links to the GNU readline library, and as such is bound by the
102
  terms of the GNU General Public License as published by the Free Software
103
  Foundation, either version 2 or (at your option) any later version.
104
 
105
  The GNU General Public License is often shipped with GNU software, and is
106
  generally kept in a file called COPYING or LICENSE.  If you do not have a
107
  copy of the license, write to the Free Software Foundation, 59 Temple Place,
108
  Suite 330, Boston, MA 02111 USA.
109
 
110
  This program is distributed in the hope that it will be useful, but WITHOUT
111
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
112
  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
113
  details.
114
 
115
*******************************************************************************
116
******************************************************************************/
117
 
118
 
119
 
120
#include <dlfcn.h>
121
#include <stdio.h>
122
#include <strings.h>
123
#include <stdlib.h>
124
#include <unistd.h>
125
 
126
#include <readline/readline.h>
127
#include <readline/history.h>
128
 
129
 
130
 
131
/* for dynamically connecting to the native fgets() */
132
#if defined(RTLD_NEXT)
133
#define REAL_LIBC RTLD_NEXT
134
#else
135
#define REAL_LIBC ((void *) -1L)
136
#endif
137
typedef char * ( * fgets_t ) ( char * s, int n, FILE * stream ) ;
138
 
139
 
140
 
141
/* private data */
142
/* -- writeable data is stored in the shared library's data segment
143
   -- every process that uses the shared library gets a private memory copy of
144
      its entire data segment
145
   -- static data in the shared library is not copied to the application
146
   -- only read-only (i.e. 'const') data is stored in the shared library's
147
      text segment
148
*/
149
static char ** my_fgets_names           = NULL ;
150
static int     my_fgets_number_of_names = 0    ;
151
static int     my_fgets_debug_flag      = 0    ;
152
 
153
 
154
 
155
/* invoked with _fgets_reset_ */
156
static void
157
my_fgets_reset (
158
  void
159
) {
160
  if ( my_fgets_names && (my_fgets_number_of_names > 0) ) {
161
    int i ;
162
    if ( my_fgets_debug_flag ) {
163
      printf ( "libfgets:  removing command list\n" ) ;
164
    }
165
    for ( i = 0 ; i < my_fgets_number_of_names ; i ++ ) {
166
      if ( my_fgets_names[i] ) free ( my_fgets_names[i] ) ;
167
    }
168
    free ( my_fgets_names ) ;
169
  }
170
  my_fgets_names = NULL ;
171
  my_fgets_number_of_names = 0 ;
172
}
173
 
174
 
175
 
176
/* invoked with _fgets_dump_ */
177
static void
178
my_fgets_dump (
179
  void
180
) {
181
  char * s ;
182
  printf ( "\n" ) ;
183
  s = getenv ( "FGETS_PROMPT" ) ;
184
  printf ( "FGETS_PROMPT       = %s\n", s ? s : "" ) ;
185
  s = getenv ( "FGETS_COMMAND_FILE" ) ;
186
  printf ( "FGETS_COMMAND_FILE = %s\n", s ? s : "" ) ;
187
  printf ( "debug flag         = %d\n", my_fgets_debug_flag ) ;
188
  printf ( "#commands          = %d\n", my_fgets_number_of_names ) ;
189
  if ( my_fgets_debug_flag ) {
190
    if ( my_fgets_names && (my_fgets_number_of_names > 0) ) {
191
      int i ;
192
      for ( i = 0 ; i < my_fgets_number_of_names ; i ++ ) {
193
        printf ( "%s\n", my_fgets_names[i] ) ;
194
      }
195
    }
196
  }
197
  printf ( "\n" ) ;
198
}
199
 
200
 
201
 
202
/* invoked with _fgets_debug_ */
203
static void
204
my_fgets_debug_toggle (
205
  void
206
) {
207
  my_fgets_debug_flag = my_fgets_debug_flag ? 0 : 1 ;
208
  if ( my_fgets_debug_flag ) {
209
    printf ( "libfgets:  debug flag = %d\n", my_fgets_debug_flag ) ;
210
  }
211
}
212
 
213
 
214
 
215
/* read the command list if needed, return the i-th name */
216
static char *
217
my_fgets_lookup (
218
  int index
219
) {
220
  if ( (! my_fgets_names) || (! my_fgets_number_of_names) ) {
221
    char * fname ;
222
    FILE * fp ;
223
    fgets_t _fgets ;
224
    int i ;
225
    char buf1[256], buf2[256] ;
226
    fname = getenv ( "FGETS_COMMAND_FILE" ) ;
227
    if ( ! fname ) {
228
      if ( my_fgets_debug_flag ) {
229
        printf ( "libfgets:  empty or unset FGETS_COMMAND_FILE\n" ) ;
230
      }
231
      return NULL ;
232
    }
233
    fp = fopen ( fname, "r" ) ;
234
    if ( ! fp ) {
235
      if ( my_fgets_debug_flag ) {
236
        printf ( "libfgets:  cannot open '%s' for reading\n", fname ) ;
237
      }
238
      return NULL ;
239
    }
240
    _fgets = (fgets_t) dlsym ( REAL_LIBC, "fgets" ) ;
241
    if ( ! _fgets ) {
242
      fprintf ( stderr,
243
        "libfgets:  failed to dynamically link to native fgets()\n"
244
      ) ;
245
      return NULL ;
246
    }
247
    for ( i = 0 ; _fgets(buf1,255,fp) ; i ++ ) ;
248
    if ( ! i ) { fclose(fp) ; return NULL ; }
249
    my_fgets_names = (char**) calloc ( i, sizeof(char*) ) ;
250
    rewind ( fp ) ;
251
    i = 0 ;
252
    while ( _fgets(buf1,255,fp) ) {
253
      buf1[255] = 0 ;
254
      if ( 1 == sscanf(buf1,"%s",buf2) ) {
255
        my_fgets_names[i] = strdup(buf2) ;
256
        i ++ ;
257
      }
258
    }
259
    fclose ( fp ) ;
260
    my_fgets_number_of_names = i ;
261
    if ( my_fgets_debug_flag ) {
262
      printf ( "libfgets:  successfully read %d commands\n", i ) ;
263
    }
264
  }
265
  if ( index < my_fgets_number_of_names ) {
266
    return my_fgets_names[index] ;
267
  } else {
268
    return NULL ;
269
  }
270
}
271
 
272
 
273
 
274
/* generate a list of partial name matches for readline() */
275
static char *
276
my_fgets_generator (
277
  const char * text,
278
  int          state
279
)
280
{
281
  static int list_index, len ;
282
  char *     name ;
283
  if ( ! state ) {
284
    list_index = 0 ;
285
    len = strlen ( text ) ;
286
  }
287
  while ( ( name = my_fgets_lookup(list_index) ) ) {
288
    list_index ++ ;
289
    if ( ! strncmp ( name, text, len ) ) {
290
      return ( strdup ( name ) ) ;
291
    }
292
  }
293
  return ( NULL ) ;
294
}
295
 
296
 
297
 
298
/* partial name completion callback for readline() */
299
static char **
300
my_fgets_completion (
301
  const char * text,
302
  int          start,
303
  int          end
304
)
305
{
306
  char ** matches ;
307
  matches = NULL ;
308
  if ( ! start ) {
309
    matches = rl_completion_matches ( text, my_fgets_generator ) ;
310
  }
311
  return ( matches ) ;
312
}
313
 
314
 
315
 
316
/* fgets() intercept */
317
char *
318
fgets (
319
  char * s,
320
  int    n,
321
  FILE * stream
322
)
323
{
324
  if ( ! s ) return NULL ;
325
  if ( stream == stdin ) {
326
    char * prompt ;
327
    char * my_fgets_line ;
328
    rl_already_prompted = 1 ;
329
    rl_attempted_completion_function = my_fgets_completion ;
330
    rl_catch_signals = 1 ;
331
    rl_catch_sigwinch = 1 ;
332
    rl_set_signals () ;
333
    prompt = getenv ( "FGETS_PROMPT" ) ;
334
    for (
335
      my_fgets_line = 0 ; ! my_fgets_line ; my_fgets_line=readline(prompt)
336
    ) ;
337
    if ( ! strncmp(my_fgets_line, "_fgets_reset_", 13) ) {
338
      my_fgets_reset () ;
339
      free ( my_fgets_line ) ;
340
      strcpy ( s, "\n" ) ;
341
      return ( s ) ;
342
    }
343
    if ( ! strncmp(my_fgets_line, "_fgets_dump_", 12) ) {
344
      my_fgets_dump () ;
345
      free ( my_fgets_line ) ;
346
      strcpy ( s, "\n" ) ;
347
      return ( s ) ;
348
    }
349
    if ( ! strncmp(my_fgets_line, "_fgets_debug_", 13) ) {
350
      my_fgets_debug_toggle () ;
351
      free ( my_fgets_line ) ;
352
      strcpy ( s, "\n" ) ;
353
      return ( s ) ;
354
    }
355
    (void) strncpy ( s, my_fgets_line, n-1 ) ;
356
    (void) strcat ( s, "\n" ) ;
357
    if ( *my_fgets_line ) add_history ( my_fgets_line ) ;
358
    free ( my_fgets_line ) ;
359
    return ( s ) ;
360
  } else {
361
    static fgets_t _fgets ;
362
    _fgets = (fgets_t) dlsym ( REAL_LIBC, "fgets" ) ;
363
    if ( ! _fgets ) {
364
      fprintf ( stderr,
365
        "libfgets:  failed to dynamically link to native fgets()\n"
366
      ) ;
367
      strcpy ( s, "\n" ) ;
368
      return ( s ) ;
369
    }
370
    return (
371
      _fgets ( s, n, stream )
372
    ) ;
373
  }
374
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.