1 /* fileman.c - file manager example for readline library. */
3 /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
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.
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.
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.
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/>.
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. */
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_FILE_H
32 # include <sys/file.h>
44 #if defined (HAVE_STRING_H)
46 #else /* !HAVE_STRING_H */
48 #endif /* !HAVE_STRING_H */
56 #ifdef READLINE_LIBRARY
57 # include "readline.h"
60 # include <readline/readline.h>
61 # include <readline/history.h>
64 extern char *xmalloc
PARAMS((size_t));
66 /* The names of functions that actually do the manipulation. */
67 int com_list
PARAMS((char *));
68 int com_view
PARAMS((char *));
69 int com_rename
PARAMS((char *));
70 int com_stat
PARAMS((char *));
71 int com_pwd
PARAMS((char *));
72 int com_delete
PARAMS((char *));
73 int com_help
PARAMS((char *));
74 int com_cd
PARAMS((char *));
75 int com_quit
PARAMS((char *));
77 /* A structure which contains information on the commands this program
81 char *name
; /* User printable name of the function. */
82 rl_icpfunc_t
*func
; /* Function to call to do the job. */
83 char *doc
; /* Documentation for this function. */
86 COMMAND 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" },
98 { (char *)NULL
, (rl_icpfunc_t
*)NULL
, (char *)NULL
}
101 /* Forward declarations. */
103 COMMAND
*find_command ();
105 /* The name of this program, as taken from argv[0]. */
108 /* When non-zero, this global means the user is done using this program. */
117 r
= xmalloc (strlen (s
) + 1);
130 initialize_readline (); /* Bind our completer. */
132 /* Loop reading and executing lines until the user quits. */
135 line
= readline ("FileMan: ");
140 /* Remove leading and trailing whitespace from the line.
141 Then, if there is anything left, add it to the history list
143 s
= stripwhite (line
);
156 /* Execute a command line. */
165 /* Isolate the command word. */
167 while (line
[i
] && whitespace (line
[i
]))
171 while (line
[i
] && !whitespace (line
[i
]))
177 command
= find_command (word
);
181 fprintf (stderr
, "%s: No such command for FileMan.\n", word
);
185 /* Get argument to command, if any. */
186 while (whitespace (line
[i
]))
191 /* Call the function. */
192 return ((*(command
->func
)) (word
));
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. */
203 for (i
= 0; commands
[i
].name
; i
++)
204 if (strcmp (name
, commands
[i
].name
) == 0)
205 return (&commands
[i
]);
207 return ((COMMAND
*)NULL
);
210 /* Strip whitespace from the start and end of STRING. Return a pointer
216 register char *s
, *t
;
218 for (s
= string
; whitespace (*s
); s
++)
224 t
= s
+ strlen (s
) - 1;
225 while (t
> s
&& whitespace (*t
))
232 /* **************************************************************** */
234 /* Interface to Readline Completion */
236 /* **************************************************************** */
238 char *command_generator
PARAMS((const char *, int));
239 char **fileman_completion
PARAMS((const char *, int, int));
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
244 initialize_readline ()
246 /* Allow conditional parsing of the ~/.inputrc file. */
247 rl_readline_name
= "FileMan";
249 /* Tell the completer that we want a crack first. */
250 rl_attempted_completion_function
= fileman_completion
;
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. */
259 fileman_completion (text
, start
, end
)
265 matches
= (char **)NULL
;
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
271 matches
= rl_completion_matches (text
, command_generator
);
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. */
280 command_generator (text
, state
)
284 static int list_index
, len
;
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
296 /* Return the next name which partially matches from the command list. */
297 while (name
= commands
[list_index
].name
)
301 if (strncmp (name
, text
, len
) == 0)
302 return (dupstr(name
));
305 /* If no names matched, then return NULL. */
306 return ((char *)NULL
);
309 /* **************************************************************** */
311 /* FileMan Commands */
313 /* **************************************************************** */
315 /* String to pass to system (). This is for the LIST, VIEW and RENAME
317 static char syscom
[1024];
319 /* List the file(s) named in arg. */
326 sprintf (syscom
, "ls -FClg %s", arg
);
327 return (system (syscom
));
333 if (!valid_argument ("view", arg
))
336 #if defined (__MSDOS__)
337 /* more.com doesn't grok slashes in pathnames */
338 sprintf (syscom
, "less %s", arg
);
340 sprintf (syscom
, "more %s", arg
);
342 return (system (syscom
));
348 too_dangerous ("rename");
357 if (!valid_argument ("stat", arg
))
360 if (stat (arg
, &finfo
) == -1)
366 printf ("Statistics for `%s':\n", arg
);
368 printf ("%s has %d link%s, and is %d byte%s in length.\n",
371 (finfo
.st_nlink
== 1) ? "" : "s",
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
));
383 too_dangerous ("delete");
387 /* Print out help for ARG, or for all of the commands if ARG is
395 for (i
= 0; commands
[i
].name
; i
++)
397 if (!*arg
|| (strcmp (arg
, commands
[i
].name
) == 0))
399 printf ("%s\t\t%s.\n", commands
[i
].name
, commands
[i
].doc
);
406 printf ("No commands match `%s'. Possibilties are:\n", arg
);
408 for (i
= 0; commands
[i
].name
; i
++)
410 /* Print in six columns. */
417 printf ("%s\t", commands
[i
].name
);
427 /* Change to the directory ARG. */
431 if (chdir (arg
) == -1)
441 /* Print out the current working directory. */
447 s
= getcwd (dir
, sizeof(dir
) - 1);
450 printf ("Error getting pwd: %s\n", dir
);
454 printf ("Current directory is %s\n", dir
);
458 /* The user wishes to quit using this program. Just set DONE non-zero. */
466 /* Function which tells you that you can't do this. */
467 too_dangerous (caller
)
471 "%s: Too dangerous for me to distribute. Write it yourself.\n",
475 /* Return non-zero if ARG is a valid argument for CALLER, else print
476 an error message and return zero. */
478 valid_argument (caller
, arg
)
483 fprintf (stderr
, "%s: Argument required.\n", caller
);