Annotation of 43BSDReno/usr.sbin/named/db_dump.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted provided
        !             6:  * that: (1) source distributions retain this entire copyright notice and
        !             7:  * comment, and (2) distributions including binaries display the following
        !             8:  * acknowledgement:  ``This product includes software developed by the
        !             9:  * University of California, Berkeley and its contributors'' in the
        !            10:  * documentation or other materials provided with the distribution and in
        !            11:  * all advertising materials mentioning features or use of this software.
        !            12:  * Neither the name of the University nor the names of its contributors may
        !            13:  * be used to endorse or promote products derived from this software without
        !            14:  * specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: static char sccsid[] = "@(#)db_dump.c  4.30 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include <sys/param.h>
        !            25: #include <sys/time.h>
        !            26: #include <sys/stat.h>
        !            27: #include <netinet/in.h>
        !            28: #include <netdb.h>
        !            29: #include <stdio.h>
        !            30: #include <syslog.h>
        !            31: #include <arpa/nameser.h>
        !            32: #include "ns.h"
        !            33: #include "db.h"
        !            34: #include "pathnames.h"
        !            35: 
        !            36: extern char *p_type(), *p_class();
        !            37: 
        !            38: #ifdef DUMPFILE
        !            39: char   *dumpfile = DUMPFILE;
        !            40: #else
        !            41: char   *dumpfile = _PATH_DUMPFILE;
        !            42: #endif
        !            43: 
        !            44: extern char *cache_file;
        !            45: 
        !            46: /*
        !            47:  * Dump current cache in a format similar to RFC 883.
        !            48:  *
        !            49:  * We try to be careful and determine whether the operation succeeded
        !            50:  * so that the new cache file can be installed.
        !            51:  */
        !            52: 
        !            53: #define DB_ROOT_TIMBUF 3600
        !            54: 
        !            55: doachkpt()
        !            56: {
        !            57:     extern int errno;
        !            58:     FILE *fp;
        !            59:     char tmpcheckfile[256];
        !            60: 
        !            61:     /* nowhere to checkpoint cache... */
        !            62:     if (cache_file == NULL) {
        !            63: #ifdef DEBUG
        !            64:         if (debug >= 3)
        !            65:             fprintf(ddt,"doachkpt(to where?)\n");
        !            66: #endif
        !            67:         return;
        !            68:     }
        !            69: 
        !            70: #ifdef DEBUG
        !            71:     if (debug >= 3)
        !            72:         fprintf(ddt,"doachkpt()\n");
        !            73: #endif
        !            74: 
        !            75:     (void) sprintf(tmpcheckfile, "%s.chk", cache_file);
        !            76:     if ((fp = fopen(tmpcheckfile, "w")) == NULL) {
        !            77: #ifdef DEBUG
        !            78:         if (debug >= 3)
        !            79:             fprintf(ddt,"doachkpt(can't open %s for write)\n", tmpcheckfile);
        !            80: #endif
        !            81:         return;
        !            82:     }
        !            83: 
        !            84:     (void) gettime(&tt);
        !            85:     fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
        !            86:     fflush(fp);
        !            87:     if (ferror(fp)) {
        !            88: #ifdef DEBUG
        !            89:         if (debug >= 3)
        !            90:             fprintf(ddt,"doachkpt(write to checkpoint file failed)\n");
        !            91: #endif
        !            92:         return;
        !            93:     }
        !            94: 
        !            95:     if (fcachetab != NULL) {
        !            96:        int n;
        !            97:        if ((n = scan_root(hashtab)) < MINROOTS) {
        !            98:            syslog(LOG_ERR, "%d root hints... (too low)", n);
        !            99:            fprintf(fp, "; ---- Root hint cache dump ----\n");
        !           100:            (void) db_dump(fcachetab, fp, DB_Z_CACHE, "");
        !           101:        }
        !           102:     }
        !           103: 
        !           104:     if (hashtab != NULL) {
        !           105:         fprintf(fp, "; ---- Cache dump ----\n");
        !           106:         if (db_dump(hashtab, fp, DB_Z_CACHE, "") == NODBFILE) {
        !           107: #ifdef DEBUG
        !           108:             if (debug >= 3)
        !           109:                 fprintf(ddt,"doachkpt(checkpoint failed)\n");
        !           110: #endif
        !           111:             (void) fclose(fp);
        !           112:             return;
        !           113:         }
        !           114:     }
        !           115: 
        !           116:     (void) fsync(fileno(fp));
        !           117:     if (fclose(fp) == EOF) {
        !           118: #ifdef DEBUG
        !           119:         if (debug >= 3)
        !           120:             fprintf(ddt,"doachkpt(close failed)\n");
        !           121: #endif
        !           122:         return;
        !           123:     }
        !           124: 
        !           125:     if (rename(tmpcheckfile, cache_file)) {
        !           126: #ifdef DEBUG
        !           127:         if (debug >= 3)
        !           128:             fprintf(ddt,"doachkpt(install %s to %s failed, %d)\n",
        !           129:                     tmpcheckfile,cache_file, errno);
        !           130: #endif
        !           131:     }
        !           132: }
        !           133: 
        !           134: /*
        !           135:  * What we do is scan the root hint cache to make sure there are at least
        !           136:  * MINROOTS root pointers with non-0 TTL's so that the checkpoint will not
        !           137:  * lose the root.  Failing this, all pointers are written out w/ TTL ~0
        !           138:  * (root pointers timed out and prime_cache() not done or failed).
        !           139:  */
        !           140: #define TIMBUF 300
        !           141: 
        !           142: int
        !           143: scan_root(htp)
        !           144:        struct hashbuf *htp;
        !           145: {
        !           146:        register struct databuf *dp;
        !           147:        register struct namebuf *np;
        !           148:        struct timeval soon;
        !           149:        int roots = 0;
        !           150: 
        !           151: #ifdef DEBUG
        !           152:        if (debug)
        !           153:                fprintf(ddt,"scan_root(0x%x)\n", htp);
        !           154: #endif
        !           155: 
        !           156:        /* metric by which we determine whether a root NS pointer is still */
        !           157:        /* valid (will be written out if we do a dump).  we also add some */
        !           158:        /* time buffer for safety... */
        !           159:        (void) gettime(&soon);
        !           160:        soon.tv_sec += TIMBUF;
        !           161: 
        !           162:        for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
        !           163:                if (np->n_dname[0] == '\0') {
        !           164:                        dp = np->n_data;
        !           165:                        while (dp != NULL) {
        !           166:                                if (dp->d_type == T_NS &&
        !           167:                                    dp->d_ttl > soon.tv_sec) {
        !           168:                                        roots++;
        !           169:                                        if (roots >= MINROOTS)
        !           170:                                                return (roots);
        !           171:                                }
        !           172:                                dp = dp->d_next;
        !           173:                        }
        !           174:                }
        !           175:        }
        !           176:        return (roots);
        !           177: }
        !           178: 
        !           179: #ifdef notdef
        !           180: mark_cache(htp, ttl)
        !           181:     struct hashbuf *htp;
        !           182:     int ttl;
        !           183: {
        !           184:     register struct databuf *dp;
        !           185:     register struct namebuf *np;
        !           186:     struct namebuf **npp, **nppend;
        !           187:     struct timeval soon;
        !           188: 
        !           189: #ifdef DEBUG
        !           190:     if (debug)
        !           191:         fprintf(ddt,"mark_cache()\n");
        !           192: #endif
        !           193: 
        !           194:     (void) gettime(&soon);
        !           195:     soon.tv_sec += TIMBUF;
        !           196: 
        !           197:     npp = htp->h_tab;
        !           198:     nppend = npp + htp->h_size;
        !           199:     while (npp < nppend) {
        !           200:         for (np = *npp++; np != NULL; np = np->n_next) {
        !           201:             if (np->n_data == NULL)
        !           202:                 continue;
        !           203:             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
        !           204:                 if (dp->d_ttl < soon.tv_sec)
        !           205:                     dp->d_ttl = ttl;
        !           206:             }
        !           207:         }
        !           208:     }
        !           209: 
        !           210:     npp = htp->h_tab;
        !           211:     nppend = npp + htp->h_size;
        !           212:     while (npp < nppend) {
        !           213:         for (np = *npp++; np != NULL; np = np->n_next) {
        !           214:             if (np->n_hash == NULL)
        !           215:                 continue;
        !           216:             mark_cache(np->n_hash, ttl);
        !           217:         }
        !           218:     }
        !           219: }
        !           220: #endif notdef
        !           221: 
        !           222: /*
        !           223:  * Dump current data base in a format similar to RFC 883.
        !           224:  */
        !           225: 
        !           226: doadump()
        !           227: {
        !           228:        FILE    *fp;
        !           229: 
        !           230: #ifdef DEBUG
        !           231:        if (debug >= 3)
        !           232:                fprintf(ddt,"doadump()\n");
        !           233: #endif
        !           234: 
        !           235:        if ((fp = fopen(dumpfile, "w")) == NULL)
        !           236:                return;
        !           237:        gettime(&tt);
        !           238:        fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
        !           239:        fprintf(fp, "; --- Cache & Data ---\n");
        !           240:        if (hashtab != NULL)
        !           241:                (void) db_dump(hashtab, fp, DB_Z_ALL, "");
        !           242:        fprintf(fp, "; --- Hints ---\n");
        !           243:        if (fcachetab != NULL)
        !           244:                (void) db_dump(fcachetab, fp, DB_Z_ALL, "");
        !           245:        (void) fclose(fp);
        !           246: }
        !           247: 
        !           248: #ifdef ALLOW_UPDATES
        !           249: /* Create a disk database to back up zones 
        !           250:  */
        !           251: zonedump(zp)
        !           252:     register struct zoneinfo *zp;
        !           253: {
        !           254:        FILE    *fp;
        !           255:        char *fname;
        !           256:        struct hashbuf *htp;
        !           257:        char *op;
        !           258:        struct stat st;
        !           259: 
        !           260:        /* Only dump zone if there is a cache specified */
        !           261:        if (zp->z_source && *(zp->z_source)) {
        !           262: #ifdef DEBUG
        !           263:            if (debug)
        !           264:                    fprintf(ddt, "zonedump(%s)\n", zp->z_source);
        !           265: #endif
        !           266: 
        !           267:            if ((fp = fopen(zp->z_source, "w")) == NULL)
        !           268:                    return;
        !           269:            if (op = index(zp->z_origin, '.'))
        !           270:                op++;
        !           271:            gettime(&tt);
        !           272:            htp = hashtab;
        !           273:            if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) {
        !           274:                    db_dump(htp, fp, zp-zones, (op == NULL ? "" : op));
        !           275: #ifdef ALLOW_UPDATES
        !           276:                    zp->hasChanged = 0;         /* Checkpointed */
        !           277: #endif ALLOW_UPDATES
        !           278:            }
        !           279:            (void) fclose(fp);
        !           280:            if (stat(zp->z_source, &st) == 0)
        !           281:                    zp->z_ftime = st.st_mtime;
        !           282:        }
        !           283: #ifdef DEBUG
        !           284:            else if (debug)
        !           285:                fprintf(ddt, "zonedump: no zone to dump\n");
        !           286: #endif
        !           287: }
        !           288: #endif
        !           289: 
        !           290: int
        !           291: db_dump(htp, fp, zone, origin)
        !           292:        int zone;
        !           293:        struct hashbuf *htp;
        !           294:        FILE *fp;
        !           295:        char *origin;
        !           296: {
        !           297:        register struct databuf *dp;
        !           298:        register struct namebuf *np;
        !           299:        struct namebuf **npp, **nppend;
        !           300:        char dname[MAXDNAME];
        !           301:        u_long n;
        !           302:        u_long addr;
        !           303:        u_short i;
        !           304:        int j;
        !           305:        register u_char *cp;
        !           306:        u_char *end;
        !           307:        char *proto;
        !           308:        extern char *inet_ntoa(), *protocolname(), *servicename();
        !           309:        int found_data, tab, printed_origin = 0;
        !           310: 
        !           311:        npp = htp->h_tab;
        !           312:        nppend = npp + htp->h_size;
        !           313:        while (npp < nppend) {
        !           314:            for (np = *npp++; np != NULL; np = np->n_next) {
        !           315:                if (np->n_data == NULL)
        !           316:                        continue;
        !           317:                /* Blecch - can't tell if there is data here for the
        !           318:                 * right zone, so can't print name yet
        !           319:                 */
        !           320:                found_data = 0;
        !           321:                /* we want a snapshot in time... */
        !           322:                for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
        !           323:                        /* Is the data for this zone? */
        !           324:                        if (zone != DB_Z_ALL && dp->d_zone != zone)
        !           325:                            continue;
        !           326:                        if (dp->d_zone == DB_Z_CACHE &&
        !           327:                            dp->d_ttl <= tt.tv_sec &&
        !           328:                            (dp->d_flags & DB_F_HINT) == 0)
        !           329:                                continue;
        !           330:                        if (!printed_origin) {
        !           331:                            fprintf(fp, "$ORIGIN %s.\n", origin);
        !           332:                            printed_origin++;
        !           333:                        }
        !           334:                        tab = 0;
        !           335:                        if (!found_data) {
        !           336:                            if (np->n_dname[0] == 0) {
        !           337:                                if (origin[0] == 0)
        !           338:                                    fprintf(fp, ".\t");
        !           339:                                else
        !           340:                                    fprintf(fp, ".%s.\t", origin); /* ??? */
        !           341:                            } else
        !           342:                                fprintf(fp, "%s\t", np->n_dname);
        !           343:                            if (strlen(np->n_dname) < 8)
        !           344:                                tab = 1;
        !           345:                            found_data++;
        !           346:                        } else {
        !           347:                            (void) putc('\t', fp);
        !           348:                            tab = 1;
        !           349:                        }
        !           350:                        if (dp->d_zone == DB_Z_CACHE) {
        !           351:                            if (dp->d_flags & DB_F_HINT &&
        !           352:                                (long)(dp->d_ttl - tt.tv_sec) < DB_ROOT_TIMBUF)
        !           353:                                    fprintf(fp, "%d\t", DB_ROOT_TIMBUF);
        !           354:                            else
        !           355:                                    fprintf(fp, "%d\t",
        !           356:                                        (int)(dp->d_ttl - tt.tv_sec));
        !           357:                        } else if (dp->d_ttl != 0 &&
        !           358:                            dp->d_ttl != zones[dp->d_zone].z_minimum)
        !           359:                                fprintf(fp, "%d\t", (int)dp->d_ttl);
        !           360:                        else if (tab)
        !           361:                            (void) putc('\t', fp);
        !           362:                        fprintf(fp, "%s\t%s\t", p_class(dp->d_class),
        !           363:                                p_type(dp->d_type));
        !           364:                        cp = (u_char *)dp->d_data;
        !           365:                        /*
        !           366:                         * Print type specific data
        !           367:                         */
        !           368:                        switch (dp->d_type) {
        !           369:                        case T_A:
        !           370:                                switch (dp->d_class) {
        !           371:                                case C_IN:
        !           372:                                case C_HS:
        !           373:                                        GETLONG(n, cp);
        !           374:                                        n = htonl(n);
        !           375:                                        fprintf(fp, "%s",
        !           376:                                           inet_ntoa(*(struct in_addr *)&n));
        !           377:                                        break;
        !           378:                                }
        !           379:                                if (dp->d_nstime)
        !           380:                                        fprintf(fp, "\t; %d", dp->d_nstime);
        !           381:                                fprintf(fp, "\n");
        !           382:                                break;
        !           383:                        case T_CNAME:
        !           384:                        case T_MB:
        !           385:                        case T_MG:
        !           386:                        case T_MR:
        !           387:                        case T_PTR:
        !           388:                                if (cp[0] == '\0')
        !           389:                                        fprintf(fp, ".\n");
        !           390:                                else
        !           391:                                        fprintf(fp, "%s.\n", cp);
        !           392:                                break;
        !           393: 
        !           394:                        case T_NS:
        !           395:                                cp = (u_char *)dp->d_data;
        !           396:                                if (cp[0] == '\0')
        !           397:                                        fprintf(fp, ".\t");
        !           398:                                else
        !           399:                                        fprintf(fp, "%s.", cp);
        !           400:                                if (dp->d_nstime)
        !           401:                                        fprintf(fp, "\t; %d???", dp->d_nstime);
        !           402:                                fprintf(fp, "\n");
        !           403:                                break;
        !           404: 
        !           405:                        case T_HINFO:
        !           406:                                if (n = *cp++) {
        !           407:                                        fprintf(fp, "\"%.*s\"", (int)n, cp);
        !           408:                                        cp += n;
        !           409:                                } else
        !           410:                                        fprintf(fp, "\"\"");
        !           411:                                if (n = *cp++)
        !           412:                                        fprintf(fp, " \"%.*s\"", (int)n, cp);
        !           413:                                else
        !           414:                                        fprintf(fp, " \"\"");
        !           415:                                (void) putc('\n', fp);
        !           416:                                break;
        !           417: 
        !           418:                        case T_SOA:
        !           419:                                fprintf(fp, "%s.", cp);
        !           420:                                cp += strlen(cp) + 1;
        !           421:                                fprintf(fp, " %s. (\n", cp);
        !           422:                                cp += strlen(cp) + 1;
        !           423:                                GETLONG(n, cp);
        !           424:                                fprintf(fp, "\t\t%lu", n);
        !           425:                                GETLONG(n, cp);
        !           426:                                fprintf(fp, " %lu", n);
        !           427:                                GETLONG(n, cp);
        !           428:                                fprintf(fp, " %lu", n);
        !           429:                                GETLONG(n, cp);
        !           430:                                fprintf(fp, " %lu", n);
        !           431:                                GETLONG(n, cp);
        !           432:                                fprintf(fp, " %lu )\n", n);
        !           433:                                break;
        !           434: 
        !           435:                        case T_MX:
        !           436:                                GETSHORT(n, cp);
        !           437:                                fprintf(fp,"%lu", n);
        !           438:                                fprintf(fp," %s.\n", cp);
        !           439:                                break;
        !           440: 
        !           441:                        case T_TXT:
        !           442:                                end = (u_char *)dp->d_data + dp->d_size;
        !           443:                                (void) putc('"', fp);
        !           444:                                while (cp < end) {
        !           445:                                    if (n = *cp++) {
        !           446:                                        for (j = n ; j > 0 && cp < end ; j--)
        !           447:                                            if (*cp == '\n') {
        !           448:                                                (void) putc('\\', fp);
        !           449:                                                (void) putc(*cp++, fp);
        !           450:                                            } else
        !           451:                                                (void) putc(*cp++, fp);
        !           452:                                    }
        !           453:                                }
        !           454:                                (void) fputs("\"\n", fp);
        !           455:                                break;
        !           456: 
        !           457:                        case T_UINFO:
        !           458:                                fprintf(fp, "\"%s\"\n", cp);
        !           459:                                break;
        !           460: 
        !           461:                        case T_UID:
        !           462:                        case T_GID:
        !           463:                                if (dp->d_size == sizeof(u_long)) {
        !           464:                                        GETLONG(n, cp);
        !           465:                                        fprintf(fp, "%lu\n", n);
        !           466:                                }
        !           467:                                break;
        !           468: 
        !           469:                        case T_WKS:
        !           470:                                GETLONG(addr, cp);      
        !           471:                                addr = htonl(addr);     
        !           472:                                fprintf(fp,"%s ",
        !           473:                                    inet_ntoa(*(struct in_addr *)&addr));
        !           474:                                proto = protocolname(*cp);
        !           475:                                cp += sizeof(char); 
        !           476:                                fprintf(fp, "%s ", proto);
        !           477:                                i = 0;
        !           478:                                while(cp < (u_char *)dp->d_data + dp->d_size) {
        !           479:                                        j = *cp++;
        !           480:                                        do {
        !           481:                                            if (j & 0200)
        !           482:                                                fprintf(fp," %s",
        !           483:                                                   servicename(i, proto));
        !           484:                                            j <<= 1;
        !           485:                                        } while(++i & 07);
        !           486:                                } 
        !           487:                                fprintf(fp,"\n");
        !           488:                                break;
        !           489: 
        !           490:                        case T_MINFO:
        !           491:                                fprintf(fp, "%s.", cp);
        !           492:                                cp += strlen(cp) + 1;
        !           493:                                fprintf(fp, " %s.\n", cp);
        !           494:                                break;
        !           495: #ifdef ALLOW_T_UNSPEC
        !           496:                        case T_UNSPEC:
        !           497:                                /* Dump binary data out in an ASCII-encoded
        !           498:                                   format */
        !           499:                                {
        !           500:                                        /* Allocate more than enough space:
        !           501:                                         *  actually need 5/4 size + 20 or so
        !           502:                                         */
        !           503:                                        int TmpSize = 2 * dp->d_size + 30;
        !           504:                                        char *TmpBuf = (char *) malloc(TmpSize);
        !           505:                                        if (TmpBuf == NULL) {
        !           506: #ifdef DEBUG
        !           507:                                            if (debug)
        !           508:                                                fprintf(ddt, "Dump T_UNSPEC: malloc returned NULL\n");
        !           509: #endif DEBUG
        !           510:                                                syslog(LOG_ERR, "Dump T_UNSPEC: malloc: %m");
        !           511:                                        }
        !           512:                                        if (btoa(cp, dp->d_size, TmpBuf,
        !           513:                                                 TmpSize) == CONV_OVERFLOW) {
        !           514: #ifdef DEBUG
        !           515:                                                if (debug)
        !           516:                                                    fprintf(ddt, "Dump T_UNSPEC: Output buffer overflow\n");
        !           517: #endif DEBUG
        !           518:                                                    syslog(LOG_ERR, "Dump T_UNSPEC: Output buffer overflow\n");
        !           519:                                        } else
        !           520:                                                fprintf(fp, "%s\n", TmpBuf);
        !           521:                                }
        !           522:                                break;
        !           523: #endif ALLOW_T_UNSPEC
        !           524:                        default:
        !           525:                                fprintf(fp, "???\n");
        !           526:                        }
        !           527:                }
        !           528:            }
        !           529:        }
        !           530:         if (ferror(fp))
        !           531:             return(NODBFILE);
        !           532: 
        !           533:        npp = htp->h_tab;
        !           534:        nppend = npp + htp->h_size;
        !           535:        while (npp < nppend) {
        !           536:            for (np = *npp++; np != NULL; np = np->n_next) {
        !           537:                if (np->n_hash == NULL)
        !           538:                        continue;
        !           539:                getname(np, dname, sizeof(dname));
        !           540:                if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE)
        !           541:                    return(NODBFILE);
        !           542:            }
        !           543:        }
        !           544:        return(OK);
        !           545: }
        !           546: 
        !           547: #ifdef ALLOW_T_UNSPEC
        !           548: /*
        !           549:  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
        !           550:  * Computes the number of bytes, and three kinds of simple checksums.
        !           551:  * Incoming bytes are collected into 32-bit words, then printed in base 85:
        !           552:  *     exp(85,5) > exp(2,32)
        !           553:  * The ASCII characters used are between '!' and 'u';
        !           554:  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
        !           555:  *
        !           556:  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
        !           557:  * the atob/btoa programs, released with the compress program, in mod.sources.
        !           558:  * Modified by Mike Schwartz 8/19/86 for use in BIND.
        !           559:  */
        !           560: 
        !           561: /* Make sure global variable names are unique */
        !           562: #define Ceor T_UNSPEC_Ceor
        !           563: #define Csum T_UNSPEC_Csum
        !           564: #define Crot T_UNSPEC_Crot
        !           565: #define word T_UNSPEC_word
        !           566: #define bcount T_UNSPEC_bcount
        !           567: 
        !           568: static long int Ceor, Csum, Crot, word, bcount;
        !           569: 
        !           570: #define EN(c)  ((int) ((c) + '!'))
        !           571: #define DE(c) ((c) - '!')
        !           572: #define AddToBuf(bufp, c) **bufp = c; (*bufp)++;
        !           573: #define streq(s0, s1)  strcmp(s0, s1) == 0
        !           574: #define times85(x)     ((((((x<<2)+x)<<2)+x)<<2)+x)
        !           575: 
        !           576: 
        !           577: /* Decode ASCII-encoded byte c into binary representation and 
        !           578:  * place into *bufp, advancing bufp 
        !           579:  */
        !           580: static int
        !           581: byte_atob(c, bufp)
        !           582:        register c;
        !           583:        char **bufp;
        !           584: {
        !           585:        if (c == 'z') {
        !           586:                if (bcount != 0)
        !           587:                        return(CONV_BADFMT);
        !           588:                else {
        !           589:                        putbyte(0, bufp);
        !           590:                        putbyte(0, bufp);
        !           591:                        putbyte(0, bufp);
        !           592:                        putbyte(0, bufp);
        !           593:                }
        !           594:        } else if ((c >= '!') && (c < ('!' + 85))) {
        !           595:                if (bcount == 0) {
        !           596:                        word = DE(c);
        !           597:                        ++bcount;
        !           598:                } else if (bcount < 4) {
        !           599:                        word = times85(word);
        !           600:                        word += DE(c);
        !           601:                        ++bcount;
        !           602:                } else {
        !           603:                        word = times85(word) + DE(c);
        !           604:                        putbyte((int)((word >> 24) & 255), bufp);
        !           605:                        putbyte((int)((word >> 16) & 255), bufp);
        !           606:                        putbyte((int)((word >> 8) & 255), bufp);
        !           607:                        putbyte((int)(word & 255), bufp);
        !           608:                        word = 0;
        !           609:                        bcount = 0;
        !           610:                }
        !           611:        } else
        !           612:                return(CONV_BADFMT);
        !           613:        return(CONV_SUCCESS);
        !           614: }
        !           615: 
        !           616: /* Compute checksum info and place c into *bufp, advancing bufp */
        !           617: static
        !           618: putbyte(c, bufp)
        !           619:        register c;
        !           620:        char **bufp;
        !           621: {
        !           622:        Ceor ^= c;
        !           623:        Csum += c;
        !           624:        Csum += 1;
        !           625:        if ((Crot & 0x80000000)) {
        !           626:                Crot <<= 1;
        !           627:                Crot += 1;
        !           628:        } else {
        !           629:                Crot <<= 1;
        !           630:        }
        !           631:        Crot += c;
        !           632:        AddToBuf(bufp, c);
        !           633: }
        !           634: 
        !           635: /* Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
        !           636:    it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
        !           637:    outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
        !           638:    in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
        !           639:    boundary, there will be no problem...it will be padded with 0 bytes, and
        !           640:    numbytes will indicate the correct number of bytes.  The main point is
        !           641:    that since the buffer is filled in 4 bytes at a time, even if there is
        !           642:    not a full 4 bytes of data at the end, there has to be room to 0-pad the
        !           643:    data, so the buffer must be of size divisible by 4).  Place the number of
        !           644:    output bytes in numbytes, and return a failure/success status  */
        !           645: int
        !           646: atob(inbuf, inbuflen, outbuf, outbuflen, numbytes)
        !           647:        char *inbuf;
        !           648:        int inbuflen;
        !           649:        char *outbuf;
        !           650:        int outbuflen;
        !           651:        int *numbytes;
        !           652: {
        !           653:        int inc, nb;
        !           654:        long int oeor, osum, orot;
        !           655:        char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen];
        !           656: 
        !           657:        if ( (outbuflen % 4) != 0)
        !           658:                return(CONV_BADBUFLEN);
        !           659:        Ceor = Csum = Crot = word = bcount = 0;
        !           660:        for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) {
        !           661:                if (outp > endoutp)
        !           662:                        return(CONV_OVERFLOW);
        !           663:                if (*inp == 'x') {
        !           664:                        inp +=2;
        !           665:                        break;
        !           666:                } else {
        !           667:                        if (byte_atob(*inp, &outp) == CONV_BADFMT)
        !           668:                                return(CONV_BADFMT);
        !           669:                }
        !           670:        }
        !           671: 
        !           672:        /* Get byte count and checksum information from end of buffer */
        !           673:        if(sscanf(inp, "%ld %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
        !           674:                return(CONV_BADFMT);
        !           675:        if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
        !           676:                return(CONV_BADCKSUM);
        !           677:        return(CONV_SUCCESS);
        !           678: }
        !           679: 
        !           680: /* Encode binary byte c into ASCII representation and place into *bufp,
        !           681:    advancing bufp */
        !           682: static
        !           683: byte_btoa(c, bufp)
        !           684:        register c;
        !           685:        char **bufp;
        !           686: {
        !           687:        Ceor ^= c;
        !           688:        Csum += c;
        !           689:        Csum += 1;
        !           690:        if ((Crot & 0x80000000)) {
        !           691:                Crot <<= 1;
        !           692:                Crot += 1;
        !           693:        } else {
        !           694:                Crot <<= 1;
        !           695:        }
        !           696:        Crot += c;
        !           697: 
        !           698:        word <<= 8;
        !           699:        word |= c;
        !           700:        if (bcount == 3) {
        !           701:                if (word == 0) {
        !           702:                        AddToBuf(bufp, 'z');
        !           703:                } else {
        !           704:                    register int tmp = 0;
        !           705:                    register long int tmpword = word;
        !           706:                        
        !           707:                    if (tmpword < 0) {  
        !           708:                           /* Because some don't support unsigned long */
        !           709:                        tmp = 32;
        !           710:                        tmpword -= (long)(85 * 85 * 85 * 85 * 32);
        !           711:                    }
        !           712:                    if (tmpword < 0) {
        !           713:                        tmp = 64;
        !           714:                        tmpword -= (long)(85 * 85 * 85 * 85 * 32);
        !           715:                    }
        !           716:                    AddToBuf(bufp,
        !           717:                         EN((tmpword / (long)(85 * 85 * 85 * 85)) + tmp));
        !           718:                    tmpword %= (long)(85 * 85 * 85 * 85);
        !           719:                    AddToBuf(bufp, EN(tmpword / (85 * 85 * 85)));
        !           720:                    tmpword %= (85 * 85 * 85);
        !           721:                    AddToBuf(bufp, EN(tmpword / (85 * 85)));
        !           722:                    tmpword %= (85 * 85);
        !           723:                    AddToBuf(bufp, EN(tmpword / 85));
        !           724:                    tmpword %= 85;
        !           725:                    AddToBuf(bufp, EN(tmpword));
        !           726:                }
        !           727:                bcount = 0;
        !           728:        } else {
        !           729:                bcount += 1;
        !           730:        }
        !           731: }
        !           732: 
        !           733: 
        !           734: /*
        !           735:  * Encode the binary data from inbuf, of length inbuflen, into a
        !           736:  * null-terminated ASCII representation in outbuf, not to exceed outbuflen
        !           737:  * bytes. Return success/failure status
        !           738:  */
        !           739: int
        !           740: btoa(inbuf, inbuflen, outbuf, outbuflen)
        !           741:        char *inbuf;
        !           742:        int inbuflen;
        !           743:        char *outbuf;
        !           744:        int outbuflen;
        !           745: {
        !           746:        long int inc, nb;
        !           747:        long int oeor, osum, orot;
        !           748:        char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen -1];
        !           749: 
        !           750:        Ceor = Csum = Crot = word = bcount = 0;
        !           751:        for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) {
        !           752:                byte_btoa((unsigned char) (*inp), &outp);
        !           753:                if (outp >= endoutp)
        !           754:                        return(CONV_OVERFLOW);
        !           755:        }
        !           756:        while (bcount != 0) {
        !           757:                byte_btoa(0, &outp);
        !           758:                if (outp >= endoutp)
        !           759:                        return(CONV_OVERFLOW);
        !           760:        }
        !           761:        /* Put byte count and checksum information at end of buffer, delimited
        !           762:           by 'x' */
        !           763:        (void) sprintf(outp, "x %ld %lx %lx %lx", inbuflen, Ceor, Csum, Crot);
        !           764:        if (&outp[strlen(outp) - 1] >= endoutp)
        !           765:                return(CONV_OVERFLOW);
        !           766:        else
        !           767:                return(CONV_SUCCESS);
        !           768: }
        !           769: #endif ALLOW_T_UNSPEC

unix.superglobalmegacorp.com

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