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