Annotation of 43BSDTahoe/etc/named/db_dump.c, revision 1.1.1.1

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