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