#ifndef lint
static char sccsid[] = "@(#)token.c 1.12 97/11/13 SMI";
#endif
 
/*
 * Copyright (c) 1988 by Sun Microsystems, Inc.
 */

#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <bsm/audit.h>
#include <bsm/audit_record.h>
#include <bsm/libbsm.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mkdev.h>
#include <pwd.h>
#include <grp.h>
#include <netdb.h>

#include "praudit.h"

extern char *sys_errlist[];
extern int  sys_nerr;

static int au_fetch_char();
static int au_fetch_short();
static int au_fetch_int32();
static int au_fetch_int64();
static int au_fetch_bytes();
static char *get_Hname();
static void convertascii();
static int convert_char_to_string();
static int convert_int32_to_string();
static int convert_int64_to_string();
static int convertbinary();
static char *hexconvert();
static char *pa_gettokenstring();

/* au_read_rec:
 *	If the file pointer or the record buffer passed in are NULL,
 *	free up the static space and return an error code < 0.
 *	Otherwise, attempt to read an audit record from the file pointer.
 *
 *	If successful:
 *		Set recbuf to the pointer to the space holding the record.
 *		Advance in the stream (fp).
 *		Return 0.
 *
 *	If failed:
 *		Don't alter recbuf.
 *		Don't advance the stream.
 *		Return error code < 0.
 */

#ifdef __STDC__
int au_read_rec(FILE *fp, char **recbuf)
#else
int au_read_rec(fp, recbuf)
	FILE *fp;
	char **recbuf;
#endif
{
	static char *p_space = NULL; /* pointer to a record buffer */
	static int cur_size = 0; /* size of p_space in bytes */
	
	adr_t adr;		/* pointer to an audit trail */
	char tokenid;		/* token (attribute) identifier */
	uint32_t record_size;	/* length of a header attribute record */
	u_short name_len;	/* length of a file attribute record */
	long start_pos;		/* initial position in fp */
	int new_size;		/* size of the new static space in bytes */

	if (fp == NULL || recbuf == NULL) {
		cur_size = 0;
		free(p_space);
		return -1;
	}

	/* Use the adr routines for reading the audit trail.
	 * They have a bit of overhead, but the already do
	 * the byte stream conversions that we will need.
	 */
	adrf_start(&adr, fp);

	/* Save the current position in the file.
	 * We`ll need to back up to here before
	 * reading in the entire record.
	 */
	start_pos = ftell(fp);

	/* Determine the amount of space needed for the record... */

	/* Skip passed the token id */
	if (adrf_char(&adr, &tokenid, 1) != 0) {
		return -2;
	}

	/* Read in the size of the record */
	if (tokenid == AUT_HEADER32 || tokenid == AUT_HEADER64) {
		if (adrf_u_int32(&adr, &record_size, 1) != 0) {
			fseek(fp, start_pos, SEEK_SET);
			return -4;
		}
	} else if (tokenid == AUT_OTHER_FILE32) {
		int32_t date_time[2];

		if (adrf_int32(&adr, date_time, 8) != 0) {
			fseek(fp, start_pos, SEEK_SET);
			return -5;
		}
		if (adrf_u_short(&adr, &name_len, 1) != 0) {
			fseek(fp, start_pos, SEEK_SET);
			return -6;
		}
		/* 11 is the size of an attr id, */
		/* date&time32, and name length */
		record_size = (u_int)name_len + 11;
	} else if (tokenid == AUT_OTHER_FILE64) {
		int64_t date_time[2];

		if (adrf_int64(&adr, date_time, 2) != 0) {
			fseek(fp, start_pos, SEEK_SET);
			return -5;
		}
		if (adrf_u_short(&adr, &name_len, 1) != 0) {
			fseek(fp, start_pos, SEEK_SET);
			return -6;
		}
		/* 19 is the size of an date&time64 */
		record_size = (u_int)name_len + 19;
	} else {
		fseek(fp, start_pos, SEEK_SET);
		return -7;
	}

	/* Go back to the starting point so we can read in the entire record */
	fseek(fp, start_pos, SEEK_SET);

	/* If the current size of the static p_space cannot hold
	 * the entire record, make it larger.
	 */
	new_size = cur_size;
	while (new_size < record_size) {
		new_size += 512;
		/* If we need more than a megabyte to hold a single record
		 * something is amiss.
		 */
		if (new_size > 1000000) {
			return -8;
		}
	}
	if (new_size != cur_size) {
		cur_size = 0;
		free(p_space);
		if ((p_space = (char *)malloc(new_size)) == NULL) {
			return -9;
		}
		cur_size = new_size;
	}

	/* Do what we came here for; read an audit record */
	if (fread(p_space, record_size, 1, fp) != 1) {
		fseek(fp, start_pos, SEEK_SET);
		return -10;
	}

	/* Pad the buffer with zeroes */
	memset(p_space + record_size, '\0', cur_size - record_size);

	*recbuf = (char *)p_space;
	return 0;
}

/* au_fetch_tok():
 *
 * Au_fetch_tok() behaves like strtok(3).  On the first call, a buffer
 * is passed in.  On subsequent calls, NULL is passed in as buffer.
 * Au_fetch_tok() manages the buffer pointer offset and returns tokens
 * until the end of the buffer is reached.  The user of the routine must
 * guarantee that the buffer starts with and contains at least one full
 * audit record.  This type of assurance is provided by au_read_rec().
 */

#ifdef __STDC__
int au_fetch_tok(au_token_t *tok, char *buf, int flags)
#else
int au_fetch_tok(tok, buf, flags)
	au_token_t *tok;
	char *buf;
	int flags;
