[BACK]Return to ftp.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ftp

Annotation of src/usr.bin/ftp/ftp.c, Revision 1.87

1.87    ! deraadt     1: /*     $OpenBSD: ftp.c,v 1.86 2014/05/20 01:25:23 guenther Exp $       */
1.22      millert     2: /*     $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $   */
1.1       deraadt     3:
                      4: /*
1.34      itojun      5:  * Copyright (C) 1997 and 1998 WIDE Project.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     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. Neither the name of the project nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*
1.1       deraadt    34:  * Copyright (c) 1985, 1989, 1993, 1994
                     35:  *     The Regents of the University of California.  All rights reserved.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
1.53      millert    45:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    46:  *    may be used to endorse or promote products derived from this software
                     47:  *    without specific prior written permission.
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  */
                     61:
1.10      millert    62: #include <sys/types.h>
1.1       deraadt    63: #include <sys/stat.h>
                     64: #include <sys/socket.h>
                     65:
                     66: #include <netinet/in.h>
                     67: #include <netinet/in_systm.h>
                     68: #include <netinet/ip.h>
                     69: #include <arpa/inet.h>
                     70: #include <arpa/ftp.h>
                     71: #include <arpa/telnet.h>
                     72:
                     73: #include <ctype.h>
                     74: #include <err.h>
                     75: #include <errno.h>
                     76: #include <netdb.h>
1.54      millert    77: #include <poll.h>
                     78: #include <stdarg.h>
1.1       deraadt    79: #include <stdio.h>
                     80: #include <stdlib.h>
                     81: #include <string.h>
                     82: #include <unistd.h>
1.12      millert    83: #include <utime.h>
1.1       deraadt    84:
                     85: #include "ftp_var.h"
                     86:
1.34      itojun     87: union sockunion {
                     88:        struct sockinet {
                     89:                u_char si_len;
                     90:                u_char si_family;
                     91:                u_short si_port;
                     92:        } su_si;
                     93:        struct sockaddr_in  su_sin;
                     94:        struct sockaddr_in6 su_sin6;
                     95: };
                     96: #define su_len         su_si.si_len
                     97: #define su_family      su_si.si_family
                     98: #define su_port                su_si.si_port
                     99:
                    100: union sockunion myctladdr, hisctladdr, data_addr;
                    101:
1.1       deraadt   102: int    data = -1;
                    103: int    abrtflag = 0;
                    104: jmp_buf        ptabort;
                    105: int    ptabflg;
                    106: int    ptflag = 0;
                    107: off_t  restart_point = 0;
                    108:
                    109:
                    110: FILE   *cin, *cout;
                    111:
                    112: char *
1.56      deraadt   113: hookup(char *host, char *port)
1.1       deraadt   114: {
1.57      deraadt   115:        int s, tos, error;
1.10      millert   116:        static char hostnamebuf[MAXHOSTNAMELEN];
1.82      haesbaer  117:        struct addrinfo hints, *res, *res0, *ares;
1.51      itojun    118:        char hbuf[NI_MAXHOST];
1.34      itojun    119:        char *cause = "unknown";
1.57      deraadt   120:        socklen_t namelen;
1.34      itojun    121:
1.36      itojun    122:        epsv4bad = 0;
                    123:
1.34      itojun    124:        memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
                    125:        memset(&hints, 0, sizeof(hints));
                    126:        hints.ai_flags = AI_CANONNAME;
1.45      deraadt   127:        hints.ai_family = family;
1.34      itojun    128:        hints.ai_socktype = SOCK_STREAM;
                    129:        hints.ai_protocol = 0;
                    130:        error = getaddrinfo(host, port, &hints, &res0);
1.35      deraadt   131:        if (error == EAI_SERVICE) {
                    132:                /*
                    133:                 * If the services file is corrupt/missing, fall back
                    134:                 * on our hard-coded defines.
                    135:                 */
                    136:                char pbuf[NI_MAXSERV];
                    137:
                    138:                pbuf[0] = '\0';
                    139:                if (strcmp(port, "ftp") == 0)
                    140:                        snprintf(pbuf, sizeof(pbuf), "%d", FTP_PORT);
                    141:                else if (strcmp(port, "ftpgate") == 0)
                    142:                        snprintf(pbuf, sizeof(pbuf), "%d", GATE_PORT);
                    143:                else if (strcmp(port, "http") == 0)
                    144:                        snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT);
1.63      deraadt   145: #ifndef SMALL
                    146:                else if (strcmp(port, "https") == 0)
                    147:                        snprintf(pbuf, sizeof(pbuf), "%d", HTTPS_PORT);
1.72      martynas  148: #endif /* !SMALL */
1.35      deraadt   149:                if (pbuf[0])
                    150:                        error = getaddrinfo(host, pbuf, &hints, &res0);
                    151:        }
1.34      itojun    152:        if (error) {
1.39      itojun    153:                if (error == EAI_SERVICE)
                    154:                        warnx("%s: bad port number `%s'", host, port);
                    155:                else
                    156:                        warnx("%s: %s", host, gai_strerror(error));
1.1       deraadt   157:                code = -1;
                    158:                return (0);
                    159:        }
1.34      itojun    160:
                    161:        if (res0->ai_canonname)
1.41      lebel     162:                strlcpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf));
1.34      itojun    163:        else
1.41      lebel     164:                strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
1.34      itojun    165:        hostname = hostnamebuf;
1.82      haesbaer  166:
                    167: #ifndef SMALL
                    168:        if (srcaddr) {
                    169:                struct addrinfo ahints;
                    170:
                    171:                memset(&ahints, 0, sizeof(ahints));
                    172:                ahints.ai_family = family;
                    173:                ahints.ai_socktype = SOCK_STREAM;
                    174:                ahints.ai_flags |= AI_NUMERICHOST;
                    175:                ahints.ai_protocol = 0;
                    176:
                    177:                error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
                    178:                if (error) {
1.86      guenther  179:                        warnx("%s: %s", srcaddr, gai_strerror(error));
1.82      haesbaer  180:                        code = -1;
                    181:                        return (0);
                    182:                }
                    183:        }
                    184: #endif /* !SMALL */
1.34      itojun    185:
                    186:        s = -1;
                    187:        for (res = res0; res; res = res->ai_next) {
                    188: #if 0  /*old behavior*/
                    189:                if (res != res0)        /* not on the first address */
                    190: #else
                    191:                if (res0->ai_next)      /* if we have multiple possibilities */
                    192: #endif
                    193:                {
1.50      itojun    194:                        if (getnameinfo(res->ai_addr, res->ai_addrlen,
                    195:                            hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
                    196:                                strlcpy(hbuf, "unknown", sizeof(hbuf));
1.70      pyr       197:                        if (verbose)
                    198:                                fprintf(ttyout, "Trying %s...\n", hbuf);
1.34      itojun    199:                }
                    200:                s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                    201:                if (s < 0) {
                    202:                        cause = "socket";
1.27      deraadt   203:                        continue;
1.34      itojun    204:                }
1.82      haesbaer  205: #ifndef SMALL
                    206:                if (srcaddr) {
                    207:                        if (ares->ai_family != res->ai_family) {
                    208:                                close(s);
                    209:                                s = -1;
                    210:                                errno = EINVAL;
                    211:                                cause = "bind";
                    212:                                continue;
                    213:                        }
                    214:                        if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) {
                    215:                                cause = "bind";
                    216:                                error = errno;
                    217:                                close(s);
                    218:                                errno = error;
                    219:                                s = -1;
                    220:                                continue;
                    221:                        }
                    222:                }
                    223: #endif /* !SMALL */
1.34      itojun    224:                while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0
                    225:                                && errno == EINTR) {
                    226:                        ;
                    227:                }
                    228:                if (error) {
                    229:                        /* this "if" clause is to prevent print warning twice */
1.78      martynas  230:                        if (verbose && res->ai_next) {
1.50      itojun    231:                                if (getnameinfo(res->ai_addr, res->ai_addrlen,
                    232:                                    hbuf, sizeof(hbuf), NULL, 0,
                    233:                                    NI_NUMERICHOST) != 0)
                    234:                                        strlcpy(hbuf, "(unknown)",
                    235:                                            sizeof(hbuf));
1.34      itojun    236:                                warn("connect to address %s", hbuf);
1.1       deraadt   237:                        }
1.34      itojun    238:                        cause = "connect";
1.60      moritz    239:                        error = errno;
1.34      itojun    240:                        close(s);
1.60      moritz    241:                        errno = error;
1.34      itojun    242:                        s = -1;
1.1       deraadt   243:                        continue;
                    244:                }
1.34      itojun    245:
                    246:                /* finally we got one */
                    247:                break;
                    248:        }
                    249:        if (s < 0) {
1.38      millert   250:                warn("%s", cause);
1.1       deraadt   251:                code = -1;
1.34      itojun    252:                freeaddrinfo(res0);
                    253:                return 0;
1.1       deraadt   254:        }
1.34      itojun    255:        memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen);
1.57      deraadt   256:        namelen = res->ai_addrlen;
1.34      itojun    257:        freeaddrinfo(res0);
                    258:        res0 = res = NULL;
1.82      haesbaer  259: #ifndef SMALL
                    260:        if (srcaddr) {
                    261:                freeaddrinfo(ares);
                    262:                ares = NULL;
                    263:        }
                    264: #endif /* !SMALL */
1.57      deraadt   265:        if (getsockname(s, (struct sockaddr *)&myctladdr, &namelen) < 0) {
1.1       deraadt   266:                warn("getsockname");
                    267:                code = -1;
                    268:                goto bad;
                    269:        }
1.34      itojun    270: #if defined(IPPROTO_IP) && defined(IP_TOS)
                    271:        if (hisctladdr.su_family == AF_INET) {
                    272:                tos = IPTOS_LOWDELAY;
                    273:                if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
                    274:                        warn("setsockopt TOS (ignored)");
                    275:        }
1.1       deraadt   276: #endif
                    277:        cin = fdopen(s, "r");
                    278:        cout = fdopen(s, "w");
                    279:        if (cin == NULL || cout == NULL) {
                    280:                warnx("fdopen failed.");
                    281:                if (cin)
1.11      millert   282:                        (void)fclose(cin);
1.1       deraadt   283:                if (cout)
1.11      millert   284:                        (void)fclose(cout);
1.1       deraadt   285:                code = -1;
                    286:                goto bad;
                    287:        }
                    288:        if (verbose)
1.18      deraadt   289:                fprintf(ttyout, "Connected to %s.\n", hostname);
1.1       deraadt   290:        if (getreply(0) > 2) {  /* read startup message from server */
                    291:                if (cin)
1.11      millert   292:                        (void)fclose(cin);
1.1       deraadt   293:                if (cout)
1.11      millert   294:                        (void)fclose(cout);
1.1       deraadt   295:                code = -1;
                    296:                goto bad;
                    297:        }
                    298: #ifdef SO_OOBINLINE
                    299:        {
1.73      martynas  300:        int ret, on = 1;
1.1       deraadt   301:
1.73      martynas  302:        ret = setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on));
                    303: #ifndef SMALL
                    304:        if (ret < 0 && debug)
                    305:                warn("setsockopt");
                    306: #endif /* !SMALL */
1.1       deraadt   307:        }
                    308: #endif /* SO_OOBINLINE */
                    309:
                    310:        return (hostname);
                    311: bad:
1.11      millert   312:        (void)close(s);
1.1       deraadt   313:        return ((char *)0);
                    314: }
                    315:
