Annotation of cci/usr/src/ucb/ftp/ftp.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)ftp.c      4.11 (Berkeley) 7/26/83";
        !             3: #endif
        !             4: 
        !             5: #include <sys/param.h>
        !             6: #include <sys/stat.h>
        !             7: #include <sys/ioctl.h>
        !             8: #include <sys/socket.h>
        !             9: #include <sys/time.h>
        !            10: 
        !            11: #include <netinet/in.h>
        !            12: #include <arpa/ftp.h>
        !            13: 
        !            14: #include <stdio.h>
        !            15: #include <signal.h>
        !            16: #include <errno.h>
        !            17: #include <netdb.h>
        !            18: 
        !            19: #include "ftp_var.h"
        !            20: 
        !            21: struct sockaddr_in hisctladdr;
        !            22: struct sockaddr_in data_addr;
        !            23: int    data = -1;
        !            24: int    connected;
        !            25: struct sockaddr_in myctladdr;
        !            26: 
        !            27: FILE   *cin, *cout;
        !            28: FILE   *dataconn();
        !            29: 
        !            30: 
        !            31: /*
        !            32:        Changes made to this file :
        !            33: 
        !            34:        (1) recvrequest() :
        !            35:                a. Move the logic to check if the local file is successfully
        !            36:                   opened before sending the RETR cmd to remote server. Just 
        !            37:                   to make sure user ftp is ready to accept data from server
        !            38:                   before the RETR cmd is sent.
        !            39:                b. Add logic to report actual no of bytes received from server
        !            40:                   and actual size of new file. They are different because ftp
        !            41:                   user program strips '\n' characters.
        !            42:                c. Fix for 1st char. lost when print out error message to 
        !            43:                   indicate local cannot be opened.
        !            44:        
        !            45:                d. If you try to retrieve something into a local file, and you
        !            46:                   don't have the write permission on the file, it should test
        !            47:                   whether you have write permission on the directory contain-
        !            48:                   ing the file.  But, previously, if the local file is a path
        !            49:                   name containing slashes, it does a test on a null pathname
        !            50:                   rather than on the containing directory. This is wrong.
        !            51: 
        !            52:        (2) empty():    Peter P. 07/02/85
        !            53:                @  removed because no routine uses it. Peter P. 07/02/85
        !            54: 
        !            55:        (3) getreply(): Peter P. 07/02/85
        !            56:                a. Prevent the reply getter to get more replies than necessary.
        !            57:                   only one reply is gotten per call to this routine.
        !            58: */
        !            59: 
        !            60: struct hostent *
        !            61: hookup(host, port)
        !            62:        char *host;
        !            63:        int port;
        !            64: {
        !            65:        register struct hostent *hp;
        !            66:        int s, len;
        !            67: 
        !            68:        bzero((char *)&hisctladdr, sizeof (hisctladdr));
        !            69:        hp = gethostbyname(host);
        !            70:        if (hp == NULL) {
        !            71:                static struct hostent def;
        !            72:                static struct in_addr defaddr;
        !            73:                static char namebuf[128];
        !            74:                int inet_addr();
        !            75: 
        !            76:                defaddr.s_addr = inet_addr(host);
        !            77:                if (defaddr.s_addr == -1) {
        !            78:                        fprintf(stderr, "%s: Unknown host.\n", host);
        !            79:                        return (0);
        !            80:                }
        !            81:                strcpy(namebuf, host);
        !            82:                def.h_name = namebuf;
        !            83:                hostname = namebuf;
        !            84:                def.h_addr = (char *)&defaddr;
        !            85:                def.h_length = sizeof (struct in_addr);
        !            86:                def.h_addrtype = AF_INET;
        !            87:                def.h_aliases = 0;
        !            88:                hp = &def;
        !            89:        }
        !            90:        hostname = hp->h_name;
        !            91:        hisctladdr.sin_family = hp->h_addrtype;
        !            92:        s = socket(hp->h_addrtype, SOCK_STREAM, 0, 0);
        !            93:        if (s < 0) {
        !            94:                perror("ftp: socket");
        !            95:                return (0);
        !            96:        }
        !            97:        if (bind(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0) {
        !            98:                perror("ftp: bind");
        !            99:                goto bad;
        !           100:        }
        !           101:        bcopy(hp->h_addr, (char *)&hisctladdr.sin_addr, hp->h_length);
        !           102:        hisctladdr.sin_port = port;
        !           103:        if (connect(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0) {
        !           104:                perror("ftp: connect");
        !           105:                goto bad;
        !           106:        }
        !           107:        len = sizeof (myctladdr);
        !           108:        if (getsockname(s, (char *)&myctladdr, &len) < 0) {
        !           109:                perror("ftp: getsockname");
        !           110:                goto bad;
        !           111:        }
        !           112:        cin = fdopen(s, "r");
        !           113:        cout = fdopen(s, "w");
        !           114:        if (cin == NULL || cout == NULL) {
        !           115:                fprintf(stderr, "ftp: fdopen failed.\n");
        !           116:                if (cin)
        !           117:                        fclose(cin);
        !           118:                if (cout)
        !           119:                        fclose(cout);
        !           120:                goto bad;
        !           121:        }
        !           122:        if (verbose)
        !           123:                printf("Connected to %s.\n", hp->h_name);
        !           124:        (void) getreply(0);             /* read startup message from server */
        !           125:        return (hp);
        !           126: bad:
        !           127:        close(s);
        !           128:        return ((struct hostent *)0);
        !           129: }
        !           130: 
        !           131: login(hp)
        !           132:        struct hostent *hp;
        !           133: {
        !           134:        char acct[80];
        !           135:        char *user, *pass;
        !           136:        int n;
        !           137: 
        !           138:        user = pass = 0;
        !           139:        ruserpass(hp->h_name, &user, &pass);
        !           140:        n = command("USER %s", user);
        !           141:        if (n == CONTINUE)
        !           142:                n = command("PASS %s", pass);
        !           143:        if (n == CONTINUE) {
        !           144:                printf("Account: "); (void) fflush(stdout);
        !           145:                (void) fgets(acct, sizeof(acct) - 1, stdin);
        !           146:                acct[strlen(acct) - 1] = '\0';
        !           147:                n = command("ACCT %s", acct);
        !           148:        }
        !           149:        if (n != COMPLETE) {
        !           150:                fprintf(stderr, "Login failed.\n");
        !           151:                return (0);
        !           152:        }
        !           153:        return (1);
        !           154: }
        !           155: 
        !           156: /*VARARGS 1*/
        !           157: command(fmt, args)
        !           158:        char *fmt;
        !           159: {
        !           160: 
        !           161:        if (debug) {
        !           162:                printf("---> ");
        !           163:                _doprnt(fmt, &args, stdout);
        !           164:                printf("\n");
        !           165:                (void) fflush(stdout);
        !           166:        }
        !           167:        if (cout == NULL) {
        !           168:                perror ("No control connection for command");
        !           169:                return (0);
        !           170:        }
        !           171:        _doprnt(fmt, &args, cout);
        !           172:        fprintf(cout, "\r\n");
        !           173:        (void) fflush(cout);
        !           174:        return (getreply(!strcmp(fmt, "QUIT")));
        !           175: }
        !           176: 
        !           177: #include <ctype.h>
        !           178: 
        !           179: getreply(expecteof)
        !           180:        int expecteof;
        !           181: {
        !           182:        register int n;
        !           183:        register char c;
        !           184:        register int code, dig;
        !           185:        int originalcode = 0, continuation = 0;
        !           186: 
        !           187:        for (;;) {
        !           188:                dig = n = code = 0;
        !           189:                while ((c = getc(cin)) != '\n') {
        !           190:                        dig++;
        !           191:                        if (c == EOF) {
        !           192:                                if (expecteof)
        !           193:                                        return (0);
        !           194:                                lostpeer();
        !           195:                                exit(1);
        !           196:                        }
        !           197:                        if (verbose && c != '\r' ||
        !           198:                            (n == '5' && dig > 4))
        !           199:                                putchar(c);
        !           200:                        if (dig < 4 && isdigit(c))
        !           201:                                code = code * 10 + (c - '0');
        !           202:                        if (dig == 4 && c == '-')
        !           203:                                continuation++;
        !           204:                        if (n == 0)
        !           205:                                n = c;
        !           206:                }
        !           207:                if (verbose || n == '5') {
        !           208:                        putchar(c);
        !           209:                        (void) fflush (stdout);
        !           210:                }
        !           211:                if (continuation && code != originalcode) {
        !           212:                        if (originalcode == 0)
        !           213:                                originalcode = code;
        !           214:                        continue;
        !           215:                }
        !           216: /*             if (expecteof || empty(cin))    Peter 07/02/85 */
        !           217:                        return (n - '0');
        !           218:        }
        !           219: }
        !           220: 
        !           221: /*     not called by anyone anymore...         Peter P. 07/02/85
        !           222: empty(f)
        !           223:        FILE *f;
        !           224: {
        !           225:        long mask;
        !           226:        struct timeval t;
        !           227: 
        !           228:        if (f->_cnt > 0)
        !           229:                return (0);
        !           230:        mask = (1 << fileno(f));
        !           231:        t.tv_sec = t.tv_usec = 0;
        !           232:        (void) select(20, &mask, 0, 0, &t);
        !           233:        return (mask == 0);
        !           234: }
        !           235: */
        !           236: 
        !           237: jmp_buf        sendabort;
        !           238: 
        !           239: abortsend()
        !           240: {
        !           241: 
        !           242:        longjmp(sendabort, 1);
        !           243: }
        !           244: 
        !           245: sendrequest(cmd, local, remote)
        !           246:        char *cmd, *local, *remote;
        !           247: {
        !           248:        FILE *fin, *dout, *popen();
        !           249:        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
        !           250:        char buf[BUFSIZ];
        !           251:        long bytes = 0, hashbytes = sizeof (buf);
        !           252:        long wscnt = 0;
        !           253:        register int c, d;
        !           254:        struct stat st;
        !           255:        struct timeval start, stop;
        !           256: 
        !           257:        closefunc = NULL;
        !           258:        if (setjmp(sendabort))
        !           259:                goto bad;
        !           260:        oldintr = signal(SIGINT, abortsend);
        !           261:        if (strcmp(local, "-") == 0)
        !           262:                fin = stdin;
        !           263:        else if (*local == '|') {
        !           264:                fin = popen(local + 1, "r");
        !           265:                if (fin == NULL) {
        !           266:                        perror(local + 1);
        !           267:                        goto bad;
        !           268:                }
        !           269:                closefunc = pclose;
        !           270:        } else {
        !           271:                fin = fopen(local, "r");
        !           272:                if (fin == NULL) {
        !           273:                        perror(local);
        !           274:                        goto bad;
        !           275:                }
        !           276:                closefunc = fclose;
        !           277:                if (fstat(fileno(fin), &st) < 0 ||
        !           278:                    (st.st_mode&S_IFMT) != S_IFREG) {
        !           279:                        fprintf(stderr, "%s: not a plain file.", local);
        !           280:                        goto bad;
        !           281:                }
        !           282:        }
        !           283:        if (initconn())
        !           284:                goto bad;
        !           285:        if (remote) {
        !           286:                if (command("%s %s", cmd, remote) != PRELIM)
        !           287:                        goto bad;
        !           288:        } else
        !           289:                if (command("%s", cmd) != PRELIM)
        !           290:                        goto bad;
        !           291:        dout = dataconn("w");
        !           292:        if (dout == NULL)
        !           293:                goto bad;
        !           294:        gettimeofday(&start, (struct timezone *)0);
        !           295:        switch (type) {
        !           296: 
        !           297:        case TYPE_I:
        !           298:        case TYPE_L:
        !           299:                errno = d = 0;
        !           300:                while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
        !           301:                        if ((d = write(fileno (dout), buf, c)) < 0)
        !           302:                                break;
        !           303:                        bytes += c;
        !           304:                        if (hash) {
        !           305:                                putchar('#');
        !           306:                                fflush(stdout);
        !           307:                        }
        !           308:                }
        !           309:                wscnt = bytes;
        !           310:                if (hash && bytes > 0) {
        !           311:                        putchar('\n');
        !           312:                        fflush(stdout);
        !           313:                }
        !           314:                if (c < 0)
        !           315:                        perror(local);
        !           316:                if (d < 0)
        !           317:                        perror("netout");
        !           318:                break;
        !           319: 
        !           320:        case TYPE_A:
        !           321:                while ((c = getc(fin)) != EOF) {
        !           322:                        wscnt++;
        !           323:                        if (c == '\n') {
        !           324:                                while (hash && (bytes >= hashbytes)) {
        !           325:                                        putchar('#');
        !           326:                                        fflush(stdout);
        !           327:                                        hashbytes += sizeof (buf);
        !           328:                                }
        !           329:                                if (ferror(dout))
        !           330:                                        break;
        !           331:                                putc('\r', dout);
        !           332:                                bytes++;
        !           333:                        }
        !           334:                        putc(c, dout);
        !           335:                        bytes++;
        !           336:                        if (c == '\r') {
        !           337:                                putc('\0', dout);
        !           338:                                bytes++;
        !           339:                        }
        !           340:                }
        !           341:                if (hash) {
        !           342:                        if (bytes < hashbytes)
        !           343:                                putchar('#');
        !           344:                        putchar('\n');
        !           345:                        fflush(stdout);
        !           346:                }
        !           347:                if (ferror(fin))
        !           348:                        perror(local);
        !           349:                if (ferror(dout))
        !           350:                        perror("netout");
        !           351:                break;
        !           352:        }
        !           353:        if (closefunc != NULL)
        !           354:                (*closefunc)(fin);
        !           355:        (void) fclose(dout);
        !           356:        (void) getreply(0);
        !           357: done:
        !           358:        gettimeofday(&stop, (struct timezone *)0);
        !           359:        signal(SIGINT, oldintr);
        !           360:        if (bytes > 0 && verbose) { 
        !           361:                if (fin != stdin)
        !           362:                        printf("Actual size of %s is %d bytes\n", local, wscnt);
        !           363:                ptransfer("sent", bytes, &start, &stop);
        !           364:        }
        !           365:        return;
        !           366: bad:
        !           367:        if (data >= 0)
        !           368:                (void) close(data), data = -1;
        !           369:        if (closefunc != NULL && fin != NULL)
        !           370:                (*closefunc)(fin);
        !           371:        goto done;
        !           372: }
        !           373: 
        !           374: jmp_buf        recvabort;
        !           375: 
        !           376: abortrecv()
        !           377: {
        !           378: 
        !           379:        longjmp(recvabort, 1);
        !           380: }
        !           381: 
        !           382: recvrequest(cmd, local, remote, mode)
        !           383:        char *cmd, *local, *remote, *mode;
        !           384: {
        !           385:        FILE *fout, *din, *popen();
        !           386:        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
        !           387:        char buf[BUFSIZ];
        !           388:        long wrcnt = 0;
        !           389:        long bytes = 0, hashbytes = sizeof (buf);
        !           390:        register int c, d;
        !           391:        struct timeval start, stop;
        !           392: 
        !           393:        din = NULL;
        !           394:        closefunc = NULL;
        !           395:        if (setjmp(recvabort))
        !           396:                goto bad;
        !           397:        oldintr = signal(SIGINT, abortrecv);
        !           398:        if (strcmp(local, "-") && *local != '|')
        !           399:                if (access(local, 2) < 0) {
        !           400:                    if (errno == ENOENT) {
        !           401:                        char *dir = rindex(local, '/');
        !           402: 
        !           403:                        if (dir != NULL)
        !           404:                                *dir = 0;
        !           405:                        if (access(dir ? local : ".", 2) < 0) {
        !           406:                                perror(local);
        !           407:                                goto bad;
        !           408:                        }
        !           409:                        if (dir != NULL)
        !           410:                                *dir = '/';
        !           411:                   } 
        !           412:                   else {
        !           413:                        perror(local);
        !           414:                        goto bad;
        !           415:                   }
        !           416:                }
        !           417:        if (strcmp(local, "-") == 0)
        !           418:                fout = stdout;
        !           419:        else if (*local == '|') {
        !           420:                fout = popen(local + 1, "w");
        !           421:                closefunc = pclose;
        !           422:        } else {
        !           423:                fout = fopen(local, mode);
        !           424:                closefunc = fclose;
        !           425:        }
        !           426:        if (fout == NULL) {
        !           427:                if (*local == '|') perror(local + 1);
        !           428:                        else perror(local);
        !           429:                goto bad;
        !           430:        }
        !           431:        if (initconn())
        !           432:                goto bad;
        !           433:        if (remote) {
        !           434:                if (command("%s %s", cmd, remote) != PRELIM)
        !           435:                        goto bad;
        !           436:        } else
        !           437:                if (command("%s", cmd) != PRELIM)
        !           438:                        goto bad;
        !           439:        din = dataconn("r");
        !           440:        if (din == NULL)
        !           441:                goto bad;
        !           442:        gettimeofday(&start, (struct timezone *)0);
        !           443:        switch (type) {
        !           444: 
        !           445:        case TYPE_I:
        !           446:        case TYPE_L:
        !           447:                errno = d = 0;
        !           448:                while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
        !           449:                        if ((d = write(fileno(fout), buf, c)) < 0)
        !           450:                                break;
        !           451:                        bytes += d;
        !           452:                        if (hash) {
        !           453:                                putchar('#');
        !           454:                                fflush(stdout);
        !           455:                        }
        !           456:                }
        !           457:                wrcnt = bytes;
        !           458:                if (hash && bytes > 0) {
        !           459:                        putchar('\n');
        !           460:                        fflush(stdout);
        !           461:                }
        !           462:                if (c < 0)
        !           463:                        perror("netin");
        !           464:                if (d < 0)
        !           465:                        perror(local);
        !           466:                break;
        !           467: 
        !           468:        case TYPE_A:
        !           469:                while ((c = getc(din)) != EOF) {
        !           470:                        bytes++;
        !           471:                        if (c == '\r') {
        !           472:                                while (hash && (bytes >= hashbytes)) {
        !           473:                                        putchar('#');
        !           474:                                        fflush(stdout);
        !           475:                                        hashbytes += sizeof (buf);
        !           476:                                }
        !           477:                                c = getc(din);
        !           478:                                bytes++;
        !           479:                                if (c != '\n') {
        !           480:                                        if (ferror (fout))
        !           481:                                                break;
        !           482:                                        putc ('\r', fout);
        !           483:                                        wrcnt++;
        !           484:                                }
        !           485:                                if (c == '\0') {
        !           486:                                        continue;
        !           487:                                }
        !           488:                        }
        !           489:                        putc (c, fout);
        !           490:                        wrcnt++;
        !           491:                }
        !           492:                if (hash) {
        !           493:                        if (bytes < hashbytes)
        !           494:                                putchar('#');
        !           495:                        putchar('\n');
        !           496:                        fflush(stdout);
        !           497:                }
        !           498:                if (ferror (din))
        !           499:                        perror ("netin");
        !           500:                if (ferror (fout))
        !           501:                        perror (local);
        !           502:                break;
        !           503:        }
        !           504:        (void) fclose(din);
        !           505:        if (closefunc != NULL)
        !           506:                (*closefunc)(fout);
        !           507:        (void) getreply(0);
        !           508: done:
        !           509:        gettimeofday(&stop, (struct timezone *)0);
        !           510:        signal(SIGINT, oldintr);
        !           511:        if (bytes > 0 && verbose) {
        !           512:                ptransfer("received", bytes, &start, &stop);
        !           513:                if (fout != stdout)
        !           514:                        printf("Actual size of %s is %d bytes\n", local, wrcnt);
        !           515:        }
        !           516:        return;
        !           517: bad:
        !           518:        if (data >= 0) {
        !           519: /*
        !           520: /*             if (din != NULL) {
        !           521: /*                     printf("\nstart drainning..\n");
        !           522: /*                     if (!empty(din))
        !           523: /*                             for(;;) { c=getc(din);
        !           524: /*                                     if (c == EOF) break;
        !           525: /*                             }
        !           526: /*             }
        !           527: /*             (void) getreply(0);
        !           528: /**/
        !           529:                (void) close(data), data = -1;
        !           530:        }
        !           531:        if (closefunc != NULL && fout != NULL)
        !           532:                (*closefunc)(fout);
        !           533:        goto done;
        !           534: }
        !           535: 
        !           536: /*
        !           537:  * Need to start a listen on the data channel
        !           538:  * before we send the command, otherwise the
        !           539:  * server's connect may fail.
        !           540:  */
        !           541: static int sendport = -1;
        !           542: 
        !           543: initconn()
        !           544: {
        !           545:        register char *p, *a;
        !           546:        int result, len;
        !           547: 
        !           548: noport:
        !           549:        data_addr = myctladdr;
        !           550:        if (sendport)
        !           551:                data_addr.sin_port = 0; /* let system pick one */ 
        !           552:        if (data != -1)
        !           553:                (void) close (data);
        !           554:        data = socket(AF_INET, SOCK_STREAM, 0, 0);
        !           555:        if (data < 0) {
        !           556:                perror("ftp: socket");
        !           557:                return (1);
        !           558:        }
        !           559:        if (!sendport)
        !           560:                if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) {
        !           561:                        perror("ftp: setsockopt (resuse address)");
        !           562:                        goto bad;
        !           563:                }
        !           564:        if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) {
        !           565:                perror("ftp: bind");
        !           566:                goto bad;
        !           567:        }
        !           568:        if (options & SO_DEBUG &&
        !           569:            setsockopt(data, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
        !           570:                perror("ftp: setsockopt (ignored)");
        !           571:        len = sizeof (data_addr);
        !           572:        if (getsockname(data, (char *)&data_addr, &len) < 0) {
        !           573:                perror("ftp: getsockname");
        !           574:                goto bad;
        !           575:        }
        !           576:        if (listen(data, 1) < 0) {
        !           577:                perror("ftp: listen");
        !           578:                goto bad;
        !           579:        }
        !           580:        if (sendport) {
        !           581:                a = (char *)&data_addr.sin_addr;
        !           582:                p = (char *)&data_addr.sin_port;
        !           583: #define        UC(b)   (((int)b)&0xff)
        !           584:                result =
        !           585:                    command("PORT %d,%d,%d,%d,%d,%d",
        !           586:                      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
        !           587:                      UC(p[0]), UC(p[1]));
        !           588:                if (result == ERROR && sendport == -1) {
        !           589:                        sendport = 0;
        !           590:                        goto noport;
        !           591:                }
        !           592:                return (result != COMPLETE);
        !           593:        }
        !           594:        return (0);
        !           595: bad:
        !           596:        (void) close(data), data = -1;
        !           597:        return (1);
        !           598: }
        !           599: 
        !           600: FILE *
        !           601: dataconn(mode)
        !           602:        char *mode;
        !           603: {
        !           604:        struct sockaddr_in from;
        !           605:        int s, fromlen = sizeof (from);
        !           606: 
        !           607:        s = accept(data, &from, &fromlen, 0);
        !           608:        if (s < 0) {
        !           609:                perror("ftp: accept");
        !           610:                (void) close(data), data = -1;
        !           611:                return (NULL);
        !           612:        }
        !           613:        (void) close(data);
        !           614:        data = s;
        !           615:        return (fdopen(data, mode));
        !           616: }
        !           617: 
        !           618: ptransfer(direction, bytes, t0, t1)
        !           619:        char *direction;
        !           620:        long bytes;
        !           621:        struct timeval *t0, *t1;
        !           622: {
        !           623:        struct timeval td;
        !           624:        long ms;
        !           625:        float bs;
        !           626: 
        !           627:        tvsub(&td, t1, t0);
        !           628:        ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
        !           629: #define        nz(x)   ((x) == 0 ? 1 : (x))
        !           630:        bs = ((bytes * NBBY * 1000) / (float) nz(ms)) / NBBY;
        !           631:        printf("%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n",
        !           632:                bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.);
        !           633: }
        !           634: 
        !           635: tvadd(tsum, t0)
        !           636:        struct timeval *tsum, *t0;
        !           637: {
        !           638: 
        !           639:        tsum->tv_sec += t0->tv_sec;
        !           640:        tsum->tv_usec += t0->tv_usec;
        !           641:        if (tsum->tv_usec > 1000000)
        !           642:                tsum->tv_sec++, tsum->tv_usec -= 1000000;
        !           643: }
        !           644: 
        !           645: tvsub(tdiff, t1, t0)
        !           646:        struct timeval *tdiff, *t1, *t0;
        !           647: {
        !           648: 
        !           649:        tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
        !           650:        tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
        !           651:        if (tdiff->tv_usec < 0)
        !           652:                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
        !           653: }

unix.superglobalmegacorp.com

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