#endif
{
	static char *invalid_txt = "invalid token id";
	static int len_invalid_txt = 17;
	static char *old_buf = NULL; /* position in buf at end of last fetch */
	char *orig_buf; /* position in buf when fetch entered */
	char *cur_buf; /* current location in buf */
	int length;
	int i;
	int valid_id;

	/* Check flags, one should be on.  */
	i = 0;
	if (flags & AUF_POINT) {
		i++;
	}
	if (flags & AUF_DUP) {
		i++;
	}
	if (flags & AUF_COPY_IN) {
		i++;
	}
	if (i != 1) {
		return -1;
	}
	/* Skip not implemented, yet */
	if (flags & AUF_SKIP) {
		return -2;
	}

	if (buf == NULL) {
		orig_buf = old_buf;
		cur_buf = old_buf;
	} else {
		orig_buf = buf;
		cur_buf = buf;
	}

	tok->data = cur_buf;
	au_fetch_char(&tok->id, &cur_buf, flags);
	tok->next = NULL;
	tok->prev = NULL;

	valid_id = 1;

	switch(tok->id) {
		case AUT_OTHER_FILE32:
			(void)au_fetch_int32(&tok->un.file32.time,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.file32.msec,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.file32.length,
						&cur_buf, flags);
			(void)au_fetch_bytes(&tok->un.file32.fname,
				&cur_buf,tok->un.file32.length, flags);
			tok->size = 11 + tok->un.file32.length;
		break;
		case AUT_OTHER_FILE64:
			(void)au_fetch_int64(&tok->un.file64.time,
						&cur_buf, flags);
			(void)au_fetch_int64(&tok->un.file64.msec,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.file64.length,
						&cur_buf, flags);
			(void)au_fetch_bytes(&tok->un.file64.fname,
				&cur_buf,tok->un.file64.length, flags);
			tok->size = 19 + tok->un.file64.length;
		break;
		case AUT_HEADER32:
			(void)au_fetch_int32(&tok->un.header32.length,
						&cur_buf, flags);
			(void)au_fetch_char(&tok->un.header32.version,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.header32.event,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.header32.emod,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.header32.time,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.header32.msec,
						&cur_buf, flags);
			tok->size = 18;
		break;
		case AUT_HEADER64:
			(void)au_fetch_int32(&tok->un.header64.length,
						&cur_buf, flags);
			(void)au_fetch_char(&tok->un.header64.version,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.header64.event,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.header64.emod,
						&cur_buf, flags);
			(void)au_fetch_int64(&tok->un.header64.time,
						&cur_buf, flags);
			(void)au_fetch_int64(&tok->un.header64.msec,
						&cur_buf, flags);
			tok->size = 26;
		break;
		case AUT_TRAILER:
			(void)au_fetch_short(&tok->un.trailer.magic,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.trailer.length, flags);
			tok->size = 7;
		break;
		case AUT_DATA:
			(void)au_fetch_char(&tok->un.data.pfmt, &cur_buf,
						flags);
			(void)au_fetch_char(&tok->un.data.size, &cur_buf,
						flags);
			(void)au_fetch_char(&tok->un.data.number, &cur_buf,
						flags);
			length = (int)tok->un.data.size * 
					(int)tok->un.data.number;
			(void)au_fetch_bytes(&tok->un.data.data, &cur_buf,
						length, flags);
			tok->size = 4 + length;
		break;
		case AUT_IPC:
			(void)au_fetch_int32(&tok->un.ipc.id,&cur_buf,flags);
			tok->size = 5;
		break;
		case AUT_PATH:
			(void)au_fetch_short(&tok->un.path.length, &cur_buf,
						flags);
			(void)au_fetch_bytes(&tok->un.path.name, &cur_buf,
						tok->un.path.length, flags);
			tok->size = 3 + tok->un.path.length;
		break;
		case AUT_SUBJECT32:
			(void)au_fetch_int32(&tok->un.subj32.auid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.euid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.egid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.ruid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.rgid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.pid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.sid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.tid.port, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj32.tid.machine,
						&cur_buf, flags);
			tok->size = 37;
		break;
		case AUT_SUBJECT64:
			(void)au_fetch_int32(&tok->un.subj64.auid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.euid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.egid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.ruid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.rgid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.pid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.sid, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.subj64.tid.port, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.subj64.tid.machine,
						&cur_buf, flags);
			tok->size = 41;
		break;
		case AUT_SERVER:
			(void)au_fetch_int32(&tok->un.server.auid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.server.euid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.server.ruid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.server.egid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.server.pid, &cur_buf,
						flags);
			tok->size = 21;
		break;
		case AUT_PROCESS32:
			(void)au_fetch_int32(&tok->un.proc32.auid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc32.euid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc32.ruid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc32.rgid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc32.pid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc32.sid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc32.tid.port,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.proc32.tid.machine,
						&cur_buf, flags);
			tok->size = 33;
		case AUT_PROCESS64:
			(void)au_fetch_int32(&tok->un.proc64.auid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc64.euid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc64.ruid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc64.rgid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc64.pid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.proc64.sid, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.proc64.tid.port,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.proc64.tid.machine,
						&cur_buf, flags);
			tok->size = 37;
		break;
		case AUT_RETURN32:
			(void)au_fetch_char(&tok->un.ret32.error, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.ret32.retval, &cur_buf,
						flags);
			tok->size = 6;
		break;
		case AUT_RETURN64:
			(void)au_fetch_char(&tok->un.ret64.error, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.ret64.retval, &cur_buf,
						flags);
			tok->size = 10;
		break;
		case AUT_TEXT:
			(void)au_fetch_short(&tok->un.text.length, &cur_buf,
						flags);
			(void)au_fetch_bytes(&tok->un.text.data, &cur_buf,
						tok->un.text.length, flags);
			tok->size = 3 + tok->un.text.length;
		break;
		case AUT_OPAQUE:
			(void)au_fetch_short(&tok->un.opaque.length, &cur_buf,
						flags);
			(void)au_fetch_bytes(&tok->un.opaque.data, &cur_buf,
						tok->un.opaque.length, flags);
			tok->size = 3 + tok->un.opaque.length;
		break;
		case AUT_IN_ADDR:
			(void)au_fetch_int32(&tok->un.inaddr.ia.s_addr,
						&cur_buf, flags);
			tok->size = 5;
		break;
		case AUT_IP:
			(void)au_fetch_char(&tok->un.ip.version, &cur_buf,
						flags);
			(void)au_fetch_char(&tok->un.ip.ip.ip_tos, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.ip.ip.ip_len, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.ip.ip.ip_id, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.ip.ip.ip_off, &cur_buf,
						flags);
			(void)au_fetch_char(&tok->un.ip.ip.ip_ttl, &cur_buf,
						flags);
			(void)au_fetch_char(&tok->un.ip.ip.ip_p, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.ip.ip.ip_sum, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.ip.ip.ip_src.s_addr,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ip.ip.ip_dst.s_addr,
						&cur_buf, flags);
			tok->size = 21;
		break;
		case AUT_IPORT:
			(void)au_fetch_short(&tok->un.iport.iport, &cur_buf,
						flags);
			tok->size = 3;
		break;
		case AUT_ARG32:
			(void)au_fetch_char(&tok->un.arg32.num, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.arg32.val, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.arg32.length, &cur_buf,
						flags);
			(void)au_fetch_bytes(&tok->un.arg32.data, &cur_buf,
						tok->un.arg32.length, flags);
			tok->size = 8 + tok->un.arg32.length;
		case AUT_ARG64:
			(void)au_fetch_char(&tok->un.arg64.num, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.arg64.val, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.arg64.length, &cur_buf,
						flags);
			(void)au_fetch_bytes(&tok->un.arg64.data, &cur_buf,
						tok->un.arg64.length, flags);
			tok->size = 12 + tok->un.arg64.length;
		break;
		case AUT_SOCKET:
			(void)au_fetch_short(&tok->un.socket.type, &cur_buf,
						flags);
			(void)au_fetch_short(&tok->un.socket.lport, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.socket.laddr.s_addr,
						&cur_buf, flags);
			(void)au_fetch_short(&tok->un.socket.fport, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.socket.faddr.s_addr,
						&cur_buf, flags);
			tok->size = 15;
		break;
		case AUT_SEQ:
			(void)au_fetch_int32(&tok->un.seq.num, &cur_buf,
						flags);
			tok->size = 5;
		break;
		case AUT_ACL:
			(void)au_fetch_int32(&tok->un.acl.type,&cur_buf,flags);
			(void)au_fetch_int32(&tok->un.acl.id,&cur_buf,flags);
			(void)au_fetch_int32(&tok->un.acl.mode,&cur_buf,flags);
			tok->size = 13;
		break;
		case AUT_ATTR32:
			(void)au_fetch_int32(&tok->un.attr32.mode, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr32.uid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr32.gid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr32.fs, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.attr32.node, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr32.dev, &cur_buf,
						flags);
			tok->size = 29;
		case AUT_ATTR64:
			(void)au_fetch_int32(&tok->un.attr64.mode, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr64.uid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr64.gid, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.attr64.fs, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.attr64.node, &cur_buf,
						flags);
			(void)au_fetch_int64(&tok->un.attr64.dev, &cur_buf,
						flags);
			tok->size = 33;
		break;
		case AUT_IPC_PERM:
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.uid,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.gid,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.cuid,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.cgid,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.mode,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.seq,
						&cur_buf, flags);
			(void)au_fetch_int32(&tok->un.ipc_perm.ipc_perm.key,
						&cur_buf, flags);
			tok->size = 29;
		break;
		case AUT_GROUPS:
			for (i=0; i<NGROUPS_MAX; i++) {
				(void)au_fetch_int32(&tok->un.groups.groups[i],
						&cur_buf, flags);
			}
			tok->size = 1 + (NGROUPS_MAX * sizeof(gid_t));
		break;
		case AUT_EXIT:
			(void)au_fetch_int32(&tok->un.exit.status, &cur_buf,
						flags);
			(void)au_fetch_int32(&tok->un.exit.retval, &cur_buf,
						flags);
			tok->size = 9;
		break;
		case AUT_INVALID:
		default:
			au_fetch_bytes(&tok->un.invalid.data, &invalid_txt,
						len_invalid_txt, flags);
			tok->un.invalid.length = len_invalid_txt;
			tok->size = len_invalid_txt;
			valid_id = 0;
	}
	if (valid_id == 0) {
		old_buf = orig_buf;
		return -3;
	}
	old_buf = cur_buf;
	return 0;
}

