Commit | Line | Data |
---|---|---|
edf71f48 | 1 | /* |
9069f68e | 2 | * Copyright (c) 1985 Regents of the University of California. |
edf71f48 DF |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
e0b077fe | 7 | #ifndef lint |
f2cc6cbf | 8 | static char sccsid[] = "@(#)ftp.c 5.14 (Berkeley) %G%"; |
edf71f48 | 9 | #endif not lint |
e0b077fe | 10 | |
9069f68e GM |
11 | #include "ftp_var.h" |
12 | ||
e0b077fe SL |
13 | #include <sys/stat.h> |
14 | #include <sys/ioctl.h> | |
15 | #include <sys/socket.h> | |
19371098 | 16 | #include <sys/time.h> |
f2cc6cbf | 17 | #include <sys/param.h> |
e0b077fe SL |
18 | |
19 | #include <netinet/in.h> | |
62c4a390 | 20 | #include <arpa/ftp.h> |
9069f68e | 21 | #include <arpa/telnet.h> |
e0b077fe SL |
22 | |
23 | #include <stdio.h> | |
24 | #include <signal.h> | |
e0b077fe SL |
25 | #include <errno.h> |
26 | #include <netdb.h> | |
9069f68e GM |
27 | #include <fcntl.h> |
28 | #include <pwd.h> | |
e0b077fe SL |
29 | |
30 | struct sockaddr_in hisctladdr; | |
31 | struct sockaddr_in data_addr; | |
32 | int data = -1; | |
9069f68e GM |
33 | int abrtflag = 0; |
34 | int ptflag = 0; | |
e0b077fe SL |
35 | int connected; |
36 | struct sockaddr_in myctladdr; | |
04480325 | 37 | uid_t getuid(); |
e0b077fe SL |
38 | |
39 | FILE *cin, *cout; | |
40 | FILE *dataconn(); | |
41 | ||
198ce38e | 42 | char * |
e0b077fe SL |
43 | hookup(host, port) |
44 | char *host; | |
45 | int port; | |
46 | { | |
198ce38e | 47 | register struct hostent *hp = 0; |
bd9f17de | 48 | int s,len; |
198ce38e | 49 | static char hostnamebuf[80]; |
e0b077fe SL |
50 | |
51 | bzero((char *)&hisctladdr, sizeof (hisctladdr)); | |
198ce38e MK |
52 | hisctladdr.sin_addr.s_addr = inet_addr(host); |
53 | if (hisctladdr.sin_addr.s_addr != -1) { | |
54 | hisctladdr.sin_family = AF_INET; | |
55 | (void) strcpy(hostnamebuf, host); | |
9069f68e GM |
56 | } |
57 | else { | |
5c91ebd4 | 58 | hp = gethostbyname(host); |
198ce38e MK |
59 | if (hp == NULL) { |
60 | printf("%s: unknown host\n", host); | |
9069f68e GM |
61 | code = -1; |
62 | return((char *) 0); | |
198ce38e MK |
63 | } |
64 | hisctladdr.sin_family = hp->h_addrtype; | |
65 | bcopy(hp->h_addr_list[0], | |
66 | (caddr_t)&hisctladdr.sin_addr, hp->h_length); | |
67 | (void) strcpy(hostnamebuf, hp->h_name); | |
5c91ebd4 | 68 | } |
198ce38e MK |
69 | hostname = hostnamebuf; |
70 | s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); | |
e0b077fe SL |
71 | if (s < 0) { |
72 | perror("ftp: socket"); | |
9069f68e | 73 | code = -1; |
e0b077fe SL |
74 | return (0); |
75 | } | |
e0b077fe | 76 | hisctladdr.sin_port = port; |
04480325 | 77 | while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { |
198ce38e MK |
78 | if (hp && hp->h_addr_list[1]) { |
79 | int oerrno = errno; | |
80 | ||
81 | fprintf(stderr, "ftp: connect to address %s: ", | |
82 | inet_ntoa(hisctladdr.sin_addr)); | |
83 | errno = oerrno; | |
04480325 | 84 | perror((char *) 0); |
198ce38e MK |
85 | hp->h_addr_list++; |
86 | bcopy(hp->h_addr_list[0], | |
9069f68e | 87 | (caddr_t)&hisctladdr.sin_addr, hp->h_length); |
04480325 | 88 | fprintf(stdout, "Trying %s...\n", |
198ce38e | 89 | inet_ntoa(hisctladdr.sin_addr)); |
d97e9a77 MK |
90 | (void) close(s); |
91 | s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); | |
92 | if (s < 0) { | |
93 | perror("ftp: socket"); | |
94 | code = -1; | |
95 | return (0); | |
96 | } | |
198ce38e MK |
97 | continue; |
98 | } | |
e0b077fe | 99 | perror("ftp: connect"); |
9069f68e | 100 | code = -1; |
e0b077fe SL |
101 | goto bad; |
102 | } | |
8c1d51c7 SL |
103 | len = sizeof (myctladdr); |
104 | if (getsockname(s, (char *)&myctladdr, &len) < 0) { | |
105 | perror("ftp: getsockname"); | |
9069f68e | 106 | code = -1; |
e0b077fe SL |
107 | goto bad; |
108 | } | |
109 | cin = fdopen(s, "r"); | |
110 | cout = fdopen(s, "w"); | |
d33c618b | 111 | if (cin == NULL || cout == NULL) { |
e0b077fe SL |
112 | fprintf(stderr, "ftp: fdopen failed.\n"); |
113 | if (cin) | |
04480325 | 114 | (void) fclose(cin); |
e0b077fe | 115 | if (cout) |
04480325 | 116 | (void) fclose(cout); |
9069f68e | 117 | code = -1; |
e0b077fe SL |
118 | goto bad; |
119 | } | |
120 | if (verbose) | |
2e5611a5 | 121 | printf("Connected to %s.\n", hostname); |
bd9f17de | 122 | if (getreply(0) > 2) { /* read startup message from server */ |
9069f68e | 123 | if (cin) |
04480325 | 124 | (void) fclose(cin); |
9069f68e | 125 | if (cout) |
04480325 | 126 | (void) fclose(cout); |
9069f68e GM |
127 | code = -1; |
128 | goto bad; | |
129 | } | |
bd9f17de GM |
130 | #ifdef SO_OOBINLINE |
131 | { | |
132 | int on = 1; | |
9069f68e | 133 | |
bd9f17de GM |
134 | if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) |
135 | < 0 && debug) { | |
136 | perror("ftp: setsockopt"); | |
137 | } | |
138 | } | |
139 | #endif SO_OOBINLINE | |
9069f68e | 140 | |
198ce38e | 141 | return (hostname); |
e0b077fe | 142 | bad: |
04480325 | 143 | (void) close(s); |
198ce38e | 144 | return ((char *)0); |
e0b077fe SL |
145 | } |
146 | ||
198ce38e MK |
147 | login(host) |
148 | char *host; | |
e0b077fe | 149 | { |
9069f68e | 150 | char tmp[80]; |
04480325 | 151 | char *user, *pass, *acct, *getlogin(), *mygetpass(); |
9069f68e GM |
152 | int n, aflag = 0; |
153 | ||
154 | user = pass = acct = 0; | |
155 | if (ruserpass(host, &user, &pass, &acct) < 0) { | |
156 | disconnect(); | |
157 | code = -1; | |
158 | return(0); | |
159 | } | |
160 | if (user == NULL) { | |
161 | char *myname = getlogin(); | |
e0b077fe | 162 | |
9069f68e GM |
163 | if (myname == NULL) { |
164 | struct passwd *pp = getpwuid(getuid()); | |
165 | ||
98c50518 | 166 | if (pp != NULL) |
9069f68e | 167 | myname = pp->pw_name; |
9069f68e GM |
168 | } |
169 | printf("Name (%s:%s): ", host, myname); | |
170 | (void) fgets(tmp, sizeof(tmp) - 1, stdin); | |
171 | tmp[strlen(tmp) - 1] = '\0'; | |
98c50518 | 172 | if (*tmp == '\0') |
9069f68e | 173 | user = myname; |
98c50518 | 174 | else |
9069f68e | 175 | user = tmp; |
9069f68e | 176 | } |
e0b077fe | 177 | n = command("USER %s", user); |
9069f68e | 178 | if (n == CONTINUE) { |
98c50518 | 179 | if (pass == NULL) |
04480325 | 180 | pass = mygetpass("Password:"); |
e0b077fe | 181 | n = command("PASS %s", pass); |
9069f68e | 182 | } |
e0b077fe | 183 | if (n == CONTINUE) { |
9069f68e | 184 | aflag++; |
04480325 | 185 | acct = mygetpass("Account:"); |
e0b077fe SL |
186 | n = command("ACCT %s", acct); |
187 | } | |
188 | if (n != COMPLETE) { | |
189 | fprintf(stderr, "Login failed.\n"); | |
190 | return (0); | |
191 | } | |
98c50518 | 192 | if (!aflag && acct != NULL) |
9069f68e | 193 | (void) command("ACCT %s", acct); |
98c50518 | 194 | if (proxy) |
9069f68e | 195 | return(1); |
9069f68e GM |
196 | for (n = 0; n < macnum; ++n) { |
197 | if (!strcmp("init", macros[n].mac_name)) { | |
04480325 | 198 | (void) strcpy(line, "$init"); |
9069f68e GM |
199 | makeargv(); |
200 | domacro(margc, margv); | |
201 | break; | |
202 | } | |
203 | } | |
e0b077fe SL |
204 | return (1); |
205 | } | |
206 | ||
9069f68e GM |
207 | cmdabort() |
208 | { | |
209 | extern jmp_buf ptabort; | |
210 | ||
211 | printf("\n"); | |
212 | (void) fflush(stdout); | |
213 | abrtflag++; | |
98c50518 | 214 | if (ptflag) |
9069f68e | 215 | longjmp(ptabort,1); |
9069f68e GM |
216 | } |
217 | ||
04480325 | 218 | /*VARARGS1*/ |
e0b077fe SL |
219 | command(fmt, args) |
220 | char *fmt; | |
221 | { | |
9069f68e | 222 | int r, (*oldintr)(), cmdabort(); |
e0b077fe | 223 | |
9069f68e | 224 | abrtflag = 0; |
e0b077fe SL |
225 | if (debug) { |
226 | printf("---> "); | |
227 | _doprnt(fmt, &args, stdout); | |
228 | printf("\n"); | |
229 | (void) fflush(stdout); | |
230 | } | |
d33c618b SL |
231 | if (cout == NULL) { |
232 | perror ("No control connection for command"); | |
9069f68e | 233 | code = -1; |
d33c618b SL |
234 | return (0); |
235 | } | |
9069f68e | 236 | oldintr = signal(SIGINT,cmdabort); |
e0b077fe SL |
237 | _doprnt(fmt, &args, cout); |
238 | fprintf(cout, "\r\n"); | |
239 | (void) fflush(cout); | |
9069f68e GM |
240 | cpend = 1; |
241 | r = getreply(!strcmp(fmt, "QUIT")); | |
98c50518 | 242 | if (abrtflag && oldintr != SIG_IGN) |
9069f68e | 243 | (*oldintr)(); |
9069f68e GM |
244 | (void) signal(SIGINT, oldintr); |
245 | return(r); | |
e0b077fe SL |
246 | } |
247 | ||
248 | #include <ctype.h> | |
249 | ||
250 | getreply(expecteof) | |
251 | int expecteof; | |
252 | { | |
d33c618b | 253 | register int c, n; |
9069f68e GM |
254 | register int dig; |
255 | int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); | |
256 | int pflag = 0; | |
257 | char *pt = pasv; | |
e0b077fe | 258 | |
9069f68e | 259 | oldintr = signal(SIGINT,cmdabort); |
e0b077fe SL |
260 | for (;;) { |
261 | dig = n = code = 0; | |
262 | while ((c = getc(cin)) != '\n') { | |
bd9f17de GM |
263 | if (c == IAC) { /* handle telnet commands */ |
264 | switch (c = getc(cin)) { | |
265 | case WILL: | |
266 | case WONT: | |
267 | c = getc(cin); | |
268 | fprintf(cout, "%c%c%c",IAC,WONT,c); | |
269 | (void) fflush(cout); | |
270 | break; | |
271 | case DO: | |
272 | case DONT: | |
273 | c = getc(cin); | |
274 | fprintf(cout, "%c%c%c",IAC,DONT,c); | |
275 | (void) fflush(cout); | |
276 | break; | |
277 | default: | |
278 | break; | |
279 | } | |
280 | continue; | |
281 | } | |
e0b077fe SL |
282 | dig++; |
283 | if (c == EOF) { | |
9069f68e GM |
284 | if (expecteof) { |
285 | (void) signal(SIGINT,oldintr); | |
286 | code = 221; | |
e0b077fe | 287 | return (0); |
9069f68e | 288 | } |
e0b077fe | 289 | lostpeer(); |
9069f68e GM |
290 | if (verbose) { |
291 | printf("421 Service not available, remote server has closed connection\n"); | |
292 | (void) fflush(stdout); | |
293 | code = 421; | |
294 | return(4); | |
295 | } | |
e0b077fe | 296 | } |
9069f68e GM |
297 | if (c != '\r' && (verbose > 0 || |
298 | (verbose > -1 && n == '5' && dig > 4))) { | |
98c50518 JL |
299 | if (proxflag && |
300 | (dig == 1 || dig == 5 && verbose == 0)) | |
9069f68e | 301 | printf("%s:",hostname); |
04480325 | 302 | (void) putchar(c); |
9069f68e | 303 | } |
e0b077fe SL |
304 | if (dig < 4 && isdigit(c)) |
305 | code = code * 10 + (c - '0'); | |
98c50518 | 306 | if (!pflag && code == 227) |
9069f68e | 307 | pflag = 1; |
98c50518 | 308 | if (dig > 4 && pflag == 1 && isdigit(c)) |
9069f68e | 309 | pflag = 2; |
9069f68e | 310 | if (pflag == 2) { |
98c50518 | 311 | if (c != '\r' && c != ')') |
9069f68e | 312 | *pt++ = c; |
9069f68e GM |
313 | else { |
314 | *pt = '\0'; | |
315 | pflag = 3; | |
316 | } | |
317 | } | |
318 | if (dig == 4 && c == '-') { | |
98c50518 | 319 | if (continuation) |
9069f68e | 320 | code = 0; |
e0b077fe | 321 | continuation++; |
9069f68e | 322 | } |
e0b077fe SL |
323 | if (n == 0) |
324 | n = c; | |
325 | } | |
9069f68e | 326 | if (verbose > 0 || verbose > -1 && n == '5') { |
04480325 | 327 | (void) putchar(c); |
7968a79f SL |
328 | (void) fflush (stdout); |
329 | } | |
e0b077fe SL |
330 | if (continuation && code != originalcode) { |
331 | if (originalcode == 0) | |
332 | originalcode = code; | |
333 | continue; | |
334 | } | |
98c50518 | 335 | if (n != '1') |
9069f68e | 336 | cpend = 0; |
9069f68e | 337 | (void) signal(SIGINT,oldintr); |
98c50518 | 338 | if (code == 421 || originalcode == 421) |
9069f68e | 339 | lostpeer(); |
98c50518 | 340 | if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) |
9069f68e | 341 | (*oldintr)(); |
14433a73 | 342 | return (n - '0'); |
e0b077fe SL |
343 | } |
344 | } | |
345 | ||
9069f68e | 346 | empty(mask, sec) |
bd9f17de | 347 | struct fd_set *mask; |
9069f68e GM |
348 | int sec; |
349 | { | |
350 | struct timeval t; | |
351 | ||
352 | t.tv_sec = (long) sec; | |
353 | t.tv_usec = 0; | |
bd9f17de | 354 | return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); |
9069f68e GM |
355 | } |
356 | ||
e0b077fe SL |
357 | jmp_buf sendabort; |
358 | ||
359 | abortsend() | |
360 | { | |
361 | ||
9069f68e GM |
362 | mflag = 0; |
363 | abrtflag = 0; | |
364 | printf("\nsend aborted\n"); | |
365 | (void) fflush(stdout); | |
e0b077fe SL |
366 | longjmp(sendabort, 1); |
367 | } | |
368 | ||
369 | sendrequest(cmd, local, remote) | |
370 | char *cmd, *local, *remote; | |
371 | { | |
04480325 GM |
372 | FILE *fin, *dout = 0, *mypopen(); |
373 | int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); | |
9069f68e | 374 | int abortsend(); |
d33c618b | 375 | char buf[BUFSIZ]; |
5ac6fc46 | 376 | long bytes = 0, hashbytes = sizeof (buf); |
7968a79f | 377 | register int c, d; |
e0b077fe SL |
378 | struct stat st; |
379 | struct timeval start, stop; | |
380 | ||
9069f68e GM |
381 | if (proxy) { |
382 | proxtrans(cmd, local, remote); | |
383 | return; | |
384 | } | |
e0b077fe | 385 | closefunc = NULL; |
9069f68e GM |
386 | oldintr = NULL; |
387 | oldintp = NULL; | |
388 | if (setjmp(sendabort)) { | |
389 | while (cpend) { | |
390 | (void) getreply(0); | |
391 | } | |
392 | if (data >= 0) { | |
393 | (void) close(data); | |
394 | data = -1; | |
395 | } | |
98c50518 | 396 | if (oldintr) |
9069f68e | 397 | (void) signal(SIGINT,oldintr); |
98c50518 | 398 | if (oldintp) |
9069f68e | 399 | (void) signal(SIGPIPE,oldintp); |
9069f68e GM |
400 | code = -1; |
401 | return; | |
402 | } | |
e0b077fe SL |
403 | oldintr = signal(SIGINT, abortsend); |
404 | if (strcmp(local, "-") == 0) | |
405 | fin = stdin; | |
406 | else if (*local == '|') { | |
9069f68e | 407 | oldintp = signal(SIGPIPE,SIG_IGN); |
04480325 | 408 | fin = mypopen(local + 1, "r"); |
e0b077fe | 409 | if (fin == NULL) { |
9069f68e GM |
410 | perror(local + 1); |
411 | (void) signal(SIGINT, oldintr); | |
412 | (void) signal(SIGPIPE, oldintp); | |
413 | code = -1; | |
414 | return; | |
e0b077fe | 415 | } |
04480325 | 416 | closefunc = mypclose; |
e0b077fe SL |
417 | } else { |
418 | fin = fopen(local, "r"); | |
419 | if (fin == NULL) { | |
420 | perror(local); | |
9069f68e GM |
421 | (void) signal(SIGINT, oldintr); |
422 | code = -1; | |
423 | return; | |
e0b077fe SL |
424 | } |
425 | closefunc = fclose; | |
426 | if (fstat(fileno(fin), &st) < 0 || | |
427 | (st.st_mode&S_IFMT) != S_IFREG) { | |
04480325 | 428 | fprintf(stdout, "%s: not a plain file.\n", local); |
9069f68e GM |
429 | (void) signal(SIGINT, oldintr); |
430 | code = -1; | |
431 | return; | |
e0b077fe SL |
432 | } |
433 | } | |
9069f68e GM |
434 | if (initconn()) { |
435 | (void) signal(SIGINT, oldintr); | |
98c50518 | 436 | if (oldintp) |
9069f68e | 437 | (void) signal(SIGPIPE, oldintp); |
9069f68e GM |
438 | code = -1; |
439 | return; | |
440 | } | |
98c50518 | 441 | if (setjmp(sendabort)) |
9069f68e | 442 | goto abort; |
e0b077fe | 443 | if (remote) { |
9069f68e GM |
444 | if (command("%s %s", cmd, remote) != PRELIM) { |
445 | (void) signal(SIGINT, oldintr); | |
98c50518 | 446 | if (oldintp) |
9069f68e | 447 | (void) signal(SIGPIPE, oldintp); |
9069f68e GM |
448 | return; |
449 | } | |
e0b077fe | 450 | } else |
9069f68e GM |
451 | if (command("%s", cmd) != PRELIM) { |
452 | (void) signal(SIGINT, oldintr); | |
98c50518 | 453 | if (oldintp) |
9069f68e | 454 | (void) signal(SIGPIPE, oldintp); |
9069f68e GM |
455 | return; |
456 | } | |
e0b077fe | 457 | dout = dataconn("w"); |
98c50518 | 458 | if (dout == NULL) |
9069f68e | 459 | goto abort; |
04480325 | 460 | (void) gettimeofday(&start, (struct timezone *)0); |
d33c618b SL |
461 | switch (type) { |
462 | ||
463 | case TYPE_I: | |
464 | case TYPE_L: | |
7968a79f | 465 | errno = d = 0; |
d33c618b | 466 | while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { |
7968a79f | 467 | if ((d = write(fileno (dout), buf, c)) < 0) |
d33c618b SL |
468 | break; |
469 | bytes += c; | |
5ac6fc46 | 470 | if (hash) { |
04480325 GM |
471 | (void) putchar('#'); |
472 | (void) fflush(stdout); | |
5ac6fc46 SL |
473 | } |
474 | } | |
614e24b6 | 475 | if (hash && bytes > 0) { |
04480325 GM |
476 | (void) putchar('\n'); |
477 | (void) fflush(stdout); | |
d33c618b SL |
478 | } |
479 | if (c < 0) | |
480 | perror(local); | |
7968a79f | 481 | if (d < 0) |
d33c618b SL |
482 | perror("netout"); |
483 | break; | |
484 | ||
485 | case TYPE_A: | |
486 | while ((c = getc(fin)) != EOF) { | |
487 | if (c == '\n') { | |
5ac6fc46 | 488 | while (hash && (bytes >= hashbytes)) { |
04480325 GM |
489 | (void) putchar('#'); |
490 | (void) fflush(stdout); | |
5ac6fc46 SL |
491 | hashbytes += sizeof (buf); |
492 | } | |
d33c618b SL |
493 | if (ferror(dout)) |
494 | break; | |
04480325 | 495 | (void) putc('\r', dout); |
d33c618b SL |
496 | bytes++; |
497 | } | |
04480325 | 498 | (void) putc(c, dout); |
d33c618b | 499 | bytes++; |
9069f68e | 500 | /* if (c == '\r') { */ |
04480325 | 501 | /* (void) putc('\0', dout); /* this violates rfc */ |
9069f68e GM |
502 | /* bytes++; */ |
503 | /* } */ | |
d33c618b | 504 | } |
5ac6fc46 | 505 | if (hash) { |
614e24b6 | 506 | if (bytes < hashbytes) |
04480325 GM |
507 | (void) putchar('#'); |
508 | (void) putchar('\n'); | |
509 | (void) fflush(stdout); | |
5ac6fc46 | 510 | } |
d33c618b SL |
511 | if (ferror(fin)) |
512 | perror(local); | |
7968a79f | 513 | if (ferror(dout)) |
d33c618b SL |
514 | perror("netout"); |
515 | break; | |
e0b077fe | 516 | } |
04480325 | 517 | (void) gettimeofday(&stop, (struct timezone *)0); |
e0b077fe | 518 | if (closefunc != NULL) |
9069f68e | 519 | (*closefunc)(fin); |
e0b077fe | 520 | (void) fclose(dout); |
9069f68e GM |
521 | (void) getreply(0); |
522 | (void) signal(SIGINT, oldintr); | |
e0b077fe | 523 | if (bytes > 0 && verbose) |
9069f68e | 524 | ptransfer("sent", bytes, &start, &stop, local, remote); |
e0b077fe | 525 | return; |
9069f68e | 526 | abort: |
04480325 | 527 | (void) gettimeofday(&stop, (struct timezone *)0); |
9069f68e | 528 | (void) signal(SIGINT, oldintr); |
98c50518 | 529 | if (oldintp) |
9069f68e | 530 | (void) signal(SIGPIPE, oldintp); |
9069f68e GM |
531 | if (!cpend) { |
532 | code = -1; | |
533 | return; | |
534 | } | |
535 | if (data >= 0) { | |
536 | (void) close(data); | |
537 | data = -1; | |
538 | } | |
98c50518 | 539 | if (dout) |
9069f68e | 540 | (void) fclose(dout); |
9069f68e GM |
541 | (void) getreply(0); |
542 | code = -1; | |
e0b077fe | 543 | if (closefunc != NULL && fin != NULL) |
9069f68e GM |
544 | (*closefunc)(fin); |
545 | if (bytes > 0 && verbose) | |
546 | ptransfer("sent", bytes, &start, &stop, local, remote); | |
e0b077fe SL |
547 | } |
548 | ||
549 | jmp_buf recvabort; | |
550 | ||
551 | abortrecv() | |
552 | { | |
553 | ||
9069f68e GM |
554 | mflag = 0; |
555 | abrtflag = 0; | |
556 | printf("\n"); | |
557 | (void) fflush(stdout); | |
e0b077fe SL |
558 | longjmp(recvabort, 1); |
559 | } | |
560 | ||
5ac6fc46 SL |
561 | recvrequest(cmd, local, remote, mode) |
562 | char *cmd, *local, *remote, *mode; | |
e0b077fe | 563 | { |
04480325 GM |
564 | FILE *fout, *din = 0, *mypopen(); |
565 | int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); | |
bd9f17de GM |
566 | int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd; |
567 | char buf[BUFSIZ], *gunique(), msg; | |
04480325 GM |
568 | long bytes = 0, hashbytes = sizeof (buf); |
569 | struct fd_set mask; | |
7968a79f | 570 | register int c, d; |
e0b077fe SL |
571 | struct timeval start, stop; |
572 | ||
9069f68e GM |
573 | if (proxy && strcmp(cmd,"RETR") == 0) { |
574 | proxtrans(cmd, local, remote); | |
575 | return; | |
576 | } | |
e0b077fe | 577 | closefunc = NULL; |
9069f68e GM |
578 | oldintr = NULL; |
579 | oldintp = NULL; | |
580 | tcrflag = !crflag && !strcmp(cmd, "RETR"); | |
581 | if (setjmp(recvabort)) { | |
582 | while (cpend) { | |
583 | (void) getreply(0); | |
584 | } | |
585 | if (data >= 0) { | |
586 | (void) close(data); | |
587 | data = -1; | |
588 | } | |
98c50518 | 589 | if (oldintr) |
9069f68e | 590 | (void) signal(SIGINT, oldintr); |
9069f68e GM |
591 | code = -1; |
592 | return; | |
593 | } | |
e0b077fe | 594 | oldintr = signal(SIGINT, abortrecv); |
9069f68e | 595 | if (strcmp(local, "-") && *local != '|') { |
e0b077fe | 596 | if (access(local, 2) < 0) { |
9069f68e GM |
597 | char *dir = rindex(local, '/'); |
598 | ||
599 | if (errno != ENOENT && errno != EACCES) { | |
600 | perror(local); | |
601 | (void) signal(SIGINT, oldintr); | |
602 | code = -1; | |
603 | return; | |
604 | } | |
605 | if (dir != NULL) | |
606 | *dir = 0; | |
607 | d = access(dir ? local : ".", 2); | |
608 | if (dir != NULL) | |
609 | *dir = '/'; | |
610 | if (d < 0) { | |
611 | perror(local); | |
612 | (void) signal(SIGINT, oldintr); | |
613 | code = -1; | |
614 | return; | |
615 | } | |
616 | if (!runique && errno == EACCES && | |
617 | chmod(local,0600) < 0) { | |
e0b077fe | 618 | perror(local); |
9069f68e GM |
619 | (void) signal(SIGINT, oldintr); |
620 | code = -1; | |
621 | return; | |
622 | } | |
623 | if (runique && errno == EACCES && | |
624 | (local = gunique(local)) == NULL) { | |
625 | (void) signal(SIGINT, oldintr); | |
626 | code = -1; | |
627 | return; | |
e0b077fe | 628 | } |
e0b077fe | 629 | } |
9069f68e GM |
630 | else if (runique && (local = gunique(local)) == NULL) { |
631 | (void) signal(SIGINT, oldintr); | |
632 | code = -1; | |
633 | return; | |
634 | } | |
635 | } | |
636 | if (initconn()) { | |
637 | (void) signal(SIGINT, oldintr); | |
638 | code = -1; | |
639 | return; | |
640 | } | |
98c50518 | 641 | if (setjmp(recvabort)) |
9069f68e | 642 | goto abort; |
9069f68e GM |
643 | if (strcmp(cmd, "RETR") && type != TYPE_A) { |
644 | oldtype = type; | |
645 | oldverbose = verbose; | |
98c50518 | 646 | if (!debug) |
9069f68e | 647 | verbose = 0; |
9069f68e GM |
648 | setascii(); |
649 | verbose = oldverbose; | |
650 | } | |
e0b077fe | 651 | if (remote) { |
9069f68e GM |
652 | if (command("%s %s", cmd, remote) != PRELIM) { |
653 | (void) signal(SIGINT, oldintr); | |
654 | if (oldtype) { | |
98c50518 | 655 | if (!debug) |
9069f68e | 656 | verbose = 0; |
9069f68e GM |
657 | switch (oldtype) { |
658 | case TYPE_I: | |
659 | setbinary(); | |
660 | break; | |
661 | case TYPE_E: | |
662 | setebcdic(); | |
663 | break; | |
664 | case TYPE_L: | |
665 | settenex(); | |
666 | break; | |
667 | } | |
668 | verbose = oldverbose; | |
669 | } | |
670 | return; | |
671 | } | |
672 | } else { | |
673 | if (command("%s", cmd) != PRELIM) { | |
674 | (void) signal(SIGINT, oldintr); | |
675 | if (oldtype) { | |
98c50518 | 676 | if (!debug) |
9069f68e | 677 | verbose = 0; |
9069f68e GM |
678 | switch (oldtype) { |
679 | case TYPE_I: | |
680 | setbinary(); | |
681 | break; | |
682 | case TYPE_E: | |
683 | setebcdic(); | |
684 | break; | |
685 | case TYPE_L: | |
686 | settenex(); | |
687 | break; | |
688 | } | |
689 | verbose = oldverbose; | |
690 | } | |
691 | return; | |
692 | } | |
693 | } | |
694 | din = dataconn("r"); | |
695 | if (din == NULL) | |
696 | goto abort; | |
98c50518 | 697 | if (strcmp(local, "-") == 0) |
e0b077fe SL |
698 | fout = stdout; |
699 | else if (*local == '|') { | |
9069f68e | 700 | oldintp = signal(SIGPIPE, SIG_IGN); |
04480325 | 701 | fout = mypopen(local + 1, "w"); |
9069f68e GM |
702 | if (fout == NULL) { |
703 | perror(local+1); | |
704 | goto abort; | |
705 | } | |
04480325 | 706 | closefunc = mypclose; |
9069f68e GM |
707 | } |
708 | else { | |
5ac6fc46 | 709 | fout = fopen(local, mode); |
9069f68e GM |
710 | if (fout == NULL) { |
711 | perror(local); | |
712 | goto abort; | |
713 | } | |
e0b077fe SL |
714 | closefunc = fclose; |
715 | } | |
04480325 | 716 | (void) gettimeofday(&start, (struct timezone *)0); |
d33c618b SL |
717 | switch (type) { |
718 | ||
719 | case TYPE_I: | |
720 | case TYPE_L: | |
7968a79f | 721 | errno = d = 0; |
d33c618b | 722 | while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { |
7968a79f | 723 | if ((d = write(fileno(fout), buf, c)) < 0) |
d33c618b SL |
724 | break; |
725 | bytes += c; | |
5ac6fc46 | 726 | if (hash) { |
04480325 GM |
727 | (void) putchar('#'); |
728 | (void) fflush(stdout); | |
5ac6fc46 SL |
729 | } |
730 | } | |
614e24b6 | 731 | if (hash && bytes > 0) { |
04480325 GM |
732 | (void) putchar('\n'); |
733 | (void) fflush(stdout); | |
d33c618b SL |
734 | } |
735 | if (c < 0) | |
736 | perror("netin"); | |
7968a79f | 737 | if (d < 0) |
e0b077fe | 738 | perror(local); |
d33c618b SL |
739 | break; |
740 | ||
741 | case TYPE_A: | |
742 | while ((c = getc(din)) != EOF) { | |
edb8d233 | 743 | while (c == '\r') { |
5ac6fc46 | 744 | while (hash && (bytes >= hashbytes)) { |
04480325 GM |
745 | (void) putchar('#'); |
746 | (void) fflush(stdout); | |
5ac6fc46 SL |
747 | hashbytes += sizeof (buf); |
748 | } | |
e0b077fe | 749 | bytes++; |
9069f68e | 750 | if ((c = getc(din)) != '\n' || tcrflag) { |
d33c618b SL |
751 | if (ferror (fout)) |
752 | break; | |
04480325 | 753 | (void) putc ('\r', fout); |
d33c618b | 754 | } |
9069f68e | 755 | /*if (c == '\0') { |
d33c618b SL |
756 | bytes++; |
757 | continue; | |
9069f68e | 758 | }*/ |
d33c618b | 759 | } |
04480325 | 760 | (void) putc (c, fout); |
d33c618b | 761 | bytes++; |
e0b077fe | 762 | } |
5ac6fc46 | 763 | if (hash) { |
614e24b6 | 764 | if (bytes < hashbytes) |
04480325 GM |
765 | (void) putchar('#'); |
766 | (void) putchar('\n'); | |
767 | (void) fflush(stdout); | |
5ac6fc46 | 768 | } |
d33c618b SL |
769 | if (ferror (din)) |
770 | perror ("netin"); | |
771 | if (ferror (fout)) | |
772 | perror (local); | |
773 | break; | |
e0b077fe | 774 | } |
98c50518 | 775 | if (closefunc != NULL) |
9069f68e | 776 | (*closefunc)(fout); |
04480325 | 777 | (void) signal(SIGINT, oldintr); |
98c50518 | 778 | if (oldintp) |
9069f68e | 779 | (void) signal(SIGPIPE, oldintp); |
04480325 | 780 | (void) gettimeofday(&stop, (struct timezone *)0); |
9069f68e GM |
781 | (void) fclose(din); |
782 | (void) getreply(0); | |
e0b077fe | 783 | if (bytes > 0 && verbose) |
9069f68e GM |
784 | ptransfer("received", bytes, &start, &stop, local, remote); |
785 | if (oldtype) { | |
98c50518 | 786 | if (!debug) |
9069f68e | 787 | verbose = 0; |
9069f68e GM |
788 | switch (oldtype) { |
789 | case TYPE_I: | |
790 | setbinary(); | |
791 | break; | |
792 | case TYPE_E: | |
793 | setebcdic(); | |
794 | break; | |
795 | case TYPE_L: | |
796 | settenex(); | |
797 | break; | |
798 | } | |
799 | verbose = oldverbose; | |
800 | } | |
e0b077fe | 801 | return; |
9069f68e GM |
802 | abort: |
803 | ||
bd9f17de | 804 | /* abort using RFC959 recommended IP,SYNC sequence */ |
9069f68e | 805 | |
04480325 | 806 | (void) gettimeofday(&stop, (struct timezone *)0); |
98c50518 | 807 | if (oldintp) |
9069f68e | 808 | (void) signal(SIGPIPE, oldintr); |
9069f68e GM |
809 | (void) signal(SIGINT,SIG_IGN); |
810 | if (oldtype) { | |
98c50518 | 811 | if (!debug) |
9069f68e | 812 | verbose = 0; |
9069f68e GM |
813 | switch (oldtype) { |
814 | case TYPE_I: | |
815 | setbinary(); | |
816 | break; | |
817 | case TYPE_E: | |
818 | setebcdic(); | |
819 | break; | |
820 | case TYPE_L: | |
821 | settenex(); | |
822 | break; | |
823 | } | |
824 | verbose = oldverbose; | |
825 | } | |
826 | if (!cpend) { | |
827 | code = -1; | |
828 | (void) signal(SIGINT,oldintr); | |
829 | return; | |
830 | } | |
9069f68e | 831 | |
bd9f17de GM |
832 | fprintf(cout,"%c%c",IAC,IP); |
833 | (void) fflush(cout); | |
834 | msg = IAC; | |
835 | /* send IAC in urgent mode instead of DM because UNIX places oob mark */ | |
836 | /* after urgent byte rather than before as now is protocol */ | |
837 | if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { | |
838 | perror("abort"); | |
9069f68e | 839 | } |
bd9f17de | 840 | fprintf(cout,"%cABOR\r\n",DM); |
9069f68e | 841 | (void) fflush(cout); |
bd9f17de | 842 | FD_ZERO(&mask); |
04480325 GM |
843 | FD_SET(fileno(cin), &mask); |
844 | if (din) { | |
845 | FD_SET(fileno(din), &mask); | |
846 | } | |
bd9f17de GM |
847 | if ((nfnd = empty(&mask,10)) <= 0) { |
848 | if (nfnd < 0) { | |
849 | perror("abort"); | |
850 | } | |
9069f68e GM |
851 | code = -1; |
852 | lostpeer(); | |
853 | } | |
04480325 | 854 | if (din && FD_ISSET(fileno(din), &mask)) { |
98c50518 JL |
855 | while ((c = read(fileno(din), buf, sizeof (buf))) > 0) |
856 | ; | |
04480325 | 857 | } |
bd9f17de | 858 | if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ |
9069f68e | 859 | if (data >= 0) { |
04480325 | 860 | (void) close(data); |
9069f68e GM |
861 | data = -1; |
862 | } | |
863 | (void) getreply(0); | |
864 | } | |
865 | (void) getreply(0); | |
866 | code = -1; | |
867 | if (data >= 0) { | |
868 | (void) close(data); | |
869 | data = -1; | |
870 | } | |
98c50518 | 871 | if (closefunc != NULL && fout != NULL) |
e0b077fe | 872 | (*closefunc)(fout); |
98c50518 | 873 | if (din) |
9069f68e | 874 | (void) fclose(din); |
9069f68e GM |
875 | if (bytes > 0 && verbose) |
876 | ptransfer("received", bytes, &start, &stop, local, remote); | |
877 | (void) signal(SIGINT,oldintr); | |
e0b077fe SL |
878 | } |
879 | ||
880 | /* | |
881 | * Need to start a listen on the data channel | |
882 | * before we send the command, otherwise the | |
883 | * server's connect may fail. | |
884 | */ | |
5ac6fc46 SL |
885 | static int sendport = -1; |
886 | ||
e0b077fe SL |
887 | initconn() |
888 | { | |
889 | register char *p, *a; | |
9069f68e | 890 | int result, len, tmpno = 0; |
044f3211 | 891 | int on = 1; |
e0b077fe | 892 | |
5ac6fc46 | 893 | noport: |
e0b077fe | 894 | data_addr = myctladdr; |
5ac6fc46 SL |
895 | if (sendport) |
896 | data_addr.sin_port = 0; /* let system pick one */ | |
897 | if (data != -1) | |
898 | (void) close (data); | |
71a655cd | 899 | data = socket(AF_INET, SOCK_STREAM, 0); |
e0b077fe SL |
900 | if (data < 0) { |
901 | perror("ftp: socket"); | |
98c50518 | 902 | if (tmpno) |
9069f68e | 903 | sendport = 1; |
e0b077fe SL |
904 | return (1); |
905 | } | |
62c4a390 | 906 | if (!sendport) |
bd9f17de | 907 | if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { |
9069f68e | 908 | perror("ftp: setsockopt (resuse address)"); |
62c4a390 SL |
909 | goto bad; |
910 | } | |
04480325 | 911 | if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { |
e0b077fe SL |
912 | perror("ftp: bind"); |
913 | goto bad; | |
914 | } | |
e0b077fe | 915 | if (options & SO_DEBUG && |
bd9f17de | 916 | setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) |
e0b077fe | 917 | perror("ftp: setsockopt (ignored)"); |
8c1d51c7 SL |
918 | len = sizeof (data_addr); |
919 | if (getsockname(data, (char *)&data_addr, &len) < 0) { | |
920 | perror("ftp: getsockname"); | |
e0b077fe SL |
921 | goto bad; |
922 | } | |
98c50518 | 923 | if (listen(data, 1) < 0) |
e0b077fe | 924 | perror("ftp: listen"); |
5ac6fc46 SL |
925 | if (sendport) { |
926 | a = (char *)&data_addr.sin_addr; | |
927 | p = (char *)&data_addr.sin_port; | |
e0b077fe | 928 | #define UC(b) (((int)b)&0xff) |
5ac6fc46 SL |
929 | result = |
930 | command("PORT %d,%d,%d,%d,%d,%d", | |
931 | UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), | |
932 | UC(p[0]), UC(p[1])); | |
933 | if (result == ERROR && sendport == -1) { | |
934 | sendport = 0; | |
9069f68e | 935 | tmpno = 1; |
5ac6fc46 SL |
936 | goto noport; |
937 | } | |
938 | return (result != COMPLETE); | |
939 | } | |
98c50518 | 940 | if (tmpno) |
9069f68e | 941 | sendport = 1; |
5ac6fc46 | 942 | return (0); |
e0b077fe SL |
943 | bad: |
944 | (void) close(data), data = -1; | |
98c50518 | 945 | if (tmpno) |
9069f68e | 946 | sendport = 1; |
e0b077fe SL |
947 | return (1); |
948 | } | |
949 | ||
950 | FILE * | |
951 | dataconn(mode) | |
952 | char *mode; | |
953 | { | |
954 | struct sockaddr_in from; | |
955 | int s, fromlen = sizeof (from); | |
956 | ||
04480325 | 957 | s = accept(data, (struct sockaddr *) &from, &fromlen); |
e0b077fe SL |
958 | if (s < 0) { |
959 | perror("ftp: accept"); | |
960 | (void) close(data), data = -1; | |
961 | return (NULL); | |
962 | } | |
963 | (void) close(data); | |
964 | data = s; | |
965 | return (fdopen(data, mode)); | |
966 | } | |
967 | ||
9069f68e GM |
968 | ptransfer(direction, bytes, t0, t1, local, remote) |
969 | char *direction, *local, *remote; | |
5ac6fc46 | 970 | long bytes; |
e0b077fe SL |
971 | struct timeval *t0, *t1; |
972 | { | |
973 | struct timeval td; | |
6ee561e3 | 974 | float s, bs; |
e0b077fe SL |
975 | |
976 | tvsub(&td, t1, t0); | |
6ee561e3 | 977 | s = td.tv_sec + (td.tv_usec / 1000000.); |
e0b077fe | 978 | #define nz(x) ((x) == 0 ? 1 : (x)) |
6ee561e3 | 979 | bs = bytes / nz(s); |
98c50518 | 980 | if (local && *local != '-') |
9069f68e | 981 | printf("local: %s ", local); |
98c50518 | 982 | if (remote) |
9069f68e | 983 | printf("remote: %s\n", remote); |
6ee561e3 CL |
984 | printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", |
985 | bytes, direction, s, bs / 1024.); | |
e0b077fe SL |
986 | } |
987 | ||
04480325 | 988 | /*tvadd(tsum, t0) |
e0b077fe SL |
989 | struct timeval *tsum, *t0; |
990 | { | |
991 | ||
992 | tsum->tv_sec += t0->tv_sec; | |
993 | tsum->tv_usec += t0->tv_usec; | |
994 | if (tsum->tv_usec > 1000000) | |
995 | tsum->tv_sec++, tsum->tv_usec -= 1000000; | |
04480325 | 996 | } */ |
e0b077fe SL |
997 | |
998 | tvsub(tdiff, t1, t0) | |
999 | struct timeval *tdiff, *t1, *t0; | |
1000 | { | |
1001 | ||
1002 | tdiff->tv_sec = t1->tv_sec - t0->tv_sec; | |
1003 | tdiff->tv_usec = t1->tv_usec - t0->tv_usec; | |
1004 | if (tdiff->tv_usec < 0) | |
1005 | tdiff->tv_sec--, tdiff->tv_usec += 1000000; | |
1006 | } | |
9069f68e GM |
1007 | |
1008 | psabort() | |
1009 | { | |
1010 | extern int abrtflag; | |
1011 | ||
1012 | abrtflag++; | |
1013 | } | |
1014 | ||
1015 | pswitch(flag) | |
1016 | int flag; | |
1017 | { | |
1018 | extern int proxy, abrtflag; | |
1019 | int (*oldintr)(); | |
1020 | static struct comvars { | |
1021 | int connect; | |
f2cc6cbf | 1022 | char name[MAXHOSTNAMELEN]; |
9069f68e GM |
1023 | struct sockaddr_in mctl; |
1024 | struct sockaddr_in hctl; | |
1025 | FILE *in; | |
1026 | FILE *out; | |
9069f68e GM |
1027 | int tpe; |
1028 | int cpnd; | |
1029 | int sunqe; | |
1030 | int runqe; | |
1031 | int mcse; | |
1032 | int ntflg; | |
1033 | char nti[17]; | |
1034 | char nto[17]; | |
1035 | int mapflg; | |
1036 | char mi[MAXPATHLEN]; | |
1037 | char mo[MAXPATHLEN]; | |
1038 | } proxstruct, tmpstruct; | |
1039 | struct comvars *ip, *op; | |
1040 | ||
1041 | abrtflag = 0; | |
1042 | oldintr = signal(SIGINT, psabort); | |
1043 | if (flag) { | |
98c50518 | 1044 | if (proxy) |
9069f68e | 1045 | return; |
9069f68e GM |
1046 | ip = &tmpstruct; |
1047 | op = &proxstruct; | |
1048 | proxy++; | |
1049 | } | |
1050 | else { | |
98c50518 | 1051 | if (!proxy) |
9069f68e | 1052 | return; |
9069f68e GM |
1053 | ip = &proxstruct; |
1054 | op = &tmpstruct; | |
1055 | proxy = 0; | |
1056 | } | |
1057 | ip->connect = connected; | |
1058 | connected = op->connect; | |
f2cc6cbf MK |
1059 | if (hostname) { |
1060 | (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); | |
1061 | ip->name[strlen(ip->name)] = '\0'; | |
1062 | } else | |
1063 | ip->name[0] = 0; | |
9069f68e GM |
1064 | hostname = op->name; |
1065 | ip->hctl = hisctladdr; | |
1066 | hisctladdr = op->hctl; | |
1067 | ip->mctl = myctladdr; | |
1068 | myctladdr = op->mctl; | |
1069 | ip->in = cin; | |
1070 | cin = op->in; | |
1071 | ip->out = cout; | |
1072 | cout = op->out; | |
9069f68e GM |
1073 | ip->tpe = type; |
1074 | type = op->tpe; | |
98c50518 | 1075 | if (!type) |
9069f68e | 1076 | type = 1; |
9069f68e GM |
1077 | ip->cpnd = cpend; |
1078 | cpend = op->cpnd; | |
1079 | ip->sunqe = sunique; | |
1080 | sunique = op->sunqe; | |
1081 | ip->runqe = runique; | |
1082 | runique = op->runqe; | |
1083 | ip->mcse = mcase; | |
1084 | mcase = op->mcse; | |
1085 | ip->ntflg = ntflag; | |
1086 | ntflag = op->ntflg; | |
04480325 | 1087 | (void) strncpy(ip->nti, ntin, 16); |
9069f68e | 1088 | (ip->nti)[strlen(ip->nti)] = '\0'; |
04480325 GM |
1089 | (void) strcpy(ntin, op->nti); |
1090 | (void) strncpy(ip->nto, ntout, 16); | |
9069f68e | 1091 | (ip->nto)[strlen(ip->nto)] = '\0'; |
04480325 | 1092 | (void) strcpy(ntout, op->nto); |
9069f68e GM |
1093 | ip->mapflg = mapflag; |
1094 | mapflag = op->mapflg; | |
04480325 | 1095 | (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); |
9069f68e | 1096 | (ip->mi)[strlen(ip->mi)] = '\0'; |
04480325 GM |
1097 | (void) strcpy(mapin, op->mi); |
1098 | (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); | |
9069f68e | 1099 | (ip->mo)[strlen(ip->mo)] = '\0'; |
04480325 | 1100 | (void) strcpy(mapout, op->mo); |
9069f68e GM |
1101 | (void) signal(SIGINT, oldintr); |
1102 | if (abrtflag) { | |
1103 | abrtflag = 0; | |
1104 | (*oldintr)(); | |
98c50518 | 1105 | } |
9069f68e GM |
1106 | } |
1107 | ||
1108 | jmp_buf ptabort; | |
1109 | int ptabflg; | |
1110 | ||
1111 | abortpt() | |
1112 | { | |
1113 | printf("\n"); | |
04480325 | 1114 | (void) fflush(stdout); |
9069f68e GM |
1115 | ptabflg++; |
1116 | mflag = 0; | |
1117 | abrtflag = 0; | |
1118 | longjmp(ptabort, 1); | |
1119 | } | |
1120 | ||
1121 | proxtrans(cmd, local, remote) | |
1122 | char *cmd, *local, *remote; | |
1123 | { | |
bd9f17de | 1124 | int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; |
9069f68e GM |
1125 | extern jmp_buf ptabort; |
1126 | char *cmd2; | |
04480325 | 1127 | struct fd_set mask; |
9069f68e | 1128 | |
98c50518 | 1129 | if (strcmp(cmd, "RETR")) |
9069f68e | 1130 | cmd2 = "RETR"; |
98c50518 | 1131 | else |
9069f68e | 1132 | cmd2 = runique ? "STOU" : "STOR"; |
9069f68e GM |
1133 | if (command("PASV") != COMPLETE) { |
1134 | printf("proxy server does not support third part transfers.\n"); | |
1135 | return; | |
1136 | } | |
1137 | tmptype = type; | |
1138 | pswitch(0); | |
1139 | if (!connected) { | |
1140 | printf("No primary connection\n"); | |
1141 | pswitch(1); | |
1142 | code = -1; | |
1143 | return; | |
1144 | } | |
1145 | if (type != tmptype) { | |
1146 | oldtype = type; | |
1147 | switch (tmptype) { | |
1148 | case TYPE_A: | |
1149 | setascii(); | |
1150 | break; | |
1151 | case TYPE_I: | |
1152 | setbinary(); | |
1153 | break; | |
1154 | case TYPE_E: | |
1155 | setebcdic(); | |
1156 | break; | |
1157 | case TYPE_L: | |
1158 | settenex(); | |
1159 | break; | |
1160 | } | |
1161 | } | |
1162 | if (command("PORT %s", pasv) != COMPLETE) { | |
1163 | switch (oldtype) { | |
1164 | case 0: | |
1165 | break; | |
1166 | case TYPE_A: | |
1167 | setascii(); | |
1168 | break; | |
1169 | case TYPE_I: | |
1170 | setbinary(); | |
1171 | break; | |
1172 | case TYPE_E: | |
1173 | setebcdic(); | |
1174 | break; | |
1175 | case TYPE_L: | |
1176 | settenex(); | |
1177 | break; | |
1178 | } | |
1179 | pswitch(1); | |
1180 | return; | |
1181 | } | |
98c50518 | 1182 | if (setjmp(ptabort)) |
9069f68e | 1183 | goto abort; |
9069f68e GM |
1184 | oldintr = signal(SIGINT, abortpt); |
1185 | if (command("%s %s", cmd, remote) != PRELIM) { | |
1186 | (void) signal(SIGINT, oldintr); | |
1187 | switch (oldtype) { | |
1188 | case 0: | |
1189 | break; | |
1190 | case TYPE_A: | |
1191 | setascii(); | |
1192 | break; | |
1193 | case TYPE_I: | |
1194 | setbinary(); | |
1195 | break; | |
1196 | case TYPE_E: | |
1197 | setebcdic(); | |
1198 | break; | |
1199 | case TYPE_L: | |
1200 | settenex(); | |
1201 | break; | |
1202 | } | |
1203 | pswitch(1); | |
1204 | return; | |
1205 | } | |
1206 | sleep(2); | |
1207 | pswitch(1); | |
1208 | secndflag++; | |
98c50518 | 1209 | if (command("%s %s", cmd2, local) != PRELIM) |
9069f68e | 1210 | goto abort; |
9069f68e GM |
1211 | ptflag++; |
1212 | (void) getreply(0); | |
1213 | pswitch(0); | |
1214 | (void) getreply(0); | |
1215 | (void) signal(SIGINT, oldintr); | |
1216 | switch (oldtype) { | |
1217 | case 0: | |
1218 | break; | |
1219 | case TYPE_A: | |
1220 | setascii(); | |
1221 | break; | |
1222 | case TYPE_I: | |
1223 | setbinary(); | |
1224 | break; | |
1225 | case TYPE_E: | |
1226 | setebcdic(); | |
1227 | break; | |
1228 | case TYPE_L: | |
1229 | settenex(); | |
1230 | break; | |
1231 | } | |
1232 | pswitch(1); | |
1233 | ptflag = 0; | |
1234 | printf("local: %s remote: %s\n", local, remote); | |
1235 | return; | |
1236 | abort: | |
1237 | (void) signal(SIGINT, SIG_IGN); | |
1238 | ptflag = 0; | |
98c50518 | 1239 | if (strcmp(cmd, "RETR") && !proxy) |
9069f68e | 1240 | pswitch(1); |
98c50518 | 1241 | else if (!strcmp(cmd, "RETR") && proxy) |
9069f68e | 1242 | pswitch(0); |
9069f68e GM |
1243 | if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ |
1244 | if (command("%s %s", cmd2, local) != PRELIM) { | |
1245 | pswitch(0); | |
1246 | switch (oldtype) { | |
1247 | case 0: | |
1248 | break; | |
1249 | case TYPE_A: | |
1250 | setascii(); | |
1251 | break; | |
1252 | case TYPE_I: | |
1253 | setbinary(); | |
1254 | break; | |
1255 | case TYPE_E: | |
1256 | setebcdic(); | |
1257 | break; | |
1258 | case TYPE_L: | |
1259 | settenex(); | |
1260 | break; | |
1261 | } | |
bd9f17de | 1262 | if (cpend) { |
9069f68e GM |
1263 | char msg[2]; |
1264 | ||
1265 | fprintf(cout,"%c%c",IAC,IP); | |
1266 | (void) fflush(cout); | |
1267 | *msg = IAC; | |
1268 | *(msg+1) = DM; | |
98c50518 | 1269 | if (send(fileno(cout),msg,2,MSG_OOB) != 2) |
9069f68e | 1270 | perror("abort"); |
9069f68e GM |
1271 | fprintf(cout,"ABOR\r\n"); |
1272 | (void) fflush(cout); | |
bd9f17de | 1273 | FD_ZERO(&mask); |
04480325 | 1274 | FD_SET(fileno(cin), &mask); |
bd9f17de GM |
1275 | if ((nfnd = empty(&mask,10)) <= 0) { |
1276 | if (nfnd < 0) { | |
1277 | perror("abort"); | |
1278 | } | |
98c50518 | 1279 | if (ptabflg) |
9069f68e | 1280 | code = -1; |
9069f68e GM |
1281 | lostpeer(); |
1282 | } | |
1283 | (void) getreply(0); | |
1284 | (void) getreply(0); | |
1285 | } | |
1286 | } | |
1287 | pswitch(1); | |
98c50518 | 1288 | if (ptabflg) |
9069f68e | 1289 | code = -1; |
9069f68e GM |
1290 | (void) signal(SIGINT, oldintr); |
1291 | return; | |
1292 | } | |
bd9f17de | 1293 | if (cpend) { |
9069f68e GM |
1294 | char msg[2]; |
1295 | ||
1296 | fprintf(cout,"%c%c",IAC,IP); | |
1297 | (void) fflush(cout); | |
1298 | *msg = IAC; | |
1299 | *(msg+1) = DM; | |
98c50518 | 1300 | if (send(fileno(cout),msg,2,MSG_OOB) != 2) |
9069f68e | 1301 | perror("abort"); |
9069f68e GM |
1302 | fprintf(cout,"ABOR\r\n"); |
1303 | (void) fflush(cout); | |
bd9f17de | 1304 | FD_ZERO(&mask); |
04480325 | 1305 | FD_SET(fileno(cin), &mask); |
bd9f17de GM |
1306 | if ((nfnd = empty(&mask,10)) <= 0) { |
1307 | if (nfnd < 0) { | |
1308 | perror("abort"); | |
1309 | } | |
98c50518 | 1310 | if (ptabflg) |
9069f68e | 1311 | code = -1; |
9069f68e GM |
1312 | lostpeer(); |
1313 | } | |
1314 | (void) getreply(0); | |
1315 | (void) getreply(0); | |
1316 | } | |
1317 | pswitch(!proxy); | |
1318 | if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ | |
1319 | if (command("%s %s", cmd2, local) != PRELIM) { | |
1320 | pswitch(0); | |
1321 | switch (oldtype) { | |
1322 | case 0: | |
1323 | break; | |
1324 | case TYPE_A: | |
1325 | setascii(); | |
1326 | break; | |
1327 | case TYPE_I: | |
1328 | setbinary(); | |
1329 | break; | |
1330 | case TYPE_E: | |
1331 | setebcdic(); | |
1332 | break; | |
1333 | case TYPE_L: | |
1334 | settenex(); | |
1335 | break; | |
1336 | } | |
bd9f17de | 1337 | if (cpend) { |
9069f68e GM |
1338 | char msg[2]; |
1339 | ||
1340 | fprintf(cout,"%c%c",IAC,IP); | |
1341 | (void) fflush(cout); | |
1342 | *msg = IAC; | |
1343 | *(msg+1) = DM; | |
98c50518 | 1344 | if (send(fileno(cout),msg,2,MSG_OOB) != 2) |
9069f68e | 1345 | perror("abort"); |
9069f68e GM |
1346 | fprintf(cout,"ABOR\r\n"); |
1347 | (void) fflush(cout); | |
bd9f17de | 1348 | FD_ZERO(&mask); |
04480325 | 1349 | FD_SET(fileno(cin), &mask); |
bd9f17de GM |
1350 | if ((nfnd = empty(&mask,10)) <= 0) { |
1351 | if (nfnd < 0) { | |
1352 | perror("abort"); | |
1353 | } | |
98c50518 | 1354 | if (ptabflg) |
9069f68e | 1355 | code = -1; |
9069f68e GM |
1356 | lostpeer(); |
1357 | } | |
1358 | (void) getreply(0); | |
1359 | (void) getreply(0); | |
1360 | } | |
1361 | pswitch(1); | |
98c50518 | 1362 | if (ptabflg) |
9069f68e | 1363 | code = -1; |
9069f68e GM |
1364 | (void) signal(SIGINT, oldintr); |
1365 | return; | |
1366 | } | |
1367 | } | |
bd9f17de | 1368 | if (cpend) { |
9069f68e GM |
1369 | char msg[2]; |
1370 | ||
1371 | fprintf(cout,"%c%c",IAC,IP); | |
1372 | (void) fflush(cout); | |
1373 | *msg = IAC; | |
1374 | *(msg+1) = DM; | |
98c50518 | 1375 | if (send(fileno(cout),msg,2,MSG_OOB) != 2) |
9069f68e | 1376 | perror("abort"); |
9069f68e GM |
1377 | fprintf(cout,"ABOR\r\n"); |
1378 | (void) fflush(cout); | |
bd9f17de | 1379 | FD_ZERO(&mask); |
04480325 | 1380 | FD_SET(fileno(cin), &mask); |
bd9f17de GM |
1381 | if ((nfnd = empty(&mask,10)) <= 0) { |
1382 | if (nfnd < 0) { | |
1383 | perror("abort"); | |
1384 | } | |
98c50518 | 1385 | if (ptabflg) |
9069f68e | 1386 | code = -1; |
9069f68e GM |
1387 | lostpeer(); |
1388 | } | |
1389 | (void) getreply(0); | |
1390 | (void) getreply(0); | |
1391 | } | |
1392 | pswitch(!proxy); | |
1393 | if (cpend) { | |
bd9f17de | 1394 | FD_ZERO(&mask); |
04480325 | 1395 | FD_SET(fileno(cin), &mask); |
bd9f17de GM |
1396 | if ((nfnd = empty(&mask,10)) <= 0) { |
1397 | if (nfnd < 0) { | |
1398 | perror("abort"); | |
1399 | } | |
98c50518 | 1400 | if (ptabflg) |
9069f68e | 1401 | code = -1; |
9069f68e GM |
1402 | lostpeer(); |
1403 | } | |
1404 | (void) getreply(0); | |
1405 | (void) getreply(0); | |
1406 | } | |
98c50518 | 1407 | if (proxy) |
9069f68e | 1408 | pswitch(0); |
9069f68e GM |
1409 | switch (oldtype) { |
1410 | case 0: | |
1411 | break; | |
1412 | case TYPE_A: | |
1413 | setascii(); | |
1414 | break; | |
1415 | case TYPE_I: | |
1416 | setbinary(); | |
1417 | break; | |
1418 | case TYPE_E: | |
1419 | setebcdic(); | |
1420 | break; | |
1421 | case TYPE_L: | |
1422 | settenex(); | |
1423 | break; | |
1424 | } | |
1425 | pswitch(1); | |
98c50518 | 1426 | if (ptabflg) |
9069f68e | 1427 | code = -1; |
9069f68e GM |
1428 | (void) signal(SIGINT, oldintr); |
1429 | } | |
1430 | ||
1431 | reset() | |
1432 | { | |
04480325 GM |
1433 | struct fd_set mask; |
1434 | int nfnd = 1; | |
9069f68e | 1435 | |
bd9f17de | 1436 | FD_ZERO(&mask); |
04480325 GM |
1437 | while (nfnd) { |
1438 | FD_SET(fileno(cin), &mask); | |
bd9f17de | 1439 | if ((nfnd = empty(&mask,0)) < 0) { |
9069f68e GM |
1440 | perror("reset"); |
1441 | code = -1; | |
1442 | lostpeer(); | |
1443 | } | |
bd9f17de | 1444 | else if (nfnd) { |
9069f68e | 1445 | (void) getreply(0); |
04480325 | 1446 | } |
9069f68e GM |
1447 | } |
1448 | } | |
1449 | ||
1450 | char * | |
1451 | gunique(local) | |
1452 | char *local; | |
1453 | { | |
1454 | static char new[MAXPATHLEN]; | |
1455 | char *cp = rindex(local, '/'); | |
1456 | int d, count=0; | |
1457 | char ext = '1'; | |
1458 | ||
98c50518 | 1459 | if (cp) |
9069f68e | 1460 | *cp = '\0'; |
9069f68e | 1461 | d = access(cp ? local : ".", 2); |
98c50518 | 1462 | if (cp) |
9069f68e | 1463 | *cp = '/'; |
9069f68e GM |
1464 | if (d < 0) { |
1465 | perror(local); | |
1466 | return((char *) 0); | |
1467 | } | |
1468 | (void) strcpy(new, local); | |
1469 | cp = new + strlen(new); | |
1470 | *cp++ = '.'; | |
1471 | while (!d) { | |
1472 | if (++count == 100) { | |
1473 | printf("runique: can't find unique file name.\n"); | |
1474 | return((char *) 0); | |
1475 | } | |
1476 | *cp++ = ext; | |
1477 | *cp = '\0'; | |
98c50518 | 1478 | if (ext == '9') |
9069f68e | 1479 | ext = '0'; |
98c50518 | 1480 | else |
9069f68e | 1481 | ext++; |
98c50518 | 1482 | if ((d = access(new, 0)) < 0) |
9069f68e | 1483 | break; |
98c50518 | 1484 | if (ext != '0') |
9069f68e | 1485 | cp--; |
98c50518 | 1486 | else if (*(cp - 2) == '.') |
9069f68e | 1487 | *(cp - 1) = '1'; |
9069f68e GM |
1488 | else { |
1489 | *(cp - 2) = *(cp - 2) + 1; | |
1490 | cp--; | |
1491 | } | |
1492 | } | |
1493 | return(new); | |
1494 | } |