Import readline 7.0 (patch 5)
[deliverable/binutils-gdb.git] / readline / examples / fileman.c
CommitLineData
cc88a640 1/* fileman.c - file manager example for readline library. */
9255ee31 2
cc88a640
JK
3/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
4
5 This file is part of the GNU Readline Library (Readline), a library for
9255ee31
EZ
6 reading lines of text with interactive input and history editing.
7
cc88a640
JK
8 Readline is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
9255ee31
EZ
11 (at your option) any later version.
12
cc88a640
JK
13 Readline is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9255ee31
EZ
16 GNU General Public License for more details.
17
cc88a640
JK
18 You should have received a copy of the GNU General Public License
19 along with Readline. If not, see <http://www.gnu.org/licenses/>.
20*/
9255ee31 21
d60d9f65
SS
22/* fileman.c -- A tiny application which demonstrates how to use the
23 GNU Readline library. This application interactively allows users
24 to manipulate files and their modes. */
d60d9f65
SS
25
26#ifdef HAVE_CONFIG_H
1b17e766 27# include <config.h>
d60d9f65
SS
28#endif
29
30#include <sys/types.h>
31#ifdef HAVE_SYS_FILE_H
1b17e766 32# include <sys/file.h>
d60d9f65
SS
33#endif
34#include <sys/stat.h>
35
1b17e766
EZ
36#ifdef HAVE_UNISTD_H
37# include <unistd.h>
38#endif
39
40#include <fcntl.h>
d60d9f65
SS
41#include <stdio.h>
42#include <errno.h>
43
44#if defined (HAVE_STRING_H)
45# include <string.h>
46#else /* !HAVE_STRING_H */
47# include <strings.h>
48#endif /* !HAVE_STRING_H */
49
1b17e766
EZ
50#ifdef HAVE_STDLIB_H
51# include <stdlib.h>
52#endif
53
cc88a640
JK
54#include <time.h>
55
d60d9f65
SS
56#ifdef READLINE_LIBRARY
57# include "readline.h"
58# include "history.h"
59#else
60# include <readline/readline.h>
61# include <readline/history.h>
62#endif
63
cc88a640 64extern char *xmalloc PARAMS((size_t));
d60d9f65 65
775e241e
TT
66void initialize_readline PARAMS((void));
67void too_dangerous PARAMS((char *));
68
69int execute_line PARAMS((char *));
70int valid_argument PARAMS((char *, char *));
71
d60d9f65 72/* The names of functions that actually do the manipulation. */
9255ee31
EZ
73int com_list PARAMS((char *));
74int com_view PARAMS((char *));
75int com_rename PARAMS((char *));
76int com_stat PARAMS((char *));
77int com_pwd PARAMS((char *));
78int com_delete PARAMS((char *));
79int com_help PARAMS((char *));
80int com_cd PARAMS((char *));
81int com_quit PARAMS((char *));
d60d9f65
SS
82
83/* A structure which contains information on the commands this program
84 can understand. */
85
86typedef struct {
87 char *name; /* User printable name of the function. */
9255ee31 88 rl_icpfunc_t *func; /* Function to call to do the job. */
d60d9f65
SS
89 char *doc; /* Documentation for this function. */
90} COMMAND;
91
92COMMAND commands[] = {
93 { "cd", com_cd, "Change to directory DIR" },
94 { "delete", com_delete, "Delete FILE" },
95 { "help", com_help, "Display this text" },
96 { "?", com_help, "Synonym for `help'" },
97 { "list", com_list, "List files in DIR" },
98 { "ls", com_list, "Synonym for `list'" },
99 { "pwd", com_pwd, "Print the current working directory" },
100 { "quit", com_quit, "Quit using Fileman" },
101 { "rename", com_rename, "Rename FILE to NEWNAME" },
102 { "stat", com_stat, "Print out statistics on FILE" },
103 { "view", com_view, "View the contents of FILE" },
9255ee31 104 { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL }
d60d9f65
SS
105};
106
107/* Forward declarations. */
108char *stripwhite ();
109COMMAND *find_command ();
110
111/* The name of this program, as taken from argv[0]. */
112char *progname;
113
114/* When non-zero, this global means the user is done using this program. */
115int done;
116
117char *
118dupstr (s)
119 char *s;
120{
121 char *r;
122
123 r = xmalloc (strlen (s) + 1);
124 strcpy (r, s);
125 return (r);
126}
127
775e241e 128int
d60d9f65
SS
129main (argc, argv)
130 int argc;
131 char **argv;
132{
133 char *line, *s;
134
135 progname = argv[0];
136
137 initialize_readline (); /* Bind our completer. */
138
139 /* Loop reading and executing lines until the user quits. */
140 for ( ; done == 0; )
141 {
142 line = readline ("FileMan: ");
143
144 if (!line)
145 break;
146
147 /* Remove leading and trailing whitespace from the line.
148 Then, if there is anything left, add it to the history list
149 and execute it. */
150 s = stripwhite (line);
151
152 if (*s)
153 {
154 add_history (s);
155 execute_line (s);
156 }
157
158 free (line);
159 }
160 exit (0);
161}
162
163/* Execute a command line. */
164int
165execute_line (line)
166 char *line;
167{
168 register int i;
169 COMMAND *command;
170 char *word;
171
172 /* Isolate the command word. */
173 i = 0;
174 while (line[i] && whitespace (line[i]))
175 i++;
176 word = line + i;
177
178 while (line[i] && !whitespace (line[i]))
179 i++;
180
181 if (line[i])
182 line[i++] = '\0';
183
184 command = find_command (word);
185
186 if (!command)
187 {
188 fprintf (stderr, "%s: No such command for FileMan.\n", word);
189 return (-1);
190 }
191
192 /* Get argument to command, if any. */
193 while (whitespace (line[i]))
194 i++;
195
196 word = line + i;
197
198 /* Call the function. */
199 return ((*(command->func)) (word));
200}
201
202/* Look up NAME as the name of a command, and return a pointer to that
203 command. Return a NULL pointer if NAME isn't a command name. */
204COMMAND *
205find_command (name)
206 char *name;
207{
208 register int i;
209
210 for (i = 0; commands[i].name; i++)
211 if (strcmp (name, commands[i].name) == 0)
212 return (&commands[i]);
213
214 return ((COMMAND *)NULL);
215}
216
217/* Strip whitespace from the start and end of STRING. Return a pointer
218 into STRING. */
219char *
220stripwhite (string)
221 char *string;
222{
223 register char *s, *t;
224
225 for (s = string; whitespace (*s); s++)
226 ;
227
228 if (*s == 0)
229 return (s);
230
231 t = s + strlen (s) - 1;
232 while (t > s && whitespace (*t))
233 t--;
234 *++t = '\0';
235
236 return s;
237}
238
239/* **************************************************************** */
240/* */
241/* Interface to Readline Completion */
242/* */
243/* **************************************************************** */
244
9255ee31
EZ
245char *command_generator PARAMS((const char *, int));
246char **fileman_completion PARAMS((const char *, int, int));
d60d9f65
SS
247
248/* Tell the GNU Readline library how to complete. We want to try to complete
249 on command names if this is the first word in the line, or on filenames
250 if not. */
775e241e 251void
d60d9f65
SS
252initialize_readline ()
253{
254 /* Allow conditional parsing of the ~/.inputrc file. */
255 rl_readline_name = "FileMan";
256
257 /* Tell the completer that we want a crack first. */
9255ee31 258 rl_attempted_completion_function = fileman_completion;
d60d9f65
SS
259}
260
261/* Attempt to complete on the contents of TEXT. START and END bound the
262 region of rl_line_buffer that contains the word to complete. TEXT is
263 the word to complete. We can use the entire contents of rl_line_buffer
264 in case we want to do some simple parsing. Return the array of matches,
265 or NULL if there aren't any. */
266char **
267fileman_completion (text, start, end)
9255ee31 268 const char *text;
d60d9f65
SS
269 int start, end;
270{
271 char **matches;
272
273 matches = (char **)NULL;
274
275 /* If this word is at the start of the line, then it is a command
276 to complete. Otherwise it is the name of a file in the current
277 directory. */
278 if (start == 0)
9255ee31 279 matches = rl_completion_matches (text, command_generator);
d60d9f65
SS
280
281 return (matches);
282}
283
284/* Generator function for command completion. STATE lets us know whether
285 to start from scratch; without any state (i.e. STATE == 0), then we
286 start at the top of the list. */
287char *
288command_generator (text, state)
9255ee31 289 const char *text;
d60d9f65
SS
290 int state;
291{
292 static int list_index, len;
293 char *name;
294
295 /* If this is a new word to complete, initialize now. This includes
296 saving the length of TEXT for efficiency, and initializing the index
297 variable to 0. */
298 if (!state)
299 {
300 list_index = 0;
301 len = strlen (text);
302 }
303
304 /* Return the next name which partially matches from the command list. */
305 while (name = commands[list_index].name)
306 {
307 list_index++;
308
309 if (strncmp (name, text, len) == 0)
310 return (dupstr(name));
311 }
312
313 /* If no names matched, then return NULL. */
314 return ((char *)NULL);
315}
316
317/* **************************************************************** */
318/* */
319/* FileMan Commands */
320/* */
321/* **************************************************************** */
322
323/* String to pass to system (). This is for the LIST, VIEW and RENAME
324 commands. */
325static char syscom[1024];
326
327/* List the file(s) named in arg. */
775e241e 328int
d60d9f65
SS
329com_list (arg)
330 char *arg;
331{
332 if (!arg)
333 arg = "";
334
335 sprintf (syscom, "ls -FClg %s", arg);
336 return (system (syscom));
337}
338
775e241e 339int
d60d9f65
SS
340com_view (arg)
341 char *arg;
342{
343 if (!valid_argument ("view", arg))
344 return 1;
345
1b17e766
EZ
346#if defined (__MSDOS__)
347 /* more.com doesn't grok slashes in pathnames */
348 sprintf (syscom, "less %s", arg);
349#else
d60d9f65 350 sprintf (syscom, "more %s", arg);
1b17e766 351#endif
d60d9f65
SS
352 return (system (syscom));
353}
354
775e241e 355int
d60d9f65
SS
356com_rename (arg)
357 char *arg;
358{
359 too_dangerous ("rename");
360 return (1);
361}
362
775e241e 363int
d60d9f65
SS
364com_stat (arg)
365 char *arg;
366{
367 struct stat finfo;
368
369 if (!valid_argument ("stat", arg))
370 return (1);
371
372 if (stat (arg, &finfo) == -1)
373 {
374 perror (arg);
375 return (1);
376 }
377
378 printf ("Statistics for `%s':\n", arg);
379
380 printf ("%s has %d link%s, and is %d byte%s in length.\n",
381 arg,
382 finfo.st_nlink,
383 (finfo.st_nlink == 1) ? "" : "s",
384 finfo.st_size,
385 (finfo.st_size == 1) ? "" : "s");
386 printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
387 printf (" Last access at: %s", ctime (&finfo.st_atime));
388 printf (" Last modified at: %s", ctime (&finfo.st_mtime));
389 return (0);
390}
391
775e241e 392int
d60d9f65
SS
393com_delete (arg)
394 char *arg;
395{
396 too_dangerous ("delete");
397 return (1);
398}
399
400/* Print out help for ARG, or for all of the commands if ARG is
401 not present. */
775e241e 402int
d60d9f65
SS
403com_help (arg)
404 char *arg;
405{
406 register int i;
407 int printed = 0;
408
409 for (i = 0; commands[i].name; i++)
410 {
411 if (!*arg || (strcmp (arg, commands[i].name) == 0))
412 {
413 printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
414 printed++;
415 }
416 }
417
418 if (!printed)
419 {
420 printf ("No commands match `%s'. Possibilties are:\n", arg);
421
422 for (i = 0; commands[i].name; i++)
423 {
424 /* Print in six columns. */
425 if (printed == 6)
426 {
427 printed = 0;
428 printf ("\n");
429 }
430
431 printf ("%s\t", commands[i].name);
432 printed++;
433 }
434
435 if (printed)
436 printf ("\n");
437 }
438 return (0);
439}
440
441/* Change to the directory ARG. */
775e241e 442int
d60d9f65
SS
443com_cd (arg)
444 char *arg;
445{
446 if (chdir (arg) == -1)
447 {
448 perror (arg);
449 return 1;
450 }
451
452 com_pwd ("");
453 return (0);
454}
455
456/* Print out the current working directory. */
775e241e 457int
d60d9f65
SS
458com_pwd (ignore)
459 char *ignore;
460{
461 char dir[1024], *s;
462
1b17e766 463 s = getcwd (dir, sizeof(dir) - 1);
d60d9f65
SS
464 if (s == 0)
465 {
466 printf ("Error getting pwd: %s\n", dir);
467 return 1;
468 }
469
470 printf ("Current directory is %s\n", dir);
471 return 0;
472}
473
474/* The user wishes to quit using this program. Just set DONE non-zero. */
775e241e 475int
d60d9f65
SS
476com_quit (arg)
477 char *arg;
478{
479 done = 1;
480 return (0);
481}
482
483/* Function which tells you that you can't do this. */
775e241e 484void
d60d9f65
SS
485too_dangerous (caller)
486 char *caller;
487{
488 fprintf (stderr,
489 "%s: Too dangerous for me to distribute. Write it yourself.\n",
490 caller);
491}
492
493/* Return non-zero if ARG is a valid argument for CALLER, else print
494 an error message and return zero. */
495int
496valid_argument (caller, arg)
497 char *caller, *arg;
498{
499 if (!arg || !*arg)
500 {
501 fprintf (stderr, "%s: Argument required.\n", caller);
502 return (0);
503 }
504
505 return (1);
506}
This page took 0.902503 seconds and 4 git commands to generate.