1.57      deraadt   316: /* ARGSUSED */
1.1       deraadt   317: void
1.57      deraadt   318: cmdabort(int signo)
1.1       deraadt   319: {
1.87    ! deraadt   320:        int save_errno = errno;
1.1       deraadt   321:
1.10      millert   322:        alarmtimer(0);
1.87    ! deraadt   323:        (void) write(fileno(ttyout), "\n\r", 2);
1.1       deraadt   324:        abrtflag++;
1.87    ! deraadt   325:
        !           326:        errno = save_errno;
1.1       deraadt   327:        if (ptflag)
1.10      millert   328:                longjmp(ptabort, 1);
1.1       deraadt   329: }
                    330:
                    331: /*VARARGS*/
                    332: int
1.13      millert   333: command(const char *fmt, ...)
1.1       deraadt   334: {
                    335:        va_list ap;
                    336:        int r;
                    337:        sig_t oldintr;
                    338:
                    339:        abrtflag = 0;
1.73      martynas  340: #ifndef SMALL
1.1       deraadt   341:        if (debug) {
1.18      deraadt   342:                fputs("---> ", ttyout);
1.13      millert   343:                va_start(ap, fmt);
1.1       deraadt   344:                if (strncmp("PASS ", fmt, 5) == 0)
1.18      deraadt   345:                        fputs("PASS XXXX", ttyout);
1.10      millert   346:                else if (strncmp("ACCT ", fmt, 5) == 0)
1.18      deraadt   347:                        fputs("ACCT XXXX", ttyout);
1.10      millert   348:                else
1.28      millert   349:                        vfprintf(ttyout, fmt, ap);
1.1       deraadt   350:                va_end(ap);
1.18      deraadt   351:                putc('\n', ttyout);
                    352:                (void)fflush(ttyout);
1.1       deraadt   353:        }
1.73      martynas  354: #endif /* !SMALL */
1.1       deraadt   355:        if (cout == NULL) {
1.13      millert   356:                warnx("No control connection for command.");
1.1       deraadt   357:                code = -1;
                    358:                return (0);
                    359:        }
                    360:        oldintr = signal(SIGINT, cmdabort);
1.13      millert   361:        va_start(ap, fmt);
1.1       deraadt   362:        vfprintf(cout, fmt, ap);
                    363:        va_end(ap);
1.11      millert   364:        fputs("\r\n", cout);
                    365:        (void)fflush(cout);
1.1       deraadt   366:        cpend = 1;
                    367:        r = getreply(!strcmp(fmt, "QUIT"));
                    368:        if (abrtflag && oldintr != SIG_IGN)
                    369:                (*oldintr)(SIGINT);
1.11      millert   370:        (void)signal(SIGINT, oldintr);
1.1       deraadt   371:        return (r);
                    372: }
                    373:
1.68      espie     374: int keep_alive_timeout = 60;           /* 0 -> no timeout */
1.67      espie     375:
                    376: static int full_noops_sent = 0;
                    377: static time_t last_timestamp = 0;      /* 0 -> no measurement yet */
                    378: static char noop[] = "NOOP\r\n";
                    379: #define NOOP_LENGTH (sizeof noop - 1)
                    380: static int current_nop_pos = 0;                /* 0 -> no noop started */
                    381:
                    382: /* to achieve keep alive, we send noop one byte at a time */
1.83      deraadt   383: static void
                    384: send_noop_char(void)
1.67      espie     385: {
1.73      martynas  386: #ifndef SMALL
1.67      espie     387:        if (debug)
                    388:                fprintf(ttyout, "---> %c\n", noop[current_nop_pos]);
1.73      martynas  389: #endif /* !SMALL */
1.67      espie     390:        fputc(noop[current_nop_pos++], cout);
                    391:        (void)fflush(cout);
                    392:        if (current_nop_pos >= NOOP_LENGTH) {
                    393:                full_noops_sent++;
                    394:                current_nop_pos = 0;
                    395:        }
                    396: }
                    397:
1.83      deraadt   398: static void
                    399: may_reset_noop_timeout(void)
1.67      espie     400: {
                    401:        if (keep_alive_timeout != 0)
                    402:                last_timestamp = time(NULL);
                    403: }
                    404:
1.83      deraadt   405: static void
                    406: may_receive_noop_ack(void)
1.67      espie     407: {
                    408:        int i;
1.74      martynas  409:
                    410:        if (cout == NULL) {
                    411:                /* Lost connection;  so just pretend we're fine. */
                    412:                current_nop_pos = full_noops_sent = 0;
                    413:                return;
                    414:        }
1.67      espie     415:
                    416:        /* finish sending last incomplete noop */
                    417:        if (current_nop_pos != 0) {
                    418:                fputs(&(noop[current_nop_pos]), cout);
1.73      martynas  419: #ifndef SMALL
1.67      espie     420:                if (debug)
                    421:                        fprintf(ttyout, "---> %s\n", &(noop[current_nop_pos]));
1.73      martynas  422: #endif /* !SMALL */
1.67      espie     423:                (void)fflush(cout);
                    424:                current_nop_pos = 0;
                    425:                full_noops_sent++;
                    426:        }
                    427:        /* and get the replies */
                    428:        for (i = 0; i < full_noops_sent; i++)
                    429:                (void)getreply(0);
                    430:
                    431:        full_noops_sent = 0;
                    432: }
                    433:
1.83      deraadt   434: static void
                    435: may_send_noop_char(void)
1.67      espie     436: {
                    437:        if (keep_alive_timeout != 0) {
                    438:                if (last_timestamp != 0) {
                    439:                        time_t t = time(NULL);
                    440:
                    441:                        if (t - last_timestamp >= keep_alive_timeout) {
                    442:                                last_timestamp = t;
                    443:                                send_noop_char();
                    444:                        }
                    445:                } else {
                    446:                        last_timestamp = time(NULL);
                    447:                }
                    448:        }
                    449: }
                    450:
1.10      millert   451: char reply_string[BUFSIZ];             /* first line of previous reply */
1.1       deraadt   452:
                    453: int
1.56      deraadt   454: getreply(int expecteof)
1.1       deraadt   455: {
1.10      millert   456:        char current_line[BUFSIZ];      /* last line of previous reply */
1.64      ray       457:        int c, n, lineno;
1.1       deraadt   458:        int dig;
                    459:        int originalcode = 0, continuation = 0;
                    460:        sig_t oldintr;
                    461:        int pflag = 0;
                    462:        char *cp, *pt = pasv;
                    463:
1.25      weingart  464:        memset(current_line, 0, sizeof(current_line));
1.1       deraadt   465:        oldintr = signal(SIGINT, cmdabort);
1.64      ray       466:        for (lineno = 0 ;; lineno++) {
1.1       deraadt   467:                dig = n = code = 0;
1.10      millert   468:                cp = current_line;
1.23      millert   469:                while ((c = fgetc(cin)) != '\n') {
1.1       deraadt   470:                        if (c == IAC) {     /* handle telnet commands */
1.23      millert   471:                                switch (c = fgetc(cin)) {
1.1       deraadt   472:                                case WILL:
                    473:                                case WONT:
1.23      millert   474:                                        c = fgetc(cin);
1.1       deraadt   475:                                        fprintf(cout, "%c%c%c", IAC, DONT, c);
1.11      millert   476:                                        (void)fflush(cout);
1.1       deraadt   477:                                        break;
                    478:                                case DO:
                    479:                                case DONT:
1.23      millert   480:                                        c = fgetc(cin);
1.1       deraadt   481:                                        fprintf(cout, "%c%c%c", IAC, WONT, c);
1.11      millert   482:                                        (void)fflush(cout);
1.1       deraadt   483:                                        break;
                    484:                                default:
                    485:                                        break;
                    486:                                }
                    487:                                continue;
                    488:                        }
                    489:                        dig++;
                    490:                        if (c == EOF) {
                    491:                                if (expecteof) {
1.11      millert   492:                                        (void)signal(SIGINT, oldintr);
1.1       deraadt   493:                                        code = 221;
                    494:                                        return (0);
                    495:                                }
                    496:                                lostpeer();
                    497:                                if (verbose) {
1.18      deraadt   498:                                        fputs(
                    499: "421 Service not available, remote server has closed connection.\n", ttyout);
                    500:                                        (void)fflush(ttyout);
1.1       deraadt   501:                                }
                    502:                                code = 421;
                    503:                                return (4);
                    504:                        }
1.10      millert   505:                        if (c != '\r' && (verbose > 0 ||
1.71      martynas  506:                            ((verbose > -1 && n == '5' && dig > 4) &&
1.21      mickey    507:                            (((!n && c < '5') || (n && n < '5'))
1.71      martynas  508:                             || !retry_connect)))) {
1.1       deraadt   509:                                if (proxflag &&
1.10      millert   510:                                   (dig == 1 || (dig == 5 && verbose == 0)))
1.18      deraadt   511:                                        fprintf(ttyout, "%s:", hostname);
                    512:                                (void)putc(c, ttyout);
1.1       deraadt   513:                        }
                    514:                        if (dig < 4 && isdigit(c))
                    515:                                code = code * 10 + (c - '0');
1.34      itojun    516:                        if (!pflag && (code == 227 || code == 228))
1.1       deraadt   517:                                pflag = 1;
1.34      itojun    518:                        else if (!pflag && code == 229)
                    519:                                pflag = 100;
1.1       deraadt   520:                        if (dig > 4 && pflag == 1 && isdigit(c))
                    521:                                pflag = 2;
                    522:                        if (pflag == 2) {
1.44      itojun    523:                                if (c != '\r' && c != ')') {
                    524:                                        if (pt < &pasv[sizeof(pasv) - 1])
                    525:                                                *pt++ = c;
                    526:                                } else {
1.1       deraadt   527:                                        *pt = '\0';
                    528:                                        pflag = 3;
                    529:                                }
                    530:                        }
1.34      itojun    531:                        if (pflag == 100 && c == '(')
                    532:                                pflag = 2;
1.1       deraadt   533:                        if (dig == 4 && c == '-') {
                    534:                                if (continuation)
                    535:                                        code = 0;
                    536:                                continuation++;
                    537:                        }
1.10      millert   538:                        if (n == 0)
                    539:                                n = c;
                    540:                        if (cp < &current_line[sizeof(current_line) - 1])
1.1       deraadt   541:                                *cp++ = c;
                    542:                }
1.11      millert   543:                if (verbose > 0 || ((verbose > -1 && n == '5') &&
                    544:                    (n < '5' || !retry_connect))) {
1.18      deraadt   545:                        (void)putc(c, ttyout);
                    546:                        (void)fflush (ttyout);
1.1       deraadt   547:                }
1.64      ray       548:                if (lineno == 0) {
1.10      millert   549:                        size_t len = cp - current_line;
                    550:
                    551:                        if (len > sizeof(reply_string))
                    552:                                len = sizeof(reply_string);
                    553:
1.48      itojun    554:                        (void)strlcpy(reply_string, current_line, len);
1.10      millert   555:                }
1.1       deraadt   556:                if (continuation && code != originalcode) {
                    557:                        if (originalcode == 0)
                    558:                                originalcode = code;
                    559:                        continue;
                    560:                }
                    561:                *cp = '\0';
                    562:                if (n != '1')
                    563:                        cpend = 0;
1.11      millert   564:                (void)signal(SIGINT, oldintr);
1.1       deraadt   565:                if (code == 421 || originalcode == 421)
                    566:                        lostpeer();
                    567:                if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
                    568:                        (*oldintr)(SIGINT);
                    569:                return (n - '0');
                    570:        }
                    571: }
                    572:
1.77      martynas  573: #ifndef SMALL
1.1       deraadt   574: jmp_buf        sendabort;
                    575:
