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