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