Annotation of researchv8dc/cmd/inet/etc/ftpd/ftpd.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)ftpd.c     4.28 (Berkeley) 9/22/83";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * FTP server.
        !             7:  */
        !             8: #include <sys/param.h>
        !             9: #include <sys/stat.h>
        !            10: #include <sys/ioctl.h>
        !            11: #include <sys/file.h>
        !            12: #include <wait.h>
        !            13: 
        !            14: #include <sys/inet/in.h>
        !            15: 
        !            16: #include "ftp.h"
        !            17: 
        !            18: #include <stdio.h>
        !            19: #include <signal.h>
        !            20: #include <pwd.h>
        !            21: #include <setjmp.h>
        !            22: #include <errno.h>
        !            23: 
        !            24: /*
        !            25:  * File containing login names
        !            26:  * NOT to be used on this machine.
        !            27:  * Commonly used to disallow uucp.
        !            28:  */
        !            29: #define        FTPUSERS        "/etc/ftpusers"
        !            30: 
        !            31: extern int errno;
        !            32: extern char *sys_errlist[];
        !            33: extern char *crypt();
        !            34: extern char version[];
        !            35: extern char *home;             /* pointer to home directory for glob */
        !            36: extern FILE *popen(), *fopen();
        !            37: extern int pclose(), fclose();
        !            38: 
        !            39: struct socket {
        !            40:        unsigned short sport;
        !            41:        unsigned short dport;
        !            42:        long saddr;
        !            43:        long daddr;
        !            44: } his_addr, data_dest, data_source, ctrl_addr;
        !            45: 
        !            46: int    data;
        !            47: jmp_buf        errcatch;
        !            48: int    logged_in;
        !            49: struct passwd *pw;
        !            50: int    debug;
        !            51: int    timeout;
        !            52: int    logging;
        !            53: int    guest;
        !            54: int    type;
        !            55: int    form;
        !            56: int    stru;                   /* avoid C keyword */
        !            57: int    mode;
        !            58: int    usedefault = 1;         /* for data transfers */
        !            59: char   hostname[32];
        !            60: char   remotehost[32];
        !            61: 
        !            62: 
        !            63: /*
        !            64:  * Timeout intervals for retrying connections
        !            65:  * to hosts that don't accept PORT cmds.  This
        !            66:  * is a kludge, but given the problems with TCP...
        !            67:  */
        !            68: #define        SWAITMAX        90      /* wait at most 90 seconds */
        !            69: #define        SWAITINT        5       /* interval between retries */
        !            70: 
        !            71: int    swaitmax = SWAITMAX;
        !            72: int    swaitint = SWAITINT;
        !            73: 
        !            74: int    lostconn();
        !            75: int    reapchild();
        !            76: int    getdatasock();
        !            77: FILE   *dataconn();
        !            78: 
        !            79: main(argc, argv)
        !            80:        int argc;
        !            81:        char *argv[];
        !            82: {
        !            83:        int ctrl, s, options = 0;
        !            84:        char *cp;
        !            85:        int dev;
        !            86:        struct in_service *servp;
        !            87: 
        !            88:        servp = in_service("ftp", "tcp", 0);
        !            89:        if (servp == 0) {
        !            90:                fprintf(stderr, "ftpd: ftp/tcp: unknown service\n");
        !            91:                exit(1);
        !            92:        }
        !            93:        ctrl_addr.sport = servp->port;
        !            94:        data_source.sport = servp->port - 1;
        !            95:        while (argc > 0 && *argv[0] == '-') {
        !            96:                for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
        !            97: 
        !            98:                case 'v':
        !            99:                        debug = 1;
        !           100:                        break;
        !           101: 
        !           102:                case 'd':
        !           103:                        debug = 1;
        !           104:                        break;
        !           105: 
        !           106:                case 'l':
        !           107:                        logging = 1;
        !           108:                        break;
        !           109: 
        !           110:                case 't':
        !           111:                        timeout = atoi(++cp);
        !           112:                        goto nextopt;
        !           113:                        break;
        !           114: 
        !           115:                default:
        !           116:                        fprintf(stderr, "Unknown flag -%c ignored.\n", *cp);
        !           117:                        break;
        !           118:                }
        !           119: nextopt:
        !           120:                argc--, argv++;
        !           121:        }
        !           122:        signal(SIGPIPE, SIG_IGN);
        !           123:        signal(SIGHUP, SIG_IGN);
        !           124: 
        !           125:        do {
        !           126:                s = tcp_sock();
        !           127:                if (s < 0) {
        !           128:                        perror("ftpd: socket");;
        !           129:                        sleep(5);
        !           130:                        continue;
        !           131:                }
        !           132:                if (tcp_listen(s, servp->port, 0, 0) < 0) {
        !           133:                        close(s);
        !           134:                        s = -1;
        !           135:                        sleep(30);
        !           136:                        continue;
        !           137:                }
        !           138:        } while (s < 0);
        !           139: 
        !           140:        signal(SIGCHLD, reapchild);
        !           141:        for (;;) {
        !           142:                int ctrl;
        !           143: 
        !           144:                ctrl = tcp_accept(s, &his_addr.saddr, &his_addr.sport, &dev);
        !           145:                fprintf(stderr, "accept req from %s, port %d\n", inet_ntoa(his_addr.saddr), his_addr.sport);
        !           146:                if (ctrl < 0) {
        !           147:                        if (errno == EINTR)
        !           148:                                continue;
        !           149:                        perror("ftpd: accept");
        !           150:                        sleep(1);
        !           151:                        continue;
        !           152:                }
        !           153:                switch(fork()) {
        !           154:                case -1:
        !           155:                        printf("Out of processes\n");
        !           156:                        break;
        !           157:                case 0:
        !           158:                        signal (SIGCHLD, SIG_IGN);
        !           159:                        dolog(&his_addr);
        !           160:                        close(s);
        !           161:                        dup2(ctrl, 0), close(ctrl), dup2(0, 1);
        !           162:                        /*
        !           163:                         * Set up default state
        !           164:                         */
        !           165:                        logged_in = 0;
        !           166:                        data = -1;
        !           167:                        type = TYPE_A;
        !           168:                        form = FORM_N;
        !           169:                        stru = STRU_F;
        !           170:                        mode = MODE_S;
        !           171: /* try to do this equivalently
        !           172:                        (void) getsockname(0, &ctrl_addr, sizeof (ctrl_addr));
        !           173:                        gethostname(hostname, sizeof (hostname));
        !           174: */
        !           175:                        reply(220, "%s FTP server (%s) ready.",
        !           176:                                hostname, version);
        !           177:                        for (;;) {
        !           178:                                setjmp(errcatch);
        !           179:                                yyparse();
        !           180:                        }
        !           181:                }
        !           182:                close(ctrl);
        !           183:        }
        !           184: }
        !           185: 
        !           186: reapchild()
        !           187: {
        !           188:        union wait status;
        !           189: 
        !           190:        while (wait3(&status, WNOHANG, 0) > 0)
        !           191:                ;
        !           192: }
        !           193: 
        !           194: lostconn()
        !           195: {
        !           196: 
        !           197:        if (debug)
        !           198:                fprintf(stderr, "Lost connection.\n");
        !           199:        dologout(-1);
        !           200: }
        !           201: 
        !           202: pass(passwd)
        !           203:        char *passwd;
        !           204: {
        !           205:        char *xpasswd, *savestr();
        !           206:        static struct passwd save;
        !           207: 
        !           208:        if (logged_in || pw == NULL) {
        !           209:                reply(503, "Login with USER first.");
        !           210:                return;
        !           211:        }
        !           212:        if (!guest) {           /* "ftp" is only account allowed no password */
        !           213:                xpasswd = crypt(passwd, pw->pw_passwd);
        !           214:                if (*pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) {
        !           215:                        reply(530, "Login incorrect.");
        !           216:                        pw = NULL;
        !           217:                        return;
        !           218:                }
        !           219:        }
        !           220:        setegid(pw->pw_gid);
        !           221: /*     initgroups(pw->pw_name, pw->pw_gid);  */
        !           222:        if (chdir(pw->pw_dir)) {
        !           223:                reply(550, "User %s: can't change directory to $s.",
        !           224:                        pw->pw_name, pw->pw_dir);
        !           225:                goto bad;
        !           226:        }
        !           227:        if (guest && chroot(pw->pw_dir) < 0) {
        !           228:                reply(550, "Can't set guest privileges.");
        !           229:                goto bad;
        !           230:        }
        !           231:        if (!guest)
        !           232:                reply(230, "User %s logged in.", pw->pw_name);
        !           233:        else
        !           234:                reply(230, "Guest login ok, access restrictions apply.");
        !           235:        logged_in = 1;
        !           236:        dologin(pw);
        !           237:        seteuid(pw->pw_uid);
        !           238:        /*
        !           239:         * Save everything so globbing doesn't
        !           240:         * clobber the fields.
        !           241:         */
        !           242:        save = *pw;
        !           243:        save.pw_name = savestr(pw->pw_name);
        !           244:        save.pw_passwd = savestr(pw->pw_passwd);
        !           245:        save.pw_comment = savestr(pw->pw_comment);
        !           246:        save.pw_gecos = savestr(pw->pw_gecos, &save.pw_gecos);
        !           247:        save.pw_dir = savestr(pw->pw_dir);
        !           248:        save.pw_shell = savestr(pw->pw_shell);
        !           249:        pw = &save;
        !           250:        home = pw->pw_dir;              /* home dir for globbing */
        !           251:        return;
        !           252: bad:
        !           253:        seteuid(0);
        !           254:        pw = NULL;
        !           255: }
        !           256: 
        !           257: char *
        !           258: savestr(s)
        !           259:        char *s;
        !           260: {
        !           261:        char *malloc();
        !           262:        char *new = malloc(strlen(s) + 1);
        !           263:        
        !           264:        if (new != NULL)
        !           265:                strcpy(new, s);
        !           266:        return (new);
        !           267: }
        !           268: 
        !           269: retrieve(cmd, name)
        !           270:        char *cmd, *name;
        !           271: {
        !           272:        FILE *fin, *dout;
        !           273:        struct stat st;
        !           274:        int (*closefunc)();
        !           275: 
        !           276:        st.st_size = 0;
        !           277:        if (cmd == 0 &&
        !           278:            (stat(name, &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) {
        !           279:                reply(550, "%s: not a plain file.", name);
        !           280:                goto done;
        !           281:        }
        !           282:        dout = dataconn(name, st.st_size, "w");
        !           283:        if (dout == NULL)
        !           284:                goto done;
        !           285:        if (cmd == 0) {
        !           286: #ifdef notdef
        !           287:                /* no remote command execution -- it's a security hole */
        !           288:                if (*name == '|')
        !           289:                        fin = popen(name + 1, "r"), closefunc = pclose;
        !           290:                else
        !           291: #endif
        !           292:                        fin = fopen(name, "r"), closefunc = fclose;
        !           293:        } else {
        !           294:                char line[BUFSIZ];
        !           295: 
        !           296:                sprintf(line, cmd, name), name = line;
        !           297:                fin = popen(line, "r"), closefunc = pclose;
        !           298:        }
        !           299:        if (fin == NULL) {
        !           300:                if (errno != 0)
        !           301:                        reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           302:                return;
        !           303:        }
        !           304:        if (send_data(fin, dout) || ferror(dout))
        !           305:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           306:        else
        !           307:                reply(226, "Transfer complete.");
        !           308:        fclose(dout), data = -1;
        !           309: done:
        !           310:        (*closefunc)(fin);
        !           311: }
        !           312: 
        !           313: store(name, mode)
        !           314:        char *name, *mode;
        !           315: {
        !           316:        FILE *fout, *din;
        !           317:        int (*closefunc)(), dochown = 0;
        !           318: 
        !           319:        din = dataconn(name, (off_t)-1, "r");
        !           320:        if (din == NULL)
        !           321:                goto done;
        !           322: #ifdef notdef
        !           323:        /* no remote command execution -- it's a security hole */
        !           324:        if (name[0] == '|')
        !           325:                fout = popen(&name[1], "w"), closefunc = pclose;
        !           326:        else
        !           327: #endif
        !           328:        {
        !           329:                struct stat st;
        !           330: 
        !           331:                if (stat(name, &st) < 0)
        !           332:                        dochown++;
        !           333:                fout = fopen(name, mode), closefunc = fclose;
        !           334:        }
        !           335:        if (fout == NULL) {
        !           336:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           337:                return;
        !           338:        }
        !           339:        if (receive_data(din, fout) || ferror(fout))
        !           340:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           341:        else
        !           342:                reply(226, "Transfer complete.");
        !           343:        fclose(din), data = -1;
        !           344: done:
        !           345:        if (dochown)
        !           346:                (void) chown(name, pw->pw_uid, -1);
        !           347:        (*closefunc)(fout);
        !           348: }
        !           349: 
        !           350: getdatasock(mode)
        !           351:        char *mode;
        !           352: {
        !           353:        int s;
        !           354: 
        !           355:        if (data >= 0)
        !           356:                return (data);
        !           357:        data_source.saddr = ctrl_addr.saddr;
        !           358:        s = tcp_sock();
        !           359:        if (s < 0) {
        !           360:                perror("ftpd: socket");;
        !           361:                return(NULL);
        !           362:        }
        !           363: 
        !           364:        seteuid(pw->pw_uid);
        !           365:        return (s);
        !           366: }
        !           367: 
        !           368: FILE *
        !           369: dataconn(name, size, mode)
        !           370:        char *name;
        !           371:        off_t size;
        !           372:        char *mode;
        !           373: {
        !           374:        char sizebuf[32];
        !           375:        FILE *file;
        !           376:        int retry = 0;
        !           377: 
        !           378:        if (size >= 0)
        !           379:                sprintf (sizebuf, " (%ld bytes)", size);
        !           380:        else
        !           381:                (void) strcpy(sizebuf, "");
        !           382:        if (data >= 0) {
        !           383:                reply(125, "Using existing data connection for %s%s.",
        !           384:                    name, sizebuf);
        !           385:                usedefault = 1;
        !           386:                return (fdopen(data, mode));
        !           387:        }
        !           388:        if (usedefault)
        !           389:                data_dest = his_addr;
        !           390:        usedefault = 1;
        !           391:        data  = getdatasock(mode);
        !           392:        if (data < 0) {
        !           393:                reply(425, "Can't create data socket (%s,%d): %s.",
        !           394:                        inet_ntoa(data_source.saddr),
        !           395:                        ntohs(data_source.sport),
        !           396:                sys_errlist[errno]);
        !           397:                return (NULL);
        !           398:        }
        !           399:        reply(150, "Opening data connection for %s (%s,%d)%s.",
        !           400:            name,
        !           401:                inet_ntoa(data_dest.saddr),
        !           402:                data_dest.sport, sizebuf);
        !           403: 
        !           404:        while (tcp_connect(data, 0, data_dest.saddr, data_dest.sport) < 0) {            
        !           405:                data = -1;
        !           406:                if (retry < swaitmax) {
        !           407:                        data = getdatasock(mode); 
        !           408:                        sleep(swaitint);
        !           409:                        retry += swaitint;
        !           410:                        continue;
        !           411:                }
        !           412:                reply(425, "Can't build data connection: %s.",
        !           413:                    sys_errlist[errno]);
        !           414:                (void)fclose(file);
        !           415:                return (NULL);
        !           416:        }
        !           417:        return (fdopen(data, mode));
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * Tranfer the contents of "instr" to
        !           422:  * "outstr" peer using the appropriate
        !           423:  * encapulation of the date subject
        !           424:  * to Mode, Structure, and Type.
        !           425:  *
        !           426:  * NB: Form isn't handled.
        !           427:  */
        !           428: send_data(instr, outstr)
        !           429:        FILE *instr, *outstr;
        !           430: {
        !           431:        register int c;
        !           432:        int netfd, filefd, cnt;
        !           433:        char buf[BUFSIZ];
        !           434: 
        !           435:        switch (type) {
        !           436: 
        !           437:        case TYPE_A:
        !           438:                while ((c = getc(instr)) != EOF) {
        !           439:                        if (c == '\n') {
        !           440:                                if (ferror (outstr))
        !           441:                                        return (1);
        !           442:                                putc('\r', outstr);
        !           443:                        }
        !           444:                        putc(c, outstr);
        !           445:                        if (c == '\r')
        !           446:                                putc ('\0', outstr);
        !           447:                }
        !           448:                if (ferror (instr) || ferror (outstr))
        !           449:                        return (1);
        !           450:                return (0);
        !           451:                
        !           452:        case TYPE_I:
        !           453:        case TYPE_L:
        !           454:                netfd = fileno(outstr);
        !           455:                filefd = fileno(instr);
        !           456: 
        !           457:                while ((cnt = read(filefd, buf, sizeof (buf))) > 0)
        !           458:                        if (write(netfd, buf, cnt) < 0)
        !           459:                                return (1);
        !           460:                return (cnt < 0);
        !           461:        }
        !           462:        reply(504,"Unimplemented TYPE %d in send_data", type);
        !           463:        return (1);
        !           464: }
        !           465: 
        !           466: /*
        !           467:  * Transfer data from peer to
        !           468:  * "outstr" using the appropriate
        !           469:  * encapulation of the data subject
        !           470:  * to Mode, Structure, and Type.
        !           471:  *
        !           472:  * N.B.: Form isn't handled.
        !           473:  */
        !           474: receive_data(instr, outstr)
        !           475:        FILE *instr, *outstr;
        !           476: {
        !           477:        register int c;
        !           478:        int cnt;
        !           479:        char buf[BUFSIZ];
        !           480: 
        !           481: 
        !           482:        switch (type) {
        !           483: 
        !           484:        case TYPE_I:
        !           485:        case TYPE_L:
        !           486:                while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0)
        !           487:                        if (write(fileno(outstr), buf, cnt) < 0)
        !           488:                                return (1);
        !           489:                return (cnt < 0);
        !           490: 
        !           491:        case TYPE_E:
        !           492:                reply(504, "TYPE E not implemented.");
        !           493:                return (1);
        !           494: 
        !           495:        case TYPE_A:
        !           496:                while ((c = getc(instr)) != EOF) {
        !           497:                        if (c == '\r') {
        !           498:                                if (ferror (outstr))
        !           499:                                        return (1);
        !           500:                                if ((c = getc(instr)) != '\n')
        !           501:                                        putc ('\r', outstr);
        !           502:                                if (c == '\0')
        !           503:                                        continue;
        !           504:                        }
        !           505:                        putc (c, outstr);
        !           506:                }
        !           507:                if (ferror (instr) || ferror (outstr))
        !           508:                        return (1);
        !           509:                return (0);
        !           510:        }
        !           511:        fatal("Unknown type in receive_data.");
        !           512:        /*NOTREACHED*/
        !           513: }
        !           514: 
        !           515: fatal(s)
        !           516:        char *s;
        !           517: {
        !           518:        reply(451, "Error in server: %s\n", s);
        !           519:        reply(221, "Closing connection due to server error.");
        !           520:        dologout(0);
        !           521: }
        !           522: 
        !           523: reply(n, s, args)
        !           524:        int n;
        !           525:        char *s;
        !           526: {
        !           527: 
        !           528:        printf("%d ", n);
        !           529:        _doprnt(s, &args, stdout);
        !           530:        printf("\r\n");
        !           531:        fflush(stdout);
        !           532:        if (debug) {
        !           533:                fprintf(stderr, "<--- %d ", n);
        !           534:                _doprnt(s, &args, stderr);
        !           535:                fprintf(stderr, "\n");
        !           536:                fflush(stderr);
        !           537:        }
        !           538: }
        !           539: 
        !           540: lreply(n, s, args)
        !           541:        int n;
        !           542:        char *s;
        !           543: {
        !           544:        printf("%d-", n);
        !           545:        _doprnt(s, &args, stdout);
        !           546:        printf("\r\n");
        !           547:        fflush(stdout);
        !           548:        if (debug) {
        !           549:                fprintf(stderr, "<--- %d-", n);
        !           550:                _doprnt(s, &args, stderr);
        !           551:                fprintf(stderr, "\n");
        !           552:        }
        !           553: }
        !           554: 
        !           555: replystr(s)
        !           556:        char *s;
        !           557: {
        !           558:        printf("%s\r\n", s);
        !           559:        fflush(stdout);
        !           560:        if (debug)
        !           561:                fprintf(stderr, "<--- %s\n", s);
        !           562: }
        !           563: 
        !           564: ack(s)
        !           565:        char *s;
        !           566: {
        !           567:        reply(200, "%s command okay.", s);
        !           568: }
        !           569: 
        !           570: nack(s)
        !           571:        char *s;
        !           572: {
        !           573:        reply(502, "%s command not implemented.", s);
        !           574: }
        !           575: 
        !           576: yyerror()
        !           577: {
        !           578:        reply(500, "Command not understood.");
        !           579: }
        !           580: 
        !           581: delete(name)
        !           582:        char *name;
        !           583: {
        !           584:        struct stat st;
        !           585: 
        !           586:        if (stat(name, &st) < 0) {
        !           587:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           588:                return;
        !           589:        }
        !           590:        if ((st.st_mode&S_IFMT) == S_IFDIR) {
        !           591:                if (rmdir(name) < 0) {
        !           592:                        reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           593:                        return;
        !           594:                }
        !           595:                goto done;
        !           596:        }
        !           597:        if (unlink(name) < 0) {
        !           598:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           599:                return;
        !           600:        }
        !           601: done:
        !           602:        ack("DELE");
        !           603: }
        !           604: 
        !           605: cwd(path)
        !           606:        char *path;
        !           607: {
        !           608: 
        !           609:        if (chdir(path) < 0) {
        !           610:                reply(550, "%s: %s.", path, sys_errlist[errno]);
        !           611:                return;
        !           612:        }
        !           613:        ack("CWD");
        !           614: }
        !           615: 
        !           616: makedir(name)
        !           617:        char *name;
        !           618: {
        !           619:        struct stat st;
        !           620:        int dochown = stat(name, &st) < 0;
        !           621:        
        !           622:        if (mkdir(name, 0777) < 0) {
        !           623:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           624:                return;
        !           625:        }
        !           626:        if (dochown)
        !           627:                (void) chown(name, pw->pw_uid, -1);
        !           628:        ack("MKDIR");
        !           629: }
        !           630: 
        !           631: removedir(name)
        !           632:        char *name;
        !           633: {
        !           634: 
        !           635:        if (rmdir(name) < 0) {
        !           636:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           637:                return;
        !           638:        }
        !           639:        ack("RMDIR");
        !           640: }
        !           641: 
        !           642: #define        MAXPATHLEN      256
        !           643: pwd()
        !           644: {
        !           645:        char path[MAXPATHLEN + 1];
        !           646: 
        !           647:        if (getwd(path) == NULL) {
        !           648:                reply(451, "%s.", path);
        !           649:                return;
        !           650:        }
        !           651:        reply(251, "\"%s\" is current directory.", path);
        !           652: }
        !           653: 
        !           654: char *
        !           655: renamefrom(name)
        !           656:        char *name;
        !           657: {
        !           658:        struct stat st;
        !           659: 
        !           660:        if (stat(name, &st) < 0) {
        !           661:                reply(550, "%s: %s.", name, sys_errlist[errno]);
        !           662:                return ((char *)0);
        !           663:        }
        !           664:        reply(350, "File exists, ready for destination name");
        !           665:        return (name);
        !           666: }
        !           667: 
        !           668: renamecmd(from, to)
        !           669:        char *from, *to;
        !           670: {
        !           671: 
        !           672:        if (rename(from, to) < 0) {
        !           673:                reply(550, "rename: %s.", sys_errlist[errno]);
        !           674:                return;
        !           675:        }
        !           676:        ack("RNTO");
        !           677: }
        !           678: 
        !           679: dolog(addr)
        !           680:        register struct socket *addr;
        !           681: {
        !           682:        char *h_name = (char *)in_host(addr->saddr);
        !           683:        time_t t;
        !           684: 
        !           685:        strncpy(remotehost, h_name, sizeof (remotehost));
        !           686:        if (!logging)
        !           687:                return;
        !           688:        t = time(0);
        !           689:        fprintf(stderr,"FTPD: connection from %s at %s", remotehost, ctime(&t));
        !           690:        fflush(stderr);
        !           691: }
        !           692: 
        !           693: #include <utmp.h>
        !           694: 
        !           695: #define        SCPYN(a, b)     strncpy(a, b, sizeof (a))
        !           696: struct utmp utmp;
        !           697: 
        !           698: /*
        !           699:  * Record login in wtmp file.
        !           700:  */
        !           701: 
        !           702: #define        O_WRONLY        1
        !           703: #define O_APPEND       1
        !           704: dologin(pw)
        !           705:        struct passwd *pw;
        !           706: {
        !           707:        int wtmp;
        !           708:        char line[32];
        !           709: 
        !           710:        wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
        !           711:        if (wtmp >= 0) {
        !           712:                /* hack, but must be unique and no tty line */
        !           713:                sprintf(line, "ftp%d", getpid());
        !           714:                SCPYN(utmp.ut_line, line);
        !           715:                SCPYN(utmp.ut_name, pw->pw_name);
        !           716:                utmp.ut_time = time(0);
        !           717:                (void) write(wtmp, (char *)&utmp, sizeof (utmp));
        !           718:                (void) close(wtmp);
        !           719:        }
        !           720: }
        !           721: 
        !           722: /*
        !           723:  * Record logout in wtmp file
        !           724:  * and exit with supplied status.
        !           725:  */
        !           726: dologout(status)
        !           727:        int status;
        !           728: {
        !           729:        int wtmp;
        !           730: 
        !           731:        if (!logged_in)
        !           732:                _exit(status);
        !           733:        seteuid(0);
        !           734:        wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND);
        !           735:        if (wtmp >= 0) {
        !           736:                SCPYN(utmp.ut_name, "");
        !           737:                utmp.ut_time = time(0);
        !           738:                (void) write(wtmp, (char *)&utmp, sizeof (utmp));
        !           739:                (void) close(wtmp);
        !           740:        }
        !           741:        /* beware of flushing buffers after a SIGPIPE */
        !           742:        _exit(status);
        !           743: }
        !           744: 
        !           745: /*
        !           746:  * Special version of popen which avoids
        !           747:  * call to shell.  This insures noone may 
        !           748:  * create a pipe to a hidden program as a side
        !           749:  * effect of a list or dir command.
        !           750:  */
        !           751: #define        tst(a,b)        (*mode == 'r'? (b) : (a))
        !           752: #define        RDR     0
        !           753: #define        WTR     1
        !           754: static int popen_pid[5];
        !           755: 
        !           756: static char *
        !           757: nextarg(cpp)
        !           758:        char *cpp;
        !           759: {
        !           760:        register char *cp = cpp;
        !           761: 
        !           762:        if (cp == 0)
        !           763:                return (cp);
        !           764:        while (*cp && *cp != ' ' && *cp != '\t')
        !           765:                cp++;
        !           766:        if (*cp == ' ' || *cp == '\t') {
        !           767:                *cp++ = '\0';
        !           768:                while (*cp == ' ' || *cp == '\t')
        !           769:                        cp++;
        !           770:        }
        !           771:        if (cp == cpp)
        !           772:                return ((char *)0);
        !           773:        return (cp);
        !           774: }
        !           775: 
        !           776: FILE *
        !           777: popen(cmd, mode)
        !           778:        char *cmd, *mode;
        !           779: {
        !           780:        int p[2], ac, gac;
        !           781:        register myside, hisside, pid;
        !           782:        char *av[20], *gav[512];
        !           783:        register char *cp;
        !           784: 
        !           785:        if (pipe(p) < 0)
        !           786:                return (NULL);
        !           787:        cp = cmd, ac = 0;
        !           788:        /* break up string into pieces */
        !           789:        do {
        !           790:                av[ac++] = cp;
        !           791:                cp = nextarg(cp);
        !           792:        } while (cp && *cp && ac < 20);
        !           793:        av[ac] = (char *)0;
        !           794:        gav[0] = av[0];
        !           795:        /* glob each piece */
        !           796:        for (gac = ac = 1; av[ac] != NULL; ac++) {
        !           797:                char **pop;
        !           798:                extern char **glob();
        !           799: 
        !           800:                pop = glob(av[ac]);
        !           801:                if (pop) {
        !           802:                        av[ac] = (char *)pop;           /* save to free later */
        !           803:                        while (*pop && gac < 512)
        !           804:                                gav[gac++] = *pop++;
        !           805:                }
        !           806:        }
        !           807:        gav[gac] = (char *)0;
        !           808:        myside = tst(p[WTR], p[RDR]);
        !           809:        hisside = tst(p[RDR], p[WTR]);
        !           810:        if ((pid = fork()) == 0) {
        !           811:                /* myside and hisside reverse roles in child */
        !           812:                close(myside);
        !           813:                dup2(hisside, tst(0, 1));
        !           814:                close(hisside);
        !           815:                execv(gav[0], gav);
        !           816:                _exit(1);
        !           817:        }
        !           818:        for (ac = 1; av[ac] != NULL; ac++)
        !           819:                blkfree((char **)av[ac]);
        !           820:        if (pid == -1)
        !           821:                return (NULL);
        !           822:        popen_pid[myside] = pid;
        !           823:        close(hisside);
        !           824:        return (fdopen(myside, mode));
        !           825: }
        !           826: 
        !           827: pclose(ptr)
        !           828:        FILE *ptr;
        !           829: {
        !           830:        register f, r, (*hstat)(), (*istat)(), (*qstat)();
        !           831:        int status;
        !           832: 
        !           833:        f = fileno(ptr);
        !           834:        fclose(ptr);
        !           835:        istat = signal(SIGINT, SIG_IGN);
        !           836:        qstat = signal(SIGQUIT, SIG_IGN);
        !           837:        hstat = signal(SIGHUP, SIG_IGN);
        !           838:        while ((r = wait(&status)) != popen_pid[f] && r != -1)
        !           839:                ;
        !           840:        if (r == -1)
        !           841:                status = -1;
        !           842:        signal(SIGINT, istat);
        !           843:        signal(SIGQUIT, qstat);
        !           844:        signal(SIGHUP, hstat);
        !           845:        return (status);
        !           846: }
        !           847: 
        !           848: /*
        !           849:  * Check user requesting login priviledges.
        !           850:  * Disallow anyone mentioned in the file FTPUSERS
        !           851:  * to allow people such as uucp to be avoided.
        !           852:  */
        !           853: checkuser(name)
        !           854:        register char *name;
        !           855: {
        !           856:        char line[BUFSIZ], *index();
        !           857:        FILE *fd;
        !           858:        int found = 0;
        !           859: 
        !           860:        fd = fopen(FTPUSERS, "r");
        !           861:        if (fd == NULL)
        !           862:                return (1);
        !           863:        while (fgets(line, sizeof (line), fd) != NULL) {
        !           864:                register char *cp = index(line, '\n');
        !           865: 
        !           866:                if (cp)
        !           867:                        *cp = '\0';
        !           868:                if (strcmp(line, name) == 0) {
        !           869:                        found++;
        !           870:                        break;
        !           871:                }
        !           872:        }
        !           873:        fclose(fd);
        !           874:        return (!found);
        !           875: }
        !           876: seteuid(uid)
        !           877: {
        !           878:        return(setuid(uid));
        !           879: }
        !           880: setegid(gid)
        !           881: {
        !           882:        return(setgid(gid));
        !           883: }
        !           884: 
        !           885: rename(from, to)
        !           886: {
        !           887:        if (-1 == link(from, to))
        !           888:                return(-1);
        !           889:        return(unlink(from));
        !           890: }
        !           891: inet_ntoa(addr)
        !           892: long addr;
        !           893: {
        !           894:        static char b[32];
        !           895:        unsigned char *xp = (unsigned char *)&addr;
        !           896: 
        !           897:        sprintf(b, "%d.%d.%d.%d", xp[3], xp[2], xp[1], xp[0]);
        !           898:        return(b);
        !           899: }

unix.superglobalmegacorp.com

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