This commit was manufactured by cvs2svn to create tag
[heimdal.git] / appl / ftp / ftp / ftp.c
blob675a46d71cd959dc0544d6132a3dd51e00e2d77e
1 /*
2 * Copyright (c) 1985, 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "ftp_locl.h"
35 RCSID ("$Id$");
37 struct sockaddr_storage hisctladdr_ss;
38 struct sockaddr *hisctladdr = (struct sockaddr *)&hisctladdr_ss;
39 struct sockaddr_storage data_addr_ss;
40 struct sockaddr *data_addr = (struct sockaddr *)&data_addr_ss;
41 struct sockaddr_storage myctladdr_ss;
42 struct sockaddr *myctladdr = (struct sockaddr *)&myctladdr_ss;
43 int data = -1;
44 int abrtflag = 0;
45 jmp_buf ptabort;
46 int ptabflg;
47 int ptflag = 0;
48 off_t restart_point = 0;
51 FILE *cin, *cout;
53 typedef void (*sighand) (int);
55 char *
56 hookup (const char *host, int port)
58 static char hostnamebuf[MaxHostNameLen];
59 struct addrinfo *ai, *a;
60 struct addrinfo hints;
61 int error;
62 char portstr[NI_MAXSERV];
63 socklen_t len;
64 int s;
66 memset (&hints, 0, sizeof(hints));
67 hints.ai_socktype = SOCK_STREAM;
68 hints.ai_protocol = IPPROTO_TCP;
69 hints.ai_flags = AI_CANONNAME;
71 snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
73 error = getaddrinfo (host, portstr, &hints, &ai);
74 if (error) {
75 warnx ("%s: %s", host, gai_strerror(error));
76 code = -1;
77 return NULL;
79 strlcpy (hostnamebuf, host, sizeof(hostnamebuf));
80 hostname = hostnamebuf;
82 for (a = ai; a != NULL; a = a->ai_next) {
83 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
84 if (s < 0)
85 continue;
87 if (a->ai_canonname != NULL)
88 strlcpy (hostnamebuf, a->ai_canonname, sizeof(hostnamebuf));
90 memcpy (hisctladdr, a->ai_addr, a->ai_addrlen);
92 error = connect (s, a->ai_addr, a->ai_addrlen);
93 if (error < 0) {
94 char addrstr[256];
96 if (getnameinfo (a->ai_addr, a->ai_addrlen,
97 addrstr, sizeof(addrstr),
98 NULL, 0, NI_NUMERICHOST) != 0)
99 strlcpy (addrstr, "unknown address", sizeof(addrstr));
101 warn ("connect %s", addrstr);
102 close (s);
103 continue;
105 break;
107 freeaddrinfo (ai);
108 if (error < 0) {
109 warnx ("failed to contact %s", host);
110 code = -1;
111 return NULL;
114 len = sizeof(myctladdr_ss);
115 if (getsockname (s, myctladdr, &len) < 0) {
116 warn ("getsockname");
117 code = -1;
118 close (s);
119 return NULL;
121 #ifdef IPTOS_LOWDELAY
122 socket_set_tos (s, IPTOS_LOWDELAY);
123 #endif
124 cin = fdopen (s, "r");
125 cout = fdopen (s, "w");
126 if (cin == NULL || cout == NULL) {
127 warnx ("fdopen failed.");
128 if (cin)
129 fclose (cin);
130 if (cout)
131 fclose (cout);
132 code = -1;
133 goto bad;
135 if (verbose)
136 printf ("Connected to %s.\n", hostname);
137 if (getreply (0) > 2) { /* read startup message from server */
138 if (cin)
139 fclose (cin);
140 if (cout)
141 fclose (cout);
142 code = -1;
143 goto bad;
145 #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
147 int on = 1;
149 if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
150 < 0 && debug) {
151 warn ("setsockopt");
154 #endif /* SO_OOBINLINE */
156 return (hostname);
157 bad:
158 close (s);
159 return NULL;
163 login (char *host)
165 char tmp[80];
166 char defaultpass[128];
167 char *user, *pass, *acct;
168 int n, aflag = 0;
170 char *myname = NULL;
171 struct passwd *pw = k_getpwuid(getuid());
173 if (pw != NULL)
174 myname = pw->pw_name;
176 user = pass = acct = 0;
178 if(sec_login(host))
179 printf("\n*** Using plaintext user and password ***\n\n");
180 else{
181 printf("Authentication successful.\n\n");
184 if (ruserpass (host, &user, &pass, &acct) < 0) {
185 code = -1;
186 return (0);
188 while (user == NULL) {
189 if (myname)
190 printf ("Name (%s:%s): ", host, myname);
191 else
192 printf ("Name (%s): ", host);
193 *tmp = '\0';
194 if (fgets (tmp, sizeof (tmp) - 1, stdin) != NULL)
195 tmp[strlen (tmp) - 1] = '\0';
196 if (*tmp == '\0')
197 user = myname;
198 else
199 user = tmp;
201 strlcpy(username, user, sizeof(username));
202 n = command("USER %s", user);
203 if (n == COMPLETE)
204 n = command("PASS dummy"); /* DK: Compatibility with gssftp daemon */
205 else if(n == CONTINUE) {
206 if (pass == NULL) {
207 char prompt[128];
208 if(myname &&
209 (!strcmp(user, "ftp") || !strcmp(user, "anonymous"))) {
210 snprintf(defaultpass, sizeof(defaultpass),
211 "%s@%s", myname, mydomain);
212 snprintf(prompt, sizeof(prompt),
213 "Password (%s): ", defaultpass);
214 } else if (sec_complete) {
215 pass = myname;
216 } else {
217 *defaultpass = '\0';
218 snprintf(prompt, sizeof(prompt), "Password: ");
220 if (pass == NULL) {
221 pass = defaultpass;
222 des_read_pw_string (tmp, sizeof (tmp), prompt, 0);
223 if (tmp[0])
224 pass = tmp;
227 n = command ("PASS %s", pass);
229 if (n == CONTINUE) {
230 aflag++;
231 acct = tmp;
232 des_read_pw_string (acct, 128, "Account:", 0);
233 n = command ("ACCT %s", acct);
235 if (n != COMPLETE) {
236 warnx ("Login failed.");
237 return (0);
239 if (!aflag && acct != NULL)
240 command ("ACCT %s", acct);
241 if (proxy)
242 return (1);
243 for (n = 0; n < macnum; ++n) {
244 if (!strcmp("init", macros[n].mac_name)) {
245 strlcpy (line, "$init", sizeof (line));
246 makeargv();
247 domacro(margc, margv);
248 break;
251 sec_set_protection_level ();
252 return (1);
255 void
256 cmdabort (int sig)
259 printf ("\n");
260 fflush (stdout);
261 abrtflag++;
262 if (ptflag)
263 longjmp (ptabort, 1);
267 command (char *fmt,...)
269 va_list ap;
270 int r;
271 sighand oldintr;
273 abrtflag = 0;
274 if (cout == NULL) {
275 warn ("No control connection for command");
276 code = -1;
277 return (0);
279 oldintr = signal(SIGINT, cmdabort);
280 if(debug){
281 printf("---> ");
282 if (strncmp("PASS ", fmt, 5) == 0)
283 printf("PASS XXXX");
284 else {
285 va_start(ap, fmt);
286 vfprintf(stdout, fmt, ap);
287 va_end(ap);
290 va_start(ap, fmt);
291 sec_vfprintf(cout, fmt, ap);
292 va_end(ap);
293 if(debug){
294 printf("\n");
295 fflush(stdout);
297 fprintf (cout, "\r\n");
298 fflush (cout);
299 cpend = 1;
300 r = getreply (!strcmp (fmt, "QUIT"));
301 if (abrtflag && oldintr != SIG_IGN)
302 (*oldintr) (SIGINT);
303 signal (SIGINT, oldintr);
304 return (r);
307 char reply_string[BUFSIZ]; /* last line of previous reply */
310 getreply (int expecteof)
312 char *p;
313 char *lead_string;
314 int c;
315 struct sigaction sa, osa;
316 char buf[8192];
317 int reply_code;
318 int long_warn = 0;
320 sigemptyset (&sa.sa_mask);
321 sa.sa_flags = 0;
322 sa.sa_handler = cmdabort;
323 sigaction (SIGINT, &sa, &osa);
325 p = buf;
327 reply_code = 0;
328 while (1) {
329 c = getc (cin);
330 switch (c) {
331 case EOF:
332 if (expecteof) {
333 sigaction (SIGINT, &osa, NULL);
334 code = 221;
335 return 0;
337 lostpeer (0);
338 if (verbose) {
339 printf ("421 Service not available, "
340 "remote server has closed connection\n");
341 fflush (stdout);
343 code = 421;
344 return (4);
345 case IAC:
346 c = getc (cin);
347 if (c == WILL || c == WONT)
348 fprintf (cout, "%c%c%c", IAC, DONT, getc (cin));
349 if (c == DO || c == DONT)
350 fprintf (cout, "%c%c%c", IAC, WONT, getc (cin));
351 continue;
352 case '\n':
353 *p++ = '\0';
354 if(isdigit(buf[0])){
355 sscanf(buf, "%d", &code);
356 if(code == 631){
357 code = 0;
358 sec_read_msg(buf, prot_safe);
359 sscanf(buf, "%d", &code);
360 lead_string = "S:";
361 } else if(code == 632){
362 code = 0;
363 sec_read_msg(buf, prot_private);
364 sscanf(buf, "%d", &code);
365 lead_string = "P:";
366 }else if(code == 633){
367 code = 0;
368 sec_read_msg(buf, prot_confidential);
369 sscanf(buf, "%d", &code);
370 lead_string = "C:";
371 }else if(sec_complete)
372 lead_string = "!!";
373 else
374 lead_string = "";
375 if(code != 0 && reply_code == 0)
376 reply_code = code;
377 if (verbose > 0 || (verbose > -1 && code > 499))
378 fprintf (stdout, "%s%s\n", lead_string, buf);
379 if (code == reply_code && buf[3] == ' ') {
380 strlcpy (reply_string, buf, sizeof(reply_string));
381 if (code >= 200)
382 cpend = 0;
383 sigaction (SIGINT, &osa, NULL);
384 if (code == 421)
385 lostpeer (0);
386 #if 1
387 if (abrtflag &&
388 osa.sa_handler != cmdabort &&
389 osa.sa_handler != SIG_IGN)
390 osa.sa_handler (SIGINT);
391 #endif
392 if (code == 227 || code == 229) {
393 char *p;
395 p = strchr (reply_string, '(');
396 if (p) {
397 p++;
398 strlcpy(pasv, p, sizeof(pasv));
399 p = strrchr(pasv, ')');
400 if (p)
401 *p = '\0';
404 return code / 100;
406 }else{
407 if(verbose > 0 || (verbose > -1 && code > 499)){
408 if(sec_complete)
409 fprintf(stdout, "!!");
410 fprintf(stdout, "%s\n", buf);
413 p = buf;
414 long_warn = 0;
415 continue;
416 default:
417 if(p < buf + sizeof(buf) - 1)
418 *p++ = c;
419 else if(long_warn == 0) {
420 fprintf(stderr, "WARNING: incredibly long line received\n");
421 long_warn = 1;
429 #if 0
431 getreply (int expecteof)
433 int c, n;
434 int dig;
435 int originalcode = 0, continuation = 0;
436 sighand oldintr;
437 int pflag = 0;
438 char *cp, *pt = pasv;
440 oldintr = signal (SIGINT, cmdabort);
441 for (;;) {
442 dig = n = code = 0;
443 cp = reply_string;
444 while ((c = getc (cin)) != '\n') {
445 if (c == IAC) { /* handle telnet commands */
446 switch (c = getc (cin)) {
447 case WILL:
448 case WONT:
449 c = getc (cin);
450 fprintf (cout, "%c%c%c", IAC, DONT, c);
451 fflush (cout);
452 break;
453 case DO:
454 case DONT:
455 c = getc (cin);
456 fprintf (cout, "%c%c%c", IAC, WONT, c);
457 fflush (cout);
458 break;
459 default:
460 break;
462 continue;
464 dig++;
465 if (c == EOF) {
466 if (expecteof) {
467 signal (SIGINT, oldintr);
468 code = 221;
469 return (0);
471 lostpeer (0);
472 if (verbose) {
473 printf ("421 Service not available, remote server has closed connection\n");
474 fflush (stdout);
476 code = 421;
477 return (4);
479 if (c != '\r' && (verbose > 0 ||
480 (verbose > -1 && n == '5' && dig > 4))) {
481 if (proxflag &&
482 (dig == 1 || dig == 5 && verbose == 0))
483 printf ("%s:", hostname);
484 putchar (c);
486 if (dig < 4 && isdigit (c))
487 code = code * 10 + (c - '0');
488 if (!pflag && code == 227)
489 pflag = 1;
490 if (dig > 4 && pflag == 1 && isdigit (c))
491 pflag = 2;
492 if (pflag == 2) {
493 if (c != '\r' && c != ')')
494 *pt++ = c;
495 else {
496 *pt = '\0';
497 pflag = 3;
500 if (dig == 4 && c == '-') {
501 if (continuation)
502 code = 0;
503 continuation++;
505 if (n == 0)
506 n = c;
507 if (cp < &reply_string[sizeof (reply_string) - 1])
508 *cp++ = c;
510 if (verbose > 0 || verbose > -1 && n == '5') {
511 putchar (c);
512 fflush (stdout);
514 if (continuation && code != originalcode) {
515 if (originalcode == 0)
516 originalcode = code;
517 continue;
519 *cp = '\0';
520 if(sec_complete){
521 if(code == 631)
522 sec_read_msg(reply_string, prot_safe);
523 else if(code == 632)
524 sec_read_msg(reply_string, prot_private);
525 else if(code == 633)
526 sec_read_msg(reply_string, prot_confidential);
527 n = code / 100 + '0';
529 if (n != '1')
530 cpend = 0;
531 signal (SIGINT, oldintr);
532 if (code == 421 || originalcode == 421)
533 lostpeer (0);
534 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
535 (*oldintr) (SIGINT);
536 return (n - '0');
540 #endif
543 empty (fd_set * mask, int sec)
545 struct timeval t;
547 t.tv_sec = sec;
548 t.tv_usec = 0;
549 return (select (FD_SETSIZE, mask, NULL, NULL, &t));
552 jmp_buf sendabort;
554 static RETSIGTYPE
555 abortsend (int sig)
558 mflag = 0;
559 abrtflag = 0;
560 printf ("\nsend aborted\nwaiting for remote to finish abort\n");
561 fflush (stdout);
562 longjmp (sendabort, 1);
565 #define HASHBYTES 1024
567 static int
568 copy_stream (FILE * from, FILE * to)
570 static size_t bufsize;
571 static char *buf;
572 int n;
573 int bytes = 0;
574 int werr = 0;
575 int hashbytes = HASHBYTES;
576 struct stat st;
578 #if defined(HAVE_MMAP) && !defined(NO_MMAP)
579 void *chunk;
581 #ifndef MAP_FAILED
582 #define MAP_FAILED (-1)
583 #endif
585 if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) {
587 * mmap zero bytes has potential of loosing, don't do it.
589 if (st.st_size == 0)
590 return 0;
591 chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
592 if (chunk != (void *) MAP_FAILED) {
593 int res;
595 res = sec_write (fileno (to), chunk, st.st_size);
596 if (munmap (chunk, st.st_size) < 0)
597 warn ("munmap");
598 sec_fflush (to);
599 return res;
602 #endif
604 buf = alloc_buffer (buf, &bufsize,
605 fstat (fileno (from), &st) >= 0 ? &st : NULL);
606 if (buf == NULL)
607 return -1;
609 while ((n = read (fileno (from), buf, bufsize)) > 0) {
610 werr = sec_write (fileno (to), buf, n);
611 if (werr < 0)
612 break;
613 bytes += werr;
614 while (hash && bytes > hashbytes) {
615 putchar ('#');
616 hashbytes += HASHBYTES;
619 sec_fflush (to);
620 if (n < 0)
621 warn ("local");
623 if (werr < 0) {
624 if (errno != EPIPE)
625 warn ("netout");
626 bytes = -1;
628 return bytes;
631 void
632 sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
634 struct stat st;
635 struct timeval start, stop;
636 int c, d;
637 FILE *fin, *dout = 0;
638 int (*closefunc) (FILE *);
639 RETSIGTYPE (*oldintr)(int), (*oldintp)(int);
640 long bytes = 0, hashbytes = HASHBYTES;
641 char *rmode = "w";
643 if (verbose && printnames) {
644 if (local && strcmp (local, "-") != 0)
645 printf ("local: %s ", local);
646 if (remote)
647 printf ("remote: %s\n", remote);
649 if (proxy) {
650 proxtrans (cmd, local, remote);
651 return;
653 if (curtype != type)
654 changetype (type, 0);
655 closefunc = NULL;
656 oldintr = NULL;
657 oldintp = NULL;
659 if (setjmp (sendabort)) {
660 while (cpend) {
661 getreply (0);
663 if (data >= 0) {
664 close (data);
665 data = -1;
667 if (oldintr)
668 signal (SIGINT, oldintr);
669 if (oldintp)
670 signal (SIGPIPE, oldintp);
671 code = -1;
672 return;
674 oldintr = signal (SIGINT, abortsend);
675 if (strcmp (local, "-") == 0)
676 fin = stdin;
677 else if (*local == '|') {
678 oldintp = signal (SIGPIPE, SIG_IGN);
679 fin = popen (local + 1, lmode);
680 if (fin == NULL) {
681 warn ("%s", local + 1);
682 signal (SIGINT, oldintr);
683 signal (SIGPIPE, oldintp);
684 code = -1;
685 return;
687 closefunc = pclose;
688 } else {
689 fin = fopen (local, lmode);
690 if (fin == NULL) {
691 warn ("local: %s", local);
692 signal (SIGINT, oldintr);
693 code = -1;
694 return;
696 closefunc = fclose;
697 if (fstat (fileno (fin), &st) < 0 ||
698 (st.st_mode & S_IFMT) != S_IFREG) {
699 fprintf (stdout, "%s: not a plain file.\n", local);
700 signal (SIGINT, oldintr);
701 fclose (fin);
702 code = -1;
703 return;
706 if (initconn ()) {
707 signal (SIGINT, oldintr);
708 if (oldintp)
709 signal (SIGPIPE, oldintp);
710 code = -1;
711 if (closefunc != NULL)
712 (*closefunc) (fin);
713 return;
715 if (setjmp (sendabort))
716 goto abort;
718 if (restart_point &&
719 (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
720 int rc;
722 switch (curtype) {
723 case TYPE_A:
724 rc = fseek (fin, (long) restart_point, SEEK_SET);
725 break;
726 case TYPE_I:
727 case TYPE_L:
728 rc = lseek (fileno (fin), restart_point, SEEK_SET);
729 break;
731 if (rc < 0) {
732 warn ("local: %s", local);
733 restart_point = 0;
734 if (closefunc != NULL)
735 (*closefunc) (fin);
736 return;
738 if (command ("REST %ld", (long) restart_point)
739 != CONTINUE) {
740 restart_point = 0;
741 if (closefunc != NULL)
742 (*closefunc) (fin);
743 return;
745 restart_point = 0;
746 rmode = "r+w";
748 if (remote) {
749 if (command ("%s %s", cmd, remote) != PRELIM) {
750 signal (SIGINT, oldintr);
751 if (oldintp)
752 signal (SIGPIPE, oldintp);
753 if (closefunc != NULL)
754 (*closefunc) (fin);
755 return;
757 } else if (command ("%s", cmd) != PRELIM) {
758 signal(SIGINT, oldintr);
759 if (oldintp)
760 signal(SIGPIPE, oldintp);
761 if (closefunc != NULL)
762 (*closefunc)(fin);
763 return;
765 dout = dataconn(rmode);
766 if (dout == NULL)
767 goto abort;
768 set_buffer_size (fileno (dout), 0);
769 gettimeofday (&start, (struct timezone *) 0);
770 oldintp = signal (SIGPIPE, SIG_IGN);
771 switch (curtype) {
773 case TYPE_I:
774 case TYPE_L:
775 errno = d = c = 0;
776 bytes = copy_stream (fin, dout);
777 break;
779 case TYPE_A:
780 while ((c = getc (fin)) != EOF) {
781 if (c == '\n') {
782 while (hash && (bytes >= hashbytes)) {
783 putchar ('#');
784 fflush (stdout);
785 hashbytes += HASHBYTES;
787 if (ferror (dout))
788 break;
789 sec_putc ('\r', dout);
790 bytes++;
792 sec_putc (c, dout);
793 bytes++;
795 sec_fflush (dout);
796 if (hash) {
797 if (bytes < hashbytes)
798 putchar ('#');
799 putchar ('\n');
800 fflush (stdout);
802 if (ferror (fin))
803 warn ("local: %s", local);
804 if (ferror (dout)) {
805 if (errno != EPIPE)
806 warn ("netout");
807 bytes = -1;
809 break;
811 if (closefunc != NULL)
812 (*closefunc) (fin);
813 fclose (dout);
814 gettimeofday (&stop, (struct timezone *) 0);
815 getreply (0);
816 signal (SIGINT, oldintr);
817 if (oldintp)
818 signal (SIGPIPE, oldintp);
819 if (bytes > 0)
820 ptransfer ("sent", bytes, &start, &stop);
821 return;
822 abort:
823 signal (SIGINT, oldintr);
824 if (oldintp)
825 signal (SIGPIPE, oldintp);
826 if (!cpend) {
827 code = -1;
828 return;
830 if (data >= 0) {
831 close (data);
832 data = -1;
834 if (dout)
835 fclose (dout);
836 getreply (0);
837 code = -1;
838 if (closefunc != NULL && fin != NULL)
839 (*closefunc) (fin);
840 gettimeofday (&stop, (struct timezone *) 0);
841 if (bytes > 0)
842 ptransfer ("sent", bytes, &start, &stop);
845 jmp_buf recvabort;
847 void
848 abortrecv (int sig)
851 mflag = 0;
852 abrtflag = 0;
853 printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
854 fflush (stdout);
855 longjmp (recvabort, 1);
858 void
859 recvrequest (char *cmd, char *local, char *remote,
860 char *lmode, int printnames, int local_given)
862 FILE *fout, *din = 0;
863 int (*closefunc) (FILE *);
864 sighand oldintr, oldintp;
865 int c, d, is_retr, tcrflag, bare_lfs = 0;
866 static size_t bufsize;
867 static char *buf;
868 long bytes = 0, hashbytes = HASHBYTES;
869 struct timeval start, stop;
870 struct stat st;
872 is_retr = strcmp (cmd, "RETR") == 0;
873 if (is_retr && verbose && printnames) {
874 if (local && strcmp (local, "-") != 0)
875 printf ("local: %s ", local);
876 if (remote)
877 printf ("remote: %s\n", remote);
879 if (proxy && is_retr) {
880 proxtrans (cmd, local, remote);
881 return;
883 closefunc = NULL;
884 oldintr = NULL;
885 oldintp = NULL;
886 tcrflag = !crflag && is_retr;
887 if (setjmp (recvabort)) {
888 while (cpend) {
889 getreply (0);
891 if (data >= 0) {
892 close (data);
893 data = -1;
895 if (oldintr)
896 signal (SIGINT, oldintr);
897 code = -1;
898 return;
900 oldintr = signal (SIGINT, abortrecv);
901 if (!local_given || (strcmp (local, "-") && *local != '|')) {
902 if (access (local, 2) < 0) {
903 char *dir = strrchr (local, '/');
905 if (errno != ENOENT && errno != EACCES) {
906 warn ("local: %s", local);
907 signal (SIGINT, oldintr);
908 code = -1;
909 return;
911 if (dir != NULL)
912 *dir = 0;
913 d = access (dir ? local : ".", 2);
914 if (dir != NULL)
915 *dir = '/';
916 if (d < 0) {
917 warn ("local: %s", local);
918 signal (SIGINT, oldintr);
919 code = -1;
920 return;
922 if (!runique && errno == EACCES &&
923 chmod (local, 0600) < 0) {
924 warn ("local: %s", local);
925 signal (SIGINT, oldintr);
926 signal (SIGINT, oldintr);
927 code = -1;
928 return;
930 if (runique && errno == EACCES &&
931 (local = gunique (local)) == NULL) {
932 signal (SIGINT, oldintr);
933 code = -1;
934 return;
936 } else if (runique && (local = gunique (local)) == NULL) {
937 signal(SIGINT, oldintr);
938 code = -1;
939 return;
942 if (!is_retr) {
943 if (curtype != TYPE_A)
944 changetype (TYPE_A, 0);
945 } else if (curtype != type)
946 changetype (type, 0);
947 if (initconn ()) {
948 signal (SIGINT, oldintr);
949 code = -1;
950 return;
952 if (setjmp (recvabort))
953 goto abort;
954 if (is_retr && restart_point &&
955 command ("REST %ld", (long) restart_point) != CONTINUE)
956 return;
957 if (remote) {
958 if (command ("%s %s", cmd, remote) != PRELIM) {
959 signal (SIGINT, oldintr);
960 return;
962 } else {
963 if (command ("%s", cmd) != PRELIM) {
964 signal (SIGINT, oldintr);
965 return;
968 din = dataconn ("r");
969 if (din == NULL)
970 goto abort;
971 set_buffer_size (fileno (din), 1);
972 if (local_given && strcmp (local, "-") == 0)
973 fout = stdout;
974 else if (local_given && *local == '|') {
975 oldintp = signal (SIGPIPE, SIG_IGN);
976 fout = popen (local + 1, "w");
977 if (fout == NULL) {
978 warn ("%s", local + 1);
979 goto abort;
981 closefunc = pclose;
982 } else {
983 fout = fopen (local, lmode);
984 if (fout == NULL) {
985 warn ("local: %s", local);
986 goto abort;
988 closefunc = fclose;
990 buf = alloc_buffer (buf, &bufsize,
991 fstat (fileno (fout), &st) >= 0 ? &st : NULL);
992 if (buf == NULL)
993 goto abort;
995 gettimeofday (&start, (struct timezone *) 0);
996 switch (curtype) {
998 case TYPE_I:
999 case TYPE_L:
1000 if (restart_point &&
1001 lseek (fileno (fout), restart_point, SEEK_SET) < 0) {
1002 warn ("local: %s", local);
1003 if (closefunc != NULL)
1004 (*closefunc) (fout);
1005 return;
1007 errno = d = 0;
1008 while ((c = sec_read (fileno (din), buf, bufsize)) > 0) {
1009 if ((d = write (fileno (fout), buf, c)) != c)
1010 break;
1011 bytes += c;
1012 if (hash) {
1013 while (bytes >= hashbytes) {
1014 putchar ('#');
1015 hashbytes += HASHBYTES;
1017 fflush (stdout);
1020 if (hash && bytes > 0) {
1021 if (bytes < HASHBYTES)
1022 putchar ('#');
1023 putchar ('\n');
1024 fflush (stdout);
1026 if (c < 0) {
1027 if (errno != EPIPE)
1028 warn ("netin");
1029 bytes = -1;
1031 if (d < c) {
1032 if (d < 0)
1033 warn ("local: %s", local);
1034 else
1035 warnx ("%s: short write", local);
1037 break;
1039 case TYPE_A:
1040 if (restart_point) {
1041 int i, n, ch;
1043 if (fseek (fout, 0L, SEEK_SET) < 0)
1044 goto done;
1045 n = restart_point;
1046 for (i = 0; i++ < n;) {
1047 if ((ch = sec_getc (fout)) == EOF)
1048 goto done;
1049 if (ch == '\n')
1050 i++;
1052 if (fseek (fout, 0L, SEEK_CUR) < 0) {
1053 done:
1054 warn ("local: %s", local);
1055 if (closefunc != NULL)
1056 (*closefunc) (fout);
1057 return;
1060 while ((c = sec_getc(din)) != EOF) {
1061 if (c == '\n')
1062 bare_lfs++;
1063 while (c == '\r') {
1064 while (hash && (bytes >= hashbytes)) {
1065 putchar ('#');
1066 fflush (stdout);
1067 hashbytes += HASHBYTES;
1069 bytes++;
1070 if ((c = sec_getc (din)) != '\n' || tcrflag) {
1071 if (ferror (fout))
1072 goto break2;
1073 putc ('\r', fout);
1074 if (c == '\0') {
1075 bytes++;
1076 goto contin2;
1078 if (c == EOF)
1079 goto contin2;
1082 putc (c, fout);
1083 bytes++;
1084 contin2:;
1086 break2:
1087 if (bare_lfs) {
1088 printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
1089 bare_lfs);
1090 printf ("File may not have transferred correctly.\n");
1092 if (hash) {
1093 if (bytes < hashbytes)
1094 putchar ('#');
1095 putchar ('\n');
1096 fflush (stdout);
1098 if (ferror (din)) {
1099 if (errno != EPIPE)
1100 warn ("netin");
1101 bytes = -1;
1103 if (ferror (fout))
1104 warn ("local: %s", local);
1105 break;
1107 if (closefunc != NULL)
1108 (*closefunc) (fout);
1109 signal (SIGINT, oldintr);
1110 if (oldintp)
1111 signal (SIGPIPE, oldintp);
1112 fclose (din);
1113 gettimeofday (&stop, (struct timezone *) 0);
1114 getreply (0);
1115 if (bytes > 0 && is_retr)
1116 ptransfer ("received", bytes, &start, &stop);
1117 return;
1118 abort:
1120 /* abort using RFC959 recommended IP,SYNC sequence */
1122 if (oldintp)
1123 signal (SIGPIPE, oldintr);
1124 signal (SIGINT, SIG_IGN);
1125 if (!cpend) {
1126 code = -1;
1127 signal (SIGINT, oldintr);
1128 return;
1130 abort_remote(din);
1131 code = -1;
1132 if (data >= 0) {
1133 close (data);
1134 data = -1;
1136 if (closefunc != NULL && fout != NULL)
1137 (*closefunc) (fout);
1138 if (din)
1139 fclose (din);
1140 gettimeofday (&stop, (struct timezone *) 0);
1141 if (bytes > 0)
1142 ptransfer ("received", bytes, &start, &stop);
1143 signal (SIGINT, oldintr);
1146 static int
1147 parse_epsv (const char *str)
1149 char sep;
1150 char *end;
1151 int port;
1153 if (*str == '\0')
1154 return -1;
1155 sep = *str++;
1156 if (sep != *str++)
1157 return -1;
1158 if (sep != *str++)
1159 return -1;
1160 port = strtol (str, &end, 0);
1161 if (str == end)
1162 return -1;
1163 if (end[0] != sep || end[1] != '\0')
1164 return -1;
1165 return htons(port);
1168 static int
1169 parse_pasv (struct sockaddr_in *sin, const char *str)
1171 int a0, a1, a2, a3, p0, p1;
1174 * What we've got at this point is a string of comma separated
1175 * one-byte unsigned integer values. The first four are the an IP
1176 * address. The fifth is the MSB of the port number, the sixth is the
1177 * LSB. From that we'll prepare a sockaddr_in.
1180 if (sscanf (str, "%d,%d,%d,%d,%d,%d",
1181 &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1182 printf ("Passive mode address scan failure. "
1183 "Shouldn't happen!\n");
1184 return -1;
1186 if (a0 < 0 || a0 > 255 ||
1187 a1 < 0 || a1 > 255 ||
1188 a2 < 0 || a2 > 255 ||
1189 a3 < 0 || a3 > 255 ||
1190 p0 < 0 || p0 > 255 ||
1191 p1 < 0 || p1 > 255) {
1192 printf ("Can't parse passive mode string.\n");
1193 return -1;
1195 memset (sin, 0, sizeof(*sin));
1196 sin->sin_family = AF_INET;
1197 sin->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
1198 (a2 << 8) | a3);
1199 sin->sin_port = htons ((p0 << 8) | p1);
1200 return 0;
1203 static int
1204 passive_mode (void)
1206 int port;
1208 data = socket (myctladdr->sa_family, SOCK_STREAM, 0);
1209 if (data < 0) {
1210 warn ("socket");
1211 return (1);
1213 if (options & SO_DEBUG)
1214 socket_set_debug (data);
1215 if (command ("EPSV") != COMPLETE) {
1216 if (command ("PASV") != COMPLETE) {
1217 printf ("Passive mode refused.\n");
1218 goto bad;
1223 * Parse the reply to EPSV or PASV
1226 port = parse_epsv (pasv);
1227 if (port > 0) {
1228 data_addr->sa_family = myctladdr->sa_family;
1229 socket_set_address_and_port (data_addr,
1230 socket_get_address (hisctladdr),
1231 port);
1232 } else {
1233 if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0)
1234 goto bad;
1237 if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1238 warn ("connect");
1239 goto bad;
1241 #ifdef IPTOS_THROUGHPUT
1242 socket_set_tos (data, IPTOS_THROUGHPUT);
1243 #endif
1244 return (0);
1245 bad:
1246 close (data);
1247 data = -1;
1248 sendport = 1;
1249 return (1);
1253 static int
1254 active_mode (void)
1256 int tmpno = 0;
1257 socklen_t len;
1258 int result;
1260 noport:
1261 data_addr->sa_family = myctladdr->sa_family;
1262 socket_set_address_and_port (data_addr, socket_get_address (myctladdr),
1263 sendport ? 0 : socket_get_port (myctladdr));
1265 if (data != -1)
1266 close (data);
1267 data = socket (data_addr->sa_family, SOCK_STREAM, 0);
1268 if (data < 0) {
1269 warn ("socket");
1270 if (tmpno)
1271 sendport = 1;
1272 return (1);
1274 if (!sendport)
1275 socket_set_reuseaddr (data, 1);
1276 if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1277 warn ("bind");
1278 goto bad;
1280 if (options & SO_DEBUG)
1281 socket_set_debug (data);
1282 len = sizeof (data_addr_ss);
1283 if (getsockname (data, data_addr, &len) < 0) {
1284 warn ("getsockname");
1285 goto bad;
1287 if (listen (data, 1) < 0)
1288 warn ("listen");
1289 if (sendport) {
1290 char addr_str[256];
1291 int inet_af;
1292 int overbose;
1294 if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr),
1295 addr_str, sizeof(addr_str)) == NULL)
1296 errx (1, "inet_ntop failed");
1297 switch (data_addr->sa_family) {
1298 case AF_INET :
1299 inet_af = 1;
1300 break;
1301 #ifdef HAVE_IPV6
1302 case AF_INET6 :
1303 inet_af = 2;
1304 break;
1305 #endif
1306 default :
1307 errx (1, "bad address family %d", data_addr->sa_family);
1311 overbose = verbose;
1312 if (debug == 0)
1313 verbose = -1;
1315 result = command ("EPRT |%d|%s|%d|",
1316 inet_af, addr_str,
1317 ntohs(socket_get_port (data_addr)));
1318 verbose = overbose;
1320 if (result == ERROR) {
1321 struct sockaddr_in *sin = (struct sockaddr_in *)data_addr;
1323 unsigned int a = ntohl(sin->sin_addr.s_addr);
1324 unsigned int p = ntohs(sin->sin_port);
1326 if (data_addr->sa_family != AF_INET) {
1327 warnx ("remote server doesn't support EPRT");
1328 goto bad;
1331 result = command("PORT %d,%d,%d,%d,%d,%d",
1332 (a >> 24) & 0xff,
1333 (a >> 16) & 0xff,
1334 (a >> 8) & 0xff,
1335 a & 0xff,
1336 (p >> 8) & 0xff,
1337 p & 0xff);
1338 if (result == ERROR && sendport == -1) {
1339 sendport = 0;
1340 tmpno = 1;
1341 goto noport;
1343 return (result != COMPLETE);
1345 return result != COMPLETE;
1347 if (tmpno)
1348 sendport = 1;
1351 #ifdef IPTOS_THROUGHPUT
1352 socket_set_tos (data, IPTOS_THROUGHPUT);
1353 #endif
1354 return (0);
1355 bad:
1356 close (data);
1357 data = -1;
1358 if (tmpno)
1359 sendport = 1;
1360 return (1);
1364 * Need to start a listen on the data channel before we send the command,
1365 * otherwise the server's connect may fail.
1368 initconn (void)
1370 if (passivemode)
1371 return passive_mode ();
1372 else
1373 return active_mode ();
1376 FILE *
1377 dataconn (const char *lmode)
1379 struct sockaddr_storage from_ss;
1380 struct sockaddr *from = (struct sockaddr *)&from_ss;
1381 socklen_t fromlen = sizeof(from_ss);
1382 int s;
1384 if (passivemode)
1385 return (fdopen (data, lmode));
1387 s = accept (data, from, &fromlen);
1388 if (s < 0) {
1389 warn ("accept");
1390 close (data), data = -1;
1391 return (NULL);
1393 close (data);
1394 data = s;
1395 #ifdef IPTOS_THROUGHPUT
1396 socket_set_tos (s, IPTOS_THROUGHPUT);
1397 #endif
1398 return (fdopen (data, lmode));
1401 void
1402 ptransfer (char *direction, long int bytes,
1403 struct timeval * t0, struct timeval * t1)
1405 struct timeval td;
1406 float s;
1407 float bs;
1408 int prec;
1409 char *unit;
1411 if (verbose) {
1412 td.tv_sec = t1->tv_sec - t0->tv_sec;
1413 td.tv_usec = t1->tv_usec - t0->tv_usec;
1414 if (td.tv_usec < 0) {
1415 td.tv_sec--;
1416 td.tv_usec += 1000000;
1418 s = td.tv_sec + (td.tv_usec / 1000000.);
1419 bs = bytes / (s ? s : 1);
1420 if (bs >= 1048576) {
1421 bs /= 1048576;
1422 unit = "M";
1423 prec = 2;
1424 } else if (bs >= 1024) {
1425 bs /= 1024;
1426 unit = "k";
1427 prec = 1;
1428 } else {
1429 unit = "";
1430 prec = 0;
1433 printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
1434 bytes, direction, s, prec, bs, unit);
1438 void
1439 psabort (int sig)
1442 abrtflag++;
1445 void
1446 pswitch (int flag)
1448 sighand oldintr;
1449 static struct comvars {
1450 int connect;
1451 char name[MaxHostNameLen];
1452 struct sockaddr_storage mctl;
1453 struct sockaddr_storage hctl;
1454 FILE *in;
1455 FILE *out;
1456 int tpe;
1457 int curtpe;
1458 int cpnd;
1459 int sunqe;
1460 int runqe;
1461 int mcse;
1462 int ntflg;
1463 char nti[17];
1464 char nto[17];
1465 int mapflg;
1466 char mi[MaxPathLen];
1467 char mo[MaxPathLen];
1468 } proxstruct, tmpstruct;
1469 struct comvars *ip, *op;
1471 abrtflag = 0;
1472 oldintr = signal (SIGINT, psabort);
1473 if (flag) {
1474 if (proxy)
1475 return;
1476 ip = &tmpstruct;
1477 op = &proxstruct;
1478 proxy++;
1479 } else {
1480 if (!proxy)
1481 return;
1482 ip = &proxstruct;
1483 op = &tmpstruct;
1484 proxy = 0;
1486 ip->connect = connected;
1487 connected = op->connect;
1488 if (hostname) {
1489 strlcpy (ip->name, hostname, sizeof (ip->name));
1490 } else
1491 ip->name[0] = 0;
1492 hostname = op->name;
1493 ip->hctl = hisctladdr_ss;
1494 hisctladdr_ss = op->hctl;
1495 ip->mctl = myctladdr_ss;
1496 myctladdr_ss = op->mctl;
1497 ip->in = cin;
1498 cin = op->in;
1499 ip->out = cout;
1500 cout = op->out;
1501 ip->tpe = type;
1502 type = op->tpe;
1503 ip->curtpe = curtype;
1504 curtype = op->curtpe;
1505 ip->cpnd = cpend;
1506 cpend = op->cpnd;
1507 ip->sunqe = sunique;
1508 sunique = op->sunqe;
1509 ip->runqe = runique;
1510 runique = op->runqe;
1511 ip->mcse = mcase;
1512 mcase = op->mcse;
1513 ip->ntflg = ntflag;
1514 ntflag = op->ntflg;
1515 strlcpy (ip->nti, ntin, sizeof (ip->nti));
1516 strlcpy (ntin, op->nti, 17);
1517 strlcpy (ip->nto, ntout, sizeof (ip->nto));
1518 strlcpy (ntout, op->nto, 17);
1519 ip->mapflg = mapflag;
1520 mapflag = op->mapflg;
1521 strlcpy (ip->mi, mapin, MaxPathLen);
1522 strlcpy (mapin, op->mi, MaxPathLen);
1523 strlcpy (ip->mo, mapout, MaxPathLen);
1524 strlcpy (mapout, op->mo, MaxPathLen);
1525 signal(SIGINT, oldintr);
1526 if (abrtflag) {
1527 abrtflag = 0;
1528 (*oldintr) (SIGINT);
1532 void
1533 abortpt (int sig)
1536 printf ("\n");
1537 fflush (stdout);
1538 ptabflg++;
1539 mflag = 0;
1540 abrtflag = 0;
1541 longjmp (ptabort, 1);
1544 void
1545 proxtrans (char *cmd, char *local, char *remote)
1547 sighand oldintr;
1548 int secndflag = 0, prox_type, nfnd;
1549 char *cmd2;
1550 fd_set mask;
1552 if (strcmp (cmd, "RETR"))
1553 cmd2 = "RETR";
1554 else
1555 cmd2 = runique ? "STOU" : "STOR";
1556 if ((prox_type = type) == 0) {
1557 if (unix_server && unix_proxy)
1558 prox_type = TYPE_I;
1559 else
1560 prox_type = TYPE_A;
1562 if (curtype != prox_type)
1563 changetype (prox_type, 1);
1564 if (command ("PASV") != COMPLETE) {
1565 printf ("proxy server does not support third party transfers.\n");
1566 return;
1568 pswitch (0);
1569 if (!connected) {
1570 printf ("No primary connection\n");
1571 pswitch (1);
1572 code = -1;
1573 return;
1575 if (curtype != prox_type)
1576 changetype (prox_type, 1);
1577 if (command ("PORT %s", pasv) != COMPLETE) {
1578 pswitch (1);
1579 return;
1581 if (setjmp (ptabort))
1582 goto abort;
1583 oldintr = signal (SIGINT, abortpt);
1584 if (command ("%s %s", cmd, remote) != PRELIM) {
1585 signal (SIGINT, oldintr);
1586 pswitch (1);
1587 return;
1589 sleep (2);
1590 pswitch (1);
1591 secndflag++;
1592 if (command ("%s %s", cmd2, local) != PRELIM)
1593 goto abort;
1594 ptflag++;
1595 getreply (0);
1596 pswitch (0);
1597 getreply (0);
1598 signal (SIGINT, oldintr);
1599 pswitch (1);
1600 ptflag = 0;
1601 printf ("local: %s remote: %s\n", local, remote);
1602 return;
1603 abort:
1604 signal (SIGINT, SIG_IGN);
1605 ptflag = 0;
1606 if (strcmp (cmd, "RETR") && !proxy)
1607 pswitch (1);
1608 else if (!strcmp (cmd, "RETR") && proxy)
1609 pswitch (0);
1610 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1611 if (command ("%s %s", cmd2, local) != PRELIM) {
1612 pswitch (0);
1613 if (cpend)
1614 abort_remote ((FILE *) NULL);
1616 pswitch (1);
1617 if (ptabflg)
1618 code = -1;
1619 signal (SIGINT, oldintr);
1620 return;
1622 if (cpend)
1623 abort_remote ((FILE *) NULL);
1624 pswitch (!proxy);
1625 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1626 if (command ("%s %s", cmd2, local) != PRELIM) {
1627 pswitch (0);
1628 if (cpend)
1629 abort_remote ((FILE *) NULL);
1630 pswitch (1);
1631 if (ptabflg)
1632 code = -1;
1633 signal (SIGINT, oldintr);
1634 return;
1637 if (cpend)
1638 abort_remote ((FILE *) NULL);
1639 pswitch (!proxy);
1640 if (cpend) {
1641 FD_ZERO (&mask);
1642 if (fileno(cin) >= FD_SETSIZE)
1643 errx (1, "fd too large");
1644 FD_SET (fileno (cin), &mask);
1645 if ((nfnd = empty (&mask, 10)) <= 0) {
1646 if (nfnd < 0) {
1647 warn ("abort");
1649 if (ptabflg)
1650 code = -1;
1651 lostpeer (0);
1653 getreply (0);
1654 getreply (0);
1656 if (proxy)
1657 pswitch (0);
1658 pswitch (1);
1659 if (ptabflg)
1660 code = -1;
1661 signal (SIGINT, oldintr);
1664 void
1665 reset (int argc, char **argv)
1667 fd_set mask;
1668 int nfnd = 1;
1670 FD_ZERO (&mask);
1671 while (nfnd > 0) {
1672 if (fileno (cin) >= FD_SETSIZE)
1673 errx (1, "fd too large");
1674 FD_SET (fileno (cin), &mask);
1675 if ((nfnd = empty (&mask, 0)) < 0) {
1676 warn ("reset");
1677 code = -1;
1678 lostpeer(0);
1679 } else if (nfnd) {
1680 getreply(0);
1685 char *
1686 gunique (char *local)
1688 static char new[MaxPathLen];
1689 char *cp = strrchr (local, '/');
1690 int d, count = 0;
1691 char ext = '1';
1693 if (cp)
1694 *cp = '\0';
1695 d = access (cp ? local : ".", 2);
1696 if (cp)
1697 *cp = '/';
1698 if (d < 0) {
1699 warn ("local: %s", local);
1700 return NULL;
1702 strlcpy (new, local, sizeof(new));
1703 cp = new + strlen(new);
1704 *cp++ = '.';
1705 while (!d) {
1706 if (++count == 100) {
1707 printf ("runique: can't find unique file name.\n");
1708 return NULL;
1710 *cp++ = ext;
1711 *cp = '\0';
1712 if (ext == '9')
1713 ext = '0';
1714 else
1715 ext++;
1716 if ((d = access (new, 0)) < 0)
1717 break;
1718 if (ext != '0')
1719 cp--;
1720 else if (*(cp - 2) == '.')
1721 *(cp - 1) = '1';
1722 else {
1723 *(cp - 2) = *(cp - 2) + 1;
1724 cp--;
1727 return (new);
1730 void
1731 abort_remote (FILE * din)
1733 char buf[BUFSIZ];
1734 int nfnd;
1735 fd_set mask;
1738 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1739 * after urgent byte rather than before as is protocol now
1741 snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC);
1742 if (send (fileno (cout), buf, 3, MSG_OOB) != 3)
1743 warn ("abort");
1744 fprintf (cout, "%cABOR\r\n", DM);
1745 fflush (cout);
1746 FD_ZERO (&mask);
1747 if (fileno (cin) >= FD_SETSIZE)
1748 errx (1, "fd too large");
1749 FD_SET (fileno (cin), &mask);
1750 if (din) {
1751 if (fileno (din) >= FD_SETSIZE)
1752 errx (1, "fd too large");
1753 FD_SET (fileno (din), &mask);
1755 if ((nfnd = empty (&mask, 10)) <= 0) {
1756 if (nfnd < 0) {
1757 warn ("abort");
1759 if (ptabflg)
1760 code = -1;
1761 lostpeer (0);
1763 if (din && FD_ISSET (fileno (din), &mask)) {
1764 while (read (fileno (din), buf, BUFSIZ) > 0)
1765 /* LOOP */ ;
1767 if (getreply (0) == ERROR && code == 552) {
1768 /* 552 needed for nic style abort */
1769 getreply (0);
1771 getreply (0);