From b99a05c240d58e4923ce45db6fa8cb82833ba3c9 Mon Sep 17 00:00:00 2001 From: Theo de Raadt Date: Tue, 6 Mar 2001 06:11:45 +0000 Subject: sftp -b batchfile; mouring@etoh.eviladmin.org --- usr.bin/ssh/sftp-int.c | 46 +++++++++++++++++++++++++++++++++------------- usr.bin/ssh/sftp.1 | 14 +++++++++++++- usr.bin/ssh/sftp.c | 18 +++++++++++++++--- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/usr.bin/ssh/sftp-int.c b/usr.bin/ssh/sftp-int.c index 53136be0754..7aa7abdb942 100644 --- a/usr.bin/ssh/sftp-int.c +++ b/usr.bin/ssh/sftp-int.c @@ -28,7 +28,7 @@ /* XXX: recursive operations */ #include "includes.h" -RCSID("$OpenBSD: sftp-int.c,v 1.24 2001/03/04 17:42:28 millert Exp $"); +RCSID("$OpenBSD: sftp-int.c,v 1.25 2001/03/06 06:11:44 deraadt Exp $"); #include "buffer.h" #include "xmalloc.h" @@ -40,6 +40,8 @@ RCSID("$OpenBSD: sftp-int.c,v 1.24 2001/03/04 17:42:28 millert Exp $"); #include "sftp-client.h" #include "sftp-int.h" +extern FILE* infile; + /* Seperators for interactive commands */ #define WHITESPACE " \t\r\n" @@ -444,6 +446,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) unsigned long n_arg; Attrib a, *aa; char path_buf[MAXPATHLEN]; + int err = 0; path1 = path2 = NULL; cmdnum = parse_args(&cmd, &pflag, &n_arg, &path1, &path2); @@ -454,49 +457,54 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) break; case I_GET: path1 = make_absolute(path1, *pwd); - do_download(in, out, path1, path2, pflag); + err = do_download(in, out, path1, path2, pflag); break; case I_PUT: path2 = make_absolute(path2, *pwd); - do_upload(in, out, path1, path2, pflag); + err = do_upload(in, out, path1, path2, pflag); break; case I_RENAME: path1 = make_absolute(path1, *pwd); path2 = make_absolute(path2, *pwd); - do_rename(in, out, path1, path2); + err = do_rename(in, out, path1, path2); break; case I_RM: path1 = make_absolute(path1, *pwd); - do_rm(in, out, path1); + err = do_rm(in, out, path1); break; case I_MKDIR: path1 = make_absolute(path1, *pwd); attrib_clear(&a); a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = 0777; - do_mkdir(in, out, path1, &a); + err = do_mkdir(in, out, path1, &a); break; case I_RMDIR: path1 = make_absolute(path1, *pwd); - do_rmdir(in, out, path1); + err = do_rmdir(in, out, path1); break; case I_CHDIR: path1 = make_absolute(path1, *pwd); - if ((tmp = do_realpath(in, out, path1)) == NULL) + if ((tmp = do_realpath(in, out, path1)) == NULL) { + err = 1; break; + } if ((aa = do_stat(in, out, tmp)) == NULL) { xfree(tmp); + err = 1; break; } if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) { error("Can't change directory: Can't check target"); xfree(tmp); + err = 1; break; } if (!S_ISDIR(aa->perm)) { error("Can't change directory: \"%s\" is not " "a directory", tmp); xfree(tmp); + err = 1; break; } xfree(*pwd); @@ -522,14 +530,18 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) do_ls(in, out, path1); break; case I_LCHDIR: - if (chdir(path1) == -1) + if (chdir(path1) == -1) { error("Couldn't change local directory to " "\"%s\": %s", path1, strerror(errno)); + err = 1; + } break; case I_LMKDIR: - if (mkdir(path1, 0777) == -1) + if (mkdir(path1, 0777) == -1) { error("Couldn't create local directory " "\"%s\": %s", path1, strerror(errno)); + err = 1; + } break; case I_LLS: local_do_ls(cmd); @@ -598,6 +610,11 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) xfree(path1); if (path2) xfree(path2); + + /* If an error occurs in batch mode we should abort. */ + if (infile != stdin && err > 0) + return -1; + return(0); } @@ -612,7 +629,7 @@ interactive_loop(int fd_in, int fd_out) fatal("Need cwd"); setvbuf(stdout, NULL, _IOLBF, 0); - setvbuf(stdin, NULL, _IOLBF, 0); + setvbuf(infile, NULL, _IOLBF, 0); for(;;) { char *cp; @@ -620,13 +637,16 @@ interactive_loop(int fd_in, int fd_out) printf("sftp> "); /* XXX: use libedit */ - if (fgets(cmd, sizeof(cmd), stdin) == NULL) { + if (fgets(cmd, sizeof(cmd), infile) == NULL) { printf("\n"); break; - } + } else if (infile != stdin) /* Bluff typing */ + printf("%s", cmd); + cp = strrchr(cmd, '\n'); if (cp) *cp = '\0'; + if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd)) break; } diff --git a/usr.bin/ssh/sftp.1 b/usr.bin/ssh/sftp.1 index 22915133b16..e1c6960f898 100644 --- a/usr.bin/ssh/sftp.1 +++ b/usr.bin/ssh/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.9 2001/03/02 18:54:31 deraadt Exp $ +.\" $OpenBSD: sftp.1,v 1.10 2001/03/06 06:11:44 deraadt Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -31,6 +31,7 @@ .Sh SYNOPSIS .Nm sftp .Op Fl vC +.Op Fl b Ar batchfile .Op Fl o Ar ssh_option .Op Ar hostname | user@hostname .Sh DESCRIPTION @@ -55,6 +56,17 @@ Raise logging level. This option is also passed to ssh. Enables compression (via ssh's .Fl C flag) +.It Fl b Ar batchfile +Batch mode reads a series of commands from an input +.Fn batchfile +instead of +.Fn stdin . +Since it lacks user interaction it should be used in conjuction with a +non-interactive authentication. Sftp will abort if any of the following +commands fail: +.Pa get, put, rename, rm, mkdir, chdir, lchdir +and +.Pa lmkdir. .It Fl o Ar ssh_option Specify an option to be directly passed to .Xr ssh 1 . diff --git a/usr.bin/ssh/sftp.c b/usr.bin/ssh/sftp.c index a997db083e0..6d1e556fbd9 100644 --- a/usr.bin/ssh/sftp.c +++ b/usr.bin/ssh/sftp.c @@ -24,7 +24,7 @@ #include "includes.h" -RCSID("$OpenBSD: sftp.c,v 1.9 2001/03/03 23:52:22 markus Exp $"); +RCSID("$OpenBSD: sftp.c,v 1.10 2001/03/06 06:11:44 deraadt Exp $"); /* XXX: commandline mode */ /* XXX: copy between two remote hosts (commandline) */ @@ -43,6 +43,7 @@ RCSID("$OpenBSD: sftp.c,v 1.9 2001/03/03 23:52:22 markus Exp $"); int use_ssh1 = 0; char *ssh_program = _PATH_SSH_PROGRAM; char *sftp_server = NULL; +FILE* infile; void connect_to_server(char **args, int *in, int *out, pid_t *sshpid) @@ -140,7 +141,7 @@ make_ssh_args(char *add_arg) void usage(void) { - fprintf(stderr, "usage: sftp [-1vC] [-osshopt=value] [user@]host\n"); + fprintf(stderr, "usage: sftp [-1vC] [-b batchfile] [-osshopt=value] [user@]host\n"); exit(1); } @@ -154,9 +155,10 @@ main(int argc, char **argv) extern int optind; extern char *optarg; + infile = stdin; /* Read from STDIN unless changed by -b */ debug_level = compress_flag = 0; - while ((ch = getopt(argc, argv, "1hvCo:s:S:")) != -1) { + while ((ch = getopt(argc, argv, "1hvCo:s:S:b:")) != -1) { switch (ch) { case 'C': compress_flag = 1; @@ -179,6 +181,14 @@ main(int argc, char **argv) case 'S': ssh_program = optarg; break; + case 'b': + if (infile == stdin) { + infile = fopen(optarg, "r"); + if (infile == NULL) + fatal("%s (%s).", strerror(errno), optarg); + } else + fatal("Filename already specified."); + break; case 'h': default: usage(); @@ -245,6 +255,8 @@ main(int argc, char **argv) close(in); close(out); + if (infile != stdin) + fclose(infile); if (waitpid(sshpid, NULL, 0) == -1) fatal("Couldn't wait for ssh process: %s", strerror(errno)); -- cgit v1.2.3