X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=restore%2Finteractive.c;h=bc94ed45c339cdff5c5bd02eae8598e1d83ee1b9;hp=2f262789632fe1cf351d5f85cadccbbda228edb0;hb=5d2a3d246d400d45dfd4c49ddb588c69fb60873d;hpb=8d4197bb9ba5bbcef21409231ed8903b0cac353a diff --git a/restore/interactive.c b/restore/interactive.c index 2f26278..bc94ed4 100644 --- a/restore/interactive.c +++ b/restore/interactive.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999 - * + * Stelian Pop , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000-2002 */ /* @@ -40,18 +40,20 @@ */ #ifndef lint -#if 0 -static char sccsid[] = "@(#)interactive.c 8.5 (Berkeley) 5/1/95"; -#endif static const char rcsid[] = - "$Id: interactive.c,v 1.4 1999/10/11 13:08:09 stelian Exp $"; + "$Id: interactive.c,v 1.21 2002/01/25 15:08:59 stelian Exp $"; #endif /* not lint */ +#include #include #include #ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else #include +#endif #include #else /* __linux__ */ #include @@ -75,6 +77,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)) /* @@ -83,12 +96,12 @@ extern char * __progname; static int runshell; static jmp_buf reset; static char *nextarg = NULL; - +static int pflag = 0; /* prompt mode */ /* * Structure and routines associated with listing directories. */ struct afile { - ino_t fnum; /* inode number of file */ + dump_ino_t fnum; /* inode number of file */ char *fname; /* file name */ short len; /* name length */ char prefix; /* prefix character */ @@ -116,21 +129,24 @@ static void printlist __P((char *, char *)); void runcmdshell(void) { - register struct entry *np; - ino_t ino; + struct entry *np; + dump_ino_t ino; struct arglist arglist; char curdir[MAXPATHLEN]; char name[MAXPATHLEN]; char cmd[BUFSIZ]; +#if HAVE_READLINE + initialize_readline(); +#endif arglist.freeglob = 0; arglist.argcnt = 0; arglist.glob.gl_flags = GLOB_ALTDIRFUNC; arglist.glob.gl_opendir = (void *)rst_opendir; arglist.glob.gl_readdir = (void *)glob_readdir; arglist.glob.gl_closedir = (void *)rst_closedir; - arglist.glob.gl_lstat = glob_stat; - arglist.glob.gl_stat = glob_stat; + arglist.glob.gl_lstat = (int (*)(const char *, void *))glob_stat; + arglist.glob.gl_stat = (int (*)(const char *, void *))glob_stat; canon("/", curdir, sizeof(curdir)); loop: if (setjmp(reset) != 0) { @@ -207,7 +223,7 @@ loop: if (strncmp(cmd, "help", strlen(cmd)) != 0) goto bad; case '?': - fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "Available commands are:\n", "\tls [arg] - list directory\n", "\tcd arg - change directory\n", @@ -222,6 +238,7 @@ loop: "\twhat - list dump header information\n", "\tverbose - toggle verbose flag", " (useful with ``ls'')\n", + "\tprompt - toggle the prompt display\n", "\thelp or `?' - print this list\n", "If no `arg' is supplied, the current", " directory is used\n"); @@ -238,12 +255,26 @@ loop: * Print current directory. */ case 'p': - if (strncmp(cmd, "pwd", strlen(cmd)) != 0) - goto bad; - if (curdir[1] == '\0') - fprintf(stderr, "/\n"); - else - fprintf(stderr, "%s\n", &curdir[1]); + if (strncmp(cmd, "pwd", strlen(cmd)) == 0) { + if (curdir[1] == '\0') + fprintf(stderr, "/\n"); + else + fprintf(stderr, "%s\n", &curdir[1]); + } + /* + * Toggle prompt mode. + */ + else if (strncmp(cmd, "prompt", strlen(cmd)) == 0) { + if (pflag) { + fprintf(stderr, "prompt mode off\n"); + pflag = 0; + break; + } + fprintf(stderr, "prompt mode on\n"); + pflag++; + break; + } + else goto bad; break; /* * Quit. @@ -285,6 +316,7 @@ loop: if (strncmp(cmd, "what", strlen(cmd)) != 0) goto bad; printdumpinfo(); + printvolinfo(); break; /* * Turn on debugging. @@ -325,7 +357,7 @@ loop: static void getcmd(char *curdir, char *cmd, char *name, int size, struct arglist *ap) { - register char *cp; + char *cp; static char input[BUFSIZ]; char output[BUFSIZ]; # define rawname input /* save space by reusing input buffer */ @@ -340,8 +372,17 @@ 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 { - fprintf(stderr, "%s > ", __progname); + if (pflag) + fprintf(stderr, "%s:%s:%s > ", + __progname, + spcl.c_filesys, + curdir[1] ? &curdir[1] : "/"); + else + fprintf(stderr, "%s > ", __progname); (void) fflush(stderr); (void) fgets(input, BUFSIZ, terminal); } while (!feof(terminal) && input[0] == '\n'); @@ -349,6 +390,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'; @@ -411,7 +453,7 @@ retnext: static char * copynext(char *input, char *output) { - register char *cp, *bp; + char *cp, *bp; char quote; for (cp = input; *cp == ' ' || *cp == '\t'; cp++) @@ -442,7 +484,7 @@ copynext(char *input, char *output) */ quote = *cp++; while (*cp != quote && *cp != '\0') - *bp++ = *cp++ | 0200; + *bp++ = *cp++; if (*cp++ == '\0') { fprintf(stderr, "missing %c\n", quote); cp--; @@ -460,7 +502,7 @@ copynext(char *input, char *output) void canon(char *rawname, char *canonname, int len) { - register char *cp, *np; + char *cp, *np; if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) (void) strcpy(canonname, ""); @@ -512,8 +554,8 @@ canon(char *rawname, char *canonname, int len) static void printlist(char *name, char *basename) { - register struct afile *fp, *list, *listp = NULL; - register struct direct *dp; + struct afile *fp, *list, *listp = NULL; + struct direct *dp; struct afile single; RST_DIR *dirp; int entries, len, namelen; @@ -657,7 +699,7 @@ mkentry(char *name, struct direct *dp, struct afile *fp) static void formatf(struct afile *list, int nentry) { - register struct afile *fp, *endlist; + struct afile *fp, *endlist; int width, bigino, haveprefix, havepostfix; int i, j, w, precision = 0, columns, lines; @@ -694,7 +736,7 @@ formatf(struct afile *list, int nentry) for (j = 0; j < columns; j++) { fp = &list[j * lines + i]; if (vflag) { - fprintf(stderr, "%*ld ", precision, fp->fnum); + fprintf(stderr, "%*ld ", precision, (long)fp->fnum); fp->len += precision + 1; } if (haveprefix) { @@ -754,7 +796,7 @@ glob_readdir(RST_DIR *dirp) static int glob_stat(const char *name, struct stat *stp) { - register struct direct *dp; + struct direct *dp; dp = pathsearch(name); if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) || (!vflag && dp->d_ino == WINO)) @@ -790,3 +832,198 @@ 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'; + rl_instream = terminal; +} + +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 */