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