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