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