xref: /reactos/base/applications/network/ftp/ftp.c (revision 018ba0f7)
1 /*
2  * Copyright (c) 1985, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #include "precomp.h"
19 
20 #include <signal.h>
21 
22 #define L_SET SEEK_SET
23 #define L_INCR SEEK_CUR
24 #define caddr_t void *
25 
26 #ifndef lint
27 static char sccsid[] = "@(#)ftp.c	5.28 (Berkeley) 4/20/89";
28 #endif /* not lint */
29 
30 #ifndef MAXHOSTNAMELEN
31 #define MAXHOSTNAMELEN 64
32 #endif
33 
34 #ifdef NOVFPRINTF
35 #define vfprintf(a,b,c) _doprnt(b,c,a)
36 #endif
37 
38 #ifdef sun
39 /* FD_SET wasn't defined until 4.0. its a cheap test for uid_t  presence */
40 #ifndef FD_SET
41 #define	NBBY	8		/* number of bits in a byte */
42 /*
43  * Select uses bit masks of file descriptors in longs.
44  * These macros manipulate such bit fields (the filesystem macros use chars).
45  * FD_SETSIZE may be defined by the user, but the default here
46  * should be >= NOFILE (param.h).
47  */
48 #ifndef	FD_SETSIZE
49 #define	FD_SETSIZE	256
50 #endif
51 
52 typedef long	fd_mask;
53 #define NFDBITS	(sizeof(fd_mask) * NBBY)	/* bits per mask */
54 #ifndef howmany
55 #define	howmany(x, y)	(((x)+((y)-1))/(y))
56 #endif
57 
58 #define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
59 #define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
60 #define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
61 #define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
62 
63 typedef int uid_t;
64 typedef int gid_t;
65 #endif
66 #endif
67 
68 struct	sockaddr_in hisctladdr;
69 struct	sockaddr_in data_addr;
70 int	data = -1;
71 int	abrtflag = 0;
72 int	ptflag = 0;
73 int	allbinary;
74 struct	sockaddr_in myctladdr;
75 uid_t	getuid();
76 #ifdef __REACTOS__
77 void lostpeer(void);
78 #else
79 sig_t	lostpeer();
80 #endif
81 off_t	restart_point = 0;
82 
83 SOCKET cin, cout;
84 int	dataconn(const char *mode);
85 
86 int command(const char *fmt, ...);
87 
88 char *hostname;
89 
90 typedef void (*Sig_t)(int);
91 
92 // Signal Handlers
93 
94 void psabort(int sig);
95 
hookup(const char * host,int port)96 char *hookup(const char *host, int port)
97 {
98 	register struct hostent *hp = 0;
99 	int len;
100 	SOCKET s;
101 	static char hostnamebuf[80];
102 
103 	bzero((char *)&hisctladdr, sizeof (hisctladdr));
104 	hisctladdr.sin_addr.s_addr = inet_addr(host);
105 	if (hisctladdr.sin_addr.s_addr != (unsigned long)-1) {
106 		hisctladdr.sin_family = AF_INET;
107 		(void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
108 	} else {
109 		hp = gethostbyname(host);
110 		if (hp == NULL) {
111 			fprintf(stderr, "ftp: %s: ", host);
112 			herror((char *)NULL);
113 			code = -1;
114 			return((char *) 0);
115 		}
116 		hisctladdr.sin_family = hp->h_addrtype;
117 		bcopy(hp->h_addr_list[0],
118 			 (caddr_t)&hisctladdr.sin_addr, hp->h_length);
119 		(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
120 	}
121 	hostname = hostnamebuf;
122 	s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
123 	if (s == INVALID_SOCKET) {
124 		perror("ftp: socket");
125 		code = -1;
126 		return (0);
127 	}
128 	hisctladdr.sin_port = port;
129 	while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
130 		if (hp && hp->h_addr_list[1]) {
131 			int oerrno = errno;
132 
133 			fprintf(stderr, "ftp: connect to address %s: ",
134 				inet_ntoa(hisctladdr.sin_addr));
135 			errno = oerrno;
136 			perror((char *) 0);
137 			hp->h_addr_list++;
138 			bcopy(hp->h_addr_list[0],
139 			     (caddr_t)&hisctladdr.sin_addr, hp->h_length);
140 			fprintf(stdout, "Trying %s...\n",
141 				inet_ntoa(hisctladdr.sin_addr));
142 			(void) fflush(stdout);
143 			(void) close(s);
144 			s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
145 			if (s == INVALID_SOCKET) {
146 				perror("ftp: socket");
147 				code = -1;
148 				return (0);
149 			}
150 			continue;
151 		}
152 		perror("ftp: connect");
153 		code = -1;
154 		goto bad;
155 	}
156 	len = sizeof (myctladdr);
157 	if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
158 		perror("ftp: getsockname");
159 		code = -1;
160 		goto bad;
161 	}
162 	cin = cout = s;
163 	if (verbose) {
164 		printf("Connected to %s.\n", hostname);
165 		(void) fflush(stdout);
166 	}
167 	if (getreply(0) > 2) { 	/* read startup message from server */
168 		closesocket(cin);
169 		code = -1;
170 		goto bad;
171 	}
172 #ifdef SO_OOBINLINE
173 	{
174 	int on = 1;
175 
176 	if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (const char *) &on, sizeof(on))
177 		< 0 && debug) {
178 			perror("ftp: setsockopt");
179 		}
180 	}
181 #endif //SO_OOBINLINE
182 
183 	return (hostname);
184 bad:
185 	(void) close(s);
186 	return ((char *)0);
187 }
188 
login(const char * host)189 int login(const char *host)
190 {
191 	char tmp[80];
192 	char *puser, *ppass, *pacct;
193 	const char *user, *pass, *acct;
194 	int n, aflag = 0;
195 
196 	user = pass = acct = 0;
197 	n = ruserpass(host, &puser, &ppass, &pacct);
198 	if (n < 0) {
199 		code = -1;
200 		return(0);
201 	}
202 	if (0 != n) {
203 		user = puser;
204 		pass = ppass;
205 		acct = pacct;
206 	}
207 	while (user == NULL) {
208 		const char *myname = "none"; // This needs to become the username env
209 
210 		if (myname)
211 			printf("Name (%s:%s): ", host, myname);
212 		else
213 			printf("Name (%s): ", host);
214 		(void) fflush(stdout);
215 		(void) fgets(tmp, sizeof(tmp) - 1, stdin);
216 		tmp[strlen(tmp) - 1] = '\0';
217 		if (*tmp == '\0')
218 			user = myname;
219 		else
220 			user = tmp;
221 	}
222 	n = command("USER %s", user);
223 	if (n == CONTINUE) {
224 		if (pass == NULL)
225 			pass = getpass("Password:");
226 		n = command("PASS %s", pass);
227 		fflush(stdin);
228 	}
229 	if (n == CONTINUE) {
230 		aflag++;
231 		acct = getpass("Account:");
232 		n = command("ACCT %s", acct);
233 	}
234 	if (n != COMPLETE) {
235 		fprintf(stderr, "Login failed.\n");
236 		return (0);
237 	}
238 	if (!aflag && acct != NULL)
239 		(void) command("ACCT %s", acct);
240 	if (proxy)
241 		return(1);
242 	for (n = 0; n < macnum; ++n) {
243 		if (!strcmp("init", macros[n].mac_name)) {
244 			(void) strcpy(line, "$init");
245 			makeargv();
246 			domacro(margc, margv);
247 			break;
248 		}
249 	}
250 	return (1);
251 }
252 
253 static void
cmdabort(int sig)254 cmdabort(int sig)
255 {
256 	extern jmp_buf ptabort;
257 
258 	printf("\n");
259 	(void) fflush(stdout);
260 	abrtflag++;
261 	if (ptflag)
262 		longjmp(ptabort,1);
263 }
264 
265 /*VARARGS1*/
command(const char * fmt,...)266 int command(const char *fmt, ...)
267 {
268 	va_list ap;
269 	int r;
270 	void (*oldintr)(int);
271 
272 	abrtflag = 0;
273 	if (debug) {
274 		printf("---> ");
275 		va_start(ap, fmt);
276 		vfprintf(stdout, fmt, ap);
277 		va_end(ap);
278 		printf("\n");
279 		(void) fflush(stdout);
280 	}
281 	if (cout == 0) {
282 		perror ("No control connection for command");
283 		code = -1;
284 		return (0);
285 	}
286 	oldintr = signal(SIGINT,cmdabort);
287 	{
288 		char buffer[1024];
289 
290 		va_start(ap, fmt);
291 		vsprintf(buffer, fmt, ap);
292 		va_end(ap);
293 //DLJ: to work through  firewalls - send the command as a single message
294 		strcat(buffer,"\r\n");
295 		fprintfSocket(cout, buffer);
296 	}
297 //DLJ: the following two lines are replaced by the strcat above - seems to
298 // make it work through firewalls.
299 //	fprintfSocket(cout, "\r\n");
300 //	(void) fflush(cout);
301 	cpend = 1;
302 	r = getreply(!strcmp(fmt, "QUIT"));
303 	if (abrtflag && oldintr != SIG_IGN)
304 		(*oldintr)(SIGINT);
305 //	(void) signal(SIGINT, oldintr);
306 	return(r);
307 }
308 
309 char reply_string[BUFSIZ];		/* last line of previous reply */
310 
311 #include <ctype.h>
312 
313 int
getreply(expecteof)314 getreply(expecteof)
315 	int expecteof;
316 {
317 	register int c, n;
318 	register int dig;
319 	register char *cp;
320 	int originalcode = 0, continuation = 0;
321 	void (*oldintr)(int);
322 	int pflag = 0;
323 	char *pt = pasv;
324 
325 	oldintr = signal(SIGINT,cmdabort);
326 	for (;;) {
327 		dig = n = code = 0;
328 		cp = reply_string;
329 		while ((c = fgetcSocket(cin)) != '\n') {
330 			if (c == IAC) {     /* handle telnet commands */
331 				switch (fgetcSocket(cin)) {
332 				case WILL:
333 				case WONT:
334 					c = fgetcSocket(cin);
335 					fprintfSocket(cout, "%c%c%c",IAC,DONT,c);
336 					break;
337 				case DO:
338 				case DONT:
339 					c = fgetcSocket(cin);
340 					fprintfSocket(cout, "%c%c%c",IAC,WONT,c);
341 					break;
342 				default:
343 					break;
344 				}
345 				continue;
346 			}
347 			dig++;
348 			if (c == EOF) {
349 				if (expecteof) {
350 //					(void) signal(SIGINT,oldintr);
351 					code = 221;
352 					return (0);
353 				}
354 				lostpeer();
355 				if (verbose) {
356 					printf("421 Service not available, remote server has closed connection\n");
357 					(void) fflush(stdout);
358 				}
359 				code = 421;
360 				return(4);
361 			}
362 			if (c != '\r' && (verbose > 0 ||
363 			    (verbose > -1 && n == '5' && dig > 4))) {
364 				if (proxflag &&
365 				   ((dig == 1 || dig == 5) && verbose == 0))
366 					printf("%s:",hostname);
367 				(void) putchar(c);
368 				(void) fflush(stdout);
369 			}
370 			if (dig < 4 && isdigit(c))
371 				code = code * 10 + (c - '0');
372 			if (!pflag && code == 227)
373 				pflag = 1;
374 			if (dig > 4 && pflag == 1 && isdigit(c))
375 				pflag = 2;
376 			if (pflag == 2) {
377 				if (c != '\r' && c != ')')
378 					*pt++ = c;
379 				else {
380 					*pt = '\0';
381 					pflag = 3;
382 				}
383 			}
384 			if (dig == 4 && c == '-') {
385 				if (continuation)
386 					code = 0;
387 				continuation++;
388 			}
389 			if (n == 0)
390 				n = c;
391 			if (cp < &reply_string[sizeof(reply_string) - 1])
392 				*cp++ = c;
393 		}
394 		if (verbose > 0 || (verbose > -1 && n == '5')) {
395 			(void) putchar(c);
396 			(void) fflush (stdout);
397 		}
398 		if (continuation && code != originalcode) {
399 			if (originalcode == 0)
400 				originalcode = code;
401 			continue;
402 		}
403 		*cp = '\0';
404 		if (n != '1')
405 			cpend = 0;
406 		(void) signal(SIGINT,oldintr);
407 		if (code == 421 || originalcode == 421)
408 			lostpeer();
409 		if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
410 			(*oldintr)(SIGINT);
411 		return (n - '0');
412 	}
413 }
414 
415 static int
empty(mask,sec)416 empty(mask, sec)
417 	struct fd_set *mask;
418 	int sec;
419 {
420 	struct timeval t;
421 
422 	t.tv_sec = (long) sec;
423 	t.tv_usec = 0;
424 	return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
425 }
426 
427 jmp_buf	sendabort;
428 
429 #if 0
430 void abortsend()
431 {
432 
433 	mflag = 0;
434 	abrtflag = 0;
435 	printf("\nsend aborted\n");
436 	(void) fflush(stdout);
437 	longjmp(sendabort, 1);
438 }
439 #endif
440 
441 #define HASHBYTES 1024
442 
sendrequest(const char * cmd,const char * local,const char * remote,int printnames)443 void sendrequest(const char *cmd, const char *local, const char *remote, int printnames)
444 {
445 	FILE *fin;
446 	int dout = 0;
447 	int (*closefunc)();
448 	sig_t (*oldintr)(), (*oldintp)();
449 	char buf[BUFSIZ], *bufp;
450 	long bytes = 0, hashbytes = HASHBYTES;
451 	register int c, d;
452 	struct stat st;
453 	struct timeval start, stop;
454 	const char *mode;
455 
456 	if (verbose && printnames) {
457 		if (local && *local != '-')
458 			printf("local: %s ", local);
459 		if (remote)
460 			printf("remote: %s\n", remote);
461 		(void) fflush(stdout);
462 	}
463 	if (proxy) {
464 		proxtrans(cmd, local, remote);
465 		return;
466 	}
467 	closefunc = NULL;
468 	oldintr = NULL;
469 	oldintp = NULL;
470 	mode = "w";
471 	if (setjmp(sendabort)) {
472 		while (cpend) {
473 			(void) getreply(0);
474 		}
475 		if (data >= 0) {
476 			(void) close(data);
477 			data = -1;
478 		}
479 		if (oldintr)
480 null();//			(void) signal(SIGINT,oldintr);
481 		if (oldintp)
482 null();//			(void) signal(SIGPIPE,oldintp);
483 		code = -1;
484 		return;
485 	}
486 null();//	oldintr = signal(SIGINT, abortsend);
487 	if (strcmp(local, "-") == 0)
488 		fin = stdin;
489 	else if (*local == '|') {
490 null();//		oldintp = signal(SIGPIPE,SIG_IGN);
491 		fin = _popen(local + 1, "r");
492 		if (fin == NULL) {
493 			perror(local + 1);
494 null();//			(void) signal(SIGINT, oldintr);
495 null();//			(void) signal(SIGPIPE, oldintp);
496 			code = -1;
497 			return;
498 		}
499 		closefunc = _pclose;
500 	} else {
501 		fin = fopen(local, "r");
502 		if (fin == NULL) {
503 			perror(local);
504 null();//			(void) signal(SIGINT, oldintr);
505 			code = -1;
506 			return;
507 		}
508 		closefunc = fclose;
509 		if (fstat(fileno(fin), &st) < 0 ||
510 		    (st.st_mode&S_IFMT) != S_IFREG) {
511 			fprintf(stdout, "%s: not a plain file.\n", local);
512 			(void) fflush(stdout);
513 null();//			(void) signal(SIGINT, oldintr);
514 			fclose(fin);
515 			code = -1;
516 			return;
517 		}
518 	}
519 	if (initconn()) {
520 null();//		(void) signal(SIGINT, oldintr);
521 		if (oldintp)
522 null();//			(void) signal(SIGPIPE, oldintp);
523 		code = -1;
524 		if (closefunc != NULL)
525 			(*closefunc)(fin);
526 		return;
527 	}
528 	if (setjmp(sendabort))
529 		goto abort;
530 
531 	if (restart_point &&
532 	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
533 		if (fseek(fin, (long) restart_point, 0) < 0) {
534 			perror(local);
535 			restart_point = 0;
536 			if (closefunc != NULL)
537 				(*closefunc)(fin);
538 			return;
539 		}
540 		if (command("REST %ld", (long) restart_point)
541 			!= CONTINUE) {
542 			restart_point = 0;
543 			if (closefunc != NULL)
544 				(*closefunc)(fin);
545 			return;
546 		}
547 		restart_point = 0;
548 		mode = "r+w";
549 	}
550 	if (remote) {
551 		if (command("%s %s", cmd, remote) != PRELIM) {
552 null();//			(void) signal(SIGINT, oldintr);
553 			if (oldintp)
554 null();//				(void) signal(SIGPIPE, oldintp);
555 			if (closefunc != NULL)
556 				(*closefunc)(fin);
557 			return;
558 		}
559 	} else
560 		if (command("%s", cmd) != PRELIM) {
561 null();//			(void) signal(SIGINT, oldintr);
562 			if (oldintp)
563 null();//				(void) signal(SIGPIPE, oldintp);
564 			if (closefunc != NULL)
565 				(*closefunc)(fin);
566 			return;
567 		}
568 	dout = dataconn(mode);
569 	if (!dout)
570 		goto abort;
571 	(void) gettimeofday(&start, (struct timezone *)0);
572 null();//	oldintp = signal(SIGPIPE, SIG_IGN);
573 	switch (type) {
574 
575 	case TYPE_I:
576 	case TYPE_L:
577 		errno = d = 0;
578 		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
579 			bytes += c;
580 			for (bufp = buf; c > 0; c -= d, bufp += d)
581 				if ((d = send(dout, bufp, c, 0)) <= 0)
582 					break;
583 			if (hash) {
584 				while (bytes >= hashbytes) {
585 					(void) putchar('#');
586 					hashbytes += HASHBYTES;
587 				}
588 				(void) fflush(stdout);
589 			}
590 		}
591 		if (hash && bytes > 0) {
592 			if (bytes < HASHBYTES)
593 				(void) putchar('#');
594 			(void) putchar('\n');
595 			(void) fflush(stdout);
596 		}
597 		if (c < 0)
598 			perror(local);
599 		if (d <= 0) {
600 			if (d == 0)
601 				fprintf(stderr, "netout: write returned 0?\n");
602 			else if (errno != EPIPE)
603 				perror("netout");
604 			bytes = -1;
605 		}
606 		break;
607 
608 	case TYPE_A:
609 		{
610 		char buf[1024];
611 		static int bufsize = 1024;
612 		int ipos=0;
613 
614 		while ((c = getc(fin)) != EOF) {
615 			if (c == '\n') {
616 				while (hash && (bytes >= hashbytes)) {
617 					(void) putchar('#');
618 					(void) fflush(stdout);
619 					hashbytes += HASHBYTES;
620 				}
621 // Szurgot: The following code is unnecessary on Win32.
622 //				(void) fputcSocket(dout, '\r');
623 //				bytes++;
624 			}
625 
626 			if (ipos >= bufsize) {
627 				fputSocket(dout,buf,ipos);
628 				if(!hash) (void) putchar('.');
629 				ipos=0;
630 			}
631 			buf[ipos]=c; ++ipos;
632 			bytes++;
633 		}
634 		if (ipos) {
635 			fputSocket(dout,buf,ipos);
636 			ipos=0;
637 		}
638 		if (hash) {
639 			if (bytes < hashbytes)
640 			(void) putchar('#');
641 			(void) putchar('\n');
642 			(void) fflush(stdout);
643 		}
644 		else {
645 			(void) putchar('.');
646 			(void) putchar('\n');
647 			(void) fflush(stdout);
648 		}
649 		if (ferror(fin))
650 			perror(local);
651 //		if (ferror(dout)) {
652 //			if (errno != EPIPE)
653 //				perror("netout");
654 //			bytes = -1;
655 //		}
656 		break;
657 		}
658 	}
659 	(void) gettimeofday(&stop, (struct timezone *)0);
660 	if (closefunc != NULL)
661 		(*closefunc)(fin);
662 	if(closesocket(dout)) {
663 		int iret=WSAGetLastError ();
664 		fprintf(stdout,"Error closing socket(%d)\n",iret);
665 		(void) fflush(stdout);
666 	}
667 	(void) getreply(0);
668 null();//	(void) signal(SIGINT, oldintr);
669 	if (oldintp)
670 null();//		(void) signal(SIGPIPE, oldintp);
671 	if (bytes > 0)
672 		ptransfer("sent", bytes, &start, &stop);
673 	return;
674 abort:
675 	(void) gettimeofday(&stop, (struct timezone *)0);
676 null();//	(void) signal(SIGINT, oldintr);
677 	if (oldintp)
678 null();//		(void) signal(SIGPIPE, oldintp);
679 	if (!cpend) {
680 		code = -1;
681 		(*closefunc)(fin);
682 		return;
683 	}
684 	if (data >= 0) {
685 		(void) close(data);
686 		data = -1;
687 	}
688 	if (dout)
689 		if(closesocket(dout)) {
690 			int iret=WSAGetLastError ();
691 			fprintf(stdout,"Error closing socket(%d)\n",iret);
692 			(void) fflush(stdout);
693 		}
694 
695 	(void) getreply(0);
696 	code = -1;
697 	if (closefunc != NULL && fin != NULL)
698 		(*closefunc)(fin);
699 	if (bytes > 0)
700 		ptransfer("sent", bytes, &start, &stop);
701 }
702 
703 jmp_buf	recvabort;
704 
705 #if 0
706 void abortrecv()
707 {
708 
709 	mflag = 0;
710 	abrtflag = 0;
711 	printf("\n");
712 	(void) fflush(stdout);
713 	longjmp(recvabort, 1);
714 }
715 #endif
716 
recvrequest(const char * cmd,const char * local,const char * remote,const char * mode,int printnames)717 void recvrequest(const char *cmd, const char *local, const char *remote, const char *mode,
718                 int printnames)
719 {
720 	FILE *fout = stdout;
721 	int din = 0;
722 	int (*closefunc)();
723 	void (*oldintr)(int), (*oldintp)(int);
724 	int oldverbose = 0, oldtype = 0, is_retr, tcrflag, nfnd, bare_lfs = 0;
725 	char msg;
726 //	static char *buf; // Szurgot: Shouldn't this go SOMEWHERE?
727 	char buf[1024];
728 	static int bufsize = 1024;
729 	long bytes = 0, hashbytes = HASHBYTES;
730 //	struct
731 		fd_set mask;
732 	register int c;
733 	struct timeval start, stop;
734 //	struct stat st;
735 
736 	is_retr = strcmp(cmd, "RETR") == 0;
737 	if (is_retr && verbose && printnames) {
738 		if (local && *local != '-')
739 			printf("local: %s ", local);
740 		if (remote)
741 			printf("remote: %s\n", remote);
742 		(void) fflush(stdout);
743 	}
744 	if (proxy && is_retr) {
745 		proxtrans(cmd, local, remote);
746 		return;
747 	}
748 	closefunc = NULL;
749 	oldintr = NULL;
750 	oldintp = NULL;
751 	tcrflag = !crflag && is_retr;
752 	if (setjmp(recvabort)) {
753 		while (cpend) {
754 			(void) getreply(0);
755 		}
756 		if (data >= 0) {
757 			(void) close(data);
758 			data = -1;
759 		}
760 		if (oldintr)
761 null();//			(void) signal(SIGINT, oldintr);
762 		code = -1;
763 		return;
764 	}
765 null();//	oldintr = signal(SIGINT, abortrecv);
766 	if (strcmp(local, "-") && *local != '|') {
767 #ifndef _WIN32
768 	register int d;
769 // This whole thing is a problem... access Won't work on non-existent files
770 		if (access(local, 2) < 0) {
771 			char *dir = rindex(local, '/');
772 
773 			if (errno != ENOENT && errno != EACCES) {
774 				perror(local);
775 				(void) signal(SIGINT, oldintr);
776 				code = -1;
777 				return;
778 			}
779 			if (dir != NULL)
780 				*dir = 0;
781 			d = access(dir ? local : ".", 2);
782 			if (dir != NULL)
783 				*dir = '/';
784 			if (d < 0) {
785 				perror(local);
786 				(void) signal(SIGINT, oldintr);
787 				code = -1;
788 				return;
789 			}
790 			if (!runique && errno == EACCES &&
791 			    chmod(local, 0600) < 0) {
792 				perror(local);
793 				(void) signal(SIGINT, oldintr);
794 				code = -1;
795 				return;
796 			}
797 			if (runique && errno == EACCES &&
798 			    (local = gunique(local)) == NULL) {
799 				(void) signal(SIGINT, oldintr);
800 				code = -1;
801 				return;
802 			}
803 		}
804 		else if (runique && (local = gunique(local)) == NULL) {
805 			(void) signal(SIGINT, oldintr);
806 			code = -1;
807 			return;
808 		}
809 #endif
810 	}
811 	if (initconn()) {
812 null();//		(void) signal(SIGINT, oldintr);
813 		code = -1;
814 		return;
815 	}
816 	if (setjmp(recvabort))
817 		goto abort;
818 	if (!is_retr) {
819 		if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) {
820 			oldtype = type;
821 			oldverbose = verbose;
822 			if (!debug)
823 				verbose = 0;
824 			setascii(0, NULL);
825 			verbose = oldverbose;
826 		}
827 	} else if (restart_point) {
828 		if (command("REST %ld", (long) restart_point) != CONTINUE)
829 			return;
830 	}
831 	if (remote) {
832 		if (command("%s %s", cmd, remote) != PRELIM) {
833 null();//			(void) signal(SIGINT, oldintr);
834 			if (oldtype) {
835 				if (!debug)
836 					verbose = 0;
837 				switch (oldtype) {
838 					case TYPE_I:
839 						setbinary(0, NULL);
840 						break;
841 					case TYPE_E:
842 						setebcdic();
843 						break;
844 					case TYPE_L:
845 						settenex(0, NULL);
846 						break;
847 				}
848 				verbose = oldverbose;
849 			}
850 			return;
851 		}
852 	} else {
853 		if (command("%s", cmd) != PRELIM) {
854 null();//			(void) signal(SIGINT, oldintr);
855 			if (oldtype) {
856 				if (!debug)
857 					verbose = 0;
858 				switch (oldtype) {
859 					case TYPE_I:
860 						setbinary(0, NULL);
861 						break;
862 					case TYPE_E:
863 						setebcdic();
864 						break;
865 					case TYPE_L:
866 						settenex(0, NULL);
867 						break;
868 				}
869 				verbose = oldverbose;
870 			}
871 			return;
872 		}
873 	}
874 	din = dataconn("r");
875 	if (!din)
876 		goto abort;
877 	if (strcmp(local, "-") == 0)
878 		fout = stdout;
879 	else if (*local == '|') {
880 null();//		oldintp = signal(SIGPIPE, SIG_IGN);
881 		fout = _popen(local + 1, "w");
882 		if (fout == NULL) {
883 			perror(local+1);
884 			goto abort;
885 		}
886 		closefunc = _pclose;
887 	} else {
888 		fout = fopen(local, mode);
889 		if (fout == NULL) {
890 			perror(local);
891 			goto abort;
892 		}
893 		closefunc = fclose;
894 	}
895 	(void) gettimeofday(&start, (struct timezone *)0);
896 	switch (type) {
897 
898 	case TYPE_I:
899 	case TYPE_L:
900 		if (restart_point &&
901 		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
902 			perror(local);
903 			if (closefunc != NULL)
904 				(*closefunc)(fout);
905 			return;
906 		}
907 		errno = 0;
908 //		while ((c = recv(din, buf, bufsize, 1)) > 0) {
909 //			if ((d = write(fileno(fout), buf, c)) != c)
910 //			if ((d = write(fileno(fout), buf, c)) != c)
911 //				break;
912 		while ((c = recv(din, buf, bufsize, 0)) > 0) {
913 			write(fileno(fout), buf, c);
914 			bytes += c;
915 			if (hash) {
916 				while (bytes >= hashbytes) {
917 					(void) putchar('#');
918 					hashbytes += HASHBYTES;
919 				}
920 				(void) fflush(stdout);
921 			}
922 		}
923 		if (hash && bytes > 0) {
924 			if (bytes < HASHBYTES)
925 				(void) putchar('#');
926 			(void) putchar('\n');
927 			(void) fflush(stdout);
928 		}
929 //		if (c < 0) {
930 //			if (errno != EPIPE)
931 //				perror("netin");
932 //			bytes = -1;
933 //		}
934 //		if (d < c) {
935 //			if (d < 0)
936 //				perror(local);
937 //			else
938 //				fprintf(stderr, "%s: short write\n", local);
939 //		}
940 		break;
941 
942 	case TYPE_A:
943 		if (restart_point) {
944 			register int i, n, c;
945 
946 			if (fseek(fout, 0L, L_SET) < 0)
947 				goto done;
948 			n = restart_point;
949 			i = 0;
950 			while (i++ < n) {
951 				if ((c=getc(fout)) == EOF)
952 					goto done;
953 				if (c == '\n')
954 					i++;
955 			}
956 			if (fseek(fout, 0L, L_INCR) < 0) {
957 done:
958 				perror(local);
959 				if (closefunc != NULL)
960 					(*closefunc)(fout);
961 				return;
962 			}
963 		}
964 		while ((c = fgetcSocket(din)) != EOF) {
965 			if (c == '\n')
966 				bare_lfs++;
967 			while (c == '\r') {
968 				while (hash && (bytes >= hashbytes)) {
969 					(void) putchar('#');
970 					(void) fflush(stdout);
971 					hashbytes += HASHBYTES;
972 				}
973 				bytes++;
974 				if ((c = fgetcSocket(din)) != '\n' || tcrflag) {
975 					if (ferror(fout))
976 					goto break2;
977 					(void) putc('\r', fout);
978 					if (c == '\0') {
979 						bytes++;
980 						goto contin2;
981 					}
982 					if (c == EOF)
983 						goto contin2;
984 				}
985 			}
986 			(void) putc(c, fout);
987 			bytes++;
988 	contin2:	;
989 		}
990 break2:
991 		if (bare_lfs) {
992 			printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
993 			printf("File may not have transferred correctly.\n");
994 			(void) fflush(stdout);
995 		}
996 		if (hash) {
997 			if (bytes < hashbytes)
998 				(void) putchar('#');
999 			(void) putchar('\n');
1000 			(void) fflush(stdout);
1001 		}
1002 //		if (ferror(din)) {
1003 //			if (errno != EPIPE)
1004 //				perror("netin");
1005 //			bytes = -1;
1006 //		}
1007 		if (ferror(fout))
1008 			perror(local);
1009 		break;
1010 	}
1011 	if (closefunc != NULL)
1012 		(*closefunc)(fout);
1013 null();//	(void) signal(SIGINT, oldintr);
1014 	if (oldintp)
1015 null();//		(void) signal(SIGPIPE, oldintp);
1016 	(void) gettimeofday(&stop, (struct timezone *)0);
1017 	if(closesocket(din)) {
1018 		int iret=WSAGetLastError ();
1019 		fprintf(stdout,"Error closing socket(%d)\n",iret);
1020 		(void) fflush(stdout);
1021 	}
1022 
1023 	(void) getreply(0);
1024 	if (bytes > 0 && is_retr)
1025 		ptransfer("received", bytes, &start, &stop);
1026 	if (oldtype) {
1027 		if (!debug)
1028 			verbose = 0;
1029 		switch (oldtype) {
1030 			case TYPE_I:
1031 				setbinary(0, NULL);
1032 				break;
1033 			case TYPE_E:
1034 				setebcdic();
1035 				break;
1036 			case TYPE_L:
1037 				settenex(0, NULL);
1038 				break;
1039 		}
1040 		verbose = oldverbose;
1041 	}
1042 	return;
1043 abort:
1044 
1045 /* abort using RFC959 recommended IP,SYNC sequence  */
1046 
1047 	(void) gettimeofday(&stop, (struct timezone *)0);
1048 	if (oldintp)
1049 null();//		(void) signal(SIGPIPE, oldintr);
1050 null();//	(void) signal(SIGINT,SIG_IGN);
1051 	if (oldtype) {
1052 		if (!debug)
1053 			verbose = 0;
1054 		switch (oldtype) {
1055 			case TYPE_I:
1056 				setbinary(0, NULL);
1057 				break;
1058 			case TYPE_E:
1059 				setebcdic();
1060 				break;
1061 			case TYPE_L:
1062 				settenex(0, NULL);
1063 				break;
1064 		}
1065 		verbose = oldverbose;
1066 	}
1067 	if (!cpend) {
1068 		code = -1;
1069 null();//		(void) signal(SIGINT,oldintr);
1070 		return;
1071 	}
1072 
1073 	fprintfSocket(cout,"%c%c",IAC,IP);
1074 	msg = (char)IAC;
1075 /* send IAC in urgent mode instead of DM because UNIX places oob mark */
1076 /* after urgent byte rather than before as now is protocol */
1077 	if (send(cout,&msg,1,MSG_OOB) != 1) {
1078 		perror("abort");
1079 	}
1080 	fprintfSocket(cout,"%cABOR\r\n",DM);
1081 	FD_ZERO(&mask);
1082 	FD_SET(cin, &mask); // Need to correct this
1083 	if (din) {
1084 		FD_SET(din, &mask); // Need to correct this
1085 	}
1086 	if ((nfnd = empty(&mask,10)) <= 0) {
1087 		if (nfnd < 0) {
1088 			perror("abort");
1089 		}
1090 		code = -1;
1091 		lostpeer();
1092 	}
1093 	if (din && FD_ISSET(din, &mask)) {
1094 		while (recv(din, buf, bufsize, 0) > 0)
1095 			;
1096 	}
1097 	if (getreply(0) == ERROR && code == 552) { /* needed for nic style abort */
1098 		if (data >= 0) {
1099 			(void) close(data);
1100 			data = -1;
1101 		}
1102 		(void) getreply(0);
1103 	}
1104 	(void) getreply(0);
1105 	code = -1;
1106 	if (data >= 0) {
1107 		(void) close(data);
1108 		data = -1;
1109 	}
1110 	if (closefunc != NULL && fout != NULL)
1111 		(*closefunc)(fout);
1112 	if (din)
1113 		if(closesocket(din)) {
1114 			int iret=WSAGetLastError ();
1115 			fprintf(stdout,"Error closing socket(%d)\n",iret);
1116 			(void) fflush(stdout);
1117 		}
1118 
1119 	if (bytes > 0)
1120 		ptransfer("received", bytes, &start, &stop);
1121 null();//	(void) signal(SIGINT,oldintr);
1122 }
1123 
1124 int
initconn()1125 initconn()
1126 {
1127 	register char *p, *a;
1128 	int result, len, tmpno = 0;
1129 	int on = 1;
1130 	int a0, a1, a2, a3, p0, p1;
1131 
1132 
1133 	if (passivemode) {
1134 		data = socket(AF_INET, SOCK_STREAM, 0);
1135 		if (data < 0) {
1136 			perror("ftp: socket");
1137 			return(1);
1138 		}
1139 		if ((options & SO_DEBUG) &&
1140 		    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1141 		    sizeof (on)) < 0)
1142 			perror("ftp: setsockopt (ignored)");
1143 		if (command("PASV") != COMPLETE) {
1144 			printf("Passive mode refused.\n");
1145 			goto bad;
1146 		}
1147 
1148 		/*
1149 		 * What we've got at this point is a string of comma
1150 		 * separated one-byte unsigned integer values.
1151 		 * The first four are the an IP address. The fifth is
1152 		 * the MSB of the port number, the sixth is the LSB.
1153 		 * From that we'll prepare a sockaddr_in.
1154 		 */
1155 
1156 		if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",
1157 		    &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1158 			printf("Passive mode address scan failure. Shouldn't happen!\n");
1159 			goto bad;
1160 		}
1161 
1162 		bzero(&data_addr, sizeof(data_addr));
1163 		data_addr.sin_family = AF_INET;
1164 		a = (char *)&data_addr.sin_addr.s_addr;
1165 		a[0] = a0 & 0xff;
1166 		a[1] = a1 & 0xff;
1167 		a[2] = a2 & 0xff;
1168 		a[3] = a3 & 0xff;
1169 		p = (char *)&data_addr.sin_port;
1170 		p[0] = p0 & 0xff;
1171 		p[1] = p1 & 0xff;
1172 
1173 		if (connect(data, (struct sockaddr *)&data_addr,
1174 		    sizeof(data_addr)) < 0) {
1175 			perror("ftp: connect");
1176 			goto bad;
1177 		}
1178 		return(0);
1179 	}
1180 
1181 
1182 noport:
1183 	data_addr = myctladdr;
1184 	if (sendport)
1185 		data_addr.sin_port = 0;	/* let system pick one */
1186 	if (data != -1)
1187 		(void) close (data);
1188 	data = socket(AF_INET, SOCK_STREAM, 0);
1189 	if (data < 0) {
1190 		perror("ftp: socket");
1191 		if (tmpno)
1192 			sendport = 1;
1193 		return (1);
1194 	}
1195 	if (!sendport)
1196 		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1197 			perror("ftp: setsockopt (reuse address)");
1198 			goto bad;
1199 		}
1200 	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1201 		perror("ftp: bind");
1202 		goto bad;
1203 	}
1204 	if (options & SO_DEBUG &&
1205 	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1206 		perror("ftp: setsockopt (ignored)");
1207 	len = sizeof (data_addr);
1208 	if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1209 		perror("ftp: getsockname");
1210 		goto bad;
1211 	}
1212 	if (listen(data, 1) < 0)
1213 		perror("ftp: listen");
1214 	if (sendport) {
1215 		a = (char *)&data_addr.sin_addr;
1216 		p = (char *)&data_addr.sin_port;
1217 #define	UC(b)	(((int)b)&0xff)
1218 		result =
1219 		    command("PORT %d,%d,%d,%d,%d,%d",
1220 		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1221 		      UC(p[0]), UC(p[1]));
1222 		if (result == ERROR && sendport == -1) {
1223 			sendport = 0;
1224 			tmpno = 1;
1225 			goto noport;
1226 		}
1227 		return (result != COMPLETE);
1228 	}
1229 	if (tmpno)
1230 		sendport = 1;
1231 	return (0);
1232 bad:
1233 	(void) fflush(stdout);
1234 	(void) close(data), data = -1;
1235 	if (tmpno)
1236 		sendport = 1;
1237 	return (1);
1238 }
1239 
dataconn(const char * mode)1240 int dataconn(const char *mode)
1241 {
1242 	struct sockaddr_in from;
1243 	int s, fromlen = sizeof (from);
1244 
1245 	if (passivemode)
1246 		return (data);
1247 
1248 	s = accept(data, (struct sockaddr *) &from, &fromlen);
1249 	if (s < 0) {
1250 		perror("ftp: accept");
1251 		(void) closesocket(data), data = -1;
1252 		return 0;
1253 	}
1254 	if(closesocket(data)) {
1255 		int iret=WSAGetLastError ();
1256 		fprintf(stdout,"Error closing socket(%d)\n",iret);
1257 		(void) fflush(stdout);
1258 	}
1259 
1260 	data = s;
1261 	return (data);
1262 }
1263 
ptransfer(direction,bytes,t0,t1)1264 void ptransfer(direction, bytes, t0, t1)
1265 	const char *direction;
1266 	long bytes;
1267 	struct timeval *t0, *t1;
1268 {
1269 	struct timeval td;
1270 	double s, bs;
1271 
1272 	if (verbose) {
1273 		tvsub(&td, t1, t0);
1274 		s = td.tv_sec + (td.tv_usec / 1000000.);
1275 #define	nz(x)	((x) == 0 ? 1 : (x))
1276 		bs = bytes / nz(s);
1277 		printf("%ld bytes %s in %.1f seconds (%.0f Kbytes/s)\n",
1278 		    bytes, direction, s, bs / 1024.);
1279 		(void) fflush(stdout);
1280 	}
1281 }
1282 
1283 /*tvadd(tsum, t0)
1284 	struct timeval *tsum, *t0;
1285 {
1286 
1287 	tsum->tv_sec += t0->tv_sec;
1288 	tsum->tv_usec += t0->tv_usec;
1289 	if (tsum->tv_usec > 1000000)
1290 		tsum->tv_sec++, tsum->tv_usec -= 1000000;
1291 } */
1292 
tvsub(tdiff,t1,t0)1293 void tvsub(tdiff, t1, t0)
1294 	struct timeval *tdiff, *t1, *t0;
1295 {
1296 
1297 	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1298 	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1299 	if (tdiff->tv_usec < 0)
1300 		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1301 }
1302 
psabort(int flag)1303 void psabort(int flag)
1304 {
1305 	extern int abrtflag;
1306 
1307 	abrtflag++;
1308 }
1309 
pswitch(int flag)1310 void pswitch(int flag)
1311 {
1312 	extern int proxy, abrtflag;
1313 	Sig_t oldintr;
1314 	static struct comvars {
1315 		int connect;
1316 		char name[MAXHOSTNAMELEN];
1317 		struct sockaddr_in mctl;
1318 		struct sockaddr_in hctl;
1319 		SOCKET in;
1320 		SOCKET out;
1321 		int tpe;
1322 		int cpnd;
1323 		int sunqe;
1324 		int runqe;
1325 		int mcse;
1326 		int ntflg;
1327 		char nti[17];
1328 		char nto[17];
1329 		int mapflg;
1330 		char mi[MAXPATHLEN];
1331 		char mo[MAXPATHLEN];
1332 		} proxstruct, tmpstruct;
1333 	struct comvars *ip, *op;
1334 
1335 	abrtflag = 0;
1336 	oldintr = signal(SIGINT, psabort);
1337 	if (flag) {
1338 		if (proxy)
1339 			return;
1340 		ip = &tmpstruct;
1341 		op = &proxstruct;
1342 		proxy++;
1343 	}
1344 	else {
1345 		if (!proxy)
1346 			return;
1347 		ip = &proxstruct;
1348 		op = &tmpstruct;
1349 		proxy = 0;
1350 	}
1351 	ip->connect = connected;
1352 	connected = op->connect;
1353 	if (hostname) {
1354 		(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1355 		ip->name[strlen(ip->name)] = '\0';
1356 	} else
1357 		ip->name[0] = 0;
1358 	hostname = op->name;
1359 	ip->hctl = hisctladdr;
1360 	hisctladdr = op->hctl;
1361 	ip->mctl = myctladdr;
1362 	myctladdr = op->mctl;
1363 	ip->in = cin;
1364 	cin = op->in;
1365 	ip->out = cout;
1366 	cout = op->out;
1367 	ip->tpe = type;
1368 	type = op->tpe;
1369 	if (!type)
1370 		type = 1;
1371 	ip->cpnd = cpend;
1372 	cpend = op->cpnd;
1373 	ip->sunqe = sunique;
1374 	sunique = op->sunqe;
1375 	ip->runqe = runique;
1376 	runique = op->runqe;
1377 	ip->mcse = mcase;
1378 	mcase = op->mcse;
1379 	ip->ntflg = ntflag;
1380 	ntflag = op->ntflg;
1381 	(void) strncpy(ip->nti, ntin, 16);
1382 	(ip->nti)[strlen(ip->nti)] = '\0';
1383 	(void) strcpy(ntin, op->nti);
1384 	(void) strncpy(ip->nto, ntout, 16);
1385 	(ip->nto)[strlen(ip->nto)] = '\0';
1386 	(void) strcpy(ntout, op->nto);
1387 	ip->mapflg = mapflag;
1388 	mapflag = op->mapflg;
1389 	(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1390 	(ip->mi)[strlen(ip->mi)] = '\0';
1391 	(void) strcpy(mapin, op->mi);
1392 	(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1393 	(ip->mo)[strlen(ip->mo)] = '\0';
1394 	(void) strcpy(mapout, op->mo);
1395 //	(void) signal(SIGINT, oldintr);
1396 	if (abrtflag) {
1397 		abrtflag = 0;
1398 		(*oldintr)(1);
1399 	}
1400 }
1401 
1402 jmp_buf ptabort;
1403 int ptabflg;
1404 
1405 #if 0
1406 void
1407 abortpt()
1408 {
1409 	printf("\n");
1410 	(void) fflush(stdout);
1411 	ptabflg++;
1412 	mflag = 0;
1413 	abrtflag = 0;
1414 	longjmp(ptabort, 1);
1415 }
1416 #endif
1417 
proxtrans(cmd,local,remote)1418 void proxtrans(cmd, local, remote)
1419 	const char *cmd, *local, *remote;
1420 {
1421 //	void (*oldintr)(int);
1422 	int tmptype, oldtype = 0, secndflag = 0, nfnd;
1423 	extern jmp_buf ptabort;
1424 	const char *cmd2;
1425 //	struct
1426 	fd_set mask;
1427 
1428 	if (strcmp(cmd, "RETR"))
1429 		cmd2 = "RETR";
1430 	else
1431 		cmd2 = runique ? "STOU" : "STOR";
1432 	if (command("PASV") != COMPLETE) {
1433 		printf("proxy server does not support third part transfers.\n");
1434 		(void) fflush(stdout);
1435 		return;
1436 	}
1437 	tmptype = type;
1438 	pswitch(0);
1439 	if (!connected) {
1440 		printf("No primary connection\n");
1441 		(void) fflush(stdout);
1442 		pswitch(1);
1443 		code = -1;
1444 		return;
1445 	}
1446 	if (type != tmptype) {
1447 		oldtype = type;
1448 		switch (tmptype) {
1449 			case TYPE_A:
1450 				setascii(0, NULL);
1451 				break;
1452 			case TYPE_I:
1453 				setbinary(0, NULL);
1454 				break;
1455 			case TYPE_E:
1456 				setebcdic();
1457 				break;
1458 			case TYPE_L:
1459 				settenex(0, NULL);
1460 				break;
1461 		}
1462 	}
1463 	if (command("PORT %s", pasv) != COMPLETE) {
1464 		switch (oldtype) {
1465 			case 0:
1466 				break;
1467 			case TYPE_A:
1468 				setascii(0, NULL);
1469 				break;
1470 			case TYPE_I:
1471 				setbinary(0, NULL);
1472 				break;
1473 			case TYPE_E:
1474 				setebcdic();
1475 				break;
1476 			case TYPE_L:
1477 				settenex(0, NULL);
1478 				break;
1479 		}
1480 		pswitch(1);
1481 		return;
1482 	}
1483 	if (setjmp(ptabort))
1484 		goto abort;
1485 null();//	oldintr = signal(SIGINT, abortpt);
1486 	if (command("%s %s", cmd, remote) != PRELIM) {
1487 null();//		(void) signal(SIGINT, oldintr);
1488 		switch (oldtype) {
1489 			case 0:
1490 				break;
1491 			case TYPE_A:
1492 				setascii(0, NULL);
1493 				break;
1494 			case TYPE_I:
1495 				setbinary(0, NULL);
1496 				break;
1497 			case TYPE_E:
1498 				setebcdic();
1499 				break;
1500 			case TYPE_L:
1501 				settenex(0, NULL);
1502 				break;
1503 		}
1504 		pswitch(1);
1505 		return;
1506 	}
1507 	sleep(2);
1508 	pswitch(1);
1509 	secndflag++;
1510 	if (command("%s %s", cmd2, local) != PRELIM)
1511 		goto abort;
1512 	ptflag++;
1513 	(void) getreply(0);
1514 	pswitch(0);
1515 	(void) getreply(0);
1516 null();//	(void) signal(SIGINT, oldintr);
1517 	switch (oldtype) {
1518 		case 0:
1519 			break;
1520 		case TYPE_A:
1521 			setascii(0, NULL);
1522 			break;
1523 		case TYPE_I:
1524 			setbinary(0, NULL);
1525 			break;
1526 		case TYPE_E:
1527 			setebcdic();
1528 			break;
1529 		case TYPE_L:
1530 			settenex(0, NULL);
1531 			break;
1532 	}
1533 	pswitch(1);
1534 	ptflag = 0;
1535 	printf("local: %s remote: %s\n", local, remote);
1536 	(void) fflush(stdout);
1537 	return;
1538 abort:
1539 null();//	(void) signal(SIGINT, SIG_IGN);
1540 	ptflag = 0;
1541 	if (strcmp(cmd, "RETR") && !proxy)
1542 		pswitch(1);
1543 	else if (!strcmp(cmd, "RETR") && proxy)
1544 		pswitch(0);
1545 	if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
1546 		if (command("%s %s", cmd2, local) != PRELIM) {
1547 			pswitch(0);
1548 			switch (oldtype) {
1549 				case 0:
1550 					break;
1551 				case TYPE_A:
1552 					setascii(0, NULL);
1553 					break;
1554 				case TYPE_I:
1555 					setbinary(0, NULL);
1556 					break;
1557 				case TYPE_E:
1558 					setebcdic();
1559 					break;
1560 				case TYPE_L:
1561 					settenex(0, NULL);
1562 					break;
1563 			}
1564 			if (cpend) {
1565 				char msg[2];
1566 
1567 				fprintfSocket(cout,"%c%c",IAC,IP);
1568 				*msg = (char) IAC;
1569 				*(msg+1) = (char) DM;
1570 				if (send(cout,msg,2,MSG_OOB) != 2)
1571 					perror("abort");
1572 				fprintfSocket(cout,"ABOR\r\n");
1573 				FD_ZERO(&mask);
1574 //				FD_SET(fileno(cin), &mask); // Chris: Need to correct this
1575 				if ((nfnd = empty(&mask,10)) <= 0) {
1576 					if (nfnd < 0) {
1577 						perror("abort");
1578 					}
1579 					if (ptabflg)
1580 						code = -1;
1581 					lostpeer();
1582 				}
1583 				(void) getreply(0);
1584 				(void) getreply(0);
1585 			}
1586 		}
1587 		pswitch(1);
1588 		if (ptabflg)
1589 			code = -1;
1590 null();//		(void) signal(SIGINT, oldintr);
1591 		return;
1592 	}
1593 	if (cpend) {
1594 		char msg[2];
1595 
1596 		fprintfSocket(cout,"%c%c",IAC,IP);
1597 		*msg = (char)IAC;
1598 		*(msg+1) = (char)DM;
1599 		if (send(cout,msg,2,MSG_OOB) != 2)
1600 			perror("abort");
1601 		fprintfSocket(cout,"ABOR\r\n");
1602 		FD_ZERO(&mask);
1603 //		FD_SET(fileno(cin), &mask); // Chris: Need to correct this...
1604 		if ((nfnd = empty(&mask,10)) <= 0) {
1605 			if (nfnd < 0) {
1606 				perror("abort");
1607 			}
1608 			if (ptabflg)
1609 				code = -1;
1610 			lostpeer();
1611 		}
1612 		(void) getreply(0);
1613 		(void) getreply(0);
1614 	}
1615 	pswitch(!proxy);
1616 	if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
1617 		if (command("%s %s", cmd2, local) != PRELIM) {
1618 			pswitch(0);
1619 			switch (oldtype) {
1620 				case 0:
1621 					break;
1622 				case TYPE_A:
1623 					setascii(0, NULL);
1624 					break;
1625 				case TYPE_I:
1626 					setbinary(0, NULL);
1627 					break;
1628 				case TYPE_E:
1629 					setebcdic();
1630 					break;
1631 				case TYPE_L:
1632 					settenex(0, NULL);
1633 					break;
1634 			}
1635 			if (cpend) {
1636 				char msg[2];
1637 
1638 				fprintfSocket(cout,"%c%c",IAC,IP);
1639 				*msg = (char)IAC;
1640 				*(msg+1) = (char)DM;
1641 				if (send(cout,msg,2,MSG_OOB) != 2)
1642 					perror("abort");
1643 				fprintfSocket(cout,"ABOR\r\n");
1644 				FD_ZERO(&mask);
1645 //				FD_SET(fileno(cin), &mask); // Chris:
1646 				if ((nfnd = empty(&mask,10)) <= 0) {
1647 					if (nfnd < 0) {
1648 						perror("abort");
1649 					}
1650 					if (ptabflg)
1651 						code = -1;
1652 					lostpeer();
1653 				}
1654 				(void) getreply(0);
1655 				(void) getreply(0);
1656 			}
1657 			pswitch(1);
1658 			if (ptabflg)
1659 				code = -1;
1660 null();//			(void) signal(SIGINT, oldintr);
1661 			return;
1662 		}
1663 	}
1664 	if (cpend) {
1665 		char msg[2];
1666 
1667 		fprintfSocket(cout,"%c%c",IAC,IP);
1668 		*msg = (char)IAC;
1669 		*(msg+1) = (char)DM;
1670 		if (send(cout,msg,2,MSG_OOB) != 2)
1671 			perror("abort");
1672 		fprintfSocket(cout,"ABOR\r\n");
1673 		FD_ZERO(&mask);
1674 //		FD_SET(fileno(cin), &mask); // Chris:
1675 		if ((nfnd = empty(&mask,10)) <= 0) {
1676 			if (nfnd < 0) {
1677 				perror("abort");
1678 			}
1679 			if (ptabflg)
1680 				code = -1;
1681 			lostpeer();
1682 		}
1683 		(void) getreply(0);
1684 		(void) getreply(0);
1685 	}
1686 	pswitch(!proxy);
1687 	if (cpend) {
1688 		FD_ZERO(&mask);
1689 //		FD_SET(fileno(cin), &mask); // Chris:
1690 		if ((nfnd = empty(&mask,10)) <= 0) {
1691 			if (nfnd < 0) {
1692 				perror("abort");
1693 			}
1694 			if (ptabflg)
1695 				code = -1;
1696 			lostpeer();
1697 		}
1698 		(void) getreply(0);
1699 		(void) getreply(0);
1700 	}
1701 	if (proxy)
1702 		pswitch(0);
1703 	switch (oldtype) {
1704 		case 0:
1705 			break;
1706 		case TYPE_A:
1707 			setascii(0, NULL);
1708 			break;
1709 		case TYPE_I:
1710 			setbinary(0, NULL);
1711 			break;
1712 		case TYPE_E:
1713 			setebcdic();
1714 			break;
1715 		case TYPE_L:
1716 			settenex(0, NULL);
1717 			break;
1718 	}
1719 	pswitch(1);
1720 	if (ptabflg)
1721 		code = -1;
1722 null();//	(void) signal(SIGINT, oldintr);
1723 }
1724 
reset(int argc,const char * argv[])1725 void reset(int argc, const char *argv[])
1726 {
1727 //	struct
1728 	fd_set mask;
1729 	int nfnd = 1;
1730 
1731 	FD_ZERO(&mask);
1732 	while (nfnd > 0) {
1733 //		FD_SET(fileno(cin), &mask); // Chris
1734 		if ((nfnd = empty(&mask,0)) < 0) {
1735 			perror("reset");
1736 			code = -1;
1737 			lostpeer();
1738 		}
1739 		else if (nfnd) {
1740 			(void) getreply(0);
1741 		}
1742 	}
1743 }
1744 
1745 #if 0
1746 char *
1747 gunique(local)
1748 	char *local;
1749 {
1750 	static char new[MAXPATHLEN];
1751 	char *cp = rindex(local, '/');
1752 	int d, count=0;
1753 	char ext = '1';
1754 
1755 	if (cp)
1756 		*cp = '\0';
1757 	d = access(cp ? local : ".", 2);
1758 	if (cp)
1759 		*cp = '/';
1760 	if (d < 0) {
1761 		perror(local);
1762 		return((char *) 0);
1763 	}
1764 	(void) strcpy(new, local);
1765 	cp = new + strlen(new);
1766 	*cp++ = '.';
1767 	while (!d) {
1768 		if (++count == 100) {
1769 			printf("runique: can't find unique file name.\n");
1770 			(void) fflush(stdout);
1771 			return((char *) 0);
1772 		}
1773 		*cp++ = ext;
1774 		*cp = '\0';
1775 		if (ext == '9')
1776 			ext = '0';
1777 		else
1778 			ext++;
1779 		if ((d = access(new, 0)) < 0)
1780 			break;
1781 		if (ext != '0')
1782 			cp--;
1783 		else if (*(cp - 2) == '.')
1784 			*(cp - 1) = '1';
1785 		else {
1786 			*(cp - 2) = *(cp - 2) + 1;
1787 			cp--;
1788 		}
1789 	}
1790 	return(new);
1791 }
1792 #endif
1793 
null(void)1794 int null(void)
1795 {
1796 	return 0;
1797 }
1798