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