|
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 |
|