23217: Use the correct length for unmap, msync
[heimdal.git] / appl / ftp / ftp / ftp.c
blobc5b29f7b86f5f7d7611d3eeb5422c9425cf57b9b
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 s = -1;
83 for (a = ai; a != NULL; a = a->ai_next) {
84 s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
85 if (s < 0)
86 continue;
88 if (a->ai_canonname != NULL)
89 strlcpy (hostnamebuf, a->ai_canonname, sizeof(hostnamebuf));
91 memcpy (hisctladdr, a->ai_addr, a->ai_addrlen);
93 error = connect (s, a->ai_addr, a->ai_addrlen);
94 if (error < 0) {
95 char addrstr[256];
97 if (getnameinfo (a->ai_addr, a->ai_addrlen,
98 addrstr, sizeof(addrstr),
99 NULL, 0, NI_NUMERICHOST) != 0)
100 strlcpy (addrstr, "unknown address", sizeof(addrstr));
102 warn ("connect %s", addrstr);
103 close (s);
104 s = -1;
105 continue;
107 break;
109 freeaddrinfo (ai);
110 if (s < 0) {
111 warnx ("failed to contact %s", host);
112 code = -1;
113 return NULL;
116 len = sizeof(myctladdr_ss);
117 if (getsockname (s, myctladdr, &len) < 0) {
118 warn ("getsockname");
119 code = -1;
120 close (s);
121 return NULL;
123 #ifdef IPTOS_LOWDELAY
124 socket_set_tos (s, IPTOS_LOWDELAY);
125 #endif
126 cin = fdopen (s, "r");
127 cout = fdopen (s, "w");
128 if (cin == NULL || cout == NULL) {
129 warnx ("fdopen failed.");
130 if (cin)
131 fclose (cin);
132 if (cout)
133 fclose (cout);
134 code = -1;
135 goto bad;
137 if (verbose)
138 printf ("Connected to %s.\n", hostname);
139 if (getreply (0) > 2) { /* read startup message from server */
140 if (cin)
141 fclose (cin);
142 if (cout)
143 fclose (cout);
144 code = -1;
145 goto bad;
147 #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
149 int on = 1;
151 if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
152 < 0 && debug) {
153 warn ("setsockopt");
156 #endif /* SO_OOBINLINE */
158 return (hostname);
159 bad:
160 close (s);
161 return NULL;
165 login (char *host)
167 char tmp[80];
168 char defaultpass[128];
169 char *userstr, *pass, *acctstr;
170 int n, aflag = 0;
172 char *myname = NULL;
173 struct passwd *pw = k_getpwuid(getuid());
175 if (pw != NULL)
176 myname = pw->pw_name;
178 userstr = pass = acctstr = 0;
180 if(sec_login(host))
181 printf("\n*** Using plaintext user and password ***\n\n");
182 else{
183 printf("Authentication successful.\n\n");
186 if (ruserpass (host, &userstr, &pass, &acctstr) < 0) {
187 code = -1;
188 return (0);
190 while (userstr == NULL) {
191 if (myname)
192 printf ("Name (%s:%s): ", host, myname);
193 else
194 printf ("Name (%s): ", host);
195 *tmp = '\0';
196 if (fgets (tmp, sizeof (tmp) - 1, stdin) != NULL)
197 tmp[strlen (tmp) - 1] = '\0';
198 if (*tmp == '\0')
199 userstr = myname;
200 else
201 userstr = tmp;
203 strlcpy(username, userstr, sizeof(username));
204 n = command("USER %s", userstr);
205 if (n == COMPLETE)
206 n = command("PASS dummy"); /* DK: Compatibility with gssftp daemon */
207 else if(n == CONTINUE) {
208 if (pass == NULL) {
209 char prompt[128];
210 if(myname &&
211 (!strcmp(userstr, "ftp") || !strcmp(userstr, "anonymous"))) {
212 snprintf(defaultpass, sizeof(defaultpass),
213 "%s@%s", myname, mydomain);
214 snprintf(prompt, sizeof(prompt),
215 "Password (%s): ", defaultpass);
216 } else if (sec_complete) {
217 pass = myname;
218 } else {
219 *defaultpass = '\0';
220 snprintf(prompt, sizeof(prompt), "Password: ");
222 if (pass == NULL) {
223 pass = defaultpass;
224 UI_UTIL_read_pw_string (tmp, sizeof (tmp), prompt, 0);
225 if (tmp[0])
226 pass = tmp;
229 n = command ("PASS %s", pass);
231 if (n == CONTINUE) {
232 aflag++;
233 acctstr = tmp;
234 UI_UTIL_read_pw_string (acctstr, 128, "Account:", 0);
235 n = command ("ACCT %s", acctstr);
237 if (n != COMPLETE) {
238 warnx ("Login failed.");
239 return (0);
241 if (!aflag && acctstr != NULL)
242 command ("ACCT %s", acctstr);
243 if (proxy)
244 return (1);
245 for (n = 0; n < macnum; ++n) {
246 if (!strcmp("init", macros[n].mac_name)) {
247 strlcpy (line, "$init", sizeof (line));
248 makeargv();
249 domacro(margc, margv);
250 break;
253 sec_set_protection_level ();
254 return (1);
257 void
258 cmdabort (int sig)
261 printf ("\n");
262 fflush (stdout);
263 abrtflag++;
264 if (ptflag)
265 longjmp (ptabort, 1);
269 command (char *fmt,...)
271 va_list ap;
272 int r;
273 sighand oldintr;
275 abrtflag = 0;
276 if (cout == NULL) {
277 warn ("No control connection for command");
278 code = -1;
279 return (0);
281 oldintr = signal(SIGINT, cmdabort);
282 if(debug){
283 printf("---> ");
284 if (strncmp("PASS ", fmt, 5) == 0)
285 printf("PASS XXXX");
286 else {
287 va_start(ap, fmt);
288 vfprintf(stdout, fmt, ap);
289 va_end(ap);
292 va_start(ap, fmt);
293 sec_vfprintf(cout, fmt, ap);
294 va_end(ap);
295 if(debug){
296 printf("\n");
297 fflush(stdout);
299 fprintf (cout, "\r\n");
300 fflush (cout);
301 cpend = 1;
302 r = getreply (!strcmp (fmt, "QUIT"));
303 if (abrtflag && oldintr != SIG_IGN)
304 (*oldintr) (SIGINT);
305 signal (SIGINT, oldintr);
306 return (r);
309 char reply_string[BUFSIZ]; /* last line of previous reply */
312 getreply (int expecteof)
314 char *p;
315 char *lead_string;
316 int c;
317 struct sigaction sa, osa;
318 char buf[8192];
319 int reply_code;
320 int long_warn = 0;
322 sigemptyset (&sa.sa_mask);
323 sa.sa_flags = 0;
324 sa.sa_handler = cmdabort;
325 sigaction (SIGINT, &sa, &osa);
327 p = buf;
329 reply_code = 0;
330 while (1) {
331 c = getc (cin);
332 switch (c) {
333 case EOF:
334 if (expecteof) {
335 sigaction (SIGINT, &osa, NULL);
336 code = 221;
337 return 0;
339 lostpeer (0);
340 if (verbose) {
341 printf ("421 Service not available, "
342 "remote server has closed connection\n");
343 fflush (stdout);
345 code = 421;
346 return (4);
347 case IAC:
348 c = getc (cin);
349 if (c == WILL || c == WONT)
350 fprintf (cout, "%c%c%c", IAC, DONT, getc (cin));
351 if (c == DO || c == DONT)
352 fprintf (cout, "%c%c%c", IAC, WONT, getc (cin));
353 continue;
354 case '\n':
355 *p++ = '\0';
356 if(isdigit((unsigned char)buf[0])){
357 sscanf(buf, "%d", &code);
358 if(code == 631){
359 code = 0;
360 sec_read_msg(buf, prot_safe);
361 sscanf(buf, "%d", &code);
362 lead_string = "S:";
363 } else if(code == 632){
364 code = 0;
365 sec_read_msg(buf, prot_private);
366 sscanf(buf, "%d", &code);
367 lead_string = "P:";
368 }else if(code == 633){
369 code = 0;
370 sec_read_msg(buf, prot_confidential);
371 sscanf(buf, "%d", &code);
372 lead_string = "C:";
373 }else if(sec_complete)
374 lead_string = "!!";
375 else
376 lead_string = "";
377 if(code != 0 && reply_code == 0)
378 reply_code = code;
379 if (verbose > 0 || (verbose > -1 && code > 499))
380 fprintf (stdout, "%s%s\n", lead_string, buf);
381 if (code == reply_code && buf[3] == ' ') {
382 strlcpy (reply_string, buf, sizeof(reply_string));
383 if (code >= 200)
384 cpend = 0;
385 sigaction (SIGINT, &osa, NULL);
386 if (code == 421)
387 lostpeer (0);
388 #if 1
389 if (abrtflag &&
390 osa.sa_handler != cmdabort &&
391 osa.sa_handler != SIG_IGN)
392 osa.sa_handler (SIGINT);
393 #endif
394 if (code == 227 || code == 229) {
395 char *q;
397 q = strchr (reply_string, '(');
398 if (q) {
399 q++;
400 strlcpy(pasv, q, sizeof(pasv));
401 q = strrchr(pasv, ')');
402 if (q)
403 *q = '\0';
406 return code / 100;
408 }else{
409 if(verbose > 0 || (verbose > -1 && code > 499)){
410 if(sec_complete)
411 fprintf(stdout, "!!");
412 fprintf(stdout, "%s\n", buf);
415 p = buf;
416 long_warn = 0;
417 continue;
418 default:
419 if(p < buf + sizeof(buf) - 1)
420 *p++ = c;
421 else if(long_warn == 0) {
422 fprintf(stderr, "WARNING: incredibly long line received\n");
423 long_warn = 1;
431 #if 0
433 getreply (int expecteof)
435 int c, n;
436 int dig;
437 int originalcode = 0, continuation = 0;
438 sighand oldintr;
439 int pflag = 0;
440 char *cp, *pt = pasv;
442 oldintr = signal (SIGINT, cmdabort);
443 for (;;) {
444 dig = n = code = 0;
445 cp = reply_string;
446 while ((c = getc (cin)) != '\n') {
447 if (c == IAC) { /* handle telnet commands */
448 switch (c = getc (cin)) {
449 case WILL:
450 case WONT:
451 c = getc (cin);
452 fprintf (cout, "%c%c%c", IAC, DONT, c);
453 fflush (cout);
454 break;
455 case DO:
456 case DONT:
457 c = getc (cin);
458 fprintf (cout, "%c%c%c", IAC, WONT, c);
459 fflush (cout);
460 break;
461 default:
462 break;
464 continue;
466 dig++;
467 if (c == EOF) {
468 if (expecteof) {
469 signal (SIGINT, oldintr);
470 code = 221;
471 return (0);
473 lostpeer (0);
474 if (verbose) {
475 printf ("421 Service not available, remote server has closed connection\n");
476 fflush (stdout);
478 code = 421;
479 return (4);
481 if (c != '\r' && (verbose > 0 ||
482 (verbose > -1 && n == '5' && dig > 4))) {
483 if (proxflag &&
484 (dig == 1 || dig == 5 && verbose == 0))
485 printf ("%s:", hostname);
486 putchar (c);
488 if (dig < 4 && isdigit (c))
489 code = code * 10 + (c - '0');
490 if (!pflag && code == 227)
491 pflag = 1;
492 if (dig > 4 && pflag == 1 && isdigit (c))
493 pflag = 2;
494 if (pflag == 2) {
495 if (c != '\r' && c != ')')
496 *pt++ = c;
497 else {
498 *pt = '\0';
499 pflag = 3;
502 if (dig == 4 && c == '-') {
503 if (continuation)
504 code = 0;
505 continuation++;
507 if (n == 0)
508 n = c;
509 if (cp < &reply_string[sizeof (reply_string) - 1])
510 *cp++ = c;
512 if (verbose > 0 || verbose > -1 && n == '5') {
513 putchar (c);
514 fflush (stdout);
516 if (continuation && code != originalcode) {
517 if (originalcode == 0)
518 originalcode = code;
519 continue;
521 *cp = '\0';
522 if(sec_complete){
523 if(code == 631)
524 sec_read_msg(reply_string, prot_safe);
525 else if(code == 632)
526 sec_read_msg(reply_string, prot_private);
527 else if(code == 633)
528 sec_read_msg(reply_string, prot_confidential);
529 n = code / 100 + '0';
531 if (n != '1')
532 cpend = 0;
533 signal (SIGINT, oldintr);
534 if (code == 421 || originalcode == 421)
535 lostpeer (0);
536 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
537 (*oldintr) (SIGINT);
538 return (n - '0');
542 #endif
545 empty (fd_set * mask, int sec)
547 struct timeval t;
549 t.tv_sec = sec;
550 t.tv_usec = 0;
551 return (select (FD_SETSIZE, mask, NULL, NULL, &t));
554 jmp_buf sendabort;
556 static RETSIGTYPE
557 abortsend (int sig)
560 mflag = 0;
561 abrtflag = 0;
562 printf ("\nsend aborted\nwaiting for remote to finish abort\n");
563 fflush (stdout);
564 longjmp (sendabort, 1);
567 #define HASHBYTES 1024
569 static int
570 copy_stream (FILE * from, FILE * to)
572 static size_t bufsize;
573 static char *buf;
574 int n;
575 int bytes = 0;
576 int werr = 0;
577 int hashbytes = HASHBYTES;
578 struct stat st;
580 #if defined(HAVE_MMAP) && !defined(NO_MMAP)
581 void *chunk;
582 size_t off;
584 #define BLOCKSIZE (1024 * 1024 * 10)
586 #ifndef MAP_FAILED
587 #define MAP_FAILED (-1)
588 #endif
590 if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) {
592 * mmap zero bytes has potential of loosing, don't do it.
594 if (st.st_size == 0)
595 return 0;
596 off = 0;
597 while (off != st.st_size) {
598 size_t len;
599 ssize_t res;
601 len = st.st_size - off;
602 if (len > BLOCKSIZE)
603 len = BLOCKSIZE;
605 chunk = mmap (0, len, PROT_READ, MAP_SHARED, fileno (from), off);
606 if (chunk == (void *) MAP_FAILED) {
607 if (off == 0) /* try read if mmap doesn't work */
608 goto try_read;
609 break;
612 res = sec_write (fileno (to), chunk, len);
613 if (msync (chunk, len, MS_ASYNC))
614 warn ("msync");
615 if (munmap (chunk, len) < 0)
616 warn ("munmap");
617 sec_fflush (to);
618 if (res != len)
619 return off;
620 off += len;
622 return off;
624 try_read:
625 #endif
627 buf = alloc_buffer (buf, &bufsize,
628 fstat (fileno (from), &st) >= 0 ? &st : NULL);
629 if (buf == NULL)
630 return -1;
632 while ((n = read (fileno (from), buf, bufsize)) > 0) {
633 werr = sec_write (fileno (to), buf, n);
634 if (werr < 0)
635 break;
636 bytes += werr;
637 while (hash && bytes > hashbytes) {
638 putchar ('#');
639 hashbytes += HASHBYTES;
642 sec_fflush (to);
643 if (n < 0)
644 warn ("local");
646 if (werr < 0) {
647 if (errno != EPIPE)
648 warn ("netout");
649 bytes = -1;
651 return bytes;
654 void
655 sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
657 struct stat st;
658 struct timeval start, stop;
659 int c, d;
660 FILE *fin, *dout = 0;
661 int (*closefunc) (FILE *);
662 RETSIGTYPE (*oldintr)(int), (*oldintp)(int);
663 long bytes = 0, hashbytes = HASHBYTES;
664 char *rmode = "w";
666 if (verbose && printnames) {
667 if (local && strcmp (local, "-") != 0)
668 printf ("local: %s ", local);
669 if (remote)
670 printf ("remote: %s\n", remote);
672 if (proxy) {
673 proxtrans (cmd, local, remote);
674 return;
676 if (curtype != type)
677 changetype (type, 0);
678 closefunc = NULL;
679 oldintr = NULL;
680 oldintp = NULL;
682 if (setjmp (sendabort)) {
683 while (cpend) {
684 getreply (0);
686 if (data >= 0) {
687 close (data);
688 data = -1;
690 if (oldintr)
691 signal (SIGINT, oldintr);
692 if (oldintp)
693 signal (SIGPIPE, oldintp);
694 code = -1;
695 return;
697 oldintr = signal (SIGINT, abortsend);
698 if (strcmp (local, "-") == 0)
699 fin = stdin;
700 else if (*local == '|') {
701 oldintp = signal (SIGPIPE, SIG_IGN);
702 fin = popen (local + 1, lmode);
703 if (fin == NULL) {
704 warn ("%s", local + 1);
705 signal (SIGINT, oldintr);
706 signal (SIGPIPE, oldintp);
707 code = -1;
708 return;
710 closefunc = pclose;
711 } else {
712 fin = fopen (local, lmode);
713 if (fin == NULL) {
714 warn ("local: %s", local);
715 signal (SIGINT, oldintr);
716 code = -1;
717 return;
719 closefunc = fclose;
720 if (fstat (fileno (fin), &st) < 0 ||
721 (st.st_mode & S_IFMT) != S_IFREG) {
722 fprintf (stdout, "%s: not a plain file.\n", local);
723 signal (SIGINT, oldintr);
724 fclose (fin);
725 code = -1;
726 return;
729 if (initconn ()) {
730 signal (SIGINT, oldintr);
731 if (oldintp)
732 signal (SIGPIPE, oldintp);
733 code = -1;
734 if (closefunc != NULL)
735 (*closefunc) (fin);
736 return;
738 if (setjmp (sendabort))
739 goto abort;
741 if (restart_point &&
742 (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
743 int rc;
745 switch (curtype) {
746 case TYPE_A:
747 rc = fseek (fin, (long) restart_point, SEEK_SET);
748 break;
749 case TYPE_I:
750 case TYPE_L:
751 rc = lseek (fileno (fin), restart_point, SEEK_SET);
752 break;
753 default:
754 abort();
756 if (rc < 0) {
757 warn ("local: %s", local);
758 restart_point = 0;
759 if (closefunc != NULL)
760 (*closefunc) (fin);
761 return;
763 if (command ("REST %ld", (long) restart_point)
764 != CONTINUE) {
765 restart_point = 0;
766 if (closefunc != NULL)
767 (*closefunc) (fin);
768 return;
770 restart_point = 0;
771 rmode = "r+w";
773 if (remote) {
774 if (command ("%s %s", cmd, remote) != PRELIM) {
775 signal (SIGINT, oldintr);
776 if (oldintp)
777 signal (SIGPIPE, oldintp);
778 if (closefunc != NULL)
779 (*closefunc) (fin);
780 return;
782 } else if (command ("%s", cmd) != PRELIM) {
783 signal(SIGINT, oldintr);
784 if (oldintp)
785 signal(SIGPIPE, oldintp);
786 if (closefunc != NULL)
787 (*closefunc)(fin);
788 return;
790 dout = dataconn(rmode);
791 if (dout == NULL)
792 goto abort;
793 set_buffer_size (fileno (dout), 0);
794 gettimeofday (&start, (struct timezone *) 0);
795 oldintp = signal (SIGPIPE, SIG_IGN);
796 switch (curtype) {
798 case TYPE_I:
799 case TYPE_L:
800 errno = d = c = 0;
801 bytes = copy_stream (fin, dout);
802 break;
804 case TYPE_A:
805 while ((c = getc (fin)) != EOF) {
806 if (c == '\n') {
807 while (hash && (bytes >= hashbytes)) {
808 putchar ('#');
809 fflush (stdout);
810 hashbytes += HASHBYTES;
812 if (ferror (dout))
813 break;
814 sec_putc ('\r', dout);
815 bytes++;
817 sec_putc (c, dout);
818 bytes++;
820 sec_fflush (dout);
821 if (hash) {
822 if (bytes < hashbytes)
823 putchar ('#');
824 putchar ('\n');
825 fflush (stdout);
827 if (ferror (fin))
828 warn ("local: %s", local);
829 if (ferror (dout)) {
830 if (errno != EPIPE)
831 warn ("netout");
832 bytes = -1;
834 break;
836 if (closefunc != NULL)
837 (*closefunc) (fin);
838 fclose (dout);
839 gettimeofday (&stop, (struct timezone *) 0);
840 getreply (0);
841 signal (SIGINT, oldintr);
842 if (oldintp)
843 signal (SIGPIPE, oldintp);
844 if (bytes > 0)
845 ptransfer ("sent", bytes, &start, &stop);
846 return;
847 abort:
848 signal (SIGINT, oldintr);
849 if (oldintp)
850 signal (SIGPIPE, oldintp);
851 if (!cpend) {
852 code = -1;
853 return;
855 if (data >= 0) {
856 close (data);
857 data = -1;
859 if (dout)
860 fclose (dout);
861 getreply (0);
862 code = -1;
863 if (closefunc != NULL && fin != NULL)
864 (*closefunc) (fin);
865 gettimeofday (&stop, (struct timezone *) 0);
866 if (bytes > 0)
867 ptransfer ("sent", bytes, &start, &stop);
870 jmp_buf recvabort;
872 void
873 abortrecv (int sig)
876 mflag = 0;
877 abrtflag = 0;
878 printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
879 fflush (stdout);
880 longjmp (recvabort, 1);
883 void
884 recvrequest (char *cmd, char *local, char *remote,
885 char *lmode, int printnames, int local_given)
887 FILE *fout = NULL, *din = NULL;
888 int (*closefunc) (FILE *);
889 sighand oldintr, oldintp;
890 int c, d, is_retr, tcrflag, bare_lfs = 0;
891 static size_t bufsize;
892 static char *buf;
893 long bytes = 0, hashbytes = HASHBYTES;
894 struct timeval start, stop;
895 struct stat st;
897 is_retr = strcmp (cmd, "RETR") == 0;
898 if (is_retr && verbose && printnames) {
899 if (local && strcmp (local, "-") != 0)
900 printf ("local: %s ", local);
901 if (remote)
902 printf ("remote: %s\n", remote);
904 if (proxy && is_retr) {
905 proxtrans (cmd, local, remote);
906 return;
908 closefunc = NULL;
909 oldintr = NULL;
910 oldintp = NULL;
911 tcrflag = !crflag && is_retr;
912 if (setjmp (recvabort)) {
913 while (cpend) {
914 getreply (0);
916 if (data >= 0) {
917 close (data);
918 data = -1;
920 if (oldintr)
921 signal (SIGINT, oldintr);
922 code = -1;
923 return;
925 oldintr = signal (SIGINT, abortrecv);
926 if (!local_given || (strcmp (local, "-") && *local != '|')) {
927 if (access (local, 2) < 0) {
928 char *dir = strrchr (local, '/');
930 if (errno != ENOENT && errno != EACCES) {
931 warn ("local: %s", local);
932 signal (SIGINT, oldintr);
933 code = -1;
934 return;
936 if (dir != NULL)
937 *dir = 0;
938 d = access (dir ? local : ".", 2);
939 if (dir != NULL)
940 *dir = '/';
941 if (d < 0) {
942 warn ("local: %s", local);
943 signal (SIGINT, oldintr);
944 code = -1;
945 return;
947 if (!runique && errno == EACCES &&
948 chmod (local, 0600) < 0) {
949 warn ("local: %s", local);
950 signal (SIGINT, oldintr);
951 signal (SIGINT, oldintr);
952 code = -1;
953 return;
955 if (runique && errno == EACCES &&
956 (local = gunique (local)) == NULL) {
957 signal (SIGINT, oldintr);
958 code = -1;
959 return;
961 } else if (runique && (local = gunique (local)) == NULL) {
962 signal(SIGINT, oldintr);
963 code = -1;
964 return;
967 if (!is_retr) {
968 if (curtype != TYPE_A)
969 changetype (TYPE_A, 0);
970 } else if (curtype != type)
971 changetype (type, 0);
972 if (initconn ()) {
973 signal (SIGINT, oldintr);
974 code = -1;
975 return;
977 if (setjmp (recvabort))
978 goto abort;
979 if (is_retr && restart_point &&
980 command ("REST %ld", (long) restart_point) != CONTINUE)
981 return;
982 if (remote) {
983 if (command ("%s %s", cmd, remote) != PRELIM) {
984 signal (SIGINT, oldintr);
985 return;
987 } else {
988 if (command ("%s", cmd) != PRELIM) {
989 signal (SIGINT, oldintr);
990 return;
993 din = dataconn ("r");
994 if (din == NULL)
995 goto abort;
996 set_buffer_size (fileno (din), 1);
997 if (local_given && strcmp (local, "-") == 0)
998 fout = stdout;
999 else if (local_given && *local == '|') {
1000 oldintp = signal (SIGPIPE, SIG_IGN);
1001 fout = popen (local + 1, "w");
1002 if (fout == NULL) {
1003 warn ("%s", local + 1);
1004 goto abort;
1006 closefunc = pclose;
1007 } else {
1008 fout = fopen (local, lmode);
1009 if (fout == NULL) {
1010 warn ("local: %s", local);
1011 goto abort;
1013 closefunc = fclose;
1015 buf = alloc_buffer (buf, &bufsize,
1016 fstat (fileno (fout), &st) >= 0 ? &st : NULL);
1017 if (buf == NULL)
1018 goto abort;
1020 gettimeofday (&start, (struct timezone *) 0);
1021 switch (curtype) {
1023 case TYPE_I:
1024 case TYPE_L:
1025 if (restart_point &&
1026 lseek (fileno (fout), restart_point, SEEK_SET) < 0) {
1027 warn ("local: %s", local);
1028 if (closefunc != NULL)
1029 (*closefunc) (fout);
1030 return;
1032 errno = d = 0;
1033 while ((c = sec_read (fileno (din), buf, bufsize)) > 0) {
1034 if ((d = write (fileno (fout), buf, c)) != c)
1035 break;
1036 bytes += c;
1037 if (hash) {
1038 while (bytes >= hashbytes) {
1039 putchar ('#');
1040 hashbytes += HASHBYTES;
1042 fflush (stdout);
1045 if (hash && bytes > 0) {
1046 if (bytes < HASHBYTES)
1047 putchar ('#');
1048 putchar ('\n');
1049 fflush (stdout);
1051 if (c < 0) {
1052 if (errno != EPIPE)
1053 warn ("netin");
1054 bytes = -1;
1056 if (d < c) {
1057 if (d < 0)
1058 warn ("local: %s", local);
1059 else
1060 warnx ("%s: short write", local);
1062 break;
1064 case TYPE_A:
1065 if (restart_point) {
1066 int i, n, ch;
1068 if (fseek (fout, 0L, SEEK_SET) < 0)
1069 goto done;
1070 n = restart_point;
1071 for (i = 0; i++ < n;) {
1072 if ((ch = sec_getc (fout)) == EOF)
1073 goto done;
1074 if (ch == '\n')
1075 i++;
1077 if (fseek (fout, 0L, SEEK_CUR) < 0) {
1078 done:
1079 warn ("local: %s", local);
1080 if (closefunc != NULL)
1081 (*closefunc) (fout);
1082 return;
1085 while ((c = sec_getc(din)) != EOF) {
1086 if (c == '\n')
1087 bare_lfs++;
1088 while (c == '\r') {
1089 while (hash && (bytes >= hashbytes)) {
1090 putchar ('#');
1091 fflush (stdout);
1092 hashbytes += HASHBYTES;
1094 bytes++;
1095 if ((c = sec_getc (din)) != '\n' || tcrflag) {
1096 if (ferror (fout))
1097 goto break2;
1098 putc ('\r', fout);
1099 if (c == '\0') {
1100 bytes++;
1101 goto contin2;
1103 if (c == EOF)
1104 goto contin2;
1107 putc (c, fout);
1108 bytes++;
1109 contin2:;
1111 break2:
1112 if (bare_lfs) {
1113 printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
1114 bare_lfs);
1115 printf ("File may not have transferred correctly.\n");
1117 if (hash) {
1118 if (bytes < hashbytes)
1119 putchar ('#');
1120 putchar ('\n');
1121 fflush (stdout);
1123 if (ferror (din)) {
1124 if (errno != EPIPE)
1125 warn ("netin");
1126 bytes = -1;
1128 if (ferror (fout))
1129 warn ("local: %s", local);
1130 break;
1132 if (closefunc != NULL)
1133 (*closefunc) (fout);
1134 signal (SIGINT, oldintr);
1135 if (oldintp)
1136 signal (SIGPIPE, oldintp);
1137 fclose (din);
1138 gettimeofday (&stop, (struct timezone *) 0);
1139 getreply (0);
1140 if (bytes > 0 && is_retr)
1141 ptransfer ("received", bytes, &start, &stop);
1142 return;
1143 abort:
1145 /* abort using RFC959 recommended IP,SYNC sequence */
1147 if (oldintp)
1148 signal (SIGPIPE, oldintr);
1149 signal (SIGINT, SIG_IGN);
1150 if (!cpend) {
1151 code = -1;
1152 signal (SIGINT, oldintr);
1153 return;
1155 abort_remote(din);
1156 code = -1;
1157 if (data >= 0) {
1158 close (data);
1159 data = -1;
1161 if (closefunc != NULL && fout != NULL)
1162 (*closefunc) (fout);
1163 if (din)
1164 fclose (din);
1165 gettimeofday (&stop, (struct timezone *) 0);
1166 if (bytes > 0)
1167 ptransfer ("received", bytes, &start, &stop);
1168 signal (SIGINT, oldintr);
1171 static int
1172 parse_epsv (const char *str)
1174 char sep;
1175 char *end;
1176 int port;
1178 if (*str == '\0')
1179 return -1;
1180 sep = *str++;
1181 if (sep != *str++)
1182 return -1;
1183 if (sep != *str++)
1184 return -1;
1185 port = strtol (str, &end, 0);
1186 if (str == end)
1187 return -1;
1188 if (end[0] != sep || end[1] != '\0')
1189 return -1;
1190 return htons(port);
1193 static int
1194 parse_pasv (struct sockaddr_in *sin4, const char *str)
1196 int a0, a1, a2, a3, p0, p1;
1199 * What we've got at this point is a string of comma separated
1200 * one-byte unsigned integer values. The first four are the an IP
1201 * address. The fifth is the MSB of the port number, the sixth is the
1202 * LSB. From that we'll prepare a sockaddr_in.
1205 if (sscanf (str, "%d,%d,%d,%d,%d,%d",
1206 &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1207 printf ("Passive mode address scan failure. "
1208 "Shouldn't happen!\n");
1209 return -1;
1211 if (a0 < 0 || a0 > 255 ||
1212 a1 < 0 || a1 > 255 ||
1213 a2 < 0 || a2 > 255 ||
1214 a3 < 0 || a3 > 255 ||
1215 p0 < 0 || p0 > 255 ||
1216 p1 < 0 || p1 > 255) {
1217 printf ("Can't parse passive mode string.\n");
1218 return -1;
1220 memset (sin4, 0, sizeof(*sin4));
1221 sin4->sin_family = AF_INET;
1222 sin4->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
1223 (a2 << 8) | a3);
1224 sin4->sin_port = htons ((p0 << 8) | p1);
1225 return 0;
1228 static int
1229 passive_mode (void)
1231 int port;
1233 data = socket (myctladdr->sa_family, SOCK_STREAM, 0);
1234 if (data < 0) {
1235 warn ("socket");
1236 return (1);
1238 if (options & SO_DEBUG)
1239 socket_set_debug (data);
1240 if (command ("EPSV") != COMPLETE) {
1241 if (command ("PASV") != COMPLETE) {
1242 printf ("Passive mode refused.\n");
1243 goto bad;
1248 * Parse the reply to EPSV or PASV
1251 port = parse_epsv (pasv);
1252 if (port > 0) {
1253 data_addr->sa_family = myctladdr->sa_family;
1254 socket_set_address_and_port (data_addr,
1255 socket_get_address (hisctladdr),
1256 port);
1257 } else {
1258 if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0)
1259 goto bad;
1262 if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1263 warn ("connect");
1264 goto bad;
1266 #ifdef IPTOS_THROUGHPUT
1267 socket_set_tos (data, IPTOS_THROUGHPUT);
1268 #endif
1269 return (0);
1270 bad:
1271 close (data);
1272 data = -1;
1273 sendport = 1;
1274 return (1);
1278 static int
1279 active_mode (void)
1281 int tmpno = 0;
1282 socklen_t len;
1283 int result;
1285 noport:
1286 data_addr->sa_family = myctladdr->sa_family;
1287 socket_set_address_and_port (data_addr, socket_get_address (myctladdr),
1288 sendport ? 0 : socket_get_port (myctladdr));
1290 if (data != -1)
1291 close (data);
1292 data = socket (data_addr->sa_family, SOCK_STREAM, 0);
1293 if (data < 0) {
1294 warn ("socket");
1295 if (tmpno)
1296 sendport = 1;
1297 return (1);
1299 if (!sendport)
1300 socket_set_reuseaddr (data, 1);
1301 if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
1302 warn ("bind");
1303 goto bad;
1305 if (options & SO_DEBUG)
1306 socket_set_debug (data);
1307 len = sizeof (data_addr_ss);
1308 if (getsockname (data, data_addr, &len) < 0) {
1309 warn ("getsockname");
1310 goto bad;
1312 if (listen (data, 1) < 0)
1313 warn ("listen");
1314 if (sendport) {
1315 char addr_str[256];
1316 int inet_af;
1317 int overbose;
1319 if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr),
1320 addr_str, sizeof(addr_str)) == NULL)
1321 errx (1, "inet_ntop failed");
1322 switch (data_addr->sa_family) {
1323 case AF_INET :
1324 inet_af = 1;
1325 break;
1326 #ifdef HAVE_IPV6
1327 case AF_INET6 :
1328 inet_af = 2;
1329 break;
1330 #endif
1331 default :
1332 errx (1, "bad address family %d", data_addr->sa_family);
1336 overbose = verbose;
1337 if (debug == 0)
1338 verbose = -1;
1340 result = command ("EPRT |%d|%s|%d|",
1341 inet_af, addr_str,
1342 ntohs(socket_get_port (data_addr)));
1343 verbose = overbose;
1345 if (result == ERROR) {
1346 struct sockaddr_in *sin4 = (struct sockaddr_in *)data_addr;
1348 unsigned int a = ntohl(sin4->sin_addr.s_addr);
1349 unsigned int p = ntohs(sin4->sin_port);
1351 if (data_addr->sa_family != AF_INET) {
1352 warnx ("remote server doesn't support EPRT");
1353 goto bad;
1356 result = command("PORT %d,%d,%d,%d,%d,%d",
1357 (a >> 24) & 0xff,
1358 (a >> 16) & 0xff,
1359 (a >> 8) & 0xff,
1360 a & 0xff,
1361 (p >> 8) & 0xff,
1362 p & 0xff);
1363 if (result == ERROR && sendport == -1) {
1364 sendport = 0;
1365 tmpno = 1;
1366 goto noport;
1368 return (result != COMPLETE);
1370 return result != COMPLETE;
1372 if (tmpno)
1373 sendport = 1;
1376 #ifdef IPTOS_THROUGHPUT
1377 socket_set_tos (data, IPTOS_THROUGHPUT);
1378 #endif
1379 return (0);
1380 bad:
1381 close (data);
1382 data = -1;
1383 if (tmpno)
1384 sendport = 1;
1385 return (1);
1389 * Need to start a listen on the data channel before we send the command,
1390 * otherwise the server's connect may fail.
1393 initconn (void)
1395 if (passivemode)
1396 return passive_mode ();
1397 else
1398 return active_mode ();
1401 FILE *
1402 dataconn (const char *lmode)
1404 struct sockaddr_storage from_ss;
1405 struct sockaddr *from = (struct sockaddr *)&from_ss;
1406 socklen_t fromlen = sizeof(from_ss);
1407 int s;
1409 if (passivemode)
1410 return (fdopen (data, lmode));
1412 s = accept (data, from, &fromlen);
1413 if (s < 0) {
1414 warn ("accept");
1415 close (data), data = -1;
1416 return (NULL);
1418 close (data);
1419 data = s;
1420 #ifdef IPTOS_THROUGHPUT
1421 socket_set_tos (s, IPTOS_THROUGHPUT);
1422 #endif
1423 return (fdopen (data, lmode));
1426 void
1427 ptransfer (char *direction, long int bytes,
1428 struct timeval * t0, struct timeval * t1)
1430 struct timeval td;
1431 float s;
1432 float bs;
1433 int prec;
1434 char *unit;
1436 if (verbose) {
1437 td.tv_sec = t1->tv_sec - t0->tv_sec;
1438 td.tv_usec = t1->tv_usec - t0->tv_usec;
1439 if (td.tv_usec < 0) {
1440 td.tv_sec--;
1441 td.tv_usec += 1000000;
1443 s = td.tv_sec + (td.tv_usec / 1000000.);
1444 bs = bytes / (s ? s : 1);
1445 if (bs >= 1048576) {
1446 bs /= 1048576;
1447 unit = "M";
1448 prec = 2;
1449 } else if (bs >= 1024) {
1450 bs /= 1024;
1451 unit = "k";
1452 prec = 1;
1453 } else {
1454 unit = "";
1455 prec = 0;
1458 printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
1459 bytes, direction, s, prec, bs, unit);
1463 void
1464 psabort (int sig)
1467 abrtflag++;
1470 void
1471 pswitch (int flag)
1473 sighand oldintr;
1474 static struct comvars {
1475 int connect;
1476 char name[MaxHostNameLen];
1477 struct sockaddr_storage mctl;
1478 struct sockaddr_storage hctl;
1479 FILE *in;
1480 FILE *out;
1481 int tpe;
1482 int curtpe;
1483 int cpnd;
1484 int sunqe;
1485 int runqe;
1486 int mcse;
1487 int ntflg;
1488 char nti[17];
1489 char nto[17];
1490 int mapflg;
1491 char mi[MaxPathLen];
1492 char mo[MaxPathLen];
1493 } proxstruct, tmpstruct;
1494 struct comvars *ip, *op;
1496 abrtflag = 0;
1497 oldintr = signal (SIGINT, psabort);
1498 if (flag) {
1499 if (proxy)
1500 return;
1501 ip = &tmpstruct;
1502 op = &proxstruct;
1503 proxy++;
1504 } else {
1505 if (!proxy)
1506 return;
1507 ip = &proxstruct;
1508 op = &tmpstruct;
1509 proxy = 0;
1511 ip->connect = connected;
1512 connected = op->connect;
1513 if (hostname) {
1514 strlcpy (ip->name, hostname, sizeof (ip->name));
1515 } else
1516 ip->name[0] = 0;
1517 hostname = op->name;
1518 ip->hctl = hisctladdr_ss;
1519 hisctladdr_ss = op->hctl;
1520 ip->mctl = myctladdr_ss;
1521 myctladdr_ss = op->mctl;
1522 ip->in = cin;
1523 cin = op->in;
1524 ip->out = cout;
1525 cout = op->out;
1526 ip->tpe = type;
1527 type = op->tpe;
1528 ip->curtpe = curtype;
1529 curtype = op->curtpe;
1530 ip->cpnd = cpend;
1531 cpend = op->cpnd;
1532 ip->sunqe = sunique;
1533 sunique = op->sunqe;
1534 ip->runqe = runique;
1535 runique = op->runqe;
1536 ip->mcse = mcase;
1537 mcase = op->mcse;
1538 ip->ntflg = ntflag;
1539 ntflag = op->ntflg;
1540 strlcpy (ip->nti, ntin, sizeof (ip->nti));
1541 strlcpy (ntin, op->nti, 17);
1542 strlcpy (ip->nto, ntout, sizeof (ip->nto));
1543 strlcpy (ntout, op->nto, 17);
1544 ip->mapflg = mapflag;
1545 mapflag = op->mapflg;
1546 strlcpy (ip->mi, mapin, MaxPathLen);
1547 strlcpy (mapin, op->mi, MaxPathLen);
1548 strlcpy (ip->mo, mapout, MaxPathLen);
1549 strlcpy (mapout, op->mo, MaxPathLen);
1550 signal(SIGINT, oldintr);
1551 if (abrtflag) {
1552 abrtflag = 0;
1553 (*oldintr) (SIGINT);
1557 void
1558 abortpt (int sig)
1561 printf ("\n");
1562 fflush (stdout);
1563 ptabflg++;
1564 mflag = 0;
1565 abrtflag = 0;
1566 longjmp (ptabort, 1);
1569 void
1570 proxtrans (char *cmd, char *local, char *remote)
1572 sighand oldintr = NULL;
1573 int secndflag = 0, prox_type, nfnd;
1574 char *cmd2;
1575 fd_set mask;
1577 if (strcmp (cmd, "RETR"))
1578 cmd2 = "RETR";
1579 else
1580 cmd2 = runique ? "STOU" : "STOR";
1581 if ((prox_type = type) == 0) {
1582 if (unix_server && unix_proxy)
1583 prox_type = TYPE_I;
1584 else
1585 prox_type = TYPE_A;
1587 if (curtype != prox_type)
1588 changetype (prox_type, 1);
1589 if (command ("PASV") != COMPLETE) {
1590 printf ("proxy server does not support third party transfers.\n");
1591 return;
1593 pswitch (0);
1594 if (!connected) {
1595 printf ("No primary connection\n");
1596 pswitch (1);
1597 code = -1;
1598 return;
1600 if (curtype != prox_type)
1601 changetype (prox_type, 1);
1602 if (command ("PORT %s", pasv) != COMPLETE) {
1603 pswitch (1);
1604 return;
1606 if (setjmp (ptabort))
1607 goto abort;
1608 oldintr = signal (SIGINT, abortpt);
1609 if (command ("%s %s", cmd, remote) != PRELIM) {
1610 signal (SIGINT, oldintr);
1611 pswitch (1);
1612 return;
1614 sleep (2);
1615 pswitch (1);
1616 secndflag++;
1617 if (command ("%s %s", cmd2, local) != PRELIM)
1618 goto abort;
1619 ptflag++;
1620 getreply (0);
1621 pswitch (0);
1622 getreply (0);
1623 signal (SIGINT, oldintr);
1624 pswitch (1);
1625 ptflag = 0;
1626 printf ("local: %s remote: %s\n", local, remote);
1627 return;
1628 abort:
1629 signal (SIGINT, SIG_IGN);
1630 ptflag = 0;
1631 if (strcmp (cmd, "RETR") && !proxy)
1632 pswitch (1);
1633 else if (!strcmp (cmd, "RETR") && proxy)
1634 pswitch (0);
1635 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1636 if (command ("%s %s", cmd2, local) != PRELIM) {
1637 pswitch (0);
1638 if (cpend)
1639 abort_remote ((FILE *) NULL);
1641 pswitch (1);
1642 if (ptabflg)
1643 code = -1;
1644 if (oldintr)
1645 signal (SIGINT, oldintr);
1646 return;
1648 if (cpend)
1649 abort_remote ((FILE *) NULL);
1650 pswitch (!proxy);
1651 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1652 if (command ("%s %s", cmd2, local) != PRELIM) {
1653 pswitch (0);
1654 if (cpend)
1655 abort_remote ((FILE *) NULL);
1656 pswitch (1);
1657 if (ptabflg)
1658 code = -1;
1659 signal (SIGINT, oldintr);
1660 return;
1663 if (cpend)
1664 abort_remote ((FILE *) NULL);
1665 pswitch (!proxy);
1666 if (cpend) {
1667 FD_ZERO (&mask);
1668 if (fileno(cin) >= FD_SETSIZE)
1669 errx (1, "fd too large");
1670 FD_SET (fileno (cin), &mask);
1671 if ((nfnd = empty (&mask, 10)) <= 0) {
1672 if (nfnd < 0) {
1673 warn ("abort");
1675 if (ptabflg)
1676 code = -1;
1677 lostpeer (0);
1679 getreply (0);
1680 getreply (0);
1682 if (proxy)
1683 pswitch (0);
1684 pswitch (1);
1685 if (ptabflg)
1686 code = -1;
1687 signal (SIGINT, oldintr);
1690 void
1691 reset (int argc, char **argv)
1693 fd_set mask;
1694 int nfnd = 1;
1696 FD_ZERO (&mask);
1697 while (nfnd > 0) {
1698 if (fileno (cin) >= FD_SETSIZE)
1699 errx (1, "fd too large");
1700 FD_SET (fileno (cin), &mask);
1701 if ((nfnd = empty (&mask, 0)) < 0) {
1702 warn ("reset");
1703 code = -1;
1704 lostpeer(0);
1705 } else if (nfnd) {
1706 getreply(0);
1711 char *
1712 gunique (char *local)
1714 static char new[MaxPathLen];
1715 char *cp = strrchr (local, '/');
1716 int d, count = 0;
1717 char ext = '1';
1719 if (cp)
1720 *cp = '\0';
1721 d = access (cp ? local : ".", 2);
1722 if (cp)
1723 *cp = '/';
1724 if (d < 0) {
1725 warn ("local: %s", local);
1726 return NULL;
1728 strlcpy (new, local, sizeof(new));
1729 cp = new + strlen(new);
1730 *cp++ = '.';
1731 while (!d) {
1732 if (++count == 100) {
1733 printf ("runique: can't find unique file name.\n");
1734 return NULL;
1736 *cp++ = ext;
1737 *cp = '\0';
1738 if (ext == '9')
1739 ext = '0';
1740 else
1741 ext++;
1742 if ((d = access (new, 0)) < 0)
1743 break;
1744 if (ext != '0')
1745 cp--;
1746 else if (*(cp - 2) == '.')
1747 *(cp - 1) = '1';
1748 else {
1749 *(cp - 2) = *(cp - 2) + 1;
1750 cp--;
1753 return (new);
1756 void
1757 abort_remote (FILE * din)
1759 char buf[BUFSIZ];
1760 int nfnd;
1761 fd_set mask;
1764 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1765 * after urgent byte rather than before as is protocol now
1767 snprintf (buf, sizeof (buf), "%c%c%c", IAC, IP, IAC);
1768 if (send (fileno (cout), buf, 3, MSG_OOB) != 3)
1769 warn ("abort");
1770 fprintf (cout, "%c", DM);
1771 sec_fprintf(cout, "ABOR");
1772 sec_fflush (cout);
1773 fprintf (cout, "\r\n");
1774 fflush(cout);
1775 FD_ZERO (&mask);
1776 if (fileno (cin) >= FD_SETSIZE)
1777 errx (1, "fd too large");
1778 FD_SET (fileno (cin), &mask);
1779 if (din) {
1780 if (fileno (din) >= FD_SETSIZE)
1781 errx (1, "fd too large");
1782 FD_SET (fileno (din), &mask);
1784 if ((nfnd = empty (&mask, 10)) <= 0) {
1785 if (nfnd < 0) {
1786 warn ("abort");
1788 if (ptabflg)
1789 code = -1;
1790 lostpeer (0);
1792 if (din && FD_ISSET (fileno (din), &mask)) {
1793 while (read (fileno (din), buf, BUFSIZ) > 0)
1794 /* LOOP */ ;
1796 if (getreply (0) == ERROR && code == 552) {
1797 /* 552 needed for nic style abort */
1798 getreply (0);
1800 getreply (0);