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