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