1/* 2 * Copyright (c) 2001,2002 Damien Miller. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25#include "includes.h" 26
|
27RCSID("$OpenBSD: sftp.c,v 1.34 2003/01/10 08:19:07 fgsch Exp $");
|
27RCSID("$OpenBSD: sftp.c,v 1.37 2003/07/10 20:05:55 markus Exp $"); |
28
|
29/* XXX: short-form remote directory listings (like 'ls -C') */
30
|
29#include "buffer.h" 30#include "xmalloc.h" 31#include "log.h" 32#include "pathnames.h" 33#include "misc.h" 34 35#include "sftp.h" 36#include "sftp-common.h" 37#include "sftp-client.h" 38#include "sftp-int.h" 39 40#ifdef HAVE___PROGNAME 41extern char *__progname; 42#else 43char *__progname; 44#endif 45 46FILE* infile; 47size_t copy_buffer_len = 32768; 48size_t num_requests = 16;
|
49static pid_t sshpid = -1; |
50 51extern int showprogress; 52 53static void
|
55connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid)
|
54killchild(int signo) |
55{
|
56 if (sshpid > 1) 57 kill(sshpid, signo); 58 59 _exit(1); 60} 61 62static void 63connect_to_server(char *path, char **args, int *in, int *out) 64{ |
65 int c_in, c_out; 66 67#ifdef USE_PIPES 68 int pin[2], pout[2]; 69 70 if ((pipe(pin) == -1) || (pipe(pout) == -1)) 71 fatal("pipe: %s", strerror(errno)); 72 *in = pin[0]; 73 *out = pout[1]; 74 c_in = pout[0]; 75 c_out = pin[1]; 76#else /* USE_PIPES */ 77 int inout[2]; 78 79 if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) 80 fatal("socketpair: %s", strerror(errno)); 81 *in = *out = inout[0]; 82 c_in = c_out = inout[1]; 83#endif /* USE_PIPES */ 84
|
77 if ((*sshpid = fork()) == -1)
|
85 if ((sshpid = fork()) == -1) |
86 fatal("fork: %s", strerror(errno));
|
79 else if (*sshpid == 0) {
|
87 else if (sshpid == 0) { |
88 if ((dup2(c_in, STDIN_FILENO) == -1) || 89 (dup2(c_out, STDOUT_FILENO) == -1)) { 90 fprintf(stderr, "dup2: %s\n", strerror(errno)); 91 exit(1); 92 } 93 close(*in); 94 close(*out); 95 close(c_in); 96 close(c_out); 97 execv(path, args); 98 fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); 99 exit(1); 100 } 101
|
102 signal(SIGTERM, killchild); 103 signal(SIGINT, killchild); 104 signal(SIGHUP, killchild); |
105 close(c_in); 106 close(c_out); 107} 108 109static void 110usage(void) 111{ 112 extern char *__progname; 113 114 fprintf(stderr,
|
104 "usage: %s [-vC1] [-b batchfile] [-o option] [-s subsystem|path] [-B buffer_size]\n"
105 " [-F config] [-P direct server path] [-S program]\n"
|
115 "usage: %s [-vC1] [-b batchfile] [-o ssh_option] [-s subsystem | sftp_server]\n" 116 " [-B buffer_size] [-F ssh_config] [-P sftp_server path]\n" 117 " [-R num_requests] [-S program]\n" |
118 " [user@]host[:file [file]]\n", __progname); 119 exit(1); 120} 121 122int 123main(int argc, char **argv) 124{ 125 int in, out, ch, err;
|
114 pid_t sshpid;
|
126 char *host, *userhost, *cp, *file2; 127 int debug_level = 0, sshver = 2; 128 char *file1 = NULL, *sftp_server = NULL; 129 char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; 130 LogLevel ll = SYSLOG_LEVEL_INFO; 131 arglist args; 132 extern int optind; 133 extern char *optarg; 134
|
124 __progname = get_progname(argv[0]);
|
135 __progname = ssh_get_progname(argv[0]); |
136 args.list = NULL; 137 addargs(&args, "ssh"); /* overwritten with ssh_program */ 138 addargs(&args, "-oForwardX11 no"); 139 addargs(&args, "-oForwardAgent no"); 140 addargs(&args, "-oClearAllForwardings yes"); 141 ll = SYSLOG_LEVEL_INFO; 142 infile = stdin; /* Read from STDIN unless changed by -b */ 143 144 while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) { 145 switch (ch) { 146 case 'C': 147 addargs(&args, "-C"); 148 break; 149 case 'v': 150 if (debug_level < 3) { 151 addargs(&args, "-v"); 152 ll = SYSLOG_LEVEL_DEBUG1 + debug_level; 153 } 154 debug_level++; 155 break; 156 case 'F': 157 case 'o': 158 addargs(&args, "-%c%s", ch, optarg); 159 break; 160 case '1': 161 sshver = 1; 162 if (sftp_server == NULL) 163 sftp_server = _PATH_SFTP_SERVER; 164 break; 165 case 's': 166 sftp_server = optarg; 167 break; 168 case 'S': 169 ssh_program = optarg; 170 break; 171 case 'b': 172 if (infile == stdin) { 173 infile = fopen(optarg, "r"); 174 if (infile == NULL) 175 fatal("%s (%s).", strerror(errno), optarg); 176 } else 177 fatal("Filename already specified."); 178 showprogress = 0; 179 break; 180 case 'P': 181 sftp_direct = optarg; 182 break; 183 case 'B': 184 copy_buffer_len = strtol(optarg, &cp, 10); 185 if (copy_buffer_len == 0 || *cp != '\0') 186 fatal("Invalid buffer size \"%s\"", optarg); 187 break; 188 case 'R': 189 num_requests = strtol(optarg, &cp, 10); 190 if (num_requests == 0 || *cp != '\0') 191 fatal("Invalid number of requests \"%s\"", 192 optarg); 193 break; 194 case 'h': 195 default: 196 usage(); 197 } 198 } 199 200 log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); 201 202 if (sftp_direct == NULL) { 203 if (optind == argc || argc > (optind + 2)) 204 usage(); 205 206 userhost = xstrdup(argv[optind]); 207 file2 = argv[optind+1]; 208 209 if ((cp = colon(userhost)) != NULL) { 210 *cp++ = '\0'; 211 file1 = cp; 212 } 213 214 if ((host = strrchr(userhost, '@')) == NULL) 215 host = userhost; 216 else { 217 *host++ = '\0'; 218 if (!userhost[0]) { 219 fprintf(stderr, "Missing username\n"); 220 usage(); 221 } 222 addargs(&args, "-l%s",userhost); 223 } 224 225 host = cleanhostname(host); 226 if (!*host) { 227 fprintf(stderr, "Missing hostname\n"); 228 usage(); 229 } 230 231 addargs(&args, "-oProtocol %d", sshver); 232 233 /* no subsystem if the server-spec contains a '/' */ 234 if (sftp_server == NULL || strchr(sftp_server, '/') == NULL) 235 addargs(&args, "-s"); 236 237 addargs(&args, "%s", host); 238 addargs(&args, "%s", (sftp_server != NULL ? 239 sftp_server : "sftp")); 240 args.list[0] = ssh_program; 241 242 fprintf(stderr, "Connecting to %s...\n", host);
|
232 connect_to_server(ssh_program, args.list, &in, &out,
233 &sshpid);
|
243 connect_to_server(ssh_program, args.list, &in, &out); |
244 } else { 245 args.list = NULL; 246 addargs(&args, "sftp-server"); 247 248 fprintf(stderr, "Attaching to %s...\n", sftp_direct);
|
239 connect_to_server(sftp_direct, args.list, &in, &out,
240 &sshpid);
|
249 connect_to_server(sftp_direct, args.list, &in, &out); |
250 } 251 252 err = interactive_loop(in, out, file1, file2); 253 254#if !defined(USE_PIPES) 255 shutdown(in, SHUT_RDWR); 256 shutdown(out, SHUT_RDWR); 257#endif 258 259 close(in); 260 close(out); 261 if (infile != stdin) 262 fclose(infile); 263 264 while (waitpid(sshpid, NULL, 0) == -1) 265 if (errno != EINTR) 266 fatal("Couldn't wait for ssh process: %s", 267 strerror(errno)); 268 269 exit(err == 0 ? 0 : 1); 270}
|