1.57      deraadt   576: /* ARGSUSED */
1.1       deraadt   577: void
1.57      deraadt   578: abortsend(int signo)
1.1       deraadt   579: {
1.87    ! deraadt   580:        int save_errno = errno;
1.10      millert   581:        alarmtimer(0);
1.1       deraadt   582:        mflag = 0;
                    583:        abrtflag = 0;
1.87    ! deraadt   584: #define MSG "\nsend aborted\nwaiting for remote to finish abort.\n"
        !           585:        (void) write(fileno(ttyout), MSG, strlen(MSG));
        !           586: #undef MSG
        !           587:
        !           588:        errno = save_errno;
1.1       deraadt   589:        longjmp(sendabort, 1);
                    590: }
                    591:
                    592: void
1.56      deraadt   593: sendrequest(const char *cmd, const char *local, const char *remote,
                    594:     int printnames)
1.1       deraadt   595: {
                    596:        struct stat st;
                    597:        int c, d;
1.40      millert   598:        FILE * volatile fin, * volatile dout;
1.42      millert   599:        int (* volatile closefunc)(FILE *);
1.40      millert   600:        volatile sig_t oldinti, oldintr, oldintp;
1.20      millert   601:        volatile off_t hashbytes;
1.40      millert   602:        char * volatile lmode;
                    603:        char buf[BUFSIZ], *bufp;
1.69      ray       604:        int oprogress, serrno;
1.1       deraadt   605:
1.10      millert   606:        hashbytes = mark;
                    607:        direction = "sent";
1.20      millert   608:        dout = NULL;
1.10      millert   609:        bytes = 0;
                    610:        filesize = -1;
1.13      millert   611:        oprogress = progress;
1.1       deraadt   612:        if (verbose && printnames) {
                    613:                if (local && *local != '-')
1.18      deraadt   614:                        fprintf(ttyout, "local: %s ", local);
1.1       deraadt   615:                if (remote)
1.18      deraadt   616:                        fprintf(ttyout, "remote: %s\n", remote);
1.1       deraadt   617:        }
                    618:        if (proxy) {
                    619:                proxtrans(cmd, local, remote);
                    620:                return;
                    621:        }
                    622:        if (curtype != type)
                    623:                changetype(type, 0);
                    624:        closefunc = NULL;
                    625:        oldintr = NULL;
                    626:        oldintp = NULL;
1.10      millert   627:        oldinti = NULL;
1.1       deraadt   628:        lmode = "w";
                    629:        if (setjmp(sendabort)) {
                    630:                while (cpend) {
1.11      millert   631:                        (void)getreply(0);
1.1       deraadt   632:                }
                    633:                if (data >= 0) {
1.11      millert   634:                        (void)close(data);
1.1       deraadt   635:                        data = -1;
                    636:                }
                    637:                if (oldintr)
1.11      millert   638:                        (void)signal(SIGINT, oldintr);
1.1       deraadt   639:                if (oldintp)
1.11      millert   640:                        (void)signal(SIGPIPE, oldintp);
1.10      millert   641:                if (oldinti)
1.11      millert   642:                        (void)signal(SIGINFO, oldinti);
1.13      millert   643:                progress = oprogress;
1.1       deraadt   644:                code = -1;
                    645:                return;
                    646:        }
                    647:        oldintr = signal(SIGINT, abortsend);
1.10      millert   648:        oldinti = signal(SIGINFO, psummary);
1.13      millert   649:        if (strcmp(local, "-") == 0) {
1.1       deraadt   650:                fin = stdin;
1.31      millert   651:                if (progress == 1)
                    652:                        progress = 0;
1.13      millert   653:        } else if (*local == '|') {
1.10      millert   654:                oldintp = signal(SIGPIPE, SIG_IGN);
1.1       deraadt   655:                fin = popen(local + 1, "r");
                    656:                if (fin == NULL) {
                    657:                        warn("%s", local + 1);
1.11      millert   658:                        (void)signal(SIGINT, oldintr);
                    659:                        (void)signal(SIGPIPE, oldintp);
                    660:                        (void)signal(SIGINFO, oldinti);
1.1       deraadt   661:                        code = -1;
                    662:                        return;
                    663:                }
1.31      millert   664:                if (progress == 1)
                    665:                        progress = 0;
1.1       deraadt   666:                closefunc = pclose;
                    667:        } else {
                    668:                fin = fopen(local, "r");
                    669:                if (fin == NULL) {
                    670:                        warn("local: %s", local);
1.11      millert   671:                        (void)signal(SIGINT, oldintr);
                    672:                        (void)signal(SIGINFO, oldinti);
1.1       deraadt   673:                        code = -1;
                    674:                        return;
                    675:                }
                    676:                closefunc = fclose;
                    677:                if (fstat(fileno(fin), &st) < 0 ||
1.14      millert   678:                    (st.st_mode & S_IFMT) != S_IFREG) {
1.18      deraadt   679:                        fprintf(ttyout, "%s: not a plain file.\n", local);
1.11      millert   680:                        (void)signal(SIGINT, oldintr);
                    681:                        (void)signal(SIGINFO, oldinti);
1.1       deraadt   682:                        fclose(fin);
                    683:                        code = -1;
                    684:                        return;
                    685:                }
1.10      millert   686:                filesize = st.st_size;
1.1       deraadt   687:        }
                    688:        if (initconn()) {
1.11      millert   689:                (void)signal(SIGINT, oldintr);
                    690:                (void)signal(SIGINFO, oldinti);
1.1       deraadt   691:                if (oldintp)
1.11      millert   692:                        (void)signal(SIGPIPE, oldintp);
1.1       deraadt   693:                code = -1;
1.13      millert   694:                progress = oprogress;
1.1       deraadt   695:                if (closefunc != NULL)
                    696:                        (*closefunc)(fin);
                    697:                return;
                    698:        }
                    699:        if (setjmp(sendabort))
                    700:                goto abort;
                    701:
                    702:        if (restart_point &&
                    703:            (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
1.59      deraadt   704:                int rc = -1;
1.1       deraadt   705:
                    706:                switch (curtype) {
                    707:                case TYPE_A:
1.58      sturm     708:                        rc = fseeko(fin, restart_point, SEEK_SET);
1.1       deraadt   709:                        break;
                    710:                case TYPE_I:
                    711:                case TYPE_L:
1.59      deraadt   712:                        if (lseek(fileno(fin), restart_point, SEEK_SET) != -1)
                    713:                                rc = 0;
1.1       deraadt   714:                        break;
                    715:                }
1.59      deraadt   716:                if (rc == -1) {
1.1       deraadt   717:                        warn("local: %s", local);
1.13      millert   718:                        progress = oprogress;
1.1       deraadt   719:                        if (closefunc != NULL)
                    720:                                (*closefunc)(fin);
                    721:                        return;
                    722:                }
1.58      sturm     723:                if (command("REST %lld", (long long) restart_point)
1.1       deraadt   724:                        != CONTINUE) {
1.13      millert   725:                        progress = oprogress;
1.1       deraadt   726:                        if (closefunc != NULL)
                    727:                                (*closefunc)(fin);
                    728:                        return;
                    729:                }
                    730:                lmode = "r+w";
                    731:        }
                    732:        if (remote) {
                    733:                if (command("%s %s", cmd, remote) != PRELIM) {
1.11      millert   734:                        (void)signal(SIGINT, oldintr);
                    735:                        (void)signal(SIGINFO, oldinti);
1.13      millert   736:                        progress = oprogress;
1.1       deraadt   737:                        if (oldintp)
1.11      millert   738:                                (void)signal(SIGPIPE, oldintp);
1.1       deraadt   739:                        if (closefunc != NULL)
                    740:                                (*closefunc)(fin);
                    741:                        return;
                    742:                }
                    743:        } else
                    744:                if (command("%s", cmd) != PRELIM) {
1.11      millert   745:                        (void)signal(SIGINT, oldintr);
                    746:                        (void)signal(SIGINFO, oldinti);
1.13      millert   747:                        progress = oprogress;
1.1       deraadt   748:                        if (oldintp)
1.11      millert   749:                                (void)signal(SIGPIPE, oldintp);
1.1       deraadt   750:                        if (closefunc != NULL)
                    751:                                (*closefunc)(fin);
                    752:                        return;
                    753:                }
                    754:        dout = dataconn(lmode);
                    755:        if (dout == NULL)
                    756:                goto abort;
1.75      martynas  757:        progressmeter(-1, remote);
1.67      espie     758:        may_reset_noop_timeout();
1.1       deraadt   759:        oldintp = signal(SIGPIPE, SIG_IGN);
                    760:        switch (curtype) {
                    761:
                    762:        case TYPE_I:
                    763:        case TYPE_L:
1.69      ray       764:                d = 0;
1.11      millert   765:                while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) {
1.67      espie     766:                        may_send_noop_char();
1.1       deraadt   767:                        bytes += c;
                    768:                        for (bufp = buf; c > 0; c -= d, bufp += d)
1.20      millert   769:                                if ((d = write(fileno(dout), bufp, (size_t)c))
                    770:                                    <= 0)
1.1       deraadt   771:                                        break;
1.10      millert   772:                        if (hash && (!progress || filesize < 0) ) {
1.1       deraadt   773:                                while (bytes >= hashbytes) {
1.18      deraadt   774:                                        (void)putc('#', ttyout);
1.7       kstailey  775:                                        hashbytes += mark;
1.1       deraadt   776:                                }
1.18      deraadt   777:                                (void)fflush(ttyout);
1.1       deraadt   778:                        }
                    779:                }
1.69      ray       780:                if (c == -1 || d == -1)
                    781:                        serrno = errno;
1.10      millert   782:                if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7       kstailey  783:                        if (bytes < mark)
1.18      deraadt   784:                                (void)putc('#', ttyout);
                    785:                        (void)putc('\n', ttyout);
                    786:                        (void)fflush(ttyout);
1.1       deraadt   787:                }
                    788:                if (c < 0)
1.86      guenther  789:                        warnc(serrno, "local: %s", local);
1.1       deraadt   790:                if (d < 0) {
1.69      ray       791:                        if (serrno != EPIPE)
1.86      guenther  792:                                warnc(serrno, "netout");
1.1       deraadt   793:                        bytes = -1;
                    794:                }
                    795:                break;
                    796:
                    797:        case TYPE_A:
1.23      millert   798:                while ((c = fgetc(fin)) != EOF) {
1.67      espie     799:                        may_send_noop_char();
1.1       deraadt   800:                        if (c == '\n') {
1.10      millert   801:                                while (hash && (!progress || filesize < 0) &&
                    802:                                    (bytes >= hashbytes)) {
1.18      deraadt   803:                                        (void)putc('#', ttyout);
                    804:                                        (void)fflush(ttyout);
1.7       kstailey  805:                                        hashbytes += mark;
1.1       deraadt   806:                                }
                    807:                                if (ferror(dout))
                    808:                                        break;
1.11      millert   809:                                (void)putc('\r', dout);
1.1       deraadt   810:                                bytes++;
                    811:                        }
1.11      millert   812:                        (void)putc(c, dout);
1.1       deraadt   813:                        bytes++;
1.10      millert   814: #if 0  /* this violates RFC */
                    815:                        if (c == '\r') {
                    816:                                (void)putc('\0', dout);
                    817:                                bytes++;
                    818:                        }
                    819: #endif
1.1       deraadt   820:                }
1.69      ray       821:                if (ferror(fin) || ferror(dout))
                    822:                        serrno = errno;
1.10      millert   823:                if (hash && (!progress || filesize < 0)) {
1.1       deraadt   824:                        if (bytes < hashbytes)
1.18      deraadt   825:                                (void)putc('#', ttyout);
                    826:                        (void)putc('\n', ttyout);
                    827:                        (void)fflush(ttyout);
1.1       deraadt   828:                }
                    829:                if (ferror(fin))
1.86      guenther  830:                        warnc(serrno, "local: %s", local);
1.1       deraadt   831:                if (ferror(dout)) {
                    832:                        if (errno != EPIPE)
1.86      guenther  833:                                warnc(serrno, "netout");
1.1       deraadt   834:                        bytes = -1;
                    835:                }
                    836:                break;
                    837:        }
