summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-01-10 21:40:00 +1100
committerDamien Miller <djm@mindrot.org>2003-01-10 21:40:00 +1100
commit956f3fb28b93420e87a51d1611029accebb2e43b (patch)
treed1f304e1bf833cef147bec2335b75187a93f9e98
parenta8ed44b79e6dd78d7871b0fb8149951b54662ef5 (diff)
- (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
-rw-r--r--ChangeLog9
-rw-r--r--sftp-int.c132
-rw-r--r--sftp-int.h4
-rw-r--r--sftp.111
-rw-r--r--sftp.c8
5 files changed, 103 insertions, 61 deletions
diff --git a/ChangeLog b/ChangeLog
index 492eadab..3c38dbb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
20030110
- (djm) Enable new setproctitle emulation for Linux, AIX and HP/UX. More
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
- (djm) Sync openbsd-compat/ with OpenBSD -current
@@ -969,4 +976,4 @@
save auth method before monitor_reset_key_state(); bugzilla bug #284;
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 $
diff --git a/sftp-int.c b/sftp-int.c
index 04b67c96..f2c8fa6d 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -25,7 +25,7 @@
/* XXX: recursive operations */
#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 "xmalloc.h"
@@ -666,7 +666,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
}
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)
{
const char *cmd, *cp = *cpp;
@@ -678,10 +678,17 @@ parse_args(const char **cpp, int *pflag, int *lflag,
/* Skip leading whitespace */
cp = cp + strspn(cp, WHITESPACE);
- /* Ignore blank lines */
- if (!*cp)
- return(-1);
+ /* 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++;
+ }
+
/* Figure out which command we have */
for (i = 0; cmds[i].c; i++) {
int cmdlen = strlen(cmds[i].c);
@@ -703,7 +710,7 @@ parse_args(const char **cpp, int *pflag, int *lflag,
cmdnum = I_SHELL;
} else if (cmdnum == -1) {
error("Invalid command.");
- return(-1);
+ return (-1);
}
/* Get arguments and parse flags */
@@ -813,10 +820,11 @@ parse_args(const char **cpp, int *pflag, int *lflag,
}
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;
- int pflag, lflag, cmdnum, i;
+ int pflag, lflag, iflag, cmdnum, i;
unsigned long n_arg;
Attrib a, *aa;
char path_buf[MAXPATHLEN];
@@ -824,14 +832,22 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg,
+ cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg,
&path1, &path2);
+ if (iflag != 0)
+ err_abort = 0;
+
memset(&g, 0, sizeof(g));
/* Perform command */
switch (cmdnum) {
+ case 0:
+ /* Blank line */
+ break;
case -1:
+ /* Unrecognized command */
+ err = -1;
break;
case I_GET:
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);
for (i = 0; g.gl_pathv[i]; i++) {
printf("Removing %s\n", g.gl_pathv[i]);
- if (do_rm(conn, g.gl_pathv[i]) == -1)
- err = -1;
+ err = do_rm(conn, g.gl_pathv[i]);
+ if (err != 0 && err_abort)
+ break;
}
break;
case I_MKDIR:
@@ -907,8 +924,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
tmp = *pwd;
path1 = make_absolute(path1, *pwd);
-
- do_globbed_ls(conn, path1, tmp, lflag);
+ err = do_globbed_ls(conn, path1, tmp, lflag);
break;
case I_LCHDIR:
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);
for (i = 0; g.gl_pathv[i]; 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;
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:
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 = do_stat(conn, g.gl_pathv[i], 0))) {
+ if (err != 0 && err_abort)
+ break;
+ else
+ continue;
+ }
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of "
"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->gid = n_arg;
- do_setstat(conn, g.gl_pathv[i], aa);
+ if (cmdnum == I_CHOWN) {
+ 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;
case I_PWD:
printf("Remote working directory: %s\n", *pwd);
break;
case I_LPWD:
- if (!getcwd(path_buf, sizeof(path_buf)))
- error("Couldn't get local cwd: %s",
- strerror(errno));
- else
- printf("Local working directory: %s\n",
- path_buf);
+ if (!getcwd(path_buf, sizeof(path_buf))) {
+ error("Couldn't get local cwd: %s", strerror(errno));
+ err = -1;
+ break;
+ }
+ printf("Local working directory: %s\n", path_buf);
break;
case I_QUIT:
- return(-1);
+ /* Processed below */
+ break;
case I_HELP:
help();
break;
@@ -1009,20 +1026,23 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
if (path2)
xfree(path2);
- /* If an error occurs in batch mode we should abort. */
- if (infile != stdin && err > 0)
- return -1;
+ /* If an unignored error occurs in batch mode we should abort. */
+ if (err_abort && err != 0)
+ 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)
{
char *pwd;
char *dir = NULL;
char cmd[2048];
struct sftp_conn *conn;
+ int err;
conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
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) {
printf("Changing to: %s\n", 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 {
if (file2 == NULL)
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,
file2);
- parse_dispatch_command(conn, cmd, &pwd);
+ err = parse_dispatch_command(conn, cmd, &pwd, 1);
xfree(dir);
- return;
+ return (err);
}
xfree(dir);
}
+
#if HAVE_SETVBUF
setvbuf(stdout, 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);
#endif
+ err = 0;
for (;;) {
char *cp;
@@ -1077,8 +1100,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
if (cp)
*cp = '\0';
- if (parse_dispatch_command(conn, cmd, &pwd))
+ err = parse_dispatch_command(conn, cmd, &pwd, infile != stdin);
+ if (err != 0)
break;
}
xfree(pwd);
+
+ /* err == 1 signifies normal "quit" exit */
+ return (err >= 0 ? 0 : -1);
}
+
diff --git a/sftp-int.h b/sftp-int.h
index 97687581..8a04a03f 100644
--- a/sftp-int.h
+++ b/sftp-int.h
@@ -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.
@@ -24,4 +24,4 @@
* 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 *);
diff --git a/sftp.1 b/sftp.1
index 60d46b1c..67086bda 100644
--- a/sftp.1
+++ b/sftp.1
@@ -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.
.\"
@@ -77,9 +77,16 @@ non-interactive authentication.
will abort if any of the following
commands fail:
.Ic get , put , rename , ln ,
-.Ic rm , mkdir , chdir , lchdir
+.Ic rm , mkdir , chdir , ls ,
+.Ic lchdir , chmod , chown , chgrp , lpwd
and
.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
Can be used to pass options to
.Nm ssh
diff --git a/sftp.c b/sftp.c
index c173e58c..d62e9e42 100644
--- a/sftp.c
+++ b/sftp.c
@@ -24,7 +24,7 @@
#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') */
@@ -108,7 +108,7 @@ usage(void)
int
main(int argc, char **argv)
{
- int in, out, ch;
+ int in, out, ch, err;
pid_t sshpid;
char *host, *userhost, *cp, *file2;
int debug_level = 0, sshver = 2;
@@ -237,7 +237,7 @@ main(int argc, char **argv)
&sshpid);
}
- interactive_loop(in, out, file1, file2);
+ err = interactive_loop(in, out, file1, file2);
#if !defined(USE_PIPES)
shutdown(in, SHUT_RDWR);
@@ -254,5 +254,5 @@ main(int argc, char **argv)
fatal("Couldn't wait for ssh process: %s",
strerror(errno));
- exit(0);
+ exit(err == 0 ? 0 : 1);
}