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