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

Defined functions

atob defined in line 653; used 1 times
btoa defined in line 747; used 1 times
byte_atob defined in line 588; used 1 times
byte_btoa defined in line 690; used 2 times
db_dump defined in line 280; used 6 times
doadump defined in line 218; used 1 times
mark_cache defined in line 172; used 1 times
p_protocal defined in line 522; used 4 times
p_service defined in line 538; used 4 times
putbyte defined in line 625; used 8 times
scan_root defined in line 134; used 1 times
  • in line 89

Defined variables

Ceor defined in line 576; never used
Crot defined in line 576; never used
Csum defined in line 576; never used
bcount defined in line 576; never used
dumpfile defined in line 33; used 1 times
sccsid defined in line 14; never used
word defined in line 576; never used

Defined macros

AddToBuf defined in line 580; used 7 times
Ceor defined in line 570; used 6 times
Crot defined in line 572; used 14 times
Csum defined in line 571; used 8 times
DB_ROOT_TIMBUF defined in line 45; used 2 times
DE defined in line 579; used 3 times
EN defined in line 578; used 5 times
TIMBUF defined in line 132; used 2 times
bcount defined in line 574; used 12 times
streq defined in line 581; never used
times85 defined in line 582; used 2 times
word defined in line 573; used 17 times
Last modified: 1988-09-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5806
Valid CSS Valid XHTML 1.0 Strict