]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssh/sftp.c
zfs: merge openzfs/zfs@ef83e07db (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / crypto / openssh / sftp.c
1 /* $OpenBSD: sftp.c,v 1.212 2021/09/11 09:05:50 schwarze Exp $ */
2 /*
3  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include "includes.h"
19
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 #ifdef HAVE_SYS_STAT_H
23 # include <sys/stat.h>
24 #endif
25 #include <sys/param.h>
26 #include <sys/socket.h>
27 #include <sys/wait.h>
28 #ifdef HAVE_SYS_STATVFS_H
29 #include <sys/statvfs.h>
30 #endif
31
32 #include <ctype.h>
33 #include <errno.h>
34
35 #ifdef HAVE_PATHS_H
36 # include <paths.h>
37 #endif
38 #ifdef HAVE_LIBGEN_H
39 #include <libgen.h>
40 #endif
41 #ifdef HAVE_LOCALE_H
42 # include <locale.h>
43 #endif
44 #ifdef USE_LIBEDIT
45 #include <histedit.h>
46 #else
47 typedef void EditLine;
48 #endif
49 #include <limits.h>
50 #include <signal.h>
51 #include <stdarg.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <unistd.h>
56
57 #ifdef HAVE_UTIL_H
58 # include <util.h>
59 #endif
60
61 #include "xmalloc.h"
62 #include "log.h"
63 #include "pathnames.h"
64 #include "misc.h"
65 #include "utf8.h"
66
67 #include "sftp.h"
68 #include "ssherr.h"
69 #include "sshbuf.h"
70 #include "sftp-common.h"
71 #include "sftp-client.h"
72
73 /* File to read commands from */
74 FILE* infile;
75
76 /* Are we in batchfile mode? */
77 int batchmode = 0;
78
79 /* PID of ssh transport process */
80 static volatile pid_t sshpid = -1;
81
82 /* Suppress diagnostic messages */
83 int quiet = 0;
84
85 /* This is set to 0 if the progressmeter is not desired. */
86 int showprogress = 1;
87
88 /* When this option is set, we always recursively download/upload directories */
89 int global_rflag = 0;
90
91 /* When this option is set, we resume download or upload if possible */
92 int global_aflag = 0;
93
94 /* When this option is set, the file transfers will always preserve times */
95 int global_pflag = 0;
96
97 /* When this option is set, transfers will have fsync() called on each file */
98 int global_fflag = 0;
99
100 /* SIGINT received during command processing */
101 volatile sig_atomic_t interrupted = 0;
102
103 /* I wish qsort() took a separate ctx for the comparison function...*/
104 int sort_flag;
105 glob_t *sort_glob;
106
107 /* Context used for commandline completion */
108 struct complete_ctx {
109         struct sftp_conn *conn;
110         char **remote_pathp;
111 };
112
113 int remote_glob(struct sftp_conn *, const char *, int,
114     int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
115
116 extern char *__progname;
117
118 /* Separators for interactive commands */
119 #define WHITESPACE " \t\r\n"
120
121 /* ls flags */
122 #define LS_LONG_VIEW    0x0001  /* Full view ala ls -l */
123 #define LS_SHORT_VIEW   0x0002  /* Single row view ala ls -1 */
124 #define LS_NUMERIC_VIEW 0x0004  /* Long view with numeric uid/gid */
125 #define LS_NAME_SORT    0x0008  /* Sort by name (default) */
126 #define LS_TIME_SORT    0x0010  /* Sort by mtime */
127 #define LS_SIZE_SORT    0x0020  /* Sort by file size */
128 #define LS_REVERSE_SORT 0x0040  /* Reverse sort order */
129 #define LS_SHOW_ALL     0x0080  /* Don't skip filenames starting with '.' */
130 #define LS_SI_UNITS     0x0100  /* Display sizes as K, M, G, etc. */
131
132 #define VIEW_FLAGS      (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW|LS_SI_UNITS)
133 #define SORT_FLAGS      (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
134
135 /* Commands for interactive mode */
136 enum sftp_command {
137         I_CHDIR = 1,
138         I_CHGRP,
139         I_CHMOD,
140         I_CHOWN,
141         I_DF,
142         I_GET,
143         I_HELP,
144         I_LCHDIR,
145         I_LINK,
146         I_LLS,
147         I_LMKDIR,
148         I_LPWD,
149         I_LS,
150         I_LUMASK,
151         I_MKDIR,
152         I_PUT,
153         I_PWD,
154         I_QUIT,
155         I_REGET,
156         I_RENAME,
157         I_REPUT,
158         I_RM,
159         I_RMDIR,
160         I_SHELL,
161         I_SYMLINK,
162         I_VERSION,
163         I_PROGRESS,
164 };
165
166 struct CMD {
167         const char *c;
168         const int n;
169         const int t;
170 };
171
172 /* Type of completion */
173 #define NOARGS  0
174 #define REMOTE  1
175 #define LOCAL   2
176
177 static const struct CMD cmds[] = {
178         { "bye",        I_QUIT,         NOARGS  },
179         { "cd",         I_CHDIR,        REMOTE  },
180         { "chdir",      I_CHDIR,        REMOTE  },
181         { "chgrp",      I_CHGRP,        REMOTE  },
182         { "chmod",      I_CHMOD,        REMOTE  },
183         { "chown",      I_CHOWN,        REMOTE  },
184         { "df",         I_DF,           REMOTE  },
185         { "dir",        I_LS,           REMOTE  },
186         { "exit",       I_QUIT,         NOARGS  },
187         { "get",        I_GET,          REMOTE  },
188         { "help",       I_HELP,         NOARGS  },
189         { "lcd",        I_LCHDIR,       LOCAL   },
190         { "lchdir",     I_LCHDIR,       LOCAL   },
191         { "lls",        I_LLS,          LOCAL   },
192         { "lmkdir",     I_LMKDIR,       LOCAL   },
193         { "ln",         I_LINK,         REMOTE  },
194         { "lpwd",       I_LPWD,         LOCAL   },
195         { "ls",         I_LS,           REMOTE  },
196         { "lumask",     I_LUMASK,       NOARGS  },
197         { "mkdir",      I_MKDIR,        REMOTE  },
198         { "mget",       I_GET,          REMOTE  },
199         { "mput",       I_PUT,          LOCAL   },
200         { "progress",   I_PROGRESS,     NOARGS  },
201         { "put",        I_PUT,          LOCAL   },
202         { "pwd",        I_PWD,          REMOTE  },
203         { "quit",       I_QUIT,         NOARGS  },
204         { "reget",      I_REGET,        REMOTE  },
205         { "rename",     I_RENAME,       REMOTE  },
206         { "reput",      I_REPUT,        LOCAL   },
207         { "rm",         I_RM,           REMOTE  },
208         { "rmdir",      I_RMDIR,        REMOTE  },
209         { "symlink",    I_SYMLINK,      REMOTE  },
210         { "version",    I_VERSION,      NOARGS  },
211         { "!",          I_SHELL,        NOARGS  },
212         { "?",          I_HELP,         NOARGS  },
213         { NULL,         -1,             -1      }
214 };
215
216 /* ARGSUSED */
217 static void
218 killchild(int signo)
219 {
220         pid_t pid;
221
222         pid = sshpid;
223         if (pid > 1) {
224                 kill(pid, SIGTERM);
225                 waitpid(pid, NULL, 0);
226         }
227
228         _exit(1);
229 }
230
231 /* ARGSUSED */
232 static void
233 suspchild(int signo)
234 {
235         if (sshpid > 1) {
236                 kill(sshpid, signo);
237                 while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR)
238                         continue;
239         }
240         kill(getpid(), SIGSTOP);
241 }
242
243 /* ARGSUSED */
244 static void
245 cmd_interrupt(int signo)
246 {
247         const char msg[] = "\rInterrupt  \n";
248         int olderrno = errno;
249
250         (void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
251         interrupted = 1;
252         errno = olderrno;
253 }
254
255 /* ARGSUSED */
256 static void
257 read_interrupt(int signo)
258 {
259         interrupted = 1;
260 }
261
262 /*ARGSUSED*/
263 static void
264 sigchld_handler(int sig)
265 {
266         int save_errno = errno;
267         pid_t pid;
268         const char msg[] = "\rConnection closed.  \n";
269
270         /* Report if ssh transport process dies. */
271         while ((pid = waitpid(sshpid, NULL, WNOHANG)) == -1 && errno == EINTR)
272                 continue;
273         if (pid == sshpid) {
274                 (void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
275                 sshpid = -1;
276         }
277
278         errno = save_errno;
279 }
280
281 static void
282 help(void)
283 {
284         printf("Available commands:\n"
285             "bye                                Quit sftp\n"
286             "cd path                            Change remote directory to 'path'\n"
287             "chgrp [-h] grp path                Change group of file 'path' to 'grp'\n"
288             "chmod [-h] mode path               Change permissions of file 'path' to 'mode'\n"
289             "chown [-h] own path                Change owner of file 'path' to 'own'\n"
290             "df [-hi] [path]                    Display statistics for current directory or\n"
291             "                                   filesystem containing 'path'\n"
292             "exit                               Quit sftp\n"
293             "get [-afpR] remote [local]         Download file\n"
294             "help                               Display this help text\n"
295             "lcd path                           Change local directory to 'path'\n"
296             "lls [ls-options [path]]            Display local directory listing\n"
297             "lmkdir path                        Create local directory\n"
298             "ln [-s] oldpath newpath            Link remote file (-s for symlink)\n"
299             "lpwd                               Print local working directory\n"
300             "ls [-1afhlnrSt] [path]             Display remote directory listing\n"
301             "lumask umask                       Set local umask to 'umask'\n"
302             "mkdir path                         Create remote directory\n"
303             "progress                           Toggle display of progress meter\n"
304             "put [-afpR] local [remote]         Upload file\n"
305             "pwd                                Display remote working directory\n"
306             "quit                               Quit sftp\n"
307             "reget [-fpR] remote [local]        Resume download file\n"
308             "rename oldpath newpath             Rename remote file\n"
309             "reput [-fpR] local [remote]        Resume upload file\n"
310             "rm path                            Delete remote file\n"
311             "rmdir path                         Remove remote directory\n"
312             "symlink oldpath newpath            Symlink remote file\n"
313             "version                            Show SFTP version\n"
314             "!command                           Execute 'command' in local shell\n"
315             "!                                  Escape to local shell\n"
316             "?                                  Synonym for help\n");
317 }
318
319 static void
320 local_do_shell(const char *args)
321 {
322         int status;
323         char *shell;
324         pid_t pid;
325
326         if (!*args)
327                 args = NULL;
328
329         if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
330                 shell = _PATH_BSHELL;
331
332         if ((pid = fork()) == -1)
333                 fatal("Couldn't fork: %s", strerror(errno));
334
335         if (pid == 0) {
336                 /* XXX: child has pipe fds to ssh subproc open - issue? */
337                 if (args) {
338                         debug3("Executing %s -c \"%s\"", shell, args);
339                         execl(shell, shell, "-c", args, (char *)NULL);
340                 } else {
341                         debug3("Executing %s", shell);
342                         execl(shell, shell, (char *)NULL);
343                 }
344                 fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell,
345                     strerror(errno));
346                 _exit(1);
347         }
348         while (waitpid(pid, &status, 0) == -1)
349                 if (errno != EINTR)
350                         fatal("Couldn't wait for child: %s", strerror(errno));
351         if (!WIFEXITED(status))
352                 error("Shell exited abnormally");
353         else if (WEXITSTATUS(status))
354                 error("Shell exited with status %d", WEXITSTATUS(status));
355 }
356
357 static void
358 local_do_ls(const char *args)
359 {
360         if (!args || !*args)
361                 local_do_shell(_PATH_LS);
362         else {
363                 int len = strlen(_PATH_LS " ") + strlen(args) + 1;
364                 char *buf = xmalloc(len);
365
366                 /* XXX: quoting - rip quoting code from ftp? */
367                 snprintf(buf, len, _PATH_LS " %s", args);
368                 local_do_shell(buf);
369                 free(buf);
370         }
371 }
372
373 /* Strip one path (usually the pwd) from the start of another */
374 static char *
375 path_strip(const char *path, const char *strip)
376 {
377         size_t len;
378
379         if (strip == NULL)
380                 return (xstrdup(path));
381
382         len = strlen(strip);
383         if (strncmp(path, strip, len) == 0) {
384                 if (strip[len - 1] != '/' && path[len] == '/')
385                         len++;
386                 return (xstrdup(path + len));
387         }
388
389         return (xstrdup(path));
390 }
391
392 static int
393 parse_getput_flags(const char *cmd, char **argv, int argc,
394     int *aflag, int *fflag, int *pflag, int *rflag)
395 {
396         extern int opterr, optind, optopt, optreset;
397         int ch;
398
399         optind = optreset = 1;
400         opterr = 0;
401
402         *aflag = *fflag = *rflag = *pflag = 0;
403         while ((ch = getopt(argc, argv, "afPpRr")) != -1) {
404                 switch (ch) {
405                 case 'a':
406                         *aflag = 1;
407                         break;
408                 case 'f':
409                         *fflag = 1;
410                         break;
411                 case 'p':
412                 case 'P':
413                         *pflag = 1;
414                         break;
415                 case 'r':
416                 case 'R':
417                         *rflag = 1;
418                         break;
419                 default:
420                         error("%s: Invalid flag -%c", cmd, optopt);
421                         return -1;
422                 }
423         }
424
425         return optind;
426 }
427
428 static int
429 parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
430 {
431         extern int opterr, optind, optopt, optreset;
432         int ch;
433
434         optind = optreset = 1;
435         opterr = 0;
436
437         *sflag = 0;
438         while ((ch = getopt(argc, argv, "s")) != -1) {
439                 switch (ch) {
440                 case 's':
441                         *sflag = 1;
442                         break;
443                 default:
444                         error("%s: Invalid flag -%c", cmd, optopt);
445                         return -1;
446                 }
447         }
448
449         return optind;
450 }
451
452 static int
453 parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag)
454 {
455         extern int opterr, optind, optopt, optreset;
456         int ch;
457
458         optind = optreset = 1;
459         opterr = 0;
460
461         *lflag = 0;
462         while ((ch = getopt(argc, argv, "l")) != -1) {
463                 switch (ch) {
464                 case 'l':
465                         *lflag = 1;
466                         break;
467                 default:
468                         error("%s: Invalid flag -%c", cmd, optopt);
469                         return -1;
470                 }
471         }
472
473         return optind;
474 }
475
476 static int
477 parse_ls_flags(char **argv, int argc, int *lflag)
478 {
479         extern int opterr, optind, optopt, optreset;
480         int ch;
481
482         optind = optreset = 1;
483         opterr = 0;
484
485         *lflag = LS_NAME_SORT;
486         while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) {
487                 switch (ch) {
488                 case '1':
489                         *lflag &= ~VIEW_FLAGS;
490                         *lflag |= LS_SHORT_VIEW;
491                         break;
492                 case 'S':
493                         *lflag &= ~SORT_FLAGS;
494                         *lflag |= LS_SIZE_SORT;
495                         break;
496                 case 'a':
497                         *lflag |= LS_SHOW_ALL;
498                         break;
499                 case 'f':
500                         *lflag &= ~SORT_FLAGS;
501                         break;
502                 case 'h':
503                         *lflag |= LS_SI_UNITS;
504                         break;
505                 case 'l':
506                         *lflag &= ~LS_SHORT_VIEW;
507                         *lflag |= LS_LONG_VIEW;
508                         break;
509                 case 'n':
510                         *lflag &= ~LS_SHORT_VIEW;
511                         *lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
512                         break;
513                 case 'r':
514                         *lflag |= LS_REVERSE_SORT;
515                         break;
516                 case 't':
517                         *lflag &= ~SORT_FLAGS;
518                         *lflag |= LS_TIME_SORT;
519                         break;
520                 default:
521                         error("ls: Invalid flag -%c", optopt);
522                         return -1;
523                 }
524         }
525
526         return optind;
527 }
528
529 static int
530 parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
531 {
532         extern int opterr, optind, optopt, optreset;
533         int ch;
534
535         optind = optreset = 1;
536         opterr = 0;
537
538         *hflag = *iflag = 0;
539         while ((ch = getopt(argc, argv, "hi")) != -1) {
540                 switch (ch) {
541                 case 'h':
542                         *hflag = 1;
543                         break;
544                 case 'i':
545                         *iflag = 1;
546                         break;
547                 default:
548                         error("%s: Invalid flag -%c", cmd, optopt);
549                         return -1;
550                 }
551         }
552
553         return optind;
554 }
555
556 static int
557 parse_ch_flags(const char *cmd, char **argv, int argc, int *hflag)
558 {
559         extern int opterr, optind, optopt, optreset;
560         int ch;
561
562         optind = optreset = 1;
563         opterr = 0;
564
565         *hflag = 0;
566         while ((ch = getopt(argc, argv, "h")) != -1) {
567                 switch (ch) {
568                 case 'h':
569                         *hflag = 1;
570                         break;
571                 default:
572                         error("%s: Invalid flag -%c", cmd, optopt);
573                         return -1;
574                 }
575         }
576
577         return optind;
578 }
579
580 static int
581 parse_no_flags(const char *cmd, char **argv, int argc)
582 {
583         extern int opterr, optind, optopt, optreset;
584         int ch;
585
586         optind = optreset = 1;
587         opterr = 0;
588
589         while ((ch = getopt(argc, argv, "")) != -1) {
590                 switch (ch) {
591                 default:
592                         error("%s: Invalid flag -%c", cmd, optopt);
593                         return -1;
594                 }
595         }
596
597         return optind;
598 }
599
600 static int
601 process_get(struct sftp_conn *conn, const char *src, const char *dst,
602     const char *pwd, int pflag, int rflag, int resume, int fflag)
603 {
604         char *abs_src = NULL;
605         char *abs_dst = NULL;
606         glob_t g;
607         char *filename, *tmp=NULL;
608         int i, r, err = 0;
609
610         abs_src = xstrdup(src);
611         abs_src = make_absolute(abs_src, pwd);
612         memset(&g, 0, sizeof(g));
613
614         debug3("Looking up %s", abs_src);
615         if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
616                 if (r == GLOB_NOSPACE) {
617                         error("Too many matches for \"%s\".", abs_src);
618                 } else {
619                         error("File \"%s\" not found.", abs_src);
620                 }
621                 err = -1;
622                 goto out;
623         }
624
625         /*
626          * If multiple matches then dst must be a directory or
627          * unspecified.
628          */
629         if (g.gl_matchc > 1 && dst != NULL && !local_is_dir(dst)) {
630                 error("Multiple source paths, but destination "
631                     "\"%s\" is not a directory", dst);
632                 err = -1;
633                 goto out;
634         }
635
636         for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
637                 tmp = xstrdup(g.gl_pathv[i]);
638                 if ((filename = basename(tmp)) == NULL) {
639                         error("basename %s: %s", tmp, strerror(errno));
640                         free(tmp);
641                         err = -1;
642                         goto out;
643                 }
644
645                 if (g.gl_matchc == 1 && dst) {
646                         if (local_is_dir(dst)) {
647                                 abs_dst = path_append(dst, filename);
648                         } else {
649                                 abs_dst = xstrdup(dst);
650                         }
651                 } else if (dst) {
652                         abs_dst = path_append(dst, filename);
653                 } else {
654                         abs_dst = xstrdup(filename);
655                 }
656                 free(tmp);
657
658                 resume |= global_aflag;
659                 if (!quiet && resume)
660                         mprintf("Resuming %s to %s\n",
661                             g.gl_pathv[i], abs_dst);
662                 else if (!quiet && !resume)
663                         mprintf("Fetching %s to %s\n",
664                             g.gl_pathv[i], abs_dst);
665                 /* XXX follow link flag */
666                 if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
667                         if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
668                             pflag || global_pflag, 1, resume,
669                             fflag || global_fflag, 0) == -1)
670                                 err = -1;
671                 } else {
672                         if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
673                             pflag || global_pflag, resume,
674                             fflag || global_fflag) == -1)
675                                 err = -1;
676                 }
677                 free(abs_dst);
678                 abs_dst = NULL;
679         }
680
681 out:
682         free(abs_src);
683         globfree(&g);
684         return(err);
685 }
686
687 static int
688 process_put(struct sftp_conn *conn, const char *src, const char *dst,
689     const char *pwd, int pflag, int rflag, int resume, int fflag)
690 {
691         char *tmp_dst = NULL;
692         char *abs_dst = NULL;
693         char *tmp = NULL, *filename = NULL;
694         glob_t g;
695         int err = 0;
696         int i, dst_is_dir = 1;
697         struct stat sb;
698
699         if (dst) {
700                 tmp_dst = xstrdup(dst);
701                 tmp_dst = make_absolute(tmp_dst, pwd);
702         }
703
704         memset(&g, 0, sizeof(g));
705         debug3("Looking up %s", src);
706         if (glob(src, GLOB_NOCHECK | GLOB_MARK, NULL, &g)) {
707                 error("File \"%s\" not found.", src);
708                 err = -1;
709                 goto out;
710         }
711
712         /* If we aren't fetching to pwd then stash this status for later */
713         if (tmp_dst != NULL)
714                 dst_is_dir = remote_is_dir(conn, tmp_dst);
715
716         /* If multiple matches, dst may be directory or unspecified */
717         if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
718                 error("Multiple paths match, but destination "
719                     "\"%s\" is not a directory", tmp_dst);
720                 err = -1;
721                 goto out;
722         }
723
724         for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
725                 if (stat(g.gl_pathv[i], &sb) == -1) {
726                         err = -1;
727                         error("stat %s: %s", g.gl_pathv[i], strerror(errno));
728                         continue;
729                 }
730
731                 tmp = xstrdup(g.gl_pathv[i]);
732                 if ((filename = basename(tmp)) == NULL) {
733                         error("basename %s: %s", tmp, strerror(errno));
734                         free(tmp);
735                         err = -1;
736                         goto out;
737                 }
738
739                 if (g.gl_matchc == 1 && tmp_dst) {
740                         /* If directory specified, append filename */
741                         if (dst_is_dir)
742                                 abs_dst = path_append(tmp_dst, filename);
743                         else
744                                 abs_dst = xstrdup(tmp_dst);
745                 } else if (tmp_dst) {
746                         abs_dst = path_append(tmp_dst, filename);
747                 } else {
748                         abs_dst = make_absolute(xstrdup(filename), pwd);
749                 }
750                 free(tmp);
751
752                 resume |= global_aflag;
753                 if (!quiet && resume)
754                         mprintf("Resuming upload of %s to %s\n",
755                             g.gl_pathv[i], abs_dst);
756                 else if (!quiet && !resume)
757                         mprintf("Uploading %s to %s\n",
758                             g.gl_pathv[i], abs_dst);
759                 /* XXX follow_link_flag */
760                 if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
761                         if (upload_dir(conn, g.gl_pathv[i], abs_dst,
762                             pflag || global_pflag, 1, resume,
763                             fflag || global_fflag, 0) == -1)
764                                 err = -1;
765                 } else {
766                         if (do_upload(conn, g.gl_pathv[i], abs_dst,
767                             pflag || global_pflag, resume,
768                             fflag || global_fflag) == -1)
769                                 err = -1;
770                 }
771         }
772
773 out:
774         free(abs_dst);
775         free(tmp_dst);
776         globfree(&g);
777         return(err);
778 }
779
780 static int
781 sdirent_comp(const void *aa, const void *bb)
782 {
783         SFTP_DIRENT *a = *(SFTP_DIRENT **)aa;
784         SFTP_DIRENT *b = *(SFTP_DIRENT **)bb;
785         int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
786
787 #define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
788         if (sort_flag & LS_NAME_SORT)
789                 return (rmul * strcmp(a->filename, b->filename));
790         else if (sort_flag & LS_TIME_SORT)
791                 return (rmul * NCMP(a->a.mtime, b->a.mtime));
792         else if (sort_flag & LS_SIZE_SORT)
793                 return (rmul * NCMP(a->a.size, b->a.size));
794
795         fatal("Unknown ls sort type");
796 }
797
798 /* sftp ls.1 replacement for directories */
799 static int
800 do_ls_dir(struct sftp_conn *conn, const char *path,
801     const char *strip_path, int lflag)
802 {
803         int n;
804         u_int c = 1, colspace = 0, columns = 1;
805         SFTP_DIRENT **d;
806
807         if ((n = do_readdir(conn, path, &d)) != 0)
808                 return (n);
809
810         if (!(lflag & LS_SHORT_VIEW)) {
811                 u_int m = 0, width = 80;
812                 struct winsize ws;
813                 char *tmp;
814
815                 /* Count entries for sort and find longest filename */
816                 for (n = 0; d[n] != NULL; n++) {
817                         if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL))
818                                 m = MAXIMUM(m, strlen(d[n]->filename));
819                 }
820
821                 /* Add any subpath that also needs to be counted */
822                 tmp = path_strip(path, strip_path);
823                 m += strlen(tmp);
824                 free(tmp);
825
826                 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
827                         width = ws.ws_col;
828
829                 columns = width / (m + 2);
830                 columns = MAXIMUM(columns, 1);
831                 colspace = width / columns;
832                 colspace = MINIMUM(colspace, width);
833         }
834
835         if (lflag & SORT_FLAGS) {
836                 for (n = 0; d[n] != NULL; n++)
837                         ;       /* count entries */
838                 sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
839                 qsort(d, n, sizeof(*d), sdirent_comp);
840         }
841
842         for (n = 0; d[n] != NULL && !interrupted; n++) {
843                 char *tmp, *fname;
844
845                 if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL))
846                         continue;
847
848                 tmp = path_append(path, d[n]->filename);
849                 fname = path_strip(tmp, strip_path);
850                 free(tmp);
851
852                 if (lflag & LS_LONG_VIEW) {
853                         if (lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) {
854                                 char *lname;
855                                 struct stat sb;
856
857                                 memset(&sb, 0, sizeof(sb));
858                                 attrib_to_stat(&d[n]->a, &sb);
859                                 lname = ls_file(fname, &sb, 1,
860                                     (lflag & LS_SI_UNITS));
861                                 mprintf("%s\n", lname);
862                                 free(lname);
863                         } else
864                                 mprintf("%s\n", d[n]->longname);
865                 } else {
866                         mprintf("%-*s", colspace, fname);
867                         if (c >= columns) {
868                                 printf("\n");
869                                 c = 1;
870                         } else
871                                 c++;
872                 }
873
874                 free(fname);
875         }
876
877         if (!(lflag & LS_LONG_VIEW) && (c != 1))
878                 printf("\n");
879
880         free_sftp_dirents(d);
881         return (0);
882 }
883
884 static int
885 sglob_comp(const void *aa, const void *bb)
886 {
887         u_int a = *(const u_int *)aa;
888         u_int b = *(const u_int *)bb;
889         const char *ap = sort_glob->gl_pathv[a];
890         const char *bp = sort_glob->gl_pathv[b];
891         const struct stat *as = sort_glob->gl_statv[a];
892         const struct stat *bs = sort_glob->gl_statv[b];
893         int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
894
895 #define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
896         if (sort_flag & LS_NAME_SORT)
897                 return (rmul * strcmp(ap, bp));
898         else if (sort_flag & LS_TIME_SORT) {
899 #if defined(HAVE_STRUCT_STAT_ST_MTIM)
900                 if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==))
901                         return 0;
902                 return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ?
903                     rmul : -rmul;
904 #elif defined(HAVE_STRUCT_STAT_ST_MTIME)
905                 return (rmul * NCMP(as->st_mtime, bs->st_mtime));
906 #else
907         return rmul * 1;
908 #endif
909         } else if (sort_flag & LS_SIZE_SORT)
910                 return (rmul * NCMP(as->st_size, bs->st_size));
911
912         fatal("Unknown ls sort type");
913 }
914
915 /* sftp ls.1 replacement which handles path globs */
916 static int
917 do_globbed_ls(struct sftp_conn *conn, const char *path,
918     const char *strip_path, int lflag)
919 {
920         char *fname, *lname;
921         glob_t g;
922         int err, r;
923         struct winsize ws;
924         u_int i, j, nentries, *indices = NULL, c = 1;
925         u_int colspace = 0, columns = 1, m = 0, width = 80;
926
927         memset(&g, 0, sizeof(g));
928
929         if ((r = remote_glob(conn, path,
930             GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT,
931             NULL, &g)) != 0 ||
932             (g.gl_pathc && !g.gl_matchc)) {
933                 if (g.gl_pathc)
934                         globfree(&g);
935                 if (r == GLOB_NOSPACE) {
936                         error("Can't ls: Too many matches for \"%s\"", path);
937                 } else {
938                         error("Can't ls: \"%s\" not found", path);
939                 }
940                 return -1;
941         }
942
943         if (interrupted)
944                 goto out;
945
946         /*
947          * If the glob returns a single match and it is a directory,
948          * then just list its contents.
949          */
950         if (g.gl_matchc == 1 && g.gl_statv[0] != NULL &&
951             S_ISDIR(g.gl_statv[0]->st_mode)) {
952                 err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
953                 globfree(&g);
954                 return err;
955         }
956
957         if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
958                 width = ws.ws_col;
959
960         if (!(lflag & LS_SHORT_VIEW)) {
961                 /* Count entries for sort and find longest filename */
962                 for (i = 0; g.gl_pathv[i]; i++)
963                         m = MAXIMUM(m, strlen(g.gl_pathv[i]));
964
965                 columns = width / (m + 2);
966                 columns = MAXIMUM(columns, 1);
967                 colspace = width / columns;
968         }
969
970         /*
971          * Sorting: rather than mess with the contents of glob_t, prepare
972          * an array of indices into it and sort that. For the usual
973          * unsorted case, the indices are just the identity 1=1, 2=2, etc.
974          */
975         for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++)
976                 ;       /* count entries */
977         indices = calloc(nentries, sizeof(*indices));
978         for (i = 0; i < nentries; i++)
979                 indices[i] = i;
980
981         if (lflag & SORT_FLAGS) {
982                 sort_glob = &g;
983                 sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
984                 qsort(indices, nentries, sizeof(*indices), sglob_comp);
985                 sort_glob = NULL;
986         }
987
988         for (j = 0; j < nentries && !interrupted; j++) {
989                 i = indices[j];
990                 fname = path_strip(g.gl_pathv[i], strip_path);
991                 if (lflag & LS_LONG_VIEW) {
992                         if (g.gl_statv[i] == NULL) {
993                                 error("no stat information for %s", fname);
994                                 continue;
995                         }
996                         lname = ls_file(fname, g.gl_statv[i], 1,
997                             (lflag & LS_SI_UNITS));
998                         mprintf("%s\n", lname);
999                         free(lname);
1000                 } else {
1001                         mprintf("%-*s", colspace, fname);
1002                         if (c >= columns) {
1003                                 printf("\n");
1004                                 c = 1;
1005                         } else
1006                                 c++;
1007                 }
1008                 free(fname);
1009         }
1010
1011         if (!(lflag & LS_LONG_VIEW) && (c != 1))
1012                 printf("\n");
1013
1014  out:
1015         if (g.gl_pathc)
1016                 globfree(&g);
1017         free(indices);
1018
1019         return 0;
1020 }
1021
1022 static int
1023 do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag)
1024 {
1025         struct sftp_statvfs st;
1026         char s_used[FMT_SCALED_STRSIZE], s_avail[FMT_SCALED_STRSIZE];
1027         char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE];
1028         char s_icapacity[16], s_dcapacity[16];
1029
1030         if (do_statvfs(conn, path, &st, 1) == -1)
1031                 return -1;
1032         if (st.f_files == 0)
1033                 strlcpy(s_icapacity, "ERR", sizeof(s_icapacity));
1034         else {
1035                 snprintf(s_icapacity, sizeof(s_icapacity), "%3llu%%",
1036                     (unsigned long long)(100 * (st.f_files - st.f_ffree) /
1037                     st.f_files));
1038         }
1039         if (st.f_blocks == 0)
1040                 strlcpy(s_dcapacity, "ERR", sizeof(s_dcapacity));
1041         else {
1042                 snprintf(s_dcapacity, sizeof(s_dcapacity), "%3llu%%",
1043                     (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
1044                     st.f_blocks));
1045         }
1046         if (iflag) {
1047                 printf("     Inodes        Used       Avail      "
1048                     "(root)    %%Capacity\n");
1049                 printf("%11llu %11llu %11llu %11llu         %s\n",
1050                     (unsigned long long)st.f_files,
1051                     (unsigned long long)(st.f_files - st.f_ffree),
1052                     (unsigned long long)st.f_favail,
1053                     (unsigned long long)st.f_ffree, s_icapacity);
1054         } else if (hflag) {
1055                 strlcpy(s_used, "error", sizeof(s_used));
1056                 strlcpy(s_avail, "error", sizeof(s_avail));
1057                 strlcpy(s_root, "error", sizeof(s_root));
1058                 strlcpy(s_total, "error", sizeof(s_total));
1059                 fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used);
1060                 fmt_scaled(st.f_bavail * st.f_frsize, s_avail);
1061                 fmt_scaled(st.f_bfree * st.f_frsize, s_root);
1062                 fmt_scaled(st.f_blocks * st.f_frsize, s_total);
1063                 printf("    Size     Used    Avail   (root)    %%Capacity\n");
1064                 printf("%7sB %7sB %7sB %7sB         %s\n",
1065                     s_total, s_used, s_avail, s_root, s_dcapacity);
1066         } else {
1067                 printf("        Size         Used        Avail       "
1068                     "(root)    %%Capacity\n");
1069                 printf("%12llu %12llu %12llu %12llu         %s\n",
1070                     (unsigned long long)(st.f_frsize * st.f_blocks / 1024),
1071                     (unsigned long long)(st.f_frsize *
1072                     (st.f_blocks - st.f_bfree) / 1024),
1073                     (unsigned long long)(st.f_frsize * st.f_bavail / 1024),
1074                     (unsigned long long)(st.f_frsize * st.f_bfree / 1024),
1075                     s_dcapacity);
1076         }
1077         return 0;
1078 }
1079
1080 /*
1081  * Undo escaping of glob sequences in place. Used to undo extra escaping
1082  * applied in makeargv() when the string is destined for a function that
1083  * does not glob it.
1084  */
1085 static void
1086 undo_glob_escape(char *s)
1087 {
1088         size_t i, j;
1089
1090         for (i = j = 0;;) {
1091                 if (s[i] == '\0') {
1092                         s[j] = '\0';
1093                         return;
1094                 }
1095                 if (s[i] != '\\') {
1096                         s[j++] = s[i++];
1097                         continue;
1098                 }
1099                 /* s[i] == '\\' */
1100                 ++i;
1101                 switch (s[i]) {
1102                 case '?':
1103                 case '[':
1104                 case '*':
1105                 case '\\':
1106                         s[j++] = s[i++];
1107                         break;
1108                 case '\0':
1109                         s[j++] = '\\';
1110                         s[j] = '\0';
1111                         return;
1112                 default:
1113                         s[j++] = '\\';
1114                         s[j++] = s[i++];
1115                         break;
1116                 }
1117         }
1118 }
1119
1120 /*
1121  * Split a string into an argument vector using sh(1)-style quoting,
1122  * comment and escaping rules, but with some tweaks to handle glob(3)
1123  * wildcards.
1124  * The "sloppy" flag allows for recovery from missing terminating quote, for
1125  * use in parsing incomplete commandlines during tab autocompletion.
1126  *
1127  * Returns NULL on error or a NULL-terminated array of arguments.
1128  *
1129  * If "lastquote" is not NULL, the quoting character used for the last
1130  * argument is placed in *lastquote ("\0", "'" or "\"").
1131  *
1132  * If "terminated" is not NULL, *terminated will be set to 1 when the
1133  * last argument's quote has been properly terminated or 0 otherwise.
1134  * This parameter is only of use if "sloppy" is set.
1135  */
1136 #define MAXARGS         128
1137 #define MAXARGLEN       8192
1138 static char **
1139 makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1140     u_int *terminated)
1141 {
1142         int argc, quot;
1143         size_t i, j;
1144         static char argvs[MAXARGLEN];
1145         static char *argv[MAXARGS + 1];
1146         enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q;
1147
1148         *argcp = argc = 0;
1149         if (strlen(arg) > sizeof(argvs) - 1) {
1150  args_too_longs:
1151                 error("string too long");
1152                 return NULL;
1153         }
1154         if (terminated != NULL)
1155                 *terminated = 1;
1156         if (lastquote != NULL)
1157                 *lastquote = '\0';
1158         state = MA_START;
1159         i = j = 0;
1160         for (;;) {
1161                 if ((size_t)argc >= sizeof(argv) / sizeof(*argv)){
1162                         error("Too many arguments.");
1163                         return NULL;
1164                 }
1165                 if (isspace((unsigned char)arg[i])) {
1166                         if (state == MA_UNQUOTED) {
1167                                 /* Terminate current argument */
1168                                 argvs[j++] = '\0';
1169                                 argc++;
1170                                 state = MA_START;
1171                         } else if (state != MA_START)
1172                                 argvs[j++] = arg[i];
1173                 } else if (arg[i] == '"' || arg[i] == '\'') {
1174                         q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE;
1175                         if (state == MA_START) {
1176                                 argv[argc] = argvs + j;
1177                                 state = q;
1178                                 if (lastquote != NULL)
1179                                         *lastquote = arg[i];
1180                         } else if (state == MA_UNQUOTED)
1181                                 state = q;
1182                         else if (state == q)
1183                                 state = MA_UNQUOTED;
1184                         else
1185                                 argvs[j++] = arg[i];
1186                 } else if (arg[i] == '\\') {
1187                         if (state == MA_SQUOTE || state == MA_DQUOTE) {
1188                                 quot = state == MA_SQUOTE ? '\'' : '"';
1189                                 /* Unescape quote we are in */
1190                                 /* XXX support \n and friends? */
1191                                 if (arg[i + 1] == quot) {
1192                                         i++;
1193                                         argvs[j++] = arg[i];
1194                                 } else if (arg[i + 1] == '?' ||
1195                                     arg[i + 1] == '[' || arg[i + 1] == '*') {
1196                                         /*
1197                                          * Special case for sftp: append
1198                                          * double-escaped glob sequence -
1199                                          * glob will undo one level of
1200                                          * escaping. NB. string can grow here.
1201                                          */
1202                                         if (j >= sizeof(argvs) - 5)
1203                                                 goto args_too_longs;
1204                                         argvs[j++] = '\\';
1205                                         argvs[j++] = arg[i++];
1206                                         argvs[j++] = '\\';
1207                                         argvs[j++] = arg[i];
1208                                 } else {
1209                                         argvs[j++] = arg[i++];
1210                                         argvs[j++] = arg[i];
1211                                 }
1212                         } else {
1213                                 if (state == MA_START) {
1214                                         argv[argc] = argvs + j;
1215                                         state = MA_UNQUOTED;
1216                                         if (lastquote != NULL)
1217                                                 *lastquote = '\0';
1218                                 }
1219                                 if (arg[i + 1] == '?' || arg[i + 1] == '[' ||
1220                                     arg[i + 1] == '*' || arg[i + 1] == '\\') {
1221                                         /*
1222                                          * Special case for sftp: append
1223                                          * escaped glob sequence -
1224                                          * glob will undo one level of
1225                                          * escaping.
1226                                          */
1227                                         argvs[j++] = arg[i++];
1228                                         argvs[j++] = arg[i];
1229                                 } else {
1230                                         /* Unescape everything */
1231                                         /* XXX support \n and friends? */
1232                                         i++;
1233                                         argvs[j++] = arg[i];
1234                                 }
1235                         }
1236                 } else if (arg[i] == '#') {
1237                         if (state == MA_SQUOTE || state == MA_DQUOTE)
1238                                 argvs[j++] = arg[i];
1239                         else
1240                                 goto string_done;
1241                 } else if (arg[i] == '\0') {
1242                         if (state == MA_SQUOTE || state == MA_DQUOTE) {
1243                                 if (sloppy) {
1244                                         state = MA_UNQUOTED;
1245                                         if (terminated != NULL)
1246                                                 *terminated = 0;
1247                                         goto string_done;
1248                                 }
1249                                 error("Unterminated quoted argument");
1250                                 return NULL;
1251                         }
1252  string_done:
1253                         if (state == MA_UNQUOTED) {
1254                                 argvs[j++] = '\0';
1255                                 argc++;
1256                         }
1257                         break;
1258                 } else {
1259                         if (state == MA_START) {
1260                                 argv[argc] = argvs + j;
1261                                 state = MA_UNQUOTED;
1262                                 if (lastquote != NULL)
1263                                         *lastquote = '\0';
1264                         }
1265                         if ((state == MA_SQUOTE || state == MA_DQUOTE) &&
1266                             (arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) {
1267                                 /*
1268                                  * Special case for sftp: escape quoted
1269                                  * glob(3) wildcards. NB. string can grow
1270                                  * here.
1271                                  */
1272                                 if (j >= sizeof(argvs) - 3)
1273                                         goto args_too_longs;
1274                                 argvs[j++] = '\\';
1275                                 argvs[j++] = arg[i];
1276                         } else
1277                                 argvs[j++] = arg[i];
1278                 }
1279                 i++;
1280         }
1281         *argcp = argc;
1282         return argv;
1283 }
1284
1285 static int
1286 parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
1287           int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
1288           int *rflag, int *sflag,
1289     unsigned long *n_arg, char **path1, char **path2)
1290 {
1291         const char *cmd, *cp = *cpp;
1292         char *cp2, **argv;
1293         int base = 0;
1294         long long ll;
1295         int path1_mandatory = 0, i, cmdnum, optidx, argc;
1296
1297         /* Skip leading whitespace */
1298         cp = cp + strspn(cp, WHITESPACE);
1299
1300         /*
1301          * Check for leading '-' (disable error processing) and '@' (suppress
1302          * command echo)
1303          */
1304         *ignore_errors = 0;
1305         *disable_echo = 0;
1306         for (;*cp != '\0'; cp++) {
1307                 if (*cp == '-') {
1308                         *ignore_errors = 1;
1309                 } else if (*cp == '@') {
1310                         *disable_echo = 1;
1311                 } else {
1312                         /* all other characters terminate prefix processing */
1313                         break;
1314                 }
1315         }
1316         cp = cp + strspn(cp, WHITESPACE);
1317
1318         /* Ignore blank lines and lines which begin with comment '#' char */
1319         if (*cp == '\0' || *cp == '#')
1320                 return (0);
1321
1322         if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL)
1323                 return -1;
1324
1325         /* Figure out which command we have */
1326         for (i = 0; cmds[i].c != NULL; i++) {
1327                 if (argv[0] != NULL && strcasecmp(cmds[i].c, argv[0]) == 0)
1328                         break;
1329         }
1330         cmdnum = cmds[i].n;
1331         cmd = cmds[i].c;
1332
1333         /* Special case */
1334         if (*cp == '!') {
1335                 cp++;
1336                 cmdnum = I_SHELL;
1337         } else if (cmdnum == -1) {
1338                 error("Invalid command.");
1339                 return -1;
1340         }
1341
1342         /* Get arguments and parse flags */
1343         *aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0;
1344         *rflag = *sflag = 0;
1345         *path1 = *path2 = NULL;
1346         optidx = 1;
1347         switch (cmdnum) {
1348         case I_GET:
1349         case I_REGET:
1350         case I_REPUT:
1351         case I_PUT:
1352                 if ((optidx = parse_getput_flags(cmd, argv, argc,
1353                     aflag, fflag, pflag, rflag)) == -1)
1354                         return -1;
1355                 /* Get first pathname (mandatory) */
1356                 if (argc - optidx < 1) {
1357                         error("You must specify at least one path after a "
1358                             "%s command.", cmd);
1359                         return -1;
1360                 }
1361                 *path1 = xstrdup(argv[optidx]);
1362                 /* Get second pathname (optional) */
1363                 if (argc - optidx > 1) {
1364                         *path2 = xstrdup(argv[optidx + 1]);
1365                         /* Destination is not globbed */
1366                         undo_glob_escape(*path2);
1367                 }
1368                 break;
1369         case I_LINK:
1370                 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
1371                         return -1;
1372                 goto parse_two_paths;
1373         case I_RENAME:
1374                 if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1)
1375                         return -1;
1376                 goto parse_two_paths;
1377         case I_SYMLINK:
1378                 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1379                         return -1;
1380  parse_two_paths:
1381                 if (argc - optidx < 2) {
1382                         error("You must specify two paths after a %s "
1383                             "command.", cmd);
1384                         return -1;
1385                 }
1386                 *path1 = xstrdup(argv[optidx]);
1387                 *path2 = xstrdup(argv[optidx + 1]);
1388                 /* Paths are not globbed */
1389                 undo_glob_escape(*path1);
1390                 undo_glob_escape(*path2);
1391                 break;
1392         case I_RM:
1393         case I_MKDIR:
1394         case I_RMDIR:
1395         case I_LMKDIR:
1396                 path1_mandatory = 1;
1397                 /* FALLTHROUGH */
1398         case I_CHDIR:
1399         case I_LCHDIR:
1400                 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1401                         return -1;
1402                 /* Get pathname (mandatory) */
1403                 if (argc - optidx < 1) {
1404                         if (!path1_mandatory)
1405                                 break; /* return a NULL path1 */
1406                         error("You must specify a path after a %s command.",
1407                             cmd);
1408                         return -1;
1409                 }
1410                 *path1 = xstrdup(argv[optidx]);
1411                 /* Only "rm" globs */
1412                 if (cmdnum != I_RM)
1413                         undo_glob_escape(*path1);
1414                 break;
1415         case I_DF:
1416                 if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
1417                     iflag)) == -1)
1418                         return -1;
1419                 /* Default to current directory if no path specified */
1420                 if (argc - optidx < 1)
1421                         *path1 = NULL;
1422                 else {
1423                         *path1 = xstrdup(argv[optidx]);
1424                         undo_glob_escape(*path1);
1425                 }
1426                 break;
1427         case I_LS:
1428                 if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
1429                         return(-1);
1430                 /* Path is optional */
1431                 if (argc - optidx > 0)
1432                         *path1 = xstrdup(argv[optidx]);
1433                 break;
1434         case I_LLS:
1435                 /* Skip ls command and following whitespace */
1436                 cp = cp + strlen(cmd) + strspn(cp, WHITESPACE);
1437         case I_SHELL:
1438                 /* Uses the rest of the line */
1439                 break;
1440         case I_LUMASK:
1441         case I_CHMOD:
1442                 base = 8;
1443                 /* FALLTHROUGH */
1444         case I_CHOWN:
1445         case I_CHGRP:
1446                 if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1)
1447                         return -1;
1448                 /* Get numeric arg (mandatory) */
1449                 if (argc - optidx < 1)
1450                         goto need_num_arg;
1451                 errno = 0;
1452                 ll = strtoll(argv[optidx], &cp2, base);
1453                 if (cp2 == argv[optidx] || *cp2 != '\0' ||
1454                     ((ll == LLONG_MIN || ll == LLONG_MAX) && errno == ERANGE) ||
1455                     ll < 0 || ll > UINT32_MAX) {
1456  need_num_arg:
1457                         error("You must supply a numeric argument "
1458                             "to the %s command.", cmd);
1459                         return -1;
1460                 }
1461                 *n_arg = ll;
1462                 if (cmdnum == I_LUMASK)
1463                         break;
1464                 /* Get pathname (mandatory) */
1465                 if (argc - optidx < 2) {
1466                         error("You must specify a path after a %s command.",
1467                             cmd);
1468                         return -1;
1469                 }
1470                 *path1 = xstrdup(argv[optidx + 1]);
1471                 break;
1472         case I_QUIT:
1473         case I_PWD:
1474         case I_LPWD:
1475         case I_HELP:
1476         case I_VERSION:
1477         case I_PROGRESS:
1478                 if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
1479                         return -1;
1480                 break;
1481         default:
1482                 fatal("Command not implemented");
1483         }
1484
1485         *cpp = cp;
1486         return(cmdnum);
1487 }
1488
1489 static int
1490 parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1491     const char *startdir, int err_abort, int echo_command)
1492 {
1493         const char *ocmd = cmd;
1494         char *path1, *path2, *tmp;
1495         int ignore_errors = 0, disable_echo = 1;
1496         int aflag = 0, fflag = 0, hflag = 0, iflag = 0;
1497         int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
1498         int cmdnum, i;
1499         unsigned long n_arg = 0;
1500         Attrib a, *aa;
1501         char path_buf[PATH_MAX];
1502         int err = 0;
1503         glob_t g;
1504
1505         path1 = path2 = NULL;
1506         cmdnum = parse_args(&cmd, &ignore_errors, &disable_echo, &aflag, &fflag,
1507             &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg,
1508             &path1, &path2);
1509         if (ignore_errors != 0)
1510                 err_abort = 0;
1511
1512         if (echo_command && !disable_echo)
1513                 mprintf("sftp> %s\n", ocmd);
1514
1515         memset(&g, 0, sizeof(g));
1516
1517         /* Perform command */
1518         switch (cmdnum) {
1519         case 0:
1520                 /* Blank line */
1521                 break;
1522         case -1:
1523                 /* Unrecognized command */
1524                 err = -1;
1525                 break;
1526         case I_REGET:
1527                 aflag = 1;
1528                 /* FALLTHROUGH */
1529         case I_GET:
1530                 err = process_get(conn, path1, path2, *pwd, pflag,
1531                     rflag, aflag, fflag);
1532                 break;
1533         case I_REPUT:
1534                 aflag = 1;
1535                 /* FALLTHROUGH */
1536         case I_PUT:
1537                 err = process_put(conn, path1, path2, *pwd, pflag,
1538                     rflag, aflag, fflag);
1539                 break;
1540         case I_RENAME:
1541                 path1 = make_absolute(path1, *pwd);
1542                 path2 = make_absolute(path2, *pwd);
1543                 err = do_rename(conn, path1, path2, lflag);
1544                 break;
1545         case I_SYMLINK:
1546                 sflag = 1;
1547                 /* FALLTHROUGH */
1548         case I_LINK:
1549                 if (!sflag)
1550                         path1 = make_absolute(path1, *pwd);
1551                 path2 = make_absolute(path2, *pwd);
1552                 err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
1553                 break;
1554         case I_RM:
1555                 path1 = make_absolute(path1, *pwd);
1556                 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1557                 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1558                         if (!quiet)
1559                                 mprintf("Removing %s\n", g.gl_pathv[i]);
1560                         err = do_rm(conn, g.gl_pathv[i]);
1561                         if (err != 0 && err_abort)
1562                                 break;
1563                 }
1564                 break;
1565         case I_MKDIR:
1566                 path1 = make_absolute(path1, *pwd);
1567                 attrib_clear(&a);
1568                 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1569                 a.perm = 0777;
1570                 err = do_mkdir(conn, path1, &a, 1);
1571                 break;
1572         case I_RMDIR:
1573                 path1 = make_absolute(path1, *pwd);
1574                 err = do_rmdir(conn, path1);
1575                 break;
1576         case I_CHDIR:
1577                 if (path1 == NULL || *path1 == '\0')
1578                         path1 = xstrdup(startdir);
1579                 path1 = make_absolute(path1, *pwd);
1580                 if ((tmp = do_realpath(conn, path1)) == NULL) {
1581                         err = 1;
1582                         break;
1583                 }
1584                 if ((aa = do_stat(conn, tmp, 0)) == NULL) {
1585                         free(tmp);
1586                         err = 1;
1587                         break;
1588                 }
1589                 if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
1590                         error("Can't change directory: Can't check target");
1591                         free(tmp);
1592                         err = 1;
1593                         break;
1594                 }
1595                 if (!S_ISDIR(aa->perm)) {
1596                         error("Can't change directory: \"%s\" is not "
1597                             "a directory", tmp);
1598                         free(tmp);
1599                         err = 1;
1600                         break;
1601                 }
1602                 free(*pwd);
1603                 *pwd = tmp;
1604                 break;
1605         case I_LS:
1606                 if (!path1) {
1607                         do_ls_dir(conn, *pwd, *pwd, lflag);
1608                         break;
1609                 }
1610
1611                 /* Strip pwd off beginning of non-absolute paths */
1612                 tmp = NULL;
1613                 if (!path_absolute(path1))
1614                         tmp = *pwd;
1615
1616                 path1 = make_absolute(path1, *pwd);
1617                 err = do_globbed_ls(conn, path1, tmp, lflag);
1618                 break;
1619         case I_DF:
1620                 /* Default to current directory if no path specified */
1621                 if (path1 == NULL)
1622                         path1 = xstrdup(*pwd);
1623                 path1 = make_absolute(path1, *pwd);
1624                 err = do_df(conn, path1, hflag, iflag);
1625                 break;
1626         case I_LCHDIR:
1627                 if (path1 == NULL || *path1 == '\0')
1628                         path1 = xstrdup("~");
1629                 tmp = tilde_expand_filename(path1, getuid());
1630                 free(path1);
1631                 path1 = tmp;
1632                 if (chdir(path1) == -1) {
1633                         error("Couldn't change local directory to "
1634                             "\"%s\": %s", path1, strerror(errno));
1635                         err = 1;
1636                 }
1637                 break;
1638         case I_LMKDIR:
1639                 if (mkdir(path1, 0777) == -1) {
1640                         error("Couldn't create local directory "
1641                             "\"%s\": %s", path1, strerror(errno));
1642                         err = 1;
1643                 }
1644                 break;
1645         case I_LLS:
1646                 local_do_ls(cmd);
1647                 break;
1648         case I_SHELL:
1649                 local_do_shell(cmd);
1650                 break;
1651         case I_LUMASK:
1652                 umask(n_arg);
1653                 printf("Local umask: %03lo\n", n_arg);
1654                 break;
1655         case I_CHMOD:
1656                 path1 = make_absolute(path1, *pwd);
1657                 attrib_clear(&a);
1658                 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
1659                 a.perm = n_arg;
1660                 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1661                 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1662                         if (!quiet)
1663                                 mprintf("Changing mode on %s\n",
1664                                     g.gl_pathv[i]);
1665                         err = (hflag ? do_lsetstat : do_setstat)(conn,
1666                             g.gl_pathv[i], &a);
1667                         if (err != 0 && err_abort)
1668                                 break;
1669                 }
1670                 break;
1671         case I_CHOWN:
1672         case I_CHGRP:
1673                 path1 = make_absolute(path1, *pwd);
1674                 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
1675                 for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1676                         if (!(aa = (hflag ? do_lstat : do_stat)(conn,
1677                             g.gl_pathv[i], 0))) {
1678                                 if (err_abort) {
1679                                         err = -1;
1680                                         break;
1681                                 } else
1682                                         continue;
1683                         }
1684                         if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
1685                                 error("Can't get current ownership of "
1686                                     "remote file \"%s\"", g.gl_pathv[i]);
1687                                 if (err_abort) {
1688                                         err = -1;
1689                                         break;
1690                                 } else
1691                                         continue;
1692                         }
1693                         aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
1694                         if (cmdnum == I_CHOWN) {
1695                                 if (!quiet)
1696                                         mprintf("Changing owner on %s\n",
1697                                             g.gl_pathv[i]);
1698                                 aa->uid = n_arg;
1699                         } else {
1700                                 if (!quiet)
1701                                         mprintf("Changing group on %s\n",
1702                                             g.gl_pathv[i]);
1703                                 aa->gid = n_arg;
1704                         }
1705                         err = (hflag ? do_lsetstat : do_setstat)(conn,
1706                             g.gl_pathv[i], aa);
1707                         if (err != 0 && err_abort)
1708                                 break;
1709                 }
1710                 break;
1711         case I_PWD:
1712                 mprintf("Remote working directory: %s\n", *pwd);
1713                 break;
1714         case I_LPWD:
1715                 if (!getcwd(path_buf, sizeof(path_buf))) {
1716                         error("Couldn't get local cwd: %s", strerror(errno));
1717                         err = -1;
1718                         break;
1719                 }
1720                 mprintf("Local working directory: %s\n", path_buf);
1721                 break;
1722         case I_QUIT:
1723                 /* Processed below */
1724                 break;
1725         case I_HELP:
1726                 help();
1727                 break;
1728         case I_VERSION:
1729                 printf("SFTP protocol version %u\n", sftp_proto_version(conn));
1730                 break;
1731         case I_PROGRESS:
1732                 showprogress = !showprogress;
1733                 if (showprogress)
1734                         printf("Progress meter enabled\n");
1735                 else
1736                         printf("Progress meter disabled\n");
1737                 break;
1738         default:
1739                 fatal("%d is not implemented", cmdnum);
1740         }
1741
1742         if (g.gl_pathc)
1743                 globfree(&g);
1744         free(path1);
1745         free(path2);
1746
1747         /* If an unignored error occurs in batch mode we should abort. */
1748         if (err_abort && err != 0)
1749                 return (-1);
1750         else if (cmdnum == I_QUIT)
1751                 return (1);
1752
1753         return (0);
1754 }
1755
1756 #ifdef USE_LIBEDIT
1757 static char *
1758 prompt(EditLine *el)
1759 {
1760         return ("sftp> ");
1761 }
1762
1763 /* Display entries in 'list' after skipping the first 'len' chars */
1764 static void
1765 complete_display(char **list, u_int len)
1766 {
1767         u_int y, m = 0, width = 80, columns = 1, colspace = 0, llen;
1768         struct winsize ws;
1769         char *tmp;
1770
1771         /* Count entries for sort and find longest */
1772         for (y = 0; list[y]; y++)
1773                 m = MAXIMUM(m, strlen(list[y]));
1774
1775         if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
1776                 width = ws.ws_col;
1777
1778         m = m > len ? m - len : 0;
1779         columns = width / (m + 2);
1780         columns = MAXIMUM(columns, 1);
1781         colspace = width / columns;
1782         colspace = MINIMUM(colspace, width);
1783
1784         printf("\n");
1785         m = 1;
1786         for (y = 0; list[y]; y++) {
1787                 llen = strlen(list[y]);
1788                 tmp = llen > len ? list[y] + len : "";
1789                 mprintf("%-*s", colspace, tmp);
1790                 if (m >= columns) {
1791                         printf("\n");
1792                         m = 1;
1793                 } else
1794                         m++;
1795         }
1796         printf("\n");
1797 }
1798
1799 /*
1800  * Given a "list" of words that begin with a common prefix of "word",
1801  * attempt to find an autocompletion to extends "word" by the next
1802  * characters common to all entries in "list".
1803  */
1804 static char *
1805 complete_ambiguous(const char *word, char **list, size_t count)
1806 {
1807         if (word == NULL)
1808                 return NULL;
1809
1810         if (count > 0) {
1811                 u_int y, matchlen = strlen(list[0]);
1812
1813                 /* Find length of common stem */
1814                 for (y = 1; list[y]; y++) {
1815                         u_int x;
1816
1817                         for (x = 0; x < matchlen; x++)
1818                                 if (list[0][x] != list[y][x])
1819                                         break;
1820
1821                         matchlen = x;
1822                 }
1823
1824                 if (matchlen > strlen(word)) {
1825                         char *tmp = xstrdup(list[0]);
1826
1827                         tmp[matchlen] = '\0';
1828                         return tmp;
1829                 }
1830         }
1831
1832         return xstrdup(word);
1833 }
1834
1835 /* Autocomplete a sftp command */
1836 static int
1837 complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
1838     int terminated)
1839 {
1840         u_int y, count = 0, cmdlen, tmplen;
1841         char *tmp, **list, argterm[3];
1842         const LineInfo *lf;
1843
1844         list = xcalloc((sizeof(cmds) / sizeof(*cmds)) + 1, sizeof(char *));
1845
1846         /* No command specified: display all available commands */
1847         if (cmd == NULL) {
1848                 for (y = 0; cmds[y].c; y++)
1849                         list[count++] = xstrdup(cmds[y].c);
1850
1851                 list[count] = NULL;
1852                 complete_display(list, 0);
1853
1854                 for (y = 0; list[y] != NULL; y++)
1855                         free(list[y]);
1856                 free(list);
1857                 return count;
1858         }
1859
1860         /* Prepare subset of commands that start with "cmd" */
1861         cmdlen = strlen(cmd);
1862         for (y = 0; cmds[y].c; y++)  {
1863                 if (!strncasecmp(cmd, cmds[y].c, cmdlen))
1864                         list[count++] = xstrdup(cmds[y].c);
1865         }
1866         list[count] = NULL;
1867
1868         if (count == 0) {
1869                 free(list);
1870                 return 0;
1871         }
1872
1873         /* Complete ambiguous command */
1874         tmp = complete_ambiguous(cmd, list, count);
1875         if (count > 1)
1876                 complete_display(list, 0);
1877
1878         for (y = 0; list[y]; y++)
1879                 free(list[y]);
1880         free(list);
1881
1882         if (tmp != NULL) {
1883                 tmplen = strlen(tmp);
1884                 cmdlen = strlen(cmd);
1885                 /* If cmd may be extended then do so */
1886                 if (tmplen > cmdlen)
1887                         if (el_insertstr(el, tmp + cmdlen) == -1)
1888                                 fatal("el_insertstr failed.");
1889                 lf = el_line(el);
1890                 /* Terminate argument cleanly */
1891                 if (count == 1) {
1892                         y = 0;
1893                         if (!terminated)
1894                                 argterm[y++] = quote;
1895                         if (lastarg || *(lf->cursor) != ' ')
1896                                 argterm[y++] = ' ';
1897                         argterm[y] = '\0';
1898                         if (y > 0 && el_insertstr(el, argterm) == -1)
1899                                 fatal("el_insertstr failed.");
1900                 }
1901                 free(tmp);
1902         }
1903
1904         return count;
1905 }
1906
1907 /*
1908  * Determine whether a particular sftp command's arguments (if any)
1909  * represent local or remote files.
1910  */
1911 static int
1912 complete_is_remote(char *cmd) {
1913         int i;
1914
1915         if (cmd == NULL)
1916                 return -1;
1917
1918         for (i = 0; cmds[i].c; i++) {
1919                 if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c)))
1920                         return cmds[i].t;
1921         }
1922
1923         return -1;
1924 }
1925
1926 /* Autocomplete a filename "file" */
1927 static int
1928 complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1929     char *file, int remote, int lastarg, char quote, int terminated)
1930 {
1931         glob_t g;
1932         char *tmp, *tmp2, ins[8];
1933         u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
1934         int clen;
1935         const LineInfo *lf;
1936
1937         /* Glob from "file" location */
1938         if (file == NULL)
1939                 tmp = xstrdup("*");
1940         else
1941                 xasprintf(&tmp, "%s*", file);
1942
1943         /* Check if the path is absolute. */
1944         isabs = path_absolute(tmp);
1945
1946         memset(&g, 0, sizeof(g));
1947         if (remote != LOCAL) {
1948                 tmp = make_absolute(tmp, remote_path);
1949                 remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
1950         } else
1951                 glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
1952
1953         /* Determine length of pwd so we can trim completion display */
1954         for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) {
1955                 /* Terminate counting on first unescaped glob metacharacter */
1956                 if (tmp[tmplen] == '*' || tmp[tmplen] == '?') {
1957                         if (tmp[tmplen] != '*' || tmp[tmplen + 1] != '\0')
1958                                 hadglob = 1;
1959                         break;
1960                 }
1961                 if (tmp[tmplen] == '\\' && tmp[tmplen + 1] != '\0')
1962                         tmplen++;
1963                 if (tmp[tmplen] == '/')
1964                         pwdlen = tmplen + 1;    /* track last seen '/' */
1965         }
1966         free(tmp);
1967         tmp = NULL;
1968
1969         if (g.gl_matchc == 0)
1970                 goto out;
1971
1972         if (g.gl_matchc > 1)
1973                 complete_display(g.gl_pathv, pwdlen);
1974
1975         /* Don't try to extend globs */
1976         if (file == NULL || hadglob)
1977                 goto out;
1978
1979         tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc);
1980         tmp = path_strip(tmp2, isabs ? NULL : remote_path);
1981         free(tmp2);
1982
1983         if (tmp == NULL)
1984                 goto out;
1985
1986         tmplen = strlen(tmp);
1987         filelen = strlen(file);
1988
1989         /* Count the number of escaped characters in the input string. */
1990         cesc = isesc = 0;
1991         for (i = 0; i < filelen; i++) {
1992                 if (!isesc && file[i] == '\\' && i + 1 < filelen){
1993                         isesc = 1;
1994                         cesc++;
1995                 } else
1996                         isesc = 0;
1997         }
1998
1999         if (tmplen > (filelen - cesc)) {
2000                 tmp2 = tmp + filelen - cesc;
2001                 len = strlen(tmp2);
2002                 /* quote argument on way out */
2003                 for (i = 0; i < len; i += clen) {
2004                         if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
2005                             (size_t)clen > sizeof(ins) - 2)
2006                                 fatal("invalid multibyte character");
2007                         ins[0] = '\\';
2008                         memcpy(ins + 1, tmp2 + i, clen);
2009                         ins[clen + 1] = '\0';
2010                         switch (tmp2[i]) {
2011                         case '\'':
2012                         case '"':
2013                         case '\\':
2014                         case '\t':
2015                         case '[':
2016                         case ' ':
2017                         case '#':
2018                         case '*':
2019                                 if (quote == '\0' || tmp2[i] == quote) {
2020                                         if (el_insertstr(el, ins) == -1)
2021                                                 fatal("el_insertstr "
2022                                                     "failed.");
2023                                         break;
2024                                 }
2025                                 /* FALLTHROUGH */
2026                         default:
2027                                 if (el_insertstr(el, ins + 1) == -1)
2028                                         fatal("el_insertstr failed.");
2029                                 break;
2030                         }
2031                 }
2032         }
2033
2034         lf = el_line(el);
2035         if (g.gl_matchc == 1) {
2036                 i = 0;
2037                 if (!terminated && quote != '\0')
2038                         ins[i++] = quote;
2039                 if (*(lf->cursor - 1) != '/' &&
2040                     (lastarg || *(lf->cursor) != ' '))
2041                         ins[i++] = ' ';
2042                 ins[i] = '\0';
2043                 if (i > 0 && el_insertstr(el, ins) == -1)
2044                         fatal("el_insertstr failed.");
2045         }
2046         free(tmp);
2047
2048  out:
2049         globfree(&g);
2050         return g.gl_matchc;
2051 }
2052
2053 /* tab-completion hook function, called via libedit */
2054 static unsigned char
2055 complete(EditLine *el, int ch)
2056 {
2057         char **argv, *line, quote;
2058         int argc, carg;
2059         u_int cursor, len, terminated, ret = CC_ERROR;
2060         const LineInfo *lf;
2061         struct complete_ctx *complete_ctx;
2062
2063         lf = el_line(el);
2064         if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0)
2065                 fatal_f("el_get failed");
2066
2067         /* Figure out which argument the cursor points to */
2068         cursor = lf->cursor - lf->buffer;
2069         line = xmalloc(cursor + 1);
2070         memcpy(line, lf->buffer, cursor);
2071         line[cursor] = '\0';
2072         argv = makeargv(line, &carg, 1, &quote, &terminated);
2073         free(line);
2074
2075         /* Get all the arguments on the line */
2076         len = lf->lastchar - lf->buffer;
2077         line = xmalloc(len + 1);
2078         memcpy(line, lf->buffer, len);
2079         line[len] = '\0';
2080         argv = makeargv(line, &argc, 1, NULL, NULL);
2081
2082         /* Ensure cursor is at EOL or a argument boundary */
2083         if (line[cursor] != ' ' && line[cursor] != '\0' &&
2084             line[cursor] != '\n') {
2085                 free(line);
2086                 return ret;
2087         }
2088
2089         if (carg == 0) {
2090                 /* Show all available commands */
2091                 complete_cmd_parse(el, NULL, argc == carg, '\0', 1);
2092                 ret = CC_REDISPLAY;
2093         } else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ')  {
2094                 /* Handle the command parsing */
2095                 if (complete_cmd_parse(el, argv[0], argc == carg,
2096                     quote, terminated) != 0)
2097                         ret = CC_REDISPLAY;
2098         } else if (carg >= 1) {
2099                 /* Handle file parsing */
2100                 int remote = complete_is_remote(argv[0]);
2101                 char *filematch = NULL;
2102
2103                 if (carg > 1 && line[cursor-1] != ' ')
2104                         filematch = argv[carg - 1];
2105
2106                 if (remote != 0 &&
2107                     complete_match(el, complete_ctx->conn,
2108                     *complete_ctx->remote_pathp, filematch,
2109                     remote, carg == argc, quote, terminated) != 0)
2110                         ret = CC_REDISPLAY;
2111         }
2112
2113         free(line);
2114         return ret;
2115 }
2116 #endif /* USE_LIBEDIT */
2117
2118 static int
2119 interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
2120 {
2121         char *remote_path;
2122         char *dir = NULL, *startdir = NULL;
2123         char cmd[2048];
2124         int err, interactive;
2125         EditLine *el = NULL;
2126 #ifdef USE_LIBEDIT
2127         History *hl = NULL;
2128         HistEvent hev;
2129         extern char *__progname;
2130         struct complete_ctx complete_ctx;
2131
2132         if (!batchmode && isatty(STDIN_FILENO)) {
2133                 if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)
2134                         fatal("Couldn't initialise editline");
2135                 if ((hl = history_init()) == NULL)
2136                         fatal("Couldn't initialise editline history");
2137                 history(hl, &hev, H_SETSIZE, 100);
2138                 el_set(el, EL_HIST, history, hl);
2139
2140                 el_set(el, EL_PROMPT, prompt);
2141                 el_set(el, EL_EDITOR, "emacs");
2142                 el_set(el, EL_TERMINAL, NULL);
2143                 el_set(el, EL_SIGNAL, 1);
2144                 el_source(el, NULL);
2145
2146                 /* Tab Completion */
2147                 el_set(el, EL_ADDFN, "ftp-complete",
2148                     "Context sensitive argument completion", complete);
2149                 complete_ctx.conn = conn;
2150                 complete_ctx.remote_pathp = &remote_path;
2151                 el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
2152                 el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
2153                 /* enable ctrl-left-arrow and ctrl-right-arrow */
2154                 el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
2155                 el_set(el, EL_BIND, "\\e\\e[C", "em-next-word", NULL);
2156                 el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
2157                 el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
2158                 /* make ^w match ksh behaviour */
2159                 el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
2160         }
2161 #endif /* USE_LIBEDIT */
2162
2163         remote_path = do_realpath(conn, ".");
2164         if (remote_path == NULL)
2165                 fatal("Need cwd");
2166         startdir = xstrdup(remote_path);
2167
2168         if (file1 != NULL) {
2169                 dir = xstrdup(file1);
2170                 dir = make_absolute(dir, remote_path);
2171
2172                 if (remote_is_dir(conn, dir) && file2 == NULL) {
2173                         if (!quiet)
2174                                 mprintf("Changing to: %s\n", dir);
2175                         snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
2176                         if (parse_dispatch_command(conn, cmd,
2177                             &remote_path, startdir, 1, 0) != 0) {
2178                                 free(dir);
2179                                 free(startdir);
2180                                 free(remote_path);
2181                                 free(conn);
2182                                 return (-1);
2183                         }
2184                 } else {
2185                         /* XXX this is wrong wrt quoting */
2186                         snprintf(cmd, sizeof cmd, "get%s %s%s%s",
2187                             global_aflag ? " -a" : "", dir,
2188                             file2 == NULL ? "" : " ",
2189                             file2 == NULL ? "" : file2);
2190                         err = parse_dispatch_command(conn, cmd,
2191                             &remote_path, startdir, 1, 0);
2192                         free(dir);
2193                         free(startdir);
2194                         free(remote_path);
2195                         free(conn);
2196                         return (err);
2197                 }
2198                 free(dir);
2199         }
2200
2201         setvbuf(stdout, NULL, _IOLBF, 0);
2202         setvbuf(infile, NULL, _IOLBF, 0);
2203
2204         interactive = !batchmode && isatty(STDIN_FILENO);
2205         err = 0;
2206         for (;;) {
2207                 struct sigaction sa;
2208
2209                 interrupted = 0;
2210                 memset(&sa, 0, sizeof(sa));
2211                 sa.sa_handler = interactive ? read_interrupt : killchild;
2212                 if (sigaction(SIGINT, &sa, NULL) == -1) {
2213                         debug3("sigaction(%s): %s", strsignal(SIGINT),
2214                             strerror(errno));
2215                         break;
2216                 }
2217                 if (el == NULL) {
2218                         if (interactive)
2219                                 printf("sftp> ");
2220                         if (fgets(cmd, sizeof(cmd), infile) == NULL) {
2221                                 if (interactive)
2222                                         printf("\n");
2223                                 if (interrupted)
2224                                         continue;
2225                                 break;
2226                         }
2227                 } else {
2228 #ifdef USE_LIBEDIT
2229                         const char *line;
2230                         int count = 0;
2231
2232                         if ((line = el_gets(el, &count)) == NULL ||
2233                             count <= 0) {
2234                                 printf("\n");
2235                                 if (interrupted)
2236                                         continue;
2237                                 break;
2238                         }
2239                         history(hl, &hev, H_ENTER, line);
2240                         if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
2241                                 fprintf(stderr, "Error: input line too long\n");
2242                                 continue;
2243                         }
2244 #endif /* USE_LIBEDIT */
2245                 }
2246
2247                 cmd[strcspn(cmd, "\n")] = '\0';
2248
2249                 /* Handle user interrupts gracefully during commands */
2250                 interrupted = 0;
2251                 ssh_signal(SIGINT, cmd_interrupt);
2252
2253                 err = parse_dispatch_command(conn, cmd, &remote_path,
2254                     startdir, batchmode, !interactive && el == NULL);
2255                 if (err != 0)
2256                         break;
2257         }
2258         ssh_signal(SIGCHLD, SIG_DFL);
2259         free(remote_path);
2260         free(startdir);
2261         free(conn);
2262
2263 #ifdef USE_LIBEDIT
2264         if (el != NULL)
2265                 el_end(el);
2266 #endif /* USE_LIBEDIT */
2267
2268         /* err == 1 signifies normal "quit" exit */
2269         return (err >= 0 ? 0 : -1);
2270 }
2271
2272 static void
2273 connect_to_server(char *path, char **args, int *in, int *out)
2274 {
2275         int c_in, c_out;
2276
2277 #ifdef USE_PIPES
2278         int pin[2], pout[2];
2279
2280         if ((pipe(pin) == -1) || (pipe(pout) == -1))
2281                 fatal("pipe: %s", strerror(errno));
2282         *in = pin[0];
2283         *out = pout[1];
2284         c_in = pout[0];
2285         c_out = pin[1];
2286 #else /* USE_PIPES */
2287         int inout[2];
2288
2289         if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
2290                 fatal("socketpair: %s", strerror(errno));
2291         *in = *out = inout[0];
2292         c_in = c_out = inout[1];
2293 #endif /* USE_PIPES */
2294
2295         if ((sshpid = fork()) == -1)
2296                 fatal("fork: %s", strerror(errno));
2297         else if (sshpid == 0) {
2298                 if ((dup2(c_in, STDIN_FILENO) == -1) ||
2299                     (dup2(c_out, STDOUT_FILENO) == -1)) {
2300                         fprintf(stderr, "dup2: %s\n", strerror(errno));
2301                         _exit(1);
2302                 }
2303                 close(*in);
2304                 close(*out);
2305                 close(c_in);
2306                 close(c_out);
2307
2308                 /*
2309                  * The underlying ssh is in the same process group, so we must
2310                  * ignore SIGINT if we want to gracefully abort commands,
2311                  * otherwise the signal will make it to the ssh process and
2312                  * kill it too.  Contrawise, since sftp sends SIGTERMs to the
2313                  * underlying ssh, it must *not* ignore that signal.
2314                  */
2315                 ssh_signal(SIGINT, SIG_IGN);
2316                 ssh_signal(SIGTERM, SIG_DFL);
2317                 execvp(path, args);
2318                 fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
2319                 _exit(1);
2320         }
2321
2322         ssh_signal(SIGTERM, killchild);
2323         ssh_signal(SIGINT, killchild);
2324         ssh_signal(SIGHUP, killchild);
2325         ssh_signal(SIGTSTP, suspchild);
2326         ssh_signal(SIGTTIN, suspchild);
2327         ssh_signal(SIGTTOU, suspchild);
2328         ssh_signal(SIGCHLD, sigchld_handler);
2329         close(c_in);
2330         close(c_out);
2331 }
2332
2333 static void
2334 usage(void)
2335 {
2336         extern char *__progname;
2337
2338         fprintf(stderr,
2339             "usage: %s [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
2340             "          [-D sftp_server_path] [-F ssh_config] [-i identity_file]\n"
2341             "          [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
2342             "          [-R num_requests] [-S program] [-s subsystem | sftp_server]\n"
2343             "          destination\n",
2344             __progname);
2345         exit(1);
2346 }
2347
2348 int
2349 main(int argc, char **argv)
2350 {
2351         int in, out, ch, err, tmp, port = -1, noisy = 0;
2352         char *host = NULL, *user, *cp, *file2 = NULL;
2353         int debug_level = 0;
2354         char *file1 = NULL, *sftp_server = NULL;
2355         char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
2356         const char *errstr;
2357         LogLevel ll = SYSLOG_LEVEL_INFO;
2358         arglist args;
2359         extern int optind;
2360         extern char *optarg;
2361         struct sftp_conn *conn;
2362         size_t copy_buffer_len = 0;
2363         size_t num_requests = 0;
2364         long long limit_kbps = 0;
2365
2366         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2367         sanitise_stdfd();
2368         msetlocale();
2369
2370         seed_rng();
2371
2372         __progname = ssh_get_progname(argv[0]);
2373         memset(&args, '\0', sizeof(args));
2374         args.list = NULL;
2375         addargs(&args, "%s", ssh_program);
2376         addargs(&args, "-oForwardX11 no");
2377         addargs(&args, "-oPermitLocalCommand no");
2378         addargs(&args, "-oClearAllForwardings yes");
2379
2380         ll = SYSLOG_LEVEL_INFO;
2381         infile = stdin;
2382
2383         while ((ch = getopt(argc, argv,
2384             "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
2385                 switch (ch) {
2386                 /* Passed through to ssh(1) */
2387                 case 'A':
2388                 case '4':
2389                 case '6':
2390                 case 'C':
2391                         addargs(&args, "-%c", ch);
2392                         break;
2393                 /* Passed through to ssh(1) with argument */
2394                 case 'F':
2395                 case 'J':
2396                 case 'c':
2397                 case 'i':
2398                 case 'o':
2399                         addargs(&args, "-%c", ch);
2400                         addargs(&args, "%s", optarg);
2401                         break;
2402                 case 'q':
2403                         ll = SYSLOG_LEVEL_ERROR;
2404                         quiet = 1;
2405                         showprogress = 0;
2406                         addargs(&args, "-%c", ch);
2407                         break;
2408                 case 'P':
2409                         port = a2port(optarg);
2410                         if (port <= 0)
2411                                 fatal("Bad port \"%s\"\n", optarg);
2412                         break;
2413                 case 'v':
2414                         if (debug_level < 3) {
2415                                 addargs(&args, "-v");
2416                                 ll = SYSLOG_LEVEL_DEBUG1 + debug_level;
2417                         }
2418                         debug_level++;
2419                         break;
2420                 case '1':
2421                         fatal("SSH protocol v.1 is no longer supported");
2422                         break;
2423                 case '2':
2424                         /* accept silently */
2425                         break;
2426                 case 'a':
2427                         global_aflag = 1;
2428                         break;
2429                 case 'B':
2430                         copy_buffer_len = strtol(optarg, &cp, 10);
2431                         if (copy_buffer_len == 0 || *cp != '\0')
2432                                 fatal("Invalid buffer size \"%s\"", optarg);
2433                         break;
2434                 case 'b':
2435                         if (batchmode)
2436                                 fatal("Batch file already specified.");
2437
2438                         /* Allow "-" as stdin */
2439                         if (strcmp(optarg, "-") != 0 &&
2440                             (infile = fopen(optarg, "r")) == NULL)
2441                                 fatal("%s (%s).", strerror(errno), optarg);
2442                         showprogress = 0;
2443                         quiet = batchmode = 1;
2444                         addargs(&args, "-obatchmode yes");
2445                         break;
2446                 case 'f':
2447                         global_fflag = 1;
2448                         break;
2449                 case 'N':
2450                         noisy = 1; /* Used to clear quiet mode after getopt */
2451                         break;
2452                 case 'p':
2453                         global_pflag = 1;
2454                         break;
2455                 case 'D':
2456                         sftp_direct = optarg;
2457                         break;
2458                 case 'l':
2459                         limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
2460                             &errstr);
2461                         if (errstr != NULL)
2462                                 usage();
2463                         limit_kbps *= 1024; /* kbps */
2464                         break;
2465                 case 'r':
2466                         global_rflag = 1;
2467                         break;
2468                 case 'R':
2469                         num_requests = strtol(optarg, &cp, 10);
2470                         if (num_requests == 0 || *cp != '\0')
2471                                 fatal("Invalid number of requests \"%s\"",
2472                                     optarg);
2473                         break;
2474                 case 's':
2475                         sftp_server = optarg;
2476                         break;
2477                 case 'S':
2478                         ssh_program = optarg;
2479                         replacearg(&args, 0, "%s", ssh_program);
2480                         break;
2481                 case 'h':
2482                 default:
2483                         usage();
2484                 }
2485         }
2486
2487         /* Do this last because we want the user to be able to override it */
2488         addargs(&args, "-oForwardAgent no");
2489
2490         if (!isatty(STDERR_FILENO))
2491                 showprogress = 0;
2492
2493         if (noisy)
2494                 quiet = 0;
2495
2496         log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
2497
2498         if (sftp_direct == NULL) {
2499                 if (optind == argc || argc > (optind + 2))
2500                         usage();
2501                 argv += optind;
2502
2503                 switch (parse_uri("sftp", *argv, &user, &host, &tmp, &file1)) {
2504                 case -1:
2505                         usage();
2506                         break;
2507                 case 0:
2508                         if (tmp != -1)
2509                                 port = tmp;
2510                         break;
2511                 default:
2512                         /* Try with user, host and path. */
2513                         if (parse_user_host_path(*argv, &user, &host,
2514                             &file1) == 0)
2515                                 break;
2516                         /* Try with user and host. */
2517                         if (parse_user_host_port(*argv, &user, &host, NULL)
2518                             == 0)
2519                                 break;
2520                         /* Treat as a plain hostname. */
2521                         host = xstrdup(*argv);
2522                         host = cleanhostname(host);
2523                         break;
2524                 }
2525                 file2 = *(argv + 1);
2526
2527                 if (!*host) {
2528                         fprintf(stderr, "Missing hostname\n");
2529                         usage();
2530                 }
2531
2532                 if (port != -1)
2533                         addargs(&args, "-oPort %d", port);
2534                 if (user != NULL) {
2535                         addargs(&args, "-l");
2536                         addargs(&args, "%s", user);
2537                 }
2538
2539                 /* no subsystem if the server-spec contains a '/' */
2540                 if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)
2541                         addargs(&args, "-s");
2542
2543                 addargs(&args, "--");
2544                 addargs(&args, "%s", host);
2545                 addargs(&args, "%s", (sftp_server != NULL ?
2546                     sftp_server : "sftp"));
2547
2548                 connect_to_server(ssh_program, args.list, &in, &out);
2549         } else {
2550                 args.list = NULL;
2551                 addargs(&args, "sftp-server");
2552
2553                 connect_to_server(sftp_direct, args.list, &in, &out);
2554         }
2555         freeargs(&args);
2556
2557         conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
2558         if (conn == NULL)
2559                 fatal("Couldn't initialise connection to server");
2560
2561         if (!quiet) {
2562                 if (sftp_direct == NULL)
2563                         fprintf(stderr, "Connected to %s.\n", host);
2564                 else
2565                         fprintf(stderr, "Attached to %s.\n", sftp_direct);
2566         }
2567
2568         err = interactive_loop(conn, file1, file2);
2569
2570 #if !defined(USE_PIPES)
2571         shutdown(in, SHUT_RDWR);
2572         shutdown(out, SHUT_RDWR);
2573 #endif
2574
2575         close(in);
2576         close(out);
2577         if (batchmode)
2578                 fclose(infile);
2579
2580         while (waitpid(sshpid, NULL, 0) == -1 && sshpid > 1)
2581                 if (errno != EINTR)
2582                         fatal("Couldn't wait for ssh process: %s",
2583                             strerror(errno));
2584
2585         exit(err == 0 ? 0 : 1);
2586 }