1.75      martynas  838:        progressmeter(1, NULL);
1.13      millert   839:        progress = oprogress;
1.1       deraadt   840:        if (closefunc != NULL)
                    841:                (*closefunc)(fin);
1.11      millert   842:        (void)fclose(dout);
                    843:        (void)getreply(0);
1.67      espie     844:        may_receive_noop_ack();
1.11      millert   845:        (void)signal(SIGINT, oldintr);
                    846:        (void)signal(SIGINFO, oldinti);
1.1       deraadt   847:        if (oldintp)
1.11      millert   848:                (void)signal(SIGPIPE, oldintp);
1.1       deraadt   849:        if (bytes > 0)
1.10      millert   850:                ptransfer(0);
1.1       deraadt   851:        return;
                    852: abort:
1.11      millert   853:        (void)signal(SIGINT, oldintr);
                    854:        (void)signal(SIGINFO, oldinti);
1.13      millert   855:        progress = oprogress;
1.1       deraadt   856:        if (oldintp)
1.11      millert   857:                (void)signal(SIGPIPE, oldintp);
1.1       deraadt   858:        if (!cpend) {
                    859:                code = -1;
                    860:                return;
                    861:        }
                    862:        if (data >= 0) {
1.11      millert   863:                (void)close(data);
1.1       deraadt   864:                data = -1;
                    865:        }
                    866:        if (dout)
1.11      millert   867:                (void)fclose(dout);
                    868:        (void)getreply(0);
1.1       deraadt   869:        code = -1;
                    870:        if (closefunc != NULL && fin != NULL)
                    871:                (*closefunc)(fin);
                    872:        if (bytes > 0)
1.10      millert   873:                ptransfer(0);
1.1       deraadt   874: }
1.77      martynas  875: #endif /* !SMALL */
1.1       deraadt   876:
                    877: jmp_buf        recvabort;
                    878:
1.57      deraadt   879: /* ARGSUSED */
1.1       deraadt   880: void
1.57      deraadt   881: abortrecv(int signo)
1.1       deraadt   882: {
                    883:
1.10      millert   884:        alarmtimer(0);
1.1       deraadt   885:        mflag = 0;
                    886:        abrtflag = 0;
1.18      deraadt   887:        fputs("\nreceive aborted\nwaiting for remote to finish abort.\n", ttyout);
                    888:        (void)fflush(ttyout);
1.1       deraadt   889:        longjmp(recvabort, 1);
                    890: }
                    891:
                    892: void
1.56      deraadt   893: recvrequest(const char *cmd, const char * volatile local, const char *remote,
                    894:     const char *lmode, int printnames, int ignorespecial)
1.1       deraadt   895: {
1.40      millert   896:        FILE * volatile fout, * volatile din;
1.42      millert   897:        int (* volatile closefunc)(FILE *);
1.40      millert   898:        volatile sig_t oldinti, oldintr, oldintp;
1.69      ray       899:        int c, d, serrno;
1.20      millert   900:        volatile int is_retr, tcrflag, bare_lfs;
                    901:        static size_t bufsize;
1.1       deraadt   902:        static char *buf;
1.20      millert   903:        volatile off_t hashbytes;
1.1       deraadt   904:        struct stat st;
1.10      millert   905:        time_t mtime;
1.13      millert   906:        int oprogress;
1.16      millert   907:        int opreserve;
1.1       deraadt   908:
1.20      millert   909:        fout = NULL;
                    910:        din = NULL;
                    911:        oldinti = NULL;
1.10      millert   912:        hashbytes = mark;
                    913:        direction = "received";
                    914:        bytes = 0;
1.20      millert   915:        bare_lfs = 0;
1.10      millert   916:        filesize = -1;
1.13      millert   917:        oprogress = progress;
1.16      millert   918:        opreserve = preserve;
1.1       deraadt   919:        is_retr = strcmp(cmd, "RETR") == 0;
                    920:        if (is_retr && verbose && printnames) {
1.22      millert   921:                if (local && (ignorespecial || *local != '-'))
1.18      deraadt   922:                        fprintf(ttyout, "local: %s ", local);
1.1       deraadt   923:                if (remote)
1.18      deraadt   924:                        fprintf(ttyout, "remote: %s\n", remote);
1.1       deraadt   925:        }
                    926:        if (proxy && is_retr) {
                    927:                proxtrans(cmd, local, remote);
                    928:                return;
                    929:        }
                    930:        closefunc = NULL;
                    931:        oldintr = NULL;
                    932:        oldintp = NULL;
                    933:        tcrflag = !crflag && is_retr;
                    934:        if (setjmp(recvabort)) {
                    935:                while (cpend) {
1.11      millert   936:                        (void)getreply(0);
1.1       deraadt   937:                }
                    938:                if (data >= 0) {
1.11      millert   939:                        (void)close(data);
1.1       deraadt   940:                        data = -1;
                    941:                }
                    942:                if (oldintr)
1.11      millert   943:                        (void)signal(SIGINT, oldintr);
1.10      millert   944:                if (oldinti)
1.11      millert   945:                        (void)signal(SIGINFO, oldinti);
1.15      millert   946:                progress = oprogress;
1.16      millert   947:                preserve = opreserve;
1.1       deraadt   948:                code = -1;
                    949:                return;
                    950:        }
                    951:        oldintr = signal(SIGINT, abortrecv);
1.10      millert   952:        oldinti = signal(SIGINFO, psummary);
1.22      millert   953:        if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
                    954:                if (access(local, W_OK) < 0) {
1.69      ray       955:                        char *dir;
1.1       deraadt   956:
                    957:                        if (errno != ENOENT && errno != EACCES) {
                    958:                                warn("local: %s", local);
1.11      millert   959:                                (void)signal(SIGINT, oldintr);
                    960:                                (void)signal(SIGINFO, oldinti);
1.1       deraadt   961:                                code = -1;
                    962:                                return;
                    963:                        }
1.69      ray       964:                        dir = strrchr(local, '/');
1.1       deraadt   965:                        if (dir != NULL)
                    966:                                *dir = 0;
1.22      millert   967:                        d = access(dir == local ? "/" : dir ? local : ".", W_OK);
1.1       deraadt   968:                        if (dir != NULL)
                    969:                                *dir = '/';
                    970:                        if (d < 0) {
                    971:                                warn("local: %s", local);
1.11      millert   972:                                (void)signal(SIGINT, oldintr);
                    973:                                (void)signal(SIGINFO, oldinti);
1.1       deraadt   974:                                code = -1;
                    975:                                return;
                    976:                        }
                    977:                        if (!runique && errno == EACCES &&
1.20      millert   978:                            chmod(local, (S_IRUSR|S_IWUSR)) < 0) {
1.1       deraadt   979:                                warn("local: %s", local);
1.11      millert   980:                                (void)signal(SIGINT, oldintr);
                    981:                                (void)signal(SIGINFO, oldinti);
1.1       deraadt   982:                                code = -1;
                    983:                                return;
                    984:                        }
                    985:                        if (runique && errno == EACCES &&
                    986:                           (local = gunique(local)) == NULL) {
1.11      millert   987:                                (void)signal(SIGINT, oldintr);
                    988:                                (void)signal(SIGINFO, oldinti);
1.1       deraadt   989:                                code = -1;
                    990:                                return;
                    991:                        }
                    992:                }
                    993:                else if (runique && (local = gunique(local)) == NULL) {
1.11      millert   994:                        (void)signal(SIGINT, oldintr);
                    995:                        (void)signal(SIGINFO, oldinti);
1.1       deraadt   996:                        code = -1;
                    997:                        return;
                    998:                }
                    999:        }
                   1000:        if (!is_retr) {
                   1001:                if (curtype != TYPE_A)
                   1002:                        changetype(TYPE_A, 0);
1.10      millert  1003:        } else {
                   1004:                if (curtype != type)
                   1005:                        changetype(type, 0);
                   1006:                filesize = remotesize(remote, 0);
                   1007:        }
1.1       deraadt  1008:        if (initconn()) {
1.11      millert  1009:                (void)signal(SIGINT, oldintr);
                   1010:                (void)signal(SIGINFO, oldinti);
1.1       deraadt  1011:                code = -1;
                   1012:                return;
                   1013:        }
                   1014:        if (setjmp(recvabort))
                   1015:                goto abort;
                   1016:        if (is_retr && restart_point &&
1.58      sturm    1017:            command("REST %lld", (long long) restart_point) != CONTINUE)
1.1       deraadt  1018:                return;
                   1019:        if (remote) {
                   1020:                if (command("%s %s", cmd, remote) != PRELIM) {
1.11      millert  1021:                        (void)signal(SIGINT, oldintr);
                   1022:                        (void)signal(SIGINFO, oldinti);
1.1       deraadt  1023:                        return;
                   1024:                }
                   1025:        } else {
                   1026:                if (command("%s", cmd) != PRELIM) {
1.11      millert  1027:                        (void)signal(SIGINT, oldintr);
                   1028:                        (void)signal(SIGINFO, oldinti);
1.1       deraadt  1029:                        return;
                   1030:                }
                   1031:        }
                   1032:        din = dataconn("r");
                   1033:        if (din == NULL)
                   1034:                goto abort;
1.22      millert  1035:        if (!ignorespecial && strcmp(local, "-") == 0) {
1.1       deraadt  1036:                fout = stdout;
1.16      millert  1037:                preserve = 0;
1.22      millert  1038:        } else if (!ignorespecial && *local == '|') {
1.1       deraadt  1039:                oldintp = signal(SIGPIPE, SIG_IGN);
                   1040:                fout = popen(local + 1, "w");
                   1041:                if (fout == NULL) {
                   1042:                        warn("%s", local+1);
                   1043:                        goto abort;
                   1044:                }
1.31      millert  1045:                if (progress == 1)
                   1046:                        progress = 0;
1.16      millert  1047:                preserve = 0;
1.1       deraadt  1048:                closefunc = pclose;
                   1049:        } else {
                   1050:                fout = fopen(local, lmode);
                   1051:                if (fout == NULL) {
                   1052:                        warn("local: %s", local);
                   1053:                        goto abort;
                   1054:                }
                   1055:                closefunc = fclose;
                   1056:        }
                   1057:        if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
                   1058:                st.st_blksize = BUFSIZ;
                   1059:        if (st.st_blksize > bufsize) {
1.65      steven   1060:                (void)free(buf);
1.1       deraadt  1061:                buf = malloc((unsigned)st.st_blksize);
                   1062:                if (buf == NULL) {
                   1063:                        warn("malloc");
                   1064:                        bufsize = 0;
                   1065:                        goto abort;
                   1066:                }
                   1067:                bufsize = st.st_blksize;
                   1068:        }
1.14      millert  1069:        if ((st.st_mode & S_IFMT) != S_IFREG) {
1.31      millert  1070:                if (progress == 1)
                   1071:                        progress = 0;
1.13      millert  1072:                preserve = 0;
                   1073:        }
