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