Annotation of 43BSDReno/contrib/isode-beta/ftam-ftp/ftp.c, revision 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.