1.75      martynas 1074:        progressmeter(-1, remote);
1.67      espie    1075:        may_reset_noop_timeout();
1.1       deraadt  1076:        switch (curtype) {
                   1077:
                   1078:        case TYPE_I:
                   1079:        case TYPE_L:
                   1080:                if (restart_point &&
                   1081:                    lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
                   1082:                        warn("local: %s", local);
1.13      millert  1083:                        progress = oprogress;
1.16      millert  1084:                        preserve = opreserve;
1.1       deraadt  1085:                        if (closefunc != NULL)
                   1086:                                (*closefunc)(fout);
                   1087:                        return;
                   1088:                }
                   1089:                errno = d = 0;
                   1090:                while ((c = read(fileno(din), buf, bufsize)) > 0) {
1.57      deraadt  1091:                        ssize_t wr;
1.32      deraadt  1092:                        size_t  rd = c;
                   1093:
1.67      espie    1094:                        may_send_noop_char();
1.32      deraadt  1095:                        d = 0;
                   1096:                        do {
                   1097:                                wr = write(fileno(fout), buf + d, rd);
1.84      jca      1098:                                if (wr == -1) {
                   1099:                                        d = -1;
1.32      deraadt  1100:                                        break;
1.84      jca      1101:                                }
1.32      deraadt  1102:                                d += wr;
                   1103:                                rd -= wr;
                   1104:                        } while (d < c);
                   1105:                        if (rd != 0)
1.1       deraadt  1106:                                break;
                   1107:                        bytes += c;
1.10      millert  1108:                        if (hash && (!progress || filesize < 0)) {
1.1       deraadt  1109:                                while (bytes >= hashbytes) {
1.18      deraadt  1110:                                        (void)putc('#', ttyout);
1.7       kstailey 1111:                                        hashbytes += mark;
1.1       deraadt  1112:                                }
1.18      deraadt  1113:                                (void)fflush(ttyout);
1.1       deraadt  1114:                        }
                   1115:                }
1.69      ray      1116:                if (c == -1 || d < c)
                   1117:                        serrno = errno;
1.10      millert  1118:                if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7       kstailey 1119:                        if (bytes < mark)
1.18      deraadt  1120:                                (void)putc('#', ttyout);
                   1121:                        (void)putc('\n', ttyout);
                   1122:                        (void)fflush(ttyout);
1.1       deraadt  1123:                }
                   1124:                if (c < 0) {
1.69      ray      1125:                        if (serrno != EPIPE)
1.86      guenther 1126:                                warnc(serrno, "netin");
1.1       deraadt  1127:                        bytes = -1;
                   1128:                }
                   1129:                if (d < c) {
                   1130:                        if (d < 0)
1.86      guenther 1131:                                warnc(serrno, "local: %s", local);
1.1       deraadt  1132:                        else
                   1133:                                warnx("%s: short write", local);
                   1134:                }
                   1135:                break;
                   1136:
                   1137:        case TYPE_A:
                   1138:                if (restart_point) {
                   1139:                        int i, n, ch;
                   1140:
                   1141:                        if (fseek(fout, 0L, SEEK_SET) < 0)
                   1142:                                goto done;
                   1143:                        n = restart_point;
                   1144:                        for (i = 0; i++ < n;) {
1.69      ray      1145:                                if ((ch = fgetc(fout)) == EOF) {
                   1146:                                        if (!ferror(fout))
                   1147:                                                errno = 0;
1.1       deraadt  1148:                                        goto done;
1.69      ray      1149:                                }
1.1       deraadt  1150:                                if (ch == '\n')
                   1151:                                        i++;
                   1152:                        }
                   1153:                        if (fseek(fout, 0L, SEEK_CUR) < 0) {
                   1154: done:
1.69      ray      1155:                                if (errno)
                   1156:                                        warn("local: %s", local);
                   1157:                                else
                   1158:                                        warnx("local: %s", local);
1.13      millert  1159:                                progress = oprogress;
1.16      millert  1160:                                preserve = opreserve;
1.1       deraadt  1161:                                if (closefunc != NULL)
                   1162:                                        (*closefunc)(fout);
                   1163:                                return;
                   1164:                        }
                   1165:                }
1.23      millert  1166:                while ((c = fgetc(din)) != EOF) {
1.67      espie    1167:                        may_send_noop_char();
1.1       deraadt  1168:                        if (c == '\n')
                   1169:                                bare_lfs++;
                   1170:                        while (c == '\r') {
1.10      millert  1171:                                while (hash && (!progress || filesize < 0) &&
                   1172:                                    (bytes >= hashbytes)) {
1.18      deraadt  1173:                                        (void)putc('#', ttyout);
                   1174:                                        (void)fflush(ttyout);
1.7       kstailey 1175:                                        hashbytes += mark;
1.1       deraadt  1176:                                }
                   1177:                                bytes++;
1.23      millert  1178:                                if ((c = fgetc(din)) != '\n' || tcrflag) {
1.1       deraadt  1179:                                        if (ferror(fout))
                   1180:                                                goto break2;
1.11      millert  1181:                                        (void)putc('\r', fout);
1.1       deraadt  1182:                                        if (c == '\0') {
                   1183:                                                bytes++;
                   1184:                                                goto contin2;
                   1185:                                        }
                   1186:                                        if (c == EOF)
                   1187:                                                goto contin2;
                   1188:                                }
                   1189:                        }
1.11      millert  1190:                        (void)putc(c, fout);
1.1       deraadt  1191:                        bytes++;
                   1192:        contin2:        ;
                   1193:                }
                   1194: break2:
1.69      ray      1195:                if (ferror(din) || ferror(fout))
                   1196:                        serrno = errno;
1.1       deraadt  1197:                if (bare_lfs) {
1.22      millert  1198:                        fprintf(ttyout,
1.13      millert  1199: "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
1.22      millert  1200:                        fputs("File may not have transferred correctly.\n",
                   1201:                            ttyout);
1.1       deraadt  1202:                }
1.10      millert  1203:                if (hash && (!progress || filesize < 0)) {
1.1       deraadt  1204:                        if (bytes < hashbytes)
1.18      deraadt  1205:                                (void)putc('#', ttyout);
                   1206:                        (void)putc('\n', ttyout);
                   1207:                        (void)fflush(ttyout);
1.1       deraadt  1208:                }
                   1209:                if (ferror(din)) {
1.69      ray      1210:                        if (serrno != EPIPE)
1.86      guenther 1211:                                warnc(serrno, "netin");
1.1       deraadt  1212:                        bytes = -1;
                   1213:                }
                   1214:                if (ferror(fout))
1.86      guenther 1215:                        warnc(serrno, "local: %s", local);
1.1       deraadt  1216:                break;
                   1217:        }
1.75      martynas 1218:        progressmeter(1, NULL);
1.13      millert  1219:        progress = oprogress;
1.16      millert  1220:        preserve = opreserve;
1.1       deraadt  1221:        if (closefunc != NULL)
                   1222:                (*closefunc)(fout);
1.11      millert  1223:        (void)signal(SIGINT, oldintr);
                   1224:        (void)signal(SIGINFO, oldinti);
1.1       deraadt  1225:        if (oldintp)
1.11      millert  1226:                (void)signal(SIGPIPE, oldintp);
                   1227:        (void)fclose(din);
                   1228:        (void)getreply(0);
1.67      espie    1229:        may_receive_noop_ack();
1.10      millert  1230:        if (bytes >= 0 && is_retr) {
                   1231:                if (bytes > 0)
                   1232:                        ptransfer(0);
                   1233:                if (preserve && (closefunc == fclose)) {
                   1234:                        mtime = remotemodtime(remote, 0);
                   1235:                        if (mtime != -1) {
1.12      millert  1236:                                struct utimbuf ut;
                   1237:
                   1238:                                ut.actime = time(NULL);
                   1239:                                ut.modtime = mtime;
                   1240:                                if (utime(local, &ut) == -1)
1.22      millert  1241:                                        fprintf(ttyout,
1.13      millert  1242:                                "Can't change modification time on %s to %s",
1.11      millert  1243:                                            local, asctime(localtime(&mtime)));
1.10      millert  1244:                        }
                   1245:                }
                   1246:        }
1.1       deraadt  1247:        return;
1.13      millert  1248:
1.1       deraadt  1249: abort:
1.79      martynas 1250:        /* abort using RFC959 recommended IP,SYNC sequence */
1.13      millert  1251:        progress = oprogress;
1.16      millert  1252:        preserve = opreserve;
1.1       deraadt  1253:        if (oldintp)
1.11      millert  1254:                (void)signal(SIGPIPE, oldintp);
                   1255:        (void)signal(SIGINT, SIG_IGN);
1.1       deraadt  1256:        if (!cpend) {
                   1257:                code = -1;
1.11      millert  1258:                (void)signal(SIGINT, oldintr);
                   1259:                (void)signal(SIGINFO, oldinti);
1.1       deraadt  1260:                return;
                   1261:        }
                   1262:
                   1263:        abort_remote(din);
                   1264:        code = -1;
                   1265:        if (data >= 0) {
1.11      millert  1266:                (void)close(data);
1.1       deraadt  1267:                data = -1;
                   1268:        }
                   1269:        if (closefunc != NULL && fout != NULL)
                   1270:                (*closefunc)(fout);
                   1271:        if (din)
1.11      millert  1272:                (void)fclose(din);
1.1       deraadt  1273:        if (bytes > 0)
1.10      millert  1274:                ptransfer(0);
1.11      millert  1275:        (void)signal(SIGINT, oldintr);
                   1276:        (void)signal(SIGINFO, oldinti);
1.1       deraadt  1277: }
                   1278:
                   1279: /*
                   1280:  * Need to start a listen on the data channel before we send the command,
                   1281:  * otherwise the server's connect may fail.
                   1282:  */
                   1283: int
