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