Annotation of researchv9/ipc/src/bin/ftp.c, revision 1.1.1.1

1.1       root        1: #include <sys/param.h>
                      2: #include <sys/types.h>
                      3: #include <sys/stat.h>
                      4: #include <sys/ioctl.h>
                      5: #include <stdio.h>
                      6: #include <signal.h>
                      7: #include <sys/timeb.h>
                      8: #include <errno.h>
                      9: #include <sys/inet/tcp_user.h>
                     10: #include <libc.h>
                     11: #include "ftp.h"
                     12: #include "ftp_var.h"
                     13: 
                     14: in_addr myaddr;
                     15: tcp_port myctlport;
                     16: in_addr hisaddr;
                     17: tcp_port dataport;
                     18: int    data = -1;
                     19: int    connected;
                     20: 
                     21: FILE   *cin, *cout;
                     22: FILE   *dataconn();
                     23: 
                     24: char *
                     25: hookup(host, port)
                     26:        char *host;
                     27:        int port;
                     28: {
                     29:        int s;
                     30:        struct tcpuser tu;
                     31:        extern in_addr in_address();
                     32:        extern char *in_host();
                     33: 
                     34:        hisaddr = in_address(host);
                     35:        if (hisaddr == 0) {
                     36:                perror("ftp: host unknown");
                     37:                return (0);
                     38:        }
                     39:        hostname = in_host(hisaddr);
                     40:        if ((s = tcp_sock()) < 0) {
                     41:                perror("ftp: socket");
                     42:                return (0);
                     43:        }
                     44:        tu.laddr = 0;
                     45:        tu.lport = 0;
                     46:        tu.faddr = hisaddr;
                     47:        tu.fport = port;
                     48:        tu.param = 0;
                     49:        if (tcp_connect(s, &tu) < 0) {
                     50:                perror("ftp: tcp_connect");
                     51:                goto bad;
                     52:        }
                     53:        myaddr = tu.laddr;
                     54:        myctlport = tu.lport;
                     55:        cin = fdopen(s, "r");
                     56:        cout = fdopen(s, "w");
                     57:        if (cin == NULL || cout == NULL) {
                     58:                fprintf(stderr, "ftp: fdopen failed.\n");
                     59:                if (cin)
                     60:                        fclose(cin);
                     61:                if (cout)
                     62:                        fclose(cout);
                     63:                goto bad;
                     64:        }
                     65:        if (verbose)
                     66:                printf("Connected to %s.\n", hostname);
                     67:        (void) getreply(0);             /* read startup message from server */
                     68:        return (hostname);
                     69: bad:
                     70:        close(s);
                     71:        return ((char *)0);
                     72: }
                     73: 
                     74: login(hp)
                     75:        char *hp;
                     76: {
                     77:        char acct[80];
                     78:        char user[80], passwd[80];
                     79:        int n;
                     80:        struct sgttyb sbuf;
                     81:        int oldflags;
                     82: 
                     83:        getresponse("login: ", user, sizeof(user));
                     84:        ioctl(fileno(stdin), TIOCGETP, &sbuf);
                     85:        oldflags = sbuf.sg_flags;
                     86:        sbuf.sg_flags = oldflags & ~ECHO;
                     87:        ioctl(fileno(stdin), TIOCSETP, &sbuf);
                     88:        getresponse("password: ", passwd, sizeof(passwd));
                     89:        sbuf.sg_flags = oldflags;
                     90:        ioctl(fileno(stdin), TIOCSETP, &sbuf);
                     91:        printf("\n"); (void) fflush(stdout);
                     92:        n = command("USER %s", user);
                     93:        if (n == CONTINUE)
                     94:                n = command("PASS %s", passwd);
                     95:        if (n == CONTINUE) {
                     96:                getresponse("ACCOUNT: ", acct, sizeof(acct));
                     97:                n = command("ACCT %s", acct);
                     98:        }
                     99:        if (n != COMPLETE) {
                    100:                fprintf(stderr, "Login failed.\n");
                    101:                return (0);
                    102:        }
                    103:        return (1);
                    104: }
                    105: 
                    106: getresponse(prompt, cp, len)
                    107:        char *prompt;
                    108:        char *cp;
                    109:        int len;
                    110: {
                    111:        int c;
                    112:        char *p = cp;
                    113: 
                    114:        printf(prompt); (void) fflush(stdout);
                    115:        while(c = getchar())
                    116:                if (c != ' ' && c != '\t')
                    117:                        break;
                    118:        while(c != '\n' && c != EOF) {
                    119:                if ((cp + len - 1) > p)
                    120:                        *p++ = c;
                    121:                c = getchar();
                    122:        }
                    123:        *p = '\0';
                    124: }
                    125: 
                    126: 
                    127: 
                    128: /*VARARGS 1*/
                    129: command(fmt, args)
                    130:        char *fmt;
                    131: {
                    132: 
                    133:        if (debug) {
                    134:                printf("---> ");
                    135:                _doprnt(fmt, &args, stdout);
                    136:                printf("\n");
                    137:                (void) fflush(stdout);
                    138:        }
                    139:        if (cout == NULL) {
                    140:                perror ("No control connection for command");
                    141:                return (0);
                    142:        }
                    143:        _doprnt(fmt, &args, cout);
                    144:        fprintf(cout, "\r\n");
                    145:        (void) fflush(cout);
                    146:        return (getreply(!strcmp(fmt, "QUIT")));
                    147: }
                    148: 
                    149: #include <ctype.h>
                    150: 
                    151: getreply(expecteof)
                    152:        int expecteof;
                    153: {
                    154:        register int c, n;
                    155:        register int code, dig;
                    156:        int originalcode = 0, continuation = 0;
                    157: 
                    158:        for (;;) {
                    159:                dig = n = code = 0;
                    160:                while ((c = getc(cin)) != '\n') {
                    161:                        dig++;
                    162:                        if (c == EOF) {
                    163:                                if (expecteof)
                    164:                                        return (0);
                    165:                                lostpeer();
                    166:                                exit(1);
                    167:                        }
                    168:                        if (verbose && c != '\r' ||
                    169:                            (n == '5' && dig > 4))
                    170:                                putchar(c);
                    171:                        if (dig < 4 && isdigit(c))
                    172:                                code = code * 10 + (c - '0');
                    173:                        if (dig == 4 && c == '-')
                    174:                                continuation++;
                    175:                        if (n == 0)
                    176:                                n = c;
                    177:                }
                    178:                if (verbose || n == '5')
                    179:                        putchar(c);
                    180:                if (continuation && code != originalcode) {
                    181:                        if (originalcode == 0)
                    182:                                originalcode = code;
                    183:                        continue;
                    184:                }
                    185:                if (expecteof || empty(cin))
                    186:                        return (n - '0');
                    187:        }
                    188: }
                    189: 
                    190: empty(f)
                    191:        FILE *f;
                    192: {
                    193:        int mask;
                    194: 
                    195:        if (f->_cnt > 0)
                    196:                return (0);
                    197:        mask = (1 << fileno(f));
                    198:        (void) select(20, &mask, 0, 0);
                    199:        return (mask == 0);
                    200: }
                    201: 
                    202: jmp_buf        sendabort;
                    203: 
                    204: abortsend()
                    205: {
                    206: 
                    207:        longjmp(sendabort, 1);
                    208: }
                    209: 
                    210: sendrequest(cmd, local, remote)
                    211:        char *cmd, *local, *remote;
                    212: {
                    213:        FILE *fin, *dout, *popen();
                    214:        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
                    215:        char buf[BUFSIZ];
                    216:        register int bytes = 0, c;
                    217:        struct stat st;
                    218:        struct timeb start, stop;
                    219:        extern int errno;
                    220: 
                    221:        closefunc = NULL;
                    222:        if (setjmp(sendabort))
                    223:                goto bad;
                    224:        oldintr = signal(SIGINT, abortsend);
                    225:        if (strcmp(local, "-") == 0)
                    226:                fin = stdin;
                    227:        else if (*local == '|') {
                    228:                fin = popen(local + 1, "r");
                    229:                if (fin == NULL) {
                    230:                        perror(local + 1);
                    231:                        goto bad;
                    232:                }
                    233:                closefunc = pclose;
                    234:        } else {
                    235:                fin = fopen(local, "r");
                    236:                if (fin == NULL) {
                    237:                        perror(local);
                    238:                        goto bad;
                    239:                }
                    240:                closefunc = fclose;
                    241:                if (fstat(fileno(fin), &st) < 0 ||
                    242:                    (st.st_mode&S_IFMT) != S_IFREG) {
                    243:                        fprintf(stderr, "%s: not a plain file.", local);
                    244:                        goto bad;
                    245:                }
                    246:        }
                    247:        if (initconn())
                    248:                goto bad;
                    249:        if (remote) {
                    250:                if (command("%s %s", cmd, remote) != PRELIM)
                    251:                        goto bad;
                    252:        } else
                    253:                if (command("%s", cmd) != PRELIM)
                    254:                        goto bad;
                    255:        dout = dataconn("w");
                    256:        if (dout == NULL)
                    257:                goto bad;
                    258:        ftime(&start);
                    259:        switch (type) {
                    260: 
                    261:        case TYPE_I:
                    262:        case TYPE_L:
                    263:                errno = 0;
                    264:                while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
                    265:                        if (write(fileno (dout), buf, c) < 0)
                    266:                                break;
                    267:                        bytes += c;
                    268:                }
                    269:                if (c < 0)
                    270:                        perror(local);
                    271:                else if (errno)
                    272:                        perror("netout");
                    273:                break;
                    274: 
                    275:        case TYPE_A:
                    276:                while ((c = getc(fin)) != EOF) {
                    277:                        if (c == '\n') {
                    278:                                if (ferror(dout))
                    279:                                        break;
                    280:                                putc('\r', dout);
                    281:                                bytes++;
                    282:                        }
                    283:                        putc(c, dout);
                    284:                        bytes++;
                    285:                        if (c == '\r') {
                    286:                                putc('\0', dout);
                    287:                                bytes++;
                    288:                        }
                    289:                }
                    290:                if (ferror(fin))
                    291:                        perror(local);
                    292:                else if (ferror(dout))
                    293:                        perror("netout");
                    294:                break;
                    295:        }
                    296:        ftime(&stop);
                    297:        if (closefunc != NULL)
                    298:                (*closefunc)(fin);
                    299:        (void) fclose(dout);
                    300:        (void) getreply(0);
                    301: done:
                    302:        signal(SIGINT, oldintr);
                    303:        if (bytes > 0 && verbose)
                    304:                ptransfer("sent", bytes, &start, &stop);
                    305:        return;
                    306: bad:
                    307:        if (data >= 0)
                    308:                (void) close(data), data = -1;
                    309:        if (closefunc != NULL && fin != NULL)
                    310:                (*closefunc)(fin);
                    311:        goto done;
                    312: }
                    313: 
                    314: jmp_buf        recvabort;
                    315: 
                    316: abortrecv()
                    317: {
                    318: 
                    319:        longjmp(recvabort, 1);
                    320: }
                    321: 
                    322: recvrequest(cmd, local, remote)
                    323:        char *cmd, *local, *remote;
                    324: {
                    325:        FILE *fout, *din, *popen();
                    326:        char buf[BUFSIZ];
                    327:        int (*closefunc)(), pclose(), fclose(), (*oldintr)(), c;
                    328:        register int bytes = 0;
                    329:        struct timeb start, stop;
                    330:        extern int errno;
                    331: 
                    332:        closefunc = NULL;
                    333:        if (setjmp(recvabort))
                    334:                goto bad;
                    335:        oldintr = signal(SIGINT, abortrecv);
                    336:        if (strcmp(local, "-") && *local != '|')
                    337:                if (access(local, 2) < 0) {
                    338:                        char *dir = strrchr(local, '/');
                    339: 
                    340:                        if (dir != NULL)
                    341:                                *dir = 0;
                    342:                        if (access(dir ? dir : ".", 2) < 0) {
                    343:                                perror(local);
                    344:                                goto bad;
                    345:                        }
                    346:                        if (dir != NULL)
                    347:                                *dir = '/';
                    348:                }
                    349:        if (initconn())
                    350:                goto bad;
                    351:        if (remote) {
                    352:                if (command("%s %s", cmd, remote) != PRELIM)
                    353:                        goto bad;
                    354:        } else
                    355:                if (command("%s", cmd) != PRELIM)
                    356:                        goto bad;
                    357:        if (strcmp(local, "-") == 0)
                    358:                fout = stdout;
                    359:        else if (*local == '|') {
                    360:                fout = popen(local + 1, "w");
                    361:                closefunc = pclose;
                    362:        } else {
                    363:                fout = fopen(local, "w");
                    364:                closefunc = fclose;
                    365:        }
                    366:        if (fout == NULL) {
                    367:                perror(local + 1);
                    368:                goto bad;
                    369:        }
                    370:        din = dataconn("r");
                    371:        if (din == NULL)
                    372:                goto bad;
                    373:        ftime(&start);
                    374:        switch (type) {
                    375: 
                    376:        case TYPE_I:
                    377:        case TYPE_L:
                    378:                errno = 0;
                    379:                while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
                    380:                        if (write(fileno(fout), buf, c) < 0)
                    381:                                break;
                    382:                        bytes += c;
                    383:                }
                    384:                if (c < 0)
                    385:                        perror("netin");
                    386:                if (errno)
                    387:                        perror(local);
                    388:                break;
                    389: 
                    390:        case TYPE_A:
                    391:                while ((c = getc(din)) != EOF) {
                    392:                        if (c == '\r') {
                    393:                                bytes++;
                    394:                                if ((c = getc(din)) != '\n') {
                    395:                                        if (ferror (fout))
                    396:                                                break;
                    397:                                        putc ('\r', fout);
                    398:                                }
                    399:                                if (c == '\0') {
                    400:                                        bytes++;
                    401:                                        continue;
                    402:                                }
                    403:                        }
                    404:                        putc (c, fout);
                    405:                        bytes++;
                    406:                }
                    407:                if (ferror (din))
                    408:                        perror ("netin");
                    409:                if (ferror (fout))
                    410:                        perror (local);
                    411:                break;
                    412:        }
                    413:        ftime(&stop);
                    414:        (void) fclose(din);
                    415:        if (closefunc != NULL)
                    416:                (*closefunc)(fout);
                    417:        (void) getreply(0);
                    418: done:
                    419:        signal(SIGINT, oldintr);
                    420:        if (bytes > 0 && verbose)
                    421:                ptransfer("received", bytes, &start, &stop);
                    422:        return;
                    423: bad:
                    424:        if (data >= 0)
                    425:                (void) close(data), data = -1;
                    426:        if (closefunc != NULL && fout != NULL)
                    427:                (*closefunc)(fout);
                    428:        goto done;
                    429: }
                    430: 
                    431: /*
                    432:  * Need to start a listen on the data channel
                    433:  * before we send the command, otherwise the
                    434:  * server's connect may fail.
                    435:  */
                    436: initconn()
                    437: {
                    438:        int result;
                    439:        char *a, *p;
                    440:        in_addr hostorderaddr;
                    441:        tcp_port hostorderport;
                    442:        struct tcpuser tu;
                    443: 
                    444:        data = tcp_sock();
                    445:        if (data < 0) {
                    446:                perror("ftp: tcp_sock");
                    447:                return (1);
                    448:        }
                    449:        tu.lport = tu.fport = 0;
                    450:        tu.laddr = tu.faddr = 0;
                    451:        tu.param = 0;
                    452:        if (tcp_listen(data, &tu) < 0) {
                    453:                perror("ftp: tcp_listen");
                    454:                goto bad;
                    455:        }
                    456:        dataport = tu.lport;
                    457:        hostorderport = htons(dataport);
                    458:        hostorderaddr = htonl(myaddr);
                    459:        p = (char *)&hostorderport;
                    460:        a = (char *)&hostorderaddr;
                    461: #define        UC(b)   (((int)b)&0xff)
                    462:        result =
                    463:            command("PORT %d,%d,%d,%d,%d,%d",
                    464:              UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
                    465:              UC(p[0]), UC(p[1]));
                    466:        return (result != COMPLETE);
                    467: bad:
                    468:        (void) close(data), data = -1;
                    469:        return (1);
                    470: }
                    471: 
                    472: FILE *
                    473: dataconn(mode)
                    474:        char *mode;
                    475: {
                    476:        in_addr from_addr;
                    477:        tcp_port from_port;
                    478:        struct tcpuser tu;
                    479:        int s;
                    480: 
                    481:        tu.lport = tu.fport = 0;
                    482:        tu.laddr = tu.faddr = 0;
                    483:        tu.param = 0;
                    484:        s = tcp_accept(data, &tu);
                    485:        if (s < 0) {
                    486:                perror("ftp: accept");
                    487:                (void) close(data), data = -1;
                    488:                return (NULL);
                    489:        }
                    490:        (void) close(data);
                    491:        data = s;
                    492:        return (fdopen(data, mode));
                    493: }
                    494: 
                    495: ptransfer(direction, bytes, t0, t1)
                    496:        char *direction;
                    497:        int bytes;
                    498:        struct timeb *t0, *t1;
                    499: {
                    500:        struct timeb td;
                    501:        double ms, bs;
                    502: 
                    503:        tvsub(&td, t1, t0);
                    504:        ms = (td.time * 1000) + td.millitm;
                    505:        ms += 0.05;
                    506:        bs = bytes * 1000;
                    507:        bs = bs/(ms*1024.0);
                    508:        printf("%d bytes %s in %.3f seconds (%.2f Kbytes/s)\n",
                    509:                bytes, direction, ms/1000.0, bs);
                    510: }
                    511: 
                    512: tvadd(tsum, t0)
                    513:        struct timeb *tsum, *t0;
                    514: {
                    515: 
                    516:        tsum->time += t0->time;
                    517:        tsum->millitm += t0->millitm;
                    518:        if (tsum->time > 1000)
                    519:                tsum->time++, tsum->millitm -= 1000;
                    520: }
                    521: 
                    522: tvsub(tdiff, t1, t0)
                    523:        struct timeb *tdiff, *t1, *t0;
                    524: {
                    525: 
                    526:        tdiff->time = t1->time - t0->time;
                    527:        tdiff->millitm = t1->millitm - t0->millitm;
                    528:        if (tdiff->millitm < 0)
                    529:                tdiff->time--, tdiff->millitm += 1000;
                    530: }

unix.superglobalmegacorp.com

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