1.56      deraadt  1284: initconn(void)
1.1       deraadt  1285: {
                   1286:        char *p, *a;
1.57      deraadt  1287:        int result = ERROR, tmpno = 0;
1.1       deraadt  1288:        int on = 1;
1.34      itojun   1289:        int error;
                   1290:        u_int addr[16], port[2];
                   1291:        u_int af, hal, pal;
                   1292:        char *pasvcmd = NULL;
1.57      deraadt  1293:        socklen_t namelen;
1.82      haesbaer 1294:        struct addrinfo *ares;
1.34      itojun   1295:
                   1296:        if (myctladdr.su_family == AF_INET6
                   1297:         && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
                   1298:          || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
                   1299:                warnx("use of scoped address can be troublesome");
                   1300:        }
1.82      haesbaer 1301: #ifndef SMALL
                   1302:        if (srcaddr) {
                   1303:                struct addrinfo ahints;
                   1304:
                   1305:                memset(&ahints, 0, sizeof(ahints));
                   1306:                ahints.ai_family = family;
                   1307:                ahints.ai_socktype = SOCK_STREAM;
                   1308:                ahints.ai_flags |= AI_NUMERICHOST;
                   1309:                ahints.ai_protocol = 0;
                   1310:
                   1311:                error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
                   1312:                if (error) {
1.86      guenther 1313:                        warnx("%s: %s", srcaddr, gai_strerror(error));
1.82      haesbaer 1314:                        code = -1;
                   1315:                        return (0);
                   1316:                }
                   1317:        }
                   1318: #endif /* !SMALL */
1.24      millert  1319: reinit:
1.1       deraadt  1320:        if (passivemode) {
1.34      itojun   1321:                data_addr = myctladdr;
                   1322:                data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1       deraadt  1323:                if (data < 0) {
1.10      millert  1324:                        warn("socket");
                   1325:                        return (1);
1.1       deraadt  1326:                }
1.73      martynas 1327: #ifndef SMALL
1.82      haesbaer 1328:                if (srcaddr) {
                   1329:                        if (bind(data, ares->ai_addr, ares->ai_addrlen) < 0) {
                   1330:                                warn("bind");
                   1331:                                close(data);
                   1332:                                return (1);
                   1333:                        }
                   1334:                }
1.1       deraadt  1335:                if ((options & SO_DEBUG) &&
                   1336:                    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11      millert  1337:                               sizeof(on)) < 0)
1.10      millert  1338:                        warn("setsockopt (ignored)");
1.73      martynas 1339: #endif /* !SMALL */
1.34      itojun   1340:                switch (data_addr.su_family) {
                   1341:                case AF_INET:
1.36      itojun   1342:                        if (epsv4 && !epsv4bad) {
1.66      beck     1343:                                int ov;
                   1344:                                /* shut this command up in case it fails */
                   1345:                                ov = verbose;
                   1346:                                verbose = -1;
1.36      itojun   1347:                                result = command(pasvcmd = "EPSV");
1.66      beck     1348:                                /*
                   1349:                                 * now back to whatever verbosity we had before
                   1350:                                 * and we can try PASV
                   1351:                                 */
                   1352:                                verbose = ov;
1.36      itojun   1353:                                if (code / 10 == 22 && code != 229) {
                   1354:                                        fputs(
1.34      itojun   1355: "wrong server: return code must be 229\n",
1.36      itojun   1356:                                                ttyout);
                   1357:                                        result = COMPLETE + 1;
                   1358:                                }
                   1359:                                if (result != COMPLETE) {
                   1360:                                        epsv4bad = 1;
1.73      martynas 1361: #ifndef SMALL
1.36      itojun   1362:                                        if (debug) {
                   1363:                                                fputs(
                   1364: "disabling epsv4 for this connection\n",
                   1365:                                                    ttyout);
                   1366:                                        }
1.73      martynas 1367: #endif /* !SMALL */
1.36      itojun   1368:                                }
1.34      itojun   1369:                        }
                   1370:                        if (result != COMPLETE)
                   1371:                                result = command(pasvcmd = "PASV");
                   1372:                        break;
                   1373:                case AF_INET6:
                   1374:                        result = command(pasvcmd = "EPSV");
                   1375:                        if (code / 10 == 22 && code != 229) {
                   1376:                                fputs(
                   1377: "wrong server: return code must be 229\n",
                   1378:                                        ttyout);
                   1379:                                result = COMPLETE + 1;
                   1380:                        }
                   1381:                        if (result != COMPLETE)
                   1382:                                result = command(pasvcmd = "LPSV");
                   1383:                        break;
                   1384:                default:
                   1385:                        result = COMPLETE + 1;
                   1386:                        break;
                   1387:                }
                   1388:                if (result != COMPLETE) {
1.24      millert  1389:                        if (activefallback) {
                   1390:                                (void)close(data);
                   1391:                                data = -1;
                   1392:                                passivemode = 0;
                   1393:                                activefallback = 0;
                   1394:                                goto reinit;
                   1395:                        }
1.18      deraadt  1396:                        fputs("Passive mode refused.\n", ttyout);
1.1       deraadt  1397:                        goto bad;
                   1398:                }
                   1399:
1.34      itojun   1400: #define pack2(var, off) \
                   1401:        (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
                   1402: #define pack4(var, off) \
                   1403:        (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
                   1404:         ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
                   1405:
1.1       deraadt  1406:                /*
1.34      itojun   1407:                 * What we've got at this point is a string of comma separated
                   1408:                 * one-byte unsigned integer values, separated by commas.
1.1       deraadt  1409:                 */
1.38      millert  1410:                if (!pasvcmd)
                   1411:                        goto bad;
1.34      itojun   1412:                if (strcmp(pasvcmd, "PASV") == 0) {
                   1413:                        if (data_addr.su_family != AF_INET) {
                   1414:                                fputs(
                   1415: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
                   1416:                                goto bad;
                   1417:                        }
                   1418:                        if (code / 10 == 22 && code != 227) {
                   1419:                                fputs("wrong server: return code must be 227\n",
                   1420:                                        ttyout);
                   1421:                                goto bad;
                   1422:                        }
                   1423:                        error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
                   1424:                                        &addr[0], &addr[1], &addr[2], &addr[3],
                   1425:                                        &port[0], &port[1]);
                   1426:                        if (error != 6) {
                   1427:                                fputs(
                   1428: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
                   1429:                                goto bad;
                   1430:                        }
                   1431:                        memset(&data_addr, 0, sizeof(data_addr));
                   1432:                        data_addr.su_family = AF_INET;
                   1433:                        data_addr.su_len = sizeof(struct sockaddr_in);
                   1434:                        data_addr.su_sin.sin_addr.s_addr =
                   1435:                                htonl(pack4(addr, 0));
                   1436:                        data_addr.su_port = htons(pack2(port, 0));
                   1437:                } else if (strcmp(pasvcmd, "LPSV") == 0) {
                   1438:                        if (code / 10 == 22 && code != 228) {
                   1439:                                fputs("wrong server: return code must be 228\n",
                   1440:                                        ttyout);
                   1441:                                goto bad;
                   1442:                        }
                   1443:                        switch (data_addr.su_family) {
                   1444:                        case AF_INET:
                   1445:                                error = sscanf(pasv,
                   1446: "%u,%u,%u,%u,%u,%u,%u,%u,%u",
                   1447:                                        &af, &hal,
                   1448:                                        &addr[0], &addr[1], &addr[2], &addr[3],
                   1449:                                        &pal, &port[0], &port[1]);
                   1450:                                if (error != 9) {
                   1451:                                        fputs(
                   1452: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
                   1453:                                        goto bad;
                   1454:                                }
                   1455:                                if (af != 4 || hal != 4 || pal != 2) {
                   1456:                                        fputs(
                   1457: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
                   1458:                                        error = 1;
                   1459:                                        goto bad;
                   1460:                                }
1.1       deraadt  1461:
1.34      itojun   1462:                                memset(&data_addr, 0, sizeof(data_addr));
                   1463:                                data_addr.su_family = AF_INET;
                   1464:                                data_addr.su_len = sizeof(struct sockaddr_in);
                   1465:                                data_addr.su_sin.sin_addr.s_addr =
                   1466:                                        htonl(pack4(addr, 0));
                   1467:                                data_addr.su_port = htons(pack2(port, 0));
                   1468:                                break;
                   1469:                        case AF_INET6:
                   1470:                                error = sscanf(pasv,
                   1471: "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
                   1472:                                        &af, &hal,
                   1473:                                        &addr[0], &addr[1], &addr[2], &addr[3],
                   1474:                                        &addr[4], &addr[5], &addr[6], &addr[7],
                   1475:                                        &addr[8], &addr[9], &addr[10],
                   1476:                                        &addr[11], &addr[12], &addr[13],
                   1477:                                        &addr[14], &addr[15],
                   1478:                                        &pal, &port[0], &port[1]);
                   1479:                                if (error != 21) {
                   1480:                                        fputs(
1.18      deraadt  1481: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1.34      itojun   1482:                                        goto bad;
                   1483:                                }
                   1484:                                if (af != 6 || hal != 16 || pal != 2) {
                   1485:                                        fputs(
                   1486: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
                   1487:                                        goto bad;
                   1488:                                }
                   1489:
                   1490:                                memset(&data_addr, 0, sizeof(data_addr));
                   1491:                                data_addr.su_family = AF_INET6;
                   1492:                                data_addr.su_len = sizeof(struct sockaddr_in6);
                   1493:                            {
                   1494:                                u_int32_t *p32;
                   1495:                                p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr;
                   1496:                                p32[0] = htonl(pack4(addr, 0));
                   1497:                                p32[1] = htonl(pack4(addr, 4));
                   1498:                                p32[2] = htonl(pack4(addr, 8));
                   1499:                                p32[3] = htonl(pack4(addr, 12));
                   1500:                            }
                   1501:                                data_addr.su_port = htons(pack2(port, 0));
                   1502:                                break;
                   1503:                        default:
1.85      tedu     1504:                                fputs("Bad family!\n", ttyout);
                   1505:                                goto bad;
1.34      itojun   1506:                        }
                   1507:                } else if (strcmp(pasvcmd, "EPSV") == 0) {
                   1508:                        char delim[4];
                   1509:
                   1510:                        port[0] = 0;
                   1511:                        if (code / 10 == 22 && code != 229) {
                   1512:                                fputs("wrong server: return code must be 229\n",
                   1513:                                        ttyout);
                   1514:                                goto bad;
                   1515:                        }
                   1516:                        if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
                   1517:                                        &delim[1], &delim[2], &port[1],
                   1518:                                        &delim[3]) != 5) {
                   1519:                                fputs("parse error!\n", ttyout);
                   1520:                                goto bad;
                   1521:                        }
                   1522:                        if (delim[0] != delim[1] || delim[0] != delim[2]
                   1523:                         || delim[0] != delim[3]) {
                   1524:                                fputs("parse error!\n", ttyout);
                   1525:                                goto bad;
                   1526:                        }
                   1527:                        data_addr = hisctladdr;
                   1528:                        data_addr.su_port = htons(port[1]);
                   1529:                } else
1.1       deraadt  1530:                        goto bad;
                   1531:
1.27      deraadt  1532:                while (connect(data, (struct sockaddr *)&data_addr,
1.34      itojun   1533:                            data_addr.su_len) < 0) {
1.27      deraadt  1534:                        if (errno == EINTR)
                   1535:                                continue;
1.33      millert  1536:                        if (activefallback) {
                   1537:                                (void)close(data);
                   1538:                                data = -1;
                   1539:                                passivemode = 0;
                   1540:                                activefallback = 0;
                   1541:                                goto reinit;
                   1542:                        }
1.10      millert  1543:                        warn("connect");
1.1       deraadt  1544:                        goto bad;
                   1545:                }
1.34      itojun   1546: #if defined(IPPROTO_IP) && defined(IP_TOS)
                   1547:                if (data_addr.su_family == AF_INET) {
                   1548:                        on = IPTOS_THROUGHPUT;
                   1549:                        if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
                   1550:                                       sizeof(int)) < 0)
                   1551:                                warn("setsockopt TOS (ignored)");
                   1552:                }
1.1       deraadt  1553: #endif
1.10      millert  1554:                return (0);
1.1       deraadt  1555:        }
                   1556:
                   1557: noport:
                   1558:        data_addr = myctladdr;
                   1559:        if (sendport)
1.34      itojun   1560:                data_addr.su_port = 0;  /* let system pick one */
1.1       deraadt  1561:        if (data != -1)
1.11      millert  1562:                (void)close(data);
1.34      itojun   1563:        data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1       deraadt  1564:        if (data < 0) {
                   1565:                warn("socket");
                   1566:                if (tmpno)
                   1567:                        sendport = 1;
                   1568:                return (1);
                   1569:        }
                   1570:        if (!sendport)
1.10      millert  1571:                if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1.11      millert  1572:                                sizeof(on)) < 0) {
1.1       deraadt  1573:                        warn("setsockopt (reuse address)");
                   1574:                        goto bad;
                   1575:                }
1.49      jakob    1576:        switch (data_addr.su_family) {
                   1577:        case AF_INET:
                   1578:                on = IP_PORTRANGE_HIGH;
                   1579:                if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE,
                   1580:                    (char *)&on, sizeof(on)) < 0)
                   1581:                        warn("setsockopt IP_PORTRANGE (ignored)");
                   1582:                break;
                   1583:        case AF_INET6:
                   1584:                on = IPV6_PORTRANGE_HIGH;
                   1585:                if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
                   1586:                    (char *)&on, sizeof(on)) < 0)
                   1587:                        warn("setsockopt IPV6_PORTRANGE (ignored)");
                   1588:                break;
                   1589:        }
