X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=restore%2Finteractive.c;fp=restore%2Finteractive.c;h=d8854c663e84523364ddb21df32b52b82e051ae6;hb=c38e5b6a9c658f06d9b27f33e9db131ffa23d947;hp=4fbdf6e8a0200f6259ce08a66c5388a4ae159a2a;hpb=a110deb5071144c2f47e8c8ec072cb8dbef160f0;p=dump.git diff --git a/restore/interactive.c b/restore/interactive.c index 4fbdf6e..d8854c6 100644 --- a/restore/interactive.c +++ b/restore/interactive.c @@ -40,7 +40,7 @@ #ifndef lint static const char rcsid[] = - "$Id: interactive.c,v 1.10 2000/05/28 17:50:27 stelian Exp $"; + "$Id: interactive.c,v 1.11 2000/05/29 14:17:37 stelian Exp $"; #endif /* not lint */ #include @@ -71,6 +71,17 @@ extern char * __progname; #include "restore.h" #include "extern.h" +#if HAVE_READLINE +#include +#include + +static char *rl_gets (char *prompt); +static void initialize_readline(void); +static char **restore_completion (char *text, int start, int end); +static char *command_generator(char *text, int state); +static char *filename_generator(char *text, int state); +#endif + #define round(a, b) (((a) + (b) - 1) / (b) * (b)) /* @@ -119,6 +130,9 @@ runcmdshell(void) char name[MAXPATHLEN]; char cmd[BUFSIZ]; +#if HAVE_READLINE + initialize_readline(); +#endif arglist.freeglob = 0; arglist.argcnt = 0; arglist.glob.gl_flags = GLOB_ALTDIRFUNC; @@ -351,6 +365,9 @@ getcmd(char *curdir, char *cmd, char *name, int size, struct arglist *ap) /* * Read a command line and trim off trailing white space. */ +#if HAVE_READLINE + snprintf(input, BUFSIZ, "%s\n", rl_gets(curdir)); +#else do { if (pflag) fprintf(stderr, "%s:%s:%s > ", @@ -366,6 +383,7 @@ getcmd(char *curdir, char *cmd, char *name, int size, struct arglist *ap) (void) strcpy(cmd, "quit"); return; } +#endif for (cp = &input[strlen(input) - 2]; *cp == ' ' || *cp == '\t'; cp--) /* trim off trailing white space and newline */; *++cp = '\0'; @@ -807,3 +825,197 @@ onintr(int signo) exit(1); errno = save_errno; } + + +#if HAVE_READLINE + +/* A static variable for holding the line. */ +static char *line_read = NULL; + +static char completion_curdir[MAXPATHLEN]; + +static char *commands[] = { + "add ", "cd ", "delete ", "extract ", "help ", + "? ", "ls ", "pwd ", "prompt ", "quit ", "xit ", + "verbose ", "setmodes ", "what ", "Debug ", + NULL }; + +static char *files = NULL; + +static char * +rl_gets (char *dir) +{ + char *prompt; + int sz; + + snprintf(completion_curdir, MAXPATHLEN, "%s", dir); + completion_curdir[MAXPATHLEN - 1] = '\0'; + + if (pflag) { + sz = 6 + strlen(__progname) + strlen(spcl.c_filesys) + strlen((completion_curdir + 1 ? completion_curdir + 1 : "/")); + prompt = (char *)malloc(sz); + if (!prompt) + return NULL; + snprintf(prompt, sz, "%s:%s:%s > ", + __progname, + spcl.c_filesys, + (completion_curdir + 1 ? completion_curdir + 1 : "/")); + } + else { + sz = 4 + strlen(__progname); + prompt = (char *)malloc(sz); + if (!prompt) + return NULL; + snprintf(prompt, sz, "%s > ", __progname); + } + prompt[sz - 1] = '\0'; + + if (line_read) { + free (line_read); + line_read = (char *)NULL; + } + + do { + line_read = readline (prompt); + } while (line_read && !*line_read); + + free(prompt); + + if (!line_read) { + printf("\n"); + return strdup("quit"); + } + + add_history (line_read); + + return (line_read); +} + +static void +initialize_readline(void) +{ + rl_attempted_completion_function = restore_completion; + rl_completion_entry_function = (Function *)NULL; + rl_completion_append_character = '\0'; +} + +static char ** +restore_completion (char *text, int start, int end) +{ + char **matches; + + if (start == 0) + matches = completion_matches (text, command_generator); + else + matches = completion_matches (text, filename_generator); + + return (matches); +} + +static char * +command_generator(char *text, int state) +{ + static int list_index, len; + char *name; + + if (!state) { + list_index = 0; + len = strlen(text); + } + + while ( (name = commands[list_index]) != NULL) { + + list_index ++; + + if (strncmp(name, text, len) == 0) + return strdup(name); + } + + return NULL; +} + +static char * +filename_generator(char *text, int state) +{ + static int list_index; + char *name; + RST_DIR *dirp; + struct direct *dp; + static int entries; + char pname[MAXPATHLEN]; + char fname[MAXPATHLEN]; + char *slash; + char ppname[MAXPATHLEN]; + + if (!state) { + list_index = 0; + + if (files != NULL) { + free(files); + entries = 0; + files = NULL; + } + if ((slash = strrchr(text, '/')) != NULL) { + int idx = slash - text; + if (idx > MAXPATHLEN - 2) + idx = MAXPATHLEN - 2; + strncpy(ppname, text, MAXPATHLEN); + ppname[MAXPATHLEN - 1] = '\0'; + ppname[idx] = '\0'; + if (text[0] == '/') + snprintf(pname, MAXPATHLEN, ".%s", ppname); + else + snprintf(pname, MAXPATHLEN, "%s/%s", completion_curdir, ppname); + strncpy(fname, ppname + idx + 1, MAXPATHLEN); + ppname[idx] = '/'; + ppname[idx + 1] = '\0'; + } + else { + strncpy(pname, completion_curdir, MAXPATHLEN); + strncpy(fname, text, MAXPATHLEN); + ppname[0] = '\0'; + } + pname[MAXPATHLEN - 1] = '\0'; + fname[MAXPATHLEN - 1] = '\0'; + if ((dirp = rst_opendir(pname)) == NULL) + return NULL; + entries = 0; + while ((dp = rst_readdir(dirp))) + entries++; + rst_closedir(dirp); + files = (char *)malloc(entries * MAXPATHLEN); + if (files == NULL) { + fprintf(stderr, "Out of memory\n"); + entries = 0; + return NULL; + } + if ((dirp = rst_opendir(pname)) == NULL) + panic("directory reopen failed\n"); + entries = 0; + while ((dp = rst_readdir(dirp))) { + if (TSTINO(dp->d_ino, dumpmap) == 0) + continue; + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + if (strncmp(dp->d_name, fname, strlen(fname)) == 0) { + if (inodetype(dp->d_ino) == NODE) + snprintf(files + entries * MAXPATHLEN, MAXPATHLEN, "%s%s/", ppname, dp->d_name); + else + snprintf(files + entries * MAXPATHLEN, MAXPATHLEN, "%s%s ", ppname, dp->d_name); + *(files + (entries + 1) * MAXPATHLEN - 1) = '\0'; + ++entries; + } + } + rst_closedir(dirp); + } + + if (list_index >= entries) + return NULL; + + name = strdup(files + list_index * MAXPATHLEN); + list_index ++; + + return name; +} +#endif /* HAVE_READLINE */