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