GC old libarchive/bsdtar.
[dragonfly/port-amd64.git] / contrib / libreadline / examples / fileman.c
blobdc29a40104f7b6cf91c79b35bd3bd254520a2962
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. */
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
9 #include <sys/types.h>
10 #ifdef HAVE_SYS_FILE_H
11 # include <sys/file.h>
12 #endif
13 #include <sys/stat.h>
15 #ifdef HAVE_UNISTD_H
16 # include <unistd.h>
17 #endif
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <errno.h>
23 #if defined (HAVE_STRING_H)
24 # include <string.h>
25 #else /* !HAVE_STRING_H */
26 # include <strings.h>
27 #endif /* !HAVE_STRING_H */
29 #ifdef HAVE_STDLIB_H
30 # include <stdlib.h>
31 #endif
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
41 extern char *xmalloc ();
43 /* The names of functions that actually do the manipulation. */
44 int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
45 int com_delete (), com_help (), com_cd (), com_quit ();
47 /* A structure which contains information on the commands this program
48 can understand. */
50 typedef 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;
56 COMMAND 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 }
71 /* Forward declarations. */
72 char *stripwhite ();
73 COMMAND *find_command ();
75 /* The name of this program, as taken from argv[0]. */
76 char *progname;
78 /* When non-zero, this global means the user is done using this program. */
79 int done;
81 char *
82 dupstr (s)
83 char *s;
85 char *r;
87 r = xmalloc (strlen (s) + 1);
88 strcpy (r, s);
89 return (r);
92 main (argc, argv)
93 int argc;
94 char **argv;
96 char *line, *s;
98 progname = argv[0];
100 initialize_readline (); /* Bind our completer. */
102 /* Loop reading and executing lines until the user quits. */
103 for ( ; done == 0; )
105 line = readline ("FileMan: ");
107 if (!line)
108 break;
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);
115 if (*s)
117 add_history (s);
118 execute_line (s);
121 free (line);
123 exit (0);
126 /* Execute a command line. */
128 execute_line (line)
129 char *line;
131 register int i;
132 COMMAND *command;
133 char *word;
135 /* Isolate the command word. */
136 i = 0;
137 while (line[i] && whitespace (line[i]))
138 i++;
139 word = line + i;
141 while (line[i] && !whitespace (line[i]))
142 i++;
144 if (line[i])
145 line[i++] = '\0';
147 command = find_command (word);
149 if (!command)
151 fprintf (stderr, "%s: No such command for FileMan.\n", word);
152 return (-1);
155 /* Get argument to command, if any. */
156 while (whitespace (line[i]))
157 i++;
159 word = line + i;
161 /* Call the function. */
162 return ((*(command->func)) (word));
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. */
167 COMMAND *
168 find_command (name)
169 char *name;
171 register int i;
173 for (i = 0; commands[i].name; i++)
174 if (strcmp (name, commands[i].name) == 0)
175 return (&commands[i]);
177 return ((COMMAND *)NULL);
180 /* Strip whitespace from the start and end of STRING. Return a pointer
181 into STRING. */
182 char *
183 stripwhite (string)
184 char *string;
186 register char *s, *t;
188 for (s = string; whitespace (*s); s++)
191 if (*s == 0)
192 return (s);
194 t = s + strlen (s) - 1;
195 while (t > s && whitespace (*t))
196 t--;
197 *++t = '\0';
199 return s;
202 /* **************************************************************** */
203 /* */
204 /* Interface to Readline Completion */
205 /* */
206 /* **************************************************************** */
208 char *command_generator ();
209 char **fileman_completion ();
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. */
214 initialize_readline ()
216 /* Allow conditional parsing of the ~/.inputrc file. */
217 rl_readline_name = "FileMan";
219 /* Tell the completer that we want a crack first. */
220 rl_attempted_completion_function = (CPPFunction *)fileman_completion;
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. */
228 char **
229 fileman_completion (text, start, end)
230 char *text;
231 int start, end;
233 char **matches;
235 matches = (char **)NULL;
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);
243 return (matches);
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. */
249 char *
250 command_generator (text, state)
251 char *text;
252 int state;
254 static int list_index, len;
255 char *name;
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)
262 list_index = 0;
263 len = strlen (text);
266 /* Return the next name which partially matches from the command list. */
267 while (name = commands[list_index].name)
269 list_index++;
271 if (strncmp (name, text, len) == 0)
272 return (dupstr(name));
275 /* If no names matched, then return NULL. */
276 return ((char *)NULL);
279 /* **************************************************************** */
280 /* */
281 /* FileMan Commands */
282 /* */
283 /* **************************************************************** */
285 /* String to pass to system (). This is for the LIST, VIEW and RENAME
286 commands. */
287 static char syscom[1024];
289 /* List the file(s) named in arg. */
290 com_list (arg)
291 char *arg;
293 if (!arg)
294 arg = "";
296 sprintf (syscom, "ls -FClg %s", arg);
297 return (system (syscom));
300 com_view (arg)
301 char *arg;
303 if (!valid_argument ("view", arg))
304 return 1;
306 #if defined (__MSDOS__)
307 /* more.com doesn't grok slashes in pathnames */
308 sprintf (syscom, "less %s", arg);
309 #else
310 sprintf (syscom, "more %s", arg);
311 #endif
312 return (system (syscom));
315 com_rename (arg)
316 char *arg;
318 too_dangerous ("rename");
319 return (1);
322 com_stat (arg)
323 char *arg;
325 struct stat finfo;
327 if (!valid_argument ("stat", arg))
328 return (1);
330 if (stat (arg, &finfo) == -1)
332 perror (arg);
333 return (1);
336 printf ("Statistics for `%s':\n", arg);
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);
350 com_delete (arg)
351 char *arg;
353 too_dangerous ("delete");
354 return (1);
357 /* Print out help for ARG, or for all of the commands if ARG is
358 not present. */
359 com_help (arg)
360 char *arg;
362 register int i;
363 int printed = 0;
365 for (i = 0; commands[i].name; i++)
367 if (!*arg || (strcmp (arg, commands[i].name) == 0))
369 printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
370 printed++;
374 if (!printed)
376 printf ("No commands match `%s'. Possibilties are:\n", arg);
378 for (i = 0; commands[i].name; i++)
380 /* Print in six columns. */
381 if (printed == 6)
383 printed = 0;
384 printf ("\n");
387 printf ("%s\t", commands[i].name);
388 printed++;
391 if (printed)
392 printf ("\n");
394 return (0);
397 /* Change to the directory ARG. */
398 com_cd (arg)
399 char *arg;
401 if (chdir (arg) == -1)
403 perror (arg);
404 return 1;
407 com_pwd ("");
408 return (0);
411 /* Print out the current working directory. */
412 com_pwd (ignore)
413 char *ignore;
415 char dir[1024], *s;
417 s = getcwd (dir, sizeof(dir) - 1);
418 if (s == 0)
420 printf ("Error getting pwd: %s\n", dir);
421 return 1;
424 printf ("Current directory is %s\n", dir);
425 return 0;
428 /* The user wishes to quit using this program. Just set DONE non-zero. */
429 com_quit (arg)
430 char *arg;
432 done = 1;
433 return (0);
436 /* Function which tells you that you can't do this. */
437 too_dangerous (caller)
438 char *caller;
440 fprintf (stderr,
441 "%s: Too dangerous for me to distribute. Write it yourself.\n",
442 caller);
445 /* Return non-zero if ARG is a valid argument for CALLER, else print
446 an error message and return zero. */
448 valid_argument (caller, arg)
449 char *caller, *arg;
451 if (!arg || !*arg)
453 fprintf (stderr, "%s: Argument required.\n", caller);
454 return (0);
457 return (1);