2 /* $NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $ */
5 * Copyright (c) 1985, 1989, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/cdefs.h>
40 static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
43 __RCSID_SOURCE("$NetBSD: ftp.c,v 1.29.2.1 1997/11/18 01:01:04 mellon Exp $");
47 #include <sys/types.h>
49 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <netinet/in_systm.h>
53 #include <netinet/ip.h>
54 #include <arpa/inet.h>
56 #include <arpa/telnet.h>
74 struct sockaddr_in hisctladdr;
75 struct sockaddr_in data_addr;
81 struct sockaddr_in myctladdr;
91 struct hostent *hp = NULL;
93 static char hostnamebuf[MAXHOSTNAMELEN];
95 memset((void *)&hisctladdr, 0, sizeof(hisctladdr));
96 if (inet_aton(host, &hisctladdr.sin_addr) != 0) {
97 hisctladdr.sin_family = AF_INET;
98 (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
100 hp = gethostbyname(host);
102 warnx("%s: %s", host, hstrerror(h_errno));
106 hisctladdr.sin_family = hp->h_addrtype;
107 memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
108 MIN(hp->h_length,sizeof(hisctladdr.sin_addr)));
109 (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
111 hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
112 hostname = hostnamebuf;
113 hisctladdr.sin_port = port;
115 if ((s = socket(hisctladdr.sin_family, SOCK_STREAM, 0)) == -1) {
120 if (dobind && bind(s, (struct sockaddr *)&bindto,
121 sizeof(bindto)) == -1) {
126 if (connect(s, (struct sockaddr *)&hisctladdr,
127 sizeof(hisctladdr)) == 0)
129 if (hp && *++hp->h_addr_list) {
130 warnc(errno, "connect to address %s",
131 inet_ntoa(hisctladdr.sin_addr));
132 memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
133 MIN(hp->h_length,sizeof(hisctladdr.sin_addr)));
134 printf("Trying %s...\n",
135 inet_ntoa(hisctladdr.sin_addr));
143 len = sizeof(myctladdr);
144 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
150 tos = IPTOS_LOWDELAY;
151 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
152 warn("setsockopt TOS (ignored)");
154 cin = fdopen(s, "r");
155 cout = fdopen(s, "w");
156 if (cin == NULL || cout == NULL) {
157 warnx("fdopen failed.");
166 printf("Connected to %s.\n", hostname);
167 if (getreply(0) > 2) { /* read startup message from server */
179 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
184 #endif /* SO_OOBINLINE */
199 (void)fflush(stdout);
208 command(const char *fmt, ...)
223 fputs("---> ", stdout);
228 fmt = va_arg(ap, const char *);
230 if (strncmp("PASS ", fmt, 5) == 0)
231 fputs("PASS XXXX", stdout);
232 else if (strncmp("ACCT ", fmt, 5) == 0)
233 fputs("ACCT XXXX", stdout);
238 (void)fflush(stdout);
241 warnx("No control connection for command.");
245 oldintr = signal(SIGINT, cmdabort);
250 fmt = va_arg(ap, char *);
252 vfprintf(cout, fmt, ap);
257 r = getreply(!strcmp(fmt, "QUIT"));
258 if (abrtflag && oldintr != SIG_IGN)
260 (void)signal(SIGINT, oldintr);
264 char reply_string[BUFSIZ]; /* first line of previous reply */
270 char current_line[BUFSIZ]; /* last line of previous reply */
273 int originalcode = 0, continuation = 0;
276 char *cp, *pt = pasv;
278 oldintr = signal(SIGINT, cmdabort);
279 for (line = 0 ;; line++) {
282 while ((c = getc(cin)) != '\n') {
283 if (c == IAC) { /* handle telnet commands */
284 switch (c = getc(cin)) {
288 fprintf(cout, "%c%c%c", IAC, DONT, c);
294 fprintf(cout, "%c%c%c", IAC, WONT, c);
305 (void)signal(SIGINT, oldintr);
312 "421 Service not available, remote server has closed connection.");
313 (void)fflush(stdout);
318 if (c != '\r' && (verbose > 0 ||
319 (verbose > -1 && n == '5' && dig > 4))) {
321 (dig == 1 || (dig == 5 && verbose == 0)))
322 printf("%s:", hostname);
325 if (dig < 4 && isdigit((unsigned char)c))
326 code = code * 10 + (c - '0');
327 if (!pflag && code == 227)
329 if (dig > 4 && pflag == 1 && isdigit((unsigned char)c))
332 if (c != '\r' && c != ')' &&
333 pt < &pasv[sizeof(pasv)-1])
340 if (dig == 4 && c == '-') {
347 if (cp < ¤t_line[sizeof(current_line) - 1])
350 if (verbose > 0 || (verbose > -1 && n == '5')) {
352 (void)fflush (stdout);
355 size_t len = cp - current_line;
357 if (len > sizeof(reply_string))
358 len = sizeof(reply_string);
360 (void)strncpy(reply_string, current_line, len);
361 reply_string[len] = '\0';
363 if (continuation && code != originalcode) {
364 if (originalcode == 0)
371 (void)signal(SIGINT, oldintr);
372 if (code == 421 || originalcode == 421)
374 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
387 t.tv_sec = (long) sec;
389 return (select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
402 puts("\nsend aborted\nwaiting for remote to finish abort.");
403 (void)fflush(stdout);
404 longjmp(sendabort, 1);
408 sendrequest(cmd, local, remote, printnames)
409 const char *cmd, *local, *remote;
415 int (*closefunc) __P((FILE *));
416 sig_t oldinti, oldintr, oldintp;
417 volatile off_t hashbytes;
418 char *lmode, buf[BUFSIZ], *bufp;
421 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
436 oprogress = progress;
437 if (verbose && printnames) {
438 if (local && *local != '-')
439 printf("local: %s ", local);
441 printf("remote: %s\n", remote);
444 proxtrans(cmd, local, remote);
454 if (setjmp(sendabort)) {
463 (void)signal(SIGINT, oldintr);
465 (void)signal(SIGPIPE, oldintp);
467 (void)signal(SIGINFO, oldinti);
471 oldintr = signal(SIGINT, abortsend);
472 oldinti = signal(SIGINFO, psummary);
473 if (strcmp(local, "-") == 0) {
476 } else if (*local == '|') {
477 oldintp = signal(SIGPIPE, SIG_IGN);
478 fin = popen(local + 1, "r");
480 warn("%s", local + 1);
481 (void)signal(SIGINT, oldintr);
482 (void)signal(SIGPIPE, oldintp);
483 (void)signal(SIGINFO, oldinti);
490 fin = fopen(local, "r");
492 warn("local: %s", local);
493 (void)signal(SIGINT, oldintr);
494 (void)signal(SIGINFO, oldinti);
499 if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
500 printf("%s: not a plain file.\n", local);
501 (void)signal(SIGINT, oldintr);
502 (void)signal(SIGINFO, oldinti);
507 filesize = st.st_size;
510 (void)signal(SIGINT, oldintr);
511 (void)signal(SIGINFO, oldinti);
513 (void)signal(SIGPIPE, oldintp);
515 if (closefunc != NULL)
519 if (setjmp(sendabort))
523 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
529 rc = fseek(fin, (long) restart_point, SEEK_SET);
533 rc = lseek(fileno(fin), restart_point, SEEK_SET);
537 warn("local: %s", local);
538 if (closefunc != NULL)
542 if (command("REST %qd", (long long) restart_point) !=
544 if (closefunc != NULL)
551 if (command("%s %s", cmd, remote) != PRELIM) {
552 (void)signal(SIGINT, oldintr);
553 (void)signal(SIGINFO, oldinti);
555 (void)signal(SIGPIPE, oldintp);
556 if (closefunc != NULL)
561 if (command("%s", cmd) != PRELIM) {
562 (void)signal(SIGINT, oldintr);
563 (void)signal(SIGINFO, oldinti);
565 (void)signal(SIGPIPE, oldintp);
566 if (closefunc != NULL)
570 dout = dataconn(lmode);
574 oldintp = signal(SIGPIPE, SIG_IGN);
580 while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) {
582 for (bufp = buf; c > 0; c -= d, bufp += d)
583 if ((d = write(fileno(dout), bufp, c)) <= 0)
585 if (hash && (!progress || filesize < 0) ) {
586 while (bytes >= hashbytes) {
590 (void)fflush(stdout);
593 if (hash && (!progress || filesize < 0) && bytes > 0) {
597 (void)fflush(stdout);
600 warn("local: %s", local);
609 while ((c = getc(fin)) != EOF) {
611 while (hash && (!progress || filesize < 0) &&
612 (bytes >= hashbytes)) {
614 (void)fflush(stdout);
619 (void)putc('\r', dout);
624 #if 0 /* this violates RFC */
626 (void)putc('\0', dout);
631 if (hash && (!progress || filesize < 0)) {
632 if (bytes < hashbytes)
635 (void)fflush(stdout);
638 warn("local: %s", local);
647 if (closefunc != NULL)
651 (void)signal(SIGINT, oldintr);
652 (void)signal(SIGINFO, oldinti);
654 (void)signal(SIGPIPE, oldintp);
659 (void)signal(SIGINT, oldintr);
660 (void)signal(SIGINFO, oldinti);
662 (void)signal(SIGPIPE, oldintp);
675 if (closefunc != NULL && fin != NULL)
680 progress = oprogress;
694 puts("\nreceive aborted\nwaiting for remote to finish abort.");
695 (void)fflush(stdout);
696 longjmp(recvabort, 1);
700 recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
701 const char *cmd, *local, *remote, *lmode;
702 int printnames, ignorespecial;
705 int (*closefunc) __P((FILE *));
706 sig_t oldinti, oldintr, oldintp;
708 volatile int is_retr, tcrflag, bare_lfs;
709 static size_t bufsize;
711 volatile off_t hashbytes;
714 struct timeval tval[2];
718 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
732 direction = "received";
736 oprogress = progress;
737 opreserve = preserve;
738 is_retr = (strcmp(cmd, "RETR") == 0);
739 if (is_retr && verbose && printnames) {
740 if (local && (ignorespecial || *local != '-'))
741 printf("local: %s ", local);
743 printf("remote: %s\n", remote);
745 if (proxy && is_retr) {
746 proxtrans(cmd, local, remote);
752 tcrflag = !crflag && is_retr;
753 if (setjmp(recvabort)) {
762 (void)signal(SIGINT, oldintr);
764 (void)signal(SIGINFO, oldinti);
765 progress = oprogress;
766 preserve = opreserve;
770 oldintr = signal(SIGINT, abortrecv);
771 oldinti = signal(SIGINFO, psummary);
772 if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
773 if (access(local, W_OK) < 0) {
774 char *dir = strrchr(local, '/');
776 if (errno != ENOENT && errno != EACCES) {
777 warn("local: %s", local);
778 (void)signal(SIGINT, oldintr);
779 (void)signal(SIGINFO, oldinti);
785 d = access(dir == local ? "/" : dir ? local : ".", W_OK);
789 warn("local: %s", local);
790 (void)signal(SIGINT, oldintr);
791 (void)signal(SIGINFO, oldinti);
795 if (!runique && errno == EACCES &&
796 chmod(local, 0600) < 0) {
797 warn("local: %s", local);
798 (void)signal(SIGINT, oldintr);
799 (void)signal(SIGINFO, oldinti);
803 if (runique && errno == EACCES &&
804 (local = gunique(local)) == NULL) {
805 (void)signal(SIGINT, oldintr);
806 (void)signal(SIGINFO, oldinti);
811 else if (runique && (local = gunique(local)) == NULL) {
812 (void)signal(SIGINT, oldintr);
813 (void)signal(SIGINFO, oldinti);
819 if (curtype != TYPE_A)
820 changetype(TYPE_A, 0);
824 filesize = remotesize(remote, 0);
827 (void)signal(SIGINT, oldintr);
828 (void)signal(SIGINFO, oldinti);
832 if (setjmp(recvabort))
834 if (is_retr && restart_point &&
835 command("REST %qd", (long long) restart_point) != CONTINUE)
838 if (command("%s %s", cmd, remote) != PRELIM) {
839 (void)signal(SIGINT, oldintr);
840 (void)signal(SIGINFO, oldinti);
844 if (command("%s", cmd) != PRELIM) {
845 (void)signal(SIGINT, oldintr);
846 (void)signal(SIGINFO, oldinti);
853 if (!ignorespecial && strcmp(local, "-") == 0) {
857 } else if (!ignorespecial && *local == '|') {
858 oldintp = signal(SIGPIPE, SIG_IGN);
859 fout = popen(local + 1, "w");
868 fout = fopen(local, lmode);
870 warn("local: %s", local);
875 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
876 st.st_blksize = BUFSIZ;
877 if (st.st_blksize > bufsize) {
880 buf = malloc((unsigned)st.st_blksize);
886 bufsize = st.st_blksize;
888 if (!S_ISREG(st.st_mode)) {
897 if (is_retr && restart_point &&
898 lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
899 warn("local: %s", local);
900 progress = oprogress;
901 preserve = opreserve;
902 if (closefunc != NULL)
907 while ((c = read(fileno(din), buf, bufsize)) > 0) {
908 if ((d = write(fileno(fout), buf, c)) != c)
911 if (hash && (!progress || filesize < 0)) {
912 while (bytes >= hashbytes) {
916 (void)fflush(stdout);
919 if (hash && (!progress || filesize < 0) && bytes > 0) {
923 (void)fflush(stdout);
932 warn("local: %s", local);
934 warnx("%s: short write", local);
939 if (is_retr && restart_point) {
943 if (fseek(fout, 0L, SEEK_SET) < 0)
945 n = (long)restart_point;
946 for (i = 0; i++ < n;) {
947 if ((ch = getc(fout)) == EOF)
952 if (fseek(fout, 0L, SEEK_CUR) < 0) {
954 warn("local: %s", local);
955 progress = oprogress;
956 preserve = opreserve;
957 if (closefunc != NULL)
962 while ((c = getc(din)) != EOF) {
966 while (hash && (!progress || filesize < 0) &&
967 (bytes >= hashbytes)) {
969 (void)fflush(stdout);
973 if ((c = getc(din)) != '\n' || tcrflag) {
976 (void)putc('\r', fout);
992 "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
993 puts("File may not have transferred correctly.");
995 if (hash && (!progress || filesize < 0)) {
996 if (bytes < hashbytes)
999 (void)fflush(stdout);
1007 warn("local: %s", local);
1011 progress = oprogress;
1012 preserve = opreserve;
1013 if (closefunc != NULL)
1015 (void)signal(SIGINT, oldintr);
1016 (void)signal(SIGINFO, oldinti);
1018 (void)signal(SIGPIPE, oldintp);
1021 if (bytes >= 0 && is_retr) {
1024 if (preserve && (closefunc == fclose)) {
1025 mtime = remotemodtime(remote, 0);
1027 (void)gettimeofday(&tval[0],
1028 (struct timezone *)0);
1029 tval[1].tv_sec = mtime;
1030 tval[1].tv_usec = 0;
1031 if (utimes(local, tval) == -1) {
1033 "Can't change modification time on %s to %s",
1034 local, asctime(localtime(&mtime)));
1043 /* abort using RFC959 recommended IP,SYNC sequence */
1045 progress = oprogress;
1046 preserve = opreserve;
1048 (void)signal(SIGPIPE, oldintp);
1049 (void)signal(SIGINT, SIG_IGN);
1052 (void)signal(SIGINT, oldintr);
1053 (void)signal(SIGINFO, oldinti);
1063 if (closefunc != NULL && fout != NULL)
1069 (void)signal(SIGINT, oldintr);
1070 (void)signal(SIGINFO, oldinti);
1074 * Need to start a listen on the data channel before we send the command,
1075 * otherwise the server's connect may fail.
1081 int result, len, tmpno = 0;
1083 int a0, a1, a2, a3, p0, p1;
1087 data = socket(AF_INET, SOCK_STREAM, 0);
1092 if (dobind && bind(data, (struct sockaddr *)&bindto,
1093 sizeof(bindto)) == -1) {
1097 if ((options & SO_DEBUG) &&
1098 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1100 warn("setsockopt (ignored)");
1101 if (command("PASV") != COMPLETE) {
1102 puts("Passive mode refused.");
1107 * What we've got at this point is a string of comma
1108 * separated one-byte unsigned integer values.
1109 * The first four are the an IP address. The fifth is
1110 * the MSB of the port number, the sixth is the LSB.
1111 * From that we'll prepare a sockaddr_in.
1114 if (sscanf(pasv, "%d,%d,%d,%d,%d,%d",
1115 &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1117 "Passive mode address scan failure. Shouldn't happen!");
1121 memset(&data_addr, 0, sizeof(data_addr));
1122 data_addr.sin_family = AF_INET;
1123 a = (char *)&data_addr.sin_addr.s_addr;
1128 p = (char *)&data_addr.sin_port;
1132 if (connect(data, (struct sockaddr *)&data_addr,
1133 sizeof(data_addr)) < 0) {
1138 on = IPTOS_THROUGHPUT;
1139 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1141 warn("setsockopt TOS (ignored)");
1147 data_addr = myctladdr;
1149 data_addr.sin_port = 0; /* let system pick one */
1152 data = socket(AF_INET, SOCK_STREAM, 0);
1160 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1162 warn("setsockopt (reuse address)");
1166 ports = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
1167 if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE, (char *)&ports,
1169 warn("setsockopt PORTRANGE (ignored)");
1171 if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) {
1175 if (options & SO_DEBUG &&
1176 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1178 warn("setsockopt (ignored)");
1179 len = sizeof(data_addr);
1180 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1181 warn("getsockname");
1184 if (listen(data, 1) < 0)
1187 a = (char *)&data_addr.sin_addr;
1188 p = (char *)&data_addr.sin_port;
1189 #define UC(b) (((int)b)&0xff)
1191 command("PORT %d,%d,%d,%d,%d,%d",
1192 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1193 UC(p[0]), UC(p[1]));
1194 if (result == ERROR && sendport == -1) {
1199 return (result != COMPLETE);
1204 on = IPTOS_THROUGHPUT;
1205 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1206 warn("setsockopt TOS (ignored)");
1210 (void)close(data), data = -1;
1220 struct sockaddr_in from;
1221 int s, fromlen, tos;
1223 fromlen = sizeof(from);
1226 return (fdopen(data, lmode));
1228 s = accept(data, (struct sockaddr *) &from, &fromlen);
1231 (void)close(data), data = -1;
1237 tos = IPTOS_THROUGHPUT;
1238 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
1239 warn("setsockopt TOS (ignored)");
1241 return (fdopen(data, lmode));
1267 static struct comvars {
1269 char name[MAXHOSTNAMELEN];
1270 struct sockaddr_in mctl;
1271 struct sockaddr_in hctl;
1284 char mi[MAXPATHLEN];
1285 char mo[MAXPATHLEN];
1286 } proxstruct, tmpstruct;
1287 struct comvars *ip, *op;
1290 oldintr = signal(SIGINT, psabort);
1304 ip->connect = connected;
1305 connected = op->connect;
1307 (void)strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1308 ip->name[sizeof(ip->name) - 1] = '\0';
1311 hostname = op->name;
1312 ip->hctl = hisctladdr;
1313 hisctladdr = op->hctl;
1314 ip->mctl = myctladdr;
1315 myctladdr = op->mctl;
1322 ip->curtpe = curtype;
1323 curtype = op->curtpe;
1326 ip->sunqe = sunique;
1327 sunique = op->sunqe;
1328 ip->runqe = runique;
1329 runique = op->runqe;
1334 (void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
1335 (ip->nti)[sizeof(ip->nti) - 1] = '\0';
1336 (void)strcpy(ntin, op->nti);
1337 (void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
1338 (ip->nto)[sizeof(ip->nto) - 1] = '\0';
1339 (void)strcpy(ntout, op->nto);
1340 ip->mapflg = mapflag;
1341 mapflag = op->mapflg;
1342 (void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1);
1343 (ip->mi)[sizeof(ip->mi) - 1] = '\0';
1344 (void)strcpy(mapin, op->mi);
1345 (void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1);
1346 (ip->mo)[sizeof(ip->mo) - 1] = '\0';
1347 (void)strcpy(mapout, op->mo);
1348 (void)signal(SIGINT, oldintr);
1362 (void)fflush(stdout);
1366 longjmp(ptabort, 1);
1370 proxtrans(cmd, local, remote)
1371 const char *cmd, *local, *remote;
1374 int prox_type, nfnd;
1375 volatile int secndflag;
1379 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */
1386 if (strcmp(cmd, "RETR"))
1389 cmd2 = runique ? "STOU" : "STOR";
1390 if ((prox_type = type) == 0) {
1391 if (unix_server && unix_proxy)
1396 if (curtype != prox_type)
1397 changetype(prox_type, 1);
1398 if (command("PASV") != COMPLETE) {
1399 puts("proxy server does not support third party transfers.");
1404 puts("No primary connection.");
1409 if (curtype != prox_type)
1410 changetype(prox_type, 1);
1411 if (command("PORT %s", pasv) != COMPLETE) {
1415 if (setjmp(ptabort))
1417 oldintr = signal(SIGINT, abortpt);
1418 if (command("%s %s", cmd, remote) != PRELIM) {
1419 (void)signal(SIGINT, oldintr);
1426 if (command("%s %s", cmd2, local) != PRELIM)
1432 (void)signal(SIGINT, oldintr);
1435 printf("local: %s remote: %s\n", local, remote);
1438 (void)signal(SIGINT, SIG_IGN);
1440 if (strcmp(cmd, "RETR") && !proxy)
1442 else if (!strcmp(cmd, "RETR") && proxy)
1444 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1445 if (command("%s %s", cmd2, local) != PRELIM) {
1448 abort_remote((FILE *) NULL);
1453 (void)signal(SIGINT, oldintr);
1457 abort_remote((FILE *) NULL);
1459 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1460 if (command("%s %s", cmd2, local) != PRELIM) {
1463 abort_remote((FILE *) NULL);
1467 (void)signal(SIGINT, oldintr);
1472 abort_remote((FILE *) NULL);
1476 FD_SET(fileno(cin), &mask);
1477 if ((nfnd = empty(&mask, 10)) <= 0) {
1493 (void)signal(SIGINT, oldintr);
1506 FD_SET(fileno(cin), &mask);
1507 if ((nfnd = empty(&mask, 0)) < 0) {
1522 static char new[MAXPATHLEN];
1523 char *cp = strrchr(local, '/');
1529 d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1533 warn("local: %s", local);
1534 return ((char *) 0);
1536 (void)strcpy(new, local);
1537 cp = new + strlen(new);
1540 if (++count == 100) {
1541 puts("runique: can't find unique file name.");
1542 return ((char *) 0);
1550 if ((d = access(new, F_OK)) < 0)
1554 else if (*(cp - 2) == '.')
1557 *(cp - 2) = *(cp - 2) + 1;
1573 warnx("Lost control connection for abort.");
1580 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1581 * after urgent byte rather than before as is protocol now
1583 sprintf(buf, "%c%c%c", IAC, IP, IAC);
1584 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
1586 fprintf(cout, "%cABOR\r\n", DM);
1589 FD_SET(fileno(cin), &mask);
1591 FD_SET(fileno(din), &mask);
1593 if ((nfnd = empty(&mask, 10)) <= 0) {
1601 if (din && FD_ISSET(fileno(din), &mask)) {
1602 while (read(fileno(din), buf, BUFSIZ) > 0)
1605 if (getreply(0) == ERROR && code == 552) {
1606 /* 552 needed for nic style abort */