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