File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dhcp / common / print.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:06:54 2012 UTC (11 years, 8 months ago) by misho
Branches: dhcp, MAIN
CVS tags: v4_1_R7p0, v4_1_R7, v4_1_R4, HEAD
dhcp 4.1 r7

    1: /* print.c
    2: 
    3:    Turn data structures into printable text. */
    4: 
    5: /*
    6:  * Copyright (c) 2009-2012 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;
  483: 
  484: 	s = &dq_buf [0];
  485: 	
  486: 	i = 0;
  487: 
  488: 	/* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
  489: 	 * The sprintf can't exceed 18 bytes, and since the loop enforces
  490: 	 * 21 bytes of space per iteration at no time can we exit the
  491: 	 * loop without at least 3 bytes spare.
  492: 	 */
  493: 	do {
  494: 		sprintf (s, "%u.%u.%u.%u, ",
  495: 			 data [i], data [i + 1], data [i + 2], data [i + 3]);
  496: 		s += strlen (s);
  497: 		i += 4;
  498: 	} while ((s - &dq_buf [0] > DQLEN - 21) &&
  499: 		 i + 3 < len);
  500: 	if (i == len)
  501: 		s [-2] = 0;
  502: 	else
  503: 		strcpy (s, "...");
  504: 	return dq_buf;
  505: }
  506: 
  507: char *print_dec_1 (val)
  508: 	unsigned long val;
  509: {
  510: 	static char vbuf [32];
  511: 	sprintf (vbuf, "%lu", val);
  512: 	return vbuf;
  513: }
  514: 
  515: char *print_dec_2 (val)
  516: 	unsigned long val;
  517: {
  518: 	static char vbuf [32];
  519: 	sprintf (vbuf, "%lu", val);
  520: 	return vbuf;
  521: }
  522: 
  523: static unsigned print_subexpression (struct expression *, char *, unsigned);
  524: 
  525: static unsigned print_subexpression (expr, buf, len)
  526: 	struct expression *expr;
  527: 	char *buf;
  528: 	unsigned len;
  529: {
  530: 	unsigned rv, left;
  531: 	const char *s;
  532: 
  533: 	switch (expr -> op) {
  534: 	      case expr_none:
  535: 		if (len > 3) {
  536: 			strcpy (buf, "nil");
  537: 			return 3;
  538: 		}
  539: 		break;
  540: 		  
  541: 	      case expr_match:
  542: 		if (len > 7) {
  543: 			strcpy (buf, "(match)");
  544: 			return 7;
  545: 		}
  546: 		break;
  547: 
  548: 	      case expr_check:
  549: 		rv = 10 + strlen (expr -> data.check -> name);
  550: 		if (len > rv) {
  551: 			sprintf (buf, "(check %s)",
  552: 				 expr -> data.check -> name);
  553: 			return rv;
  554: 		}
  555: 		break;
  556: 
  557: 	      case expr_equal:
  558: 		if (len > 6) {
  559: 			rv = 4;
  560: 			strcpy (buf, "(eq ");
  561: 			rv += print_subexpression (expr -> data.equal [0],
  562: 						   buf + rv, len - rv - 2);
  563: 			buf [rv++] = ' ';
  564: 			rv += print_subexpression (expr -> data.equal [1],
  565: 						   buf + rv, len - rv - 1);
  566: 			buf [rv++] = ')';
  567: 			buf [rv] = 0;
  568: 			return rv;
  569: 		}
  570: 		break;
  571: 
  572: 	      case expr_not_equal:
  573: 		if (len > 7) {
  574: 			rv = 5;
  575: 			strcpy (buf, "(neq ");
  576: 			rv += print_subexpression (expr -> data.equal [0],
  577: 						   buf + rv, len - rv - 2);
  578: 			buf [rv++] = ' ';
  579: 			rv += print_subexpression (expr -> data.equal [1],
  580: 						   buf + rv, len - rv - 1);
  581: 			buf [rv++] = ')';
  582: 			buf [rv] = 0;
  583: 			return rv;
  584: 		}
  585: 		break;
  586: 
  587: 	      case expr_regex_match:
  588: 		if (len > 10) {
  589: 			rv = 4;
  590: 			strcpy(buf, "(regex ");
  591: 			rv += print_subexpression(expr->data.equal[0],
  592: 						  buf + rv, len - rv - 2);
  593: 			buf[rv++] = ' ';
  594: 			rv += print_subexpression(expr->data.equal[1],
  595: 						  buf + rv, len - rv - 1);
  596: 			buf[rv++] = ')';
  597: 			buf[rv] = 0;
  598: 			return rv;
  599: 		}
  600: 		break;
  601: 
  602: 	      case expr_substring:
  603: 		if (len > 11) {
  604: 			rv = 8;
  605: 			strcpy (buf, "(substr ");
  606: 			rv += print_subexpression (expr -> data.substring.expr,
  607: 						   buf + rv, len - rv - 3);
  608: 			buf [rv++] = ' ';
  609: 			rv += print_subexpression
  610: 				(expr -> data.substring.offset,
  611: 				 buf + rv, len - rv - 2);
  612: 			buf [rv++] = ' ';
  613: 			rv += print_subexpression (expr -> data.substring.len,
  614: 						   buf + rv, len - rv - 1);
  615: 			buf [rv++] = ')';
  616: 			buf [rv] = 0;
  617: 			return rv;
  618: 		}
  619: 		break;
  620: 
  621: 	      case expr_suffix:
  622: 		if (len > 10) {
  623: 			rv = 8;
  624: 			strcpy (buf, "(suffix ");
  625: 			rv += print_subexpression (expr -> data.suffix.expr,
  626: 						   buf + rv, len - rv - 2);
  627: 			if (len > rv)
  628: 				buf [rv++] = ' ';
  629: 			rv += print_subexpression (expr -> data.suffix.len,
  630: 						   buf + rv, len - rv - 1);
  631: 			if (len > rv)
  632: 				buf [rv++] = ')';
  633: 			buf [rv] = 0;
  634: 			return rv;
  635: 		}
  636: 		break;
  637: 
  638: 	      case expr_lcase:
  639: 		if (len > 9) {
  640: 			rv = 7;
  641: 			strcpy(buf, "(lcase ");
  642: 			rv += print_subexpression(expr->data.lcase,
  643: 						  buf + rv, len - rv - 1);
  644: 			buf[rv++] = ')';
  645: 			buf[rv] = 0;
  646: 			return rv;
  647: 		}
  648: 		break;
  649: 
  650: 	      case expr_ucase:
  651: 		if (len > 9) {
  652: 			rv = 7;
  653: 			strcpy(buf, "(ucase ");
  654: 			rv += print_subexpression(expr->data.ucase,
  655: 						  buf + rv, len - rv - 1);
  656: 			buf[rv++] = ')';
  657: 			buf[rv] = 0;
  658: 			return rv;
  659: 		}
  660: 		break;
  661: 
  662: 	      case expr_concat:
  663: 		if (len > 10) {
  664: 			rv = 8;
  665: 			strcpy (buf, "(concat ");
  666: 			rv += print_subexpression (expr -> data.concat [0],
  667: 						   buf + rv, len - rv - 2);
  668: 			buf [rv++] = ' ';
  669: 			rv += print_subexpression (expr -> data.concat [1],
  670: 						   buf + rv, len - rv - 1);
  671: 			buf [rv++] = ')';
  672: 			buf [rv] = 0;
  673: 			return rv;
  674: 		}
  675: 		break;
  676: 
  677: 	      case expr_pick_first_value:
  678: 		if (len > 8) {
  679: 			rv = 6;
  680: 			strcpy (buf, "(pick1st ");
  681: 			rv += print_subexpression
  682: 				(expr -> data.pick_first_value.car,
  683: 				 buf + rv, len - rv - 2);
  684: 			buf [rv++] = ' ';
  685: 			rv += print_subexpression
  686: 				(expr -> data.pick_first_value.cdr,
  687: 				 buf + rv, len - rv - 1);
  688: 			buf [rv++] = ')';
  689: 			buf [rv] = 0;
  690: 			return rv;
  691: 		}
  692: 		break;
  693: 
  694: 	      case expr_host_lookup:
  695: 		rv = 15 + strlen (expr -> data.host_lookup -> hostname);
  696: 		if (len > rv) {
  697: 			sprintf (buf, "(dns-lookup %s)",
  698: 				 expr -> data.host_lookup -> hostname);
  699: 			return rv;
  700: 		}
  701: 		break;
  702: 
  703: 	      case expr_and:
  704: 		s = "and";
  705: 	      binop:
  706: 		rv = strlen (s);
  707: 		if (len > rv + 4) {
  708: 			buf [0] = '(';
  709: 			strcpy (&buf [1], s);
  710: 			rv += 1;
  711: 			buf [rv++] = ' ';
  712: 			rv += print_subexpression (expr -> data.and [0],
  713: 						buf + rv, len - rv - 2);
  714: 			buf [rv++] = ' ';
  715: 			rv += print_subexpression (expr -> data.and [1],
  716: 						   buf + rv, len - rv - 1);
  717: 			buf [rv++] = ')';
  718: 			buf [rv] = 0;
  719: 			return rv;
  720: 		}
  721: 		break;
  722: 
  723: 	      case expr_or:
  724: 		s = "or";
  725: 		goto binop;
  726: 
  727: 	      case expr_add:
  728: 		s = "+";
  729: 		goto binop;
  730: 
  731: 	      case expr_subtract:
  732: 		s = "-";
  733: 		goto binop;
  734: 
  735: 	      case expr_multiply:
  736: 		s = "*";
  737: 		goto binop;
  738: 
  739: 	      case expr_divide:
  740: 		s = "/";
  741: 		goto binop;
  742: 
  743: 	      case expr_remainder:
  744: 		s = "%";
  745: 		goto binop;
  746: 
  747: 	      case expr_binary_and:
  748: 		s = "&";
  749: 		goto binop;
  750: 
  751: 	      case expr_binary_or:
  752: 		s = "|";
  753: 		goto binop;
  754: 
  755: 	      case expr_binary_xor:
  756: 		s = "^";
  757: 		goto binop;
  758: 		
  759: 	      case expr_not:
  760: 		if (len > 6) {
  761: 			rv = 5;
  762: 			strcpy (buf, "(not ");
  763: 			rv += print_subexpression (expr -> data.not,
  764: 						   buf + rv, len - rv - 1);
  765: 			buf [rv++] = ')';
  766: 			buf [rv] = 0;
  767: 			return rv;
  768: 		}
  769: 		break;
  770: 
  771: 	      case expr_config_option:
  772: 		s = "cfg-option";
  773: 		goto dooption;
  774: 
  775: 	      case expr_option:
  776: 		s = "option";
  777: 	      dooption:
  778: 		rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
  779: 			   strlen (expr -> data.option -> universe -> name));
  780: 		if (len > rv) {
  781: 			sprintf (buf, "(option %s.%s)",
  782: 				 expr -> data.option -> universe -> name,
  783: 				 expr -> data.option -> name);
  784: 			return rv;
  785: 		}
  786: 		break;
  787: 
  788: 	      case expr_hardware:
  789: 		if (len > 10) {
  790: 			strcpy (buf, "(hardware)");
  791: 			return 10;
  792: 		}
  793: 		break;
  794: 
  795: 	      case expr_packet:
  796: 		if (len > 10) {
  797: 			rv = 8;
  798: 			strcpy (buf, "(substr ");
  799: 			rv += print_subexpression (expr -> data.packet.offset,
  800: 						   buf + rv, len - rv - 2);
  801: 			buf [rv++] = ' ';
  802: 			rv += print_subexpression (expr -> data.packet.len,
  803: 						   buf + rv, len - rv - 1);
  804: 			buf [rv++] = ')';
  805: 			buf [rv] = 0;
  806: 			return rv;
  807: 		}
  808: 		break;
  809: 
  810: 	      case expr_const_data:
  811: 		s = print_hex_1 (expr -> data.const_data.len,
  812: 				 expr -> data.const_data.data, len);
  813: 		rv = strlen (s);
  814: 		if (rv >= len)
  815: 			rv = len - 1;
  816: 		strncpy (buf, s, rv);
  817: 		buf [rv] = 0;
  818: 		return rv;
  819: 
  820: 	      case expr_encapsulate:
  821: 		rv = 13;
  822: 		strcpy (buf, "(encapsulate ");
  823: 		rv += expr -> data.encapsulate.len;
  824: 		if (rv + 2 > len)
  825: 			rv = len - 2;
  826: 		strncpy (buf,
  827: 			 (const char *)expr -> data.encapsulate.data, rv - 13);
  828: 		buf [rv++] = ')';
  829: 		buf [rv++] = 0;
  830: 		break;
  831: 
  832: 	      case expr_extract_int8:
  833: 		if (len > 7) {
  834: 			rv = 6;
  835: 			strcpy (buf, "(int8 ");
  836: 			rv += print_subexpression (expr -> data.extract_int,
  837: 						   buf + rv, len - rv - 1);
  838: 			buf [rv++] = ')';
  839: 			buf [rv] = 0;
  840: 			return rv;
  841: 		}
  842: 		break;
  843: 
  844: 	      case expr_extract_int16:
  845: 		if (len > 8) {
  846: 			rv = 7;
  847: 			strcpy (buf, "(int16 ");
  848: 			rv += print_subexpression (expr -> data.extract_int,
  849: 						   buf + rv, len - rv - 1);
  850: 			buf [rv++] = ')';
  851: 			buf [rv] = 0;
  852: 			return rv;
  853: 		}
  854: 		break;
  855: 
  856: 	      case expr_extract_int32:
  857: 		if (len > 8) {
  858: 			rv = 7;
  859: 			strcpy (buf, "(int32 ");
  860: 			rv += print_subexpression (expr -> data.extract_int,
  861: 						   buf + rv, len - rv - 1);
  862: 			buf [rv++] = ')';
  863: 			buf [rv] = 0;
  864: 			return rv;
  865: 		}
  866: 		break;
  867: 
  868: 	      case expr_encode_int8:
  869: 		if (len > 7) {
  870: 			rv = 6;
  871: 			strcpy (buf, "(to-int8 ");
  872: 			rv += print_subexpression (expr -> data.encode_int,
  873: 						   buf + rv, len - rv - 1);
  874: 			buf [rv++] = ')';
  875: 			buf [rv] = 0;
  876: 			return rv;
  877: 		}
  878: 		break;
  879: 
  880: 	      case expr_encode_int16:
  881: 		if (len > 8) {
  882: 			rv = 7;
  883: 			strcpy (buf, "(to-int16 ");
  884: 			rv += print_subexpression (expr -> data.encode_int,
  885: 						   buf + rv, len - rv - 1);
  886: 			buf [rv++] = ')';
  887: 			buf [rv] = 0;
  888: 			return rv;
  889: 		}
  890: 		break;
  891: 
  892: 	      case expr_encode_int32:
  893: 		if (len > 8) {
  894: 			rv = 7;
  895: 			strcpy (buf, "(to-int32 ");
  896: 			rv += print_subexpression (expr -> data.encode_int,
  897: 						   buf + rv, len - rv - 1);
  898: 			buf [rv++] = ')';
  899: 			buf [rv] = 0;
  900: 			return rv;
  901: 		}
  902: 		break;
  903: 
  904: 	      case expr_const_int:
  905: 		s = print_dec_1 (expr -> data.const_int);
  906: 		rv = strlen (s);
  907: 		if (len > rv) {
  908: 			strcpy (buf, s);
  909: 			return rv;
  910: 		}
  911: 		break;
  912: 
  913: 	      case expr_exists:
  914: 		rv = 10 + (strlen (expr -> data.option -> name) +
  915: 			   strlen (expr -> data.option -> universe -> name));
  916: 		if (len > rv) {
  917: 			sprintf (buf, "(exists %s.%s)",
  918: 				 expr -> data.option -> universe -> name,
  919: 				 expr -> data.option -> name);
  920: 			return rv;
  921: 		}
  922: 		break;
  923: 
  924: 	      case expr_variable_exists:
  925: 		rv = 10 + strlen (expr -> data.variable);
  926: 		if (len > rv) {
  927: 			sprintf (buf, "(defined %s)", expr -> data.variable);
  928: 			return rv;
  929: 		}
  930: 		break;
  931: 
  932: 	      case expr_variable_reference:
  933: 		rv = strlen (expr -> data.variable);
  934: 		if (len > rv) {
  935: 			sprintf (buf, "%s", expr -> data.variable);
  936: 			return rv;
  937: 		}
  938: 		break;
  939: 
  940: 	      case expr_known:
  941: 		s = "known";
  942: 	      astring:
  943: 		rv = strlen (s);
  944: 		if (len > rv) {
  945: 			strcpy (buf, s);
  946: 			return rv;
  947: 		}
  948: 		break;
  949: 
  950: 	      case expr_leased_address:
  951: 		s = "leased-address";
  952: 		goto astring;
  953: 
  954: 	      case expr_client_state:
  955: 		s = "client-state";
  956: 		goto astring;
  957: 
  958: 	      case expr_host_decl_name:
  959: 		s = "host-decl-name";
  960: 		goto astring;
  961: 
  962: 	      case expr_lease_time:
  963: 		s = "lease-time";
  964: 		goto astring;
  965: 
  966: 	      case expr_static:
  967: 		s = "static";
  968: 		goto astring;
  969: 
  970: 	      case expr_filename:
  971: 		s = "filename";
  972: 		goto astring;
  973: 
  974: 	      case expr_sname:
  975: 		s = "server-name";
  976: 		goto astring;
  977: 
  978: 	      case expr_reverse:
  979: 		if (len > 11) {
  980: 			rv = 13;
  981: 			strcpy (buf, "(reverse ");
  982: 			rv += print_subexpression (expr -> data.reverse.width,
  983: 						   buf + rv, len - rv - 2);
  984: 			buf [rv++] = ' ';
  985: 			rv += print_subexpression (expr -> data.reverse.buffer,
  986: 						   buf + rv, len - rv - 1);
  987: 			buf [rv++] = ')';
  988: 			buf [rv] = 0;
  989: 			return rv;
  990: 		}
  991: 		break;
  992: 
  993: 	      case expr_binary_to_ascii:
  994: 		if (len > 5) {
  995: 			rv = 9;
  996: 			strcpy (buf, "(b2a ");
  997: 			rv += print_subexpression (expr -> data.b2a.base,
  998: 						   buf + rv, len - rv - 4);
  999: 			buf [rv++] = ' ';
 1000: 			rv += print_subexpression (expr -> data.b2a.width,
 1001: 						   buf + rv, len - rv - 3);
 1002: 			buf [rv++] = ' ';
 1003: 			rv += print_subexpression (expr -> data.b2a.separator,
 1004: 						   buf + rv, len - rv - 2);
 1005: 			buf [rv++] = ' ';
 1006: 			rv += print_subexpression (expr -> data.b2a.buffer,
 1007: 						   buf + rv, len - rv - 1);
 1008: 			buf [rv++] = ')';
 1009: 			buf [rv] = 0;
 1010: 			return rv;
 1011: 		}
 1012: 		break;
 1013: 
 1014: 	      case expr_dns_transaction:
 1015: 		rv = 10;
 1016: 		if (len < rv + 2) {
 1017: 			buf [0] = '(';
 1018: 			strcpy (&buf [1], "ns-update ");
 1019: 			while (len < rv + 2) {
 1020: 				rv += print_subexpression
 1021: 					(expr -> data.dns_transaction.car,
 1022: 					 buf + rv, len - rv - 2);
 1023: 				buf [rv++] = ' ';
 1024: 				expr = expr -> data.dns_transaction.cdr;
 1025: 			}
 1026: 			buf [rv - 1] = ')';
 1027: 			buf [rv] = 0;
 1028: 			return rv;
 1029: 		}
 1030: 		return 0;
 1031: 
 1032: 	      case expr_ns_delete:
 1033: 		s = "delete";
 1034: 		left = 4;
 1035: 		goto dodnsupd;
 1036: 	      case expr_ns_exists:
 1037: 		s = "exists";
 1038: 		left = 4;
 1039: 		goto dodnsupd;
 1040: 	      case expr_ns_not_exists:
 1041: 		s = "not_exists";
 1042: 		left = 4;
 1043: 		goto dodnsupd;
 1044: 	      case expr_ns_add:
 1045: 		s = "update";
 1046: 		left = 5;
 1047: 	      dodnsupd:
 1048: 		rv = strlen (s);
 1049: 		if (len > strlen (s) + 1) {
 1050: 			buf [0] = '(';
 1051: 			strcpy (buf + 1, s);
 1052: 			rv++;
 1053: 			buf [rv++] = ' ';
 1054: 			s = print_dec_1 (expr -> data.ns_add.rrclass);
 1055: 			if (len > rv + strlen (s) + left) {
 1056: 				strcpy (&buf [rv], s);
 1057: 				rv += strlen (&buf [rv]);
 1058: 			}
 1059: 			buf [rv++] = ' ';
 1060: 			left--;
 1061: 			s = print_dec_1 (expr -> data.ns_add.rrtype);
 1062: 			if (len > rv + strlen (s) + left) {
 1063: 				strcpy (&buf [rv], s);
 1064: 				rv += strlen (&buf [rv]);
 1065: 			}
 1066: 			buf [rv++] = ' ';
 1067: 			left--;
 1068: 			rv += print_subexpression
 1069: 				(expr -> data.ns_add.rrname,
 1070: 				 buf + rv, len - rv - left);
 1071: 			buf [rv++] = ' ';
 1072: 			left--;
 1073: 			rv += print_subexpression
 1074: 				(expr -> data.ns_add.rrdata,
 1075: 				 buf + rv, len - rv - left);
 1076: 			buf [rv++] = ' ';
 1077: 			left--;
 1078: 			rv += print_subexpression
 1079: 				(expr -> data.ns_add.ttl,
 1080: 				 buf + rv, len - rv - left);
 1081: 			buf [rv++] = ')';
 1082: 			buf [rv] = 0;
 1083: 			return rv;
 1084: 		}
 1085: 		break;
 1086: 
 1087: 	      case expr_null:
 1088: 		if (len > 6) {
 1089: 			strcpy (buf, "(null)");
 1090: 			return 6;
 1091: 		}
 1092: 		break;
 1093: 	      case expr_funcall:
 1094: 		rv = 12 + strlen (expr -> data.funcall.name);
 1095: 		if (len > rv + 1) {
 1096: 			strcpy (buf, "(funcall  ");
 1097: 			strcpy (buf + 9, expr -> data.funcall.name);
 1098: 			buf [rv++] = ' ';
 1099: 			rv += print_subexpression
 1100: 				(expr -> data.funcall.arglist, buf + rv,
 1101: 				 len - rv - 1);
 1102: 			buf [rv++] = ')';
 1103: 			buf [rv] = 0;
 1104: 			return rv;
 1105: 		}
 1106: 		break;
 1107: 
 1108: 	      case expr_arg:
 1109: 		rv = print_subexpression (expr -> data.arg.val, buf, len);
 1110: 		if (expr -> data.arg.next && rv + 2 < len) {
 1111: 			buf [rv++] = ' ';
 1112: 			rv += print_subexpression (expr -> data.arg.next,
 1113: 						   buf, len);
 1114: 			if (rv + 1 < len)
 1115: 				buf [rv++] = 0;
 1116: 			return rv;
 1117: 		}
 1118: 		break;
 1119: 
 1120: 	      case expr_function:
 1121: 		rv = 9;
 1122: 		if (len > rv + 1) {
 1123: 			struct string_list *foo;
 1124: 			strcpy (buf, "(function");
 1125: 			for (foo = expr -> data.func -> args;
 1126: 			     foo; foo = foo -> next) {
 1127: 				if (len > rv + 2 + strlen (foo -> string)) {
 1128: 					buf [rv - 1] = ' ';
 1129: 					strcpy (&buf [rv], foo -> string);
 1130: 					rv += strlen (foo -> string);
 1131: 				}
 1132: 			}
 1133: 			buf [rv++] = ')';
 1134: 			buf [rv] = 0;
 1135: 			return rv;
 1136: 		}
 1137: 
 1138: 	      default:
 1139: 		log_fatal("Impossible case at %s:%d (undefined expression "
 1140: 			  "%d).", MDL, expr->op);
 1141: 		break;
 1142: 	}
 1143: 	return 0;
 1144: }
 1145: 
 1146: void print_expression (name, expr)
 1147: 	const char *name;
 1148: 	struct expression *expr;
 1149: {
 1150: 	char buf [1024];
 1151: 
 1152: 	print_subexpression (expr, buf, sizeof buf);
 1153: 	log_info ("%s: %s", name, buf);
 1154: }
 1155: 
 1156: int token_print_indent_concat (FILE *file, int col,  int indent,
 1157: 			       const char *prefix, 
 1158: 			       const char *suffix, ...)
 1159: {
 1160: 	va_list list;
 1161: 	unsigned len;
 1162: 	char *s, *t, *u;
 1163: 
 1164: 	va_start (list, suffix);
 1165: 	s = va_arg (list, char *);
 1166: 	len = 0;
 1167: 	while (s) {
 1168: 		len += strlen (s);
 1169: 		s = va_arg (list, char *);
 1170: 	}
 1171: 	va_end (list);
 1172: 
 1173: 	t = dmalloc (len + 1, MDL);
 1174: 	if (!t)
 1175: 		log_fatal ("token_print_indent: no memory for copy buffer");
 1176: 
 1177: 	va_start (list, suffix);
 1178: 	s = va_arg (list, char *);
 1179: 	u = t;
 1180: 	while (s) {
 1181: 		len = strlen (s);
 1182: 		strcpy (u, s);
 1183: 		u += len;
 1184: 		s = va_arg (list, char *);
 1185: 	}
 1186: 	va_end (list);
 1187: 	
 1188: 	len = token_print_indent (file, col, indent,
 1189: 				  prefix, suffix, t);
 1190: 	dfree (t, MDL);
 1191: 	return col;
 1192: }
 1193: 
 1194: int token_indent_data_string (FILE *file, int col, int indent,
 1195: 			      const char *prefix, const char *suffix,
 1196: 			      struct data_string *data)
 1197: {
 1198: 	int i;
 1199: 	char *buf;
 1200: 	char obuf [3];
 1201: 
 1202: 	/* See if this is just ASCII. */
 1203: 	for (i = 0; i < data -> len; i++)
 1204: 		if (!isascii (data -> data [i]) ||
 1205: 		    !isprint (data -> data [i]))
 1206: 			break;
 1207: 
 1208: 	/* If we have a purely ASCII string, output it as text. */
 1209: 	if (i == data -> len) {
 1210: 		buf = dmalloc (data -> len + 3, MDL);
 1211: 		if (buf) {
 1212: 			buf [0] = '"';
 1213: 			memcpy (buf + 1, data -> data, data -> len);
 1214: 			buf [data -> len + 1] = '"';
 1215: 			buf [data -> len + 2] = 0;
 1216: 			i = token_print_indent (file, col, indent,
 1217: 						prefix, suffix, buf);
 1218: 			dfree (buf, MDL);
 1219: 			return i;
 1220: 		}
 1221: 	}
 1222: 
 1223: 	for (i = 0; i < data -> len; i++) {
 1224: 		sprintf (obuf, "%2.2x", data -> data [i]);
 1225: 		col = token_print_indent (file, col, indent,
 1226: 					  i == 0 ? prefix : "",
 1227: 					  (i + 1 == data -> len
 1228: 					   ? suffix
 1229: 					   : ""), obuf);
 1230: 		if (i + 1 != data -> len)
 1231: 			col = token_print_indent (file, col, indent,
 1232: 						  prefix, suffix, ":");
 1233: 	}
 1234: 	return col;
 1235: }
 1236: 
 1237: int token_print_indent (FILE *file, int col, int indent,
 1238: 			const char *prefix,
 1239: 			const char *suffix, const char *buf)
 1240: {
 1241: 	int len = strlen (buf) + strlen (prefix);
 1242: 	if (col + len > 79) {
 1243: 		if (indent + len < 79) {
 1244: 			indent_spaces (file, indent);
 1245: 			col = indent;
 1246: 		} else {
 1247: 			indent_spaces (file, col);
 1248: 			col = len > 79 ? 0 : 79 - len - 1;
 1249: 		}
 1250: 	} else if (prefix && *prefix) {
 1251: 		fputs (prefix, file);
 1252: 		col += strlen (prefix);
 1253: 	}
 1254: 	fputs (buf, file);
 1255: 	col += len;
 1256: 	if (suffix && *suffix) {
 1257: 		if (col + strlen (suffix) > 79) {
 1258: 			indent_spaces (file, indent);
 1259: 			col = indent;
 1260: 		} else {
 1261: 			fputs (suffix, file);
 1262: 			col += strlen (suffix);
 1263: 		}
 1264: 	}
 1265: 	return col;
 1266: }
 1267: 
 1268: void indent_spaces (FILE *file, int indent)
 1269: {
 1270: 	int i;
 1271: 	fputc ('\n', file);
 1272: 	for (i = 0; i < indent; i++)
 1273: 		fputc (' ', file);
 1274: }
 1275: 
 1276: #if defined (NSUPDATE)
 1277: void print_dns_status (int status, ns_updque *uq)
 1278: {
 1279: 	char obuf [1024];
 1280: 	char *s = &obuf [0], *end = &obuf [1022];
 1281: 	ns_updrec *u;
 1282: 	int position;
 1283: 	int ttlp;
 1284: 	const char *predicate = "if", *en, *op;
 1285: 	int errorp;
 1286: 
 1287: 	for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) {
 1288: 		ttlp = 0;
 1289: 
 1290: 		switch (u -> r_opcode)
 1291: 		{
 1292: 		      case NXRRSET:
 1293: 			op = "rrset doesn't exist";
 1294: 			position = 1;
 1295: 			break;
 1296: 		      case YXRRSET:
 1297: 			op = "rrset exists";
 1298: 			position = 1;
 1299: 			break;
 1300: 		      case NXDOMAIN:
 1301: 			op = "domain doesn't exist";
 1302: 			position = 1;
 1303: 			break;
 1304: 		      case YXDOMAIN:
 1305: 			op = "domain exists";
 1306: 			position = 1;
 1307: 			break;
 1308: 		      case ADD:
 1309: 			op = "add";
 1310: 			position = 0;
 1311: 			ttlp = 1;
 1312: 			break;
 1313: 		      case DELETE:
 1314: 			op = "delete";
 1315: 			position = 0;
 1316: 			break;
 1317: 		      default:
 1318: 			op = "unknown";
 1319: 			position = 0;
 1320: 			break;
 1321: 		}
 1322: 		if (!position) {
 1323: 			if (s != &obuf [0] && s + 1 < end)
 1324: 				*s++ = ' ';
 1325: 			if (s + strlen (op) < end) {
 1326: 				strcpy (s, op);
 1327: 				s += strlen (s);
 1328: 			}
 1329: 		} else {
 1330: 			if (s != &obuf [0] && s + 1 < end)
 1331: 				*s++ = ' ';
 1332: 			if (s + strlen (predicate) < end) {
 1333: 				strcpy (s, predicate);
 1334: 				s += strlen (s);
 1335: 			}
 1336: 			predicate = "and";
 1337: 		}
 1338: 		if (u -> r_dname) {
 1339: 			if (s + 1 < end)
 1340: 				*s++ = ' ';
 1341: 			if (s + strlen (u -> r_dname) < end) {
 1342: 				strcpy (s, u -> r_dname);
 1343: 				s += strlen (s);
 1344: 			}
 1345: 		}
 1346: 		if (ttlp) {
 1347: 			if (s + 1 < end)
 1348: 				*s++ = ' ';
 1349: 			/* 27 is as big as a ttl can get. */
 1350: 			if (s + 27 < end) {
 1351: 				sprintf (s, "%lu",
 1352: 					 (unsigned long)(u -> r_ttl));
 1353: 				s += strlen (s);
 1354: 			}
 1355: 		}
 1356: 		switch (u -> r_class) {
 1357: 		      case C_IN:
 1358: 			en = "IN";
 1359: 			break;
 1360: 		      case C_CHAOS:
 1361: 			en = "CHAOS";
 1362: 			break;
 1363: 		      case C_HS:
 1364: 			en = "HS";
 1365: 			break;
 1366: 		      default:
 1367: 			en = "UNKNOWN";
 1368: 			break;
 1369: 		}
 1370: 		if (s + strlen (en) < end) {
 1371: 			if (s + 1 < end)
 1372: 				*s++ = ' ';
 1373: 			strcpy (s, en);
 1374: 			s += strlen (en);
 1375: 		}
 1376: 		switch (u -> r_type) {
 1377: 		      case T_A:
 1378: 			en = "A";
 1379: 			break;
 1380: 		      case T_AAAA:
 1381: 			en = "AAAA";
 1382: 			break;
 1383: 		      case T_PTR:
 1384: 			en = "PTR";
 1385: 			break;
 1386: 		      case T_MX:
 1387: 			en = "MX";
 1388: 			break;
 1389: 		      case T_TXT:
 1390: 			en = "TXT";
 1391: 			break;
 1392: 		      case T_KEY:
 1393: 			en = "KEY";
 1394: 			break;
 1395: 		      case T_CNAME:
 1396: 			en = "CNAME";
 1397: 			break;
 1398: 		      default:
 1399: 			en = "UNKNOWN";
 1400: 			break;
 1401: 		}
 1402: 		if (s + strlen (en) < end) {
 1403: 			if (s + 1 < end)
 1404: 				*s++ = ' ';
 1405: 			strcpy (s, en);
 1406: 			s += strlen (en);
 1407: 		}
 1408: 		if (u -> r_data) {
 1409: 			if (s + 1 < end)
 1410: 				*s++ = ' ';
 1411: 			if (u -> r_type == T_TXT) {
 1412: 				if (s + 1 < end)
 1413: 					*s++ = '"';
 1414: 			}
 1415: 			if(u->r_type == T_KEY) {
 1416: 			  strcat(s, "<keydata>");
 1417: 			  s+=strlen("<keydata>");
 1418: 			}
 1419: 			else {  
 1420: 			  if (s + u -> r_size < end) {
 1421: 			    memcpy (s, u -> r_data, u -> r_size);
 1422: 			    s += u -> r_size;
 1423: 			    if (u -> r_type == T_TXT) {
 1424: 			      if (s + 1 < end)
 1425: 				*s++ = '"';
 1426: 			    }
 1427: 			  }
 1428: 			}
 1429: 		}
 1430: 		if (position) {
 1431: 			if (s + 1 < end)
 1432: 				*s++ = ' ';
 1433: 			if (s + strlen (op) < end) {
 1434: 				strcpy (s, op);
 1435: 				s += strlen (s);
 1436: 			}
 1437: 		}
 1438: 		if (u == ISC_LIST_TAIL (*uq))
 1439: 			break;
 1440: 	}
 1441: 	if (s == &obuf [0]) {
 1442: 		strcpy (s, "empty update");
 1443: 		s += strlen (s);
 1444: 	}
 1445: 	if (status == NOERROR)
 1446: 		errorp = 0;
 1447: 	else
 1448: 		errorp = 1;
 1449: 	en = isc_result_totext (status);
 1450: #if 0
 1451: 	switch (status) {
 1452: 	      case -1:
 1453: 		en = "resolver failed";
 1454: 		break;
 1455: 
 1456: 	      case FORMERR:
 1457: 		en = "format error";
 1458: 		break;
 1459: 
 1460: 	      case NOERROR:
 1461: 		en = "succeeded";
 1462: 		errorp = 0;
 1463: 		break;
 1464: 
 1465: 	      case NOTAUTH:
 1466: 		en = "not authorized";
 1467: 		break;
 1468: 
 1469: 	      case NOTIMP:
 1470: 		en = "not implemented";
 1471: 		break;
 1472: 
 1473: 	      case NOTZONE:
 1474: 		en = "not a single valid zone";
 1475: 		break;
 1476: 
 1477: 	      case NXDOMAIN:
 1478: 		en = "no such domain";
 1479: 		break;
 1480: 
 1481: 	      case NXRRSET:
 1482: 		en = "no such record";
 1483: 		break;
 1484: 
 1485: 	      case REFUSED:
 1486: 		en = "refused";
 1487: 		break;
 1488: 
 1489: 	      case SERVFAIL:
 1490: 		en = "server failed";
 1491: 		break;
 1492: 
 1493: 	      case YXDOMAIN:
 1494: 		en = "domain exists";
 1495: 		break;
 1496: 
 1497: 	      case YXRRSET:
 1498: 		en = "record exists";
 1499: 		break;
 1500: 
 1501: 	      default:
 1502: 		en = "unknown error";
 1503: 		break;
 1504: 	}
 1505: #endif
 1506: 
 1507: 	if (s + 2 < end) {
 1508: 		*s++ = ':';
 1509: 		*s++ = ' ';
 1510: 	}
 1511: 	if (s + strlen (en) < end) {
 1512: 		strcpy (s, en);
 1513: 		s += strlen (en);
 1514: 	}
 1515: 	if (s + 1 < end)
 1516: 		*s++ = '.';
 1517: 	*s++ = 0;
 1518: 	if (errorp)
 1519: 		log_error ("%s", obuf);
 1520: 	else
 1521: 		log_info ("%s", obuf);
 1522: }
 1523: #endif /* NSUPDATE */
 1524: 
 1525: /* Format the given time as "A; # B", where A is the format
 1526:  * used by the parser, and B is the local time, for humans.
 1527:  */
 1528: const char *
 1529: print_time(TIME t)
 1530: {
 1531: 	static char buf[sizeof("epoch 9223372036854775807; "
 1532: 			       "# Wed Jun 30 21:49:08 2147483647")];
 1533: 	static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
 1534: 	time_t since_epoch;
 1535: 	/* The string: 	       "6 2147483647/12/31 23:59:60;"
 1536: 	 * is smaller than the other, used to declare the buffer size, so
 1537: 	 * we can use one buffer for both.
 1538: 	 */
 1539: 
 1540: 	if (t == MAX_TIME)
 1541: 		return "never;";
 1542: 
 1543: 	if (t < 0)
 1544: 		return NULL;
 1545: 
 1546: 	/* For those lucky enough to have a 128-bit time_t, ensure that
 1547: 	 * whatever (corrupt) value we're given doesn't exceed the static
 1548: 	 * buffer.
 1549: 	 */
 1550: #if (MAX_TIME > 0x7fffffffffffffff)
 1551: 	if (t > 0x7fffffffffffffff)
 1552: 		return NULL;
 1553: #endif
 1554: 
 1555: 	if (db_time_format == LOCAL_TIME_FORMAT) {
 1556: 		since_epoch = mktime(localtime(&t));
 1557: 		if ((strftime(buf1, sizeof(buf1),
 1558: 			      "# %a %b %d %H:%M:%S %Y",
 1559: 			      localtime(&t)) == 0) ||
 1560: 		    (snprintf(buf, sizeof(buf), "epoch %lu; %s",
 1561: 			      (unsigned long)since_epoch, buf1) >= sizeof(buf)))
 1562: 			return NULL;
 1563: 
 1564: 	} else {
 1565: 		/* No bounds check for the year is necessary - in this case,
 1566: 		 * strftime() will run out of space and assert an error.
 1567: 		 */
 1568: 		if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
 1569: 			     gmtime(&t)) == 0)
 1570: 			return NULL;
 1571: 	}
 1572: 
 1573: 	return buf;
 1574: }

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