1.34      itojun   1590:        if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) {
1.1       deraadt  1591:                warn("bind");
                   1592:                goto bad;
                   1593:        }
1.73      martynas 1594: #ifndef SMALL
1.1       deraadt  1595:        if (options & SO_DEBUG &&
1.10      millert  1596:            setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11      millert  1597:                        sizeof(on)) < 0)
1.1       deraadt  1598:                warn("setsockopt (ignored)");
1.73      martynas 1599: #endif /* !SMALL */
1.57      deraadt  1600:        namelen = sizeof(data_addr);
                   1601:        if (getsockname(data, (struct sockaddr *)&data_addr, &namelen) < 0) {
1.1       deraadt  1602:                warn("getsockname");
                   1603:                goto bad;
                   1604:        }
                   1605:        if (listen(data, 1) < 0)
                   1606:                warn("listen");
1.34      itojun   1607:
                   1608: #define        UC(b)   (((int)b)&0xff)
                   1609:
1.1       deraadt  1610:        if (sendport) {
1.47      itojun   1611:                char hname[NI_MAXHOST], pbuf[NI_MAXSERV];
1.64      ray      1612:                int af_tmp;
1.47      itojun   1613:                union sockunion tmp;
1.34      itojun   1614:
1.47      itojun   1615:                tmp = data_addr;
                   1616:                switch (tmp.su_family) {
1.34      itojun   1617:                case AF_INET:
1.36      itojun   1618:                        if (!epsv4 || epsv4bad) {
                   1619:                                result = COMPLETE +1;
                   1620:                                break;
                   1621:                        }
                   1622:                        /*FALLTHROUGH*/
1.34      itojun   1623:                case AF_INET6:
1.47      itojun   1624:                        if (tmp.su_family == AF_INET6)
                   1625:                                tmp.su_sin6.sin6_scope_id = 0;
1.64      ray      1626:                        af_tmp = (tmp.su_family == AF_INET) ? 1 : 2;
1.47      itojun   1627:                        if (getnameinfo((struct sockaddr *)&tmp,
                   1628:                            tmp.su_len, hname, sizeof(hname),
                   1629:                            pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
1.34      itojun   1630:                                result = ERROR;
                   1631:                        } else {
1.47      itojun   1632:                                result = command("EPRT |%d|%s|%s|",
1.64      ray      1633:                                    af_tmp, hname, pbuf);
1.36      itojun   1634:                                if (result != COMPLETE) {
                   1635:                                        epsv4bad = 1;
1.73      martynas 1636: #ifndef SMALL
1.36      itojun   1637:                                        if (debug) {
                   1638:                                                fputs(
                   1639: "disabling epsv4 for this connection\n",
                   1640:                                                    ttyout);
                   1641:                                        }
1.73      martynas 1642: #endif /* !SMALL */
1.36      itojun   1643:                                }
1.34      itojun   1644:                        }
                   1645:                        break;
                   1646:                default:
                   1647:                        result = COMPLETE + 1;
                   1648:                        break;
                   1649:                }
                   1650:                if (result == COMPLETE)
                   1651:                        goto skip_port;
                   1652:
                   1653:                switch (data_addr.su_family) {
                   1654:                case AF_INET:
                   1655:                        a = (char *)&data_addr.su_sin.sin_addr;
                   1656:                        p = (char *)&data_addr.su_port;
                   1657:                        result = command("PORT %d,%d,%d,%d,%d,%d",
                   1658:                                 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
                   1659:                                 UC(p[0]), UC(p[1]));
                   1660:                        break;
                   1661:                case AF_INET6:
                   1662:                        a = (char *)&data_addr.su_sin6.sin6_addr;
                   1663:                        p = (char *)&data_addr.su_port;
                   1664:                        result = command(
                   1665: "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
                   1666:                                 6, 16,
                   1667:                                 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
                   1668:                                 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
                   1669:                                 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
                   1670:                                 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
                   1671:                                 2, UC(p[0]), UC(p[1]));
                   1672:                        break;
                   1673:                default:
                   1674:                        result = COMPLETE + 1; /* xxx */
                   1675:                }
                   1676:        skip_port:
                   1677:
1.1       deraadt  1678:                if (result == ERROR && sendport == -1) {
                   1679:                        sendport = 0;
                   1680:                        tmpno = 1;
                   1681:                        goto noport;
                   1682:                }
                   1683:                return (result != COMPLETE);
                   1684:        }
                   1685:        if (tmpno)
                   1686:                sendport = 1;
1.34      itojun   1687: #if defined(IPPROTO_IP) && defined(IP_TOS)
                   1688:        if (data_addr.su_family == AF_INET) {
                   1689:                on = IPTOS_THROUGHPUT;
                   1690:                if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
                   1691:                               sizeof(int)) < 0)
                   1692:                        warn("setsockopt TOS (ignored)");
                   1693:        }
1.1       deraadt  1694: #endif
                   1695:        return (0);
                   1696: bad:
1.11      millert  1697:        (void)close(data), data = -1;
1.1       deraadt  1698:        if (tmpno)
                   1699:                sendport = 1;
                   1700:        return (1);
                   1701: }
                   1702:
                   1703: FILE *
1.56      deraadt  1704: dataconn(const char *lmode)
1.1       deraadt  1705: {
1.34      itojun   1706:        union sockunion from;
1.57      deraadt  1707:        socklen_t fromlen = myctladdr.su_len;
                   1708:        int s;
1.1       deraadt  1709:
                   1710:        if (passivemode)
                   1711:                return (fdopen(data, lmode));
                   1712:
                   1713:        s = accept(data, (struct sockaddr *) &from, &fromlen);
                   1714:        if (s < 0) {
                   1715:                warn("accept");
1.11      millert  1716:                (void)close(data), data = -1;
1.1       deraadt  1717:                return (NULL);
                   1718:        }
1.11      millert  1719:        (void)close(data);
1.1       deraadt  1720:        data = s;
1.34      itojun   1721: #if defined(IPPROTO_IP) && defined(IP_TOS)
                   1722:        if (from.su_family == AF_INET) {
                   1723:                int tos = IPTOS_THROUGHPUT;
                   1724:                if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
                   1725:                                sizeof(int)) < 0) {
                   1726:                        warn("setsockopt TOS (ignored)");
                   1727:                }
                   1728:        }
1.1       deraadt  1729: #endif
                   1730:        return (fdopen(data, lmode));
                   1731: }
                   1732:
1.57      deraadt  1733: /* ARGSUSED */
1.1       deraadt  1734: void
1.57      deraadt  1735: psummary(int signo)
1.1       deraadt  1736: {
1.26      deraadt  1737:        int save_errno = errno;
1.10      millert  1738:
                   1739:        if (bytes > 0)
                   1740:                ptransfer(1);
1.26      deraadt  1741:        errno = save_errno;
1.1       deraadt  1742: }
                   1743:
1.57      deraadt  1744: /* ARGSUSED */
1.1       deraadt  1745: void
1.57      deraadt  1746: psabort(int signo)
1.1       deraadt  1747: {
                   1748:
1.10      millert  1749:        alarmtimer(0);
1.1       deraadt  1750:        abrtflag++;
                   1751: }
                   1752:
                   1753: void
