11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: sftp.c,v 1.132 2010/12/04 00:18:01 djm Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies. 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/ioctl.h> 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_STAT_H 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/stat.h> 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h> 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h> 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/wait.h> 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_STATVFS_H 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/statvfs.h> 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <ctype.h> 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h> 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PATHS_H 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <paths.h> 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LIBGEN_H 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <libgen.h> 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_LIBEDIT 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <histedit.h> 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef void EditLine; 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h> 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h> 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h> 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h> 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_UTIL_H 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <util.h> 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_LIBUTIL_H 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <libutil.h> 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "pathnames.h" 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h" 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp.h" 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h" 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp-common.h" 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp-client.h" 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */ 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */ 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* File to read commands from */ 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodFILE* infile; 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Are we in batchfile mode? */ 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint batchmode = 0; 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* PID of ssh transport process */ 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic pid_t sshpid = -1; 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* This is set to 0 if the progressmeter is not desired. */ 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint showprogress = 1; 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* When this option is set, we always recursively download/upload directories */ 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint global_rflag = 0; 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* When this option is set, the file transfers will always preserve times */ 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint global_pflag = 0; 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* SIGINT received during command processing */ 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvolatile sig_atomic_t interrupted = 0; 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* I wish qsort() took a separate ctx for the comparison function...*/ 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint sort_flag; 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Context used for commandline completion */ 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct complete_ctx { 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct sftp_conn *conn; 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **remote_pathp; 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint remote_glob(struct sftp_conn *, const char *, int, 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *__progname; 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Separators for interactive commands */ 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define WHITESPACE " \t\r\n" 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ls flags */ 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_LONG_VIEW 0x0001 /* Full view ala ls -l */ 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_SHORT_VIEW 0x0002 /* Single row view ala ls -1 */ 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_NUMERIC_VIEW 0x0004 /* Long view with numeric uid/gid */ 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_NAME_SORT 0x0008 /* Sort by name (default) */ 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_TIME_SORT 0x0010 /* Sort by mtime */ 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_SIZE_SORT 0x0020 /* Sort by file size */ 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_REVERSE_SORT 0x0040 /* Reverse sort order */ 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_SHOW_ALL 0x0080 /* Don't skip filenames starting with '.' */ 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LS_SI_UNITS 0x0100 /* Display sizes as K, M, G, etc. */ 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW|LS_SI_UNITS) 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT) 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Commands for interactive mode */ 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_CHDIR 1 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_CHGRP 2 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_CHMOD 3 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_CHOWN 4 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_DF 24 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_GET 5 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_HELP 6 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LCHDIR 7 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LINK 25 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LLS 8 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LMKDIR 9 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LPWD 10 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LS 11 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_LUMASK 12 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_MKDIR 13 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_PUT 14 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_PWD 15 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_QUIT 16 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_RENAME 17 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_RM 18 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_RMDIR 19 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_SHELL 20 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_SYMLINK 21 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_VERSION 22 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define I_PROGRESS 23 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct CMD { 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *c; 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const int n; 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const int t; 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Type of completion */ 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define NOARGS 0 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define REMOTE 1 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define LOCAL 2 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic const struct CMD cmds[] = { 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "bye", I_QUIT, NOARGS }, 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "cd", I_CHDIR, REMOTE }, 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "chdir", I_CHDIR, REMOTE }, 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "chgrp", I_CHGRP, REMOTE }, 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "chmod", I_CHMOD, REMOTE }, 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "chown", I_CHOWN, REMOTE }, 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "df", I_DF, REMOTE }, 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "dir", I_LS, REMOTE }, 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "exit", I_QUIT, NOARGS }, 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "get", I_GET, REMOTE }, 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "help", I_HELP, NOARGS }, 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "lcd", I_LCHDIR, LOCAL }, 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "lchdir", I_LCHDIR, LOCAL }, 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "lls", I_LLS, LOCAL }, 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "lmkdir", I_LMKDIR, LOCAL }, 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "ln", I_LINK, REMOTE }, 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "lpwd", I_LPWD, LOCAL }, 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "ls", I_LS, REMOTE }, 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "lumask", I_LUMASK, NOARGS }, 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "mkdir", I_MKDIR, REMOTE }, 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "mget", I_GET, REMOTE }, 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "mput", I_PUT, LOCAL }, 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "progress", I_PROGRESS, NOARGS }, 1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "put", I_PUT, LOCAL }, 1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "pwd", I_PWD, REMOTE }, 1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "quit", I_QUIT, NOARGS }, 1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "rename", I_RENAME, REMOTE }, 1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "rm", I_RM, REMOTE }, 1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "rmdir", I_RMDIR, REMOTE }, 1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "symlink", I_SYMLINK, REMOTE }, 1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "version", I_VERSION, NOARGS }, 1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "!", I_SHELL, NOARGS }, 1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { "?", I_HELP, NOARGS }, 1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood { NULL, -1, -1 } 1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint interactive_loop(struct sftp_conn *, char *file1, char *file2); 2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */ 2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodkillchild(int signo) 2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sshpid > 1) { 2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood kill(sshpid, SIGTERM); 2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood waitpid(sshpid, NULL, 0); 2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood _exit(1); 2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */ 2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcmd_interrupt(int signo) 2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char msg[] = "\rInterrupt \n"; 2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int olderrno = errno; 2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood write(STDERR_FILENO, msg, sizeof(msg) - 1); 2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood interrupted = 1; 2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno = olderrno; 2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodhelp(void) 2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Available commands:\n" 2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "bye Quit sftp\n" 2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "cd path Change remote directory to 'path'\n" 2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "chgrp grp path Change group of file 'path' to 'grp'\n" 2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "chmod mode path Change permissions of file 'path' to 'mode'\n" 2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "chown own path Change owner of file 'path' to 'own'\n" 2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "df [-hi] [path] Display statistics for current directory or\n" 2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " filesystem containing 'path'\n" 2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "exit Quit sftp\n" 2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "get [-Ppr] remote [local] Download file\n" 2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "help Display this help text\n" 2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "lcd path Change local directory to 'path'\n" 2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "lls [ls-options [path]] Display local directory listing\n" 2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "lmkdir path Create local directory\n" 2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "ln [-s] oldpath newpath Link remote file (-s for symlink)\n" 2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "lpwd Print local working directory\n" 2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "ls [-1afhlnrSt] [path] Display remote directory listing\n" 2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "lumask umask Set local umask to 'umask'\n" 2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "mkdir path Create remote directory\n" 2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "progress Toggle display of progress meter\n" 2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "put [-Ppr] local [remote] Upload file\n" 2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "pwd Display remote working directory\n" 2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "quit Quit sftp\n" 2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "rename oldpath newpath Rename remote file\n" 2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "rm path Delete remote file\n" 2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "rmdir path Remove remote directory\n" 2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "symlink oldpath newpath Symlink remote file\n" 2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "version Show SFTP version\n" 2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "!command Execute 'command' in local shell\n" 2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "! Escape to local shell\n" 2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "? Synonym for help\n"); 2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlocal_do_shell(const char *args) 2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int status; 2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *shell; 2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pid_t pid; 2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!*args) 2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood args = NULL; 2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((shell = getenv("SHELL")) == NULL || *shell == '\0') 2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood shell = _PATH_BSHELL; 2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((pid = fork()) == -1) 2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Couldn't fork: %s", strerror(errno)); 2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pid == 0) { 2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX: child has pipe fds to ssh subproc open - issue? */ 2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (args) { 2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Executing %s -c \"%s\"", shell, args); 2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood execl(shell, shell, "-c", args, (char *)NULL); 2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Executing %s", shell); 2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood execl(shell, shell, (char *)NULL); 2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell, 2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood _exit(1); 2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (waitpid(pid, &status, 0) == -1) 2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno != EINTR) 2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Couldn't wait for child: %s", strerror(errno)); 2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!WIFEXITED(status)) 2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Shell exited abnormally"); 2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (WEXITSTATUS(status)) 2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Shell exited with status %d", WEXITSTATUS(status)); 2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlocal_do_ls(const char *args) 3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!args || !*args) 3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood local_do_shell(_PATH_LS); 3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else { 3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int len = strlen(_PATH_LS " ") + strlen(args) + 1; 3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *buf = xmalloc(len); 3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX: quoting - rip quoting code from ftp? */ 3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood snprintf(buf, len, _PATH_LS " %s", args); 3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood local_do_shell(buf); 3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(buf); 3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Strip one path (usually the pwd) from the start of another */ 3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char * 3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpath_strip(char *path, char *strip) 3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t len; 3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strip == NULL) 3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (xstrdup(path)); 3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = strlen(strip); 3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strncmp(path, strip, len) == 0) { 3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strip[len - 1] != '/' && path[len] == '/') 3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len++; 3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (xstrdup(path + len)); 3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (xstrdup(path)); 3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char * 3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmake_absolute(char *p, char *pwd) 3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *abs_str; 3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Derelativise */ 3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (p && p[0] != '/') { 3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_str = path_append(pwd, p); 3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(p); 3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(abs_str); 3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(p); 3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_getput_flags(const char *cmd, char **argv, int argc, int *pflag, 3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int *rflag) 3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern int opterr, optind, optopt, optreset; 3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ch; 3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood optind = optreset = 1; 3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood opterr = 0; 3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *rflag = *pflag = 0; 3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((ch = getopt(argc, argv, "PpRr")) != -1) { 3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (ch) { 3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'p': 3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'P': 3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *pflag = 1; 3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'r': 3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'R': 3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *rflag = 1; 3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: Invalid flag -%c", cmd, optopt); 3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return optind; 3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_link_flags(const char *cmd, char **argv, int argc, int *sflag) 3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern int opterr, optind, optopt, optreset; 3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ch; 3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood optind = optreset = 1; 3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood opterr = 0; 3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *sflag = 0; 3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((ch = getopt(argc, argv, "s")) != -1) { 3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (ch) { 3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 's': 3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *sflag = 1; 3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: Invalid flag -%c", cmd, optopt); 3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return optind; 4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_ls_flags(char **argv, int argc, int *lflag) 4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern int opterr, optind, optopt, optreset; 4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ch; 4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood optind = optreset = 1; 4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood opterr = 0; 4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag = LS_NAME_SORT; 4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) { 4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (ch) { 4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '1': 4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag &= ~VIEW_FLAGS; 4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_SHORT_VIEW; 4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'S': 4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag &= ~SORT_FLAGS; 4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_SIZE_SORT; 4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'a': 4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_SHOW_ALL; 4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'f': 4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag &= ~SORT_FLAGS; 4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'h': 4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_SI_UNITS; 4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'l': 4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag &= ~LS_SHORT_VIEW; 4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_LONG_VIEW; 4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'n': 4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag &= ~LS_SHORT_VIEW; 4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW; 4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'r': 4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_REVERSE_SORT; 4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 't': 4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag &= ~SORT_FLAGS; 4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag |= LS_TIME_SORT; 4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("ls: Invalid flag -%c", optopt); 4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return optind; 4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag) 4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern int opterr, optind, optopt, optreset; 4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ch; 4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood optind = optreset = 1; 4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood opterr = 0; 4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *hflag = *iflag = 0; 4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((ch = getopt(argc, argv, "hi")) != -1) { 4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (ch) { 4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'h': 4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *hflag = 1; 4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'i': 4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *iflag = 1; 4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: Invalid flag -%c", cmd, optopt); 4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return optind; 4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodis_dir(char *path) 4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct stat sb; 4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX: report errors? */ 4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (stat(path, &sb) == -1) 4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(0); 4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(S_ISDIR(sb.st_mode)); 4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodremote_is_dir(struct sftp_conn *conn, char *path) 4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Attrib *a; 5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX: report errors? */ 5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((a = do_stat(conn, path, 1)) == NULL) 5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(0); 5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) 5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(0); 5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(S_ISDIR(a->perm)); 5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ 5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpathname_is_dir(char *pathname) 5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t l = strlen(pathname); 5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return l > 0 && pathname[l - 1] == '/'; 5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, 5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int pflag, int rflag) 5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *abs_src = NULL; 5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *abs_dst = NULL; 5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood glob_t g; 5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *filename, *tmp=NULL; 5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i, err = 0; 5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_src = xstrdup(src); 5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_src = make_absolute(abs_src, pwd); 5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&g, 0, sizeof(g)); 5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Looking up %s", abs_src); 5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) { 5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("File \"%s\" not found.", abs_src); 5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If multiple matches then dst must be a directory or 5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * unspecified. 5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc > 1 && dst != NULL && !is_dir(dst)) { 5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Multiple source paths, but destination " 5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "\"%s\" is not a directory", dst); 5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = xstrdup(g.gl_pathv[i]); 5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((filename = basename(tmp)) == NULL) { 5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("basename %s: %s", tmp, strerror(errno)); 5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc == 1 && dst) { 5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (is_dir(dst)) { 5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = path_append(dst, filename); 5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = xstrdup(dst); 5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (dst) { 5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = path_append(dst, filename); 5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = xstrdup(filename); 5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, 5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pflag || global_pflag, 1) == -1) 5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, 5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pflag || global_pflag) == -1) 5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(abs_dst); 5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = NULL; 5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodout: 5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(abs_src); 5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(err); 5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, 5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int pflag, int rflag) 5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp_dst = NULL; 5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *abs_dst = NULL; 5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp = NULL, *filename = NULL; 5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood glob_t g; 6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int err = 0; 6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i, dst_is_dir = 1; 6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct stat sb; 6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (dst) { 6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp_dst = xstrdup(dst); 6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp_dst = make_absolute(tmp_dst, pwd); 6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&g, 0, sizeof(g)); 6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug3("Looking up %s", src); 6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (glob(src, GLOB_NOCHECK | GLOB_MARK, NULL, &g)) { 6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("File \"%s\" not found.", src); 6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* If we aren't fetching to pwd then stash this status for later */ 6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp_dst != NULL) 6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dst_is_dir = remote_is_dir(conn, tmp_dst); 6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* If multiple matches, dst may be directory or unspecified */ 6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) { 6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Multiple paths match, but destination " 6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "\"%s\" is not a directory", tmp_dst); 6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (stat(g.gl_pathv[i], &sb) == -1) { 6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("stat %s: %s", g.gl_pathv[i], strerror(errno)); 6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = xstrdup(g.gl_pathv[i]); 6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((filename = basename(tmp)) == NULL) { 6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("basename %s: %s", tmp, strerror(errno)); 6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc == 1 && tmp_dst) { 6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* If directory specified, append filename */ 6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (dst_is_dir) 6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = path_append(tmp_dst, filename); 6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = xstrdup(tmp_dst); 6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (tmp_dst) { 6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = path_append(tmp_dst, filename); 6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood abs_dst = make_absolute(xstrdup(filename), pwd); 6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (upload_dir(conn, g.gl_pathv[i], abs_dst, 6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pflag || global_pflag, 1) == -1) 6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (do_upload(conn, g.gl_pathv[i], abs_dst, 6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pflag || global_pflag) == -1) 6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodout: 6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (abs_dst) 6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(abs_dst); 6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp_dst) 6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp_dst); 6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(err); 6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsdirent_comp(const void *aa, const void *bb) 6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SFTP_DIRENT *a = *(SFTP_DIRENT **)aa; 6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SFTP_DIRENT *b = *(SFTP_DIRENT **)bb; 6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1; 6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1)) 6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sort_flag & LS_NAME_SORT) 6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (rmul * strcmp(a->filename, b->filename)); 6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (sort_flag & LS_TIME_SORT) 6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (rmul * NCMP(a->a.mtime, b->a.mtime)); 6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (sort_flag & LS_SIZE_SORT) 6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (rmul * NCMP(a->a.size, b->a.size)); 6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Unknown ls sort type"); 6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* sftp ls.1 replacement for directories */ 6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) 6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int n; 7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int c = 1, colspace = 0, columns = 1; 7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SFTP_DIRENT **d; 7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((n = do_readdir(conn, path, &d)) != 0) 7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (n); 7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(lflag & LS_SHORT_VIEW)) { 7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int m = 0, width = 80; 7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct winsize ws; 7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp; 7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Count entries for sort and find longest filename */ 7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (n = 0; d[n] != NULL; n++) { 7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL)) 7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m = MAX(m, strlen(d[n]->filename)); 7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Add any subpath that also needs to be counted */ 7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = path_strip(path, strip_path); 7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m += strlen(tmp); 7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) 7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood width = ws.ws_col; 7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood columns = width / (m + 2); 7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood columns = MAX(columns, 1); 7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood colspace = width / columns; 7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood colspace = MIN(colspace, width); 7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lflag & SORT_FLAGS) { 7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (n = 0; d[n] != NULL; n++) 7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ; /* count entries */ 7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT); 7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood qsort(d, n, sizeof(*d), sdirent_comp); 7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (n = 0; d[n] != NULL && !interrupted; n++) { 7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp, *fname; 7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL)) 7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = path_append(path, d[n]->filename); 7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fname = path_strip(tmp, strip_path); 7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lflag & LS_LONG_VIEW) { 7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) { 7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *lname; 7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct stat sb; 7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&sb, 0, sizeof(sb)); 7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attrib_to_stat(&d[n]->a, &sb); 7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood lname = ls_file(fname, &sb, 1, 7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (lflag & LS_SI_UNITS)); 7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%s\n", lname); 7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(lname); 7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%s\n", d[n]->longname); 7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%-*s", colspace, fname); 7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (c >= columns) { 7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = 1; 7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c++; 7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(fname); 7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(lflag & LS_LONG_VIEW) && (c != 1)) 7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood free_sftp_dirents(d); 7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* sftp ls.1 replacement which handles path globs */ 7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, 7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int lflag) 7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Attrib *a = NULL; 7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *fname, *lname; 7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood glob_t g; 7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int err; 7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct winsize ws; 7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; 7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&g, 0, sizeof(g)); 7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (remote_glob(conn, path, 7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT, NULL, &g) || 7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (g.gl_pathc && !g.gl_matchc)) { 7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_pathc) 7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Can't ls: \"%s\" not found", path); 8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (interrupted) 8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If the glob returns a single match and it is a directory, 8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * then just list its contents. 8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc == 1 && g.gl_statv[0] != NULL && 8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood S_ISDIR(g.gl_statv[0]->st_mode)) { 8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag); 8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return err; 8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) 8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood width = ws.ws_col; 8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(lflag & LS_SHORT_VIEW)) { 8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Count entries for sort and find longest filename */ 8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i]; i++) 8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m = MAX(m, strlen(g.gl_pathv[i])); 8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood columns = width / (m + 2); 8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood columns = MAX(columns, 1); 8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood colspace = width / columns; 8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) { 8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fname = path_strip(g.gl_pathv[i], strip_path); 8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lflag & LS_LONG_VIEW) { 8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_statv[i] == NULL) { 8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("no stat information for %s", fname); 8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood lname = ls_file(fname, g.gl_statv[i], 1, 8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (lflag & LS_SI_UNITS)); 8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%s\n", lname); 8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(lname); 8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%-*s", colspace, fname); 8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (c >= columns) { 8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c = 1; 8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c++; 8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(fname); 8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(lflag & LS_LONG_VIEW) && (c != 1)) 8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out: 8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_pathc) 8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddo_df(struct sftp_conn *conn, char *path, int hflag, int iflag) 8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct sftp_statvfs st; 8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char s_used[FMT_SCALED_STRSIZE]; 8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char s_avail[FMT_SCALED_STRSIZE]; 8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char s_root[FMT_SCALED_STRSIZE]; 8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char s_total[FMT_SCALED_STRSIZE]; 8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood unsigned long long ffree; 8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (do_statvfs(conn, path, &st, 1) == -1) 8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (iflag) { 8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ffree = st.f_files ? (100 * (st.f_files - st.f_ffree) / st.f_files) : 0; 8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf(" Inodes Used Avail " 8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "(root) %%Capacity\n"); 8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%11llu %11llu %11llu %11llu %3llu%%\n", 8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)st.f_files, 8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(st.f_files - st.f_ffree), 8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)st.f_favail, 8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)st.f_ffree, ffree); 8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (hflag) { 8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strlcpy(s_used, "error", sizeof(s_used)); 8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strlcpy(s_avail, "error", sizeof(s_avail)); 8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strlcpy(s_root, "error", sizeof(s_root)); 8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strlcpy(s_total, "error", sizeof(s_total)); 8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used); 8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fmt_scaled(st.f_bavail * st.f_frsize, s_avail); 8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fmt_scaled(st.f_bfree * st.f_frsize, s_root); 8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fmt_scaled(st.f_blocks * st.f_frsize, s_total); 8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf(" Size Used Avail (root) %%Capacity\n"); 8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%7sB %7sB %7sB %7sB %3llu%%\n", 8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s_total, s_used, s_avail, s_root, 8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(100 * (st.f_blocks - st.f_bfree) / 8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood st.f_blocks)); 8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf(" Size Used Avail " 9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "(root) %%Capacity\n"); 9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%12llu %12llu %12llu %12llu %3llu%%\n", 9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(st.f_frsize * st.f_blocks / 1024), 9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(st.f_frsize * 9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (st.f_blocks - st.f_bfree) / 1024), 9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(st.f_frsize * st.f_bavail / 1024), 9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(st.f_frsize * st.f_bfree / 1024), 9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (unsigned long long)(100 * (st.f_blocks - st.f_bfree) / 9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood st.f_blocks)); 9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Undo escaping of glob sequences in place. Used to undo extra escaping 9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * applied in makeargv() when the string is destined for a function that 9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * does not glob it. 9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodundo_glob_escape(char *s) 9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t i, j; 9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = j = 0;;) { 9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (s[i] == '\0') { 9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j] = '\0'; 9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (s[i] != '\\') { 9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j++] = s[i++]; 9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* s[i] == '\\' */ 9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ++i; 9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (s[i]) { 9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '?': 9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '[': 9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '*': 9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\\': 9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j++] = s[i++]; 9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\0': 9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j++] = '\\'; 9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j] = '\0'; 9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j++] = '\\'; 9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood s[j++] = s[i++]; 9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Split a string into an argument vector using sh(1)-style quoting, 9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * comment and escaping rules, but with some tweaks to handle glob(3) 9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * wildcards. 9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * The "sloppy" flag allows for recovery from missing terminating quote, for 9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * use in parsing incomplete commandlines during tab autocompletion. 9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns NULL on error or a NULL-terminated array of arguments. 9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If "lastquote" is not NULL, the quoting character used for the last 9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * argument is placed in *lastquote ("\0", "'" or "\""). 9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If "terminated" is not NULL, *terminated will be set to 1 when the 9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * last argument's quote has been properly terminated or 0 otherwise. 9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This parameter is only of use if "sloppy" is set. 9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define MAXARGS 128 9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define MAXARGLEN 8192 9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char ** 9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmakeargv(const char *arg, int *argcp, int sloppy, char *lastquote, 9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int *terminated) 9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int argc, quot; 9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t i, j; 9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood static char argvs[MAXARGLEN]; 9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood static char *argv[MAXARGS + 1]; 9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q; 9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *argcp = argc = 0; 9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strlen(arg) > sizeof(argvs) - 1) { 9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood args_too_longs: 9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("string too long"); 9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (terminated != NULL) 9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *terminated = 1; 9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lastquote != NULL) 9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lastquote = '\0'; 9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = MA_START; 9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood i = j = 0; 9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (;;) { 9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (isspace(arg[i])) { 9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_UNQUOTED) { 9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Terminate current argument */ 9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = '\0'; 9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argc++; 9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = MA_START; 10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (state != MA_START) 10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (arg[i] == '"' || arg[i] == '\'') { 10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE; 10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_START) { 10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argv[argc] = argvs + j; 10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = q; 10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lastquote != NULL) 10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lastquote = arg[i]; 10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (state == MA_UNQUOTED) 10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = q; 10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (state == q) 10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = MA_UNQUOTED; 10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (arg[i] == '\\') { 10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_SQUOTE || state == MA_DQUOTE) { 10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood quot = state == MA_SQUOTE ? '\'' : '"'; 10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Unescape quote we are in */ 10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX support \n and friends? */ 10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (arg[i + 1] == quot) { 10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood i++; 10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (arg[i + 1] == '?' || 10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood arg[i + 1] == '[' || arg[i + 1] == '*') { 10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Special case for sftp: append 10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * double-escaped glob sequence - 10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * glob will undo one level of 10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * escaping. NB. string can grow here. 10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (j >= sizeof(argvs) - 5) 10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto args_too_longs; 10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = '\\'; 10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i++]; 10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = '\\'; 10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i++]; 10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_START) { 10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argv[argc] = argvs + j; 10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = MA_UNQUOTED; 10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lastquote != NULL) 10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lastquote = '\0'; 10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (arg[i + 1] == '?' || arg[i + 1] == '[' || 10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood arg[i + 1] == '*' || arg[i + 1] == '\\') { 10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Special case for sftp: append 10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * escaped glob sequence - 10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * glob will undo one level of 10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * escaping. 10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i++]; 10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Unescape everything */ 10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX support \n and friends? */ 10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood i++; 10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (arg[i] == '#') { 10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_SQUOTE || state == MA_DQUOTE) 10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto string_done; 10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (arg[i] == '\0') { 10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_SQUOTE || state == MA_DQUOTE) { 10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sloppy) { 10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = MA_UNQUOTED; 10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (terminated != NULL) 10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *terminated = 0; 10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto string_done; 10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Unterminated quoted argument"); 10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood string_done: 10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_UNQUOTED) { 10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = '\0'; 10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argc++; 10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (state == MA_START) { 10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argv[argc] = argvs + j; 10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood state = MA_UNQUOTED; 10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lastquote != NULL) 10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lastquote = '\0'; 10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((state == MA_SQUOTE || state == MA_DQUOTE) && 10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) { 10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Special case for sftp: escape quoted 10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * glob(3) wildcards. NB. string can grow 10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * here. 11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (j >= sizeof(argvs) - 3) 11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto args_too_longs; 11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = '\\'; 11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argvs[j++] = arg[i]; 11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood i++; 11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *argcp = argc; 11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return argv; 11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, 11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2) 11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *cmd, *cp = *cpp; 11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *cp2, **argv; 11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int base = 0; 11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood long l; 11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i, cmdnum, optidx, argc; 11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Skip leading whitespace */ 11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = cp + strspn(cp, WHITESPACE); 11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Check for leading '-' (disable error processing) */ 11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *iflag = 0; 11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (*cp == '-') { 11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *iflag = 1; 11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp++; 11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = cp + strspn(cp, WHITESPACE); 11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Ignore blank lines and lines which begin with comment '#' char */ 11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (*cp == '\0' || *cp == '#') 11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL) 11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Figure out which command we have */ 11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; cmds[i].c != NULL; i++) { 11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strcasecmp(cmds[i].c, argv[0]) == 0) 11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmdnum = cmds[i].n; 11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmd = cmds[i].c; 11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Special case */ 11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (*cp == '!') { 11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp++; 11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmdnum = I_SHELL; 11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (cmdnum == -1) { 11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Invalid command."); 11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get arguments and parse flags */ 11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *lflag = *pflag = *rflag = *hflag = *n_arg = 0; 11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = *path2 = NULL; 11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood optidx = 1; 11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (cmdnum) { 11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_GET: 11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_PUT: 11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((optidx = parse_getput_flags(cmd, argv, argc, 11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pflag, rflag)) == -1) 11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get first pathname (mandatory) */ 11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx < 1) { 11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("You must specify at least one path after a " 11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "%s command.", cmd); 11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = xstrdup(argv[optidx]); 11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get second pathname (optional) */ 11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx > 1) { 11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path2 = xstrdup(argv[optidx + 1]); 11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Destination is not globbed */ 11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood undo_glob_escape(*path2); 11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LINK: 11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) 11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_SYMLINK: 11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_RENAME: 11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx < 2) { 11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("You must specify two paths after a %s " 11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "command.", cmd); 11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = xstrdup(argv[optidx]); 11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path2 = xstrdup(argv[optidx + 1]); 11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Paths are not globbed */ 11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood undo_glob_escape(*path1); 11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood undo_glob_escape(*path2); 11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_RM: 12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_MKDIR: 12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_RMDIR: 12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHDIR: 12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LCHDIR: 12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LMKDIR: 12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get pathname (mandatory) */ 12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx < 1) { 12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("You must specify a path after a %s command.", 12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmd); 12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = xstrdup(argv[optidx]); 12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Only "rm" globs */ 12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cmdnum != I_RM) 12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood undo_glob_escape(*path1); 12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_DF: 12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((optidx = parse_df_flags(cmd, argv, argc, hflag, 12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood iflag)) == -1) 12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Default to current directory if no path specified */ 12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx < 1) 12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = NULL; 12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else { 12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = xstrdup(argv[optidx]); 12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood undo_glob_escape(*path1); 12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LS: 12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) 12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(-1); 12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Path is optional */ 12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx > 0) 12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = xstrdup(argv[optidx]); 12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LLS: 12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Skip ls command and following whitespace */ 12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = cp + strlen(cmd) + strspn(cp, WHITESPACE); 12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_SHELL: 12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Uses the rest of the line */ 12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LUMASK: 12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHMOD: 12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood base = 8; 12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHOWN: 12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHGRP: 12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get numeric arg (mandatory) */ 12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx < 1) 12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto need_num_arg; 12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood errno = 0; 12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood l = strtol(argv[optidx], &cp2, base); 12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cp2 == argv[optidx] || *cp2 != '\0' || 12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || 12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood l < 0) { 12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood need_num_arg: 12551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("You must supply a numeric argument " 12561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "to the %s command.", cmd); 12571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 12581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 12591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *n_arg = l; 12601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cmdnum == I_LUMASK) 12611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get pathname (mandatory) */ 12631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (argc - optidx < 2) { 12641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("You must specify a path after a %s command.", 12651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmd); 12661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 12671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 12681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *path1 = xstrdup(argv[optidx + 1]); 12691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_QUIT: 12711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_PWD: 12721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LPWD: 12731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_HELP: 12741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_VERSION: 12751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_PROGRESS: 12761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 12771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 12781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Command not implemented"); 12791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 12801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 12811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *cpp = cp; 12821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return(cmdnum); 12831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 12841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 12851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 12861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodparse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, 12871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int err_abort) 12881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 12891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *path1, *path2, *tmp; 12901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; 12911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int cmdnum, i; 12921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood unsigned long n_arg = 0; 12931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Attrib a, *aa; 12941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char path_buf[MAXPATHLEN]; 12951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int err = 0; 12961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood glob_t g; 12971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 12981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = path2 = NULL; 12991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, 13001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &sflag, &n_arg, &path1, &path2); 13011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 13021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (iflag != 0) 13031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err_abort = 0; 13041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 13051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&g, 0, sizeof(g)); 13061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 13071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Perform command */ 13081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (cmdnum) { 13091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 0: 13101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Blank line */ 13111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case -1: 13131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Unrecognized command */ 13141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 13151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_GET: 13171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = process_get(conn, path1, path2, *pwd, pflag, rflag); 13181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_PUT: 13201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = process_put(conn, path1, path2, *pwd, pflag, rflag); 13211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_RENAME: 13231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path2 = make_absolute(path2, *pwd); 13251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_rename(conn, path1, path2); 13261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_SYMLINK: 13281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sflag = 1; 13291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LINK: 13301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path2 = make_absolute(path2, *pwd); 13321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); 13331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_RM: 13351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 13371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 13381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Removing %s\n", g.gl_pathv[i]); 13391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_rm(conn, g.gl_pathv[i]); 13401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err != 0 && err_abort) 13411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 13431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_MKDIR: 13451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attrib_clear(&a); 13471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 13481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood a.perm = 0777; 13491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_mkdir(conn, path1, &a, 1); 13501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_RMDIR: 13521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_rmdir(conn, path1); 13541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHDIR: 13561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((tmp = do_realpath(conn, path1)) == NULL) { 13581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 1; 13591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 13611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((aa = do_stat(conn, tmp, 0)) == NULL) { 13621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 13631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 1; 13641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 13661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { 13671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Can't change directory: Can't check target"); 13681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 13691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 1; 13701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 13721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!S_ISDIR(aa->perm)) { 13731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Can't change directory: \"%s\" is not " 13741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "a directory", tmp); 13751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 13761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 1; 13771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 13791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(*pwd); 13801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *pwd = tmp; 13811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LS: 13831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!path1) { 13841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood do_ls_dir(conn, *pwd, *pwd, lflag); 13851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 13871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 13881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Strip pwd off beginning of non-absolute paths */ 13891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = NULL; 13901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (*path1 != '/') 13911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = *pwd; 13921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 13931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 13941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_globbed_ls(conn, path1, tmp, lflag); 13951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 13961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_DF: 13971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Default to current directory if no path specified */ 13981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (path1 == NULL) 13991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = xstrdup(*pwd); 14001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 14011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_df(conn, path1, hflag, iflag); 14021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LCHDIR: 14041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (chdir(path1) == -1) { 14051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Couldn't change local directory to " 14061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "\"%s\": %s", path1, strerror(errno)); 14071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 1; 14081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LMKDIR: 14111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (mkdir(path1, 0777) == -1) { 14121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Couldn't create local directory " 14131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "\"%s\": %s", path1, strerror(errno)); 14141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 1; 14151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LLS: 14181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood local_do_ls(cmd); 14191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_SHELL: 14211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood local_do_shell(cmd); 14221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LUMASK: 14241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood umask(n_arg); 14251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Local umask: %03lo\n", n_arg); 14261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHMOD: 14281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 14291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood attrib_clear(&a); 14301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 14311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood a.perm = n_arg; 14321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 14331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 14341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Changing mode on %s\n", g.gl_pathv[i]); 14351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_setstat(conn, g.gl_pathv[i], &a); 14361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err != 0 && err_abort) 14371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHOWN: 14411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_CHGRP: 14421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood path1 = make_absolute(path1, *pwd); 14431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); 14441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; g.gl_pathv[i] && !interrupted; i++) { 14451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) { 14461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err_abort) { 14471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 14481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 14501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 14511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { 14531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Can't get current ownership of " 14541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "remote file \"%s\"", g.gl_pathv[i]); 14551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err_abort) { 14561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 14571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 14591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 14601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; 14621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cmdnum == I_CHOWN) { 14631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Changing owner on %s\n", g.gl_pathv[i]); 14641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood aa->uid = n_arg; 14651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 14661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Changing group on %s\n", g.gl_pathv[i]); 14671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood aa->gid = n_arg; 14681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = do_setstat(conn, g.gl_pathv[i], aa); 14701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err != 0 && err_abort) 14711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_PWD: 14751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Remote working directory: %s\n", *pwd); 14761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_LPWD: 14781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!getcwd(path_buf, sizeof(path_buf))) { 14791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Couldn't get local cwd: %s", strerror(errno)); 14801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = -1; 14811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 14831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Local working directory: %s\n", path_buf); 14841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_QUIT: 14861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Processed below */ 14871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_HELP: 14891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood help(); 14901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_VERSION: 14921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("SFTP protocol version %u\n", sftp_proto_version(conn)); 14931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 14941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case I_PROGRESS: 14951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood showprogress = !showprogress; 14961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (showprogress) 14971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Progress meter enabled\n"); 14981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 14991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Progress meter disabled\n"); 15001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 15011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 15021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%d is not implemented", cmdnum); 15031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 15041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_pathc) 15061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 15071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (path1) 15081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(path1); 15091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (path2) 15101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(path2); 15111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* If an unignored error occurs in batch mode we should abort. */ 15131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err_abort && err != 0) 15141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 15151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (cmdnum == I_QUIT) 15161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (1); 15171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (0); 15191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 15201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_LIBEDIT 15221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char * 15231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprompt(EditLine *el) 15241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 15251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ("sftp> "); 15261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 15271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Display entries in 'list' after skipping the first 'len' chars */ 15291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 15301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcomplete_display(char **list, u_int len) 15311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 15321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int y, m = 0, width = 80, columns = 1, colspace = 0, llen; 15331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct winsize ws; 15341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp; 15351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Count entries for sort and find longest */ 15371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 0; list[y]; y++) 15381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m = MAX(m, strlen(list[y])); 15391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) 15411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood width = ws.ws_col; 15421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m = m > len ? m - len : 0; 15441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood columns = width / (m + 2); 15451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood columns = MAX(columns, 1); 15461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood colspace = width / columns; 15471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood colspace = MIN(colspace, width); 15481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 15501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m = 1; 15511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 0; list[y]; y++) { 15521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood llen = strlen(list[y]); 15531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = llen > len ? list[y] + len : ""; 15541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("%-*s", colspace, tmp); 15551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (m >= columns) { 15561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 15571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m = 1; 15581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 15591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood m++; 15601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 15611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 15621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 15631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 15651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Given a "list" of words that begin with a common prefix of "word", 15661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * attempt to find an autocompletion to extends "word" by the next 15671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * characters common to all entries in "list". 15681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 15691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char * 15701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcomplete_ambiguous(const char *word, char **list, size_t count) 15711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 15721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (word == NULL) 15731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return NULL; 15741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (count > 0) { 15761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int y, matchlen = strlen(list[0]); 15771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Find length of common stem */ 15791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 1; list[y]; y++) { 15801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int x; 15811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (x = 0; x < matchlen; x++) 15831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (list[0][x] != list[y][x]) 15841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 15851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood matchlen = x; 15871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 15881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (matchlen > strlen(word)) { 15901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp = xstrdup(list[0]); 15911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp[matchlen] = '\0'; 15931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return tmp; 15941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 15951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 15961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 15971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return xstrdup(word); 15981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 15991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Autocomplete a sftp command */ 16011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 16021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcomplete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote, 16031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int terminated) 16041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 16051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int y, count = 0, cmdlen, tmplen; 16061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp, **list, argterm[3]; 16071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const LineInfo *lf; 16081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood list = xcalloc((sizeof(cmds) / sizeof(*cmds)) + 1, sizeof(char *)); 16101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* No command specified: display all available commands */ 16121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cmd == NULL) { 16131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 0; cmds[y].c; y++) 16141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood list[count++] = xstrdup(cmds[y].c); 16151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood list[count] = NULL; 16171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_display(list, 0); 16181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 0; list[y] != NULL; y++) 16201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(list[y]); 16211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(list); 16221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return count; 16231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 16241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Prepare subset of commands that start with "cmd" */ 16261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmdlen = strlen(cmd); 16271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 0; cmds[y].c; y++) { 16281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!strncasecmp(cmd, cmds[y].c, cmdlen)) 16291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood list[count++] = xstrdup(cmds[y].c); 16301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 16311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood list[count] = NULL; 16321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (count == 0) 16341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return 0; 16351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Complete ambigious command */ 16371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = complete_ambiguous(cmd, list, count); 16381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (count > 1) 16391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_display(list, 0); 16401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (y = 0; list[y]; y++) 16421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(list[y]); 16431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(list); 16441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp != NULL) { 16461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmplen = strlen(tmp); 16471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmdlen = strlen(cmd); 16481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* If cmd may be extended then do so */ 16491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmplen > cmdlen) 16501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (el_insertstr(el, tmp + cmdlen) == -1) 16511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("el_insertstr failed."); 16521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood lf = el_line(el); 16531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Terminate argument cleanly */ 16541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (count == 1) { 16551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood y = 0; 16561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!terminated) 16571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argterm[y++] = quote; 16581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (lastarg || *(lf->cursor) != ' ') 16591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argterm[y++] = ' '; 16601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argterm[y] = '\0'; 16611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (y > 0 && el_insertstr(el, argterm) == -1) 16621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("el_insertstr failed."); 16631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 16641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 16651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 16661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return count; 16681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 16691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 16711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Determine whether a particular sftp command's arguments (if any) 16721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * represent local or remote files. 16731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 16741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 16751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcomplete_is_remote(char *cmd) { 16761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i; 16771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cmd == NULL) 16791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 16801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; cmds[i].c; i++) { 16821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c))) 16831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return cmds[i].t; 16841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 16851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 16871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 16881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Autocomplete a filename "file" */ 16901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int 16911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcomplete_match(EditLine *el, struct sftp_conn *conn, char *remote_path, 16921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *file, int remote, int lastarg, char quote, int terminated) 16931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 16941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood glob_t g; 16951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *tmp, *tmp2, ins[3]; 16961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int i, hadglob, pwdlen, len, tmplen, filelen; 16971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const LineInfo *lf; 16981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 16991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Glob from "file" location */ 17001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (file == NULL) 17011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = xstrdup("*"); 17021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 17031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xasprintf(&tmp, "%s*", file); 17041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&g, 0, sizeof(g)); 17061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (remote != LOCAL) { 17071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = make_absolute(tmp, remote_path); 17081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); 17091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else 17101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g); 17111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Determine length of pwd so we can trim completion display */ 17131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) { 17141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Terminate counting on first unescaped glob metacharacter */ 17151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp[tmplen] == '*' || tmp[tmplen] == '?') { 17161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp[tmplen] != '*' || tmp[tmplen + 1] != '\0') 17171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood hadglob = 1; 17181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 17191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp[tmplen] == '\\' && tmp[tmplen + 1] != '\0') 17211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmplen++; 17221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp[tmplen] == '/') 17231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pwdlen = tmplen + 1; /* track last seen '/' */ 17241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 17261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc == 0) 17281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 17291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc > 1) 17311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_display(g.gl_pathv, pwdlen); 17321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = NULL; 17341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Don't try to extend globs */ 17351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (file == NULL || hadglob) 17361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 17371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc); 17391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp = path_strip(tmp2, remote_path); 17401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp2); 17411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmp == NULL) 17431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 17441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmplen = strlen(tmp); 17461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filelen = strlen(file); 17471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (tmplen > filelen) { 17491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood tmp2 = tmp + filelen; 17501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = strlen(tmp2); 17511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* quote argument on way out */ 17521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < len; i++) { 17531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ins[0] = '\\'; 17541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ins[1] = tmp2[i]; 17551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ins[2] = '\0'; 17561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (tmp2[i]) { 17571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\'': 17581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '"': 17591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\\': 17601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '\t': 17611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '[': 17621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case ' ': 17631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (quote == '\0' || tmp2[i] == quote) { 17641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (el_insertstr(el, ins) == -1) 17651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("el_insertstr " 17661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "failed."); 17671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 17681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* FALLTHROUGH */ 17701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 17711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (el_insertstr(el, ins + 1) == -1) 17721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("el_insertstr failed."); 17731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 17741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood lf = el_line(el); 17791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (g.gl_matchc == 1) { 17801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood i = 0; 17811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!terminated) 17821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ins[i++] = quote; 17831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (*(lf->cursor - 1) != '/' && 17841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (lastarg || *(lf->cursor) != ' ')) 17851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ins[i++] = ' '; 17861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ins[i] = '\0'; 17871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (i > 0 && el_insertstr(el, ins) == -1) 17881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("el_insertstr failed."); 17891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 17901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(tmp); 17911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out: 17931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood globfree(&g); 17941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return g.gl_matchc; 17951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 17961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 17971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* tab-completion hook function, called via libedit */ 17981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic unsigned char 17991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcomplete(EditLine *el, int ch) 18001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 18011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char **argv, *line, quote; 18021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int argc, carg, cursor, len, terminated, ret = CC_ERROR; 18031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const LineInfo *lf; 18041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct complete_ctx *complete_ctx; 18051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood lf = el_line(el); 18071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0) 18081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: el_get failed", __func__); 18091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Figure out which argument the cursor points to */ 18111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cursor = lf->cursor - lf->buffer; 18121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood line = (char *)xmalloc(cursor + 1); 18131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(line, lf->buffer, cursor); 18141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood line[cursor] = '\0'; 18151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argv = makeargv(line, &carg, 1, "e, &terminated); 18161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(line); 18171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Get all the arguments on the line */ 18191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = lf->lastchar - lf->buffer; 18201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood line = (char *)xmalloc(len + 1); 18211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memcpy(line, lf->buffer, len); 18221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood line[len] = '\0'; 18231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood argv = makeargv(line, &argc, 1, NULL, NULL); 18241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Ensure cursor is at EOL or a argument boundary */ 18261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (line[cursor] != ' ' && line[cursor] != '\0' && 18271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood line[cursor] != '\n') { 18281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(line); 18291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 18301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 18311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (carg == 0) { 18331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Show all available commands */ 18341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_cmd_parse(el, NULL, argc == carg, '\0', 1); 18351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = CC_REDISPLAY; 18361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ') { 18371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Handle the command parsing */ 18381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (complete_cmd_parse(el, argv[0], argc == carg, 18391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood quote, terminated) != 0) 18401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = CC_REDISPLAY; 18411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (carg >= 1) { 18421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Handle file parsing */ 18431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int remote = complete_is_remote(argv[0]); 18441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *filematch = NULL; 18451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (carg > 1 && line[cursor-1] != ' ') 18471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood filematch = argv[carg - 1]; 18481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (remote != 0 && 18501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_match(el, complete_ctx->conn, 18511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *complete_ctx->remote_pathp, filematch, 18521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood remote, carg == argc, quote, terminated) != 0) 18531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = CC_REDISPLAY; 18541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 18551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(line); 18571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 18581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 18591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_LIBEDIT */ 18601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 18621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinteractive_loop(struct sftp_conn *conn, char *file1, char *file2) 18631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 18641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *remote_path; 18651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *dir = NULL; 18661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char cmd[2048]; 18671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int err, interactive; 18681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EditLine *el = NULL; 18691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_LIBEDIT 18701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood History *hl = NULL; 18711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood HistEvent hev; 18721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern char *__progname; 18731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct complete_ctx complete_ctx; 18741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!batchmode && isatty(STDIN_FILENO)) { 18761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL) 18771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Couldn't initialise editline"); 18781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((hl = history_init()) == NULL) 18791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Couldn't initialise editline history"); 18801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood history(hl, &hev, H_SETSIZE, 100); 18811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_HIST, history, hl); 18821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_PROMPT, prompt); 18841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_EDITOR, "emacs"); 18851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_TERMINAL, NULL); 18861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_SIGNAL, 1); 18871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_source(el, NULL); 18881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Tab Completion */ 18901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_ADDFN, "ftp-complete", 18911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "Context sensitive argument completion", complete); 18921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_ctx.conn = conn; 18931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood complete_ctx.remote_pathp = &remote_path; 18941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_CLIENTDATA, (void*)&complete_ctx); 18951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_set(el, EL_BIND, "^I", "ftp-complete", NULL); 18961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 18971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_LIBEDIT */ 18981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 18991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood remote_path = do_realpath(conn, "."); 19001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (remote_path == NULL) 19011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Need cwd"); 19021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (file1 != NULL) { 19041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dir = xstrdup(file1); 19051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood dir = make_absolute(dir, remote_path); 19061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (remote_is_dir(conn, dir) && file2 == NULL) { 19081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("Changing to: %s\n", dir); 19091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); 19101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (parse_dispatch_command(conn, cmd, 19111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &remote_path, 1) != 0) { 19121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(dir); 19131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(remote_path); 19141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(conn); 19151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (-1); 19161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 19181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (file2 == NULL) 19191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood snprintf(cmd, sizeof cmd, "get %s", dir); 19201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 19211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood snprintf(cmd, sizeof cmd, "get %s %s", dir, 19221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood file2); 19231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = parse_dispatch_command(conn, cmd, 19251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &remote_path, 1); 19261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(dir); 19271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(remote_path); 19281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(conn); 19291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (err); 19301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(dir); 19321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_SETVBUF) && !defined(BROKEN_SETVBUF) 19351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood setvbuf(stdout, NULL, _IOLBF, 0); 19361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood setvbuf(infile, NULL, _IOLBF, 0); 19371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else 19381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood setlinebuf(stdout); 19391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood setlinebuf(infile); 19401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 19411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood interactive = !batchmode && isatty(STDIN_FILENO); 19431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = 0; 19441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (;;) { 19451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *cp; 19461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGINT, SIG_IGN); 19481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (el == NULL) { 19501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (interactive) 19511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("sftp> "); 19521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (fgets(cmd, sizeof(cmd), infile) == NULL) { 19531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (interactive) 19541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 19551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 19561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!interactive) { /* Echo command */ 19581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("sftp> %s", cmd); 19591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strlen(cmd) > 0 && 19601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cmd[strlen(cmd) - 1] != '\n') 19611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 19621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 19641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_LIBEDIT 19651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *line; 19661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int count = 0; 19671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((line = el_gets(el, &count)) == NULL || 19691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood count <= 0) { 19701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood printf("\n"); 19711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 19721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood history(hl, &hev, H_ENTER, line); 19741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) { 19751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "Error: input line too long\n"); 19761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 19771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_LIBEDIT */ 19791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = strrchr(cmd, '\n'); 19821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (cp) 19831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *cp = '\0'; 19841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Handle user interrupts gracefully during commands */ 19861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood interrupted = 0; 19871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGINT, cmd_interrupt); 19881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = parse_dispatch_command(conn, cmd, &remote_path, 19901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood batchmode); 19911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (err != 0) 19921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 19931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 19941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(remote_path); 19951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(conn); 19961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 19971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_LIBEDIT 19981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (el != NULL) 19991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood el_end(el); 20001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_LIBEDIT */ 20011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* err == 1 signifies normal "quit" exit */ 20031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (err >= 0 ? 0 : -1); 20041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 20051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 20071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodconnect_to_server(char *path, char **args, int *in, int *out) 20081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 20091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int c_in, c_out; 20101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_PIPES 20121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int pin[2], pout[2]; 20131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((pipe(pin) == -1) || (pipe(pout) == -1)) 20151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("pipe: %s", strerror(errno)); 20161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *in = pin[0]; 20171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *out = pout[1]; 20181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c_in = pout[0]; 20191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c_out = pin[1]; 20201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* USE_PIPES */ 20211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int inout[2]; 20221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) 20241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("socketpair: %s", strerror(errno)); 20251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *in = *out = inout[0]; 20261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood c_in = c_out = inout[1]; 20271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_PIPES */ 20281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((sshpid = fork()) == -1) 20301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("fork: %s", strerror(errno)); 20311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else if (sshpid == 0) { 20321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((dup2(c_in, STDIN_FILENO) == -1) || 20331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (dup2(c_out, STDOUT_FILENO) == -1)) { 20341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "dup2: %s\n", strerror(errno)); 20351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood _exit(1); 20361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 20371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(*in); 20381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(*out); 20391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(c_in); 20401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(c_out); 20411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 20431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * The underlying ssh is in the same process group, so we must 20441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ignore SIGINT if we want to gracefully abort commands, 20451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * otherwise the signal will make it to the ssh process and 20461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * kill it too. Contrawise, since sftp sends SIGTERMs to the 20471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * underlying ssh, it must *not* ignore that signal. 20481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 20491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGINT, SIG_IGN); 20501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGTERM, SIG_DFL); 20511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood execvp(path, args); 20521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); 20531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood _exit(1); 20541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 20551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGTERM, killchild); 20571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGINT, killchild); 20581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signal(SIGHUP, killchild); 20591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(c_in); 20601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(c_out); 20611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 20621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 20641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodusage(void) 20651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 20661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern char *__progname; 20671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, 20691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" 20701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " [-D sftp_server_path] [-F ssh_config] " 20711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "[-i identity_file] [-l limit]\n" 20721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " [-o ssh_option] [-P port] [-R num_requests] " 20731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "[-S program]\n" 20741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " [-s subsystem | sftp_server] host\n" 20751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " %s [user@]host[:file ...]\n" 20761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " %s [user@]host[:dir[/]]\n" 20771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood " %s -b batchfile [user@]host\n", 20781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __progname, __progname, __progname, __progname); 20791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood exit(1); 20801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 20811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 20821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 20831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmain(int argc, char **argv) 20841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 20851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int in, out, ch, err; 20861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *host = NULL, *userhost, *cp, *file2 = NULL; 20871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int debug_level = 0, sshver = 2; 20881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *file1 = NULL, *sftp_server = NULL; 20891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; 20901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const char *errstr; 20911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood LogLevel ll = SYSLOG_LEVEL_INFO; 20921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood arglist args; 20931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern int optind; 20941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern char *optarg; 20951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct sftp_conn *conn; 20961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t copy_buffer_len = DEFAULT_COPY_BUFLEN; 20971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t num_requests = DEFAULT_NUM_REQUESTS; 20981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood long long limit_kbps = 0; 20991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 21001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 21011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sanitise_stdfd(); 21021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 21031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __progname = ssh_get_progname(argv[0]); 21041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(&args, '\0', sizeof(args)); 21051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood args.list = NULL; 21061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "%s", ssh_program); 21071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-oForwardX11 no"); 21081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-oForwardAgent no"); 21091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-oPermitLocalCommand no"); 21101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-oClearAllForwardings yes"); 21111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 21121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ll = SYSLOG_LEVEL_INFO; 21131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood infile = stdin; 21141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 21151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while ((ch = getopt(argc, argv, 21161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) { 21171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (ch) { 21181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Passed through to ssh(1) */ 21191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '4': 21201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '6': 21211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'C': 21221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-%c", ch); 21231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Passed through to ssh(1) with argument */ 21251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'F': 21261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'c': 21271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'i': 21281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'o': 21291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-%c", ch); 21301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "%s", optarg); 21311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'q': 21331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood showprogress = 0; 21341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-%c", ch); 21351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'P': 21371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-oPort %s", optarg); 21381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'v': 21401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (debug_level < 3) { 21411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-v"); 21421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ll = SYSLOG_LEVEL_DEBUG1 + debug_level; 21431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 21441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug_level++; 21451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '1': 21471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sshver = 1; 21481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sftp_server == NULL) 21491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sftp_server = _PATH_SFTP_SERVER; 21501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case '2': 21521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sshver = 2; 21531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'B': 21551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood copy_buffer_len = strtol(optarg, &cp, 10); 21561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (copy_buffer_len == 0 || *cp != '\0') 21571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Invalid buffer size \"%s\"", optarg); 21581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'b': 21601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (batchmode) 21611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Batch file already specified."); 21621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 21631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Allow "-" as stdin */ 21641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (strcmp(optarg, "-") != 0 && 21651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood (infile = fopen(optarg, "r")) == NULL) 21661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s (%s).", strerror(errno), optarg); 21671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood showprogress = 0; 21681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood batchmode = 1; 21691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-obatchmode yes"); 21701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'p': 21721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood global_pflag = 1; 21731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'D': 21751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sftp_direct = optarg; 21761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'l': 21781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, 21791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood &errstr); 21801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errstr != NULL) 21811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood usage(); 21821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood limit_kbps *= 1024; /* kbps */ 21831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'r': 21851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood global_rflag = 1; 21861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'R': 21881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood num_requests = strtol(optarg, &cp, 10); 21891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (num_requests == 0 || *cp != '\0') 21901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Invalid number of requests \"%s\"", 21911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood optarg); 21921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 's': 21941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sftp_server = optarg; 21951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 21961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'S': 21971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ssh_program = optarg; 21981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood replacearg(&args, 0, "%s", ssh_program); 21991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 22001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case 'h': 22011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 22021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood usage(); 22031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!isatty(STDERR_FILENO)) 22071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood showprogress = 0; 22081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); 22101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sftp_direct == NULL) { 22121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (optind == argc || argc > (optind + 2)) 22131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood usage(); 22141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood userhost = xstrdup(argv[optind]); 22161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood file2 = argv[optind+1]; 22171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((host = strrchr(userhost, '@')) == NULL) 22191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood host = userhost; 22201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else { 22211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *host++ = '\0'; 22221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!userhost[0]) { 22231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "Missing username\n"); 22241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood usage(); 22251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-l"); 22271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "%s", userhost); 22281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((cp = colon(host)) != NULL) { 22311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *cp++ = '\0'; 22321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood file1 = cp; 22331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood host = cleanhostname(host); 22361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!*host) { 22371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "Missing hostname\n"); 22381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood usage(); 22391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-oProtocol %d", sshver); 22421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* no subsystem if the server-spec contains a '/' */ 22441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) 22451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "-s"); 22461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "--"); 22481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "%s", host); 22491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "%s", (sftp_server != NULL ? 22501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood sftp_server : "sftp")); 22511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connect_to_server(ssh_program, args.list, &in, &out); 22531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 22541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood args.list = NULL; 22551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood addargs(&args, "sftp-server"); 22561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood connect_to_server(sftp_direct, args.list, &in, &out); 22581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood freeargs(&args); 22601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps); 22621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (conn == NULL) 22631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Couldn't initialise connection to server"); 22641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!batchmode) { 22661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (sftp_direct == NULL) 22671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "Connected to %s.\n", host); 22681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 22691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fprintf(stderr, "Attached to %s.\n", sftp_direct); 22701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 22711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood err = interactive_loop(conn, file1, file2); 22731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if !defined(USE_PIPES) 22751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood shutdown(in, SHUT_RDWR); 22761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood shutdown(out, SHUT_RDWR); 22771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 22781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(in); 22801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood close(out); 22811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (batchmode) 22821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fclose(infile); 22831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood while (waitpid(sshpid, NULL, 0) == -1) 22851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno != EINTR) 22861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("Couldn't wait for ssh process: %s", 22871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood strerror(errno)); 22881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 22891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood exit(err == 0 ? 0 : 1); 22901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2291