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