1.56      deraadt  1754: pswitch(int flag)
1.1       deraadt  1755: {
                   1756:        sig_t oldintr;
                   1757:        static struct comvars {
                   1758:                int connect;
                   1759:                char name[MAXHOSTNAMELEN];
1.34      itojun   1760:                union sockunion mctl;
                   1761:                union sockunion hctl;
1.1       deraadt  1762:                FILE *in;
                   1763:                FILE *out;
                   1764:                int tpe;
                   1765:                int curtpe;
                   1766:                int cpnd;
                   1767:                int sunqe;
                   1768:                int runqe;
                   1769:                int mcse;
                   1770:                int ntflg;
                   1771:                char nti[17];
                   1772:                char nto[17];
                   1773:                int mapflg;
                   1774:                char mi[MAXPATHLEN];
                   1775:                char mo[MAXPATHLEN];
                   1776:        } proxstruct, tmpstruct;
                   1777:        struct comvars *ip, *op;
                   1778:
                   1779:        abrtflag = 0;
                   1780:        oldintr = signal(SIGINT, psabort);
                   1781:        if (flag) {
                   1782:                if (proxy)
                   1783:                        return;
                   1784:                ip = &tmpstruct;
                   1785:                op = &proxstruct;
                   1786:                proxy++;
                   1787:        } else {
                   1788:                if (!proxy)
                   1789:                        return;
                   1790:                ip = &proxstruct;
                   1791:                op = &tmpstruct;
                   1792:                proxy = 0;
                   1793:        }
                   1794:        ip->connect = connected;
                   1795:        connected = op->connect;
                   1796:        if (hostname) {
1.41      lebel    1797:                (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1.1       deraadt  1798:        } else
1.11      millert  1799:                ip->name[0] = '\0';
1.1       deraadt  1800:        hostname = op->name;
                   1801:        ip->hctl = hisctladdr;
                   1802:        hisctladdr = op->hctl;
                   1803:        ip->mctl = myctladdr;
                   1804:        myctladdr = op->mctl;
                   1805:        ip->in = cin;
                   1806:        cin = op->in;
                   1807:        ip->out = cout;
                   1808:        cout = op->out;
                   1809:        ip->tpe = type;
                   1810:        type = op->tpe;
                   1811:        ip->curtpe = curtype;
                   1812:        curtype = op->curtpe;
                   1813:        ip->cpnd = cpend;
                   1814:        cpend = op->cpnd;
                   1815:        ip->sunqe = sunique;
                   1816:        sunique = op->sunqe;
                   1817:        ip->runqe = runique;
                   1818:        runique = op->runqe;
                   1819:        ip->mcse = mcase;
                   1820:        mcase = op->mcse;
                   1821:        ip->ntflg = ntflag;
                   1822:        ntflag = op->ntflg;
1.41      lebel    1823:        (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1.52      deraadt  1824:        (void)strlcpy(ntin, op->nti, sizeof ntin);
1.41      lebel    1825:        (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1.52      deraadt  1826:        (void)strlcpy(ntout, op->nto, sizeof ntout);
1.1       deraadt  1827:        ip->mapflg = mapflag;
                   1828:        mapflag = op->mapflg;
1.41      lebel    1829:        (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1.52      deraadt  1830:        (void)strlcpy(mapin, op->mi, sizeof mapin);
1.41      lebel    1831:        (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1.52      deraadt  1832:        (void)strlcpy(mapout, op->mo, sizeof mapout);
1.11      millert  1833:        (void)signal(SIGINT, oldintr);
1.1       deraadt  1834:        if (abrtflag) {
                   1835:                abrtflag = 0;
                   1836:                (*oldintr)(SIGINT);
                   1837:        }
                   1838: }
                   1839:
1.57      deraadt  1840: /* ARGSUSED */
1.1       deraadt  1841: void
1.57      deraadt  1842: abortpt(int signo)
1.1       deraadt  1843: {
                   1844:
1.10      millert  1845:        alarmtimer(0);
1.18      deraadt  1846:        putc('\n', ttyout);
                   1847:        (void)fflush(ttyout);
1.1       deraadt  1848:        ptabflg++;
                   1849:        mflag = 0;
                   1850:        abrtflag = 0;
                   1851:        longjmp(ptabort, 1);
                   1852: }
                   1853:
                   1854: void
1.56      deraadt  1855: proxtrans(const char *cmd, const char *local, const char *remote)
1.1       deraadt  1856: {
1.40      millert  1857:        volatile sig_t oldintr;
1.20      millert  1858:        int prox_type, nfnd;
                   1859:        volatile int secndflag;
1.40      millert  1860:        char * volatile cmd2;
1.54      millert  1861:        struct pollfd pfd[1];
1.20      millert  1862:
                   1863:        oldintr = NULL;
                   1864:        secndflag = 0;
1.1       deraadt  1865:        if (strcmp(cmd, "RETR"))
                   1866:                cmd2 = "RETR";
                   1867:        else
                   1868:                cmd2 = runique ? "STOU" : "STOR";
                   1869:        if ((prox_type = type) == 0) {
                   1870:                if (unix_server && unix_proxy)
                   1871:                        prox_type = TYPE_I;
                   1872:                else
                   1873:                        prox_type = TYPE_A;
                   1874:        }
                   1875:        if (curtype != prox_type)
                   1876:                changetype(prox_type, 1);
                   1877:        if (command("PASV") != COMPLETE) {
1.18      deraadt  1878:                fputs("proxy server does not support third party transfers.\n",
                   1879:                    ttyout);
1.1       deraadt  1880:                return;
                   1881:        }
                   1882:        pswitch(0);
                   1883:        if (!connected) {
1.18      deraadt  1884:                fputs("No primary connection.\n", ttyout);
1.1       deraadt  1885:                pswitch(1);
                   1886:                code = -1;
                   1887:                return;
                   1888:        }
                   1889:        if (curtype != prox_type)
                   1890:                changetype(prox_type, 1);
                   1891:        if (command("PORT %s", pasv) != COMPLETE) {
                   1892:                pswitch(1);
                   1893:                return;
                   1894:        }
                   1895:        if (setjmp(ptabort))
                   1896:                goto abort;
                   1897:        oldintr = signal(SIGINT, abortpt);
                   1898:        if (command("%s %s", cmd, remote) != PRELIM) {
1.11      millert  1899:                (void)signal(SIGINT, oldintr);
1.1       deraadt  1900:                pswitch(1);
                   1901:                return;
                   1902:        }
                   1903:        sleep(2);
                   1904:        pswitch(1);
                   1905:        secndflag++;
                   1906:        if (command("%s %s", cmd2, local) != PRELIM)
                   1907:                goto abort;
                   1908:        ptflag++;
1.11      millert  1909:        (void)getreply(0);
1.1       deraadt  1910:        pswitch(0);
1.11      millert  1911:        (void)getreply(0);
                   1912:        (void)signal(SIGINT, oldintr);
1.1       deraadt  1913:        pswitch(1);
                   1914:        ptflag = 0;
1.18      deraadt  1915:        fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1.1       deraadt  1916:        return;
                   1917: abort:
1.11      millert  1918:        (void)signal(SIGINT, SIG_IGN);
1.1       deraadt  1919:        ptflag = 0;
                   1920:        if (strcmp(cmd, "RETR") && !proxy)
                   1921:                pswitch(1);
                   1922:        else if (!strcmp(cmd, "RETR") && proxy)
                   1923:                pswitch(0);
                   1924:        if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
                   1925:                if (command("%s %s", cmd2, local) != PRELIM) {
                   1926:                        pswitch(0);
                   1927:                        if (cpend)
1.19      kstailey 1928:                                abort_remote(NULL);
1.1       deraadt  1929:                }
                   1930:                pswitch(1);
                   1931:                if (ptabflg)
                   1932:                        code = -1;
1.11      millert  1933:                (void)signal(SIGINT, oldintr);
1.1       deraadt  1934:                return;
                   1935:        }
                   1936:        if (cpend)
1.19      kstailey 1937:                abort_remote(NULL);
1.1       deraadt  1938:        pswitch(!proxy);
                   1939:        if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
                   1940:                if (command("%s %s", cmd2, local) != PRELIM) {
                   1941:                        pswitch(0);
                   1942:                        if (cpend)
1.19      kstailey 1943:                                abort_remote(NULL);
1.1       deraadt  1944:                        pswitch(1);
                   1945:                        if (ptabflg)
                   1946:                                code = -1;
1.11      millert  1947:                        (void)signal(SIGINT, oldintr);
1.1       deraadt  1948:                        return;
                   1949:                }
                   1950:        }
                   1951:        if (cpend)
1.19      kstailey 1952:                abort_remote(NULL);
1.1       deraadt  1953:        pswitch(!proxy);
                   1954:        if (cpend) {
1.54      millert  1955:                pfd[0].fd = fileno(cin);
                   1956:                pfd[0].events = POLLIN;
                   1957:                if ((nfnd = poll(pfd, 1, 10 * 1000)) <= 0) {
                   1958:                        if (nfnd < 0)
1.1       deraadt  1959:                                warn("abort");
                   1960:                        if (ptabflg)
                   1961:                                code = -1;
                   1962:                        lostpeer();
                   1963:                }
1.11      millert  1964:                (void)getreply(0);
                   1965:                (void)getreply(0);
1.1       deraadt  1966:        }
                   1967:        if (proxy)
                   1968:                pswitch(0);
                   1969:        pswitch(1);
                   1970:        if (ptabflg)
                   1971:                code = -1;
1.11      millert  1972:        (void)signal(SIGINT, oldintr);
1.1       deraadt  1973: }
                   1974:
1.80      deraadt  1975: #ifndef SMALL
1.57      deraadt  1976: /* ARGSUSED */
1.1       deraadt  1977: void
1.56      deraadt  1978: reset(int argc, char *argv[])
1.1       deraadt  1979: {
1.54      millert  1980:        struct pollfd pfd[1];
1.1       deraadt  1981:        int nfnd = 1;
                   1982:
1.54      millert  1983:        pfd[0].fd = fileno(cin);
                   1984:        pfd[0].events = POLLIN;
1.1       deraadt  1985:        while (nfnd > 0) {
1.54      millert  1986:                if ((nfnd = poll(pfd, 1, 0)) < 0) {
1.1       deraadt  1987:                        warn("reset");
                   1988:                        code = -1;
                   1989:                        lostpeer();
1.54      millert  1990:                } else if (nfnd) {
1.11      millert  1991:                        (void)getreply(0);
1.1       deraadt  1992:                }
                   1993:        }
                   1994: }
1.80      deraadt  1995: #endif
1.1       deraadt  1996:
                   1997: char *
1.56      deraadt  1998: gunique(const char *local)
1.1       deraadt  1999: {
                   2000:        static char new[MAXPATHLEN];
                   2001:        char *cp = strrchr(local, '/');
                   2002:        int d, count=0;
                   2003:        char ext = '1';
                   2004:
                   2005:        if (cp)
                   2006:                *cp = '\0';
1.22      millert  2007:        d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1.1       deraadt  2008:        if (cp)
                   2009:                *cp = '/';
                   2010:        if (d < 0) {
                   2011:                warn("local: %s", local);
                   2012:                return ((char *) 0);
                   2013:        }
1.52      deraadt  2014:        (void)strlcpy(new, local, sizeof new);
1.1       deraadt  2015:        cp = new + strlen(new);
                   2016:        *cp++ = '.';
                   2017:        while (!d) {
                   2018:                if (++count == 100) {
1.18      deraadt  2019:                        fputs("runique: can't find unique file name.\n", ttyout);
1.1       deraadt  2020:                        return ((char *) 0);
                   2021:                }
                   2022:                *cp++ = ext;
                   2023:                *cp = '\0';
                   2024:                if (ext == '9')
                   2025:                        ext = '0';
                   2026:                else
                   2027:                        ext++;
1.22      millert  2028:                if ((d = access(new, F_OK)) < 0)
1.1       deraadt  2029:                        break;
                   2030:                if (ext != '0')
                   2031:                        cp--;
                   2032:                else if (*(cp - 2) == '.')
                   2033:                        *(cp - 1) = '1';
                   2034:                else {
                   2035:                        *(cp - 2) = *(cp - 2) + 1;
                   2036:                        cp--;
                   2037:                }
                   2038:        }
                   2039:        return (new);
                   2040: }
                   2041:
1.79      martynas 2042: jmp_buf forceabort;
                   2043:
                   2044: /* ARGSUSED */
1.83      deraadt  2045: static void
1.79      martynas 2046: abortforce(int signo)
                   2047: {
1.87    ! deraadt  2048:        int save_errno = errno;
1.79      martynas 2049:
1.87    ! deraadt  2050: #define MSG    "Forced abort.  The connection will be closed.\n"
        !          2051:        (void) write(fileno(ttyout), MSG, strlen(MSG));
        !          2052: #undef MSG
1.79      martynas 2053:
1.87    ! deraadt  2054:        errno = save_errno;
1.79      martynas 2055:        longjmp(forceabort, 1);
                   2056: }
                   2057:
1.1       deraadt  2058: void
1.56      deraadt  2059: abort_remote(FILE *din)
1.1       deraadt  2060: {
                   2061:        char buf[BUFSIZ];
1.81      lum      2062:        nfds_t nfds;
1.1       deraadt  2063:        int nfnd;
1.54      millert  2064:        struct pollfd pfd[2];
1.79      martynas 2065:        sig_t oldintr;
1.13      millert  2066:
1.79      martynas 2067:        if (cout == NULL || setjmp(forceabort)) {
1.87    ! deraadt  2068:                if (cout)
        !          2069:                        fclose(cout);
1.13      millert  2070:                warnx("Lost control connection for abort.");
                   2071:                if (ptabflg)
                   2072:                        code = -1;
                   2073:                lostpeer();
                   2074:                return;
                   2075:        }
1.1       deraadt  2076:
1.79      martynas 2077:        oldintr = signal(SIGINT, abortforce);
                   2078:
1.1       deraadt  2079:        /*
                   2080:         * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
                   2081:         * after urgent byte rather than before as is protocol now
                   2082:         */
1.46      deraadt  2083:        snprintf(buf, sizeof buf, "%c%c%c", IAC, IP, IAC);
1.1       deraadt  2084:        if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
                   2085:                warn("abort");
1.10      millert  2086:        fprintf(cout, "%cABOR\r\n", DM);
1.11      millert  2087:        (void)fflush(cout);
1.54      millert  2088:        pfd[0].fd = fileno(cin);
                   2089:        pfd[0].events = POLLIN;
1.81      lum      2090:        nfds = 1;
1.10      millert  2091:        if (din) {
1.54      millert  2092:                pfd[1].fd = fileno(din);
                   2093:                pfd[1].events = POLLIN;
1.81      lum      2094:                nfds++;
1.1       deraadt  2095:        }
1.81      lum      2096:        if ((nfnd = poll(pfd, nfds, 10 * 1000)) <= 0) {
1.54      millert  2097:                if (nfnd < 0)
1.1       deraadt  2098:                        warn("abort");
                   2099:                if (ptabflg)
                   2100:                        code = -1;
                   2101:                lostpeer();
                   2102:        }
1.54      millert  2103:        if (din && (pfd[1].revents & POLLIN)) {
1.1       deraadt  2104:                while (read(fileno(din), buf, BUFSIZ) > 0)
                   2105:                        /* LOOP */;
                   2106:        }
                   2107:        if (getreply(0) == ERROR && code == 552) {
                   2108:                /* 552 needed for nic style abort */
1.11      millert  2109:                (void)getreply(0);
1.1       deraadt  2110:        }
1.11      millert  2111:        (void)getreply(0);
1.79      martynas 2112:        (void)signal(SIGINT, oldintr);
1.1       deraadt  2113: }