summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c104
1 files changed, 82 insertions, 22 deletions
diff --git a/sftp.c b/sftp.c
index f01c9194c..f8553ed82 100644
--- a/sftp.c
+++ b/sftp.c
@@ -16,7 +16,13 @@
16 16
17#include "includes.h" 17#include "includes.h"
18 18
19RCSID("$OpenBSD: sftp.c,v 1.56 2004/07/11 17:48:47 deraadt Exp $"); 19RCSID("$OpenBSD: sftp.c,v 1.62 2005/02/20 22:59:06 djm Exp $");
20
21#ifdef USE_LIBEDIT
22#include <histedit.h>
23#else
24typedef void EditLine;
25#endif
20 26
21#include "buffer.h" 27#include "buffer.h"
22#include "xmalloc.h" 28#include "xmalloc.h"
@@ -144,8 +150,10 @@ int interactive_loop(int fd_in, int fd_out, char *file1, char *file2);
144static void 150static void
145killchild(int signo) 151killchild(int signo)
146{ 152{
147 if (sshpid > 1) 153 if (sshpid > 1) {
148 kill(sshpid, SIGTERM); 154 kill(sshpid, SIGTERM);
155 waitpid(sshpid, NULL, 0);
156 }
149 157
150 _exit(1); 158 _exit(1);
151} 159}
@@ -154,9 +162,11 @@ static void
154cmd_interrupt(int signo) 162cmd_interrupt(int signo)
155{ 163{
156 const char msg[] = "\rInterrupt \n"; 164 const char msg[] = "\rInterrupt \n";
165 int olderrno = errno;
157 166
158 write(STDERR_FILENO, msg, sizeof(msg) - 1); 167 write(STDERR_FILENO, msg, sizeof(msg) - 1);
159 interrupted = 1; 168 interrupted = 1;
169 errno = olderrno;
160} 170}
161 171
162static void 172static void
@@ -256,7 +266,7 @@ path_strip(char *path, char *strip)
256 return (xstrdup(path)); 266 return (xstrdup(path));
257 267
258 len = strlen(strip); 268 len = strlen(strip);
259 if (strip != NULL && strncmp(path, strip, len) == 0) { 269 if (strncmp(path, strip, len) == 0) {
260 if (strip[len - 1] != '/' && path[len] == '/') 270 if (strip[len - 1] != '/' && path[len] == '/')
261 len++; 271 len++;
262 return (xstrdup(path + len)); 272 return (xstrdup(path + len));
@@ -738,12 +748,14 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
738{ 748{
739 glob_t g; 749 glob_t g;
740 int i, c = 1, colspace = 0, columns = 1; 750 int i, c = 1, colspace = 0, columns = 1;
741 Attrib *a; 751 Attrib *a = NULL;
742 752
743 memset(&g, 0, sizeof(g)); 753 memset(&g, 0, sizeof(g));
744 754
745 if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE, 755 if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
746 NULL, &g)) { 756 NULL, &g) || (g.gl_pathc && !g.gl_matchc)) {
757 if (g.gl_pathc)
758 globfree(&g);
747 error("Can't ls: \"%s\" not found", path); 759 error("Can't ls: \"%s\" not found", path);
748 return (-1); 760 return (-1);
749 } 761 }
@@ -752,19 +764,21 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
752 goto out; 764 goto out;
753 765
754 /* 766 /*
755 * If the glob returns a single match, which is the same as the 767 * If the glob returns a single match and it is a directory,
756 * input glob, and it is a directory, then just list its contents 768 * then just list its contents.
757 */ 769 */
758 if (g.gl_pathc == 1 && 770 if (g.gl_matchc == 1) {
759 strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) { 771 if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) {
760 if ((a = do_lstat(conn, path, 1)) == NULL) {
761 globfree(&g); 772 globfree(&g);
762 return (-1); 773 return (-1);
763 } 774 }
764 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 775 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
765 S_ISDIR(a->perm)) { 776 S_ISDIR(a->perm)) {
777 int err;
778
779 err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
766 globfree(&g); 780 globfree(&g);
767 return (do_ls_dir(conn, path, strip_path, lflag)); 781 return (err);
768 } 782 }
769 } 783 }
770 784
@@ -784,7 +798,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
784 colspace = width / columns; 798 colspace = width / columns;
785 } 799 }
786 800
787 for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 801 for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) {
788 char *fname; 802 char *fname;
789 803
790 fname = path_strip(g.gl_pathv[i], strip_path); 804 fname = path_strip(g.gl_pathv[i], strip_path);
@@ -801,7 +815,8 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
801 * that the server returns as well as the filenames. 815 * that the server returns as well as the filenames.
802 */ 816 */
803 memset(&sb, 0, sizeof(sb)); 817 memset(&sb, 0, sizeof(sb));
804 a = do_lstat(conn, g.gl_pathv[i], 1); 818 if (a == NULL)
819 a = do_lstat(conn, g.gl_pathv[i], 1);
805 if (a != NULL) 820 if (a != NULL)
806 attrib_to_stat(a, &sb); 821 attrib_to_stat(a, &sb);
807 lname = ls_file(fname, &sb, 1); 822 lname = ls_file(fname, &sb, 1);
@@ -1206,6 +1221,14 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1206 return (0); 1221 return (0);
1207} 1222}
1208 1223
1224#ifdef USE_LIBEDIT
1225static char *
1226prompt(EditLine *el)
1227{
1228 return ("sftp> ");
1229}
1230#endif
1231
1209int 1232int
1210interactive_loop(int fd_in, int fd_out, char *file1, char *file2) 1233interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1211{ 1234{
@@ -1214,6 +1237,27 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1214 char cmd[2048]; 1237 char cmd[2048];
1215 struct sftp_conn *conn; 1238 struct sftp_conn *conn;
1216 int err; 1239 int err;
1240 EditLine *el = NULL;
1241#ifdef USE_LIBEDIT
1242 History *hl = NULL;
1243 HistEvent hev;
1244 extern char *__progname;
1245
1246 if (!batchmode && isatty(STDIN_FILENO)) {
1247 if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)
1248 fatal("Couldn't initialise editline");
1249 if ((hl = history_init()) == NULL)
1250 fatal("Couldn't initialise editline history");
1251 history(hl, &hev, H_SETSIZE, 100);
1252 el_set(el, EL_HIST, history, hl);
1253
1254 el_set(el, EL_PROMPT, prompt);
1255 el_set(el, EL_EDITOR, "emacs");
1256 el_set(el, EL_TERMINAL, NULL);
1257 el_set(el, EL_SIGNAL, 1);
1258 el_source(el, NULL);
1259 }
1260#endif /* USE_LIBEDIT */
1217 1261
1218 conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); 1262 conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
1219 if (conn == NULL) 1263 if (conn == NULL)
@@ -1230,8 +1274,11 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1230 if (remote_is_dir(conn, dir) && file2 == NULL) { 1274 if (remote_is_dir(conn, dir) && file2 == NULL) {
1231 printf("Changing to: %s\n", dir); 1275 printf("Changing to: %s\n", dir);
1232 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); 1276 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
1233 if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) 1277 if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) {
1278 xfree(dir);
1279 xfree(pwd);
1234 return (-1); 1280 return (-1);
1281 }
1235 } else { 1282 } else {
1236 if (file2 == NULL) 1283 if (file2 == NULL)
1237 snprintf(cmd, sizeof cmd, "get %s", dir); 1284 snprintf(cmd, sizeof cmd, "get %s", dir);
@@ -1261,17 +1308,29 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
1261 1308
1262 signal(SIGINT, SIG_IGN); 1309 signal(SIGINT, SIG_IGN);
1263 1310
1264 printf("sftp> "); 1311 if (el == NULL) {
1312 printf("sftp> ");
1313 if (fgets(cmd, sizeof(cmd), infile) == NULL) {
1314 printf("\n");
1315 break;
1316 }
1317 if (batchmode) /* Echo command */
1318 printf("%s", cmd);
1319 } else {
1320#ifdef USE_LIBEDIT
1321 const char *line;
1322 int count = 0;
1265 1323
1266 /* XXX: use libedit */ 1324 if ((line = el_gets(el, &count)) == NULL || count <= 0)
1267 if (fgets(cmd, sizeof(cmd), infile) == NULL) { 1325 break;
1268 printf("\n"); 1326 history(hl, &hev, H_ENTER, line);
1269 break; 1327 if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
1328 fprintf(stderr, "Error: input line too long\n");
1329 continue;
1330 }
1331#endif /* USE_LIBEDIT */
1270 } 1332 }
1271 1333
1272 if (batchmode) /* Echo command */
1273 printf("%s", cmd);
1274
1275 cp = strrchr(cmd, '\n'); 1334 cp = strrchr(cmd, '\n');
1276 if (cp) 1335 if (cp)
1277 *cp = '\0'; 1336 *cp = '\0';
@@ -1420,6 +1479,7 @@ main(int argc, char **argv)
1420 fatal("%s (%s).", strerror(errno), optarg); 1479 fatal("%s (%s).", strerror(errno), optarg);
1421 showprogress = 0; 1480 showprogress = 0;
1422 batchmode = 1; 1481 batchmode = 1;
1482 addargs(&args, "-obatchmode yes");
1423 break; 1483 break;
1424 case 'P': 1484 case 'P':
1425 sftp_direct = optarg; 1485 sftp_direct = optarg;