static int au_fetch_char(result, buf, flags)
	char *result;
	char **buf;
	int flags;
{
	*result = **buf;
	(*buf)++;
	return 0;
}

static int au_fetch_short(result, buf, flags)
	short *result;
	char **buf;
	int flags;
{
	*result = **buf << 8;
	(*buf)++;
	*result |= **buf & 0x0ff;
	(*buf)++;
	return 0;
}

static int au_fetch_int32(result, buf, flags)
	int32_t *result;
	char **buf;
	int flags;
{
	int i;

	for (i=0; i<sizeof(int); i++) {
		*result <<= 8;
		*result |= **buf & 0x000000ff;
		(*buf)++;
	}
	return 0;
}

static int au_fetch_int64(result, buf, flags)
	int64_t *result;
	char **buf;
	int flags;
{
	int i;

	for (i=0; i<sizeof(int64_t); i++) {
		*result <<= 8;
		*result |= **buf & 0x00000000000000ff;
		(*buf)++;
	}
	return 0;
}

static int au_fetch_bytes(result, buf, len, flags)
	char **result;
	char **buf;
	int len;
	int flags;
{
	if (flags & AUF_POINT) {
		*result = *buf;
		(*buf) += len;
		return 0;
	}
	if (flags & AUF_DUP) {
		*result = (char *)malloc(len);
		memcpy(*result, *buf, len);
		(*buf) += len;
		return 0;
	}
	if (flags & AUF_COPY_IN) {
		memcpy(*result, *buf, len);
		(*buf) += len;
		return 0;
	}
	return -1;
}

/*
 * The following defines and functions are for work with device major
 * and minor numbers independently from libc, because it doesn't support
 * such work for 32- and 64-bit format at the same time. This implementation
 * depends on sys/mkdev.h and on format of dev_t type.
 */

