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