View | Details | Raw Unified | Return to bug 200 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile.in (-2 / +3 lines)
Lines 28-36 Link Here
28
28
29
CC=@CC@
29
CC=@CC@
30
LD=@LD@
30
LD=@LD@
31
CFLAGS=@CFLAGS@
31
CFLAGS=@CFLAGS@ -DREADLINE
32
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
32
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
33
LIBS=@LIBS@
33
LIBS=@LIBS@
34
LIBREADLINE=-lreadline -lcurses
34
LIBPAM=@LIBPAM@
35
LIBPAM=@LIBPAM@
35
LIBWRAP=@LIBWRAP@
36
LIBWRAP=@LIBWRAP@
36
AR=@AR@
37
AR=@AR@
Lines 123-129 Link Here
123
	$(LD) -o $@ sftp-server.o sftp-common.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 
124
	$(LD) -o $@ sftp-server.o sftp-common.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 
124
125
125
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o
126
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o
126
	$(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
127
	$(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBREADLINE)
127
128
128
ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o
129
ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o
129
	$(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
130
	$(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
(-)sftp-int.c (-52 / +239 lines)
Lines 28-33 Link Here
28
#include "includes.h"
28
#include "includes.h"
29
RCSID("$OpenBSD: sftp-int.c,v 1.45 2002/03/19 06:32:56 mpech Exp $");
29
RCSID("$OpenBSD: sftp-int.c,v 1.45 2002/03/19 06:32:56 mpech Exp $");
30
30
31
#ifdef READLINE
32
#include <readline/readline.h>
33
#include <readline/history.h>
34
#endif /* READLINE */
35
31
#include "buffer.h"
36
#include "buffer.h"
32
#include "xmalloc.h"
37
#include "xmalloc.h"
33
#include "log.h"
38
#include "log.h"
Lines 75-118 Link Here
75
#define I_SYMLINK	21
80
#define I_SYMLINK	21
76
#define I_VERSION	22
81
#define I_VERSION	22
77
82
83
/* Globing Mode */
84
#define M_NONE		0
85
#define M_REMOTE	1
86
#define M_LOCAL		2
87
78
struct CMD {
88
struct CMD {
79
	const char *c;
89
	const char *c;
80
	const int n;
90
	const int n;
91
	const int m;
81
};
92
};
82
93
83
const struct CMD cmds[] = {
94
const struct CMD cmds[] = {
84
	{ "bye",	I_QUIT },
95
	{ "bye",        I_QUIT,		M_NONE  }, 
85
	{ "cd",		I_CHDIR },
96
	{ "cd",		I_CHDIR,	M_REMOTE },
86
	{ "chdir",	I_CHDIR },
97
	{ "chdir",	I_CHDIR,	M_REMOTE },
87
	{ "chgrp",	I_CHGRP },
98
	{ "chgrp",	I_CHGRP,	M_REMOTE },
88
	{ "chmod",	I_CHMOD },
99
	{ "chmod",	I_CHMOD,	M_REMOTE },
89
	{ "chown",	I_CHOWN },
100
	{ "chown",	I_CHOWN,	M_REMOTE },
90
	{ "dir",	I_LS },
101
	{ "dir",	I_LS,		M_REMOTE },
91
	{ "exit",	I_QUIT },
102
	{ "exit",	I_QUIT,		M_NONE },
92
	{ "get",	I_GET },
103
	{ "get",	I_GET,		M_REMOTE },
93
	{ "mget",	I_GET },
104
	{ "mget",	I_GET,		M_REMOTE },
94
	{ "help",	I_HELP },
105
	{ "help",	I_HELP,		M_NONE },
95
	{ "lcd",	I_LCHDIR },
106
	{ "lcd",	I_LCHDIR,	M_LOCAL },
96
	{ "lchdir",	I_LCHDIR },
107
	{ "lchdir",	I_LCHDIR,	M_LOCAL },
97
	{ "lls",	I_LLS },
108
	{ "lls",	I_LLS, 		M_LOCAL },
98
	{ "lmkdir",	I_LMKDIR },
109
	{ "lmkdir",	I_LMKDIR,	M_LOCAL },
99
	{ "ln",		I_SYMLINK },
110
	{ "ln",		I_SYMLINK, 	M_REMOTE },
100
	{ "lpwd",	I_LPWD },
111
	{ "lpwd",	I_LPWD,		M_NONE },
101
	{ "ls",		I_LS },
112
	{ "ls",		I_LS,		M_REMOTE },
102
	{ "lumask",	I_LUMASK },
113
	{ "lumask",	I_LUMASK,	M_NONE },
103
	{ "mkdir",	I_MKDIR },
114
	{ "mkdir",	I_MKDIR,	M_REMOTE },
104
	{ "put",	I_PUT },
115
	{ "put",	I_PUT,		M_REMOTE },
105
	{ "mput",	I_PUT },
116
	{ "mput",	I_PUT,		M_REMOTE },
106
	{ "pwd",	I_PWD },
117
	{ "pwd",	I_PWD,		M_NONE },
107
	{ "quit",	I_QUIT },
118
	{ "quit",	I_QUIT,		M_NONE },
108
	{ "rename",	I_RENAME },
119
	{ "rename",	I_RENAME,	M_REMOTE },
109
	{ "rm",		I_RM },
120
	{ "rm",		I_RM,		M_REMOTE },
110
	{ "rmdir",	I_RMDIR },
121
	{ "rmdir",	I_RMDIR,	M_REMOTE },
111
	{ "symlink",	I_SYMLINK },
122
	{ "symlink",	I_SYMLINK,	M_REMOTE },
112
	{ "version",	I_VERSION },
123
	{ "version",	I_VERSION,	M_NONE },
113
	{ "!",		I_SHELL },
124
	{ "!",		I_SHELL,	M_NONE },
114
	{ "?",		I_HELP },
125
	{ "?",		I_HELP,		M_NONE },
115
	{ NULL,			-1}
126
	{ NULL,		-1,		-1 }
116
};
127
};
117
128
118
static void
129
static void
Lines 854-866 Link Here
854
	return(0);
865
	return(0);
855
}
866
}
856
867
868
869
int command;
870
struct sftp_conn *conn;
871
char *pwd;
872
873
#ifdef READLINE 
874
static char *
875
rl_remote_match(char *text, int state)
876
{
877
	static glob_t g;
878
	static int pwd_len;
879
880
	if (state == 0) {
881
		int len;
882
		char *path = xstrdup(text);
883
884
		/* Is the the path relative or absolute? */
885
		pwd_len = 0;
886
		if (path[0] != '/')
887
		pwd_len = strlen(pwd) + 1;
888
889
		/* Setup remote globing as a cheap completion method */
890
		path = make_absolute(path, pwd);
891
		len = strlen(path) + 2;
892
		path = xrealloc(path, len);
893
		strlcat(path, "*", len);
894
		globfree(&g);
895
		if (remote_glob(conn, path, GLOB_NOCHECK, NULL, &g)) {
896
			xfree(path);
897
			return(NULL);
898
		}
899
		xfree(path);
900
		rl_completion_append_character = ' ';
901
	} 
902
	if (state < g.gl_matchc) {
903
		char *match = xstrdup(g.gl_pathv[state] + pwd_len); 
904
		if (g.gl_matchc == 1 && remote_is_dir(conn, g.gl_pathv[state])) 
905
			rl_completion_append_character = '/';
906
		return(match);
907
	}
908
	return(NULL);
909
}
910
911
static void
912
rl_remote_list(char **matches, int len, int max)
913
{
914
	char **newmatches = xmalloc((len + 1) * sizeof(char *));
915
	int new_max = 0, x = 0;
916
917
	for (x = 0; x <= len; x++) {
918
		char *tmp = strrchr(matches[x], '/');
919
		int len;
920
		if (tmp != NULL)
921
			newmatches[x] = xstrdup(tmp + 1);
922
		else
923
			newmatches[x] = xstrdup(matches[x]);
924
925
		len = strlen(newmatches[x]);
926
		if (len > new_max)
927
			new_max = len;
928
	}
929
	rl_display_match_list(newmatches, len, new_max);
930
	rl_forced_update_display();
931
}
932
933
static char *
934
glob_match(char *text, int state)
935
{
936
	char *ret = NULL;
937
938
	if (command != -1) {
939
		switch(cmds[command].m) {
940
		    case M_REMOTE: /* Home grown matching function */
941
			rl_completion_display_matches_hook = 
942
			    (VFunction *) rl_remote_list; 
943
			ret = rl_remote_match(text, state);
944
			break;
945
		    case M_LOCAL: /* Built in readline function */
946
			rl_completion_display_matches_hook = NULL;
947
			ret = rl_filename_completion_function(text, state);
948
			break;
949
		    case M_NONE:
950
			break;
951
		    default:
952
			fatal("glob_match: Illegal glob mode found");
953
		}
954
	}
955
	return(ret);
956
}
957
958
static char *
959
cmd_match(char *text, int state)
960
{
961
	static int ndx, len;
962
	const char *name;
963
964
	if (state == 0) {
965
		len = strlen(text);
966
		ndx = 0;
967
	}
968
969
	while ((name = cmds[ndx++].c) != NULL) 
970
		if (strncmp(name, text, len) == 0) 
971
			return(xstrdup(name));
972
973
	return(NULL);
974
}
975
976
static char **
977
sftp_completion(char *cmd, int start, int end)
978
{
979
	int x;
980
	char *func, *cp;
981
	char **matches = NULL;
982
983
	/* Command completion or default to file completion */
984
	if (start == 0) 
985
		matches = rl_completion_matches(cmd, cmd_match);
986
987
	/* Guess at what the command the users is doing */
988
	func = xstrdup(rl_line_buffer);
989
	cp = strrchr(func, ' ');
990
	if (cp)
991
		*cp = '\0';
992
993
	command = -1;
994
	for (x = 0; cmds[x].c != NULL; x++) 
995
		if (!strcmp(func, cmds[x].c)) 
996
			command = x;
997
	xfree(func);
998
	return(matches);
999
}
1000
1001
static char *
1002
sftp_readline(char *prompt)
1003
{
1004
	char *cp;
1005
1006
	cp = readline(prompt);
1007
	if (cp)
1008
		add_history(cp);
1009
1010
	return cp;
1011
}
1012
1013
#else
1014
1015
static char *
1016
sftp_readline(char *prompt)
1017
{
1018
	char *cp;
1019
	char cmd[1024];
1020
1021
	printf("%s", prompt);
1022
1023
	if (fgets(cmd, sizeof(cmd), infile) == NULL) 
1024
		return(NULL);
1025
	else if (infile != stdin) /* Bluff typing */
1026
		printf("%s", cmd);
1027
1028
	cp = strrchr(cmd, '\n');
1029
	if (cp)
1030
		*cp = '\0';
1031
1032
	return xstrdup(cmd);
1033
}
1034
#endif /* READLINE */
1035
1036
857
void
1037
void
858
interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1038
interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
859
{
1039
{
860
	char *pwd;
861
	char *dir = NULL;
1040
	char *dir = NULL;
862
	char cmd[2048];
863
	struct sftp_conn *conn;
864
1041
865
	conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
1042
	conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
866
	if (conn == NULL)
1043
	if (conn == NULL)
Lines 871-876 Link Here
871
		fatal("Need cwd");
1048
		fatal("Need cwd");
872
1049
873
	if (file1 != NULL) {
1050
	if (file1 != NULL) {
1051
		char cmd[1024];
1052
874
		dir = xstrdup(file1);
1053
		dir = xstrdup(file1);
875
		dir = make_absolute(dir, pwd);
1054
		dir = make_absolute(dir, pwd);
876
1055
Lines 891-922 Link Here
891
		}
1070
		}
892
		xfree(dir);
1071
		xfree(dir);
893
	}
1072
	}
894
#if HAVE_SETVBUF
1073
#ifdef READLINE
895
	setvbuf(stdout, NULL, _IOLBF, 0);
1074
	/* Tell readline what program we are */
896
	setvbuf(infile, NULL, _IOLBF, 0);
1075
	rl_readline_name = "sftp";
1076
1077
	/* Commandline and file completion */
1078
	rl_attempted_completion_function = (CPPFunction *)sftp_completion;
1079
	rl_completion_entry_function = (Function *)glob_match;
1080
1081
	/* Map our input correct, very important for batch mode */
1082
	rl_instream = infile;
897
#else
1083
#else
898
	setlinebuf(stdout);
1084
# if HAVE_SETVBUF
899
	setlinebuf(infile);
1085
        setvbuf(stdout, NULL, _IOLBF, 0);
1086
        setvbuf(infile, NULL, _IOLBF, 0);
1087
# else
1088
        setlinebuf(stdout);
1089
        setlinebuf(infile);
1090
# endif
900
#endif
1091
#endif
901
1092
902
	for (;;) {
1093
	for (;;) {
903
		char *cp;
1094
		char *cp;
904
1095
		cp = sftp_readline("sftp> ");
905
		printf("sftp> ");
1096
		if (cp == NULL) {
906
907
		/* XXX: use libedit */
908
		if (fgets(cmd, sizeof(cmd), infile) == NULL) {
909
			printf("\n");
1097
			printf("\n");
910
			break;
1098
			break;
911
		} else if (infile != stdin) /* Bluff typing */
1099
		}
912
			printf("%s", cmd);
913
914
		cp = strrchr(cmd, '\n');
915
		if (cp)
916
			*cp = '\0';
917
1100
918
		if (parse_dispatch_command(conn, cmd, &pwd))
1101
		if (parse_dispatch_command(conn, cp, &pwd)) {
1102
			xfree(cp);
919
			break;
1103
			break;
1104
		}
1105
		xfree(cp);
920
	}
1106
	}
921
	xfree(pwd);
1107
	xfree(pwd);
922
}
1108
}
1109

Return to bug 200