|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.