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