New kbdcontrol command, replaces the old syscons(1)
[unix-history] / usr.sbin / named / db_dump.c
CommitLineData
15637ed4
RG
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, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91";
36#endif /* not lint */
37
38#include <sys/param.h>
39#include <sys/time.h>
40#include <sys/stat.h>
41#include <netinet/in.h>
42#include <netdb.h>
43#include <stdio.h>
44#include <syslog.h>
45#include <arpa/nameser.h>
46#include <resolv.h>
47#include "ns.h"
48#include "db.h"
49#include "pathnames.h"
50
51#ifdef DUMPFILE
52char *dumpfile = DUMPFILE;
53#else
54char *dumpfile = _PATH_DUMPFILE;
55#endif
56
57extern char *cache_file;
58
59/*
60 * Dump current cache in a format similar to RFC 883.
61 *
62 * We try to be careful and determine whether the operation succeeded
63 * so that the new cache file can be installed.
64 */
65
66#define DB_ROOT_TIMBUF 3600
67
68doachkpt()
69{
70 extern int errno;
71 FILE *fp;
72 char tmpcheckfile[256];
73
74 /* nowhere to checkpoint cache... */
75 if (cache_file == NULL) {
76#ifdef DEBUG
77 if (debug >= 3)
78 fprintf(ddt,"doachkpt(to where?)\n");
79#endif
80 return;
81 }
82
83#ifdef DEBUG
84 if (debug >= 3)
85 fprintf(ddt,"doachkpt()\n");
86#endif
87
88 (void) sprintf(tmpcheckfile, "%s.chk", cache_file);
89 if ((fp = fopen(tmpcheckfile, "w")) == NULL) {
90#ifdef DEBUG
91 if (debug >= 3)
92 fprintf(ddt,"doachkpt(can't open %s for write)\n", tmpcheckfile);
93#endif
94 return;
95 }
96
97 (void) gettime(&tt);
98 fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
99 fflush(fp);
100 if (ferror(fp)) {
101#ifdef DEBUG
102 if (debug >= 3)
103 fprintf(ddt,"doachkpt(write to checkpoint file failed)\n");
104#endif
105 return;
106 }
107
108 if (fcachetab != NULL) {
109 int n;
110 if ((n = scan_root(hashtab)) < MINROOTS) {
111 syslog(LOG_ERR, "%d root hints... (too low)", n);
112 fprintf(fp, "; ---- Root hint cache dump ----\n");
113 (void) db_dump(fcachetab, fp, DB_Z_CACHE, "");
114 }
115 }
116
117 if (hashtab != NULL) {
118 fprintf(fp, "; ---- Cache dump ----\n");
119 if (db_dump(hashtab, fp, DB_Z_CACHE, "") == NODBFILE) {
120#ifdef DEBUG
121 if (debug >= 3)
122 fprintf(ddt,"doachkpt(checkpoint failed)\n");
123#endif
124 (void) fclose(fp);
125 return;
126 }
127 }
128
129 (void) fsync(fileno(fp));
130 if (fclose(fp) == EOF) {
131#ifdef DEBUG
132 if (debug >= 3)
133 fprintf(ddt,"doachkpt(close failed)\n");
134#endif
135 return;
136 }
137
138 if (rename(tmpcheckfile, cache_file)) {
139#ifdef DEBUG
140 if (debug >= 3)
141 fprintf(ddt,"doachkpt(install %s to %s failed, %d)\n",
142 tmpcheckfile,cache_file, errno);
143#endif
144 }
145}
146
147/*
148 * What we do is scan the root hint cache to make sure there are at least
149 * MINROOTS root pointers with non-0 TTL's so that the checkpoint will not
150 * lose the root. Failing this, all pointers are written out w/ TTL ~0
151 * (root pointers timed out and prime_cache() not done or failed).
152 */
153#define TIMBUF 300
154
155int
156scan_root(htp)
157 struct hashbuf *htp;
158{
159 register struct databuf *dp;
160 register struct namebuf *np;
161 struct timeval soon;
162 int roots = 0;
163
164#ifdef DEBUG
165 if (debug)
166 fprintf(ddt,"scan_root(0x%x)\n", htp);
167#endif
168
169 /* metric by which we determine whether a root NS pointer is still */
170 /* valid (will be written out if we do a dump). we also add some */
171 /* time buffer for safety... */
172 (void) gettime(&soon);
173 soon.tv_sec += TIMBUF;
174
175 for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
176 if (np->n_dname[0] == '\0') {
177 dp = np->n_data;
178 while (dp != NULL) {
179 if (dp->d_type == T_NS &&
180 dp->d_ttl > soon.tv_sec) {
181 roots++;
182 if (roots >= MINROOTS)
183 return (roots);
184 }
185 dp = dp->d_next;
186 }
187 }
188 }
189 return (roots);
190}
191
192#ifdef notdef
193mark_cache(htp, ttl)
194 struct hashbuf *htp;
195 int ttl;
196{
197 register struct databuf *dp;
198 register struct namebuf *np;
199 struct namebuf **npp, **nppend;
200 struct timeval soon;
201
202#ifdef DEBUG
203 if (debug)
204 fprintf(ddt,"mark_cache()\n");
205#endif
206
207 (void) gettime(&soon);
208 soon.tv_sec += TIMBUF;
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_data == NULL)
215 continue;
216 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
217 if (dp->d_ttl < soon.tv_sec)
218 dp->d_ttl = ttl;
219 }
220 }
221 }
222
223 npp = htp->h_tab;
224 nppend = npp + htp->h_size;
225 while (npp < nppend) {
226 for (np = *npp++; np != NULL; np = np->n_next) {
227 if (np->n_hash == NULL)
228 continue;
229 mark_cache(np->n_hash, ttl);
230 }
231 }
232}
233#endif notdef
234
235/*
236 * Dump current data base in a format similar to RFC 883.
237 */
238
239doadump()
240{
241 FILE *fp;
242
243#ifdef DEBUG
244 if (debug >= 3)
245 fprintf(ddt,"doadump()\n");
246#endif
247
248 if ((fp = fopen(dumpfile, "w")) == NULL)
249 return;
250 gettime(&tt);
251 fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
252 fprintf(fp, "; --- Cache & Data ---\n");
253 if (hashtab != NULL)
254 (void) db_dump(hashtab, fp, DB_Z_ALL, "");
255 fprintf(fp, "; --- Hints ---\n");
256 if (fcachetab != NULL)
257 (void) db_dump(fcachetab, fp, DB_Z_ALL, "");
258 (void) fclose(fp);
259}
260
261#ifdef ALLOW_UPDATES
262/* Create a disk database to back up zones
263 */
264zonedump(zp)
265 register struct zoneinfo *zp;
266{
267 FILE *fp;
268 char *fname;
269 struct hashbuf *htp;
270 char *op;
271 struct stat st;
272
273 /* Only dump zone if there is a cache specified */
274 if (zp->z_source && *(zp->z_source)) {
275#ifdef DEBUG
276 if (debug)
277 fprintf(ddt, "zonedump(%s)\n", zp->z_source);
278#endif
279
280 if ((fp = fopen(zp->z_source, "w")) == NULL)
281 return;
282 if (op = index(zp->z_origin, '.'))
283 op++;
284 gettime(&tt);
285 htp = hashtab;
286 if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) {
287 db_dump(htp, fp, zp-zones, (op == NULL ? "" : op));
288#ifdef ALLOW_UPDATES
289 zp->hasChanged = 0; /* Checkpointed */
290#endif ALLOW_UPDATES
291 }
292 (void) fclose(fp);
293 if (stat(zp->z_source, &st) == 0)
294 zp->z_ftime = st.st_mtime;
295 }
296#ifdef DEBUG
297 else if (debug)
298 fprintf(ddt, "zonedump: no zone to dump\n");
299#endif
300}
301#endif
302
303int
304db_dump(htp, fp, zone, origin)
305 int zone;
306 struct hashbuf *htp;
307 FILE *fp;
308 char *origin;
309{
310 register struct databuf *dp;
311 register struct namebuf *np;
312 struct namebuf **npp, **nppend;
313 char dname[MAXDNAME];
314 u_long n;
315 u_long addr;
316 u_short i;
317 int j;
318 register u_char *cp;
319 u_char *end;
320 char *proto;
321 extern char *inet_ntoa(), *protocolname(), *servicename();
322 int found_data, tab, printed_origin = 0;
323
324 npp = htp->h_tab;
325 nppend = npp + htp->h_size;
326 while (npp < nppend) {
327 for (np = *npp++; np != NULL; np = np->n_next) {
328 if (np->n_data == NULL)
329 continue;
330 /* Blecch - can't tell if there is data here for the
331 * right zone, so can't print name yet
332 */
333 found_data = 0;
334 /* we want a snapshot in time... */
335 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
336 /* Is the data for this zone? */
337 if (zone != DB_Z_ALL && dp->d_zone != zone)
338 continue;
339 if (dp->d_zone == DB_Z_CACHE &&
340 dp->d_ttl <= tt.tv_sec &&
341 (dp->d_flags & DB_F_HINT) == 0)
342 continue;
343 if (!printed_origin) {
344 fprintf(fp, "$ORIGIN %s.\n", origin);
345 printed_origin++;
346 }
347 tab = 0;
348 if (!found_data) {
349 if (np->n_dname[0] == 0) {
350 if (origin[0] == 0)
351 fprintf(fp, ".\t");
352 else
353 fprintf(fp, ".%s.\t", origin); /* ??? */
354 } else
355 fprintf(fp, "%s\t", np->n_dname);
356 if (strlen(np->n_dname) < 8)
357 tab = 1;
358 found_data++;
359 } else {
360 (void) putc('\t', fp);
361 tab = 1;
362 }
363 if (dp->d_zone == DB_Z_CACHE) {
364 if (dp->d_flags & DB_F_HINT &&
365 (long)(dp->d_ttl - tt.tv_sec) < DB_ROOT_TIMBUF)
366 fprintf(fp, "%d\t", DB_ROOT_TIMBUF);
367 else
368 fprintf(fp, "%d\t",
369 (int)(dp->d_ttl - tt.tv_sec));
370 } else if (dp->d_ttl != 0 &&
371 dp->d_ttl != zones[dp->d_zone].z_minimum)
372 fprintf(fp, "%d\t", (int)dp->d_ttl);
373 else if (tab)
374 (void) putc('\t', fp);
375 fprintf(fp, "%s\t%s\t", p_class(dp->d_class),
376 p_type(dp->d_type));
377 cp = (u_char *)dp->d_data;
378 /*
379 * Print type specific data
380 */
381 switch (dp->d_type) {
382 case T_A:
383 switch (dp->d_class) {
384 case C_IN:
385 case C_HS:
386 GETLONG(n, cp);
387 n = htonl(n);
388 fprintf(fp, "%s",
389 inet_ntoa(*(struct in_addr *)&n));
390 break;
391 }
392 if (dp->d_nstime)
393 fprintf(fp, "\t; %d", dp->d_nstime);
394 fprintf(fp, "\n");
395 break;
396 case T_CNAME:
397 case T_MB:
398 case T_MG:
399 case T_MR:
400 case T_PTR:
401 if (cp[0] == '\0')
402 fprintf(fp, ".\n");
403 else
404 fprintf(fp, "%s.\n", cp);
405 break;
406
407 case T_NS:
408 cp = (u_char *)dp->d_data;
409 if (cp[0] == '\0')
410 fprintf(fp, ".\t");
411 else
412 fprintf(fp, "%s.", cp);
413 if (dp->d_nstime)
414 fprintf(fp, "\t; %d???", dp->d_nstime);
415 fprintf(fp, "\n");
416 break;
417
418 case T_HINFO:
419 if (n = *cp++) {
420 fprintf(fp, "\"%.*s\"", (int)n, cp);
421 cp += n;
422 } else
423 fprintf(fp, "\"\"");
424 if (n = *cp++)
425 fprintf(fp, " \"%.*s\"", (int)n, cp);
426 else
427 fprintf(fp, " \"\"");
428 (void) putc('\n', fp);
429 break;
430
431 case T_SOA:
432 fprintf(fp, "%s.", cp);
433 cp += strlen((char *)cp) + 1;
434 fprintf(fp, " %s. (\n", cp);
435 cp += strlen((char *)cp) + 1;
436 GETLONG(n, cp);
437 fprintf(fp, "\t\t%lu", n);
438 GETLONG(n, cp);
439 fprintf(fp, " %lu", n);
440 GETLONG(n, cp);
441 fprintf(fp, " %lu", n);
442 GETLONG(n, cp);
443 fprintf(fp, " %lu", n);
444 GETLONG(n, cp);
445 fprintf(fp, " %lu )\n", n);
446 break;
447
448 case T_MX:
449 GETSHORT(n, cp);
450 fprintf(fp,"%lu", n);
451 fprintf(fp," %s.\n", cp);
452 break;
453
454 case T_TXT:
455 end = (u_char *)dp->d_data + dp->d_size;
456 (void) putc('"', fp);
457 while (cp < end) {
458 if (n = *cp++) {
459 for (j = n ; j > 0 && cp < end ; j--)
460 if (*cp == '\n') {
461 (void) putc('\\', fp);
462 (void) putc(*cp++, fp);
463 } else
464 (void) putc(*cp++, fp);
465 }
466 }
467 (void) fputs("\"\n", fp);
468 break;
469
470 case T_UINFO:
471 fprintf(fp, "\"%s\"\n", cp);
472 break;
473
474 case T_UID:
475 case T_GID:
476 if (dp->d_size == sizeof(u_long)) {
477 GETLONG(n, cp);
478 fprintf(fp, "%lu\n", n);
479 }
480 break;
481
482 case T_WKS:
483 GETLONG(addr, cp);
484 addr = htonl(addr);
485 fprintf(fp,"%s ",
486 inet_ntoa(*(struct in_addr *)&addr));
487 proto = protocolname(*cp);
488 cp += sizeof(char);
489 fprintf(fp, "%s ", proto);
490 i = 0;
491 while(cp < (u_char *)dp->d_data + dp->d_size) {
492 j = *cp++;
493 do {
494 if (j & 0200)
495 fprintf(fp," %s",
496 servicename(i, proto));
497 j <<= 1;
498 } while(++i & 07);
499 }
500 fprintf(fp,"\n");
501 break;
502
503 case T_MINFO:
504 fprintf(fp, "%s.", cp);
505 cp += strlen((char *)cp) + 1;
506 fprintf(fp, " %s.\n", cp);
507 break;
508#ifdef ALLOW_T_UNSPEC
509 case T_UNSPEC:
510 /* Dump binary data out in an ASCII-encoded
511 format */
512 {
513 /* Allocate more than enough space:
514 * actually need 5/4 size + 20 or so
515 */
516 int TmpSize = 2 * dp->d_size + 30;
517 char *TmpBuf = (char *) malloc(TmpSize);
518 if (TmpBuf == NULL) {
519#ifdef DEBUG
520 if (debug)
521 fprintf(ddt, "Dump T_UNSPEC: malloc returned NULL\n");
522#endif DEBUG
523 syslog(LOG_ERR, "Dump T_UNSPEC: malloc: %m");
524 }
525 if (btoa(cp, dp->d_size, TmpBuf,
526 TmpSize) == CONV_OVERFLOW) {
527#ifdef DEBUG
528 if (debug)
529 fprintf(ddt, "Dump T_UNSPEC: Output buffer overflow\n");
530#endif DEBUG
531 syslog(LOG_ERR, "Dump T_UNSPEC: Output buffer overflow\n");
532 } else
533 fprintf(fp, "%s\n", TmpBuf);
534 }
535 break;
536#endif ALLOW_T_UNSPEC
537 default:
538 fprintf(fp, "???\n");
539 }
540 }
541 }
542 }
543 if (ferror(fp))
544 return(NODBFILE);
545
546 npp = htp->h_tab;
547 nppend = npp + htp->h_size;
548 while (npp < nppend) {
549 for (np = *npp++; np != NULL; np = np->n_next) {
550 if (np->n_hash == NULL)
551 continue;
552 getname(np, dname, sizeof(dname));
553 if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE)
554 return(NODBFILE);
555 }
556 }
557 return(OK);
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
581static 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 */
593static int
594byte_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 */
630static
631putbyte(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 */
658int
659atob(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 */
695static
696byte_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 */
752int
753btoa(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