- (djm) OpenBSD CVS Sync

- djm@cvs.openbsd.org 2003/01/08 23:53:26
     [sftp.1 sftp.c sftp-int.c sftp-int.h]
     Cleanup error handling for batchmode
     Allow blank lines and comments in input
     Ability to suppress abort on error in batchmode ("-put blah")
     Fixes mindrot bug #452; markus@ ok
This commit is contained in:
Damien Miller 2003-01-10 21:40:00 +11:00
parent a8ed44b79e
commit 956f3fb28b
5 changed files with 103 additions and 61 deletions

View File

@ -1,6 +1,13 @@
20030110 20030110
- (djm) Enable new setproctitle emulation for Linux, AIX and HP/UX. More - (djm) Enable new setproctitle emulation for Linux, AIX and HP/UX. More
systems may be added later. systems may be added later.
- (djm) OpenBSD CVS Sync
- djm@cvs.openbsd.org 2003/01/08 23:53:26
[sftp.1 sftp.c sftp-int.c sftp-int.h]
Cleanup error handling for batchmode
Allow blank lines and comments in input
Ability to suppress abort on error in batchmode ("-put blah")
Fixes mindrot bug #452; markus@ ok
20030108 20030108
- (djm) Sync openbsd-compat/ with OpenBSD -current - (djm) Sync openbsd-compat/ with OpenBSD -current
@ -969,4 +976,4 @@
save auth method before monitor_reset_key_state(); bugzilla bug #284; save auth method before monitor_reset_key_state(); bugzilla bug #284;
ok provos@ ok provos@
$Id: ChangeLog,v 1.2558 2003/01/09 22:53:12 djm Exp $ $Id: ChangeLog,v 1.2559 2003/01/10 10:40:00 djm Exp $

View File

