File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / common / print.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:30:18 2012 UTC (12 years, 5 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /* print.c
    2: 
    3:    Turn data structures into printable text. */
    4: 
    5: /*
    6:  * Copyright (c) 2009-2011 by Internet Systems Consortium, Inc. ("ISC")
    7:  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
    8:  * Copyright (c) 1995-2003 by Internet Software Consortium
    9:  *
   10:  * Permission to use, copy, modify, and distribute this software for any
   11:  * purpose with or without fee is hereby granted, provided that the above
   12:  * copyright notice and this permission notice appear in all copies.
   13:  *
   14:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
   15:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   16:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
   17:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   18:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   19:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
   20:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   21:  *
   22:  *   Internet Systems Consortium, Inc.
   23:  *   950 Charter Street
   24:  *   Redwood City, CA 94063
   25:  *   <info@isc.org>
   26:  *   https://www.isc.org/
   27:  *
   28:  * This software has been written for Internet Systems Consortium
   29:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
   30:  * To learn more about Internet Systems Consortium, see
   31:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
   32:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
   33:  * ``http://www.nominum.com''.
   34:  */
   35: 
   36: #include "dhcpd.h"
   37: 
   38: int db_time_format = DEFAULT_TIME_FORMAT;
   39: 
   40: char *quotify_string (const char *s, const char *file, int line)
   41: {
   42: 	unsigned len = 0;
   43: 	const char *sp;
   44: 	char *buf, *nsp;
   45: 
   46: 	for (sp = s; sp && *sp; sp++) {
   47: 		if (*sp == ' ')
   48: 			len++;
   49: 		else if (!isascii ((int)*sp) || !isprint ((int)*sp))
   50: 			len += 4;
   51: 		else if (*sp == '"' || *sp == '\\')
   52: 			len += 2;
   53: 		else
   54: 			len++;
   55: 	}
   56: 
   57: 	buf = dmalloc (len + 1, file, line);
   58: 	if (buf) {
   59: 		nsp = buf;
   60: 		for (sp = s; sp && *sp; sp++) {
   61: 			if (*sp == ' ')
   62: 				*nsp++ = ' ';
   63: 			else if (!isascii ((int)*sp) || !isprint ((int)*sp)) {
   64: 				sprintf (nsp, "\\%03o",
   65: 					 *(const unsigned char *)sp);
   66: 				nsp += 4;
   67: 			} else if (*sp == '"' || *sp == '\\') {
   68: 				*nsp++ = '\\';
   69: 				*nsp++ = *sp;
   70: 			} else
   71: 				*nsp++ = *sp;
   72: 		}
   73: 		*nsp++ = 0;
   74: 	}
   75: 	return buf;
   76: }
   77: 
   78: char *quotify_buf (const unsigned char *s, unsigned len,
   79: 		   const char *file, int line)
   80: {
   81: 	unsigned nulen = 0;
   82: 	char *buf, *nsp;
   83: 	int i;
   84: 
   85: 	for (i = 0; i < len; i++) {
   86: 		if (s [i] == ' ')
   87: 			nulen++;
   88: 		else if (!isascii (s [i]) || !isprint (s [i]))
   89: 			nulen += 4;
   90: 		else if (s [i] == '"' || s [i] == '\\')
   91: 			nulen += 2;
   92: 		else
   93: 			nulen++;
   94: 	}
   95: 
   96: 	buf = dmalloc (nulen + 1, MDL);
   97: 	if (buf) {
   98: 		nsp = buf;
   99: 		for (i = 0; i < len; i++) {
  100: 			if (s [i] == ' ')
  101: 				*nsp++ = ' ';
  102: 			else if (!isascii (s [i]) || !isprint (s [i])) {
  103: 				sprintf (nsp, "\\%03o", s [i]);
  104: 				nsp += 4;
  105: 			} else if (s [i] == '"' || s [i] == '\\') {
  106: 				*nsp++ = '\\';
  107: 				*nsp++ = s [i];
  108: 			} else
  109: 				*nsp++ = s [i];
  110: 		}
  111: 		*nsp++ = 0;
  112: 	}
  113: 	return buf;
  114: }
  115: 
  116: char *print_base64 (const unsigned char *buf, unsigned len,
  117: 		    const char *file, int line)
  118: {
  119: 	char *s, *b;
  120: 	unsigned bl;
  121: 	int i;
  122: 	unsigned val, extra;
  123: 	static char to64 [] =
  124: 	   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  125: 
  126: 	bl = ((len * 4 + 2) / 3) + 1;
  127: 	b = dmalloc (bl + 1, file, line);
  128: 	if (!b)
  129: 		return (char *)0;
  130: 	
  131: 	i = 0;
  132: 	s = b;
  133: 	while (i != len) {
  134: 		val = buf [i++];
  135: 		extra = val & 3;
  136: 		val = val >> 2;
  137: 		*s++ = to64 [val];
  138: 		if (i == len) {
  139: 			*s++ = to64 [extra << 4];
  140: 			*s++ = '=';
  141: 			break;
  142: 		}
  143: 		val = (extra << 8) + buf [i++];
  144: 		extra = val & 15;
  145: 		val = val >> 4;
  146: 		*s++ = to64 [val];
  147: 		if (i == len) {
  148: 			*s++ = to64 [extra << 2];
  149: 			*s++ = '=';
  150: 			break;
  151: 		}
  152: 		val = (extra << 8) + buf [i++];
  153: 		extra = val & 0x3f;
  154: 		val = val >> 6;
  155: 		*s++ = to64 [val];
  156: 		*s++ = to64 [extra];
  157: 	}
  158: 	if (!len)
  159: 		*s++ = '=';
  160: 	*s++ = 0;
  161: 	if (s > b + bl + 1)
  162: 		abort ();
  163: 	return b;
  164: }
  165: 
  166: char *print_hw_addr (htype, hlen, data)
  167: 	int htype;
  168: 	int hlen;
  169: 	unsigned char *data;
  170: {
  171: 	static char habuf [49];
  172: 	char *s;
  173: 	int i;
  174: 
  175: 	if (hlen <= 0)
  176: 		habuf [0] = 0;
  177: 	else {
  178: 		s = habuf;
  179: 		for (i = 0; i < hlen; i++) {
  180: 			sprintf (s, "%02x", data [i]);
  181: 			s += strlen (s);
  182: 			*s++ = ':';
  183: 		}
  184: 		*--s = 0;
  185: 	}
  186: 	return habuf;
  187: }
  188: 
  189: void print_lease (lease)
  190: 	struct lease *lease;
  191: {
  192: 	struct tm *t;
  193: 	char tbuf [32];
  194: 
  195: 	log_debug ("  Lease %s",
  196: 	       piaddr (lease -> ip_addr));
  197: 	
  198: 	t = gmtime (&lease -> starts);
  199: 	strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
  200: 	log_debug ("  start %s", tbuf);
  201: 	
  202: 	t = gmtime (&lease -> ends);
  203: 	strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
  204: 	log_debug ("  end %s", tbuf);
  205: 	
  206: 	if (lease -> hardware_addr.hlen)
  207: 		log_debug ("    hardware addr = %s",
  208: 			   print_hw_addr (lease -> hardware_addr.hbuf [0],
  209: 					  lease -> hardware_addr.hlen - 1,
  210: 					  &lease -> hardware_addr.hbuf [1]));
  211: 	log_debug ("  host %s  ",
  212: 	       lease -> host ? lease -> host -> name : "<none>");
  213: }	
  214: 
  215: #if defined (DEBUG_PACKET)
  216: void dump_packet_option (struct option_cache *oc,
  217: 			 struct packet *packet,
  218: 			 struct lease *lease,
  219: 			 struct client_state *client,
  220: 			 struct option_state *in_options,
  221: 			 struct option_state *cfg_options,
  222: 			 struct binding_scope **scope,
  223: 			 struct universe *u, void *foo)
  224: {
  225: 	const char *name, *dot;
  226: 	struct data_string ds;
  227: 	memset (&ds, 0, sizeof ds);
  228: 
  229: 	if (u != &dhcp_universe) {
  230: 		name = u -> name;
  231: 		dot = ".";
  232: 	} else {
  233: 		name = "";
  234: 		dot = "";
  235: 	}
  236: 	if (evaluate_option_cache (&ds, packet, lease, client,
  237: 				   in_options, cfg_options, scope, oc, MDL)) {
  238: 		log_debug ("  option %s%s%s %s;\n",
  239: 			   name, dot, oc -> option -> name,
  240: 			   pretty_print_option (oc -> option,
  241: 						ds.data, ds.len, 1, 1));
  242: 		data_string_forget (&ds, MDL);
  243: 	}
  244: }
  245: 
  246: void dump_packet (tp)
  247: 	struct packet *tp;
  248: {
  249: 	struct dhcp_packet *tdp = tp -> raw;
  250: 
  251: 	log_debug ("packet length %d", tp -> packet_length);
  252: 	log_debug ("op = %d  htype = %d  hlen = %d  hops = %d",
  253: 	       tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
  254: 	log_debug ("xid = %x  secs = %ld  flags = %x",
  255: 	       tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
  256: 	log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
  257: 	log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
  258: 	log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
  259: 	log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
  260: 	log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
  261: 	       ((unsigned char *)(tdp -> chaddr)) [0],
  262: 	       ((unsigned char *)(tdp -> chaddr)) [1],
  263: 	       ((unsigned char *)(tdp -> chaddr)) [2],
  264: 	       ((unsigned char *)(tdp -> chaddr)) [3],
  265: 	       ((unsigned char *)(tdp -> chaddr)) [4],
  266: 	       ((unsigned char *)(tdp -> chaddr)) [5]);
  267: 	log_debug ("filename = %s", tdp -> file);
  268: 	log_debug ("server_name = %s", tdp -> sname);
  269: 	if (tp -> options_valid) {
  270: 		int i;
  271: 
  272: 		for (i = 0; i < tp -> options -> universe_count; i++) {
  273: 			if (tp -> options -> universes [i]) {
  274: 				option_space_foreach (tp, (struct lease *)0,
  275: 						      (struct client_state *)0,
  276: 						      (struct option_state *)0,
  277: 						      tp -> options,
  278: 						      &global_scope,
  279: 						      universes [i], 0,
  280: 						      dump_packet_option);
  281: 			}
  282: 		}
  283: 	}
  284: 	log_debug ("%s", "");
  285: }
  286: #endif
  287: 
  288: void dump_raw (buf, len)
  289: 	const unsigned char *buf;
  290: 	unsigned len;
  291: {
  292: 	int i;
  293: 	char lbuf [80];
  294: 	int lbix = 0;
  295: 
  296: /*
  297:           1         2         3         4         5         6         7
  298: 01234567890123456789012345678901234567890123456789012345678901234567890123
  299: 280: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   .................  
  300: */
  301: 
  302: 	memset(lbuf, ' ', 79);
  303: 	lbuf [79] = 0;
  304: 
  305: 	for (i = 0; i < len; i++) {
  306: 		if ((i & 15) == 0) {
  307: 		  if (lbix) {
  308: 		    	lbuf[53]=' ';
  309: 			lbuf[54]=' ';
  310: 			lbuf[55]=' ';
  311: 			lbuf[73]='\0';
  312: 			log_info ("%s", lbuf);
  313: 		  }
  314: 		  memset(lbuf, ' ', 79);
  315: 		  lbuf [79] = 0;
  316: 		  sprintf (lbuf, "%03x:", i);
  317: 		  lbix = 4;
  318: 		} else if ((i & 7) == 0)
  319: 			lbuf [lbix++] = ' ';
  320: 
  321: 		if(isprint(buf[i])) {
  322: 		  lbuf[56+(i%16)]=buf[i];
  323: 		} else {
  324: 		  lbuf[56+(i%16)]='.';
  325: 		}
  326: 
  327: 		sprintf (&lbuf [lbix], " %02x", buf [i]);
  328: 		lbix += 3;
  329: 		lbuf[lbix]=' ';
  330: 
  331: 	}
  332: 	lbuf[53]=' ';
  333: 	lbuf[54]=' ';
  334: 	lbuf[55]=' ';
  335: 	lbuf[73]='\0';
  336: 	log_info ("%s", lbuf);
  337: }
  338: 
  339: void hash_dump (table)
  340: 	struct hash_table *table;
  341: {
  342: 	int i;
  343: 	struct hash_bucket *bp;
  344: 
  345: 	if (!table)
  346: 		return;
  347: 
  348: 	for (i = 0; i < table -> hash_count; i++) {
  349: 		if (!table -> buckets [i])
  350: 			continue;
  351: 		log_info ("hash bucket %d:", i);
  352: 		for (bp = table -> buckets [i]; bp; bp = bp -> next) {
  353: 			if (bp -> len)
  354: 				dump_raw (bp -> name, bp -> len);
  355: 			else
  356: 				log_info ("%s", (const char *)bp -> name);
  357: 		}
  358: 	}
  359: }
  360: 
  361: /*
  362:  * print a string as hex.  This only outputs
  363:  * colon separated hex list no matter what
  364:  * the input looks like.  See print_hex
  365:  * for a function that prints either cshl
  366:  * or a string if all bytes are printible
  367:  * It only uses limit characters from buf
  368:  * and doesn't do anything if buf == NULL
  369:  *
  370:  * len - length of data
  371:  * data - input data
  372:  * limit - length of buf to use
  373:  * buf - output buffer
  374:  */
  375: void print_hex_only (len, data, limit, buf)
  376: 	unsigned len;
  377: 	const u_int8_t *data;
  378: 	unsigned limit;
  379: 	char *buf;
  380: {
  381: 	unsigned i;
  382: 
  383: 	if ((buf == NULL) || (limit < 3))
  384: 		return;
  385: 
  386: 	for (i = 0; (i < limit / 3) && (i < len); i++) {
  387: 		sprintf(&buf[i*3], "%02x:", data[i]);
  388: 	}
  389: 	buf[(i * 3) - 1] = 0;
  390: 	return;
  391: }
  392: 
  393: /*
  394:  * print a string as either text if all the characters
  395:  * are printable or colon separated hex if they aren't
  396:  *
  397:  * len - length of data
  398:  * data - input data
  399:  * limit - length of buf to use
  400:  * buf - output buffer
  401:  */
  402: void print_hex_or_string (len, data, limit, buf)
  403: 	unsigned len;
  404: 	const u_int8_t *data;
  405: 	unsigned limit;
  406: 	char *buf;
  407: {
  408: 	unsigned i;
  409: 	if ((buf == NULL) || (limit < 3))
  410: 		return;
  411: 
  412: 	for (i = 0; (i < (limit - 3)) && (i < len); i++) {
  413: 		if (!isascii(data[i]) || !isprint(data[i])) {
  414: 			print_hex_only(len, data, limit, buf);
  415: 			return;
  416: 		}
  417: 	}
  418: 
  419: 	buf[0] = '"';
  420: 	i = len;
  421: 	if (i > (limit - 3))
  422: 		i = limit - 3;
  423: 	memcpy(&buf[1], data, i);
  424: 	buf[i + 1] = '"';
  425: 	buf[i + 2] = 0;
  426: 	return;
  427: }
  428: 
  429: /*
  430:  * print a string as either hex or text
  431:  * using static buffers to hold the output
  432:  * 
  433:  * len - length of data
  434:  * data - input data
  435:  * limit - length of buf
  436:  * buf_num - the output buffer to use
  437:  */
  438: #define HBLEN 1024
  439: char *print_hex(len, data, limit, buf_num)
  440: 	unsigned len;
  441: 	const u_int8_t *data;
  442: 	unsigned limit;
  443: 	unsigned buf_num;
  444: {
  445: 	static char hex_buf_1[HBLEN + 1];
  446: 	static char hex_buf_2[HBLEN + 1];
  447: 	static char hex_buf_3[HBLEN + 1];
  448: 	char *hex_buf;
  449: 
  450: 	switch(buf_num) {
  451: 	  case 0:
  452: 		hex_buf = hex_buf_1;
  453: 		if (limit >= sizeof(hex_buf_1))
  454: 			limit = sizeof(hex_buf_1);
  455: 		break;
  456: 	  case 1:
  457: 		hex_buf = hex_buf_2;
  458: 		if (limit >= sizeof(hex_buf_2))
  459: 			limit = sizeof(hex_buf_2);
  460: 		break;
  461: 	  case 2:
  462: 		hex_buf = hex_buf_3;
  463: 		if (limit >= sizeof(hex_buf_3))
  464: 			limit = sizeof(hex_buf_3);
  465: 		break;
  466: 	  default:
  467: 		return(NULL);
  468: 	}
  469: 
  470: 	print_hex_or_string(len, data, limit, hex_buf);
  471: 	return(hex_buf);
  472: }
  473: 
  474: #define DQLEN	80
  475: 
  476: char *print_dotted_quads (len, data)
  477: 	unsigned len;
  478: 	const u_int8_t *data;
  479: {
  480: 	static char dq_buf [DQLEN + 1];
  481: 	int i;
  482: 	char *s, *last;
  483: 
  484: 	s = &dq_buf [0];
  485: 	last = s;
  486: 	
  487: 	i = 0;
  488: 
  489: 	/* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
  490: 	 * The sprintf can't exceed 18 bytes, and since the loop enforces
  491: 	 * 21 bytes of space per iteration at no time can we exit the
  492: 	 * loop without at least 3 bytes spare.
  493: 	 */
  494: 	do {
  495: 		sprintf (s, "%u.%u.%u.%u, ",
  496: 			 data [i], data [i + 1], data [i + 2], data [i + 3]);
  497: 		s += strlen (s);
  498: 		i += 4;
  499: 	} while ((s - &dq_buf [0] > DQLEN - 21) &&
  500: 		 i + 3 < len);
  501: 	if (i == len)
  502: 		s [-2] = 0;
  503: 	else
  504: 		strcpy (s, "...");
  505: 	return dq_buf;
  506: }
  507: 
  508: char *print_dec_1 (val)
  509: 	unsigned long val;
  510: {
  511: 	static char vbuf [32];
  512: 	sprintf (vbuf, "%lu", val);
  513: 	return vbuf;
  514: }
  515: 
  516: char *print_dec_2 (val)
  517: 	unsigned long val;
  518: {
  519: 	static char vbuf [32];
  520: 	sprintf (vbuf, "%lu", val);
  521: 	return vbuf;
  522: }
  523: 
  524: static unsigned print_subexpression (struct expression *, char *, unsigned);
  525: 
  526: static unsigned print_subexpression (expr, buf, len)
  527: 	struct expression *expr;
  528: 	char *buf;
  529: 	unsigned len;
  530: {
  531: 	unsigned rv, left;
  532: 	const char *s;
  533: 
  534: 	switch (expr -> op) {
  535: 	      case expr_none:
  536: 		if (len > 3) {
  537: 			strcpy (buf, "nil");
  538: 			return 3;
  539: 		}
  540: 		break;
  541: 		  
  542: 	      case expr_match:
  543: 		if (len > 7) {
  544: 			strcpy (buf, "(match)");
  545: 			return 7;
  546: 		}
  547: 		break;
  548: 
  549: 	      case expr_check:
  550: 		rv = 10 + strlen (expr -> data.check -> name);
  551: 		if (len > rv) {
  552: 			sprintf (buf, "(check %s)",
  553: 				 expr -> data.check -> name);
  554: 			return rv;
  555: 		}
  556: 		break;
  557: 
  558: 	      case expr_equal:
  559: 		if (len > 6) {
  560: 			rv = 4;
  561: 			strcpy (buf, "(eq ");
  562: 			rv += print_subexpression (expr -> data.equal [0],
  563: 						   buf + rv, len - rv - 2);
  564: 			buf [rv++] = ' ';
  565: 			rv += print_subexpression (expr -> data.equal [1],
  566: 						   buf + rv, len - rv - 1);
  567: 			buf [rv++] = ')';
  568: 			buf [rv] = 0;
  569: 			return rv;
  570: 		}
  571: 		break;
  572: 
  573: 	      case expr_not_equal:
  574: 		if (len > 7) {
  575: 			rv = 5;
  576: 			strcpy (buf, "(neq ");
  577: 			rv += print_subexpression (expr -> data.equal [0],
  578: 						   buf + rv, len - rv - 2);
  579: 			buf [rv++] = ' ';
  580: 			rv += print_subexpression (expr -> data.equal [1],
  581: 						   buf + rv, len - rv - 1);
  582: 			buf [rv++] = ')';
  583: 			buf [rv] = 0;
  584: 			return rv;
  585: 		}
  586: 		break;
  587: 
  588: 	      case expr_regex_match:
  589: 		if (len > 10) {
  590: 			rv = 4;
  591: 			strcpy(buf, "(regex ");
  592: 			rv += print_subexpression(expr->data.equal[0],
  593: 						  buf + rv, len - rv - 2);
  594: 			buf[rv++] = ' ';
  595: 			rv += print_subexpression(expr->data.equal[1],
  596: 						  buf + rv, len - rv - 1);
  597: 			buf[rv++] = ')';
  598: 			buf[rv] = 0;
  599: 			return rv;
  600: 		}
  601: 		break;
  602: 
  603: 	      case expr_substring:
  604: 		if (len > 11) {
  605: 			rv = 8;
  606: 			strcpy (buf, "(substr ");
  607: 			rv += print_subexpression (expr -> data.substring.expr,
  608: 						   buf + rv, len - rv - 3);
  609: 			buf [rv++] = ' ';
  610: 			rv += print_subexpression
  611: 				(expr -> data.substring.offset,
  612: 				 buf + rv, len - rv - 2);
  613: 			buf [rv++] = ' ';
  614: 			rv += print_subexpression (expr -> data.substring.len,
  615: 						   buf + rv, len - rv - 1);
  616: 			buf [rv++] = ')';
  617: 			buf [rv] = 0;
  618: 			return rv;
  619: 		}
  620: 		break;
  621: 
  622: 	      case expr_suffix:
  623: 		if (len > 10) {
  624: 			rv = 8;
  625: 			strcpy (buf, "(suffix ");
  626: 			rv += print_subexpression (expr -> data.suffix.expr,
  627: 						   buf + rv, len - rv - 2);
  628: 			if (len > rv)
  629: 				buf [rv++] = ' ';
  630: 			rv += print_subexpression (expr -> data.suffix.len,
  631: 						   buf + rv, len - rv - 1);
  632: 			if (len > rv)
  633: 				buf [rv++] = ')';
  634: 			buf [rv] = 0;
  635: 			return rv;
  636: 		}
  637: 		break;
  638: 
  639: 	      case expr_lcase:
  640: 		if (len > 9) {
  641: 			rv = 7;
  642: 			strcpy(buf, "(lcase ");
  643: 			rv += print_subexpression(expr->data.lcase,
  644: 						  buf + rv, len - rv - 1);
  645: 			buf[rv++] = ')';
  646: 			buf[rv] = 0;
  647: 			return rv;
  648: 		}
  649: 		break;
  650: 
  651: 	      case expr_ucase:
  652: 		if (len > 9) {
  653: 			rv = 7;
  654: 			strcpy(buf, "(ucase ");
  655: 			rv += print_subexpression(expr->data.ucase,
  656: 						  buf + rv, len - rv - 1);
  657: 			buf[rv++] = ')';
  658: 			buf[rv] = 0;
  659: 			return rv;
  660: 		}
  661: 		break;
  662: 
  663: 	      case expr_concat:
  664: 		if (len > 10) {
  665: 			rv = 8;
  666: 			strcpy (buf, "(concat ");
  667: 			rv += print_subexpression (expr -> data.concat [0],
  668: 						   buf + rv, len - rv - 2);
  669: 			buf [rv++] = ' ';
  670: 			rv += print_subexpression (expr -> data.concat [1],
  671: 						   buf + rv, len - rv - 1);
  672: 			buf [rv++] = ')';
  673: 			buf [rv] = 0;
  674: 			return rv;
  675: 		}
  676: 		break;
  677: 
  678: 	      case expr_pick_first_value:
  679: 		if (len > 8) {
  680: 			rv = 6;
  681: 			strcpy (buf, "(pick1st ");
  682: 			rv += print_subexpression
  683: 				(expr -> data.pick_first_value.car,
  684: 				 buf + rv, len - rv - 2);
  685: 			buf [rv++] = ' ';
  686: 			rv += print_subexpression
  687: 				(expr -> data.pick_first_value.cdr,
  688: 				 buf + rv, len - rv - 1);
  689: 			buf [rv++] = ')';
  690: 			buf [rv] = 0;
  691: 			return rv;
  692: 		}
  693: 		break;
  694: 
  695: 	      case expr_host_lookup:
  696: 		rv = 15 + strlen (expr -> data.host_lookup -> hostname);
  697: 		if (len > rv) {
  698: 			sprintf (buf, "(dns-lookup %s)",
  699: 				 expr -> data.host_lookup -> hostname);
  700: 			return rv;
  701: 		}
  702: 		break;
  703: 
  704: 	      case expr_and:
  705: 		s = "and";
  706: 	      binop:
  707: 		rv = strlen (s);
  708: 		if (len > rv + 4) {
  709: 			buf [0] = '(';
  710: 			strcpy (&buf [1], s);
  711: 			rv += 1;
  712: 			buf [rv++] = ' ';
  713: 			rv += print_subexpression (expr -> data.and [0],
  714: 						buf + rv, len - rv - 2);
  715: 			buf [rv++] = ' ';
  716: 			rv += print_subexpression (expr -> data.and [1],
  717: 						   buf + rv, len - rv - 1);
  718: 			buf [rv++] = ')';
  719: 			buf [rv] = 0;
  720: 			return rv;
  721: 		}
  722: 		break;
  723: 
  724: 	      case expr_or:
  725: 		s = "or";
  726: 		goto binop;
  727: 
  728: 	      case expr_add:
  729: 		s = "+";
  730: 		goto binop;
  731: 
  732: 	      case expr_subtract:
  733: 		s = "-";
  734: 		goto binop;
  735: 
  736: 	      case expr_multiply:
  737: 		s = "*";
  738: 		goto binop;
  739: 
  740: 	      case expr_divide:
  741: 		s = "/";
  742: 		goto binop;
  743: 
  744: 	      case expr_remainder:
  745: 		s = "%";
  746: 		goto binop;
  747: 
  748: 	      case expr_binary_and:
  749: 		s = "&";
  750: 		goto binop;
  751: 
  752: 	      case expr_binary_or:
  753: 		s = "|";
  754: 		goto binop;
  755: 
  756: 	      case expr_binary_xor:
  757: 		s = "^";
  758: 		goto binop;
  759: 		
  760: 	      case expr_not:
  761: 		if (len > 6) {
  762: 			rv = 5;
  763: 			strcpy (buf, "(not ");
  764: 			rv += print_subexpression (expr -> data.not,
  765: 						   buf + rv, len - rv - 1);
  766: 			buf [rv++] = ')';
  767: 			buf [rv] = 0;
  768: 			return rv;
  769: 		}
  770: 		break;
  771: 
  772: 	      case expr_config_option:
  773: 		s = "cfg-option";
  774: 		goto dooption;
  775: 
  776: 	      case expr_option:
  777: 		s = "option";
  778: 	      dooption:
  779: 		rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
  780: 			   strlen (expr -> data.option -> universe -> name));
  781: 		if (len > rv) {
  782: 			sprintf (buf, "(option %s.%s)",
  783: 				 expr -> data.option -> universe -> name,
  784: 				 expr -> data.option -> name);
  785: 			return rv;
  786: 		}
  787: 		break;
  788: 
  789: 	      case expr_hardware:
  790: 		if (len > 10) {
  791: 			strcpy (buf, "(hardware)");
  792: 			return 10;
  793: 		}
  794: 		break;
  795: 
  796: 	      case expr_packet:
  797: 		if (len > 10) {
  798: 			rv = 8;
  799: 			strcpy (buf, "(substr ");
  800: 			rv += print_subexpression (expr -> data.packet.offset,
  801: 						   buf + rv, len - rv - 2);
  802: 			buf [rv++] = ' ';
  803: 			rv += print_subexpression (expr -> data.packet.len,
  804: 						   buf + rv, len - rv - 1);
  805: 			buf [rv++] = ')';
  806: 			buf [rv] = 0;
  807: 			return rv;
  808: 		}
  809: 		break;
  810: 
  811: 	      case expr_const_data:
  812: 		s = print_hex_1 (expr -> data.const_data.len,
  813: 				 expr -> data.const_data.data, len);
  814: 		rv = strlen (s);
  815: 		if (rv >= len)
  816: 			rv = len - 1;
  817: 		strncpy (buf, s, rv);
  818: 		buf [rv] = 0;
  819: 		return rv;
  820: 
  821: 	      case expr_encapsulate:
  822: 		rv = 13;
  823: 		strcpy (buf, "(encapsulate ");
  824: 		rv += expr -> data.encapsulate.len;
  825: 		if (rv + 2 > len)
  826: 			rv = len - 2;
  827: 		strncpy (buf,
  828: 			 (const char *)expr -> data.encapsulate.data, rv - 13);
  829: 		buf [rv++] = ')';
  830: 		buf [rv++] = 0;
  831: 		break;
  832: 
  833: 	      case expr_extract_int8:
  834: 		if (len > 7) {
  835: 			rv = 6;
  836: 			strcpy (buf, "(int8 ");
  837: 			rv += print_subexpression (expr -> data.extract_int,
  838: 						   buf + rv, len - rv - 1);
  839: 			buf [rv++] = ')';
  840: 			buf [rv] = 0;
  841: 			return rv;
  842: 		}
  843: 		break;
  844: 
  845: 	      case expr_extract_int16:
  846: 		if (len > 8) {
  847: 			rv = 7;
  848: 			strcpy (buf, "(int16 ");
  849: 			rv += print_subexpression (expr -> data.extract_int,
  850: 						   buf + rv, len - rv - 1);
  851: 			buf [rv++] = ')';
  852: 			buf [rv] = 0;
  853: 			return rv;
  854: 		}
  855: 		break;
  856: 
  857: 	      case expr_extract_int32:
  858: 		if (len > 8) {
  859: 			rv = 7;
  860: 			strcpy (buf, "(int32 ");
  861: 			rv += print_subexpression (expr -> data.extract_int,
  862: 						   buf + rv, len - rv - 1);
  863: 			buf [rv++] = ')';
  864: 			buf [rv] = 0;
  865: 			return rv;
  866: 		}
  867: 		break;
  868: 
  869: 	      case expr_encode_int8:
  870: 		if (len > 7) {
  871: 			rv = 6;
  872: 			strcpy (buf, "(to-int8 ");
  873: 			rv += print_subexpression (expr -> data.encode_int,
  874: 						   buf + rv, len - rv - 1);
  875: 			buf [rv++] = ')';
  876: 			buf [rv] = 0;
  877: 			return rv;
  878: 		}
  879: 		break;
  880: 
  881: 	      case expr_encode_int16:
  882: 		if (len > 8) {
  883: 			rv = 7;
  884: 			strcpy (buf, "(to-int16 ");
  885: 			rv += print_subexpression (expr -> data.encode_int,
  886: 						   buf + rv, len - rv - 1);
  887: 			buf [rv++] = ')';
  888: 			buf [rv] = 0;
  889: 			return rv;
  890: 		}
  891: 		break;
  892: 
  893: 	      case expr_encode_int32:
  894: 		if (len > 8) {
  895: 			rv = 7;
  896: 			strcpy (buf, "(to-int32 ");
  897: 			rv += print_subexpression (expr -> data.encode_int,
  898: 						   buf + rv, len - rv - 1);
  899: 			buf [rv++] = ')';
  900: 			buf [rv] = 0;
  901: 			return rv;
  902: 		}
  903: 		break;
  904: 
  905: 	      case expr_const_int:
  906: 		s = print_dec_1 (expr -> data.const_int);
  907: 		rv = strlen (s);
  908: 		if (len > rv) {
  909: 			strcpy (buf, s);
  910: 			return rv;
  911: 		}
  912: 		break;
  913: 
  914: 	      case expr_exists:
  915: 		rv = 10 + (strlen (expr -> data.option -> name) +
  916: 			   strlen (expr -> data.option -> universe -> name));
  917: 		if (len > rv) {
  918: 			sprintf (buf, "(exists %s.%s)",
  919: 				 expr -> data.option -> universe -> name,
  920: 				 expr -> data.option -> name);
  921: 			return rv;
  922: 		}
  923: 		break;
  924: 
  925: 	      case expr_variable_exists:
  926: 		rv = 10 + strlen (expr -> data.variable);
  927: 		if (len > rv) {
  928: 			sprintf (buf, "(defined %s)", expr -> data.variable);
  929: 			return rv;
  930: 		}
  931: 		break;
  932: 
  933: 	      case expr_variable_reference:
  934: 		rv = strlen (expr -> data.variable);
  935: 		if (len > rv) {
  936: 			sprintf (buf, "%s", expr -> data.variable);
  937: 			return rv;
  938: 		}
  939: 		break;
  940: 
  941: 	      case expr_known:
  942: 		s = "known";
  943: 	      astring:
  944: 		rv = strlen (s);
  945: 		if (len > rv) {
  946: 			strcpy (buf, s);
  947: 			return rv;
  948: 		}
  949: 		break;
  950: 
  951: 	      case expr_leased_address:
  952: 		s = "leased-address";
  953: 		goto astring;
  954: 
  955: 	      case expr_client_state:
  956: 		s = "client-state";
  957: 		goto astring;
  958: 
  959: 	      case expr_host_decl_name:
  960: 		s = "host-decl-name";
  961: 		goto astring;
  962: 
  963: 	      case expr_lease_time:
  964: 		s = "lease-time";
  965: 		goto astring;
  966: 
  967: 	      case expr_static:
  968: 		s = "static";
  969: 		goto astring;
  970: 
  971: 	      case expr_filename:
  972: 		s = "filename";
  973: 		goto astring;
  974: 
  975: 	      case expr_sname:
  976: 		s = "server-name";
  977: 		goto astring;
  978: 
  979: 	      case expr_reverse:
  980: 		if (len > 11) {
  981: 			rv = 13;
  982: 			strcpy (buf, "(reverse ");
  983: 			rv += print_subexpression (expr -> data.reverse.width,
  984: 						   buf + rv, len - rv - 2);
  985: 			buf [rv++] = ' ';
  986: 			rv += print_subexpression (expr -> data.reverse.buffer,
  987: 						   buf + rv, len - rv - 1);
  988: 			buf [rv++] = ')';
  989: 			buf [rv] = 0;
  990: 			return rv;
  991: 		}
  992: 		break;
  993: 
  994: 	      case expr_binary_to_ascii:
  995: 		if (len > 5) {
  996: 			rv = 9;
  997: 			strcpy (buf, "(b2a ");
  998: 			rv += print_subexpression (expr -> data.b2a.base,
  999: 						   buf + rv, len - rv - 4);
 1000: 			buf [rv++] = ' ';
 1001: 			rv += print_subexpression (expr -> data.b2a.width,
 1002: 						   buf + rv, len - rv - 3);
 1003: 			buf [rv++] = ' ';
 1004: 			rv += print_subexpression (expr -> data.b2a.separator,
 1005: 						   buf + rv, len - rv - 2);
 1006: 			buf [rv++] = ' ';
 1007: 			rv += print_subexpression (expr -> data.b2a.buffer,
 1008: 						   buf + rv, len - rv - 1);
 1009: 			buf [rv++] = ')';
 1010: 			buf [rv] = 0;
 1011: 			return rv;
 1012: 		}
 1013: 		break;
 1014: 
 1015: 	      case expr_dns_transaction:
 1016: 		rv = 10;
 1017: 		if (len < rv + 2) {
 1018: 			buf [0] = '(';
 1019: 			strcpy (&buf [1], "ns-update ");
 1020: 			while (len < rv + 2) {
 1021: 				rv += print_subexpression
 1022: 					(expr -> data.dns_transaction.car,
 1023: 					 buf + rv, len - rv - 2);
 1024: 				buf [rv++] = ' ';
 1025: 				expr = expr -> data.dns_transaction.cdr;
 1026: 			}
 1027: 			buf [rv - 1] = ')';
 1028: 			buf [rv] = 0;
 1029: 			return rv;
 1030: 		}
 1031: 		return 0;
 1032: 
 1033: 	      case expr_ns_delete:
 1034: 		s = "delete";
 1035: 		left = 4;
 1036: 		goto dodnsupd;
 1037: 	      case expr_ns_exists:
 1038: 		s = "exists";
 1039: 		left = 4;
 1040: 		goto dodnsupd;
 1041: 	      case expr_ns_not_exists:
 1042: 		s = "not_exists";
 1043: 		left = 4;
 1044: 		goto dodnsupd;
 1045: 	      case expr_ns_add:
 1046: 		s = "update";
 1047: 		left = 5;
 1048: 	      dodnsupd:
 1049: 		rv = strlen (s);
 1050: 		if (len > strlen (s) + 1) {
 1051: 			buf [0] = '(';
 1052: 			strcpy (buf + 1, s);
 1053: 			rv++;
 1054: 			buf [rv++] = ' ';
 1055: 			s = print_dec_1 (expr -> data.ns_add.rrclass);
 1056: 			if (len > rv + strlen (s) + left) {
 1057: 				strcpy (&buf [rv], s);
 1058: 				rv += strlen (&buf [rv]);
 1059: 			}
 1060: 			buf [rv++] = ' ';
 1061: 			left--;
 1062: 			s = print_dec_1 (expr -> data.ns_add.rrtype);
 1063: 			if (len > rv + strlen (s) + left) {
 1064: 				strcpy (&buf [rv], s);
 1065: 				rv += strlen (&buf [rv]);
 1066: 			}
 1067: 			buf [rv++] = ' ';
 1068: 			left--;
 1069: 			rv += print_subexpression
 1070: 				(expr -> data.ns_add.rrname,
 1071: 				 buf + rv, len - rv - left);
 1072: 			buf [rv++] = ' ';
 1073: 			left--;
 1074: 			rv += print_subexpression
 1075: 				(expr -> data.ns_add.rrdata,
 1076: 				 buf + rv, len - rv - left);
 1077: 			buf [rv++] = ' ';
 1078: 			left--;
 1079: 			rv += print_subexpression
 1080: 				(expr -> data.ns_add.ttl,
 1081: 				 buf + rv, len - rv - left);
 1082: 			buf [rv++] = ')';
 1083: 			buf [rv] = 0;
 1084: 			return rv;
 1085: 		}
 1086: 		break;
 1087: 
 1088: 	      case expr_null:
 1089: 		if (len > 6) {
 1090: 			strcpy (buf, "(null)");
 1091: 			return 6;
 1092: 		}
 1093: 		break;
 1094: 	      case expr_funcall:
 1095: 		rv = 12 + strlen (expr -> data.funcall.name);
 1096: 		if (len > rv + 1) {
 1097: 			strcpy (buf, "(funcall  ");
 1098: 			strcpy (buf + 9, expr -> data.funcall.name);
 1099: 			buf [rv++] = ' ';
 1100: 			rv += print_subexpression
 1101: 				(expr -> data.funcall.arglist, buf + rv,
 1102: 				 len - rv - 1);
 1103: 			buf [rv++] = ')';
 1104: 			buf [rv] = 0;
 1105: 			return rv;
 1106: 		}
 1107: 		break;
 1108: 
 1109: 	      case expr_arg:
 1110: 		rv = print_subexpression (expr -> data.arg.val, buf, len);
 1111: 		if (expr -> data.arg.next && rv + 2 < len) {
 1112: 			buf [rv++] = ' ';
 1113: 			rv += print_subexpression (expr -> data.arg.next,
 1114: 						   buf, len);
 1115: 			if (rv + 1 < len)
 1116: 				buf [rv++] = 0;
 1117: 			return rv;
 1118: 		}
 1119: 		break;
 1120: 
 1121: 	      case expr_function:
 1122: 		rv = 9;
 1123: 		if (len > rv + 1) {
 1124: 			struct string_list *foo;
 1125: 			strcpy (buf, "(function");
 1126: 			for (foo = expr -> data.func -> args;
 1127: 			     foo; foo = foo -> next) {
 1128: 				if (len > rv + 2 + strlen (foo -> string)) {
 1129: 					buf [rv - 1] = ' ';
 1130: 					strcpy (&buf [rv], foo -> string);
 1131: 					rv += strlen (foo -> string);
 1132: 				}
 1133: 			}
 1134: 			buf [rv++] = ')';
 1135: 			buf [rv] = 0;
 1136: 			return rv;
 1137: 		}
 1138: 
 1139: 	      default:
 1140: 		log_fatal("Impossible case at %s:%d (undefined expression "
 1141: 			  "%d).", MDL, expr->op);
 1142: 		break;
 1143: 	}
 1144: 	return 0;
 1145: }
 1146: 
 1147: void print_expression (name, expr)
 1148: 	const char *name;
 1149: 	struct expression *expr;
 1150: {
 1151: 	char buf [1024];
 1152: 
 1153: 	print_subexpression (expr, buf, sizeof buf);
 1154: 	log_info ("%s: %s", name, buf);
 1155: }
 1156: 
 1157: int token_print_indent_concat (FILE *file, int col,  int indent,
 1158: 			       const char *prefix, 
 1159: 			       const char *suffix, ...)
 1160: {
 1161: 	va_list list;
 1162: 	unsigned len;
 1163: 	char *s, *t, *u;
 1164: 
 1165: 	va_start (list, suffix);
 1166: 	s = va_arg (list, char *);
 1167: 	len = 0;
 1168: 	while (s) {
 1169: 		len += strlen (s);
 1170: 		s = va_arg (list, char *);
 1171: 	}
 1172: 	va_end (list);
 1173: 
 1174: 	t = dmalloc (len + 1, MDL);
 1175: 	if (!t)
 1176: 		log_fatal ("token_print_indent: no memory for copy buffer");
 1177: 
 1178: 	va_start (list, suffix);
 1179: 	s = va_arg (list, char *);
 1180: 	u = t;
 1181: 	while (s) {
 1182: 		len = strlen (s);
 1183: 		strcpy (u, s);
 1184: 		u += len;
 1185: 		s = va_arg (list, char *);
 1186: 	}
 1187: 	va_end (list);
 1188: 	
 1189: 	len = token_print_indent (file, col, indent,
 1190: 				  prefix, suffix, t);
 1191: 	dfree (t, MDL);
 1192: 	return col;
 1193: }
 1194: 
 1195: int token_indent_data_string (FILE *file, int col, int indent,
 1196: 			      const char *prefix, const char *suffix,
 1197: 			      struct data_string *data)
 1198: {
 1199: 	int i;
 1200: 	char *buf;
 1201: 	char obuf [3];
 1202: 
 1203: 	/* See if this is just ASCII. */
 1204: 	for (i = 0; i < data -> len; i++)
 1205: 		if (!isascii (data -> data [i]) ||
 1206: 		    !isprint (data -> data [i]))
 1207: 			break;
 1208: 
 1209: 	/* If we have a purely ASCII string, output it as text. */
 1210: 	if (i == data -> len) {
 1211: 		buf = dmalloc (data -> len + 3, MDL);
 1212: 		if (buf) {
 1213: 			buf [0] = '"';
 1214: 			memcpy (buf + 1, data -> data, data -> len);
 1215: 			buf [data -> len + 1] = '"';
 1216: 			buf [data -> len + 2] = 0;
 1217: 			i = token_print_indent (file, col, indent,
 1218: 						prefix, suffix, buf);
 1219: 			dfree (buf, MDL);
 1220: 			return i;
 1221: 		}
 1222: 	}
 1223: 
 1224: 	for (i = 0; i < data -> len; i++) {
 1225: 		sprintf (obuf, "%2.2x", data -> data [i]);
 1226: 		col = token_print_indent (file, col, indent,
 1227: 					  i == 0 ? prefix : "",
 1228: 					  (i + 1 == data -> len
 1229: 					   ? suffix
 1230: 					   : ""), obuf);
 1231: 		if (i + 1 != data -> len)
 1232: 			col = token_print_indent (file, col, indent,
 1233: 						  prefix, suffix, ":");
 1234: 	}
 1235: 	return col;
 1236: }
 1237: 
 1238: int token_print_indent (FILE *file, int col, int indent,
 1239: 			const char *prefix,
 1240: 			const char *suffix, const char *buf)
 1241: {
 1242: 	int len = strlen (buf) + strlen (prefix);
 1243: 	if (col + len > 79) {
 1244: 		if (indent + len < 79) {
 1245: 			indent_spaces (file, indent);
 1246: 			col = indent;
 1247: 		} else {
 1248: 			indent_spaces (file, col);
 1249: 			col = len > 79 ? 0 : 79 - len - 1;
 1250: 		}
 1251: 	} else if (prefix && *prefix) {
 1252: 		fputs (prefix, file);
 1253: 		col += strlen (prefix);
 1254: 	}
 1255: 	fputs (buf, file);
 1256: 	col += len;
 1257: 	if (suffix && *suffix) {
 1258: 		if (col + strlen (suffix) > 79) {
 1259: 			indent_spaces (file, indent);
 1260: 			col = indent;
 1261: 		} else {
 1262: 			fputs (suffix, file);
 1263: 			col += strlen (suffix);
 1264: 		}
 1265: 	}
 1266: 	return col;
 1267: }
 1268: 
 1269: void indent_spaces (FILE *file, int indent)
 1270: {
 1271: 	int i;
 1272: 	fputc ('\n', file);
 1273: 	for (i = 0; i < indent; i++)
 1274: 		fputc (' ', file);
 1275: }
 1276: 
 1277: #if defined (NSUPDATE)
 1278: void print_dns_status (int status, ns_updque *uq)
 1279: {
 1280: 	char obuf [1024];
 1281: 	char *s = &obuf [0], *end = &obuf [1022];
 1282: 	ns_updrec *u;
 1283: 	int position;
 1284: 	int ttlp;
 1285: 	const char *predicate = "if", *en, *op;
 1286: 	int errorp;
 1287: 
 1288: 	for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
 1289: 		ttlp = 0;
 1290: 
 1291: 		switch (u -> r_opcode)
 1292: 		{
 1293: 		      case NXRRSET:
 1294: 			op = "rrset doesn't exist";
 1295: 			position = 1;
 1296: 			break;
 1297: 		      case YXRRSET:
 1298: 			op = "rrset exists";
 1299: 			position = 1;
 1300: 			break;
 1301: 		      case NXDOMAIN:
 1302: 			op = "domain doesn't exist";
 1303: 			position = 1;
 1304: 			break;
 1305: 		      case YXDOMAIN:
 1306: 			op = "domain exists";
 1307: 			position = 1;
 1308: 			break;
 1309: 		      case ADD:
 1310: 			op = "add";
 1311: 			position = 0;
 1312: 			ttlp = 1;
 1313: 			break;
 1314: 		      case DELETE:
 1315: 			op = "delete";
 1316: 			position = 0;
 1317: 			break;
 1318: 		      default:
 1319: 			op = "unknown";
 1320: 			position = 0;
 1321: 			break;
 1322: 		}
 1323: 		if (!position) {
 1324: 			if (s != &obuf [0] && s + 1 < end)
 1325: 				*s++ = ' ';
 1326: 			if (s + strlen (op) < end) {
 1327: 				strcpy (s, op);
 1328: 				s += strlen (s);
 1329: 			}
 1330: 		} else {
 1331: 			if (s != &obuf [0] && s + 1 < end)
 1332: 				*s++ = ' ';
 1333: 			if (s + strlen (predicate) < end) {
 1334: 				strcpy (s, predicate);
 1335: 				s += strlen (s);
 1336: 			}
 1337: 			predicate = "and";
 1338: 		}
 1339: 		if (u -> r_dname) {
 1340: 			if (s + 1 < end)
 1341: 				*s++ = ' ';
 1342: 			if (s + strlen (u -> r_dname) < end) {
 1343: 				strcpy (s, u -> r_dname);
 1344: 				s += strlen (s);
 1345: 			}
 1346: 		}
 1347: 		if (ttlp) {
 1348: 			if (s + 1 < end)
 1349: 				*s++ = ' ';
 1350: 			/* 27 is as big as a ttl can get. */
 1351: 			if (s + 27 < end) {
 1352: 				sprintf (s, "%lu",
 1353: 					 (unsigned long)(u -> r_ttl));
 1354: 				s += strlen (s);
 1355: 			}
 1356: 		}
 1357: 		switch (u -> r_class) {
 1358: 		      case C_IN:
 1359: 			en = "IN";
 1360: 			break;
 1361: 		      case C_CHAOS:
 1362: 			en = "CHAOS";
 1363: 			break;
 1364: 		      case C_HS:
 1365: 			en = "HS";
 1366: 			break;
 1367: 		      default:
 1368: 			en = "UNKNOWN";
 1369: 			break;
 1370: 		}
 1371: 		if (s + strlen (en) < end) {
 1372: 			if (s + 1 < end)
 1373: 				*s++ = ' ';
 1374: 			strcpy (s, en);
 1375: 			s += strlen (en);
 1376: 		}
 1377: 		switch (u -> r_type) {
 1378: 		      case T_A:
 1379: 			en = "A";
 1380: 			break;
 1381: 		      case T_AAAA:
 1382: 			en = "AAAA";
 1383: 			break;
 1384: 		      case T_PTR:
 1385: 			en = "PTR";
 1386: 			break;
 1387: 		      case T_MX:
 1388: 			en = "MX";
 1389: 			break;
 1390: 		      case T_TXT:
 1391: 			en = "TXT";
 1392: 			break;
 1393: 		      case T_KEY:
 1394: 			en = "KEY";
 1395: 			break;
 1396: 		      case T_CNAME:
 1397: 			en = "CNAME";
 1398: 			break;
 1399: 		      default:
 1400: 			en = "UNKNOWN";
 1401: 			break;
 1402: 		}
 1403: 		if (s + strlen (en) < end) {
 1404: 			if (s + 1 < end)
 1405: 				*s++ = ' ';
 1406: 			strcpy (s, en);
 1407: 			s += strlen (en);
 1408: 		}
 1409: 		if (u -> r_data) {
 1410: 			if (s + 1 < end)
 1411: 				*s++ = ' ';
 1412: 			if (u -> r_type == T_TXT) {
 1413: 				if (s + 1 < end)
 1414: 					*s++ = '"';
 1415: 			}
 1416: 			if(u->r_type == T_KEY) {
 1417: 			  strcat(s, "<keydata>");
 1418: 			  s+=strlen("<keydata>");
 1419: 			}
 1420: 			else {  
 1421: 			  if (s + u -> r_size < end) {
 1422: 			    memcpy (s, u -> r_data, u -> r_size);
 1423: 			    s += u -> r_size;
 1424: 			    if (u -> r_type == T_TXT) {
 1425: 			      if (s + 1 < end)
 1426: 				*s++ = '"';
 1427: 			    }
 1428: 			  }
 1429: 			}
 1430: 		}
 1431: 		if (position) {
 1432: 			if (s + 1 < end)
 1433: 				*s++ = ' ';
 1434: 			if (s + strlen (op) < end) {
 1435: 				strcpy (s, op);
 1436: 				s += strlen (s);
 1437: 			}
 1438: 		}
 1439: 		if (u == ISC_LIST_TAIL (*uq))
 1440: 			break;
 1441: 	}
 1442: 	if (s == &obuf [0]) {
 1443: 		strcpy (s, "empty update");
 1444: 		s += strlen (s);
 1445: 	}
 1446: 	if (status == NOERROR)
 1447: 		errorp = 0;
 1448: 	else
 1449: 		errorp = 1;
 1450: 	en = isc_result_totext (status);
 1451: #if 0
 1452: 	switch (status) {
 1453: 	      case -1:
 1454: 		en = "resolver failed";
 1455: 		break;
 1456: 
 1457: 	      case FORMERR:
 1458: 		en = "format error";
 1459: 		break;
 1460: 
 1461: 	      case NOERROR:
 1462: 		en = "succeeded";
 1463: 		errorp = 0;
 1464: 		break;
 1465: 
 1466: 	      case NOTAUTH:
 1467: 		en = "not authorized";
 1468: 		break;
 1469: 
 1470: 	      case NOTIMP:
 1471: 		en = "not implemented";
 1472: 		break;
 1473: 
 1474: 	      case NOTZONE:
 1475: 		en = "not a single valid zone";
 1476: 		break;
 1477: 
 1478: 	      case NXDOMAIN:
 1479: 		en = "no such domain";
 1480: 		break;
 1481: 
 1482: 	      case NXRRSET:
 1483: 		en = "no such record";
 1484: 		break;
 1485: 
 1486: 	      case REFUSED:
 1487: 		en = "refused";
 1488: 		break;
 1489: 
 1490: 	      case SERVFAIL:
 1491: 		en = "server failed";
 1492: 		break;
 1493: 
 1494: 	      case YXDOMAIN:
 1495: 		en = "domain exists";
 1496: 		break;
 1497: 
 1498: 	      case YXRRSET:
 1499: 		en = "record exists";
 1500: 		break;
 1501: 
 1502: 	      default:
 1503: 		en = "unknown error";
 1504: 		break;
 1505: 	}
 1506: #endif
 1507: 
 1508: 	if (s + 2 < end) {
 1509: 		*s++ = ':';
 1510: 		*s++ = ' ';
 1511: 	}
 1512: 	if (s + strlen (en) < end) {
 1513: 		strcpy (s, en);
 1514: 		s += strlen (en);
 1515: 	}
 1516: 	if (s + 1 < end)
 1517: 		*s++ = '.';
 1518: 	*s++ = 0;
 1519: 	if (errorp)
 1520: 		log_error ("%s", obuf);
 1521: 	else
 1522: 		log_info ("%s", obuf);
 1523: }
 1524: #endif /* NSUPDATE */
 1525: 
 1526: /* Format the given time as "A; # B", where A is the format
 1527:  * used by the parser, and B is the local time, for humans.
 1528:  */
 1529: const char *
 1530: print_time(TIME t)
 1531: {
 1532: 	static char buf[sizeof("epoch 9223372036854775807; "
 1533: 			       "# Wed Jun 30 21:49:08 2147483647")];
 1534: 	static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
 1535: 	time_t since_epoch;
 1536: 	/* The string: 	       "6 2147483647/12/31 23:59:60;"
 1537: 	 * is smaller than the other, used to declare the buffer size, so
 1538: 	 * we can use one buffer for both.
 1539: 	 */
 1540: 
 1541: 	if (t == MAX_TIME)
 1542: 		return "never;";
 1543: 
 1544: 	if (t < 0)
 1545: 		return NULL;
 1546: 
 1547: 	/* For those lucky enough to have a 128-bit time_t, ensure that
 1548: 	 * whatever (corrupt) value we're given doesn't exceed the static
 1549: 	 * buffer.
 1550: 	 */
 1551: #if (MAX_TIME > 0x7fffffffffffffff)
 1552: 	if (t > 0x7fffffffffffffff)
 1553: 		return NULL;
 1554: #endif
 1555: 
 1556: 	if (db_time_format == LOCAL_TIME_FORMAT) {
 1557: 		since_epoch = mktime(localtime(&t));
 1558: 		if ((strftime(buf1, sizeof(buf1),
 1559: 			      "# %a %b %d %H:%M:%S %Y",
 1560: 			      localtime(&t)) == 0) ||
 1561: 		    (snprintf(buf, sizeof(buf), "epoch %lu; %s",
 1562: 			      (unsigned long)since_epoch, buf1) >= sizeof(buf)))
 1563: 			return NULL;
 1564: 
 1565: 	} else {
 1566: 		/* No bounds check for the year is necessary - in this case,
 1567: 		 * strftime() will run out of space and assert an error.
 1568: 		 */
 1569: 		if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
 1570: 			     gmtime(&t)) == 0)
 1571: 			return NULL;
 1572: 	}
 1573: 
 1574: 	return buf;
 1575: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>