Annotation of researchv9/ipc/src/servers/ftpd.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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