diff options
Diffstat (limited to 'sftp.c')
-rw-r--r-- | sftp.c | 222 |
1 files changed, 222 insertions, 0 deletions
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001 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 | |||
27 | RCSID("$OpenBSD: sftp.c,v 1.1 2001/02/04 11:11:54 djm Exp $"); | ||
28 | |||
29 | /* XXX: commandline mode */ | ||
30 | /* XXX: copy between two remote hosts (commandline) */ | ||
31 | /* XXX: short-form remote directory listings (like 'ls -C') */ | ||
32 | |||
33 | #include "buffer.h" | ||
34 | #include "xmalloc.h" | ||
35 | #include "log.h" | ||
36 | #include "pathnames.h" | ||
37 | |||
38 | #include "sftp.h" | ||
39 | #include "sftp-common.h" | ||
40 | #include "sftp-client.h" | ||
41 | #include "sftp-int.h" | ||
42 | |||
43 | void | ||
44 | connect_to_server(char **args, int *in, int *out, pid_t *sshpid) | ||
45 | { | ||
46 | int c_in, c_out; | ||
47 | #ifdef USE_PIPES | ||
48 | int pin[2], pout[2]; | ||
49 | if ((pipe(pin) == -1) || (pipe(pout) == -1)) | ||
50 | fatal("pipe: %s", strerror(errno)); | ||
51 | *in = pin[0]; | ||
52 | *out = pout[1]; | ||
53 | c_in = pout[0]; | ||
54 | c_out = pin[1]; | ||
55 | #else /* USE_PIPES */ | ||
56 | int inout[2]; | ||
57 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) | ||
58 | fatal("socketpair: %s", strerror(errno)); | ||
59 | *in = *out = inout[0]; | ||
60 | c_in = c_out = inout[1]; | ||
61 | #endif /* USE_PIPES */ | ||
62 | |||
63 | if ((*sshpid = fork()) == -1) | ||
64 | fatal("fork: %s", strerror(errno)); | ||
65 | else if (*sshpid == 0) { | ||
66 | if ((dup2(c_in, STDIN_FILENO) == -1) || | ||
67 | (dup2(c_out, STDOUT_FILENO) == -1)) { | ||
68 | fprintf(stderr, "dup2: %s\n", strerror(errno)); | ||
69 | exit(1); | ||
70 | } | ||
71 | close(*in); | ||
72 | close(*out); | ||
73 | close(c_in); | ||
74 | close(c_out); | ||
75 | execv(_PATH_SSH_PROGRAM, args); | ||
76 | fprintf(stderr, "exec: %s", strerror(errno)); | ||
77 | exit(1); | ||
78 | } | ||
79 | |||
80 | close(c_in); | ||
81 | close(c_out); | ||
82 | } | ||
83 | |||
84 | char ** | ||
85 | make_ssh_args(char *add_arg) | ||
86 | { | ||
87 | static char **args = NULL; | ||
88 | static int nargs = 0; | ||
89 | char debug_buf[4096]; | ||
90 | int i; | ||
91 | |||
92 | /* Init args array */ | ||
93 | if (args == NULL) { | ||
94 | nargs = 4; | ||
95 | i = 0; | ||
96 | args = xmalloc(sizeof(*args) * nargs); | ||
97 | args[i++] = "ssh"; | ||
98 | args[i++] = "-oProtocol=2"; | ||
99 | args[i++] = "-s"; | ||
100 | args[i++] = NULL; | ||
101 | } | ||
102 | |||
103 | /* If asked to add args, then do so and return */ | ||
104 | if (add_arg) { | ||
105 | i = nargs++ - 1; | ||
106 | args = xrealloc(args, sizeof(*args) * nargs); | ||
107 | args[i++] = add_arg; | ||
108 | args[i++] = NULL; | ||
109 | return(NULL); | ||
110 | } | ||
111 | |||
112 | /* Otherwise finish up and return the arg array */ | ||
113 | make_ssh_args("sftp"); | ||
114 | |||
115 | /* XXX: overflow - doesn't grow debug_buf */ | ||
116 | debug_buf[0] = '\0'; | ||
117 | for(i = 0; args[i]; i++) { | ||
118 | if (i) | ||
119 | strlcat(debug_buf, " ", sizeof(debug_buf)); | ||
120 | |||
121 | strlcat(debug_buf, args[i], sizeof(debug_buf)); | ||
122 | } | ||
123 | debug("SSH args \"%s\"", debug_buf); | ||
124 | |||
125 | return(args); | ||
126 | } | ||
127 | |||
128 | void | ||
129 | usage(void) | ||
130 | { | ||
131 | fprintf(stderr, "usage: sftp [-vC] [-osshopt=value] [user@]host\n"); | ||
132 | exit(1); | ||
133 | } | ||
134 | |||
135 | int | ||
136 | main(int argc, char **argv) | ||
137 | { | ||
138 | int in, out, i, debug_level, compress_flag; | ||
139 | pid_t sshpid; | ||
140 | char *cp; | ||
141 | LogLevel ll; | ||
142 | |||
143 | debug_level = compress_flag = 0; | ||
144 | for(i = 1; i < argc && argv[i][0] == '-'; i++) { | ||
145 | if (!strcmp(argv[i], "-v")) | ||
146 | debug_level = MIN(3, debug_level + 1); | ||
147 | else if (!strcmp(argv[i], "-C")) | ||
148 | compress_flag = 1; | ||
149 | else if (!strncmp(argv[i], "-o", 2)) { | ||
150 | make_ssh_args(argv[i]); | ||
151 | } else { | ||
152 | fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); | ||
153 | usage(); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | if (i == argc || argc > (i + 1)) | ||
158 | usage(); | ||
159 | |||
160 | if ((cp = strchr(argv[i], '@')) == NULL) | ||
161 | cp = argv[i]; | ||
162 | else { | ||
163 | *cp = '\0'; | ||
164 | if (!argv[i][0]) { | ||
165 | fprintf(stderr, "Missing username\n"); | ||
166 | usage(); | ||
167 | } | ||
168 | make_ssh_args("-l"); | ||
169 | make_ssh_args(argv[i]); | ||
170 | cp++; | ||
171 | } | ||
172 | |||
173 | if (!*cp) { | ||
174 | fprintf(stderr, "Missing hostname\n"); | ||
175 | usage(); | ||
176 | } | ||
177 | |||
178 | /* Set up logging and debug '-d' arguments to ssh */ | ||
179 | ll = SYSLOG_LEVEL_INFO; | ||
180 | switch (debug_level) { | ||
181 | case 1: | ||
182 | ll = SYSLOG_LEVEL_DEBUG1; | ||
183 | make_ssh_args("-v"); | ||
184 | break; | ||
185 | case 2: | ||
186 | ll = SYSLOG_LEVEL_DEBUG2; | ||
187 | make_ssh_args("-v"); | ||
188 | make_ssh_args("-v"); | ||
189 | break; | ||
190 | case 3: | ||
191 | ll = SYSLOG_LEVEL_DEBUG3; | ||
192 | make_ssh_args("-v"); | ||
193 | make_ssh_args("-v"); | ||
194 | make_ssh_args("-v"); | ||
195 | break; | ||
196 | } | ||
197 | |||
198 | if (compress_flag) | ||
199 | make_ssh_args("-C"); | ||
200 | |||
201 | log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); | ||
202 | |||
203 | make_ssh_args(cp); | ||
204 | |||
205 | fprintf(stderr, "Connecting to %s...\n", cp); | ||
206 | |||
207 | connect_to_server(make_ssh_args(NULL), &in, &out, &sshpid); | ||
208 | |||
209 | do_init(in, out); | ||
210 | |||
211 | interactive_loop(in, out); | ||
212 | |||
213 | close(in); | ||
214 | close(out); | ||
215 | |||
216 | if (kill(sshpid, SIGHUP) == -1) | ||
217 | fatal("Couldn't terminate ssh process: %s", strerror(errno)); | ||
218 | |||
219 | /* XXX: wait? */ | ||
220 | |||
221 | exit(0); | ||
222 | } | ||