Annotation of embedaddon/readline/examples/fileman.c, revision 1.1

1.1     ! misho       1: /* fileman.c - file manager example for readline library. */
        !             2: 
        !             3: /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
        !             4: 
        !             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.
        !             7: 
        !             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.
        !            12: 
        !            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.
        !            17: 
        !            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: */
        !            21: 
        !            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. */
        !            25: 
        !            26: #ifdef HAVE_CONFIG_H
        !            27: #  include <config.h>
        !            28: #endif
        !            29: 
        !            30: #include <sys/types.h>
        !            31: #ifdef HAVE_SYS_FILE_H
        !            32: #  include <sys/file.h>
        !            33: #endif
        !            34: #include <sys/stat.h>
        !            35: 
        !            36: #ifdef HAVE_UNISTD_H
        !            37: #  include <unistd.h>
        !            38: #endif
        !            39: 
        !            40: #include <fcntl.h>
        !            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: 
        !            50: #ifdef HAVE_STDLIB_H
        !            51: #  include <stdlib.h>
        !            52: #endif
        !            53: 
        !            54: #include <time.h>
        !            55: 
        !            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: 
        !            64: extern char *xmalloc PARAMS((size_t));
        !            65: 
        !            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 *));
        !            76: 
        !            77: /* A structure which contains information on the commands this program
        !            78:    can understand. */
        !            79: 
        !            80: typedef struct {
        !            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.  */
        !            84: } COMMAND;
        !            85: 
        !            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 }
        !            99: };
        !           100: 
        !           101: /* Forward declarations. */
        !           102: char *stripwhite ();
        !           103: COMMAND *find_command ();
        !           104: 
        !           105: /* The name of this program, as taken from argv[0]. */
        !           106: char *progname;
        !           107: 
        !           108: /* When non-zero, this global means the user is done using this program. */
        !           109: int done;
        !           110: 
        !           111: char *
        !           112: dupstr (s)
        !           113:      char *s;
        !           114: {
        !           115:   char *r;
        !           116: 
        !           117:   r = xmalloc (strlen (s) + 1);
        !           118:   strcpy (r, s);
        !           119:   return (r);
        !           120: }
        !           121: 
        !           122: main (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. */
        !           157: int
        !           158: execute_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. */
        !           197: COMMAND *
        !           198: find_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. */
        !           212: char *
        !           213: stripwhite (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: 
        !           238: char *command_generator PARAMS((const char *, int));
        !           239: char **fileman_completion PARAMS((const char *, int, int));
        !           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. */
        !           244: initialize_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. */
        !           250:   rl_attempted_completion_function = fileman_completion;
        !           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. */
        !           258: char **
        !           259: fileman_completion (text, start, end)
        !           260:      const char *text;
        !           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)
        !           271:     matches = rl_completion_matches (text, command_generator);
        !           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. */
        !           279: char *
        !           280: command_generator (text, state)
        !           281:      const char *text;
        !           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. */
        !           317: static char syscom[1024];
        !           318: 
        !           319: /* List the file(s) named in arg. */
        !           320: com_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: 
        !           330: com_view (arg)
        !           331:      char *arg;
        !           332: {
        !           333:   if (!valid_argument ("view", arg))
        !           334:     return 1;
        !           335: 
        !           336: #if defined (__MSDOS__)
        !           337:   /* more.com doesn't grok slashes in pathnames */
        !           338:   sprintf (syscom, "less %s", arg);
        !           339: #else
        !           340:   sprintf (syscom, "more %s", arg);
        !           341: #endif
        !           342:   return (system (syscom));
        !           343: }
        !           344: 
        !           345: com_rename (arg)
        !           346:      char *arg;
        !           347: {
        !           348:   too_dangerous ("rename");
        !           349:   return (1);
        !           350: }
        !           351: 
        !           352: com_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: 
        !           380: com_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. */
        !           389: com_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. */
        !           428: com_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. */
        !           442: com_pwd (ignore)
        !           443:      char *ignore;
        !           444: {
        !           445:   char dir[1024], *s;
        !           446: 
        !           447:   s = getcwd (dir, sizeof(dir) - 1);
        !           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. */
        !           459: com_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. */
        !           467: too_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. */
        !           477: int
        !           478: valid_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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>