Move readline to the readline/readline subdirectory
[deliverable/binutils-gdb.git] / readline / readline / examples / fileman.c
1 /* fileman.c - file manager example for readline library. */
2
3 /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
4
5 This file is part of the GNU Readline Library (Readline), a library for
6 reading lines of text with interactive input and history editing.
7
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
11 (at your option) any later version.
12
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
16 GNU General Public License for more details.
17
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 */
21
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. */
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_FILE_H
32 # include <sys/file.h>
33 #endif
34 #include <sys/stat.h>
35
36 #ifdef HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
39
40 #include <fcntl.h>
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
50 #ifdef HAVE_STDLIB_H
51 # include <stdlib.h>
52 #endif
53
54 #include <time.h>
55
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
64 extern char *xmalloc PARAMS((size_t));
65
66 void initialize_readline PARAMS((void));
67 void too_dangerous PARAMS((char *));
68
69 int execute_line PARAMS((char *));
70 int valid_argument PARAMS((char *, char *));
71
72 /* The names of functions that actually do the manipulation. */
73 int com_list PARAMS((char *));
74 int com_view PARAMS((char *));
75 int com_rename PARAMS((char *));
76 int com_stat PARAMS((char *));
77 int com_pwd PARAMS((char *));
78 int com_delete PARAMS((char *));
79 int com_help PARAMS((char *));
80 int com_cd PARAMS((char *));
81 int com_quit PARAMS((char *));
82
83 /* A structure which contains information on the commands this program
84 can understand. */
85
86 typedef struct {
87 char *name; /* User printable name of the function. */
88 rl_icpfunc_t *func; /* Function to call to do the job. */
89 char *doc; /* Documentation for this function. */
90 } COMMAND;
91
92 COMMAND 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" },
104 { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL }
105 };
106
107 /* Forward declarations. */
108 char *stripwhite ();
109 COMMAND *find_command ();
110
111 /* The name of this program, as taken from argv[0]. */
112 char *progname;
113
114 /* When non-zero, this global means the user is done using this program. */
115 int done;
116
117 char *
118 dupstr (s)
119 char *s;
120 {
121 char *r;
122
123 r = xmalloc (strlen (s) + 1);
124 strcpy (r, s);
125 return (r);
126 }
127
128 int
129 main (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. */
164 int
165 execute_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. */
204 COMMAND *
205 find_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. */
219 char *
220 stripwhite (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
245 char *command_generator PARAMS((const char *, int));
246 char **fileman_completion PARAMS((const char *, int, int));
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. */
251 void
252 initialize_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. */
258 rl_attempted_completion_function = fileman_completion;
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. */
266 char **
267 fileman_completion (text, start, end)
268 const char *text;
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)
279 matches = rl_completion_matches (text, command_generator);
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. */
287 char *
288 command_generator (text, state)
289 const char *text;
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. */
325 static char syscom[1024];
326
327 /* List the file(s) named in arg. */
328 int
329 com_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
339 int
340 com_view (arg)
341 char *arg;
342 {
343 if (!valid_argument ("view", arg))
344 return 1;
345
346 #if defined (__MSDOS__)
347 /* more.com doesn't grok slashes in pathnames */
348 sprintf (syscom, "less %s", arg);
349 #else
350 sprintf (syscom, "more %s", arg);
351 #endif
352 return (system (syscom));
353 }
354
355 int
356 com_rename (arg)
357 char *arg;
358 {
359 too_dangerous ("rename");
360 return (1);
361 }
362
363 int
364 com_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
392 int
393 com_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. */
402 int
403 com_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. */
442 int
443 com_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. */
457 int
458 com_pwd (ignore)
459 char *ignore;
460 {
461 char dir[1024], *s;
462
463 s = getcwd (dir, sizeof(dir) - 1);
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. */
475 int
476 com_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. */
484 void
485 too_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. */
495 int
496 valid_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.094696 seconds and 4 git commands to generate.