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