Bugzilla – Attachment 59 Details for
Bug 200
readline support for sftp
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch Discussed above
portable-readline.patch (text/plain), 8.50 KB, created by
Ben Lindstrom
on 2002-04-03 03:37:59 AEST
(
hide
)
Description:
Patch Discussed above
Filename:
MIME Type:
Creator:
Ben Lindstrom
Created:
2002-04-03 03:37:59 AEST
Size:
8.50 KB
patch
obsolete
>Index: Makefile.in >=================================================================== >RCS file: /var/cvs/openssh/Makefile.in,v >retrieving revision 1.200 >diff -u -r1.200 Makefile.in >--- Makefile.in 22 Mar 2002 02:30:43 -0000 1.200 >+++ Makefile.in 2 Apr 2002 17:04:38 -0000 >@@ -28,9 +28,10 @@ > > CC=@CC@ > LD=@LD@ >-CFLAGS=@CFLAGS@ >+CFLAGS=@CFLAGS@ -DREADLINE > CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ > LIBS=@LIBS@ >+LIBREADLINE=-lreadline -lcurses > LIBPAM=@LIBPAM@ > LIBWRAP=@LIBWRAP@ > AR=@AR@ >@@ -123,7 +124,7 @@ > $(LD) -o $@ sftp-server.o sftp-common.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) > > sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o >- $(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) >+ $(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBREADLINE) > > ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o > $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) >Index: sftp-int.c >=================================================================== >RCS file: /var/cvs/openssh/sftp-int.c,v >retrieving revision 1.34 >diff -u -r1.34 sftp-int.c >--- sftp-int.c 22 Mar 2002 02:47:29 -0000 1.34 >+++ sftp-int.c 2 Apr 2002 17:04:48 -0000 >@@ -28,6 +28,11 @@ > #include "includes.h" > RCSID("$OpenBSD: sftp-int.c,v 1.45 2002/03/19 06:32:56 mpech Exp $"); > >+#ifdef READLINE >+#include <readline/readline.h> >+#include <readline/history.h> >+#endif /* READLINE */ >+ > #include "buffer.h" > #include "xmalloc.h" > #include "log.h" >@@ -75,44 +80,50 @@ > #define I_SYMLINK 21 > #define I_VERSION 22 > >+/* Globing Mode */ >+#define M_NONE 0 >+#define M_REMOTE 1 >+#define M_LOCAL 2 >+ > struct CMD { > const char *c; > const int n; >+ const int m; > }; > > const struct CMD cmds[] = { >- { "bye", I_QUIT }, >- { "cd", I_CHDIR }, >- { "chdir", I_CHDIR }, >- { "chgrp", I_CHGRP }, >- { "chmod", I_CHMOD }, >- { "chown", I_CHOWN }, >- { "dir", I_LS }, >- { "exit", I_QUIT }, >- { "get", I_GET }, >- { "mget", I_GET }, >- { "help", I_HELP }, >- { "lcd", I_LCHDIR }, >- { "lchdir", I_LCHDIR }, >- { "lls", I_LLS }, >- { "lmkdir", I_LMKDIR }, >- { "ln", I_SYMLINK }, >- { "lpwd", I_LPWD }, >- { "ls", I_LS }, >- { "lumask", I_LUMASK }, >- { "mkdir", I_MKDIR }, >- { "put", I_PUT }, >- { "mput", I_PUT }, >- { "pwd", I_PWD }, >- { "quit", I_QUIT }, >- { "rename", I_RENAME }, >- { "rm", I_RM }, >- { "rmdir", I_RMDIR }, >- { "symlink", I_SYMLINK }, >- { "version", I_VERSION }, >- { "!", I_SHELL }, >- { "?", I_HELP }, >- { NULL, -1} >+ { "bye", I_QUIT, M_NONE }, >+ { "cd", I_CHDIR, M_REMOTE }, >+ { "chdir", I_CHDIR, M_REMOTE }, >+ { "chgrp", I_CHGRP, M_REMOTE }, >+ { "chmod", I_CHMOD, M_REMOTE }, >+ { "chown", I_CHOWN, M_REMOTE }, >+ { "dir", I_LS, M_REMOTE }, >+ { "exit", I_QUIT, M_NONE }, >+ { "get", I_GET, M_REMOTE }, >+ { "mget", I_GET, M_REMOTE }, >+ { "help", I_HELP, M_NONE }, >+ { "lcd", I_LCHDIR, M_LOCAL }, >+ { "lchdir", I_LCHDIR, M_LOCAL }, >+ { "lls", I_LLS, M_LOCAL }, >+ { "lmkdir", I_LMKDIR, M_LOCAL }, >+ { "ln", I_SYMLINK, M_REMOTE }, >+ { "lpwd", I_LPWD, M_NONE }, >+ { "ls", I_LS, M_REMOTE }, >+ { "lumask", I_LUMASK, M_NONE }, >+ { "mkdir", I_MKDIR, M_REMOTE }, >+ { "put", I_PUT, M_REMOTE }, >+ { "mput", I_PUT, M_REMOTE }, >+ { "pwd", I_PWD, M_NONE }, >+ { "quit", I_QUIT, M_NONE }, >+ { "rename", I_RENAME, M_REMOTE }, >+ { "rm", I_RM, M_REMOTE }, >+ { "rmdir", I_RMDIR, M_REMOTE }, >+ { "symlink", I_SYMLINK, M_REMOTE }, >+ { "version", I_VERSION, M_NONE }, >+ { "!", I_SHELL, M_NONE }, >+ { "?", I_HELP, M_NONE }, >+ { NULL, -1, -1 } > }; > > static void >@@ -854,13 +865,179 @@ > return(0); > } > >+ >+int command; >+struct sftp_conn *conn; >+char *pwd; >+ >+#ifdef READLINE >+static char * >+rl_remote_match(char *text, int state) >+{ >+ static glob_t g; >+ static int pwd_len; >+ >+ if (state == 0) { >+ int len; >+ char *path = xstrdup(text); >+ >+ /* Is the the path relative or absolute? */ >+ pwd_len = 0; >+ if (path[0] != '/') >+ pwd_len = strlen(pwd) + 1; >+ >+ /* Setup remote globing as a cheap completion method */ >+ path = make_absolute(path, pwd); >+ len = strlen(path) + 2; >+ path = xrealloc(path, len); >+ strlcat(path, "*", len); >+ globfree(&g); >+ if (remote_glob(conn, path, GLOB_NOCHECK, NULL, &g)) { >+ xfree(path); >+ return(NULL); >+ } >+ xfree(path); >+ rl_completion_append_character = ' '; >+ } >+ if (state < g.gl_matchc) { >+ char *match = xstrdup(g.gl_pathv[state] + pwd_len); >+ if (g.gl_matchc == 1 && remote_is_dir(conn, g.gl_pathv[state])) >+ rl_completion_append_character = '/'; >+ return(match); >+ } >+ return(NULL); >+} >+ >+static void >+rl_remote_list(char **matches, int len, int max) >+{ >+ char **newmatches = xmalloc((len + 1) * sizeof(char *)); >+ int new_max = 0, x = 0; >+ >+ for (x = 0; x <= len; x++) { >+ char *tmp = strrchr(matches[x], '/'); >+ int len; >+ if (tmp != NULL) >+ newmatches[x] = xstrdup(tmp + 1); >+ else >+ newmatches[x] = xstrdup(matches[x]); >+ >+ len = strlen(newmatches[x]); >+ if (len > new_max) >+ new_max = len; >+ } >+ rl_display_match_list(newmatches, len, new_max); >+ rl_forced_update_display(); >+} >+ >+static char * >+glob_match(char *text, int state) >+{ >+ char *ret = NULL; >+ >+ if (command != -1) { >+ switch(cmds[command].m) { >+ case M_REMOTE: /* Home grown matching function */ >+ rl_completion_display_matches_hook = >+ (VFunction *) rl_remote_list; >+ ret = rl_remote_match(text, state); >+ break; >+ case M_LOCAL: /* Built in readline function */ >+ rl_completion_display_matches_hook = NULL; >+ ret = rl_filename_completion_function(text, state); >+ break; >+ case M_NONE: >+ break; >+ default: >+ fatal("glob_match: Illegal glob mode found"); >+ } >+ } >+ return(ret); >+} >+ >+static char * >+cmd_match(char *text, int state) >+{ >+ static int ndx, len; >+ const char *name; >+ >+ if (state == 0) { >+ len = strlen(text); >+ ndx = 0; >+ } >+ >+ while ((name = cmds[ndx++].c) != NULL) >+ if (strncmp(name, text, len) == 0) >+ return(xstrdup(name)); >+ >+ return(NULL); >+} >+ >+static char ** >+sftp_completion(char *cmd, int start, int end) >+{ >+ int x; >+ char *func, *cp; >+ char **matches = NULL; >+ >+ /* Command completion or default to file completion */ >+ if (start == 0) >+ matches = rl_completion_matches(cmd, cmd_match); >+ >+ /* Guess at what the command the users is doing */ >+ func = xstrdup(rl_line_buffer); >+ cp = strrchr(func, ' '); >+ if (cp) >+ *cp = '\0'; >+ >+ command = -1; >+ for (x = 0; cmds[x].c != NULL; x++) >+ if (!strcmp(func, cmds[x].c)) >+ command = x; >+ xfree(func); >+ return(matches); >+} >+ >+static char * >+sftp_readline(char *prompt) >+{ >+ char *cp; >+ >+ cp = readline(prompt); >+ if (cp) >+ add_history(cp); >+ >+ return cp; >+} >+ >+#else >+ >+static char * >+sftp_readline(char *prompt) >+{ >+ char *cp; >+ char cmd[1024]; >+ >+ printf("%s", prompt); >+ >+ if (fgets(cmd, sizeof(cmd), infile) == NULL) >+ return(NULL); >+ else if (infile != stdin) /* Bluff typing */ >+ printf("%s", cmd); >+ >+ cp = strrchr(cmd, '\n'); >+ if (cp) >+ *cp = '\0'; >+ >+ return xstrdup(cmd); >+} >+#endif /* READLINE */ >+ >+ > void > interactive_loop(int fd_in, int fd_out, char *file1, char *file2) > { >- char *pwd; > char *dir = NULL; >- char cmd[2048]; >- struct sftp_conn *conn; > > conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); > if (conn == NULL) >@@ -871,6 +1048,8 @@ > fatal("Need cwd"); > > if (file1 != NULL) { >+ char cmd[1024]; >+ > dir = xstrdup(file1); > dir = make_absolute(dir, pwd); > >@@ -891,32 +1070,40 @@ > } > xfree(dir); > } >-#if HAVE_SETVBUF >- setvbuf(stdout, NULL, _IOLBF, 0); >- setvbuf(infile, NULL, _IOLBF, 0); >+#ifdef READLINE >+ /* Tell readline what program we are */ >+ rl_readline_name = "sftp"; >+ >+ /* Commandline and file completion */ >+ rl_attempted_completion_function = (CPPFunction *)sftp_completion; >+ rl_completion_entry_function = (Function *)glob_match; >+ >+ /* Map our input correct, very important for batch mode */ >+ rl_instream = infile; > #else >- setlinebuf(stdout); >- setlinebuf(infile); >+# if HAVE_SETVBUF >+ setvbuf(stdout, NULL, _IOLBF, 0); >+ setvbuf(infile, NULL, _IOLBF, 0); >+# else >+ setlinebuf(stdout); >+ setlinebuf(infile); >+# endif > #endif > > for (;;) { > char *cp; >- >- printf("sftp> "); >- >- /* XXX: use libedit */ >- if (fgets(cmd, sizeof(cmd), infile) == NULL) { >+ cp = sftp_readline("sftp> "); >+ if (cp == NULL) { > printf("\n"); > break; >- } else if (infile != stdin) /* Bluff typing */ >- printf("%s", cmd); >- >- cp = strrchr(cmd, '\n'); >- if (cp) >- *cp = '\0'; >+ } > >- if (parse_dispatch_command(conn, cmd, &pwd)) >+ if (parse_dispatch_command(conn, cp, &pwd)) { >+ xfree(cp); > break; >+ } >+ xfree(cp); > } > xfree(pwd); > } >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 200
:
59
|
1428
|
1743