Annotation of 43BSDReno/usr.sbin/named/db_dump.c, revision 1.1.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.