#define	NBITSMAJOR64	32	/* # of major device bits in 64-bit Solaris */
#define	NBITSMINOR64	32	/* # of minor device bits in 64-bit Solaris */
#define	MAXMAJ64	0xfffffffful	/* max major value */
#define	MAXMIN64	0xfffffffful	/* max minor value */

#define	NBITSMAJOR32	14	/* # of SVR4 major device bits */
#define	NBITSMINOR32	18	/* # of SVR4 minor device bits */
#define	NMAXMAJ32	0x3fff	/* SVR4 max major value */
#define	NMAXMIN32	0x3ffff	/* MAX minor for 3b2 software drivers. */


static int32_t
minor_64(uint64_t dev)
{
	if (dev == NODEV) {
		errno = EINVAL;
		return (NODEV);
	}
	return (int32_t)(dev & MAXMIN64);
}

static int32_t
major_64(uint64_t dev)
{
	uint32_t maj;

	maj = (uint32_t)(dev >> NBITSMINOR64);

	if (dev == NODEV || maj > MAXMAJ64) {
		errno = EINVAL;
		return (NODEV);
	}
	return (int32_t)(maj);
}

static int32_t
minor_32(uint32_t dev)
{
	if (dev == NODEV) {
		errno = EINVAL;
		return (NODEV);
	}
	return (int32_t)(dev & MAXMIN32);
}

static int32_t
major_32(uint32_t dev)
{
	uint32_t maj;

	maj = (uint32_t)(dev >> NBITSMINOR32);

	if (dev == NODEV || maj > MAXMAJ32) {
		errno = EINVAL;
		return (NODEV);
	}
	return (int32_t)(maj);
}


#ifdef __STDC__
au_fprint_tok(FILE *fp, au_token_t *tok, char *b, char *m, char *e, int flags)
#else
au_fprint_tok(fp, tok, b, m, e, flags)
	FILE *fp;
	au_token_t *tok;
	char *b, *m, *e;
	int flags;
