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