@ -25,7 +25,7 @@
/* XXX: recursive operations */ /* XXX: recursive operations */
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sftp-int.c,v 1.50 2002/11/21 23:03:51 deraadt Exp $"); RCSID("$OpenBSD: sftp-int.c,v 1.51 2003/01/08 23:53:26 djm Exp $");
#include "buffer.h" #include "buffer.h"
#include "xmalloc.h" #include "xmalloc.h"
@ -666,7 +666,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
} }
static int static int
parse_args(const char **cpp, int *pflag, int *lflag, parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
unsigned long *n_arg, char **path1, char **path2) unsigned long *n_arg, char **path1, char **path2)
{ {
const char *cmd, *cp = *cpp; const char *cmd, *cp = *cpp;
@ -678,10 +678,17 @@ parse_args(const char **cpp, int *pflag, int *lflag,
/* Skip leading whitespace */ /* Skip leading whitespace */
cp = cp + strspn(cp, WHITESPACE); cp = cp + strspn(cp, WHITESPACE);
/* Ignore blank lines */ /* Ignore blank lines and lines which begin with comment '#' char */
if (!*cp) if (*cp == '\0' || *cp == '#')
return(-1); return (0);
/* Check for leading '-' (disable error processing) */
*iflag = 0;
if (*cp == '-') {
*iflag = 1;
cp++;
}
/* Figure out which command we have */ /* Figure out which command we have */
for (i = 0; cmds[i].c; i++) { for (i = 0; cmds[i].c; i++) {
int cmdlen = strlen(cmds[i].c); int cmdlen = strlen(cmds[i].c);
@ -703,7 +710,7 @@ parse_args(const char **cpp, int *pflag, int *lflag,
cmdnum = I_SHELL; cmdnum = I_SHELL;
} else if (cmdnum == -1) { } else if (cmdnum == -1) {
error("Invalid command."); error("Invalid command.");
return(-1); return (-1);
} }
/* Get arguments and parse flags */ /* Get arguments and parse flags */
@ -813,10 +820,11 @@ parse_args(const char **cpp, int *pflag, int *lflag,
} }
static int static int
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd) parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort)
{ {
char *path1, *path2, *tmp; char *path1, *path2, *tmp;
int pflag, lflag, cmdnum, i; int pflag, lflag, iflag, cmdnum, i;
unsigned long n_arg; unsigned long n_arg;
Attrib a, *aa; Attrib a, *aa;
char path_buf[MAXPATHLEN]; char path_buf[MAXPATHLEN];
@ -824,14 +832,22 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
glob_t g; glob_t g;
path1 = path2 = NULL; path1 = path2 = NULL;
cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg, cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg,
&path1, &path2); &path1, &path2);
if (iflag != 0)
err_abort = 0;
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
/* Perform command */ /* Perform command */
switch (cmdnum) { switch (cmdnum) {
case 0:
/* Blank line */
break;
case -1: case -1:
/* Unrecognized command */
err = -1;
break; break;
case I_GET: case I_GET:
err = process_get(conn, path1, path2, *pwd, pflag); err = process_get(conn, path1, path2, *pwd, pflag);
@ -853,8 +869,9 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i]; i++) { for (i = 0; g.gl_pathv[i]; i++) {
printf("Removing %s\n", g.gl_pathv[i]); printf("Removing %s\n", g.gl_pathv[i]);
if (do_rm(conn, g.gl_pathv[i]) == -1) err = do_rm(conn, g.gl_pathv[i]);
err = -1; if (err != 0 && err_abort)
break;
} }
break; break;
case I_MKDIR: case I_MKDIR:
@ -907,8 +924,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
tmp = *pwd; tmp = *pwd;
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
err = do_globbed_ls(conn, path1, tmp, lflag);
do_globbed_ls(conn, path1, tmp, lflag);
break; break;
case I_LCHDIR: case I_LCHDIR:
if (chdir(path1) == -1) { if (chdir(path1) == -1) {
@ -942,56 +958,57 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i]; i++) { for (i = 0; g.gl_pathv[i]; i++) {
printf("Changing mode on %s\n", g.gl_pathv[i]); printf("Changing mode on %s\n", g.gl_pathv[i]);
do_setstat(conn, g.gl_pathv[i], &a); err = do_setstat(conn, g.gl_pathv[i], &a);
if (err != 0 && err_abort)
break;
} }
break; break;
case I_CHOWN: case I_CHOWN:
path1 = make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i]; i++) {
if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
continue;
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of "
"remote file \"%s\"", g.gl_pathv[i]);
continue;
}
printf("Changing owner on %s\n", g.gl_pathv[i]);
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->uid = n_arg;
do_setstat(conn, g.gl_pathv[i], aa);
}
break;
case I_CHGRP: case I_CHGRP:
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g); remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i]; i++) { for (i = 0; g.gl_pathv[i]; i++) {
if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
continue; if (err != 0 && err_abort)
break;
else
continue;
}
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of " error("Can't get current ownership of "
"remote file \"%s\"", g.gl_pathv[i]); "remote file \"%s\"", g.gl_pathv[i]);
continue; if (err != 0 && err_abort)
break;
else
continue;
} }
printf("Changing group on %s\n", g.gl_pathv[i]);
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
aa->gid = n_arg; if (cmdnum == I_CHOWN) {
do_setstat(conn, g.gl_pathv[i], aa); printf("Changing owner on %s\n", g.gl_pathv[i]);
aa->uid = n_arg;
} else {
printf("Changing group on %s\n", g.gl_pathv[i]);
aa->gid = n_arg;
}
err = do_setstat(conn, g.gl_pathv[i], aa);
if (err != 0 && err_abort)
break;
} }
break; break;
case I_PWD: case I_PWD:
printf("Remote working directory: %s\n", *pwd); printf("Remote working directory: %s\n", *pwd);
break; break;
case I_LPWD: case I_LPWD:
if (!getcwd(path_buf, sizeof(path_buf))) if (!getcwd(path_buf, sizeof(path_buf))) {
error("Couldn't get local cwd: %s", error("Couldn't get local cwd: %s", strerror(errno));
strerror(errno)); err = -1;
else break;
printf("Local working directory: %s\n", }
path_buf); printf("Local working directory: %s\n", path_buf);
break; break;
case I_QUIT: case I_QUIT:
return(-1); /* Processed below */
break;
case I_HELP: case I_HELP:
help(); help();
break; break;
@ -1009,20 +1026,23 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
if (path2) if (path2)
xfree(path2); xfree(path2);
/* If an error occurs in batch mode we should abort. */ /* If an unignored error occurs in batch mode we should abort. */
if (infile != stdin && err > 0) if (err_abort && err != 0)
return -1; return (-1);
else if (cmdnum == I_QUIT)
return (1);
return(0); return (0);
} }
void int
interactive_loop(int fd_in, int fd_out, char *file1, char *file2) interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
{ {
char *pwd; char *pwd;
char *dir = NULL; char *dir = NULL;
char cmd[2048]; char cmd[2048];
struct sftp_conn *conn; struct sftp_conn *conn;
int err;
conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
if (conn == NULL) if (conn == NULL)
@ -1039,7 +1059,8 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
if (remote_is_dir(conn, dir) && file2 == NULL) { if (remote_is_dir(conn, dir) && file2 == NULL) {
printf("Changing to: %s\n", dir); printf("Changing to: %s\n", dir);
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
parse_dispatch_command(conn, cmd, &pwd); if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0)
return (-1);
} else { } else {
if (file2 == NULL) if (file2 == NULL)
snprintf(cmd, sizeof cmd, "get %s", dir); snprintf(cmd, sizeof cmd, "get %s", dir);
@ -1047,12 +1068,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
snprintf(cmd, sizeof cmd, "get %s %s", dir, snprintf(cmd, sizeof cmd, "get %s %s", dir,
file2); file2);
parse_dispatch_command(conn, cmd, &pwd); err = parse_dispatch_command(conn, cmd, &pwd, 1);
xfree(dir); xfree(dir);
return; return (err);
} }
xfree(dir); xfree(dir);
} }
#if HAVE_SETVBUF #if HAVE_SETVBUF
setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0);
@ -1061,6 +1083,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
setlinebuf(infile); setlinebuf(infile);
#endif #endif
err = 0;
for (;;) { for (;;) {
char *cp; char *cp;
@ -1077,8 +1100,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
if (cp) if (cp)
*cp = '\0'; *cp = '\0';
if (parse_dispatch_command(conn, cmd, &pwd)) err = parse_dispatch_command(conn, cmd, &pwd, infile != stdin);
if (err != 0)
break; break;
} }
xfree(pwd); xfree(pwd);
/* err == 1 signifies normal "quit" exit */
return (err >= 0 ? 0 : -1);
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-int.h,v 1.5 2002/02/13 00:59:23 djm Exp $ */ /* $OpenBSD: sftp-int.h,v 1.6 2003/01/08 23:53:26 djm Exp $ */
/* /*
* Copyright (c) 2001,2002 Damien Miller. All rights reserved. * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
@ -24,4 +24,4 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
void interactive_loop(int, int, char *, char *); int interactive_loop(int, int, char *, char *);

11
sftp.1
View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.38 2003/01/07 23:42:54 fgsch Exp $ .\" $OpenBSD: sftp.1,v 1.39 2003/01/08 23:53:26 djm Exp $
.\" .\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\" .\"
@ -77,9 +77,16 @@ non-interactive authentication.
will abort if any of the following will abort if any of the following
commands fail: commands fail:
.Ic get , put , rename , ln , .Ic get , put , rename , ln ,
.Ic rm , mkdir , chdir , lchdir .Ic rm , mkdir , chdir , ls ,
.Ic lchdir , chmod , chown , chgrp , lpwd
and and
.Ic lmkdir . .Ic lmkdir .
Termination on error can be suppressed on a command by command basis by
prefixing the command with a
.Ic '-'
character (For example,
.Ic -rm /tmp/blah*
).
.It Fl o Ar ssh_option .It Fl o Ar ssh_option
Can be used to pass options to Can be used to pass options to
.Nm ssh .Nm ssh

8
sftp.c
View File

@ -24,7 +24,7 @@
#include "includes.h" #include "includes.h"
RCSID("$OpenBSD: sftp.c,v 1.32 2002/11/27 17:53:35 markus Exp $"); RCSID("$OpenBSD: sftp.c,v 1.33 2003/01/08 23:53:26 djm Exp $");
/* XXX: short-form remote directory listings (like 'ls -C') */ /* XXX: short-form remote directory listings (like 'ls -C') */
@ -108,7 +108,7 @@ usage(void)
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int in, out, ch; int in, out, ch, err;
pid_t sshpid; pid_t sshpid;
char *host, *userhost, *cp, *file2; char *host, *userhost, *cp, *file2;
int debug_level = 0, sshver = 2; int debug_level = 0, sshver = 2;
@ -237,7 +237,7 @@ main(int argc, char **argv)
&sshpid); &sshpid);
} }
interactive_loop(in, out, file1, file2); err = interactive_loop(in, out, file1, file2);
#if !defined(USE_PIPES) #if !defined(USE_PIPES)
shutdown(in, SHUT_RDWR); shutdown(in, SHUT_RDWR);
@ -254,5 +254,5 @@ main(int argc, char **argv)
fatal("Couldn't wait for ssh process: %s", fatal("Couldn't wait for ssh process: %s",
strerror(errno)); strerror(errno));
exit(0); exit(err == 0 ? 0 : 1);
} }