#endif
{
	char *s1, *s2;
	char s3[80], s4[80];
	char p[80];
	au_event_ent_t *p_event;
	int i;
	char *p_data;
	char c1;
	short c2;
	int c3;
	struct in_addr ia;
	char *hostname;
	char *ipstring;
	struct passwd *p_pwd;
	struct group *p_grp;

	if (flags == 0) switch(tok->id) {
		case AUT_OTHER_FILE32: {
			time_t time = (time_t)tok->un.file32.time;
			s1 = ctime(&time);
			s1[24] = '\0';
			fprintf(fp, "%s%s%s%s%s + %d msec%s",
				b, "file32", m,
				s1, m,
				(int)tok->un.file32.msec, e
			);
			free(s1);
			return 0;
		}
		case AUT_OTHER_FILE64: {
			time_t time = (time_t)tok->un.file64.time;
			s1 = ctime(&time);
			s1[24] = '\0';
			fprintf(fp, "%s%s%s%s%s + %d msec%s",
				b, "file64", m,
				s1, m,
				(int)tok->un.file64.msec, e
			);
			free(s1);
			return 0;
		}
		case AUT_HEADER32: {
			time_t time = (time_t)tok->un.header32.time;
			s1 = ctime(&time);
			s1[24] = '\0';
			i=cacheauevent(&p_event, tok->un.header32.event);
			fprintf(fp, "%s%s%s%d%s%d%s%s%s%d%s%s%s + %d msec%s",
				b, "header32", m,
				tok->un.header32.length, m,
				tok->un.header32.version, m,
				p_event->ae_desc, m,
				tok->un.header32.emod, m,
				s1, m ,
				tok->un.header32.msec, e
			);
			free(s1);
			return 0;
		}
		case AUT_HEADER64: {
			time_t time = (time_t)tok->un.header64.time;
			s1 = ctime(&time);
			s1[24] = '\0';
			i=cacheauevent(&p_event, tok->un.header64.event);
			fprintf(fp, "%s%s%s%d%s%d%s%s%s%d%s%s%s + %d msec%s",
				b, "header64", m,
				tok->un.header64.length, m,
				tok->un.header64.version, m,
				p_event->ae_desc, m,
				tok->un.header64.emod, m,
				s1, m ,
				tok->un.header64.msec, e
			);
			free(s1);
			return 0;
		}
		case AUT_TRAILER:
			if (tok->un.trailer.magic != AUT_TRAILER_MAGIC) {
				return -2;
			}
			fprintf(fp,"%s%s%s%d%s",
				b,"trailer",m,
				tok->un.trailer.length,e
			);
			return 0;
		case AUT_DATA:
			switch(tok->un.data.pfmt) {
				case AUP_BINARY:
					s1 = "binary";
					break;
				case AUP_OCTAL:
					s1 = "octal";
					break;
				case AUP_DECIMAL:
					s1 = "decimal";
					break;
				case AUP_HEX:
					s1 = "hex";
					break;
				case AUP_STRING:
					s1 = "string";
					break;
				default:
					s1 = "unknown print suggestion";
					break;
			}
			switch(tok->un.data.size) {
				/* case AUR_BYTE: */
				case AUR_CHAR:
					s2 = "char";
					break;
				case AUR_SHORT:
					s2 = "short";
					break;
				case AUR_INT32:
					s2 = "int32_t";
					break;
				case AUR_INT64:
					s2 = "int64_t";
					break;
				default:
					s2 = "unknown basic unit type";
					break;
			}
			fprintf(fp, "%s%s%s%s%s%s%s", b, "data", m, s1, m, s2, m);

			p_data = tok->un.data.data;
			for (i = 1; i <= (int)tok->un.data.number; i++) {
			    switch(tok->un.data.size) {
				case AUR_CHAR:
					if (au_fetch_char(&c1, &p_data, 0) == 0) {
						convert_char_to_string(
							tok->un.data.pfmt, c1, p);
					} else {
						return -3;
					}
				break;
				case AUR_SHORT:
					if (au_fetch_short(&c2, &p_data, 0) == 0) {
						convert_short_to_string(
							tok->un.data.pfmt, c2, p);
					} else {
						return -4;
					}
				break;
				case AUR_INT32:
					if (au_fetch_int32(&c3, &p_data, 0) == 0) {
						convert_int32_to_string(
							tok->un.data.pfmt, c3, p);
					} else {
						return -5;
					}
				break;
				case AUR_INT64:
					if (au_fetch_int64(&c3, &p_data, 0) == 0) {
						convert_int64_to_string(
							tok->un.data.pfmt, c3, p);
					} else {
						return -9;
					}
				break;
				default:
					return -6;
					break;
			    }
			    fprintf(fp, "%s%s", p, i == tok->un.data.number ? m : e);
			}
			return 0;
		case AUT_IPC:
			fprintf(fp, "%s%s%s%d%s",
				b, "IPC", m,
				tok->un.ipc.id, e
			);
			return 0;
		case AUT_PATH:
			fprintf(fp, "%s%s%s%s%s",
				b, "path", m,
				tok->un.path.name, e
			);
			return 0;
		case AUT_SUBJECT32:
			hostname = get_Hname(tok->un.subj32.tid.machine);
			ia.s_addr = tok->un.subj32.tid.machine;
			if ((s1 = inet_ntoa(ia)) == NULL) {
				s1 = "bad machine id";
			}
			fprintf(fp, "%s%s%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%s%s%s%s",
				b, "subject32", m,
				tok->un.subj32.auid, m,
				tok->un.subj32.euid, m,
				tok->un.subj32.egid, m,
				tok->un.subj32.ruid, m,
				tok->un.subj32.rgid, m,
				tok->un.subj32.pid, m,
				tok->un.subj32.sid, m,
				major_32(tok->un.subj32.tid.port), m,
				minor_32(tok->un.subj32.tid.port), m,
				hostname, m,
				s1, e
			);
		case AUT_SUBJECT64:
			hostname = get_Hname(tok->un.subj64.tid.machine);
			ia.s_addr = tok->un.subj64.tid.machine;
			if ((s1 = inet_ntoa(ia)) == NULL) {
				s1 = "bad machine id";
			}
			fprintf(fp, "%s%s%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%s%s%s%s",
				b, "subject64", m,
				tok->un.subj64.auid, m,
				tok->un.subj64.euid, m,
				tok->un.subj64.egid, m,
				tok->un.subj64.ruid, m,
				tok->un.subj64.rgid, m,
				tok->un.subj64.pid, m,
				tok->un.subj64.sid, m,
				major_64(tok->un.subj64.tid.port), m,
				minor_64(tok->un.subj64.tid.port), m,
				hostname, m,
				s1, e
			);
			return 0;
		case AUT_SERVER:
			fprintf(fp, "%s%s%s%d%s%d%s%d%s%d%s%d%s",
				b, "server", m,
				tok->un.server.auid, m,
				tok->un.server.euid, m,
				tok->un.server.ruid, m,
				tok->un.server.egid, m,
				tok->un.server.pid, e
			);
			return 0;
		case AUT_PROCESS32:
			hostname = get_Hname(tok->un.proc32.tid.machine);
			ia.s_addr = tok->un.proc32.tid.machine;
			if ((s1 = inet_ntoa(ia)) == NULL) {
				s1 = "bad machine id";
			}
			fprintf(fp, "%s%s%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%s%s%s%s",
				b, "process32", m,
				tok->un.proc32.auid, m,
				tok->un.proc32.euid, m,
				tok->un.proc32.egid, m,
				tok->un.proc32.ruid, m,
				tok->un.proc32.rgid, m,
				tok->un.proc32.pid, m,
				tok->un.proc32.sid, m,
				major_32(tok->un.proc32.tid.port), m,
				minor_32(tok->un.proc32.tid.port), m,
				hostname, m,
				s1, e
			);
			return 0;
		case AUT_PROCESS64:
			hostname = get_Hname(tok->un.proc64.tid.machine);
			ia.s_addr = tok->un.proc64.tid.machine;
			if ((s1 = inet_ntoa(ia)) == NULL) {
				s1 = "bad machine id";
			}
			fprintf(fp, "%s%s%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%d%s%s%s%s%s",
				b, "process64", m,
				tok->un.proc64.auid, m,
				tok->un.proc64.euid, m,
				tok->un.proc64.egid, m,
				tok->un.proc64.ruid, m,
				tok->un.proc64.rgid, m,
				tok->un.proc64.pid, m,
				tok->un.proc64.sid, m,
				major_64(tok->un.proc64.tid.port), m,
				minor_64(tok->un.proc64.tid.port), m,
				hostname, m,
				s1, e
			);
			return 0;
		case AUT_RETURN32:
			if (tok->un.ret32.error == 0) {
				(void) strcpy(s3, "success");
			} else if (tok->un.ret32.error == -1) {
				(void) strcpy(s3, "failure");
			} else {
				if (tok->un.ret32.error < (u_char)sys_nerr) {
					sprintf(s3, "failure: %s",
						sys_errlist[tok->un.ret32.error]);
				} else {
					(void) strcpy(s3, "Unknown errno");
				}
			}
			
			fprintf(fp,"%s%s%s%s%s%d%s",
				b, "return32", m,
				s3, m,
				tok->un.ret32.retval, e
			);
			return 0;
		case AUT_RETURN64:
			if (tok->un.ret64.error == 0) {
				(void) strcpy(s3, "success");
			} else if (tok->un.ret64.error == -1) {
				(void) strcpy(s3, "failure");
			} else {
				if (tok->un.ret64.error < (u_char)sys_nerr) {
					sprintf(s3, "failure: %s",
						sys_errlist[tok->un.ret64.error]);
				} else {
					(void) strcpy(s3, "Unknown errno");
				}
			}
			
			fprintf(fp,"%s%s%s%s%s%"PRI64d"%s",
				b, "return64", m,
				s3, m,
				tok->un.ret64.retval, e
			);
			return 0;
		case AUT_TEXT:
			fprintf(fp,"%s%s%s%s%s",
				b, "text", m,
				tok->un.text.data, e
			);
			return 0;
		case AUT_OPAQUE:
			s1 = hexconvert(tok->un.opaque.data,tok->un.opaque.length,0);
			fprintf(fp,"%s%s%s%s%s",
				b, "opaque", m,
				s1, e
			);
			free(s1);
			return 0;
		case AUT_IN_ADDR:
			s1 = get_Hname(tok->un.inaddr.ia);
			fprintf(fp, "%s%s%s%s%s",
				b, "ip address", m,
				s1, e
			);
			return 0;
		case AUT_IP:
			fprintf(fp, "%s%s%s%x%s%x%s%d%s%d%s%d%s%x%s%x%s%d%s%x%s%x%s",
				b, "ip", m,
				(int)tok->un.ip.version, m,
				(int)tok->un.ip.ip.ip_tos, m,
				tok->un.ip.ip.ip_len, m,
				tok->un.ip.ip.ip_id, m,
				tok->un.ip.ip.ip_off, m,
				(int)tok->un.ip.ip.ip_ttl, m,
				(int)tok->un.ip.ip.ip_p, m,
				tok->un.ip.ip.ip_sum, m,
				tok->un.ip.ip.ip_src, m,
				tok->un.ip.ip.ip_dst, e
			);
			return 0;
		case AUT_IPORT:
			fprintf(fp, "%s%s%s%x%s",
				b, "ip port", m,
				(int)tok->un.iport.iport, e
			);
			return 0;
		case AUT_ARG32:
			fprintf(fp, "%s%s%s%d%s%x%s%s%s",
				b, "argument32", m,
				tok->un.arg32.num, m,
				tok->un.arg32.val, m,
				tok->un.arg32.data, e
			);
			return 0;
		case AUT_ARG64:
			fprintf(fp, "%s%s%s%d%s%"PRIx64"%s%s%s",
				b, "argument64", m,
				tok->un.arg64.num, m,
				tok->un.arg64.val, m,
				tok->un.arg64.data, e
			);
			return 0;
		case AUT_SOCKET:
			s1 = get_Hname(tok->un.socket.laddr);
			s2 = get_Hname(tok->un.socket.faddr);
			fprintf(fp, "%s%s%s%x%s%x%s%s%s%x%s%s%s",
				b, "socket", m,
				(int)tok->un.socket.type, m,
				(int)tok->un.socket.lport, m,
				s1, m,
				(int)tok->un.socket.fport, m,
				s2, e
			);
			free(s1);
			free(s2);
			return 0;
		case AUT_SEQ:
			fprintf(fp, "%s%s%s%d%s",
				b, "sequence", m,
				tok->un.seq.num, e
			);
			return 0;
		case AUT_ACL:
			sprintf(s3, "%d", tok->un.acl.type);
				
			if (tok->un.acl.type & (USER_OBJ|USER)) {
				setpwent();
				p_pwd = getpwuid(tok->un.acl.id);
				if (p_pwd == NULL) {
					sprintf(s4, "%d", tok->un.acl.uid);
				else
					(void)strcpy(s4, p_pwd->pw_name);
				endpwent();
			} else if (tok->un.acl.type & (GROUP_OBJ|GROUP)) {
				setgrent();
				p_grp = getgrgid(tok->un.acl.id);
				if (p_grp == NULL)
					sprintf(s4, "%d", tok->un.acl.uid);
				else
					(void)strcpy(s4, p_grp->gr_name);
				endpwent();
			} else {
				sprintf(s4, "%d", tok->un.acl.uid);
			}
			fprintf(fp, "%s%s%s%s%s%s%s%o%s",
				b, "acl", m,
				s3, m,
				s4, m,
				tok->un.acl.mode, e
			);
			return 0;
		case AUT_ATTR32:
			setpwent();
			if ((p_pwd = getpwuid(tok->un.attr32.uid)) == NULL) {
				sprintf(s3, "%d", tok->un.attr32.uid);
			} else {
				(void)strcpy(s3, p_pwd->pw_name);
			}
			endpwent();
			setgrent();
			if ((p_grp = getgrgid(tok->un.attr32.gid)) == NULL) {
				sprintf(s4, "%d", tok->un.attr32.gid);
			} else {
				(void)strcpy(s4, p_grp->gr_name);
			}
			endgrent();
			fprintf(fp, "%s%s%s%o%s%s%s%s%s%d%s%"PRI64d"%s%u%s",
				b, "attribute32", m,
				tok->un.attr32.mode, m,
				s3, m,
				s4, m,
				tok->un.attr32.fs, m,
				tok->un.attr32.node, m,
				tok->un.attr32.dev, e
			);
			return 0;
		case AUT_ATTR64:
			setpwent();
			if ((p_pwd = getpwuid(tok->un.attr64.uid)) == NULL) {
				sprintf(s3, "%d", tok->un.attr64.uid);
			} else {
				(void)strcpy(s3, p_pwd->pw_name);
			}
			endpwent();
			setgrent();
			if ((p_grp = getgrgid(tok->un.attr64.gid)) == NULL) {
				sprintf(s4, "%d", tok->un.attr64.gid);
			} else {
				(void)strcpy(s4, p_grp->gr_name);
			}
			endgrent();
			fprintf(fp, "%s%s%s%o%s%s%s%s%s%d%s%"PRI64d"%s%"PRI64d"%s",
				b, "attribute64", m,
				tok->un.attr64.mode, m,
				s3, m,
				s4, m,
				tok->un.attr64.fs, m,
				tok->un.attr64.node, m,
				tok->un.attr64.dev, e
			);
			return 0;
		case AUT_IPC_PERM:
			setpwent();
			if ((p_pwd = getpwuid(tok->un.ipc_perm.ipc_perm.uid)) == NULL) {
				sprintf(s3, "%d", tok->un.ipc_perm.ipc_perm.uid);
			} else {
				(void)strcpy(s3, p_pwd->pw_name);
			}
			endpwent();
			setgrent();
			if ((p_grp = getgrgid(tok->un.ipc_perm.ipc_perm.gid)) == NULL) {
				sprintf(s4, "%d", tok->un.ipc_perm.ipc_perm.gid);
			} else {
				(void)strcpy(s4, p_grp->gr_name);
			}
			endgrent();
			fprintf(fp, "%s%s%s%s%s%s%s%s%s%s%s%o%s%d%s%x%s",
				b, "IPC perm", m,
				s3, m,
				s4, m
			);
			setpwent();
			if ((p_pwd = getpwuid(tok->un.ipc_perm.ipc_perm.cuid)) == NULL) {
				sprintf(s3, "%d", tok->un.ipc_perm.ipc_perm.cuid);
			} else {
				(void)strcpy(s3, p_pwd->pw_name);
			}
			endpwent();
			setgrent();
			if ((p_grp = getgrgid(tok->un.ipc_perm.ipc_perm.cgid)) == NULL) {
				sprintf(s4, "%d", tok->un.ipc_perm.ipc_perm.cgid);
			} else {
				(void)strcpy(s4, p_grp->gr_name);
			}
			endgrent();
			fprintf(fp, "%s%s%s%s%o%s%d%s%x%s",
				s3, m,
				s4, m,
				tok->un.ipc_perm.ipc_perm.mode, m,
				tok->un.ipc_perm.ipc_perm.seq, m,
				tok->un.ipc_perm.ipc_perm.key, e
			);
			return 0;
		case AUT_GROUPS:
			fprintf(fp, "%s%s%s",
				b, "group", m
			);
			for (i=0; i<NGROUPS_MAX; i++) {
				setgrent();
				if ((p_grp = getgrgid(tok->un.groups.groups[i])) == NULL) {
					sprintf(s4, "%d", tok->un.groups.groups[i]);
				} else {
					(void)strcpy(s4, p_grp->gr_name);
				}
				endgrent();
				fprintf(fp, "%s%s", s3, i == NGROUPS_MAX - 1 ? m : e);
			}
		case AUT_EXIT:
			if (tok->un.exit.retval < -1 && tok->un.exit.retval < sys_nerr) {
				sprintf(s3, "%s", sys_errlist[tok->un.exit.retval]);
			} else {
				sprintf(s3, "%s", "Unknown errno");
			}
			fprintf(fp, "%s%s%s%s%s%d%s",
				b, "exit", m,
				s3, m,
				tok->un.exit.status, e
			);
			return 0;
		case AUT_INVALID:
		default:
			fprintf(fp, "%s%s%s",
				b, "invalid token", e
			);
			return(-1);
		break;
	} 
}

		
au_fprint_tok_hex(fp, tok, b, m, e, flags)
	FILE *fp;
	au_token_t *tok;
	char b, m, e;
	int flags;
{
	char *str;
	char *prefix;

	str = hexconvert(tok->data, tok->size, tok->size);

	switch (tok->id) {
		case AUT_ARG32:
			prefix = "arg32";
			break;
		case AUT_ARG64:
			prefix = "arg64";
			break;
		case AUT_ATTR32:
			prefix = "attr32";
			break;
		case AUT_ATTR64:
			prefix = "attr64";
			break;
		case AUT_DATA:
			prefix = "data";
			break;
		case AUT_EXIT:
			prefix = "exit";
			break;
		case AUT_GROUPS:
			prefix = "groups";
			break;
		case AUT_HEADER32:
			prefix = "header32";
			break;
		case AUT_HEADER64:
			prefix = "header64";
			break;
		case AUT_INVALID:
			prefix = "invalid";
			break;
		case AUT_IN_ADDR:
			prefix = "in_addr";
			break;
		case AUT_IP:
			prefix = "ip";
			break;
		case AUT_IPC:
			prefix = "ipc";
			break;
		case AUT_IPC_PERM:
			prefix = "ipc_perm";
			break;
		case AUT_IPORT:
			prefix = "iport";
			break;
		case AUT_OPAQUE:
			prefix = "opaque";
			break;
		case AUT_OTHER_FILE32:
			prefix = "file32";
			break;
		case AUT_OTHER_FILE64:
			prefix = "file364";
			break;
		case AUT_PATH:
			prefix = "path";
			break;
		case AUT_PROCESS32:
			prefix = "process32";
			break;
		case AUT_PROCESS64:
			prefix = "process64";
			break;
		case AUT_RETURN32:
			prefix = "return32";
			break;
		case AUT_RETURN64:
			prefix = "return64";
			break;
		case AUT_SEQ:
			prefix = "seq";
			break;
		case AUT_SERVER:
			prefix = "server";
			break;
		case AUT_SOCKET:
			prefix = "socket";
			break;
		case AUT_SUBJECT32:
			prefix = "subject32";
			break;
		case AUT_SUBJECT64:
			prefix = "subject64";
			break;
		case AUT_TEXT:
			prefix = "text";
			break;
		case AUT_TRAILER:
			prefix = "trailer";
			break;
		default:
			prefix = "invalid";
			break;
	}
	fprintf(fp,"%s:%s\n", prefix, str);
}

/*
 * Convert binary data to ASCII for printing.
 */
static void
convertascii(p,c,size)
register char *p;
register char *c;
register int size;
{
	register int i;

	for (i=0; i<size; i++) {
		*(c+i) = (char)toascii(*(c+i));
		if ((int)iscntrl(*(c+i))) {
			*p++ = '^';
			*p++ = (char)(*(c+i)+0x40);
		} else
			*p++ = *(c+i);
	}

	*p = '\0';

	return;
}

/* =========================================================
   convert_char_to_string:
   Converts a byte to string depending on the print mode
   input	: printmode, which may be one of AUP_BINARY,
		  AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
		  c, which is the byte to convert
   output	: p, which is a pointer to the location where
		  the resulting string is to be stored
   ========================================================== */

static int
convert_char_to_string (printmode, c, p)
char printmode;
char c;
char *p;
{
	union {
		char c1[4];
		int c2;
	} dat;

	dat.c2 = 0;
	dat.c1[3] = c;

	if (printmode == AUP_BINARY)
		convertbinary (p,&c,sizeof(char));
	else if (printmode == AUP_OCTAL)
		sprintf(p,"%o",dat.c2);
	else if (printmode == AUP_DECIMAL)
		sprintf(p,"%d",c);
	else if (printmode == AUP_HEX)
		sprintf(p,"0x%x",dat.c2);
	else if (printmode == AUP_STRING)
		convertascii (p, &c, sizeof(char));
	return 0;
}

/* ==============================================================
   convert_short_to_string:
   Converts a short integer to string depending on the print mode
   input	: printmode, which may be one of AUP_BINARY,
		  AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
		  c, which is the short integer to convert
   output	: p, which is a pointer to the location where
		  the resulting string is to be stored
   =============================================================== */
static int
convert_short_to_string (printmode, c, p)
char printmode;
short c;
char *p;
{
	union {
		short c1[2];
		int c2;
	} dat;

	dat.c2 = 0;
	dat.c1[1] = c;

	if (printmode == AUP_BINARY)
		convertbinary (p,&c,sizeof(short));
	else if (printmode == AUP_OCTAL)
		sprintf(p,"%o",dat.c2);
	else if (printmode == AUP_DECIMAL)
		sprintf(p,"%hd",c);
	else if (printmode == AUP_HEX)
		sprintf(p,"0x%x",dat.c2);
	else if (printmode == AUP_STRING)
		convertascii (p,&c,sizeof(short));
	return 0;
}

/* =========================================================
   convert_intXX_to_string:
   Converts a integer to string depending on the print mode
   input	: printmode, which may be one of AUP_BINARY,
		  AUP_OCTAL, AUP_DECIMAL, and AUP_HEX
		  c, which is the integer to convert
   output	: p, which is a pointer to the location where
		  the resulting string is to be stored
   ========================================================== */
static int
convert_int32_to_string (printmode, c, p)
char printmode;
int32_t c;
char *p;
{
	if (printmode == AUP_BINARY)
		convertbinary (p,&c,sizeof(int32_t));
	else if (printmode == AUP_OCTAL)
		sprintf(p,"%o",c);
	else if (printmode == AUP_DECIMAL)
		sprintf(p,"%d",c);
	else if (printmode == AUP_HEX)
		sprintf(p,"0x%x",c);
	else if (printmode == AUP_STRING)
		convertascii (p,&c,sizeof(int32_t));
	return 0;
}

static int
convert_int64_to_string (printmode, c, p)
char printmode;
int c;
char *p;
{
	if (printmode == AUP_BINARY)
		convertbinary (p,&c,sizeof(int64_t));
	else if (printmode == AUP_OCTAL)
		sprintf(p,"%"PRIo,c);
	else if (printmode == AUP_DECIMAL)
		sprintf(p,"%"PRId,c);
	else if (printmode == AUP_HEX)
		sprintf(p,"0x%"PRIx,c);
	else if (printmode == AUP_STRING)
		convertascii (p,&c,sizeof(int64_t));
	return 0;
}

/* ===========================================================
   convertbinary:
   Converts a unit c of 'size' bytes long into a binary string 
   and returns it into the position pointed to by p
   ============================================================ */
static int
convertbinary (p, c,size)
char *p;
char *c;
int size;
{
	char *s, *t;
	int i, j;

	if ((s = (char *)malloc(8*size + 1)) == NULL)
		return (0);

	/* first convert to binary */
	t = s;
	for (i=0;i<size;i++) {
		for (j=0;j<8;j++)
			sprintf(t++,"%d", ((*c >> (7-j)) & (0x01)));
		c++;
	}
	*t = '\0';

	/* now string leading zero's if any */
	j = strlen (s) - 1;
	for (i=0; i<j; i++) {
		if (*s != '0')
			break;
		else
			s++;
	}

	/* now copy the contents of s to p */
	t = p;
	for (i=0;i<(8*size + 1);i++) {
		if (*s == '\0') {
			*t = '\0';
			break;
		}
		*t++ = *s++;
	}
	free (s);

	return 1;
}

static char *
hexconvert(c,size,chunk)
	unsigned char *c;
	int size;
	int chunk;
{
	register char *s, *t;
	register int i,j,k;
	int numchunks;
	int leftovers;

	if ((s = (char *)malloc((size*5)+1)) == NULL)
		return (NULL);

	if (size <= 0) 
		return (NULL);

	if (chunk > size || chunk <= 0)
		chunk = size;

	numchunks = size/chunk;
	leftovers = size % chunk;

	t = s;
	for (i=j=0; i < numchunks; i++) {
		if (j++) {
			*t = ' ';
			t++;
		}
		(void)sprintf(t,"0x");
		t+=2;
		for (k=0; k < chunk; k++) {
			sprintf(t,"%02x", *c++);
			t+=2;
		}
	}

	if (leftovers) {
		*t++ = ' ';
		*t++ = '0';
		*t++ = 'x';
		for (i=0; i < leftovers; i++) {
			sprintf(t,"%02x", *c++);
			t+=2;
		}
	}
		
	*t = '\0';
	return (s);
}

static char *
get_Hname(addr)
unsigned int addr;
{
	extern char *inet_ntoa(const struct in_addr);
	struct hostent *phe;
	static char buf[256];
	struct in_addr ia;

	phe = gethostbyaddr((const char *)&addr, 4, AF_INET);
	if (phe == (struct hostent *)0)
	{
		ia.s_addr = addr;
		(void) sprintf(buf, "%s", inet_ntoa(ia));
		return(buf);
	}
	ia.s_addr = addr;
	(void) sprintf(buf, "%s", phe->h_name);
	return(buf);
}

static char *
pa_gettokenstring (tokenid)
int tokenid;
{
        int i;
        struct tokentable *k;
 
        for (i=0;i<numtokenentries;i++) {
                k = &(tokentab[i]);
                if ((k->tokenid) == tokenid)
                        return (k->tokentype);
        }
        /* here if token id is not in table */
        return (NULL);
}
