xref: /illumos-gate/usr/src/cmd/praudit/format.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #define	_REENTRANT
30 
31 #include <ctype.h>
32 #include <errno.h>
33 #include <grp.h>
34 #include <libintl.h>
35 #include <netdb.h>
36 #include <time.h>
37 #include <pwd.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <wchar.h>
42 
43 #include <arpa/inet.h>
44 
45 #include <bsm/audit.h>
46 #include <bsm/audit_record.h>
47 #include <bsm/libbsm.h>
48 #include <security/pam_appl.h>
49 
50 #include <sys/inttypes.h>
51 #include <sys/mkdev.h>
52 #include <sys/types.h>
53 
54 #include "praudit.h"
55 #include "toktable.h"
56 #include "adt_xlate.h"
57 
58 static void	convertascii(char *p, char *c, int size);
59 static int	convertbinary(char *p, char *c, int size);
60 static void	eventmodifier2string(ushort_t emodifier, char *modstring,
61     size_t modlen);
62 static int	do_mtime32(pr_context_t *context, int status, int flag,
63     uint32_t scale);
64 static int	do_mtime64(pr_context_t *context, int status, int flag,
65     uint64_t scale);
66 
67 /*
68  * ------------------------------------------------------
69  * field widths for arbitrary data token type
70  * ------------------------------------------------------
71  */
72 static struct fw {
73 	char	basic_unit;
74 	struct {
75 		char	print_base;
76 		int	field_width;
77 	} pwidth[5];
78 } fwidth[] = {
79 	/* character data type, 8 bits */
80 		AUR_CHAR,	AUP_BINARY,	12,
81 				AUP_OCTAL,	 6,
82 				AUP_DECIMAL,	 6,
83 				AUP_HEX,	 6,
84 				AUP_STRING,	 4,
85 		AUR_BYTE,	AUP_BINARY,	12,
86 				AUP_OCTAL,	 6,
87 				AUP_DECIMAL,	 6,
88 				AUP_HEX,	 6,
89 				AUP_STRING,	 4,
90 		AUR_SHORT,	AUP_BINARY,	20,
91 				AUP_OCTAL,	10,
92 				AUP_DECIMAL,	10,
93 				AUP_HEX,	 8,
94 				AUP_STRING,	 6,
95 		AUR_INT32,	AUP_BINARY,	36,
96 				AUP_OCTAL,	18,
97 				AUP_DECIMAL,	18,
98 				AUP_HEX,	12,
99 				AUP_STRING,	10,
100 		AUR_INT64,	AUP_BINARY,	68,
101 				AUP_OCTAL,	34,
102 				AUP_DECIMAL,	34,
103 				AUP_HEX,	20,
104 				AUP_STRING,	20};
105 
106 
107 static int	numwidthentries = sizeof (fwidth)
108 			/ sizeof (struct fw);
109 
110 
111 /*
112  * -----------------------------------------------------------------------
113  * do_newline:
114  *		  Print a newline, if needed according to various formatting
115  *		  rules.
116  * return codes :   0 - success
117  *		:  -1 - error
118  * -----------------------------------------------------------------------
119  */
120 int
121 do_newline(pr_context_t *context, int flag)
122 {
123 	int	retstat = 0;
124 
125 	if (!(context->format & PRF_ONELINE) && (flag == 1))
126 		retstat = pr_putchar(context, '\n');
127 	else if (!(context->format & PRF_XMLM))
128 		retstat = pr_printf(context, "%s", context->SEPARATOR);
129 
130 	return (retstat);
131 }
132 
133 int
134 open_tag(pr_context_t *context, int tagnum)
135 {
136 	int		err = 0;
137 	token_desc_t	*tag;
138 
139 	/* no-op if not doing XML format */
140 	if (!(context->format & PRF_XMLM))
141 		return (0);
142 
143 	tag = &tokentable[tagnum];
144 
145 	/*
146 	 * First if needed do an implicit finish of a pending open for an
147 	 * extended tag.  I.e., for the extended tag xxx:
148 	 *	<xxx a=".." b=".."> ...  </xxx>
149 	 * -- insert a close bracket after the last attribute
150 	 * (in other words, when the 1st non-attribute is opened while
151 	 * this is pending). Note that only one tag could be pending at
152 	 * a given time -- it couldn't be nested.
153 	 */
154 	if (context->pending_flag && (tag->t_type != T_ATTRIBUTE)) {
155 		/* complete pending extended open */
156 		err = pr_putchar(context, '>');
157 		if (err != 0)
158 			return (err);
159 		context->pending_flag = 0;
160 	}
161 
162 	if (is_header_token(tagnum) || is_file_token(tagnum)) {
163 		/* File token or new record on new line */
164 		err = pr_putchar(context, '\n');
165 	} else if (is_token(tagnum)) {
166 		/* Each token on new line if possible */
167 		err = do_newline(context, 1);
168 	}
169 	if (err != 0)
170 		return (err);
171 
172 	switch (tag->t_type) {
173 	case T_ATTRIBUTE:
174 		err = pr_printf(context, " %s=\"", tag->t_tagname);
175 		break;
176 	case T_ELEMENT:
177 		err = pr_printf(context, "<%s>", tag->t_tagname);
178 		break;
179 	case T_ENCLOSED:
180 		err = pr_printf(context, "<%s", tag->t_tagname);
181 		break;
182 	case T_EXTENDED:
183 		err = pr_printf(context, "<%s", tag->t_tagname);
184 		if (err == 0)
185 			context->pending_flag = tagnum;
186 		break;
187 	default:
188 		break;
189 	}
190 
191 	if (is_header_token(tagnum) && (err == 0))
192 		context->current_rec = tagnum;	/* set start of new record */
193 
194 	return (err);
195 }
196 
197 /*
198  * Do an implicit close of a record when needed.
199  */
200 int
201 check_close_rec(pr_context_t *context, int tagnum)
202 {
203 	int	err = 0;
204 
205 	/* no-op if not doing XML format */
206 	if (!(context->format & PRF_XMLM))
207 		return (0);
208 
209 	/*
210 	 * If we're opening a header or the file token (i.e., starting a new
211 	 * record), if there's a current record in progress do an implicit
212 	 * close of it.
213 	 */
214 	if ((is_header_token(tagnum) || is_file_token(tagnum)) &&
215 	    context->current_rec) {
216 		err = do_newline(context, 1);
217 		if (err == 0)
218 			err = close_tag(context, context->current_rec);
219 	}
220 
221 	return (err);
222 }
223 
224 /*
225  * explicit finish of a pending open for an extended tag.
226  */
227 int
228 finish_open_tag(pr_context_t *context)
229 {
230 	int	err = 0;
231 
232 	/* no-op if not doing XML format */
233 	if (!(context->format & PRF_XMLM))
234 		return (0);
235 
236 	if (context->pending_flag) {
237 		/* complete pending extended open */
238 		err = pr_putchar(context, '>');
239 		if (err == 0)
240 			context->pending_flag = 0;
241 	}
242 	return (err);
243 }
244 
245 int
246 close_tag(pr_context_t *context, int tagnum)
247 {
248 	int		err = 0;
249 	token_desc_t	*tag;
250 
251 	/* no-op if not doing XML format */
252 	if (!(context->format & PRF_XMLM))
253 		return (0);
254 
255 	tag = &tokentable[tagnum];
256 
257 	switch (tag->t_type) {
258 	case T_ATTRIBUTE:
259 		err = pr_putchar(context, '\"');
260 		break;
261 	case T_ELEMENT:
262 		err = pr_printf(context, "</%s>", tag->t_tagname);
263 		break;
264 	case T_ENCLOSED:
265 		err = pr_printf(context, "/>");
266 		break;
267 	case T_EXTENDED:
268 		err = pr_printf(context, "</%s>", tag->t_tagname);
269 		break;
270 	default:
271 		break;
272 	}
273 
274 	if (is_header_token(tagnum) && (err == 0))
275 		context->current_rec = 0;	/* closing rec; none current */
276 
277 	return (err);
278 }
279 
280 /*
281  * -----------------------------------------------------------------------
282  * process_tag:
283  *		  Calls the routine corresponding to the tag
284  *		  Note that to use this mechanism, all such routines must
285  *		  take 2 ints for their parameters; the first of these is
286  *		  the current status.
287  *
288  *		  flag = 1 for newline / delimiter, else 0
289  * return codes : -1 - error
290  *		:  0 - successful
291  * -----------------------------------------------------------------------
292  */
293 int
294 process_tag(pr_context_t *context, int tagnum, int status, int flag)
295 {
296 	int retstat;
297 
298 	retstat = status;
299 
300 	if (retstat)
301 		return (retstat);
302 
303 	if ((tagnum > 0) && (tagnum <= MAXTAG) &&
304 	    (tokentable[tagnum].func != NOFUNC)) {
305 		retstat = open_tag(context, tagnum);
306 		if (!retstat)
307 			retstat = (*tokentable[tagnum].func)(context, status,
308 			    flag);
309 		if (!retstat)
310 			retstat = close_tag(context, tagnum);
311 		return (retstat);
312 	}
313 	/* here if token id is not in table */
314 	(void) fprintf(stderr, gettext("praudit: No code associated with "
315 	    "tag id %d\n"), tagnum);
316 	return (0);
317 }
318 
319 void
320 get_Hname(uint32_t addr, char *buf, size_t buflen)
321 {
322 	extern char	*inet_ntoa(const struct in_addr);
323 	struct hostent *phe;
324 	struct in_addr ia;
325 
326 	phe = gethostbyaddr((const char *)&addr, 4, AF_INET);
327 	if (phe == (struct hostent *)0) {
328 		ia.s_addr = addr;
329 		(void) snprintf(buf, buflen, "%s", inet_ntoa(ia));
330 		return;
331 	}
332 	ia.s_addr = addr;
333 	(void) snprintf(buf, buflen, "%s", phe->h_name);
334 }
335 
336 void
337 get_Hname_ex(uint32_t *addr, char *buf, size_t buflen)
338 {
339 	struct hostent *phe;
340 	int err;
341 
342 	phe = getipnodebyaddr((const void *)addr, 16, AF_INET6, &err);
343 
344 	if (phe == (struct hostent *)0) {
345 		(void) inet_ntop(AF_INET6, (void *)addr, buf, buflen);
346 	} else
347 		(void) snprintf(buf, buflen, "%s", phe->h_name);
348 
349 	if (phe)
350 		freehostent(phe);
351 }
352 
353 int
354 pa_hostname(pr_context_t *context, int status, int flag)
355 {
356 	int	returnstat;
357 	uint32_t	ip_addr;
358 	struct in_addr ia;
359 	uval_t uval;
360 	char	buf[256];
361 
362 	if (status <  0)
363 		return (status);
364 
365 	if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
366 		return (returnstat);
367 
368 	uval.uvaltype = PRA_STRING;
369 
370 	if (!(context->format & PRF_RAWM)) {
371 		uval.string_val = buf;
372 		get_Hname(ip_addr, buf, sizeof (buf));
373 		returnstat = pa_print(context, &uval, flag);
374 	} else {
375 		ia.s_addr = ip_addr;
376 		if ((uval.string_val = inet_ntoa(ia)) == NULL)
377 			return (-1);
378 		returnstat = pa_print(context, &uval, flag);
379 	}
380 	return (returnstat);
381 }
382 
383 int
384 pa_hostname_ex(pr_context_t *context, int status, int flag)
385 {
386 	int	returnstat;
387 	uint32_t	ip_type;
388 	uint32_t	ip_addr[4];
389 	struct in_addr ia;
390 	char buf[256];
391 	uval_t uval;
392 
393 	if (status <  0)
394 		return (status);
395 
396 	/* get ip type */
397 	if ((returnstat = pr_adr_int32(context, (int32_t *)&ip_type, 1)) != 0)
398 		return (returnstat);
399 
400 	/* only IPv4 and IPv6 addresses are legal */
401 	if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
402 		return (-1);
403 
404 	/* get ip address */
405 	if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
406 			return (returnstat);
407 
408 	if ((returnstat = open_tag(context, TAG_HOSTID)) != 0)
409 		return (returnstat);
410 
411 	uval.uvaltype = PRA_STRING;
412 	if (ip_type == AU_IPv4) {		/* ipv4 address */
413 		if (!(context->format & PRF_RAWM)) {
414 			uval.string_val = buf;
415 			get_Hname(ip_addr[0], buf, sizeof (buf));
416 			returnstat = pa_print(context, &uval, flag);
417 		} else {
418 			ia.s_addr = ip_addr[0];
419 			if ((uval.string_val = inet_ntoa(ia)) == NULL)
420 				return (-1);
421 			returnstat = pa_print(context, &uval, flag);
422 		}
423 	} else if (ip_type == AU_IPv6) {	/* IPv6 addresss (128 bits) */
424 		if (!(context->format & PRF_RAWM)) {
425 			uval.string_val = buf;
426 			get_Hname_ex(ip_addr, buf, sizeof (buf));
427 			returnstat = pa_print(context, &uval, flag);
428 		} else {
429 			uval.string_val = (char *)buf;
430 			(void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
431 			    sizeof (buf));
432 			returnstat = pa_print(context, &uval, flag);
433 		}
434 	}
435 
436 	if (returnstat != 0)
437 		return (returnstat);
438 	return (close_tag(context, TAG_HOSTID));
439 }
440 
441 int
442 pa_hostname_so(pr_context_t *context, int status, int flag)
443 {
444 	int		returnstat;
445 	short		ip_type;
446 	ushort_t	ip_port;
447 	uint32_t	ip_addr[4];
448 	struct in_addr ia;
449 	char buf[256];
450 	uval_t uval;
451 
452 	if (status <  0)
453 		return (status);
454 
455 	/* get ip type */
456 	if ((returnstat = pr_adr_short(context, &ip_type, 1)) != 0)
457 		return (returnstat);
458 
459 	/* only IPv4 and IPv6 addresses are legal */
460 	if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
461 		return (-1);
462 
463 	/* get local ip port */
464 	if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
465 		return (returnstat);
466 
467 	if ((returnstat = open_tag(context, TAG_SOCKEXLPORT)) != 0)
468 		return (returnstat);
469 
470 	uval.uvaltype = PRA_STRING;
471 	uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
472 	    sizeof (ip_port));
473 	if (uval.string_val) {
474 		returnstat = pa_print(context, &uval, 0);
475 		free(uval.string_val);
476 	} else
477 		returnstat = -1;
478 	if (returnstat)
479 		return (returnstat);
480 
481 	if ((returnstat = close_tag(context, TAG_SOCKEXLPORT)) != 0)
482 		return (returnstat);
483 
484 	/* get local ip address */
485 	if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
486 			return (returnstat);
487 
488 	if ((returnstat = open_tag(context, TAG_SOCKEXLADDR)) != 0)
489 		return (returnstat);
490 
491 	if (ip_type == AU_IPv4) {		/* ipv4 address */
492 
493 		if (!(context->format & PRF_RAWM)) {
494 			uval.string_val = buf;
495 			get_Hname(ip_addr[0], buf, sizeof (buf));
496 			returnstat = pa_print(context, &uval, 0);
497 		} else {
498 			ia.s_addr = ip_addr[0];
499 			if ((uval.string_val = inet_ntoa(ia)) == NULL)
500 				return (-1);
501 			returnstat = pa_print(context, &uval, 0);
502 		}
503 
504 	} else if (ip_type == AU_IPv6) {	/* IPv6 addresss (128 bits) */
505 
506 		if (!(context->format & PRF_RAWM)) {
507 			uval.string_val = buf;
508 			get_Hname_ex(ip_addr, buf, sizeof (buf));
509 			returnstat = pa_print(context, &uval, 0);
510 		} else {
511 			uval.string_val = (char *)buf;
512 			(void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
513 			    sizeof (buf));
514 			returnstat = pa_print(context, &uval, 0);
515 		}
516 	} else
517 		returnstat = -1;
518 
519 	if (returnstat)
520 		return (returnstat);
521 
522 	if ((returnstat = close_tag(context, TAG_SOCKEXLADDR)) != 0)
523 		return (returnstat);
524 
525 	/* get foreign ip port */
526 	if ((returnstat = pr_adr_u_short(context, &ip_port, 1)) != 0)
527 		return (returnstat);
528 
529 	if ((returnstat = open_tag(context, TAG_SOCKEXFPORT)) != 0)
530 		return (returnstat);
531 
532 	uval.string_val = hexconvert((char *)&ip_port, sizeof (ip_port),
533 	    sizeof (ip_port));
534 	if (uval.string_val) {
535 		returnstat = pa_print(context, &uval, 0);
536 		free(uval.string_val);
537 	} else
538 		returnstat = -1;
539 
540 	if (returnstat)
541 		return (returnstat);
542 
543 	if ((returnstat = close_tag(context, TAG_SOCKEXFPORT)) != 0)
544 		return (returnstat);
545 
546 	/* get foreign ip address */
547 	if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
548 			return (returnstat);
549 
550 	if ((returnstat = open_tag(context, TAG_SOCKEXFADDR)) != 0)
551 		return (returnstat);
552 
553 	if (ip_type == AU_IPv4) {		/* ipv4 address */
554 
555 		if (!(context->format & PRF_RAWM)) {
556 			uval.string_val = buf;
557 			get_Hname(ip_addr[0], buf, sizeof (buf));
558 			returnstat = pa_print(context, &uval, flag);
559 		} else {
560 			ia.s_addr = ip_addr[0];
561 			if ((uval.string_val = inet_ntoa(ia)) == NULL)
562 				return (-1);
563 			returnstat = pa_print(context, &uval, flag);
564 		}
565 
566 	} else if (ip_type == AU_IPv6) {	/* IPv6 addresss (128 bits) */
567 
568 		if (!(context->format & PRF_RAWM)) {
569 			uval.string_val = buf;
570 			get_Hname_ex(ip_addr, buf, sizeof (buf));
571 			returnstat = pa_print(context, &uval, flag);
572 		} else {
573 			uval.string_val = (char *)buf;
574 			(void) inet_ntop(AF_INET6, (void *)ip_addr, buf,
575 			    sizeof (buf));
576 			returnstat = pa_print(context, &uval, flag);
577 		}
578 	} else
579 		returnstat = -1;
580 
581 	if (returnstat)
582 		return (returnstat);
583 
584 	if ((returnstat = close_tag(context, TAG_SOCKEXFADDR)) != 0)
585 		return (returnstat);
586 
587 	return (returnstat);
588 }
589 
590 
591 #define	NBITSMAJOR64	32	/* # of major device bits in 64-bit Solaris */
592 #define	NBITSMINOR64	32	/* # of minor device bits in 64-bit Solaris */
593 #define	MAXMAJ64	0xfffffffful	/* max major value */
594 #define	MAXMIN64	0xfffffffful	/* max minor value */
595 
596 #define	NBITSMAJOR32	14	/* # of SVR4 major device bits */
597 #define	NBITSMINOR32	18	/* # of SVR4 minor device bits */
598 #define	NMAXMAJ32	0x3fff	/* SVR4 max major value */
599 #define	NMAXMIN32	0x3ffff	/* MAX minor for 3b2 software drivers. */
600 
601 
602 static int32_t
603 minor_64(uint64_t dev)
604 {
605 	if (dev == NODEV) {
606 		errno = EINVAL;
607 		return (NODEV);
608 	}
609 	return (int32_t)(dev & MAXMIN64);
610 }
611 
612 static int32_t
613 major_64(uint64_t dev)
614 {
615 	uint32_t maj;
616 
617 	maj = (uint32_t)(dev >> NBITSMINOR64);
618 
619 	if (dev == NODEV || maj > MAXMAJ64) {
620 		errno = EINVAL;
621 		return (NODEV);
622 	}
623 	return (int32_t)(maj);
624 }
625 
626 static int32_t
627 minor_32(uint32_t dev)
628 {
629 	if (dev == NODEV) {
630 		errno = EINVAL;
631 		return (NODEV);
632 	}
633 	return (int32_t)(dev & MAXMIN32);
634 }
635 
636 static int32_t
637 major_32(uint32_t dev)
638 {
639 	uint32_t maj;
640 
641 	maj = (uint32_t)(dev >> NBITSMINOR32);
642 
643 	if (dev == NODEV || maj > MAXMAJ32) {
644 		errno = EINVAL;
645 		return (NODEV);
646 	}
647 	return (int32_t)(maj);
648 }
649 
650 
651 /*
652  * -----------------------------------------------------------------------
653  * pa_tid() 	: Process terminal id and display contents
654  * return codes	: -1 - error
655  *		:  0 - successful
656  *
657  *	terminal id port		adr_int32
658  *	terminal id machine		adr_int32
659  * -----------------------------------------------------------------------
660  */
661 int
662 pa_tid32(pr_context_t *context, int status, int flag)
663 {
664 	int	returnstat;
665 	int32_t dev_maj_min;
666 	uint32_t	ip_addr;
667 	struct in_addr ia;
668 	char	*ipstring;
669 	char	buf[256];
670 	uval_t	uval;
671 
672 	if (status <  0)
673 		return (status);
674 
675 	if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
676 		return (returnstat);
677 
678 	if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
679 		return (returnstat);
680 
681 	uval.uvaltype = PRA_STRING;
682 	uval.string_val = buf;
683 
684 	if (!(context->format & PRF_RAWM)) {
685 		char	hostname[256];
686 
687 		get_Hname(ip_addr, hostname, sizeof (hostname));
688 		(void) snprintf(buf, sizeof (buf), "%d %d %s",
689 			major_32(dev_maj_min),
690 			minor_32(dev_maj_min),
691 			hostname);
692 		return (pa_print(context, &uval, flag));
693 	}
694 
695 	ia.s_addr = ip_addr;
696 	if ((ipstring = inet_ntoa(ia)) == NULL)
697 		return (-1);
698 
699 	(void) snprintf(buf, sizeof (buf), "%d %d %s",
700 		major_32(dev_maj_min),
701 		minor_32(dev_maj_min),
702 		ipstring);
703 
704 	return (pa_print(context, &uval, flag));
705 }
706 
707 int
708 pa_tid32_ex(pr_context_t *context, int status, int flag)
709 {
710 	int		returnstat;
711 	int32_t		dev_maj_min;
712 	uint32_t	ip_addr[16];
713 	uint32_t	ip_type;
714 	struct in_addr	ia;
715 	char		*ipstring;
716 	char		hostname[256];
717 	char		buf[256];
718 	char		tbuf[256];
719 	uval_t		uval;
720 
721 	if (status <  0)
722 		return (status);
723 
724 	/* get port info */
725 	if ((returnstat = pr_adr_int32(context, &dev_maj_min, 1)) != 0)
726 		return (returnstat);
727 
728 	/* get address type */
729 	if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
730 		return (returnstat);
731 
732 	/* legal address types are either AU_IPv4 or AU_IPv6 only */
733 	if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
734 		return (-1);
735 
736 	/* get address (4/16) */
737 	if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
738 		return (returnstat);
739 
740 	uval.uvaltype = PRA_STRING;
741 	if (ip_type == AU_IPv4) {
742 		uval.string_val = buf;
743 
744 		if (!(context->format & PRF_RAWM)) {
745 			get_Hname(ip_addr[0], hostname, sizeof (hostname));
746 			(void) snprintf(buf, sizeof (buf), "%d %d %s",
747 				major_32(dev_maj_min),
748 				minor_32(dev_maj_min),
749 				hostname);
750 			return (pa_print(context, &uval, flag));
751 		}
752 
753 		ia.s_addr = ip_addr[0];
754 		if ((ipstring = inet_ntoa(ia)) == NULL)
755 			return (-1);
756 
757 		(void) snprintf(buf, sizeof (buf), "%d %d %s",
758 			major_32(dev_maj_min),
759 			minor_32(dev_maj_min),
760 			ipstring);
761 
762 		return (pa_print(context, &uval, flag));
763 	} else {
764 		uval.string_val = buf;
765 
766 		if (!(context->format & PRF_RAWM)) {
767 			get_Hname_ex(ip_addr, hostname, sizeof (hostname));
768 			(void) snprintf(buf, sizeof (buf), "%d %d %s",
769 				major_32(dev_maj_min),
770 				minor_32(dev_maj_min),
771 				hostname);
772 			return (pa_print(context, &uval, flag));
773 		}
774 
775 		(void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
776 		    sizeof (tbuf));
777 
778 		(void) snprintf(buf, sizeof (buf), "%d %d %s",
779 			major_32(dev_maj_min),
780 			minor_32(dev_maj_min),
781 			tbuf);
782 
783 		return (pa_print(context, &uval, flag));
784 	}
785 }
786 
787 int
788 pa_ip_addr(pr_context_t *context, int status, int flag)
789 {
790 	int		returnstat;
791 	uval_t		uval;
792 	uint32_t	ip_addr[4];
793 	uint32_t	ip_type;
794 	struct in_addr	ia;
795 	char		*ipstring;
796 	char		hostname[256];
797 	char		buf[256];
798 	char		tbuf[256];
799 
800 	if (status <  0)
801 		return (status);
802 
803 	/* get address type */
804 	if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
805 		return (returnstat);
806 
807 	/* legal address type is AU_IPv4 or AU_IPv6 */
808 	if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
809 		return (-1);
810 
811 	/* get address (4/16) */
812 	if ((returnstat = pr_adr_char(context, (char *)ip_addr, ip_type)) != 0)
813 		return (returnstat);
814 
815 	uval.uvaltype = PRA_STRING;
816 	if (ip_type == AU_IPv4) {
817 		uval.string_val = buf;
818 
819 		if (!(context->format & PRF_RAWM)) {
820 			get_Hname(ip_addr[0], hostname, sizeof (hostname));
821 			(void) snprintf(buf, sizeof (buf), "%s",
822 				hostname);
823 			return (pa_print(context, &uval, flag));
824 		}
825 
826 		ia.s_addr = ip_addr[0];
827 		if ((ipstring = inet_ntoa(ia)) == NULL)
828 			return (-1);
829 
830 		(void) snprintf(buf, sizeof (buf), "%s",
831 			ipstring);
832 
833 		return (pa_print(context, &uval, flag));
834 	} else {
835 		uval.string_val = buf;
836 
837 		if (!(context->format & PRF_RAWM)) {
838 			get_Hname_ex(ip_addr, hostname, sizeof (hostname));
839 			(void) snprintf(buf, sizeof (buf), "%s",
840 			    hostname);
841 			return (pa_print(context, &uval, flag));
842 		}
843 
844 		(void) inet_ntop(AF_INET6, (void *) ip_addr, tbuf,
845 		    sizeof (tbuf));
846 
847 		(void) snprintf(buf, sizeof (buf), "%s", tbuf);
848 
849 		return (pa_print(context, &uval, flag));
850 	}
851 
852 }
853 
854 int
855 pa_tid64(pr_context_t *context, int status, int flag)
856 {
857 	int	returnstat;
858 	int64_t dev_maj_min;
859 	uint32_t	ip_addr;
860 	struct in_addr ia;
861 	char	*ipstring;
862 	char	buf[256];
863 	uval_t	uval;
864 
865 	if (status <  0)
866 		return (status);
867 
868 	if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
869 		return (returnstat);
870 
871 	if ((returnstat = pr_adr_char(context, (char *)&ip_addr, 4)) != 0)
872 		return (returnstat);
873 
874 	uval.uvaltype = PRA_STRING;
875 	uval.string_val = buf;
876 
877 	if (!(context->format & PRF_RAWM)) {
878 		char	hostname[256];
879 
880 		get_Hname(ip_addr, hostname, sizeof (hostname));
881 		(void) snprintf(buf, sizeof (buf), "%d %d %s",
882 			major_64(dev_maj_min),
883 			minor_64(dev_maj_min),
884 			hostname);
885 		return (pa_print(context, &uval, flag));
886 	}
887 
888 	ia.s_addr = ip_addr;
889 	if ((ipstring = inet_ntoa(ia)) == NULL)
890 		return (-1);
891 
892 	(void) snprintf(buf, sizeof (buf), "%d %d %s",
893 		major_64(dev_maj_min),
894 		minor_64(dev_maj_min),
895 		ipstring);
896 
897 	return (pa_print(context, &uval, flag));
898 }
899 
900 int
901 pa_tid64_ex(pr_context_t *context, int status, int flag)
902 {
903 	int		returnstat;
904 	int64_t		dev_maj_min;
905 	uint32_t	ip_addr[4];
906 	uint32_t	ip_type;
907 	struct in_addr	ia;
908 	char		*ipstring;
909 	char		hostname[256];
910 	char		buf[256];
911 	char		tbuf[256];
912 	uval_t		uval;
913 
914 	if (status <  0)
915 		return (status);
916 
917 	/* get port info */
918 	if ((returnstat = pr_adr_int64(context, &dev_maj_min, 1)) != 0)
919 		return (returnstat);
920 
921 	/* get address type */
922 	if ((returnstat = pr_adr_u_int32(context, &ip_type, 1)) != 0)
923 		return (returnstat);
924 
925 	/* legal address types are either AU_IPv4 or AU_IPv6 only */
926 	if ((ip_type != AU_IPv4) && (ip_type != AU_IPv6))
927 		return (-1);
928 
929 	/* get address (4/16) */
930 	if ((returnstat = pr_adr_char(context, (char *)&ip_addr, ip_type)) != 0)
931 		return (returnstat);
932 
933 	uval.uvaltype = PRA_STRING;
934 	if (ip_type == AU_IPv4) {
935 		uval.string_val = buf;
936 
937 		if (!(context->format & PRF_RAWM)) {
938 			get_Hname(ip_addr[0], hostname, sizeof (hostname));
939 			uval.string_val = buf;
940 			(void) snprintf(buf, sizeof (buf), "%d %d %s",
941 				major_64(dev_maj_min),
942 				minor_64(dev_maj_min),
943 				hostname);
944 			return (pa_print(context, &uval, flag));
945 		}
946 
947 		ia.s_addr = ip_addr[0];
948 		if ((ipstring = inet_ntoa(ia)) == NULL)
949 			return (-1);
950 
951 		(void) snprintf(buf, sizeof (buf), "%d %d %s",
952 			major_64(dev_maj_min),
953 			minor_64(dev_maj_min),
954 			ipstring);
955 
956 		return (pa_print(context, &uval, flag));
957 	} else {
958 		uval.string_val = buf;
959 
960 		if (!(context->format & PRF_RAWM)) {
961 			get_Hname_ex(ip_addr, hostname, sizeof (hostname));
962 			(void) snprintf(buf, sizeof (buf), "%d %d %s",
963 				major_64(dev_maj_min),
964 				minor_64(dev_maj_min),
965 				hostname);
966 			return (pa_print(context, &uval, flag));
967 		}
968 
969 		(void) inet_ntop(AF_INET6, (void *)ip_addr, tbuf,
970 		    sizeof (tbuf));
971 
972 		(void) snprintf(buf, sizeof (buf), "%d %d %s",
973 			major_64(dev_maj_min),
974 			minor_64(dev_maj_min),
975 			tbuf);
976 
977 		return (pa_print(context, &uval, flag));
978 	}
979 }
980 
981 
982 /*
983  * ----------------------------------------------------------------
984  * findfieldwidth:
985  * Returns the field width based on the basic unit and print mode.
986  * This routine is called to determine the field width for the
987  * data items in the arbitrary data token where the tokens are
988  * to be printed in more than one line.  The field width can be
989  * found in the fwidth structure.
990  *
991  * Input parameters:
992  * basicunit	Can be one of AUR_CHAR, AUR_BYTE, AUR_SHORT,
993  *		AUR_INT32, or AUR_INT64
994  * howtoprint	Print mode. Can be one of AUP_BINARY, AUP_OCTAL,
995  *		AUP_DECIMAL, or AUP_HEX.
996  * ----------------------------------------------------------------
997  */
998 int
999 findfieldwidth(char basicunit, char howtoprint)
1000 {
1001 	int	i, j;
1002 
1003 	for (i = 0; i < numwidthentries; i++) {
1004 		if (fwidth[i].basic_unit == basicunit) {
1005 			for (j = 0; j <= 4; j++) {
1006 				if (fwidth[i].pwidth[j].print_base ==
1007 					howtoprint)
1008 				return (fwidth[i].pwidth[j].field_width);
1009 			}
1010 			/*
1011 			 * if we got here, then we didn't get what we were after
1012 			 */
1013 			return (0);
1014 		}
1015 	}
1016 	/* if we got here, we didn't get what we wanted either */
1017 	return (0);
1018 }
1019 
1020 
1021 /*
1022  * -----------------------------------------------------------------------
1023  * pa_cmd: Retrieves the cmd item from the input stream.
1024  * return codes : -1 - error
1025  *		:  0 - successful
1026  * -----------------------------------------------------------------------
1027  */
1028 int
1029 pa_cmd(pr_context_t *context, int status, int flag)
1030 {
1031 	char	*cmd;  /* cmd */
1032 	short	length;
1033 	int	returnstat;
1034 	uval_t	uval;
1035 
1036 	/*
1037 	 * We need to know how much space to allocate for our string, so
1038 	 * read the length first, then call pr_adr_char to read those bytes.
1039 	 */
1040 	if (status >= 0) {
1041 		if (pr_adr_short(context, &length, 1) == 0) {
1042 			if ((cmd = (char *)malloc(length + 1)) == NULL)
1043 				return (-1);
1044 			if (pr_adr_char(context, cmd, length) == 0) {
1045 				uval.uvaltype = PRA_STRING;
1046 				uval.string_val = cmd;
1047 				returnstat = pa_print(context, &uval, flag);
1048 			} else {
1049 				returnstat = -1;
1050 			}
1051 			free(cmd);
1052 			return (returnstat);
1053 		} else
1054 			return (-1);
1055 	} else
1056 		return (status);
1057 }
1058 
1059 
1060 
1061 /*
1062  * -----------------------------------------------------------------------
1063  * pa_adr_byte	: Issues pr_adr_char to retrieve the next ADR item from
1064  *		  the input stream pointed to by audit_adr, and prints it
1065  *		  as an integer if status >= 0
1066  * return codes : -1 - error
1067  *		:  0 - successful
1068  * -----------------------------------------------------------------------
1069  */
1070 int
1071 pa_adr_byte(pr_context_t *context, int status, int flag)
1072 {
1073 	char	c;
1074 	uval_t	uval;
1075 
1076 	if (status >= 0) {
1077 		if (pr_adr_char(context, &c, 1) == 0) {
1078 			uval.uvaltype = PRA_BYTE;
1079 			uval.char_val = c;
1080 			return (pa_print(context, &uval, flag));
1081 		} else
1082 			return (-1);
1083 	} else
1084 		return (status);
1085 }
1086 
1087 /*
1088  * -----------------------------------------------------------------------
1089  * pa_adr_charhex: Issues pr_adr_char to retrieve the next ADR item from
1090  *			the input stream pointed to by audit_adr, and prints it
1091  *			in hexadecimal if status >= 0
1092  * return codes  : -1 - error
1093  *		 :  0 - successful
1094  * -----------------------------------------------------------------------
1095  */
1096 int
1097 pa_adr_charhex(pr_context_t *context, int status, int flag)
1098 {
1099 	char	p[2];
1100 	int	returnstat;
1101 	uval_t	uval;
1102 
1103 	if (status >= 0) {
1104 		p[0] = p[1] = 0;
1105 
1106 		if ((returnstat = pr_adr_char(context, p, 1)) == 0) {
1107 			uval.uvaltype = PRA_STRING;
1108 			uval.string_val = hexconvert(p, sizeof (char),
1109 			    sizeof (char));
1110 			if (uval.string_val) {
1111 				returnstat = pa_print(context, &uval, flag);
1112 				free(uval.string_val);
1113 			}
1114 		}
1115 		return (returnstat);
1116 	} else
1117 		return (status);
1118 }
1119 
1120 /*
1121  * -----------------------------------------------------------------------
1122  * pa_adr_int32	: Issues pr_adr_int32 to retrieve the next ADR item from the
1123  *		  input stream pointed to by audit_adr, and prints it
1124  *		  if status >= 0
1125  * return codes : -1 - error
1126  *		:  0 - successful
1127  * -----------------------------------------------------------------------
1128  */
1129 int
1130 pa_adr_int32(pr_context_t *context, int status, int flag)
1131 {
1132 	int32_t	c;
1133 	uval_t	uval;
1134 
1135 	if (status >= 0) {
1136 		if (pr_adr_int32(context, &c, 1) == 0) {
1137 			uval.uvaltype = PRA_INT32;
1138 			uval.int32_val = c;
1139 			return (pa_print(context, &uval, flag));
1140 		} else
1141 			return (-1);
1142 	} else
1143 		return (status);
1144 }
1145 
1146 
1147 
1148 
1149 /*
1150  * -----------------------------------------------------------------------
1151  * pa_adr_int64	: Issues pr_adr_int64 to retrieve the next ADR item from the
1152  *		  input stream pointed to by audit_adr, and prints it
1153  *		  if status >= 0
1154  * return codes : -1 - error
1155  *		:  0 - successful
1156  * -----------------------------------------------------------------------
1157  */
1158 int
1159 pa_adr_int64(pr_context_t *context, int status, int flag)
1160 {
1161 	int64_t	c;
1162 	uval_t	uval;
1163 
1164 	if (status >= 0) {
1165 		if (pr_adr_int64(context, &c, 1) == 0) {
1166 			uval.uvaltype = PRA_INT64;
1167 			uval.int64_val = c;
1168 			return (pa_print(context, &uval, flag));
1169 		} else
1170 			return (-1);
1171 	} else
1172 		return (status);
1173 }
1174 
1175 /*
1176  * -----------------------------------------------------------------------
1177  * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1178  *			input stream pointed to by audit_adr, and prints it
1179  *			in hexadecimal if status >= 0
1180  * return codes  : -1 - error
1181  *		:  0 - successful
1182  * -----------------------------------------------------------------------
1183  */
1184 int
1185 pa_adr_int32hex(pr_context_t *context, int status, int flag)
1186 {
1187 	int32_t	l;
1188 	int	returnstat;
1189 	uval_t	uval;
1190 
1191 	if (status >= 0) {
1192 		if ((returnstat = pr_adr_int32(context, &l, 1)) == 0) {
1193 			uval.uvaltype = PRA_HEX32;
1194 			uval.int32_val = l;
1195 			returnstat = pa_print(context, &uval, flag);
1196 		}
1197 		return (returnstat);
1198 	} else
1199 		return (status);
1200 }
1201 
1202 /*
1203  * -----------------------------------------------------------------------
1204  * pa_adr_int64hex: Issues pr_adr_int64 to retrieve the next ADR item from the
1205  *			input stream pointed to by audit_adr, and prints it
1206  *			in hexadecimal if status >= 0
1207  * return codes  : -1 - error
1208  *		:  0 - successful
1209  * -----------------------------------------------------------------------
1210  */
1211 int
1212 pa_adr_int64hex(pr_context_t *context, int status, int flag)
1213 {
1214 	int64_t	l;
1215 	int	returnstat;
1216 	uval_t	uval;
1217 
1218 	if (status >= 0) {
1219 		if ((returnstat = pr_adr_int64(context, &l, 1)) == 0) {
1220 			uval.uvaltype = PRA_HEX64;
1221 			uval.int64_val = l;
1222 			returnstat = pa_print(context, &uval, flag);
1223 		}
1224 		return (returnstat);
1225 	} else
1226 		return (status);
1227 }
1228 
1229 
1230 /*
1231  * -------------------------------------------------------------------
1232  * bu2string: Maps a print basic unit type to a string.
1233  * returns  : The string mapping or "unknown basic unit type".
1234  * -------------------------------------------------------------------
1235  */
1236 char *
1237 bu2string(char basic_unit)
1238 {
1239 	register int	i;
1240 
1241 	struct bu_map_ent {
1242 		char	basic_unit;
1243 		char	*string;
1244 	};
1245 
1246 	/*
1247 	 * TRANSLATION_NOTE
1248 	 * These names are data units when displaying the arbitrary data
1249 	 * token.
1250 	 */
1251 
1252 	static struct bu_map_ent bu_map[] = {
1253 				{ AUR_BYTE, "byte" },
1254 				{ AUR_CHAR, "char" },
1255 				{ AUR_SHORT, "short" },
1256 				{ AUR_INT32, "int32" },
1257 				{ AUR_INT64, "int64" } 	};
1258 
1259 	for (i = 0; i < sizeof (bu_map) / sizeof (struct bu_map_ent); i++)
1260 		if (basic_unit == bu_map[i].basic_unit)
1261 			return (gettext(bu_map[i].string));
1262 
1263 	return (gettext("unknown basic unit type"));
1264 }
1265 
1266 
1267 /*
1268  * -------------------------------------------------------------------
1269  * eventmodifier2string: Maps event modifier flags to a readable string.
1270  * returns: The string mapping or "none".
1271  * -------------------------------------------------------------------
1272  */
1273 static void
1274 eventmodifier2string(ushort_t emodifier, char *modstring, size_t modlen)
1275 {
1276 	register int	i, j;
1277 
1278 	struct em_map_ent {
1279 		int	mask;
1280 		char	*string;
1281 	};
1282 
1283 	/*
1284 	 * TRANSLATION_NOTE
1285 	 * These abbreviations represent the event modifier field of the
1286 	 * header token.  To gain a better understanding of each modifier,
1287 	 * read the SunShield BSM Guide, part no. 802-1965-xx.
1288 	 */
1289 
1290 	static struct em_map_ent em_map[] = {
1291 		{ (int)PAD_READ,	"rd" },	/* data read from object */
1292 		{ (int)PAD_WRITE,	"wr" },	/* data written to object */
1293 #ifdef TSOL
1294 		{ (int)PAD_SPRIVUSE,	"sp" },	/* successfully used priv */
1295 		{ (int)PAD_FPRIVUSE,	"fp" },	/* failed use of priv */
1296 #endif
1297 		{ (int)PAD_NONATTR,	"na" },	/* non-attributable event */
1298 		{ (int)PAD_FAILURE,	"fe" }	/* fail audit event */
1299 	};
1300 
1301 	modstring[0] = '\0';
1302 
1303 	for (i = 0, j = 0; i < sizeof (em_map) / sizeof (struct em_map_ent);
1304 	    i++) {
1305 		if ((int)emodifier & em_map[i].mask) {
1306 			if (j++)
1307 				(void) strlcat(modstring, ":", modlen);
1308 			(void) strlcat(modstring, em_map[i].string, modlen);
1309 		}
1310 	}
1311 }
1312 
1313 
1314 /*
1315  * ---------------------------------------------------------
1316  * convert_char_to_string:
1317  *   Converts a byte to string depending on the print mode
1318  * input	: printmode, which may be one of AUP_BINARY,
1319  *		  AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1320  *		  c, which is the byte to convert
1321  * output	: p, which is a pointer to the location where
1322  *		  the resulting string is to be stored
1323  *  ----------------------------------------------------------
1324  */
1325 
1326 int
1327 convert_char_to_string(char printmode, char c, char *p)
1328 {
1329 	union {
1330 		char	c1[4];
1331 		int	c2;
1332 	} dat;
1333 
1334 	dat.c2 = 0;
1335 	dat.c1[3] = c;
1336 
1337 	if (printmode == AUP_BINARY)
1338 		(void) convertbinary(p, &c, sizeof (char));
1339 	else if (printmode == AUP_OCTAL)
1340 		(void) sprintf(p, "%o", (int)dat.c2);
1341 	else if (printmode == AUP_DECIMAL)
1342 		(void) sprintf(p, "%d", c);
1343 	else if (printmode == AUP_HEX)
1344 		(void) sprintf(p, "0x%x", (int)dat.c2);
1345 	else if (printmode == AUP_STRING)
1346 		convertascii(p, &c, sizeof (char));
1347 	return (0);
1348 }
1349 
1350 /*
1351  * --------------------------------------------------------------
1352  * convert_short_to_string:
1353  * Converts a short integer to string depending on the print mode
1354  * input	: printmode, which may be one of AUP_BINARY,
1355  *		AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1356  *		c, which is the short integer to convert
1357  * output	: p, which is a pointer to the location where
1358  *		the resulting string is to be stored
1359  * ---------------------------------------------------------------
1360  */
1361 int
1362 convert_short_to_string(char printmode, short c, char *p)
1363 {
1364 	union {
1365 		short	c1[2];
1366 		int	c2;
1367 	} dat;
1368 
1369 	dat.c2 = 0;
1370 	dat.c1[1] = c;
1371 
1372 	if (printmode == AUP_BINARY)
1373 		(void) convertbinary(p, (char *)&c, sizeof (short));
1374 	else if (printmode == AUP_OCTAL)
1375 		(void) sprintf(p, "%o", (int)dat.c2);
1376 	else if (printmode == AUP_DECIMAL)
1377 		(void) sprintf(p, "%hd", c);
1378 	else if (printmode == AUP_HEX)
1379 		(void) sprintf(p, "0x%x", (int)dat.c2);
1380 	else if (printmode == AUP_STRING)
1381 		convertascii(p, (char *)&c, sizeof (short));
1382 	return (0);
1383 }
1384 
1385 /*
1386  * ---------------------------------------------------------
1387  * convert_int32_to_string:
1388  * Converts a integer to string depending on the print mode
1389  * input	: printmode, which may be one of AUP_BINARY,
1390  *		AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1391  *		c, which is the integer to convert
1392  * output	: p, which is a pointer to the location where
1393  *		the resulting string is to be stored
1394  * ----------------------------------------------------------
1395  */
1396 int
1397 convert_int32_to_string(char printmode, int32_t c, char *p)
1398 {
1399 	if (printmode == AUP_BINARY)
1400 		(void) convertbinary(p, (char *)&c, sizeof (int32_t));
1401 	else if (printmode == AUP_OCTAL)
1402 		(void) sprintf(p, "%o", c);
1403 	else if (printmode == AUP_DECIMAL)
1404 		(void) sprintf(p, "%d", c);
1405 	else if (printmode == AUP_HEX)
1406 		(void) sprintf(p, "0x%x", c);
1407 	else if (printmode == AUP_STRING)
1408 		convertascii(p, (char *)&c, sizeof (int));
1409 	return (0);
1410 }
1411 
1412 /*
1413  * ---------------------------------------------------------
1414  * convert_int64_to_string:
1415  * Converts a integer to string depending on the print mode
1416  * input	: printmode, which may be one of AUP_BINARY,
1417  *		AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
1418  *		c, which is the integer to convert
1419  * output	: p, which is a pointer to the location where
1420  *		the resulting string is to be stored
1421  * ----------------------------------------------------------
1422  */
1423 int
1424 convert_int64_to_string(char printmode, int64_t c, char *p)
1425 {
1426 	if (printmode == AUP_BINARY)
1427 		(void) convertbinary(p, (char *)&c, sizeof (int64_t));
1428 	else if (printmode == AUP_OCTAL)
1429 		(void) sprintf(p, "%"PRIo64, c);
1430 	else if (printmode == AUP_DECIMAL)
1431 		(void) sprintf(p, "%"PRId64, c);
1432 	else if (printmode == AUP_HEX)
1433 		(void) sprintf(p, "0x%"PRIx64, c);
1434 	else if (printmode == AUP_STRING)
1435 		convertascii(p, (char *)&c, sizeof (int64_t));
1436 	return (0);
1437 }
1438 
1439 
1440 /*
1441  * -----------------------------------------------------------
1442  * convertbinary:
1443  * Converts a unit c of 'size' bytes long into a binary string
1444  * and returns it into the position pointed to by p
1445  * ------------------------------------------------------------
1446  */
1447 int
1448 convertbinary(char *p, char *c, int size)
1449 {
1450 	char	*s, *t, *ss;
1451 	int	i, j;
1452 
1453 	if ((s = (char *)malloc(8 * size + 1)) == NULL)
1454 		return (0);
1455 
1456 	ss = s;
1457 
1458 	/* first convert to binary */
1459 	t = s;
1460 	for (i = 0; i < size; i++) {
1461 		for (j = 0; j < 8; j++)
1462 			(void) sprintf(t++, "%d", ((*c >> (7 - j)) & (0x01)));
1463 		c++;
1464 	}
1465 	*t = '\0';
1466 
1467 	/* now string leading zero's if any */
1468 	j = strlen(s) - 1;
1469 	for (i = 0; i < j; i++) {
1470 		if (*s != '0')
1471 			break;
1472 			else
1473 			s++;
1474 	}
1475 
1476 	/* now copy the contents of s to p */
1477 	t = p;
1478 	for (i = 0; i < (8 * size + 1); i++) {
1479 		if (*s == '\0') {
1480 			*t = '\0';
1481 			break;
1482 		}
1483 		*t++ = *s++;
1484 	}
1485 	free(ss);
1486 
1487 	return (1);
1488 }
1489 
1490 
1491 static char hex[] = "0123456789abcdef";
1492 /*
1493  * -------------------------------------------------------------------
1494  * hexconvert	: Converts a string of (size) bytes to hexadecimal, and
1495  *		returns the hexadecimal string.
1496  * returns	: - NULL if memory cannot be allocated for the string, or
1497  *		- pointer to the hexadecimal string if successful
1498  * -------------------------------------------------------------------
1499  */
1500 char *
1501 hexconvert(char *c, int size, int chunk)
1502 {
1503 	register char	*s, *t;
1504 	register int	i, j, k;
1505 	int	numchunks;
1506 	int	leftovers;
1507 
1508 	if (size <= 0)
1509 		return (NULL);
1510 
1511 	if ((s = (char *)malloc((size * 5) + 1)) == NULL)
1512 		return (NULL);
1513 
1514 	if (chunk > size || chunk <= 0)
1515 		chunk = size;
1516 
1517 	numchunks = size / chunk;
1518 	leftovers = size % chunk;
1519 
1520 	t = s;
1521 	for (i = j = 0; i < numchunks; i++) {
1522 		if (j++) {
1523 			*t++ = ' ';
1524 		}
1525 		*t++ = '0';
1526 		*t++ = 'x';
1527 		for (k = 0; k < chunk; k++) {
1528 			*t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1529 			*t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1530 			c++;
1531 		}
1532 	}
1533 
1534 	if (leftovers) {
1535 		*t++ = ' ';
1536 		*t++ = '0';
1537 		*t++ = 'x';
1538 		for (i = 0; i < leftovers; i++) {
1539 			*t++ = hex[(uint_t)((uchar_t)*c >> 4)];
1540 			*t++ = hex[(uint_t)((uchar_t)*c & 0xF)];
1541 			c++;
1542 		}
1543 	}
1544 
1545 	*t = '\0';
1546 	return (s);
1547 }
1548 
1549 
1550 /*
1551  * -------------------------------------------------------------------
1552  * htp2string: Maps a print suggestion to a string.
1553  * returns   : The string mapping or "unknown print suggestion".
1554  * -------------------------------------------------------------------
1555  */
1556 char *
1557 htp2string(char print_sugg)
1558 {
1559 	register int	i;
1560 
1561 	struct htp_map_ent {
1562 		char	print_sugg;
1563 		char	*print_string;
1564 	};
1565 
1566 	/*
1567 	 * TRANSLATION_NOTE
1568 	 * These names are data types when displaying the arbitrary data
1569 	 * token.
1570 	 */
1571 
1572 	static struct htp_map_ent htp_map[] = {
1573 				{ AUP_BINARY, "binary" },
1574 				{ AUP_OCTAL, "octal" },
1575 				{ AUP_DECIMAL, "decimal" },
1576 				{ AUP_HEX, "hexadecimal" },
1577 				{ AUP_STRING, "string" } 	};
1578 
1579 	for (i = 0; i < sizeof (htp_map) / sizeof (struct htp_map_ent); i++)
1580 		if (print_sugg == htp_map[i].print_sugg)
1581 			return (gettext(htp_map[i].print_string));
1582 
1583 	return (gettext("unknown print suggestion"));
1584 }
1585 
1586 /*
1587  * ----------------------------------------------------------------------
1588  * pa_adr_short: Issues pr_adr_short to retrieve the next ADR item from the
1589  *		input stream pointed to by audit_adr, and prints it
1590  *		if status >= 0
1591  * return codes: -1 - error
1592  *		:  0 - successful
1593  * ----------------------------------------------------------------------
1594  */
1595 int
1596 pa_adr_short(pr_context_t *context, int status, int flag)
1597 {
1598 	short	c;
1599 	uval_t	uval;
1600 
1601 	if (status >= 0) {
1602 		if (pr_adr_short(context, &c, 1) == 0) {
1603 			uval.uvaltype = PRA_SHORT;
1604 			uval.short_val = c;
1605 			return (pa_print(context, &uval, flag));
1606 		} else
1607 			return (-1);
1608 	} else
1609 		return (status);
1610 }
1611 
1612 /*
1613  * -----------------------------------------------------------------------
1614  * pa_adr_shorthex: Issues pr_adr_short to retrieve the next ADR item from the
1615  *			input stream pointed to by audit_adr, and prints it
1616  *			in hexadecimal if status >= 0
1617  * return codes  : -1 - error
1618  *		:  0 - successful
1619  * -----------------------------------------------------------------------
1620  */
1621 int
1622 pa_adr_shorthex(pr_context_t *context, int status, int flag)
1623 {
1624 	short	s;
1625 	int	returnstat;
1626 	uval_t	uval;
1627 
1628 	if (status >= 0) {
1629 		if ((returnstat = pr_adr_short(context, &s, 1)) == 0) {
1630 			uval.uvaltype = PRA_STRING;
1631 			uval.string_val = hexconvert((char *)&s, sizeof (s),
1632 			    sizeof (s));
1633 			if (uval.string_val) {
1634 				returnstat = pa_print(context, &uval, flag);
1635 				free(uval.string_val);
1636 			}
1637 		}
1638 		return (returnstat);
1639 	} else
1640 		return (status);
1641 }
1642 
1643 
1644 /*
1645  * -----------------------------------------------------------------------
1646  * pa_adr_string: Retrieves a string from the input stream and prints it
1647  *		  if status >= 0
1648  * return codes : -1 - error
1649  *		:  0 - successful
1650  * -----------------------------------------------------------------------
1651  */
1652 int
1653 pa_adr_string(pr_context_t *context, int status, int flag)
1654 {
1655 	char	*c;
1656 	char	*p;
1657 	short	length;
1658 	int	returnstat;
1659 	uval_t	uval;
1660 
1661 	/*
1662 	 * We need to know how much space to allocate for our string, so
1663 	 * read the length first, then call pr_adr_char to read those bytes.
1664 	 */
1665 	if (status < 0)
1666 		return (status);
1667 
1668 	if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1669 		return (returnstat);
1670 	if ((c = (char *)malloc(length + 1)) == NULL)
1671 		return (-1);
1672 	if ((p = (char *)malloc((length * 2) + 1)) == NULL) {
1673 		free(c);
1674 		return (-1);
1675 	}
1676 	if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1677 		free(c);
1678 		free(p);
1679 		return (returnstat);
1680 	}
1681 	convertascii(p, c, length - 1);
1682 	uval.uvaltype = PRA_STRING;
1683 	uval.string_val = p;
1684 	returnstat = pa_print(context, &uval, flag);
1685 	free(c);
1686 	free(p);
1687 	return (returnstat);
1688 }
1689 
1690 /*
1691  * -----------------------------------------------------------------------
1692  * pa_file_string: Retrieves a file string from the input stream and prints it
1693  *		  if status >= 0
1694  * return codes : -1 - error
1695  *		:  0 - successful
1696  * -----------------------------------------------------------------------
1697  */
1698 int
1699 pa_file_string(pr_context_t *context, int status, int flag)
1700 {
1701 	char	*c;
1702 	char	*p;
1703 	short	length;
1704 	int	returnstat;
1705 	uval_t	uval;
1706 
1707 	/*
1708 	 * We need to know how much space to allocate for our string, so
1709 	 * read the length first, then call pr_adr_char to read those bytes.
1710 	 */
1711 	if (status < 0)
1712 		return (status);
1713 
1714 	if ((returnstat = pr_adr_short(context, &length, 1)) != 0)
1715 		return (returnstat);
1716 	if ((c = (char *)malloc(length + 1)) == NULL)
1717 		return (-1);
1718 	if ((p = (char *)malloc((length * 2) + 1)) == NULL) {
1719 		free(c);
1720 		return (-1);
1721 	}
1722 	if ((returnstat = pr_adr_char(context, c, length)) != 0) {
1723 		free(c);
1724 		free(p);
1725 		return (returnstat);
1726 	}
1727 
1728 	if (is_file_token(context->tokenid))
1729 		context->audit_rec_len += length;
1730 
1731 	convertascii(p, c, length - 1);
1732 	uval.uvaltype = PRA_STRING;
1733 	uval.string_val = p;
1734 
1735 	if (returnstat == 0)
1736 		returnstat = finish_open_tag(context);
1737 
1738 	if (returnstat == 0)
1739 		returnstat = pa_print(context, &uval, flag);
1740 
1741 	free(c);
1742 	free(p);
1743 	return (returnstat);
1744 }
1745 
1746 static int
1747 pa_putstr_xml(pr_context_t *context, int printable, char *str, size_t len)
1748 {
1749 	int	err;
1750 
1751 	if (!printable) {
1752 		/*
1753 		 * Unprintable chars should always be converted to the
1754 		 * visible form. If there are unprintable characters which
1755 		 * require special treatment in xml, those should be
1756 		 * handled here.
1757 		 */
1758 		do {
1759 			err = pr_printf(context, "\\%03o",
1760 				(unsigned char)*str++);
1761 		} while (err == 0 && --len != 0);
1762 		return (err);
1763 	}
1764 	/* printable characters */
1765 	if (len == 1) {
1766 		/*
1767 		 * check for the special chars only when char size was 1
1768 		 * ie, ignore special chars appear in the middle of multibyte
1769 		 * sequence.
1770 		 */
1771 
1772 		/* Escape for XML */
1773 		switch (*str) {
1774 		case '&':
1775 			err = pr_printf(context, "%s", "&amp;");
1776 			break;
1777 
1778 		case '<':
1779 			err = pr_printf(context, "%s", "&lt;");
1780 			break;
1781 
1782 		case '>':
1783 			err = pr_printf(context, "%s", "&gt;");
1784 			break;
1785 
1786 		case '\"':
1787 			err = pr_printf(context, "%s", "&quot;");
1788 			break;
1789 
1790 		case '\'':
1791 			err = pr_printf(context, "%s", "&apos;");
1792 			break;
1793 
1794 		default:
1795 			err = pr_putchar(context, *str);
1796 			break;
1797 		}
1798 		return (err);
1799 	}
1800 	do {
1801 		err = pr_putchar(context, *str++);
1802 	} while (err == 0 && --len != 0);
1803 	return (err);
1804 }
1805 
1806 static int
1807 pa_putstr(pr_context_t *context, int printable, char *str, size_t len)
1808 {
1809 	int	err;
1810 
1811 	if (context->format & PRF_XMLM)
1812 		return (pa_putstr_xml(context, printable, str, len));
1813 
1814 	if (!printable) {
1815 		do {
1816 			err = pr_printf(context, "\\%03o",
1817 				(unsigned char)*str++);
1818 		} while (err == 0 && --len != 0);
1819 		return (err);
1820 	}
1821 	do {
1822 		err = pr_putchar(context, *str++);
1823 	} while (err == 0 && --len != 0);
1824 	return (err);
1825 }
1826 
1827 int
1828 pa_string(pr_context_t *context, int status, int flag)
1829 {
1830 	int	rstat, wstat;
1831 	int	i, printable, eos;
1832 	int	mlen, rlen;
1833 	int	mbmax = MB_CUR_MAX;
1834 	wchar_t	wc;
1835 	char	mbuf[MB_LEN_MAX + 1];
1836 	char	c;
1837 
1838 	if (status < 0)
1839 		return (status);
1840 
1841 	rstat = wstat = 0;
1842 
1843 	if (mbmax == 1) {
1844 		while (wstat == 0) {
1845 			if ((rstat = pr_adr_char(context, &c, 1)) < 0)
1846 				break;
1847 			if (c == '\0')
1848 				break;
1849 			printable = isprint((unsigned char)c);
1850 			wstat = pa_putstr(context, printable, &c, 1);
1851 		}
1852 		goto done;
1853 	}
1854 
1855 	mlen = eos = 0;
1856 	while (wstat == 0) {
1857 		rlen = 0;
1858 		do {
1859 			if (!eos) {
1860 				rstat = pr_adr_char(context, &c, 1);
1861 				if (rstat != 0 || c == '\0')
1862 					eos = 1;
1863 				else
1864 					mbuf[mlen++] = c;
1865 			}
1866 			rlen = mbtowc(&wc, mbuf, mlen);
1867 		} while (!eos && mlen < mbmax && rlen <= 0);
1868 
1869 		if (mlen == 0)
1870 			break;	/* end of string */
1871 
1872 		if (rlen <= 0) { /* no good sequence */
1873 			rlen = 1;
1874 			printable = 0;
1875 		} else {
1876 			printable = iswprint(wc);
1877 		}
1878 		wstat = pa_putstr(context, printable, mbuf, rlen);
1879 		mlen -= rlen;
1880 		if (mlen > 0) {
1881 			for (i = 0; i < mlen; i++)
1882 				mbuf[i] = mbuf[rlen + i];
1883 		}
1884 	}
1885 
1886 done:
1887 	if (wstat == 0)
1888 		wstat = do_newline(context, flag);
1889 
1890 	if (wstat == 0 && context->data_mode == FILEMODE)
1891 		(void) fflush(stdout);
1892 
1893 	return ((rstat != 0 || wstat != 0) ? -1 : 0);
1894 }
1895 
1896 /*
1897  * -----------------------------------------------------------------------
1898  * pa_adr_u_int32: Issues pr_adr_u_int32 to retrieve the next ADR item from
1899  *		  the input stream pointed to by audit_adr, and prints it
1900  *		  if status = 0
1901  * return codes : -1 - error
1902  *		:  0 - successful
1903  * -----------------------------------------------------------------------
1904  */
1905 
1906 
1907 int
1908 pa_adr_u_int32(pr_context_t *context, int status, int flag)
1909 {
1910 	uint32_t c;
1911 	uval_t	uval;
1912 
1913 	if (status >= 0) {
1914 		if (pr_adr_u_int32(context, &c, 1) == 0) {
1915 			uval.uvaltype = PRA_UINT32;
1916 			uval.uint32_val = c;
1917 			return (pa_print(context, &uval, flag));
1918 		} else
1919 			return (-1);
1920 	} else
1921 		return (status);
1922 }
1923 
1924 
1925 
1926 /*
1927  * -----------------------------------------------------------------------
1928  * pa_adr_u_int64: Issues pr_adr_u_int64 to retrieve the next ADR item from the
1929  *		  input stream pointed to by audit_adr, and prints it
1930  *		  if status = 0
1931  * return codes : -1 - error
1932  *		:  0 - successful
1933  * -----------------------------------------------------------------------
1934  */
1935 int
1936 pa_adr_u_int64(pr_context_t *context, int status, int flag)
1937 {
1938 	uint64_t c;
1939 	uval_t	uval;
1940 
1941 	if (status >= 0) {
1942 		if (pr_adr_u_int64(context, &c, 1) == 0) {
1943 			uval.uvaltype = PRA_UINT64;
1944 			uval.uint64_val = c;
1945 			return (pa_print(context, &uval, flag));
1946 		} else
1947 			return (-1);
1948 	} else
1949 		return (status);
1950 }
1951 
1952 
1953 /*
1954  * -----------------------------------------------------------------------
1955  * pa_adr_u_short: Issues pr_adr_u_short to retrieve the next ADR item from
1956  *			the input stream pointed to by audit_adr, and prints it
1957  *			if status = 0
1958  * return codes : -1 - error
1959  *		:  0 - successful
1960  * -----------------------------------------------------------------------
1961  */
1962 int
1963 pa_adr_u_short(pr_context_t *context, int status, int flag)
1964 {
1965 	ushort_t c;
1966 	uval_t	uval;
1967 
1968 	if (status >= 0) {
1969 		if (pr_adr_u_short(context, &c, 1) == 0) {
1970 			uval.uvaltype = PRA_USHORT;
1971 			uval.ushort_val = c;
1972 			return (pa_print(context, &uval, flag));
1973 		} else
1974 			return (-1);
1975 	} else
1976 		return (status);
1977 }
1978 
1979 /*
1980  * -----------------------------------------------------------------------
1981  * pa_reclen: Issues pr_adr_u_long to retrieve the length of the record
1982  *		  from the input stream pointed to by audit_adr,
1983  *		  and prints it (unless format is XML) if status = 0
1984  * return codes : -1 - error
1985  *		:  0 - successful
1986  * -----------------------------------------------------------------------
1987  */
1988 int
1989 pa_reclen(pr_context_t *context, int status)
1990 {
1991 	uint32_t c;
1992 	uval_t	uval;
1993 
1994 	if (status >= 0) {
1995 		if ((int)pr_adr_u_int32(context, &c, 1) == 0) {
1996 			context->audit_rec_len = c;
1997 
1998 			/* Don't print this for XML format */
1999 			if (context->format & PRF_XMLM) {
2000 				return (0);
2001 			} else {
2002 				uval.uvaltype = PRA_UINT32;
2003 				uval.uint32_val = c;
2004 				return (pa_print(context, &uval, 0));
2005 			}
2006 		} else
2007 			return (-1);
2008 	} else
2009 		return (status);
2010 }
2011 
2012 /*
2013  * -----------------------------------------------------------------------
2014  * pa_mode	: Issues pr_adr_u_short to retrieve the next ADR item from
2015  *		the input stream pointed to by audit_adr, and prints it
2016  *		in octal if status = 0
2017  * return codes : -1 - error
2018  *		:  0 - successful
2019  * -----------------------------------------------------------------------
2020  */
2021 int
2022 pa_mode(pr_context_t *context, int status, int flag)
2023 {
2024 	uint32_t c;
2025 	uval_t	uval;
2026 
2027 	if (status >= 0) {
2028 		if (pr_adr_u_int32(context, &c, 1) == 0) {
2029 			uval.uvaltype = PRA_LOCT;
2030 			uval.uint32_val = c;
2031 			return (pa_print(context, &uval, flag));
2032 		} else
2033 			return (-1);
2034 	} else
2035 		return (status);
2036 }
2037 
2038 
2039 /*
2040  * -----------------------------------------------------------------------
2041  * pa_pw_uid()	: Issues pr_adr_u_int32 to reads uid from input stream
2042  *		pointed to by audit_adr, and displays it in either
2043  *		raw form or its ASCII representation, if status >= 0.
2044  * return codes : -1 - error
2045  * 		:  1 - warning, passwd entry not found
2046  *		:  0 - successful
2047  * -----------------------------------------------------------------------
2048  */
2049 int
2050 pa_pw_uid(pr_context_t *context, int status, int flag)
2051 {
2052 	int	returnstat;
2053 	struct passwd *pw;
2054 	uint32_t uid;
2055 	uval_t	uval;
2056 
2057 	if (status < 0)
2058 		return (status);
2059 
2060 	if (pr_adr_u_int32(context, &uid, 1) != 0)
2061 		/* cannot retrieve uid */
2062 		return (-1);
2063 
2064 	if (!(context->format & PRF_RAWM)) {
2065 		/* get password file entry */
2066 		if ((pw = getpwuid(uid)) == NULL) {
2067 			returnstat = 1;
2068 		} else {
2069 			/* print in ASCII form */
2070 			uval.uvaltype = PRA_STRING;
2071 			uval.string_val = pw->pw_name;
2072 			returnstat = pa_print(context, &uval, flag);
2073 		}
2074 	}
2075 	/* print in integer form */
2076 	if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2077 		uval.uvaltype = PRA_INT32;
2078 		uval.int32_val = uid;
2079 		returnstat = pa_print(context, &uval, flag);
2080 	}
2081 	return (returnstat);
2082 }
2083 
2084 
2085 /*
2086  * -----------------------------------------------------------------------
2087  * pa_gr_uid()	: Issues pr_adr_u_int32 to reads group uid from input stream
2088  *			pointed to by audit_adr, and displays it in either
2089  *			raw form or its ASCII representation, if status >= 0.
2090  * return codes : -1 - error
2091  * 		:  1 - warning, passwd entry not found
2092  *		:  0 - successful
2093  * -----------------------------------------------------------------------
2094  */
2095 int
2096 pa_gr_uid(pr_context_t *context, int status, int flag)
2097 {
2098 	int	returnstat;
2099 	struct group *gr;
2100 	uint32_t gid;
2101 	uval_t	uval;
2102 
2103 	if (status < 0)
2104 		return (status);
2105 
2106 	if (pr_adr_u_int32(context, &gid, 1) != 0)
2107 		/* cannot retrieve gid */
2108 		return (-1);
2109 
2110 	if (!(context->format & PRF_RAWM)) {
2111 		/* get group file entry */
2112 		if ((gr = getgrgid(gid)) == NULL) {
2113 			returnstat = 1;
2114 		} else {
2115 			/* print in ASCII form */
2116 			uval.uvaltype = PRA_STRING;
2117 			uval.string_val = gr->gr_name;
2118 			returnstat = pa_print(context, &uval, flag);
2119 		}
2120 	}
2121 	/* print in integer form */
2122 	if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2123 		uval.uvaltype = PRA_INT32;
2124 		uval.int32_val = gid;
2125 		returnstat = pa_print(context, &uval, flag);
2126 	}
2127 	return (returnstat);
2128 }
2129 
2130 
2131 /*
2132  * -----------------------------------------------------------------------
2133  * pa_pw_uid_gr_gid()	: Issues pr_adr_u_int32 to reads uid or group uid
2134  *			from input stream
2135  *			pointed to by audit_adr, and displays it in either
2136  *			raw form or its ASCII representation, if status >= 0.
2137  * return codes : -1 - error
2138  * 		:  1 - warning, passwd entry not found
2139  *		:  0 - successful
2140  * -----------------------------------------------------------------------
2141  */
2142 int
2143 pa_pw_uid_gr_gid(pr_context_t *context, int status, int flag)
2144 {
2145 	int	returnstat;
2146 	uint32_t	value;
2147 	uval_t		uval;
2148 
2149 	if (status < 0)
2150 		return (status);
2151 
2152 	/* get value of a_type */
2153 	if ((returnstat = pr_adr_u_int32(context, &value, 1)) != 0)
2154 		return (returnstat);
2155 
2156 	if ((returnstat = open_tag(context, TAG_ACLTYPE)) != 0)
2157 		return (returnstat);
2158 
2159 	uval.uvaltype = PRA_UINT32;
2160 	uval.uint32_val = value;
2161 	if ((returnstat = pa_print(context, &uval, flag)) != 0)
2162 		return (returnstat);
2163 
2164 	if ((returnstat = close_tag(context, TAG_ACLTYPE)) != 0)
2165 		return (returnstat);
2166 
2167 	if ((returnstat = open_tag(context, TAG_ACLVAL)) != 0)
2168 		return (returnstat);
2169 	/*
2170 	 * TRANSLATION_NOTE
2171 	 * The "mask" and "other" strings refer to the class mask
2172 	 * and other (or world) entries in an ACL.
2173 	 * The "unrecognized" string refers to an unrecognized ACL
2174 	 * entry.
2175 	 */
2176 	switch (value) {
2177 		case USER_OBJ:
2178 		case USER:
2179 			returnstat = pa_pw_uid(context, returnstat, flag);
2180 			break;
2181 		case GROUP_OBJ:
2182 		case GROUP:
2183 			returnstat = pa_gr_uid(context, returnstat, flag);
2184 			break;
2185 		case CLASS_OBJ:
2186 		    returnstat = pr_adr_u_int32(context, &value, 1);
2187 		    if (returnstat != 0)
2188 			return (returnstat);
2189 
2190 		    if (!(context->format & PRF_RAWM)) {
2191 			uval.uvaltype = PRA_STRING;
2192 			uval.string_val = gettext("mask");
2193 			returnstat = pa_print(context, &uval, flag);
2194 		    } else {
2195 			uval.uvaltype = PRA_UINT32;
2196 			uval.uint32_val = value;
2197 			if ((returnstat = pa_print(context, &uval, flag)) != 0)
2198 				return (returnstat);
2199 		    }
2200 		    break;
2201 		case OTHER_OBJ:
2202 		    returnstat = pr_adr_u_int32(context, &value, 1);
2203 		    if (returnstat != 0)
2204 			return (returnstat);
2205 
2206 		    if (!(context->format & PRF_RAWM)) {
2207 			uval.uvaltype = PRA_STRING;
2208 			uval.string_val = gettext("other");
2209 			returnstat = pa_print(context, &uval, flag);
2210 		    } else {
2211 			uval.uvaltype = PRA_UINT32;
2212 			uval.uint32_val = value;
2213 			if ((returnstat = pa_print(context, &uval, flag)) != 0)
2214 				return (returnstat);
2215 		    }
2216 		    break;
2217 		default:
2218 		    returnstat = pr_adr_u_int32(context, &value, 1);
2219 		    if (returnstat != 0)
2220 			return (returnstat);
2221 
2222 		    if (!(context->format & PRF_RAWM)) {
2223 			uval.uvaltype = PRA_STRING;
2224 			uval.string_val = gettext("unrecognized");
2225 			returnstat = pa_print(context, &uval, flag);
2226 		    } else {
2227 			uval.uvaltype = PRA_UINT32;
2228 			uval.uint32_val = value;
2229 			if ((returnstat = pa_print(context, &uval, flag)) != 0)
2230 				return (returnstat);
2231 		    }
2232 	}
2233 
2234 	if ((returnstat = close_tag(context, TAG_ACLVAL)) != 0)
2235 		return (returnstat);
2236 
2237 	return (returnstat);
2238 }
2239 
2240 
2241 /*
2242  * -----------------------------------------------------------------------
2243  * pa_event_modifier(): Issues pr_adr_u_short to retrieve the next ADR item from
2244  *		  the input stream pointed to by audit_adr.  This is the
2245  *		  event type, and is displayed in hex;
2246  * return codes : -1 - error
2247  *		:  0 - successful
2248  * -----------------------------------------------------------------------
2249  */
2250 int
2251 pa_event_modifier(pr_context_t *context, int status,  int flag)
2252 {
2253 	int	returnstat;
2254 	ushort_t emodifier;
2255 	uval_t	uval;
2256 	char	modstring[64];
2257 
2258 	if (status < 0)
2259 		return (status);
2260 
2261 	if ((returnstat = pr_adr_u_short(context, &emodifier, 1)) != 0)
2262 		return (returnstat);
2263 
2264 	/* For XML, only print when modifier is non-zero */
2265 	if (!(context->format & PRF_XMLM) || (emodifier != 0)) {
2266 		uval.uvaltype = PRA_STRING;
2267 
2268 		returnstat = open_tag(context, TAG_EVMOD);
2269 
2270 		if (returnstat >= 0) {
2271 			if (!(context->format & PRF_RAWM)) {
2272 				eventmodifier2string(emodifier, modstring,
2273 				    sizeof (modstring));
2274 				uval.string_val = modstring;
2275 				returnstat = pa_print(context, &uval, flag);
2276 			} else {
2277 				uval.string_val = hexconvert((char *)&emodifier,
2278 				    sizeof (emodifier), sizeof (emodifier));
2279 				if (uval.string_val) {
2280 					returnstat = pa_print(context, &uval,
2281 					    flag);
2282 					free(uval.string_val);
2283 				}
2284 			}
2285 		}
2286 		if (returnstat >= 0)
2287 			returnstat = close_tag(context, TAG_EVMOD);
2288 	}
2289 
2290 	return (returnstat);
2291 }
2292 
2293 
2294 /*
2295  * -----------------------------------------------------------------------
2296  * pa_event_type(): Issues pr_adr_u_short to retrieve the next ADR item from
2297  *		  the input stream pointed to by audit_adr.  This is the
2298  *		  event type, and is displayed in either raw or
2299  *		  ASCII form as appropriate
2300  * return codes : -1 - error
2301  *		:  0 - successful
2302  * -----------------------------------------------------------------------
2303  */
2304 int
2305 pa_event_type(pr_context_t *context, int status,  int flag)
2306 {
2307 	ushort_t etype;
2308 	int	returnstat;
2309 	au_event_ent_t *p_event = NULL;
2310 	uval_t	uval;
2311 
2312 	if (status >= 0) {
2313 		if ((returnstat = pr_adr_u_short(context, &etype, 1)) == 0) {
2314 			if (!(context->format & PRF_RAWM)) {
2315 				uval.uvaltype = PRA_STRING;
2316 				if (context->format & PRF_NOCACHE) {
2317 					p_event = getauevnum(etype);
2318 				} else {
2319 					(void) cacheauevent(&p_event, etype);
2320 				}
2321 				if (p_event != NULL) {
2322 					if (context->format & PRF_SHORTM)
2323 						uval.string_val =
2324 						    p_event->ae_name;
2325 					else
2326 						uval.string_val =
2327 						    p_event->ae_desc;
2328 				} else {
2329 					uval.string_val =
2330 					    gettext("invalid event number");
2331 				}
2332 				returnstat = pa_print(context, &uval, flag);
2333 			} else {
2334 				uval.uvaltype = PRA_USHORT;
2335 				uval.ushort_val = etype;
2336 				returnstat = pa_print(context, &uval, flag);
2337 			}
2338 		}
2339 		return (returnstat);
2340 	} else
2341 		return (status);
2342 
2343 }
2344 
2345 
2346 /*
2347  * Print time from struct timeval to millisecond resolution.
2348  *
2349  *	typedef long	time_t;		time of day in seconds
2350  *	typedef	long	useconds_t;	signed # of microseconds
2351  *
2352  * struct timeval {
2353  *	time_t		tv_sec;		seconds
2354  *	suseconds_t	tv_usec;	and microseconds
2355  * };
2356  */
2357 
2358 int
2359 pa_utime32(pr_context_t *context, int status, int flag)
2360 {
2361 	uint32_t scale = 1000;		/* usec to msec */
2362 
2363 	return (do_mtime32(context, status, flag, scale));
2364 }
2365 
2366 /*
2367  * Print time from timestruc_t to millisecond resolution.
2368  *
2369  *	typedef struct timespec timestruct_t;
2370  * struct timespec{
2371  *	time_t	tv_sec;		seconds
2372  *	long	tv_nsec;	and nanoseconds
2373  * };
2374  */
2375 int
2376 pa_ntime32(pr_context_t *context, int status, int flag)
2377 {
2378 	uint32_t scale = 1000000;	/* nsec to msec */
2379 
2380 	return (do_mtime32(context, status, flag, scale));
2381 }
2382 
2383 /*
2384  * Format the timezone +/- HH:MM and terminate the string
2385  * Note tm and tv_sec are the same time.
2386  * Too bad strftime won't produce an ISO 8601 time zone numeric
2387  */
2388 
2389 #define	MINS	(24L * 60)
2390 static void
2391 tzone(struct tm *tm, time_t *tv_sec, char *p)
2392 {
2393 	struct tm *gmt;
2394 	int min_off;
2395 
2396 	gmt = gmtime(tv_sec);
2397 
2398 	min_off = ((tm->tm_hour - gmt->tm_hour) * 60) +
2399 	    (tm->tm_min - gmt->tm_min);
2400 
2401 	if (tm->tm_year < gmt->tm_year)		/* cross new year */
2402 		min_off -= MINS;
2403 	else if (tm->tm_year > gmt->tm_year)
2404 		min_off += MINS;
2405 	else if (tm->tm_yday < gmt->tm_yday)	/* cross dateline */
2406 		min_off -= MINS;
2407 	else if (tm->tm_yday > gmt->tm_yday)
2408 		min_off += MINS;
2409 
2410 	if (min_off < 0) {
2411 		min_off = -min_off;
2412 		*p++ = '-';
2413 	} else {
2414 		*p++ = '+';
2415 	}
2416 
2417 	*p++ = min_off / 600 + '0';		/* 10s of hours */
2418 	min_off = min_off - min_off / 600 * 600;
2419 	*p++ = min_off / 60 % 10 + '0';		/* hours */
2420 	min_off = min_off - min_off / 60 * 60;
2421 	*p++ = ':';
2422 	*p++ = min_off / 10 + '0';		/* 10s of minutes */
2423 	*p++ = min_off % 10 + '0';		/* minutes */
2424 	*p = '\0';
2425 }
2426 
2427 /*
2428  * Format the milliseconds in place in the string.
2429  * Borrowed from strftime.c:itoa()
2430  */
2431 static void
2432 msec32(uint32_t msec, char *p)
2433 {
2434 	*p++ = msec / 100 + '0';
2435 	msec  = msec - msec / 100 * 100;
2436 	*p++ = msec / 10 + '0';
2437 	*p++ = msec % 10 +'0';
2438 }
2439 
2440 /*
2441  * Format time and print relative to scale factor from micro/nano seconds.
2442  */
2443 static int
2444 do_mtime32(pr_context_t *context, int status, int flag, uint32_t scale)
2445 {
2446 	uint32_t t32;
2447 	time_t tv_sec;
2448 	struct tm tm;
2449 	char	time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2450 	int	returnstat;
2451 	uval_t	uval;
2452 
2453 	if (status < 0)
2454 		return (status);
2455 
2456 	if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2457 		return (returnstat);
2458 
2459 	if ((returnstat = pr_adr_u_int32(context,
2460 	    (uint32_t *)&tv_sec, 1)) != 0)
2461 		return (returnstat);
2462 	if ((returnstat = pr_adr_u_int32(context, &t32, 1)) == 0) {
2463 		if (!(context->format & PRF_RAWM)) {
2464 			(void) localtime_r(&tv_sec, &tm);
2465 			(void) strftime(time_created,
2466 			    sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2467 			    "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2468 			msec32(t32/scale,
2469 			    &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2470 			tzone(&tm, &tv_sec,
2471 			    &time_created[
2472 			    sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2473 			uval.uvaltype = PRA_STRING;
2474 			uval.string_val = time_created;
2475 		} else {
2476 			uval.uvaltype = PRA_UINT32;
2477 			uval.uint32_val = (uint32_t)tv_sec;
2478 			(void) pa_print(context, &uval, 0);
2479 			uval.uvaltype = PRA_UINT32;
2480 			uval.uint32_val = t32;
2481 		}
2482 		returnstat = pa_print(context, &uval, flag);
2483 	}
2484 
2485 	if (returnstat == 0)
2486 		return (close_tag(context, TAG_ISO));
2487 	else
2488 		return (returnstat);
2489 }
2490 
2491 /*
2492  * Print time from struct timeval to millisecond resolution.
2493  *
2494  *	typedef long	time_t;		time of day in seconds
2495  *	typedef	long	useconds_t;	signed # of microseconds
2496  *
2497  * struct timeval {
2498  *	time_t		tv_sec;		seconds
2499  *	suseconds_t	tv_usec;	and microseconds
2500  * };
2501  */
2502 
2503 int
2504 pa_utime64(pr_context_t *context, int status, int flag)
2505 {
2506 	uint64_t scale = 1000;		/* usec to msec */
2507 
2508 	return (do_mtime64(context, status, flag, scale));
2509 }
2510 
2511 /*
2512  * Print time from timestruc_t to millisecond resolution.
2513  *
2514  *	typedef struct timespec timestruct_t;
2515  * struct timespec{
2516  *	time_t	tv_sec;		seconds
2517  *	long	tv_nsec;	and nanoseconds
2518  * };
2519  */
2520 int
2521 pa_ntime64(pr_context_t *context, int status, int flag)
2522 {
2523 	uint64_t scale = 1000000;	/* nsec to msec */
2524 
2525 	return (do_mtime64(context, status, flag, scale));
2526 }
2527 
2528 /*
2529  * Format the milliseconds in place in the string.
2530  * Borrowed from strftime.c:itoa()
2531  */
2532 static void
2533 msec64(uint64_t msec, char *p)
2534 {
2535 	*p++ = msec / 100 + '0';
2536 	msec = msec - msec / 100 * 100;
2537 	*p++ = msec / 10 + '0';
2538 	*p++ = msec % 10 +'0';
2539 }
2540 
2541 /*
2542  * Format time and print relative to scale factor from micro/nano seconds.
2543  */
2544 static int
2545 do_mtime64(pr_context_t *context, int status, int flag, uint64_t scale)
2546 {
2547 	uint64_t t64_sec;
2548 	uint64_t t64_msec;
2549 	time_t tv_sec;
2550 	struct tm tm;
2551 	char	time_created[sizeof ("YYYY-MM-DD HH:MM:SS.sss -HH:MM")];
2552 	int	returnstat;
2553 	uval_t	uval;
2554 
2555 	if (status < 0)
2556 		return (status);
2557 
2558 	if ((returnstat = open_tag(context, TAG_ISO)) != 0)
2559 		return (returnstat);
2560 
2561 	if ((returnstat = pr_adr_u_int64(context, &t64_sec, 1)) != 0)
2562 		return (returnstat);
2563 	if ((returnstat = pr_adr_u_int64(context, &t64_msec, 1)) == 0) {
2564 		if (!(context->format & PRF_RAWM)) {
2565 #ifndef	_LP64
2566 			/*
2567 			 * N.B.
2568 			 * This fails for years from 2038
2569 			 * The Y2K+38 problem
2570 			 */
2571 #endif	/* !_LP64 */
2572 			tv_sec = (time_t)t64_sec;
2573 			(void) localtime_r(&tv_sec, &tm);
2574 			(void) strftime(time_created,
2575 			    sizeof ("YYYY-MM-DD HH:MM:SS.xxx "),
2576 			    "%Y-%m-%d %H:%M:%S.xxx ", &tm);
2577 			msec64(t64_msec/scale,
2578 			    &time_created[sizeof ("YYYY-MM-DD HH:MM:SS.")-1]);
2579 			tzone(&tm, &tv_sec,
2580 			    &time_created[
2581 			    sizeof ("YYYY-MM-DD HH:MM:SS.xxx ")-1]);
2582 			uval.uvaltype = PRA_STRING;
2583 			uval.string_val = time_created;
2584 		} else {
2585 			uval.uvaltype = PRA_UINT64;
2586 			uval.uint64_val = t64_sec;
2587 			(void) pa_print(context, &uval, 0);
2588 			uval.uvaltype = PRA_UINT64;
2589 			uval.uint64_val = t64_msec;
2590 		}
2591 		returnstat = pa_print(context, &uval, flag);
2592 	}
2593 
2594 	if (returnstat < 0)
2595 		return (returnstat);
2596 
2597 	return (close_tag(context, TAG_ISO));
2598 }
2599 
2600 /*
2601  * -----------------------------------------------------------------------
2602  * pa_error()   :  convert the return token error code.
2603  *
2604  * output	: buf string representing return token error code.
2605  *
2606  * -----------------------------------------------------------------------
2607  */
2608 void
2609 pa_error(const uchar_t err, char *buf, size_t buflen)
2610 {
2611 	if (err == 0) {
2612 		(void) strlcpy(buf, gettext("success"), buflen);
2613 	} else if ((char)err == -1) {
2614 		(void) strlcpy(buf, gettext("failure"), buflen);
2615 	} else {
2616 		char *emsg = strerror(err);
2617 
2618 		if (emsg != NULL) {
2619 			(void) strlcpy(buf, gettext("failure: "), buflen);
2620 			(void) strlcat(buf, emsg, buflen);
2621 		} else {
2622 			(void) snprintf(buf, buflen, "%s%d",
2623 			    gettext("failure: "), err);
2624 		}
2625 	}
2626 }
2627 
2628 /*
2629  * -----------------------------------------------------------------------
2630  * pa_retval()   :  convert the return token return value code.
2631  *
2632  * output	: buf string representing return token error code.
2633  *
2634  * -----------------------------------------------------------------------
2635  */
2636 void
2637 pa_retval(const int32_t retval, char *buf, size_t buflen)
2638 {
2639 	struct msg_text	*msglist = &adt_msg_text[ADT_LIST_FAIL_VALUE];
2640 
2641 	if ((retval + msglist->ml_offset >= msglist->ml_min_index) &&
2642 	    (retval + msglist->ml_offset <= msglist->ml_max_index)) {
2643 
2644 		(void) strlcpy(buf,
2645 		    gettext(msglist->ml_msg_list[retval + msglist->ml_offset]),
2646 		    buflen);
2647 	} else if ((retval >= ADT_FAIL_PAM) &&
2648 	    (retval < ADT_FAIL_PAM + PAM_TOTAL_ERRNUM))
2649 		(void) strlcpy(buf, pam_strerror(NULL, retval - ADT_FAIL_PAM),
2650 		    buflen);
2651 	else
2652 		(void) snprintf(buf, buflen, "%d", retval);
2653 }
2654 
2655 
2656 /*
2657  * -----------------------------------------------------------------------
2658  * pa_printstr()	:  print a given string, translating unprintables
2659  *			:  as needed.
2660  */
2661 static int
2662 pa_printstr(pr_context_t *context, char *str)
2663 {
2664 	int	err = 0;
2665 	int	len, printable;
2666 	int	mbmax = MB_CUR_MAX;
2667 	wchar_t	wc;
2668 	char	c;
2669 
2670 	if (mbmax == 1) {
2671 		/* fast path */
2672 		while (err == 0 && *str != '\0') {
2673 			c = *str++;
2674 			printable = isprint((unsigned char)c);
2675 			err = pa_putstr(context, printable, &c, 1);
2676 		}
2677 		return (err);
2678 	}
2679 	while (err == 0 && *str != '\0') {
2680 		len = mbtowc(&wc, str, mbmax);
2681 		if (len <= 0) {
2682 			len = 1;
2683 			printable = 0;
2684 		} else {
2685 			printable = iswprint(wc);
2686 		}
2687 		err = pa_putstr(context, printable, str, len);
2688 		str += len;
2689 	}
2690 	return (err);
2691 }
2692 
2693 /*
2694  * -----------------------------------------------------------------------
2695  * pa_print()	:  print as one str or formatted for easy reading.
2696  * 		: flag - indicates whether to output a new line for
2697  *		: multi-line output.
2698  * 		:		= 0; no new line
2699  *		:		= 1; new line if regular output
2700  * output	: The audit record information is displayed in the
2701  *		  type specified by uvaltype and value specified in
2702  *		  uval.  The printing of the delimiter or newline is
2703  *		  determined by PRF_ONELINE, and the flag value,
2704  *		  as follows:
2705  *			+--------+------+------+-----------------+
2706  *			|ONELINE | flag | last | Action          |
2707  *			+--------+------+------+-----------------+
2708  *			|    Y   |   Y  |   T  | print new line  |
2709  *			|    Y   |   Y  |   F  | print delimiter |
2710  *			|    Y   |   N  |   T  | print new line  |
2711  *			|    Y   |   N  |   F  | print delimiter |
2712  *			|    N   |   Y  |   T  | print new line  |
2713  *			|    N   |   Y  |   F  | print new line  |
2714  *			|    N   |   N  |   T  | print new line  |
2715  *			|    N   |   N  |   F  | print delimiter |
2716  *			+--------+------+------+-----------------+
2717  *
2718  * return codes : -1 - error
2719  *		0 - successful
2720  * -----------------------------------------------------------------------
2721  */
2722 int
2723 pa_print(pr_context_t *context, uval_t *uval, int flag)
2724 {
2725 	int	returnstat = 0;
2726 	int	last;
2727 
2728 	switch (uval->uvaltype) {
2729 	case PRA_INT32:
2730 		returnstat = pr_printf(context, "%d", uval->int32_val);
2731 		break;
2732 	case PRA_UINT32:
2733 		returnstat = pr_printf(context, "%u", uval->uint32_val);
2734 		break;
2735 	case PRA_INT64:
2736 		returnstat = pr_printf(context, "%"PRId64, uval->int64_val);
2737 		break;
2738 	case PRA_UINT64:
2739 		returnstat = pr_printf(context, "%"PRIu64, uval->uint64_val);
2740 		break;
2741 	case PRA_SHORT:
2742 		returnstat = pr_printf(context, "%hd", uval->short_val);
2743 		break;
2744 	case PRA_USHORT:
2745 		returnstat = pr_printf(context, "%hu", uval->ushort_val);
2746 		break;
2747 	case PRA_CHAR:
2748 		returnstat = pr_printf(context, "%c", uval->char_val);
2749 		break;
2750 	case PRA_BYTE:
2751 		returnstat = pr_printf(context, "%d", uval->char_val);
2752 		break;
2753 	case PRA_STRING:
2754 		returnstat = pa_printstr(context, uval->string_val);
2755 		break;
2756 	case PRA_HEX32:
2757 		returnstat = pr_printf(context, "0x%x", uval->int32_val);
2758 		break;
2759 	case PRA_HEX64:
2760 		returnstat = pr_printf(context, "0x%"PRIx64, uval->int64_val);
2761 		break;
2762 	case PRA_SHEX:
2763 		returnstat = pr_printf(context, "0x%hx", uval->short_val);
2764 		break;
2765 	case PRA_OCT:
2766 		returnstat = pr_printf(context, "%ho", uval->ushort_val);
2767 		break;
2768 	case PRA_LOCT:
2769 		returnstat = pr_printf(context, "%o", (int)uval->uint32_val);
2770 		break;
2771 	default:
2772 		(void) fprintf(stderr, gettext("praudit: Unknown type.\n"));
2773 		returnstat = -1;
2774 		break;
2775 	}
2776 	if (returnstat < 0)
2777 		return (returnstat);
2778 
2779 	last = (context->audit_adr->adr_now ==
2780 	    (context->audit_rec_start + context->audit_rec_len));
2781 
2782 	if (!(context->format & PRF_XMLM)) {
2783 		if (!(context->format & PRF_ONELINE)) {
2784 			if ((flag == 1) || last)
2785 				returnstat = pr_putchar(context, '\n');
2786 			else
2787 				returnstat = pr_printf(context, "%s",
2788 				    context->SEPARATOR);
2789 		} else {
2790 			if (!last)
2791 				returnstat = pr_printf(context, "%s",
2792 				    context->SEPARATOR);
2793 			else
2794 				returnstat = pr_putchar(context, '\n');
2795 		}
2796 	}
2797 	if ((returnstat == 0) && (context->data_mode == FILEMODE))
2798 		(void) fflush(stdout);
2799 
2800 	return (returnstat);
2801 }
2802 
2803 /*
2804  * Convert binary data to ASCII for printing.
2805  */
2806 void
2807 convertascii(char *p, char *c, int size)
2808 {
2809 	register int	i;
2810 
2811 	for (i = 0; i < size; i++) {
2812 		*(c + i) = (char)toascii(*(c + i));
2813 		if ((int)iscntrl(*(c + i))) {
2814 			*p++ = '^';
2815 			*p++ = (char)(*(c + i) + 0x40);
2816 		} else
2817 			*p++ = *(c + i);
2818 	}
2819 
2820 	*p = '\0';
2821 
2822 }
2823 
2824 
2825 /*
2826  * -----------------------------------------------------------------------
2827  * pa_xgeneric: Process Xobject token and display contents
2828  *		      This routine will handle many of the attribute
2829  *		      types introduced in TS 2.x, such as:
2830  *
2831  *		      AUT_XCOLORMAP, AUT_XCURSOR, AUT_XFONT,
2832  *		      AUT_XGC, AUT_XPIXMAP, AUT_XWINDOW
2833  *
2834  * NOTE: At the time of call, the token id has been retrieved
2835  *
2836  * return codes		: -1 - error
2837  *			:  0 - successful
2838  * NOTE: At the time of call, the xatom token id has been retrieved
2839  *
2840  * Format of xobj
2841  *	text token id		adr_char
2842  * 	XID 			adr_u_int32
2843  * 	creator uid		adr_pw_uid
2844  * -----------------------------------------------------------------------
2845  */
2846 int
2847 pa_xgeneric(pr_context_t *context)
2848 {
2849 	int	returnstat;
2850 
2851 	returnstat = process_tag(context, TAG_XID, 0, 0);
2852 	return (process_tag(context, TAG_XCUID, returnstat, 1));
2853 }
2854 
2855 
2856 /*
2857  * ------------------------------------------------------------------------
2858  * pa_liaison : Issues pr_adr_char to retrieve the next ADR item from the
2859  *			input stream pointed to by audit_adr, and prints it
2860  *			if status >= 0 either in ASCII or raw form
2861  * return codes : -1 - error
2862  *		: 0 - successful
2863  *		: 1 - warning, unknown label type
2864  * -----------------------------------------------------------------------
2865  */
2866 int
2867 pa_liaison(pr_context_t *context, int status, int flag)
2868 {
2869 	int	returnstat;
2870 	int32_t	li;
2871 	uval_t	uval;
2872 
2873 	if (status >= 0) {
2874 		if ((returnstat = pr_adr_int32(context, &li, 1)) != 0) {
2875 			return (returnstat);
2876 		}
2877 		if (!(context->format & PRF_RAWM)) {
2878 			uval.uvaltype = PRA_UINT32;
2879 			uval.uint32_val = li;
2880 			returnstat = pa_print(context, &uval, flag);
2881 		}
2882 		/* print in hexadecimal form */
2883 		if ((context->format & PRF_RAWM) || (returnstat == 1)) {
2884 			uval.uvaltype = PRA_HEX32;
2885 			uval.uint32_val = li;
2886 			returnstat = pa_print(context, &uval, flag);
2887 		}
2888 		return (returnstat);
2889 	} else
2890 		return (status);
2891 }
2892 
2893 /*
2894  * ------------------------------------------------------------------------
2895  * pa_xid : Issues pr_adr_int32 to retrieve the XID from the input
2896  *	      stream pointed to by audit_adr, and prints it if
2897  *	      status >= 0 either in ASCII or raw form
2898  * return codes : -1 - error
2899  *		:  0 - successful
2900  *		:  1 - warning, unknown label type
2901  * ------------------------------------------------------------------------
2902  */
2903 
2904 int
2905 pa_xid(pr_context_t *context, int status, int flag)
2906 {
2907 	int returnstat;
2908 	int32_t xid;
2909 	uval_t	uval;
2910 
2911 	if (status < 0)
2912 		return (status);
2913 
2914 	/* get XID from stream */
2915 	if ((returnstat = pr_adr_int32(context, (int32_t *)&xid, 1)) != 0)
2916 		return (returnstat);
2917 
2918 	if (!(context->format & PRF_RAWM)) {
2919 		uval.uvaltype = PRA_STRING;
2920 		uval.string_val = hexconvert((char *)&xid, sizeof (xid),
2921 		    sizeof (xid));
2922 		if (uval.string_val) {
2923 			returnstat = pa_print(context, &uval, flag);
2924 			free(uval.string_val);
2925 		}
2926 	} else {
2927 		uval.uvaltype = PRA_INT32;
2928 		uval.int32_val = xid;
2929 		returnstat = pa_print(context, &uval, flag);
2930 	}
2931 
2932 	return (returnstat);
2933 }
2934