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