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