-/* $OpenBSD: sftp.c,v 1.116 2010/01/04 02:03:57 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.123 2010/01/27 19:21:39 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
#define WHITESPACE " \t\r\n"
/* ls flags */
-#define LS_LONG_VIEW 0x01 /* Full view ala ls -l */
-#define LS_SHORT_VIEW 0x02 /* Single row view ala ls -1 */
-#define LS_NUMERIC_VIEW 0x04 /* Long view with numeric uid/gid */
-#define LS_NAME_SORT 0x08 /* Sort by name (default) */
-#define LS_TIME_SORT 0x10 /* Sort by mtime */
-#define LS_SIZE_SORT 0x20 /* Sort by file size */
-#define LS_REVERSE_SORT 0x40 /* Reverse sort order */
-#define LS_SHOW_ALL 0x80 /* Don't skip filenames starting with '.' */
-
-#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW)
+#define LS_LONG_VIEW 0x0001 /* Full view ala ls -l */
+#define LS_SHORT_VIEW 0x0002 /* Single row view ala ls -1 */
+#define LS_NUMERIC_VIEW 0x0004 /* Long view with numeric uid/gid */
+#define LS_NAME_SORT 0x0008 /* Sort by name (default) */
+#define LS_TIME_SORT 0x0010 /* Sort by mtime */
+#define LS_SIZE_SORT 0x0020 /* Sort by file size */
+#define LS_REVERSE_SORT 0x0040 /* Reverse sort order */
+#define LS_SHOW_ALL 0x0080 /* Don't skip filenames starting with '.' */
+#define LS_SI_UNITS 0x0100 /* Display sizes as K, M, G, etc. */
+
+#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW|LS_SI_UNITS)
#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
/* Commands for interactive mode */
"df [-hi] [path] Display statistics for current directory or\n"
" filesystem containing 'path'\n"
"exit Quit sftp\n"
- "get [-Pr] remote-path [local-path] Download file\n"
+ "get [-Ppr] remote [local] Download file\n"
"help Display this help text\n"
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
"lmkdir path Create local directory\n"
"ln oldpath newpath Symlink remote file\n"
"lpwd Print local working directory\n"
- "ls [-1aflnrSt] [path] Display remote directory listing\n"
+ "ls [-1afhlnrSt] [path] Display remote directory listing\n"
"lumask umask Set local umask to 'umask'\n"
"mkdir path Create remote directory\n"
"progress Toggle display of progress meter\n"
- "put [-Pr] local-path [remote-path] Upload file\n"
+ "put [-Ppr] local [remote] Upload file\n"
"pwd Display remote working directory\n"
"quit Quit sftp\n"
"rename oldpath newpath Rename remote file\n"
opterr = 0;
*lflag = LS_NAME_SORT;
- while ((ch = getopt(argc, argv, "1Saflnrt")) != -1) {
+ while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) {
switch (ch) {
case '1':
*lflag &= ~VIEW_FLAGS;
case 'f':
*lflag &= ~SORT_FLAGS;
break;
+ case 'h':
+ *lflag |= LS_SI_UNITS;
+ break;
case 'l':
- *lflag &= ~VIEW_FLAGS;
+ *lflag &= ~LS_SHORT_VIEW;
*lflag |= LS_LONG_VIEW;
break;
case 'n':
- *lflag &= ~VIEW_FLAGS;
+ *lflag &= ~LS_SHORT_VIEW;
*lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
break;
case 'r':
xfree(tmp);
if (lflag & LS_LONG_VIEW) {
- if (lflag & LS_NUMERIC_VIEW) {
+ if (lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) {
char *lname;
struct stat sb;
memset(&sb, 0, sizeof(sb));
attrib_to_stat(&d[n]->a, &sb);
- lname = ls_file(fname, &sb, 1);
+ lname = ls_file(fname, &sb, 1,
+ (lflag & LS_SI_UNITS));
printf("%s\n", lname);
xfree(lname);
} else
a = do_lstat(conn, g.gl_pathv[i], 1);
if (a != NULL)
attrib_to_stat(a, &sb);
- lname = ls_file(fname, &sb, 1);
+ lname = ls_file(fname, &sb, 1, (lflag & LS_SI_UNITS));
printf("%s\n", lname);
xfree(lname);
} else {
/* Skip leading whitespace */
cp = cp + strspn(cp, WHITESPACE);
- /* Ignore blank lines and lines which begin with comment '#' char */
- if (*cp == '\0' || *cp == '#')
- return (0);
-
/* Check for leading '-' (disable error processing) */
*iflag = 0;
if (*cp == '-') {
*iflag = 1;
cp++;
+ cp = cp + strspn(cp, WHITESPACE);
}
+ /* Ignore blank lines and lines which begin with comment '#' char */
+ if (*cp == '\0' || *cp == '#')
+ return (0);
+
if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL)
return -1;
if (matchlen > strlen(word)) {
char *tmp = xstrdup(list[0]);
- tmp[matchlen] = NULL;
+ tmp[matchlen] = '\0';
return tmp;
}
}
return count;
}
-#endif
/*
* Determine whether a particular sftp command's arguments (if any)
return -1;
}
-#ifdef USE_LIBEDIT
/* Autocomplete a filename "file" */
static int
complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
}
lf = el_line(el);
- /*
- * XXX should we really extend here? the user may not be done if
- * the filename is a directory.
- */
if (g.gl_matchc == 1) {
i = 0;
if (!terminated)
ins[i++] = quote;
- if (lastarg || *(lf->cursor) != ' ')
+ if (*(lf->cursor - 1) != '/' &&
+ (lastarg || *(lf->cursor) != ' '))
ins[i++] = ' ';
ins[i] = '\0';
if (i > 0 && el_insertstr(el, ins) == -1)
* The underlying ssh is in the same process group, so we must
* ignore SIGINT if we want to gracefully abort commands,
* otherwise the signal will make it to the ssh process and
- * kill it too
+ * kill it too. Contrawise, since sftp sends SIGTERMs to the
+ * underlying ssh, it must *not* ignore that signal.
*/
signal(SIGINT, SIG_IGN);
+ signal(SIGTERM, SIG_DFL);
execvp(path, args);
fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
_exit(1);
main(int argc, char **argv)
{
int in, out, ch, err;
- char *host, *userhost, *cp, *file2 = NULL;
+ char *host = NULL, *userhost, *cp, *file2 = NULL;
int debug_level = 0, sshver = 2;
char *file1 = NULL, *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246hqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) {
+ "1246hpqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
case '4':