Sync with HEAD.
[dragonfly.git] / contrib / dhcp-3.0 / common / print.c
blobdba117038f92d385741d68399a4f8c965569e867
1 /* print.c
3 Turn data structures into printable text. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: print.c,v 1.53.2.11 2004/06/17 20:54:39 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
42 char *quotify_string (const char *s, const char *file, int line)
44 unsigned len = 0;
45 const char *sp;
46 char *buf, *nsp;
48 for (sp = s; sp && *sp; sp++) {
49 if (*sp == ' ')
50 len++;
51 else if (!isascii (*sp) || !isprint (*sp))
52 len += 4;
53 else if (*sp == '"' || *sp == '\\')
54 len += 2;
55 else
56 len++;
59 buf = dmalloc (len + 1, file, line);
60 if (buf) {
61 nsp = buf;
62 for (sp = s; sp && *sp; sp++) {
63 if (*sp == ' ')
64 *nsp++ = ' ';
65 else if (!isascii (*sp) || !isprint (*sp)) {
66 sprintf (nsp, "\\%03o",
67 *(const unsigned char *)sp);
68 nsp += 4;
69 } else if (*sp == '"' || *sp == '\\') {
70 *nsp++ = '\\';
71 *nsp++ = *sp;
72 } else
73 *nsp++ = *sp;
75 *nsp++ = 0;
77 return buf;
80 char *quotify_buf (const unsigned char *s, unsigned len,
81 const char *file, int line)
83 unsigned nulen = 0;
84 char *buf, *nsp;
85 int i;
87 for (i = 0; i < len; i++) {
88 if (s [i] == ' ')
89 nulen++;
90 else if (!isascii (s [i]) || !isprint (s [i]))
91 nulen += 4;
92 else if (s [i] == '"' || s [i] == '\\')
93 nulen += 2;
94 else
95 nulen++;
98 buf = dmalloc (nulen + 1, MDL);
99 if (buf) {
100 nsp = buf;
101 for (i = 0; i < len; i++) {
102 if (s [i] == ' ')
103 *nsp++ = ' ';
104 else if (!isascii (s [i]) || !isprint (s [i])) {
105 sprintf (nsp, "\\%03o", s [i]);
106 nsp += 4;
107 } else if (s [i] == '"' || s [i] == '\\') {
108 *nsp++ = '\\';
109 *nsp++ = s [i];
110 } else
111 *nsp++ = s [i];
113 *nsp++ = 0;
115 return buf;
118 char *print_base64 (const unsigned char *buf, unsigned len,
119 const char *file, int line)
121 char *s, *b;
122 unsigned bl;
123 int i;
124 unsigned val, extra;
125 static char to64 [] =
126 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
128 bl = ((len * 4 + 2) / 3) + 1;
129 b = dmalloc (bl + 1, file, line);
130 if (!b)
131 return (char *)0;
133 i = 0;
134 s = b;
135 while (i != len) {
136 val = buf [i++];
137 extra = val & 3;
138 val = val >> 2;
139 *s++ = to64 [val];
140 if (i == len) {
141 *s++ = to64 [extra << 4];
142 *s++ = '=';
143 break;
145 val = (extra << 8) + buf [i++];
146 extra = val & 15;
147 val = val >> 4;
148 *s++ = to64 [val];
149 if (i == len) {
150 *s++ = to64 [extra << 2];
151 *s++ = '=';
152 break;
154 val = (extra << 8) + buf [i++];
155 extra = val & 0x3f;
156 val = val >> 6;
157 *s++ = to64 [val];
158 *s++ = to64 [extra];
160 if (!len)
161 *s++ = '=';
162 *s++ = 0;
163 if (s > b + bl + 1)
164 abort ();
165 return b;
168 char *print_hw_addr (htype, hlen, data)
169 int htype;
170 int hlen;
171 unsigned char *data;
173 static char habuf [49];
174 char *s;
175 int i;
177 if (hlen <= 0)
178 habuf [0] = 0;
179 else {
180 s = habuf;
181 for (i = 0; i < hlen; i++) {
182 sprintf (s, "%02x", data [i]);
183 s += strlen (s);
184 *s++ = ':';
186 *--s = 0;
188 return habuf;
191 void print_lease (lease)
192 struct lease *lease;
194 struct tm *t;
195 char tbuf [32];
197 log_debug (" Lease %s",
198 piaddr (lease -> ip_addr));
200 t = gmtime (&lease -> starts);
201 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
202 log_debug (" start %s", tbuf);
204 t = gmtime (&lease -> ends);
205 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
206 log_debug (" end %s", tbuf);
208 if (lease -> hardware_addr.hlen)
209 log_debug (" hardware addr = %s",
210 print_hw_addr (lease -> hardware_addr.hbuf [0],
211 lease -> hardware_addr.hlen - 1,
212 &lease -> hardware_addr.hbuf [1]));
213 log_debug (" host %s ",
214 lease -> host ? lease -> host -> name : "<none>");
217 #if defined (DEBUG_PACKET)
218 void dump_packet_option (struct option_cache *oc,
219 struct packet *packet,
220 struct lease *lease,
221 struct client_state *client,
222 struct option_state *in_options,
223 struct option_state *cfg_options,
224 struct binding_scope **scope,
225 struct universe *u, void *foo)
227 const char *name, *dot;
228 struct data_string ds;
229 memset (&ds, 0, sizeof ds);
231 if (u != &dhcp_universe) {
232 name = u -> name;
233 dot = ".";
234 } else {
235 name = "";
236 dot = "";
238 if (evaluate_option_cache (&ds, packet, lease, client,
239 in_options, cfg_options, scope, oc, MDL)) {
240 log_debug (" option %s%s%s %s;\n",
241 name, dot, oc -> option -> name,
242 pretty_print_option (oc -> option,
243 ds.data, ds.len, 1, 1));
244 data_string_forget (&ds, MDL);
248 void dump_packet (tp)
249 struct packet *tp;
251 struct dhcp_packet *tdp = tp -> raw;
253 log_debug ("packet length %d", tp -> packet_length);
254 log_debug ("op = %d htype = %d hlen = %d hops = %d",
255 tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
256 log_debug ("xid = %x secs = %ld flags = %x",
257 tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
258 log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
259 log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
260 log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
261 log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
262 log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
263 ((unsigned char *)(tdp -> chaddr)) [0],
264 ((unsigned char *)(tdp -> chaddr)) [1],
265 ((unsigned char *)(tdp -> chaddr)) [2],
266 ((unsigned char *)(tdp -> chaddr)) [3],
267 ((unsigned char *)(tdp -> chaddr)) [4],
268 ((unsigned char *)(tdp -> chaddr)) [5]);
269 log_debug ("filename = %s", tdp -> file);
270 log_debug ("server_name = %s", tdp -> sname);
271 if (tp -> options_valid) {
272 int i;
274 for (i = 0; i < tp -> options -> universe_count; i++) {
275 if (tp -> options -> universes [i]) {
276 option_space_foreach (tp, (struct lease *)0,
277 (struct client_state *)0,
278 (struct option_state *)0,
279 tp -> options,
280 &global_scope,
281 universes [i], 0,
282 dump_packet_option);
286 log_debug ("%s", "");
288 #endif
290 void dump_raw (buf, len)
291 const unsigned char *buf;
292 unsigned len;
294 int i;
295 char lbuf [80];
296 int lbix = 0;
299 1 2 3 4 5 6 7
300 01234567890123456789012345678901234567890123456789012345678901234567890123
301 280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .................
304 memset(lbuf, ' ', 79);
305 lbuf [79] = 0;
307 for (i = 0; i < len; i++) {
308 if ((i & 15) == 0) {
309 if (lbix) {
310 lbuf[53]=' ';
311 lbuf[54]=' ';
312 lbuf[55]=' ';
313 lbuf[73]='\0';
314 log_info (lbuf);
316 memset(lbuf, ' ', 79);
317 lbuf [79] = 0;
318 sprintf (lbuf, "%03x:", i);
319 lbix = 4;
320 } else if ((i & 7) == 0)
321 lbuf [lbix++] = ' ';
323 if(isprint(buf[i])) {
324 lbuf[56+(i%16)]=buf[i];
325 } else {
326 lbuf[56+(i%16)]='.';
329 sprintf (&lbuf [lbix], " %02x", buf [i]);
330 lbix += 3;
331 lbuf[lbix]=' ';
334 lbuf[53]=' ';
335 lbuf[54]=' ';
336 lbuf[55]=' ';
337 lbuf[73]='\0';
338 log_info (lbuf);
341 void hash_dump (table)
342 struct hash_table *table;
344 int i;
345 struct hash_bucket *bp;
347 if (!table)
348 return;
350 for (i = 0; i < table -> hash_count; i++) {
351 if (!table -> buckets [i])
352 continue;
353 log_info ("hash bucket %d:", i);
354 for (bp = table -> buckets [i]; bp; bp = bp -> next) {
355 if (bp -> len)
356 dump_raw (bp -> name, bp -> len);
357 else
358 log_info ("%s", (const char *)bp -> name);
363 #define HBLEN 60
365 #define DECLARE_HEX_PRINTER(x) \
366 char *print_hex##x (len, data, limit) \
367 unsigned len; \
368 const u_int8_t *data; \
369 unsigned limit; \
372 static char hex_buf##x [HBLEN + 1]; \
373 unsigned i; \
375 if (limit > HBLEN) \
376 limit = HBLEN; \
378 for (i = 0; i < (limit - 2) && i < len; i++) { \
379 if (!isascii (data [i]) || !isprint (data [i])) { \
380 for (i = 0; i < limit / 3 && i < len; i++) { \
381 sprintf (&hex_buf##x [i * 3], \
382 "%02x:", data [i]); \
384 hex_buf##x [i * 3 - 1] = 0; \
385 return hex_buf##x; \
388 hex_buf##x [0] = '"'; \
389 i = len; \
390 if (i > limit - 2) \
391 i = limit - 2; \
392 memcpy (&hex_buf##x [1], data, i); \
393 hex_buf##x [i + 1] = '"'; \
394 hex_buf##x [i + 2] = 0; \
395 return hex_buf##x; \
398 DECLARE_HEX_PRINTER (_1)
399 DECLARE_HEX_PRINTER (_2)
400 DECLARE_HEX_PRINTER (_3)
402 #define DQLEN 80
404 char *print_dotted_quads (len, data)
405 unsigned len;
406 const u_int8_t *data;
408 static char dq_buf [DQLEN + 1];
409 int i;
410 char *s, *last;
412 s = &dq_buf [0];
413 last = s;
415 i = 0;
417 /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
418 * The sprintf can't exceed 18 bytes, and since the loop enforces
419 * 21 bytes of space per iteration at no time can we exit the
420 * loop without at least 3 bytes spare.
422 do {
423 sprintf (s, "%u.%u.%u.%u, ",
424 data [i], data [i + 1], data [i + 2], data [i + 3]);
425 s += strlen (s);
426 i += 4;
427 } while ((s - &dq_buf [0] > DQLEN - 21) &&
428 i + 3 < len);
429 if (i == len)
430 s [-2] = 0;
431 else
432 strcpy (s, "...");
433 return dq_buf;
436 char *print_dec_1 (val)
437 unsigned long val;
439 static char vbuf [32];
440 sprintf (vbuf, "%lu", val);
441 return vbuf;
444 char *print_dec_2 (val)
445 unsigned long val;
447 static char vbuf [32];
448 sprintf (vbuf, "%lu", val);
449 return vbuf;
452 static unsigned print_subexpression PROTO ((struct expression *,
453 char *, unsigned));
455 static unsigned print_subexpression (expr, buf, len)
456 struct expression *expr;
457 char *buf;
458 unsigned len;
460 unsigned rv, left;
461 const char *s;
463 switch (expr -> op) {
464 case expr_none:
465 if (len > 3) {
466 strcpy (buf, "nil");
467 return 3;
469 break;
471 case expr_match:
472 if (len > 7) {
473 strcpy (buf, "(match)");
474 return 7;
476 break;
478 case expr_check:
479 rv = 10 + strlen (expr -> data.check -> name);
480 if (len > rv) {
481 sprintf (buf, "(check %s)",
482 expr -> data.check -> name);
483 return rv;
485 break;
487 case expr_equal:
488 if (len > 6) {
489 rv = 4;
490 strcpy (buf, "(eq ");
491 rv += print_subexpression (expr -> data.equal [0],
492 buf + rv, len - rv - 2);
493 buf [rv++] = ' ';
494 rv += print_subexpression (expr -> data.equal [1],
495 buf + rv, len - rv - 1);
496 buf [rv++] = ')';
497 buf [rv] = 0;
498 return rv;
500 break;
502 case expr_not_equal:
503 if (len > 7) {
504 rv = 5;
505 strcpy (buf, "(neq ");
506 rv += print_subexpression (expr -> data.equal [0],
507 buf + rv, len - rv - 2);
508 buf [rv++] = ' ';
509 rv += print_subexpression (expr -> data.equal [1],
510 buf + rv, len - rv - 1);
511 buf [rv++] = ')';
512 buf [rv] = 0;
513 return rv;
515 break;
517 case expr_substring:
518 if (len > 11) {
519 rv = 8;
520 strcpy (buf, "(substr ");
521 rv += print_subexpression (expr -> data.substring.expr,
522 buf + rv, len - rv - 3);
523 buf [rv++] = ' ';
524 rv += print_subexpression
525 (expr -> data.substring.offset,
526 buf + rv, len - rv - 2);
527 buf [rv++] = ' ';
528 rv += print_subexpression (expr -> data.substring.len,
529 buf + rv, len - rv - 1);
530 buf [rv++] = ')';
531 buf [rv] = 0;
532 return rv;
534 break;
536 case expr_suffix:
537 if (len > 10) {
538 rv = 8;
539 strcpy (buf, "(suffix ");
540 rv += print_subexpression (expr -> data.suffix.expr,
541 buf + rv, len - rv - 2);
542 if (len > rv)
543 buf [rv++] = ' ';
544 rv += print_subexpression (expr -> data.suffix.len,
545 buf + rv, len - rv - 1);
546 if (len > rv)
547 buf [rv++] = ')';
548 buf [rv] = 0;
549 return rv;
551 break;
553 case expr_concat:
554 if (len > 10) {
555 rv = 8;
556 strcpy (buf, "(concat ");
557 rv += print_subexpression (expr -> data.concat [0],
558 buf + rv, len - rv - 2);
559 buf [rv++] = ' ';
560 rv += print_subexpression (expr -> data.concat [1],
561 buf + rv, len - rv - 1);
562 buf [rv++] = ')';
563 buf [rv] = 0;
564 return rv;
566 break;
568 case expr_pick_first_value:
569 if (len > 8) {
570 rv = 6;
571 strcpy (buf, "(pick1st ");
572 rv += print_subexpression
573 (expr -> data.pick_first_value.car,
574 buf + rv, len - rv - 2);
575 buf [rv++] = ' ';
576 rv += print_subexpression
577 (expr -> data.pick_first_value.cdr,
578 buf + rv, len - rv - 1);
579 buf [rv++] = ')';
580 buf [rv] = 0;
581 return rv;
583 break;
585 case expr_host_lookup:
586 rv = 15 + strlen (expr -> data.host_lookup -> hostname);
587 if (len > rv) {
588 sprintf (buf, "(dns-lookup %s)",
589 expr -> data.host_lookup -> hostname);
590 return rv;
592 break;
594 case expr_and:
595 s = "and";
596 binop:
597 rv = strlen (s);
598 if (len > rv + 4) {
599 buf [0] = '(';
600 strcpy (&buf [1], s);
601 rv += 1;
602 buf [rv++] = ' ';
603 rv += print_subexpression (expr -> data.and [0],
604 buf + rv, len - rv - 2);
605 buf [rv++] = ' ';
606 rv += print_subexpression (expr -> data.and [1],
607 buf + rv, len - rv - 1);
608 buf [rv++] = ')';
609 buf [rv] = 0;
610 return rv;
612 break;
614 case expr_or:
615 s = "or";
616 goto binop;
618 case expr_add:
619 s = "+";
620 goto binop;
622 case expr_subtract:
623 s = "-";
624 goto binop;
626 case expr_multiply:
627 s = "*";
628 goto binop;
630 case expr_divide:
631 s = "/";
632 goto binop;
634 case expr_remainder:
635 s = "%";
636 goto binop;
638 case expr_binary_and:
639 s = "&";
640 goto binop;
642 case expr_binary_or:
643 s = "|";
644 goto binop;
646 case expr_binary_xor:
647 s = "^";
648 goto binop;
650 case expr_not:
651 if (len > 6) {
652 rv = 5;
653 strcpy (buf, "(not ");
654 rv += print_subexpression (expr -> data.not,
655 buf + rv, len - rv - 1);
656 buf [rv++] = ')';
657 buf [rv] = 0;
658 return rv;
660 break;
662 case expr_config_option:
663 s = "cfg-option";
664 goto dooption;
666 case expr_option:
667 s = "option";
668 dooption:
669 rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
670 strlen (expr -> data.option -> universe -> name));
671 if (len > rv) {
672 sprintf (buf, "(option %s.%s)",
673 expr -> data.option -> universe -> name,
674 expr -> data.option -> name);
675 return rv;
677 break;
679 case expr_hardware:
680 if (len > 10) {
681 strcpy (buf, "(hardware)");
682 return 10;
684 break;
686 case expr_packet:
687 if (len > 10) {
688 rv = 8;
689 strcpy (buf, "(substr ");
690 rv += print_subexpression (expr -> data.packet.offset,
691 buf + rv, len - rv - 2);
692 buf [rv++] = ' ';
693 rv += print_subexpression (expr -> data.packet.len,
694 buf + rv, len - rv - 1);
695 buf [rv++] = ')';
696 buf [rv] = 0;
697 return rv;
699 break;
701 case expr_const_data:
702 s = print_hex_1 (expr -> data.const_data.len,
703 expr -> data.const_data.data, len);
704 rv = strlen (s);
705 if (rv >= len)
706 rv = len - 1;
707 strncpy (buf, s, rv);
708 buf [rv] = 0;
709 return rv;
711 case expr_encapsulate:
712 rv = 13;
713 strcpy (buf, "(encapsulate ");
714 rv += expr -> data.encapsulate.len;
715 if (rv + 2 > len)
716 rv = len - 2;
717 strncpy (buf,
718 (const char *)expr -> data.encapsulate.data, rv - 13);
719 buf [rv++] = ')';
720 buf [rv++] = 0;
721 break;
723 case expr_extract_int8:
724 if (len > 7) {
725 rv = 6;
726 strcpy (buf, "(int8 ");
727 rv += print_subexpression (expr -> data.extract_int,
728 buf + rv, len - rv - 1);
729 buf [rv++] = ')';
730 buf [rv] = 0;
731 return rv;
733 break;
735 case expr_extract_int16:
736 if (len > 8) {
737 rv = 7;
738 strcpy (buf, "(int16 ");
739 rv += print_subexpression (expr -> data.extract_int,
740 buf + rv, len - rv - 1);
741 buf [rv++] = ')';
742 buf [rv] = 0;
743 return rv;
745 break;
747 case expr_extract_int32:
748 if (len > 8) {
749 rv = 7;
750 strcpy (buf, "(int32 ");
751 rv += print_subexpression (expr -> data.extract_int,
752 buf + rv, len - rv - 1);
753 buf [rv++] = ')';
754 buf [rv] = 0;
755 return rv;
757 break;
759 case expr_encode_int8:
760 if (len > 7) {
761 rv = 6;
762 strcpy (buf, "(to-int8 ");
763 rv += print_subexpression (expr -> data.encode_int,
764 buf + rv, len - rv - 1);
765 buf [rv++] = ')';
766 buf [rv] = 0;
767 return rv;
769 break;
771 case expr_encode_int16:
772 if (len > 8) {
773 rv = 7;
774 strcpy (buf, "(to-int16 ");
775 rv += print_subexpression (expr -> data.encode_int,
776 buf + rv, len - rv - 1);
777 buf [rv++] = ')';
778 buf [rv] = 0;
779 return rv;
781 break;
783 case expr_encode_int32:
784 if (len > 8) {
785 rv = 7;
786 strcpy (buf, "(to-int32 ");
787 rv += print_subexpression (expr -> data.encode_int,
788 buf + rv, len - rv - 1);
789 buf [rv++] = ')';
790 buf [rv] = 0;
791 return rv;
793 break;
795 case expr_const_int:
796 s = print_dec_1 (expr -> data.const_int);
797 rv = strlen (s);
798 if (len > rv) {
799 strcpy (buf, s);
800 return rv;
802 break;
804 case expr_exists:
805 rv = 10 + (strlen (expr -> data.option -> name) +
806 strlen (expr -> data.option -> universe -> name));
807 if (len > rv) {
808 sprintf (buf, "(exists %s.%s)",
809 expr -> data.option -> universe -> name,
810 expr -> data.option -> name);
811 return rv;
813 break;
815 case expr_variable_exists:
816 rv = 10 + strlen (expr -> data.variable);
817 if (len > rv) {
818 sprintf (buf, "(defined %s)", expr -> data.variable);
819 return rv;
821 break;
823 case expr_variable_reference:
824 rv = strlen (expr -> data.variable);
825 if (len > rv) {
826 sprintf (buf, "%s", expr -> data.variable);
827 return rv;
829 break;
831 case expr_known:
832 s = "known";
833 astring:
834 rv = strlen (s);
835 if (len > rv) {
836 strcpy (buf, s);
837 return rv;
839 break;
841 case expr_leased_address:
842 s = "leased-address";
843 goto astring;
845 case expr_client_state:
846 s = "client-state";
847 goto astring;
849 case expr_host_decl_name:
850 s = "host-decl-name";
851 goto astring;
853 case expr_lease_time:
854 s = "lease-time";
855 goto astring;
857 case expr_static:
858 s = "static";
859 goto astring;
861 case expr_filename:
862 s = "filename";
863 goto astring;
865 case expr_sname:
866 s = "server-name";
867 goto astring;
869 case expr_reverse:
870 if (len > 11) {
871 rv = 13;
872 strcpy (buf, "(reverse ");
873 rv += print_subexpression (expr -> data.reverse.width,
874 buf + rv, len - rv - 2);
875 buf [rv++] = ' ';
876 rv += print_subexpression (expr -> data.reverse.buffer,
877 buf + rv, len - rv - 1);
878 buf [rv++] = ')';
879 buf [rv] = 0;
880 return rv;
882 break;
884 case expr_binary_to_ascii:
885 if (len > 5) {
886 rv = 9;
887 strcpy (buf, "(b2a ");
888 rv += print_subexpression (expr -> data.b2a.base,
889 buf + rv, len - rv - 4);
890 buf [rv++] = ' ';
891 rv += print_subexpression (expr -> data.b2a.width,
892 buf + rv, len - rv - 3);
893 buf [rv++] = ' ';
894 rv += print_subexpression (expr -> data.b2a.seperator,
895 buf + rv, len - rv - 2);
896 buf [rv++] = ' ';
897 rv += print_subexpression (expr -> data.b2a.buffer,
898 buf + rv, len - rv - 1);
899 buf [rv++] = ')';
900 buf [rv] = 0;
901 return rv;
903 break;
905 case expr_dns_transaction:
906 rv = 10;
907 if (len < rv + 2) {
908 buf [0] = '(';
909 strcpy (&buf [1], "ns-update ");
910 while (len < rv + 2) {
911 rv += print_subexpression
912 (expr -> data.dns_transaction.car,
913 buf + rv, len - rv - 2);
914 buf [rv++] = ' ';
915 expr = expr -> data.dns_transaction.cdr;
917 buf [rv - 1] = ')';
918 buf [rv] = 0;
919 return rv;
921 return 0;
923 case expr_ns_delete:
924 s = "delete";
925 left = 4;
926 goto dodnsupd;
927 case expr_ns_exists:
928 s = "exists";
929 left = 4;
930 goto dodnsupd;
931 case expr_ns_not_exists:
932 s = "not_exists";
933 left = 4;
934 goto dodnsupd;
935 case expr_ns_add:
936 s = "update";
937 left = 5;
938 dodnsupd:
939 rv = strlen (s);
940 if (len > strlen (s) + 1) {
941 buf [0] = '(';
942 strcpy (buf + 1, s);
943 rv++;
944 buf [rv++] = ' ';
945 s = print_dec_1 (expr -> data.ns_add.rrclass);
946 if (len > rv + strlen (s) + left) {
947 strcpy (&buf [rv], s);
948 rv += strlen (&buf [rv]);
950 buf [rv++] = ' ';
951 left--;
952 s = print_dec_1 (expr -> data.ns_add.rrtype);
953 if (len > rv + strlen (s) + left) {
954 strcpy (&buf [rv], s);
955 rv += strlen (&buf [rv]);
957 buf [rv++] = ' ';
958 left--;
959 rv += print_subexpression
960 (expr -> data.ns_add.rrname,
961 buf + rv, len - rv - left);
962 buf [rv++] = ' ';
963 left--;
964 rv += print_subexpression
965 (expr -> data.ns_add.rrdata,
966 buf + rv, len - rv - left);
967 buf [rv++] = ' ';
968 left--;
969 rv += print_subexpression
970 (expr -> data.ns_add.ttl,
971 buf + rv, len - rv - left);
972 buf [rv++] = ')';
973 buf [rv] = 0;
974 return rv;
976 break;
978 case expr_null:
979 if (len > 6) {
980 strcpy (buf, "(null)");
981 return 6;
983 break;
984 case expr_funcall:
985 rv = 12 + strlen (expr -> data.funcall.name);
986 if (len > rv + 1) {
987 strcpy (buf, "(funcall ");
988 strcpy (buf + 9, expr -> data.funcall.name);
989 buf [rv++] = ' ';
990 rv += print_subexpression
991 (expr -> data.funcall.arglist, buf + rv,
992 len - rv - 1);
993 buf [rv++] = ')';
994 buf [rv] = 0;
995 return rv;
997 break;
999 case expr_arg:
1000 rv = print_subexpression (expr -> data.arg.val, buf, len);
1001 if (expr -> data.arg.next && rv + 2 < len) {
1002 buf [rv++] = ' ';
1003 rv += print_subexpression (expr -> data.arg.next,
1004 buf, len);
1005 if (rv + 1 < len)
1006 buf [rv++] = 0;
1007 return rv;
1009 break;
1010 case expr_function:
1011 rv = 9;
1012 if (len > rv + 1) {
1013 struct string_list *foo;
1014 strcpy (buf, "(function");
1015 for (foo = expr -> data.func -> args;
1016 foo; foo = foo -> next) {
1017 if (len > rv + 2 + strlen (foo -> string)) {
1018 buf [rv - 1] = ' ';
1019 strcpy (&buf [rv], foo -> string);
1020 rv += strlen (foo -> string);
1023 buf [rv] = ')';
1024 buf [rv++] = 0;
1025 return rv;
1028 return 0;
1031 void print_expression (name, expr)
1032 const char *name;
1033 struct expression *expr;
1035 char buf [1024];
1037 print_subexpression (expr, buf, sizeof buf);
1038 log_info ("%s: %s", name, buf);
1041 int token_print_indent_concat (FILE *file, int col, int indent,
1042 const char *prefix,
1043 const char *suffix, ...)
1045 va_list list;
1046 char *buf;
1047 unsigned len;
1048 char *s, *t, *u;
1050 va_start (list, suffix);
1051 s = va_arg (list, char *);
1052 len = 0;
1053 while (s) {
1054 len += strlen (s);
1055 s = va_arg (list, char *);
1057 va_end (list);
1059 t = dmalloc (len + 1, MDL);
1060 if (!t)
1061 log_fatal ("token_print_indent: no memory for copy buffer");
1063 va_start (list, suffix);
1064 s = va_arg (list, char *);
1065 u = t;
1066 while (s) {
1067 len = strlen (s);
1068 strcpy (u, s);
1069 u += len;
1071 va_end (list);
1073 len = token_print_indent (file, col, indent,
1074 prefix, suffix, t);
1075 dfree (t, MDL);
1076 return col;
1079 int token_indent_data_string (FILE *file, int col, int indent,
1080 const char *prefix, const char *suffix,
1081 struct data_string *data)
1083 int i;
1084 char *buf;
1085 char obuf [3];
1087 /* See if this is just ASCII. */
1088 for (i = 0; i < data -> len; i++)
1089 if (!isascii (data -> data [i]) ||
1090 !isprint (data -> data [i]))
1091 break;
1093 /* If we have a purely ASCII string, output it as text. */
1094 if (i == data -> len) {
1095 char *buf = dmalloc (data -> len + 3, MDL);
1096 if (buf) {
1097 buf [0] = '"';
1098 memcpy (buf + 1, data -> data, data -> len);
1099 buf [data -> len + 1] = '"';
1100 buf [data -> len + 2] = 0;
1101 i = token_print_indent (file, col, indent,
1102 prefix, suffix, buf);
1103 dfree (buf, MDL);
1104 return i;
1108 for (i = 0; i < data -> len; i++) {
1109 sprintf (obuf, "%2.2x", data -> data [i]);
1110 col = token_print_indent (file, col, indent,
1111 i == 0 ? prefix : "",
1112 (i + 1 == data -> len
1113 ? suffix
1114 : ""), obuf);
1115 if (i + 1 != data -> len)
1116 col = token_print_indent (file, col, indent,
1117 prefix, suffix, ":");
1119 return col;
1122 int token_print_indent (FILE *file, int col, int indent,
1123 const char *prefix,
1124 const char *suffix, const char *buf)
1126 int len = strlen (buf) + strlen (prefix);
1127 if (col + len > 79) {
1128 if (indent + len < 79) {
1129 indent_spaces (file, indent);
1130 col = indent;
1131 } else {
1132 indent_spaces (file, col);
1133 col = len > 79 ? 0 : 79 - len - 1;
1135 } else if (prefix && *prefix) {
1136 fputs (prefix, file);
1137 col += strlen (prefix);
1139 fputs (buf, file);
1140 col += len;
1141 if (suffix && *suffix) {
1142 if (col + strlen (suffix) > 79) {
1143 indent_spaces (file, indent);
1144 col = indent;
1145 } else {
1146 fputs (suffix, file);
1147 col += strlen (suffix);
1150 return col;
1153 void indent_spaces (FILE *file, int indent)
1155 int i;
1156 fputc ('\n', file);
1157 for (i = 0; i < indent; i++)
1158 fputc (' ', file);
1161 #if defined (NSUPDATE)
1162 void print_dns_status (int status, ns_updque *uq)
1164 char obuf [1024];
1165 char *s = &obuf [0], *end = &obuf [1022];
1166 ns_updrec *u;
1167 int position;
1168 int ttlp;
1169 const char *predicate = "if", *en, *op;
1170 int errorp;
1172 for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
1173 ttlp = 0;
1175 switch (u -> r_opcode)
1177 case NXRRSET:
1178 op = "rrset doesn't exist";
1179 position = 1;
1180 break;
1181 case YXRRSET:
1182 op = "rrset exists";
1183 position = 1;
1184 break;
1185 case NXDOMAIN:
1186 op = "domain doesn't exist";
1187 position = 1;
1188 break;
1189 case YXDOMAIN:
1190 op = "domain exists";
1191 position = 1;
1192 break;
1193 case ADD:
1194 op = "add";
1195 position = 0;
1196 ttlp = 1;
1197 break;
1198 case DELETE:
1199 op = "delete";
1200 position = 0;
1201 break;
1202 default:
1203 op = "unknown";
1204 position = 0;
1205 break;
1207 if (!position) {
1208 if (s != &obuf [0] && s + 1 < end)
1209 *s++ = ' ';
1210 if (s + strlen (op) < end) {
1211 strcpy (s, op);
1212 s += strlen (s);
1214 } else {
1215 if (s != &obuf [0] && s + 1 < end)
1216 *s++ = ' ';
1217 if (s + strlen (predicate) < end) {
1218 strcpy (s, predicate);
1219 s += strlen (s);
1221 predicate = "and";
1223 if (u -> r_dname) {
1224 if (s + 1 < end)
1225 *s++ = ' ';
1226 if (s + strlen (u -> r_dname) < end) {
1227 strcpy (s, u -> r_dname);
1228 s += strlen (s);
1231 if (ttlp) {
1232 if (s + 1 < end)
1233 *s++ = ' ';
1234 /* 27 is as big as a ttl can get. */
1235 if (s + 27 < end) {
1236 sprintf (s, "%lu",
1237 (unsigned long)(u -> r_ttl));
1238 s += strlen (s);
1241 switch (u -> r_class) {
1242 case C_IN:
1243 en = "IN";
1244 break;
1245 case C_CHAOS:
1246 en = "CHAOS";
1247 break;
1248 case C_HS:
1249 en = "HS";
1250 break;
1251 default:
1252 en = "UNKNOWN";
1253 break;
1255 if (s + strlen (en) < end) {
1256 if (s + 1 < end)
1257 *s++ = ' ';
1258 strcpy (s, en);
1259 s += strlen (en);
1261 switch (u -> r_type) {
1262 case T_A:
1263 en = "A";
1264 break;
1265 case T_PTR:
1266 en = "PTR";
1267 break;
1268 case T_MX:
1269 en = "MX";
1270 break;
1271 case T_TXT:
1272 en = "TXT";
1273 break;
1274 case T_KEY:
1275 en = "KEY";
1276 break;
1277 case T_CNAME:
1278 en = "CNAME";
1279 break;
1280 default:
1281 en = "UNKNOWN";
1282 break;
1284 if (s + strlen (en) < end) {
1285 if (s + 1 < end)
1286 *s++ = ' ';
1287 strcpy (s, en);
1288 s += strlen (en);
1290 if (u -> r_data) {
1291 if (s + 1 < end)
1292 *s++ = ' ';
1293 if (u -> r_type == T_TXT) {
1294 if (s + 1 < end)
1295 *s++ = '"';
1297 if(u->r_type == T_KEY) {
1298 strcat(s, "<keydata>");
1299 s+=strlen("<keydata>");
1301 else {
1302 if (s + u -> r_size < end) {
1303 memcpy (s, u -> r_data, u -> r_size);
1304 s += u -> r_size;
1305 if (u -> r_type == T_TXT) {
1306 if (s + 1 < end)
1307 *s++ = '"';
1312 if (position) {
1313 if (s + 1 < end)
1314 *s++ = ' ';
1315 if (s + strlen (op) < end) {
1316 strcpy (s, op);
1317 s += strlen (s);
1320 if (u == ISC_LIST_TAIL (*uq))
1321 break;
1323 if (s == &obuf [0]) {
1324 strcpy (s, "empty update");
1325 s += strlen (s);
1327 if (status == NOERROR)
1328 errorp = 0;
1329 else
1330 errorp = 1;
1331 en = isc_result_totext (status);
1332 #if 0
1333 switch (status) {
1334 case -1:
1335 en = "resolver failed";
1336 break;
1338 case FORMERR:
1339 en = "format error";
1340 break;
1342 case NOERROR:
1343 en = "succeeded";
1344 errorp = 0;
1345 break;
1347 case NOTAUTH:
1348 en = "not authorized";
1349 break;
1351 case NOTIMP:
1352 en = "not implemented";
1353 break;
1355 case NOTZONE:
1356 en = "not a single valid zone";
1357 break;
1359 case NXDOMAIN:
1360 en = "no such domain";
1361 break;
1363 case NXRRSET:
1364 en = "no such record";
1365 break;
1367 case REFUSED:
1368 en = "refused";
1369 break;
1371 case SERVFAIL:
1372 en = "server failed";
1373 break;
1375 case YXDOMAIN:
1376 en = "domain exists";
1377 break;
1379 case YXRRSET:
1380 en = "record exists";
1381 break;
1383 default:
1384 en = "unknown error";
1385 break;
1387 #endif
1389 if (s + 2 < end) {
1390 *s++ = ':';
1391 *s++ = ' ';
1393 if (s + strlen (en) < end) {
1394 strcpy (s, en);
1395 s += strlen (en);
1397 if (s + 1 < end)
1398 *s++ = '.';
1399 *s++ = 0;
1400 if (errorp)
1401 log_error ("%s", obuf);
1402 else
1403 log_info ("%s", obuf);
1405 #endif /* NSUPDATE */