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