Annotation of 43BSDReno/contrib/isode-beta/ftam-ftp/ftp.c, revision 1.1.1.1

1.1       root        1: /* ftp.c - FTP client */
                      2: 
                      3: #ifndef lint
                      4: static char *rcsid = "$Header: /f/osi/ftam-ftp/RCS/ftp.c,v 7.0 89/11/23 21:55:04 mrose Rel $"; /* from UCB 4.11 7/26/83 */
                      5: #endif
                      6: 
                      7: /* 
                      8:  * $Header: /f/osi/ftam-ftp/RCS/ftp.c,v 7.0 89/11/23 21:55:04 mrose Rel $
                      9:  *
                     10:  *
                     11:  * $Log:       ftp.c,v $
                     12:  * Revision 7.0  89/11/23  21:55:04  mrose
                     13:  * Release 6.0
                     14:  * 
                     15:  */
                     16: 
                     17: /*
                     18:  *                               NOTICE
                     19:  *
                     20:  *     The MITRE Corporation (hereafter MITRE) makes this software available 
                     21:  *     on an "as is" basis.  No guarantees, either explicit or implied, are 
                     22:  *     given as to performance or suitability.  
                     23:  *
                     24:  */
                     25: 
                     26: /*
                     27:  *     Shamelessly taken from UCB
                     28:  */
                     29: 
                     30: #include "config.h"
                     31: #include <sys/param.h>
                     32: #include <sys/ioctl.h>
                     33: #include "internet.h"
                     34: #include <sys/time.h>
                     35: 
                     36: #include <arpa/ftp.h>
                     37: 
                     38: #include <stdio.h>
                     39: #include <errno.h>
                     40: #include <varargs.h>
                     41: 
                     42: #include "ftp_var.h"
                     43: #include "general.h"
                     44: #include "logger.h"
                     45: void   advise ();
                     46: 
                     47: #ifndef NOTOK
                     48: #define NOTOK (-1)
                     49: #define OK     0
                     50: #define DONE   1
                     51: #endif /* NOTOK */
                     52: 
                     53: int    verbose = 0;
                     54: 
                     55: struct sockaddr_in hisctladdr;
                     56: struct sockaddr_in data_addr;
                     57: int    data = -1;
                     58: int    connected = 0;
                     59: struct sockaddr_in myctladdr;
                     60: 
                     61: FILE   *cin, *cout;
                     62: int    dataconn();
                     63: 
                     64: 
                     65: ftp_init()
                     66: { /* default ftp communication values */
                     67: 
                     68:        (void)strcpy(typename, "ascii"), type = TYPE_A;
                     69:         (void)strcpy(formname, "non-print"), form = FORM_N;
                     70:         (void)strcpy(modename, "stream"), mode = MODE_S;
                     71:         (void)strcpy(structname, "file"), stru = STRU_F;
                     72:         (void)strcpy(bytename, "8"), bytesize = 8;
                     73:        ftp_directory = 0;
                     74:        ftp_error = ftp_error_buffer;
                     75:        verbose = isatty (fileno (stderr));
                     76: }
                     77: 
                     78: hookup(host, port)
                     79:        char *host;
                     80:        int port;
                     81: {
                     82:        register struct hostent *hp;
                     83:        int s, len;
                     84: 
                     85:        bzero((char *)&hisctladdr, sizeof (hisctladdr));
                     86:        hp = gethostbyname(host);
                     87:        if (hp == NULL) {
                     88: #ifdef h_addr
                     89:                static char *addrs = NULL;
                     90: #endif
                     91:                static struct hostent def;
                     92:                static struct in_addr defaddr;
                     93:                static char namebuf[128];
                     94:                u_long inet_addr();
                     95: 
                     96:                defaddr.s_addr = inet_addr(host);
                     97:                if (defaddr.s_addr == -1) {
                     98:                        (void)sprintf(ftp_error, "%s: Unknown host.", host);
                     99:                        return (NOTOK);
                    100:                }
                    101:                (void)strcpy(namebuf, host);
                    102:                def.h_name = namebuf;
                    103:                hostname = namebuf;
                    104: #ifdef h_addr
                    105:                def.h_addr_list = &addrs;
                    106: #endif
                    107:                def.h_addr = (char *)&defaddr;
                    108:                def.h_length = sizeof (struct in_addr);
                    109:                def.h_addrtype = AF_INET;
                    110:                def.h_aliases = 0;
                    111:                hp = &def;
                    112:        }
                    113:        hostname = hp->h_name;
                    114:        hisctladdr.sin_family = hp->h_addrtype;
                    115:        s = socket(hp->h_addrtype, SOCK_STREAM, 0);
                    116:        if (s < 0) {
                    117:                (void)sprintf(ftp_error,"ftp: socket %s",
                    118:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    119:                return (NOTOK);
                    120:        }
                    121:        if (bind(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
                    122:                (void)sprintf(ftp_error,"ftp: bind %s",
                    123:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    124:                goto bad;
                    125:        }
                    126:        inaddr_copy (hp, &hisctladdr);
                    127:        hisctladdr.sin_port = htons ((u_short) port);
                    128:        if (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
                    129:                (void)sprintf(ftp_error,"ftp: connect %s",
                    130:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    131:                goto bad;
                    132:        }
                    133:        len = sizeof (myctladdr);
                    134:        if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
                    135:                (void)sprintf(ftp_error,"ftp: getsockname %s",
                    136:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    137:                goto bad;
                    138:        }
                    139:        cin = fdopen(s, "r");
                    140:        cout = fdopen(s, "w");
                    141:        if (cin == NULL || cout == NULL) {
                    142:                (void)sprintf(ftp_error, "ftp: fdopen failed.");
                    143:                if (cin)
                    144:                        (void)fclose(cin);
                    145:                if (cout)
                    146:                        (void)fclose(cout);
                    147:                goto bad;
                    148:        }
                    149:        (void) getreply(0);             /* read startup message from server */
                    150:        connected = 1;
                    151:        return (OK);
                    152: bad:
                    153:        (void)close(s);
                    154:        return (NOTOK);
                    155: }
                    156: 
                    157: login(user,pass,acct)
                    158:        char *user, *pass, *acct;
                    159: {
                    160:        int n;
                    161: 
                    162:        if (!user){
                    163:                (void)sprintf(ftp_error, "Username required");
                    164:                return(NOTOK);
                    165:        }
                    166:        n = command("USER %s", user);
                    167:        if (n == CONTINUE){
                    168:                if (!pass){
                    169:                        (void)sprintf(ftp_error, "Password required");
                    170:                        return(NOTOK);
                    171:                }
                    172:                n = command("PASS %s", pass);
                    173:        }
                    174:        if (n == CONTINUE) {
                    175:                if (!acct){
                    176:                        (void)sprintf(ftp_error, "Account required");
                    177:                        return(NOTOK);
                    178:                }
                    179:                n = command("ACCT %s", acct);
                    180:        }
                    181:        if (n != COMPLETE) {
                    182:                (void)sprintf(ftp_error, "Login failed.");
                    183:                return (NOTOK);
                    184:        }
                    185:        return (OK);
                    186: }
                    187: 
                    188: #ifndef        lint
                    189: command(va_alist)
                    190: va_dcl
                    191: {
                    192:     int            val;
                    193:     va_list ap;
                    194: 
                    195:     va_start (ap);
                    196: 
                    197:     val = _command (ap);
                    198: 
                    199:     va_end (ap);
                    200: 
                    201:     return val;
                    202: }
                    203: 
                    204: _command(ap)
                    205: va_list ap;
                    206: {
                    207:     char buffer[BUFSIZ];
                    208: 
                    209:        if (cout == NULL) {
                    210:                (void)sprintf(ftp_error,"No control connection for command %s",
                    211:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    212:                return (NOTOK);
                    213:        }
                    214: 
                    215:        _asprintf (buffer, NULLCP, ap);
                    216:        fprintf (cout, "%s\r\n", buffer);
                    217:        (void) fflush(cout);
                    218:        if (verbose)
                    219:            advise (LLOG_DEBUG, NULLCP, "<--- %s", buffer);
                    220:        return (getreply(!strcmp(buffer, "QUIT")));
                    221: }
                    222: #else
                    223: /* VARARGS1 */
                    224: 
                    225: command (fmt)
                    226: char   *fmt;
                    227: {
                    228:     return command (fmt);
                    229: }
                    230: #endif
                    231: 
                    232: #include <ctype.h>
                    233: 
                    234: getreply(expecteof)
                    235:        int expecteof;
                    236: {
                    237:        register int c, n;
                    238:        register int code, dig;
                    239:        int originalcode = 0, continuation = 0;
                    240:        char *mesg;
                    241: 
                    242:        mesg = ftp_error_buffer;
                    243:        for (;;) {
                    244:                dig = n = code = 0;
                    245:                while ((c = getc(cin)) != '\n') {
                    246:                        dig++;
                    247:                        if (c == EOF) {
                    248:                                if (expecteof)
                    249:                                        return (0);
                    250:                                lostpeer();
                    251:                                advise (LLOG_EXCEPTIONS,NULLCP,"getreply: %s",
                    252:                                        ftp_error_buffer);
                    253:                                return(1);
                    254:                                /* exit(1); */
                    255:                        }
                    256:                        if (c != '\r') *mesg++ = c;
                    257:                        else *mesg = '\0';
                    258:                        if (dig < 4 && isdigit(c))
                    259:                                code = code * 10 + (c - '0');
                    260:                        if (dig == 4 && c == '-')
                    261:                                continuation++;
                    262:                        if (n == 0)
                    263:                                n = c;
                    264:                }
                    265:                if (continuation && code != originalcode) {
                    266:                        if (originalcode == 0)
                    267:                                originalcode = code;
                    268:                        continue;
                    269:                }
                    270:                if (verbose)
                    271:                    advise (LLOG_DEBUG,NULLCP,"---> %s",
                    272:                            ftp_error_buffer);
                    273:                return (n - '0');
                    274:        }
                    275: }
                    276: 
                    277: /*
                    278:  *  sendrequest and recvrequest routines have been modified to send the
                    279:  *  appropriate remote command then open and return a file descriptor (socket).
                    280:  *  The FTAM code treats this as though it were a local file (which
                    281:  *  is about what FTP does)
                    282:  */
                    283: int
                    284: sendrequest(cmd, /* local, */ remote)
                    285:        char *cmd, /* *local, */ *remote;
                    286: {
                    287:        int dout;
                    288:        int expectingreply = 0;
                    289: 
                    290:        if (initconn())
                    291:                goto bad;
                    292:        if (remote) {
                    293:                if (command("%s %s", cmd, remote) != PRELIM)
                    294:                        goto bad;
                    295:        } else
                    296:                if (command("%s", cmd) != PRELIM)
                    297:                        goto bad;
                    298:        expectingreply++; /* got preliminary reply, expecting final reply */
                    299:        dout = dataconn("w");
                    300:        if (dout == NOTOK)
                    301:                goto bad;
                    302:        return(dout);
                    303: 
                    304: bad:
                    305:        if (data >= 0)
                    306:                (void) close(data), data = -1;
                    307:         if (expectingreply) {
                    308:                 (void) getreply(0);
                    309:                 expectingreply = 0;
                    310:         }
                    311:         return(NOTOK);
                    312: }
                    313: 
                    314: int
                    315: recvrequest(cmd, /* local,*/ remote)
                    316:        char *cmd, /* *local,*/ *remote;
                    317: {
                    318:        int din;
                    319:        int expectingreply = 0;
                    320: 
                    321:        if (initconn())
                    322:                goto bad;
                    323:        if (remote) {
                    324:                if (command("%s %s", cmd, remote) != PRELIM)
                    325:                        goto bad;
                    326:        } else
                    327:                if (command("%s", cmd) != PRELIM)
                    328:                        goto bad;
                    329:        expectingreply++;   /* got preliminary reply, expecting final reply */
                    330:        din = dataconn("r");
                    331:        if (din == NOTOK)
                    332:                goto bad;
                    333:        return(din);
                    334: bad:
                    335:        if (data >= 0)
                    336:                (void) close(data), data = -1;
                    337:        if (expectingreply) {
                    338:                (void) getreply(0);
                    339:                expectingreply = 0;
                    340:        }
                    341:        return(NOTOK);
                    342: }
                    343: 
                    344: /*
                    345:  * Need to start a listen on the data channel
                    346:  * before we send the command, otherwise the
                    347:  * server's connect may fail.
                    348:  */
                    349: int sendport = -1;
                    350: 
                    351: initconn()
                    352: {
                    353:        register char *p, *a;
                    354:        int result, len;
                    355: #ifdef BSD43
                    356:        int     on = 1;
                    357: #endif
                    358: 
                    359: noport:
                    360:        data_addr = myctladdr;
                    361:        if (sendport)
                    362:                data_addr.sin_port = 0; /* let system pick one */ 
                    363:        if (data != -1)
                    364:                (void) close (data);
                    365:        data = socket(AF_INET, SOCK_STREAM, 0);
                    366:        if (data < 0) {
                    367:                (void)sprintf(ftp_error,"ftp: socket %s",
                    368:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    369:                return (NOTOK);
                    370:        }
                    371:        if (!sendport)
                    372: #ifndef        BSD43
                    373:                if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *) 0, 0) < 0) {
                    374: #else
                    375:                if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on) < 0) {
                    376: #endif
                    377:                (void)sprintf(ftp_error,"ftp: setsockopt (reuse address) %s",
                    378:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    379:                        goto bad;
                    380:                }
                    381:        if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
                    382:                (void)sprintf(ftp_error,"ftp: bind %s",
                    383:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    384:                goto bad;
                    385:        }
                    386:        if (options & SO_DEBUG &&
                    387: #ifndef        BSD43
                    388:            setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *) 0, 0) < 0)
                    389: #else
                    390:            setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *) &on, on) < 0)
                    391: #endif
                    392:                (void)sprintf(ftp_error,"ftp: setsockopt (ignoreg) %s",
                    393:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    394:        len = sizeof (data_addr);
                    395:        if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
                    396:                (void)sprintf(ftp_error,"ftp: getsockname  %s",
                    397:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    398:                goto bad;
                    399:        }
                    400:        if (listen(data, 1) < 0) {
                    401:                (void)sprintf(ftp_error,"ftp: listen  %s",
                    402:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    403:                goto bad;
                    404:        }
                    405:        if (sendport) {
                    406:                a = (char *)&data_addr.sin_addr;
                    407:                p = (char *)&data_addr.sin_port;
                    408: #define        UC(b)   (((int)b)&0xff)
                    409:                result =
                    410:                    command("PORT %d,%d,%d,%d,%d,%d",
                    411:                      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
                    412:                      UC(p[0]), UC(p[1]));
                    413:                if (result == ERROR && sendport == -1) {
                    414:                        sendport = 0;
                    415:                        goto noport;
                    416:                }
                    417:                return ((result == COMPLETE)?OK:NOTOK);
                    418:        }
                    419:        return (OK);
                    420: bad:
                    421:        (void) close(data), data = -1;
                    422:        return (NOTOK);
                    423: }
                    424: 
                    425: /*ARGSUSED */
                    426: int
                    427: dataconn(modeX)
                    428:        char *modeX;
                    429: {
                    430:        struct sockaddr_in from;
                    431:        int s, fromlen = sizeof (from);
                    432: 
                    433:        s = accept(data, (struct sockaddr *) &from, &fromlen);
                    434:        if (s < 0) {
                    435:                (void)sprintf(ftp_error,"ftp: accept  %s",
                    436:                        (errno <= sys_nerr)? sys_errlist[errno]:"");
                    437:                (void) close(data), data = -1;
                    438:                return (NOTOK);
                    439:        }
                    440:        (void) close(data);
                    441:        data = s;
                    442:        return (data);
                    443: }
                    444: 
                    445: lostpeer()
                    446: {
                    447:  
                    448:         if (connected) {
                    449:                 if (cout != NULL) {
                    450:                         (void)shutdown(fileno(cout), 1+1);
                    451:                         (void)fclose(cout);
                    452:                         cout = NULL;
                    453:                 }
                    454:                 if (data >= 0) {
                    455:                         (void) shutdown(data, 1+1);
                    456:                         (void) close(data);
                    457:                         data = -1;
                    458:                 }
                    459:                 connected = 0;
                    460:         }
                    461: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.