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