OpenSolaris_b135/cmd/truss/expound.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

#define	_SYSCALL32

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <libproc.h>
#include <string.h>
#include <limits.h>
#include <sys/statfs.h>
#include <sys/times.h>
#include <sys/timex.h>
#include <sys/utssys.h>
#include <sys/utsname.h>
#include <sys/ipc.h>
#include <sys/ipc_impl.h>
#include <sys/msg.h>
#include <sys/msg_impl.h>
#include <sys/sem.h>
#include <sys/sem_impl.h>
#include <sys/shm.h>
#include <sys/shm_impl.h>
#include <sys/dirent.h>
#include <ustat.h>
#include <fcntl.h>
#include <time.h>
#include <sys/termios.h>
#include <sys/termiox.h>
#include <sys/termio.h>
#include <sys/ttold.h>
#include <sys/jioctl.h>
#include <sys/filio.h>
#include <stropts.h>
#include <poll.h>
#include <sys/uio.h>
#include <sys/resource.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <sys/aio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/byteorder.h>
#include <arpa/inet.h>
#include <sys/audioio.h>
#include <sys/cladm.h>
#include <sys/synch.h>
#include <sys/synch32.h>
#include <sys/sysmacros.h>
#include <sys/sendfile.h>
#include <priv.h>
#include <ucred.h>
#include <sys/ucred.h>
#include <sys/port_impl.h>
#include <sys/zone.h>
#include <sys/priv_impl.h>
#include <sys/priv.h>
#include <tsol/label.h>
#include <sys/nvpair.h>
#include <libnvpair.h>
#include <sys/rctl_impl.h>

#include "ramdata.h"
#include "systable.h"
#include "proto.h"

void	show_sigset(private_t *, long, const char *);
void	show_ioctl(private_t *, int, long);

static void
mk_ctime(char *str, size_t maxsize, time_t value)
{
	(void) strftime(str, maxsize, "%b %e %H:%M:%S %Z %Y",
	    localtime(&value));
}

void
prtime(private_t *pri, const char *name, time_t value)
{
	char str[80];

	mk_ctime(str, sizeof (str), value);
	(void) printf("%s\t%s%s  [ %lu ]\n",
	    pri->pname,
	    name,
	    str,
	    value);
}

void
prtimeval(private_t *pri, const char *name, struct timeval *value)
{
	char str[80];

	mk_ctime(str, sizeof (str), value->tv_sec);
	(void) printf("%s\t%s%s  [ %lu.%6.6lu ]\n",
	    pri->pname,
	    name,
	    str,
	    value->tv_sec,
	    value->tv_usec);
}

void
prtimestruc(private_t *pri, const char *name, timestruc_t *value)
{
	char str[80];

	mk_ctime(str, sizeof (str), value->tv_sec);
	(void) printf("%s\t%s%s  [ %lu.%9.9lu ]\n",
	    pri->pname,
	    name,
	    str,
	    value->tv_sec,
	    value->tv_nsec);
}

static void
show_utimens(private_t *pri, long offset)
{
	struct {
		timespec_t atime;
		timespec_t mtime;
	} utimbuf;

	if (offset == 0)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &utimbuf, sizeof (utimbuf), offset)
		    != sizeof (utimbuf))
			return;
	} else {
		struct {
			timespec32_t atime;
			timespec32_t mtime;
		} utimbuf32;

		if (Pread(Proc, &utimbuf32, sizeof (utimbuf32), offset)
		    != sizeof (utimbuf32))
			return;

		TIMESPEC32_TO_TIMESPEC(&utimbuf.atime, &utimbuf32.atime);
		TIMESPEC32_TO_TIMESPEC(&utimbuf.mtime, &utimbuf32.mtime);
	}

	/* print access and modification times */
	if (utimbuf.atime.tv_nsec == UTIME_OMIT)
		(void) printf("%s\tat = UTIME_OMIT\n", pri->pname);
	else if (utimbuf.atime.tv_nsec == UTIME_NOW)
		(void) printf("%s\tat = UTIME_NOW\n", pri->pname);
	else
		prtimestruc(pri, "at = ", &utimbuf.atime);
	if (utimbuf.mtime.tv_nsec == UTIME_OMIT)
		(void) printf("%s\tmt = UTIME_OMIT\n", pri->pname);
	else if (utimbuf.mtime.tv_nsec == UTIME_NOW)
		(void) printf("%s\tmt = UTIME_NOW\n", pri->pname);
	else
		prtimestruc(pri, "mt = ", &utimbuf.mtime);
}

void
show_timeofday(private_t *pri)
{
	struct timeval tod;
	long offset;

	if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &tod, sizeof (tod), offset)
		    != sizeof (tod))
			return;
	} else {
		struct timeval32 tod32;

		if (Pread(Proc, &tod32, sizeof (tod32), offset)
		    != sizeof (tod32))
			return;

		TIMEVAL32_TO_TIMEVAL(&tod, &tod32);
	}

	prtimeval(pri, "time: ", &tod);
}

void
show_itimerval(private_t *pri, long offset, const char *name)
{
	struct itimerval itimerval;

	if (offset == 0)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &itimerval, sizeof (itimerval), offset)
		    != sizeof (itimerval))
			return;
	} else {
		struct itimerval32 itimerval32;

		if (Pread(Proc, &itimerval32, sizeof (itimerval32), offset)
		    != sizeof (itimerval32))
			return;

		ITIMERVAL32_TO_ITIMERVAL(&itimerval, &itimerval32);
	}

	(void) printf(
	    "%s\t%s:  interval: %4ld.%6.6ld sec  value: %4ld.%6.6ld sec\n",
	    pri->pname,
	    name,
	    itimerval.it_interval.tv_sec,
	    itimerval.it_interval.tv_usec,
	    itimerval.it_value.tv_sec,
	    itimerval.it_value.tv_usec);
}

void
show_timeval(private_t *pri, long offset, const char *name)
{
	struct timeval timeval;

	if (offset == 0)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &timeval, sizeof (timeval), offset)
		    != sizeof (timeval))
			return;
	} else {
		struct timeval32 timeval32;

		if (Pread(Proc, &timeval32, sizeof (timeval32), offset)
		    != sizeof (timeval32))
			return;

		TIMEVAL32_TO_TIMEVAL(&timeval, &timeval32);
	}

	(void) printf(
	    "%s\t%s: %ld.%6.6ld sec\n",
	    pri->pname,
	    name,
	    timeval.tv_sec,
	    timeval.tv_usec);
}

void
show_timestruc(private_t *pri, long offset, const char *name)
{
	timestruc_t timestruc;

	if (offset == 0)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &timestruc, sizeof (timestruc), offset)
		    != sizeof (timestruc))
			return;
	} else {
		timestruc32_t timestruc32;

		if (Pread(Proc, &timestruc32, sizeof (timestruc32), offset)
		    != sizeof (timestruc32))
			return;

		TIMESPEC32_TO_TIMESPEC(&timestruc, &timestruc32);
	}

	(void) printf(
	    "%s\t%s: %ld.%9.9ld sec\n",
	    pri->pname,
	    name,
	    timestruc.tv_sec,
	    timestruc.tv_nsec);
}

void
show_stime(private_t *pri)
{
	if (pri->sys_nargs >= 1) {
		/* print new system time */
		prtime(pri, "systime = ", (time_t)pri->sys_args[0]);
	}
}

void
show_times(private_t *pri)
{
	long hz = sysconf(_SC_CLK_TCK);
	long offset;
	struct tms tms;

	if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &tms, sizeof (tms), offset)
		    != sizeof (tms))
			return;
	} else {
		struct tms32 tms32;

		if (Pread(Proc, &tms32, sizeof (tms32), offset)
		    != sizeof (tms32))
			return;

		/*
		 * This looks a bit odd (since the values are actually
		 * signed), but we need to suppress sign extension to
		 * preserve compatibility (we've always printed these
		 * numbers as unsigned quantities).
		 */
		tms.tms_utime = (unsigned)tms32.tms_utime;
		tms.tms_stime = (unsigned)tms32.tms_stime;
		tms.tms_cutime = (unsigned)tms32.tms_cutime;
		tms.tms_cstime = (unsigned)tms32.tms_cstime;
	}

	(void) printf(
	    "%s\tutim=%-6lu stim=%-6lu cutim=%-6lu cstim=%-6lu (HZ=%ld)\n",
	    pri->pname,
	    tms.tms_utime,
	    tms.tms_stime,
	    tms.tms_cutime,
	    tms.tms_cstime,
	    hz);
}

void
show_uname(private_t *pri, long offset)
{
	/*
	 * Old utsname buffer (no longer accessible in <sys/utsname.h>).
	 */
	struct {
		char	sysname[9];
		char	nodename[9];
		char	release[9];
		char	version[9];
		char	machine[9];
	} ubuf;

	if (offset != NULL &&
	    Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
		(void) printf(
		    "%s\tsys=%-9.9snod=%-9.9srel=%-9.9sver=%-9.9smch=%.9s\n",
		    pri->pname,
		    ubuf.sysname,
		    ubuf.nodename,
		    ubuf.release,
		    ubuf.version,
		    ubuf.machine);
	}
}

/* XX64 -- definition of 'struct ustat' is strange -- check out the defn */
void
show_ustat(private_t *pri, long offset)
{
	struct ustat ubuf;

	if (offset != NULL &&
	    Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
		(void) printf(
		    "%s\ttfree=%-6ld tinode=%-5lu fname=%-6.6s fpack=%-.6s\n",
		    pri->pname,
		    ubuf.f_tfree,
		    ubuf.f_tinode,
		    ubuf.f_fname,
		    ubuf.f_fpack);
	}
}

#ifdef _LP64
void
show_ustat32(private_t *pri, long offset)
{
	struct ustat32 ubuf;

	if (offset != NULL &&
	    Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
		(void) printf(
		    "%s\ttfree=%-6d tinode=%-5u fname=%-6.6s fpack=%-.6s\n",
		    pri->pname,
		    ubuf.f_tfree,
		    ubuf.f_tinode,
		    ubuf.f_fname,
		    ubuf.f_fpack);
	}
}
#endif	/* _LP64 */

void
show_fusers(private_t *pri, long offset, long nproc)
{
	f_user_t fubuf;
	int serial = (nproc > 4);

	if (offset == 0)
		return;

	/* enter region of lengthy output */
	if (serial)
		Eserialize();

	while (nproc > 0 &&
	    Pread(Proc, &fubuf, sizeof (fubuf), offset) == sizeof (fubuf)) {
		(void) printf("%s\tpid=%-5d uid=%-5u flags=%s\n",
		    pri->pname,
		    (int)fubuf.fu_pid,
		    fubuf.fu_uid,
		    fuflags(pri, fubuf.fu_flags));
		nproc--;
		offset += sizeof (fubuf);
	}

	/* exit region of lengthy output */
	if (serial)
		Xserialize();
}

void
show_utssys(private_t *pri, long r0)
{
	if (pri->sys_nargs >= 3) {
		switch (pri->sys_args[2]) {
		case UTS_UNAME:
			show_uname(pri, (long)pri->sys_args[0]);
			break;
		case UTS_USTAT:
			show_ustat(pri, (long)pri->sys_args[0]);
			break;
		case UTS_FUSERS:
			show_fusers(pri, (long)pri->sys_args[3], r0);
			break;
		}
	}
}

#ifdef _LP64
void
show_utssys32(private_t *pri, long r0)
{
	if (pri->sys_nargs >= 3) {
		switch (pri->sys_args[2]) {
		case UTS_UNAME:
			show_uname(pri, (long)pri->sys_args[0]);
			break;
		case UTS_USTAT:
			show_ustat32(pri, (long)pri->sys_args[0]);
			break;
		case UTS_FUSERS:
			show_fusers(pri, (long)pri->sys_args[3], r0);
			break;
		}
	}
}
#endif	/* _LP64 */

void
show_cladm(private_t *pri, int code, int function, long offset)
{
	int	arg;

	switch (code) {
	case CL_INITIALIZE:
		switch (function) {
		case CL_GET_BOOTFLAG:
			if (Pread(Proc, &arg, sizeof (arg), offset)
			    == sizeof (arg)) {
				if (arg & CLUSTER_CONFIGURED)
					(void) printf("%s\tbootflags="
					    "CLUSTER_CONFIGURED", pri->pname);
				if (arg & CLUSTER_BOOTED)
					(void) printf("|CLUSTER_BOOTED\n");
			}
			break;
		}
		break;
	case CL_CONFIG:
		switch (function) {
		case CL_NODEID:
		case CL_HIGHEST_NODEID:
			if (Pread(Proc, &arg, sizeof (arg), offset)
			    == sizeof (arg))
				(void) printf("%s\tnodeid=%d\n",
				    pri->pname, arg);
		}
		break;
	}
}

#define	ALL_LOCK_TYPES						\
	(USYNC_PROCESS | LOCK_ERRORCHECK | LOCK_RECURSIVE | 	\
	LOCK_PRIO_INHERIT | LOCK_PRIO_PROTECT | LOCK_ROBUST | 	\
	USYNC_PROCESS_ROBUST)

/* return cv and mutex types */
const char *
synch_type(private_t *pri, uint_t type)
{
	char *str = pri->code_buf;

	if (type & USYNC_PROCESS)
		(void) strcpy(str, "USYNC_PROCESS");
	else
		(void) strcpy(str, "USYNC_THREAD");

	if (type & LOCK_ERRORCHECK)
		(void) strcat(str, "|LOCK_ERRORCHECK");
	if (type & LOCK_RECURSIVE)
		(void) strcat(str, "|LOCK_RECURSIVE");
	if (type & LOCK_PRIO_INHERIT)
		(void) strcat(str, "|LOCK_PRIO_INHERIT");
	if (type & LOCK_PRIO_PROTECT)
		(void) strcat(str, "|LOCK_PRIO_PROTECT");
	if (type & LOCK_ROBUST)
		(void) strcat(str, "|LOCK_ROBUST");
	if (type & USYNC_PROCESS_ROBUST)
		(void) strcat(str, "|USYNC_PROCESS_ROBUST");

	if ((type &= ~ALL_LOCK_TYPES) != 0)
		(void) sprintf(str + strlen(str), "|0x%.4X", type);

	return ((const char *)str);
}

void
show_mutex(private_t *pri, long offset)
{
	lwp_mutex_t mutex;

	if (Pread(Proc, &mutex, sizeof (mutex), offset) == sizeof (mutex)) {
		(void) printf("%s\tmutex type: %s\n",
		    pri->pname,
		    synch_type(pri, mutex.mutex_type));
	}
}

void
show_condvar(private_t *pri, long offset)
{
	lwp_cond_t condvar;

	if (Pread(Proc, &condvar, sizeof (condvar), offset)
	    == sizeof (condvar)) {
		(void) printf("%s\tcondvar type: %s\n",
		    pri->pname,
		    synch_type(pri, condvar.cond_type));
	}
}

void
show_sema(private_t *pri, long offset)
{
	lwp_sema_t sema;

	if (Pread(Proc, &sema, sizeof (sema), offset) == sizeof (sema)) {
		(void) printf("%s\tsema type: %s  count = %u\n",
		    pri->pname,
		    synch_type(pri, sema.sema_type),
		    sema.sema_count);
	}
}

void
show_rwlock(private_t *pri, long offset)
{
	lwp_rwlock_t rwlock;

	if (Pread(Proc, &rwlock, sizeof (rwlock), offset) == sizeof (rwlock)) {
		(void) printf("%s\trwlock type: %s  readers = %d\n",
		    pri->pname,
		    synch_type(pri, rwlock.rwlock_type),
		    rwlock.rwlock_readers);
	}
}

/* represent character as itself ('c') or octal (012) */
char *
show_char(char *buf, int c)
{
	const char *fmt;

	if (c >= ' ' && c < 0177)
		fmt = "'%c'";
	else
		fmt = "%.3o";

	(void) sprintf(buf, fmt, c&0xff);
	return (buf);
}

void
show_termio(private_t *pri, long offset)
{
	struct termio termio;
	char cbuf[8];
	int i;

	if (Pread(Proc, &termio, sizeof (termio), offset) == sizeof (termio)) {
		(void) printf(
		"%s\tiflag=0%.6o oflag=0%.6o cflag=0%.6o lflag=0%.6o line=%d\n",
		    pri->pname,
		    termio.c_iflag,
		    termio.c_oflag,
		    termio.c_cflag,
		    termio.c_lflag,
		    termio.c_line);
		(void) printf("%s\t    cc: ", pri->pname);
		for (i = 0; i < NCC; i++)
			(void) printf(" %s",
			    show_char(cbuf, (int)termio.c_cc[i]));
		(void) fputc('\n', stdout);
	}
}

void
show_termios(private_t *pri, long offset)
{
	struct termios termios;
	char cbuf[8];
	int i;

	if (Pread(Proc, &termios, sizeof (termios), offset)
	    == sizeof (termios)) {
		(void) printf(
		    "%s\tiflag=0%.6o oflag=0%.6o cflag=0%.6o lflag=0%.6o\n",
		    pri->pname,
		    termios.c_iflag,
		    termios.c_oflag,
		    termios.c_cflag,
		    termios.c_lflag);
		(void) printf("%s\t    cc: ", pri->pname);
		for (i = 0; i < NCCS; i++) {
			if (i == NCC)	/* show new chars on new line */
				(void) printf("\n%s\t\t", pri->pname);
			(void) printf(" %s",
			    show_char(cbuf, (int)termios.c_cc[i]));
		}
		(void) fputc('\n', stdout);
	}
}

void
show_termiox(private_t *pri, long offset)
{
	struct termiox termiox;
	int i;

	if (Pread(Proc, &termiox, sizeof (termiox), offset)
	    == sizeof (termiox)) {
		(void) printf("%s\thflag=0%.3o cflag=0%.3o rflag=0%.3o",
		    pri->pname,
		    termiox.x_hflag,
		    termiox.x_cflag,
		    termiox.x_rflag[0]);
		for (i = 1; i < NFF; i++)
			(void) printf(",0%.3o", termiox.x_rflag[i]);
		(void) printf(" sflag=0%.3o\n",
		    termiox.x_sflag);
	}
}

void
show_sgttyb(private_t *pri, long offset)
{
	struct sgttyb sgttyb;

	if (Pread(Proc, &sgttyb, sizeof (sgttyb), offset) == sizeof (sgttyb)) {
		char erase[8];
		char kill[8];

		(void) printf(
		"%s\tispeed=%-2d ospeed=%-2d erase=%s kill=%s flags=0x%.8x\n",
		    pri->pname,
		    sgttyb.sg_ispeed&0xff,
		    sgttyb.sg_ospeed&0xff,
		    show_char(erase, sgttyb.sg_erase),
		    show_char(kill, sgttyb.sg_kill),
		    sgttyb.sg_flags);
	}
}

void
show_ltchars(private_t *pri, long offset)
{
	struct ltchars ltchars;
	char *p;
	char cbuf[8];
	int i;

	if (Pread(Proc, &ltchars, sizeof (ltchars), offset)
	    == sizeof (ltchars)) {
		(void) printf("%s\t    cc: ", pri->pname);
		for (p = (char *)&ltchars, i = 0; i < sizeof (ltchars); i++)
			(void) printf(" %s", show_char(cbuf, (int)*p++));
		(void) fputc('\n', stdout);
	}
}

void
show_tchars(private_t *pri, long offset)
{
	struct tchars tchars;
	char *p;
	char cbuf[8];
	int i;

	if (Pread(Proc, &tchars, sizeof (tchars), offset) == sizeof (tchars)) {
		(void) printf("%s\t    cc: ", pri->pname);
		for (p = (char *)&tchars, i = 0; i < sizeof (tchars); i++)
			(void) printf(" %s", show_char(cbuf, (int)*p++));
		(void) fputc('\n', stdout);
	}
}

void
show_termcb(private_t *pri, long offset)
{
	struct termcb termcb;

	if (Pread(Proc, &termcb, sizeof (termcb), offset) == sizeof (termcb)) {
		(void) printf(
		    "%s\tflgs=0%.2o termt=%d crow=%d ccol=%d vrow=%d lrow=%d\n",
		    pri->pname,
		    termcb.st_flgs&0xff,
		    termcb.st_termt&0xff,
		    termcb.st_crow&0xff,
		    termcb.st_ccol&0xff,
		    termcb.st_vrow&0xff,
		    termcb.st_lrow&0xff);
	}
}

/* integer value pointed to by ioctl() arg */
void
show_strint(private_t *pri, int code, long offset)
{
	int val;

	if (Pread(Proc, &val, sizeof (val), offset) == sizeof (val)) {
		const char *s = NULL;

		switch (code) {		/* interpret these symbolically */
		case I_GRDOPT:
			s = strrdopt(val);
			break;
		case I_GETSIG:
			s = strevents(pri, val);
			break;
		case TIOCFLUSH:
			s = tiocflush(pri, val);
			break;
		}

		if (s == NULL)
			(void) printf("%s\t0x%.8lX: %d\n",
			    pri->pname, offset, val);
		else
			(void) printf("%s\t0x%.8lX: %s\n",
			    pri->pname, offset, s);
	}
}

void
show_strioctl(private_t *pri, long offset)
{
	struct strioctl strioctl;

	if (Pread(Proc, &strioctl, sizeof (strioctl), offset) ==
	    sizeof (strioctl)) {
		(void) printf(
		    "%s\tcmd=%s timout=%d len=%d dp=0x%.8lX\n",
		    pri->pname,
		    ioctlname(pri, strioctl.ic_cmd),
		    strioctl.ic_timout,
		    strioctl.ic_len,
		    (long)strioctl.ic_dp);

		if (pri->recur++ == 0)	/* avoid indefinite recursion */
			show_ioctl(pri, strioctl.ic_cmd,
			    (long)strioctl.ic_dp);
		--pri->recur;
	}
}

#ifdef _LP64
void
show_strioctl32(private_t *pri, long offset)
{
	struct strioctl32 strioctl;

	if (Pread(Proc, &strioctl, sizeof (strioctl), offset) ==
	    sizeof (strioctl)) {
		(void) printf(
		    "%s\tcmd=%s timout=%d len=%d dp=0x%.8lX\n",
		    pri->pname,
		    ioctlname(pri, strioctl.ic_cmd),
		    strioctl.ic_timout,
		    strioctl.ic_len,
		    (long)strioctl.ic_dp);

		if (pri->recur++ == 0)	/* avoid indefinite recursion */
			show_ioctl(pri, strioctl.ic_cmd,
			    (long)strioctl.ic_dp);
		--pri->recur;
	}
}
#endif	/* _LP64 */

void
print_strbuf(private_t *pri, struct strbuf *sp, const char *name, int dump)
{
	(void) printf(
	    "%s\t%s:  maxlen=%-4d len=%-4d buf=0x%.8lX",
	    pri->pname,
	    name,
	    sp->maxlen,
	    sp->len,
	    (long)sp->buf);
	/*
	 * Should we show the buffer contents?
	 * Keyed to the '-r fds' and '-w fds' options?
	 */
	if (sp->buf == NULL || sp->len <= 0)
		(void) fputc('\n', stdout);
	else {
		int nb = (sp->len > 8)? 8 : sp->len;
		char buffer[8];
		char obuf[40];

		if (Pread(Proc, buffer, (size_t)nb, (long)sp->buf) == nb) {
			(void) strcpy(obuf, ": \"");
			showbytes(buffer, nb, obuf+3);
			(void) strcat(obuf,
			    (nb == sp->len)?
			    (const char *)"\"" : (const char *)"\"..");
			(void) fputs(obuf, stdout);
		}
		(void) fputc('\n', stdout);
		if (dump && sp->len > 8)
			showbuffer(pri, (long)sp->buf, (long)sp->len);
	}
}

#ifdef _LP64
void
print_strbuf32(private_t *pri, struct strbuf32 *sp, const char *name, int dump)
{
	(void) printf(
	    "%s\t%s:  maxlen=%-4d len=%-4d buf=0x%.8lX",
	    pri->pname,
	    name,
	    sp->maxlen,
	    sp->len,
	    (long)sp->buf);
	/*
	 * Should we show the buffer contents?
	 * Keyed to the '-r fds' and '-w fds' options?
	 */
	if (sp->buf == NULL || sp->len <= 0)
		(void) fputc('\n', stdout);
	else {
		int nb = (sp->len > 8)? 8 : sp->len;
		char buffer[8];
		char obuf[40];

		if (Pread(Proc, buffer, (size_t)nb, (long)sp->buf) == nb) {
			(void) strcpy(obuf, ": \"");
			showbytes(buffer, nb, obuf+3);
			(void) strcat(obuf,
			    (nb == sp->len)?
			    (const char *)"\"" : (const char *)"\"..");
			(void) fputs(obuf, stdout);
		}
		(void) fputc('\n', stdout);
		if (dump && sp->len > 8)
			showbuffer(pri, (long)sp->buf, (long)sp->len);
	}
}
#endif	/* _LP64 */

/* strpeek and strfdinsert flags word */
const char *
strflags(private_t *pri, int flags)
{
	const char *s;

	switch (flags) {
	case 0:
		s = "0";
		break;
	case RS_HIPRI:
		s = "RS_HIPRI";
		break;
	default:
		(void) sprintf(pri->code_buf, "0x%.4X", flags);
		s = pri->code_buf;
	}

	return (s);
}

void
show_strpeek(private_t *pri, long offset)
{
	struct strpeek strpeek;

	if (Pread(Proc, &strpeek, sizeof (strpeek), offset)
	    == sizeof (strpeek)) {

		print_strbuf(pri, &strpeek.ctlbuf, "ctl", FALSE);
		print_strbuf(pri, &strpeek.databuf, "dat", FALSE);

		(void) printf("%s\tflags=%s\n",
		    pri->pname,
		    strflags(pri, strpeek.flags));
	}
}

#ifdef _LP64
void
show_strpeek32(private_t *pri, long offset)
{
	struct strpeek32 strpeek;

	if (Pread(Proc, &strpeek, sizeof (strpeek), offset)
	    == sizeof (strpeek)) {

		print_strbuf32(pri, &strpeek.ctlbuf, "ctl", FALSE);
		print_strbuf32(pri, &strpeek.databuf, "dat", FALSE);

		(void) printf("%s\tflags=%s\n",
		    pri->pname,
		    strflags(pri, strpeek.flags));
	}
}
#endif	/* _LP64 */

void
show_strfdinsert(private_t *pri, long offset)
{
	struct strfdinsert strfdinsert;

	if (Pread(Proc, &strfdinsert, sizeof (strfdinsert), offset) ==
	    sizeof (strfdinsert)) {

		print_strbuf(pri, &strfdinsert.ctlbuf, "ctl", FALSE);
		print_strbuf(pri, &strfdinsert.databuf, "dat", FALSE);

		(void) printf("%s\tflags=%s fildes=%d offset=%d\n",
		    pri->pname,
		    strflags(pri, strfdinsert.flags),
		    strfdinsert.fildes,
		    strfdinsert.offset);
	}
}

#ifdef _LP64
void
show_strfdinsert32(private_t *pri, long offset)
{
	struct strfdinsert32 strfdinsert;

	if (Pread(Proc, &strfdinsert, sizeof (strfdinsert), offset) ==
	    sizeof (strfdinsert)) {

		print_strbuf32(pri, &strfdinsert.ctlbuf, "ctl", FALSE);
		print_strbuf32(pri, &strfdinsert.databuf, "dat", FALSE);

		(void) printf("%s\tflags=%s fildes=%d offset=%d\n",
		    pri->pname,
		    strflags(pri, strfdinsert.flags),
		    strfdinsert.fildes,
		    strfdinsert.offset);
	}
}
#endif	/* _LP64 */

void
show_strrecvfd(private_t *pri, long offset)
{
	struct strrecvfd strrecvfd;

	if (Pread(Proc, &strrecvfd, sizeof (strrecvfd), offset) ==
	    sizeof (strrecvfd)) {
		(void) printf(
		    "%s\tfd=%-5d uid=%-5u gid=%u\n",
		    pri->pname,
		    strrecvfd.fd,
		    strrecvfd.uid,
		    strrecvfd.gid);
	}
}

void
show_strlist(private_t *pri, long offset)
{
	struct str_list strlist;
	struct str_mlist list;
	int count;

	if (Pread(Proc, &strlist, sizeof (strlist), offset) ==
	    sizeof (strlist)) {
		(void) printf("%s\tnmods=%d  modlist=0x%.8lX\n",
		    pri->pname,
		    strlist.sl_nmods,
		    (long)strlist.sl_modlist);

		count = strlist.sl_nmods;
		offset = (long)strlist.sl_modlist;
		while (!interrupt && --count >= 0) {
			if (Pread(Proc, &list, sizeof (list), offset) !=
			    sizeof (list))
				break;
			(void) printf("%s\t\t\"%.*s\"\n",
			    pri->pname,
			    (int)sizeof (list.l_name),
			    list.l_name);
			offset += sizeof (struct str_mlist);
		}
	}
}

#ifdef _LP64
void
show_strlist32(private_t *pri, long offset)
{
	struct str_list32 strlist;
	struct str_mlist list;
	int count;

	if (Pread(Proc, &strlist, sizeof (strlist), offset) ==
	    sizeof (strlist)) {
		(void) printf("%s\tnmods=%d  modlist=0x%.8lX\n",
		    pri->pname,
		    strlist.sl_nmods,
		    (long)strlist.sl_modlist);

		count = strlist.sl_nmods;
		offset = (long)strlist.sl_modlist;
		while (!interrupt && --count >= 0) {
			if (Pread(Proc, &list, sizeof (list), offset) !=
			    sizeof (list))
				break;
			(void) printf("%s\t\t\"%.*s\"\n",
			    pri->pname,
			    (int)sizeof (list.l_name),
			    list.l_name);
			offset += sizeof (struct str_mlist);
		}
	}
}
#endif	/* _LP64 */

void
show_jwinsize(private_t *pri, long offset)
{
	struct jwinsize jwinsize;

	if (Pread(Proc, &jwinsize, sizeof (jwinsize), offset) ==
	    sizeof (jwinsize)) {
		(void) printf(
		    "%s\tbytesx=%-3u bytesy=%-3u bitsx=%-3u bitsy=%-3u\n",
		    pri->pname,
		    (unsigned)jwinsize.bytesx,
		    (unsigned)jwinsize.bytesy,
		    (unsigned)jwinsize.bitsx,
		    (unsigned)jwinsize.bitsy);
	}
}

void
show_winsize(private_t *pri, long offset)
{
	struct winsize winsize;

	if (Pread(Proc, &winsize, sizeof (winsize), offset)
	    == sizeof (winsize)) {
		(void) printf(
		    "%s\trow=%-3d col=%-3d xpixel=%-3d ypixel=%-3d\n",
		    pri->pname,
		    winsize.ws_row,
		    winsize.ws_col,
		    winsize.ws_xpixel,
		    winsize.ws_ypixel);
	}
}

struct audio_stuff {
	uint_t	bit;
	const char *str;
};

const struct audio_stuff audio_output_ports[] = {
	{ AUDIO_SPEAKER, "SPEAKER" },
	{ AUDIO_HEADPHONE, "HEADPHONE" },
	{ AUDIO_LINE_OUT, "LINE_OUT" },
	{ AUDIO_SPDIF_OUT, "SPDIF_OUT" },
	{ AUDIO_AUX1_OUT, "AUX1_OUT" },
	{ AUDIO_AUX2_OUT, "AUX2_OUT" },
	{ 0, NULL }
};

const struct audio_stuff audio_input_ports[] = {
	{ AUDIO_MICROPHONE, "MICROPHONE" },
	{ AUDIO_LINE_IN, "LINE_IN" },
	{ AUDIO_CD, "CD" },
	{ AUDIO_SPDIF_IN, "SPDIF_IN" },
	{ AUDIO_AUX1_IN, "AUX1_IN" },
	{ AUDIO_AUX2_IN, "AUX2_IN" },
	{ AUDIO_CODEC_LOOPB_IN, "CODEC_LOOPB_IN" },
	{ AUDIO_SUNVTS, "SUNVTS" },
	{ 0, NULL }
};

static const struct audio_stuff audio_hw_features[] = {
	{ AUDIO_HWFEATURE_DUPLEX, "DUPLEX" },
	{ AUDIO_HWFEATURE_MSCODEC, "MSCODEC" },
	{ AUDIO_HWFEATURE_IN2OUT, "IN2OUT" },
	{ AUDIO_HWFEATURE_PLAY, "PLAY" },
	{ AUDIO_HWFEATURE_RECORD, "RECORD" },
	{ 0, NULL }
};

static const struct audio_stuff audio_sw_features[] = {
	{ AUDIO_SWFEATURE_MIXER, "MIXER" },
	{ 0, NULL }
};

void
show_audio_features(const private_t *pri,
	const struct audio_stuff *audio_porttab, uint_t features,
	const char *name)
{
	(void) printf("%s\t%s=", pri->pname, name);
	if (features == 0) {
		(void) printf("0\n");
		return;
	}

	for (; audio_porttab->bit != 0; ++audio_porttab) {
		if (features & audio_porttab->bit) {
			(void) printf(audio_porttab->str);
			features &= ~audio_porttab->bit;
			if (features)
				(void) putchar('|');
		}
	}
	if (features)
		(void) printf("0x%x", features);
	(void) putchar('\n');
}

void
show_audio_ports(private_t *pri, const char *mode,
	const char *field, uint_t ports)
{
	const struct audio_stuff *audio_porttab;

	(void) printf("%s\t%s\t%s=", pri->pname, mode, field);
	if (ports == 0) {
		(void) printf("0\n");
		return;
	}
	if (*mode == 'p')
		audio_porttab = audio_output_ports;
	else
		audio_porttab = audio_input_ports;
	for (; audio_porttab->bit != 0; ++audio_porttab) {
		if (ports & audio_porttab->bit) {
			(void) printf(audio_porttab->str);
			ports &= ~audio_porttab->bit;
			if (ports)
				(void) putchar('|');
		}
	}
	if (ports)
		(void) printf("0x%x", ports);
	(void) putchar('\n');
}

void
show_audio_prinfo(private_t *pri, const char *mode, struct audio_prinfo *au_pr)
{
	const char *s;

	/*
	 * The following values describe the audio data encoding.
	 */

	(void) printf("%s\t%s\tsample_rate=%u channels=%u precision=%u\n",
	    pri->pname, mode,
	    au_pr->sample_rate,
	    au_pr->channels,
	    au_pr->precision);

	s = NULL;
	switch (au_pr->encoding) {
	case AUDIO_ENCODING_NONE:	s = "NONE";	break;
	case AUDIO_ENCODING_ULAW:	s = "ULAW";	break;
	case AUDIO_ENCODING_ALAW:	s = "ALAW";	break;
	case AUDIO_ENCODING_LINEAR:	s = "LINEAR";	break;
	case AUDIO_ENCODING_DVI:	s = "DVI";	break;
	case AUDIO_ENCODING_LINEAR8:	s = "LINEAR8";	break;
	}
	if (s)
		(void) printf("%s\t%s\tencoding=%s\n", pri->pname, mode, s);
	else {
		(void) printf("%s\t%s\tencoding=%u\n",
		    pri->pname, mode, au_pr->encoding);
	}

	/*
	 * The following values control audio device configuration
	 */

	(void) printf(
	    "%s\t%s\tgain=%u buffer_size=%u\n",
	    pri->pname, mode,
	    au_pr->gain,
	    au_pr->buffer_size);
	show_audio_ports(pri, mode, "port", au_pr->port);
	show_audio_ports(pri, mode, "avail_ports", au_pr->avail_ports);
	show_audio_ports(pri, mode, "mod_ports", au_pr->mod_ports);

	/*
	 * The following values describe driver state
	 */

	(void) printf("%s\t%s\tsamples=%u eof=%u pause=%u error=%u\n",
	    pri->pname, mode,
	    au_pr->samples,
	    au_pr->eof,
	    au_pr->pause,
	    au_pr->error);
	(void) printf("%s\t%s\twaiting=%u balance=%u minordev=%u\n",
	    pri->pname, mode,
	    au_pr->waiting,
	    au_pr->balance,
	    au_pr->minordev);

	/*
	 * The following values are read-only state flags
	 */
	(void) printf("%s\t%s\topen=%u active=%u\n",
	    pri->pname, mode,
	    au_pr->open,
	    au_pr->active);
}

void
show_audio_info(private_t *pri, long offset)
{
	struct audio_info au;

	if (Pread(Proc, &au, sizeof (au), offset) == sizeof (au)) {
		show_audio_prinfo(pri, "play", &au.play);
		show_audio_prinfo(pri, "record", &au.record);
		(void) printf("%s\tmonitor_gain=%u output_muted=%u\n",
		    pri->pname, au.monitor_gain, au.output_muted);
		show_audio_features(pri, audio_hw_features, au.hw_features,
		    "hw_features");
		show_audio_features(pri, audio_sw_features, au.sw_features,
		    "sw_features");
		show_audio_features(pri, audio_sw_features,
		    au.sw_features_enabled, "sw_features_enabled");
	}
}

void
show_ioctl(private_t *pri, int code, long offset)
{
	int lp64 = (data_model == PR_MODEL_LP64);
	int err = pri->Errno;	/* don't display output parameters */
				/* for a failed system call */
#ifndef _LP64
	if (lp64)
		return;
#endif
	if (offset == 0)
		return;

	switch (code) {
	case TCGETA:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TCSETA:
	case TCSETAW:
	case TCSETAF:
		show_termio(pri, offset);
		break;
	case TCGETS:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TCSETS:
	case TCSETSW:
	case TCSETSF:
		show_termios(pri, offset);
		break;
	case TCGETX:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TCSETX:
	case TCSETXW:
	case TCSETXF:
		show_termiox(pri, offset);
		break;
	case TIOCGETP:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TIOCSETN:
	case TIOCSETP:
		show_sgttyb(pri, offset);
		break;
	case TIOCGLTC:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TIOCSLTC:
		show_ltchars(pri, offset);
		break;
	case TIOCGETC:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TIOCSETC:
		show_tchars(pri, offset);
		break;
	case LDGETT:
		if (err)
			break;
		/*FALLTHROUGH*/
	case LDSETT:
		show_termcb(pri, offset);
		break;
	/* streams ioctl()s */
#if 0
		/* these are displayed as strings in the arg list */
		/* by prt_ioa().  don't display them again here */
	case I_PUSH:
	case I_LOOK:
	case I_FIND:
		/* these are displayed as decimal in the arg list */
		/* by prt_ioa().  don't display them again here */
	case I_LINK:
	case I_UNLINK:
	case I_SENDFD:
		/* these are displayed symbolically in the arg list */
		/* by prt_ioa().  don't display them again here */
	case I_SRDOPT:
	case I_SETSIG:
	case I_FLUSH:
		break;
		/* this one just ignores the argument */
	case I_POP:
		break;
#endif
		/* these return something in an int pointed to by arg */
	case I_NREAD:
	case I_GRDOPT:
	case I_GETSIG:
	case TIOCGSID:
	case TIOCGPGRP:
	case TIOCLGET:
	case FIONREAD:
	case FIORDCHK:
		if (err)
			break;
		/*FALLTHROUGH*/
		/* these pass something in an int pointed to by arg */
	case TIOCSPGRP:
	case TIOCFLUSH:
	case TIOCLBIS:
	case TIOCLBIC:
	case TIOCLSET:
		show_strint(pri, code, offset);
		break;
		/* these all point to structures */
	case I_STR:
#ifdef _LP64
		if (lp64)
			show_strioctl(pri, offset);
		else
			show_strioctl32(pri, offset);
#else
		show_strioctl(pri, offset);
#endif
		break;
	case I_PEEK:
#ifdef _LP64
		if (lp64)
			show_strpeek(pri, offset);
		else
			show_strpeek32(pri, offset);
#else
		show_strpeek(pri, offset);
#endif
		break;
	case I_FDINSERT:
#ifdef _LP64
		if (lp64)
			show_strfdinsert(pri, offset);
		else
			show_strfdinsert32(pri, offset);
#else
		show_strfdinsert(pri, offset);
#endif
		break;
	case I_RECVFD:
		if (err)
			break;
		show_strrecvfd(pri, offset);
		break;
	case I_LIST:
		if (err)
			break;
#ifdef _LP64
		if (lp64)
			show_strlist(pri, offset);
		else
			show_strlist32(pri, offset);
#else
		show_strlist(pri, offset);
#endif
		break;
	case JWINSIZE:
		if (err)
			break;
		show_jwinsize(pri, offset);
		break;
	case TIOCGWINSZ:
		if (err)
			break;
		/*FALLTHROUGH*/
	case TIOCSWINSZ:
		show_winsize(pri, offset);
		break;
	case AUDIO_GETINFO:
	case (int)AUDIO_SETINFO:
		show_audio_info(pri, offset);
		break;

	default:
		if (code & IOC_INOUT) {
			const char *str = ioctldatastruct(code);

			(void) printf("\t\t%s",
			    (code & IOC_INOUT) == IOC_INOUT ? "write/read" :
			    code & IOC_IN ? "write" : "read");
			if (str != NULL) {
				(void) printf(" (struct %s)\n", str);
			} else {
				(void) printf(" %d bytes\n",
				    (code >> 16) & IOCPARM_MASK);
			}
		}
	}
}

void
show_statvfs(private_t *pri)
{
	long offset;
	struct statvfs statvfs;
	char *cp;

	if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != NULL &&
	    Pread(Proc, &statvfs, sizeof (statvfs), offset)
	    == sizeof (statvfs)) {
		(void) printf(
		"%s\tbsize=%-10lu frsize=%-9lu blocks=%-8llu bfree=%-9llu\n",
		    pri->pname,
		    statvfs.f_bsize,
		    statvfs.f_frsize,
		    (u_longlong_t)statvfs.f_blocks,
		    (u_longlong_t)statvfs.f_bfree);
		(void) printf(
		"%s\tbavail=%-9llu files=%-10llu ffree=%-9llu favail=%-9llu\n",
		    pri->pname,
		    (u_longlong_t)statvfs.f_bavail,
		    (u_longlong_t)statvfs.f_files,
		    (u_longlong_t)statvfs.f_ffree,
		    (u_longlong_t)statvfs.f_favail);
		(void) printf(
		    "%s\tfsid=0x%-9.4lX basetype=%-7.16s namemax=%ld\n",
		    pri->pname,
		    statvfs.f_fsid,
		    statvfs.f_basetype,
		    (long)statvfs.f_namemax);
		(void) printf(
		    "%s\tflag=%s\n",
		    pri->pname,
		    svfsflags(pri, (ulong_t)statvfs.f_flag));
		cp = statvfs.f_fstr + strlen(statvfs.f_fstr);
		if (cp < statvfs.f_fstr + sizeof (statvfs.f_fstr) - 1 &&
		    *(cp+1) != '\0')
			*cp = ' ';
		(void) printf("%s\tfstr=\"%.*s\"\n",
		    pri->pname,
		    (int)sizeof (statvfs.f_fstr),
		    statvfs.f_fstr);
	}
}

#ifdef _LP64
void
show_statvfs32(private_t *pri)
{
	long offset;
	struct statvfs32 statvfs;
	char *cp;

	if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != NULL &&
	    Pread(Proc, &statvfs, sizeof (statvfs), offset)
	    == sizeof (statvfs)) {
		(void) printf(
		    "%s\tbsize=%-10u frsize=%-9u blocks=%-8u bfree=%-9u\n",
		    pri->pname,
		    statvfs.f_bsize,
		    statvfs.f_frsize,
		    statvfs.f_blocks,
		    statvfs.f_bfree);
		(void) printf(
		    "%s\tbavail=%-9u files=%-10u ffree=%-9u favail=%-9u\n",
		    pri->pname,
		    statvfs.f_bavail,
		    statvfs.f_files,
		    statvfs.f_ffree,
		    statvfs.f_favail);
		(void) printf(
		    "%s\tfsid=0x%-9.4X basetype=%-7.16s namemax=%d\n",
		    pri->pname,
		    statvfs.f_fsid,
		    statvfs.f_basetype,
		    (int)statvfs.f_namemax);
		(void) printf(
		    "%s\tflag=%s\n",
		    pri->pname,
		    svfsflags(pri, (ulong_t)statvfs.f_flag));
		cp = statvfs.f_fstr + strlen(statvfs.f_fstr);
		if (cp < statvfs.f_fstr + sizeof (statvfs.f_fstr) - 1 &&
		    *(cp+1) != '\0')
			*cp = ' ';
		(void) printf("%s\tfstr=\"%.*s\"\n",
		    pri->pname,
		    (int)sizeof (statvfs.f_fstr),
		    statvfs.f_fstr);
	}
}
#endif	/* _LP64 */

void
show_statvfs64(private_t *pri)
{
	long offset;
	struct statvfs64_32 statvfs;
	char *cp;

	if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != NULL &&
	    Pread(Proc, &statvfs, sizeof (statvfs), offset)
	    == sizeof (statvfs)) {
		(void) printf(
		    "%s\tbsize=%-10u frsize=%-9u blocks=%-8llu bfree=%-9llu\n",
		    pri->pname,
		    statvfs.f_bsize,
		    statvfs.f_frsize,
		    (u_longlong_t)statvfs.f_blocks,
		    (u_longlong_t)statvfs.f_bfree);
		(void) printf(
		"%s\tbavail=%-9llu files=%-10llu ffree=%-9llu favail=%-9llu\n",
		    pri->pname,
		    (u_longlong_t)statvfs.f_bavail,
		    (u_longlong_t)statvfs.f_files,
		    (u_longlong_t)statvfs.f_ffree,
		    (u_longlong_t)statvfs.f_favail);
		(void) printf(
		    "%s\tfsid=0x%-9.4X basetype=%-7.16s namemax=%d\n",
		    pri->pname,
		    statvfs.f_fsid,
		    statvfs.f_basetype,
		    (int)statvfs.f_namemax);
		(void) printf(
		    "%s\tflag=%s\n",
		    pri->pname,
		    svfsflags(pri, (ulong_t)statvfs.f_flag));
		cp = statvfs.f_fstr + strlen(statvfs.f_fstr);
		if (cp < statvfs.f_fstr + sizeof (statvfs.f_fstr) - 1 &&
		    *(cp+1) != '\0')
			*cp = ' ';
		(void) printf("%s\tfstr=\"%.*s\"\n",
		    pri->pname,
		    (int)sizeof (statvfs.f_fstr),
		    statvfs.f_fstr);
	}
}

void
show_statfs(private_t *pri)
{
	long offset;
	struct statfs statfs;

	if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL &&
	    Pread(Proc, &statfs, sizeof (statfs), offset) == sizeof (statfs)) {
		(void) printf(
		"%s\tfty=%d bsz=%ld fsz=%ld blk=%ld bfr=%ld fil=%lu ffr=%lu\n",
		    pri->pname,
		    statfs.f_fstyp,
		    statfs.f_bsize,
		    statfs.f_frsize,
		    statfs.f_blocks,
		    statfs.f_bfree,
		    statfs.f_files,
		    statfs.f_ffree);
		(void) printf("%s\t    fname=%.6s fpack=%.6s\n",
		    pri->pname,
		    statfs.f_fname,
		    statfs.f_fpack);
	}
}

#ifdef _LP64
void
show_statfs32(private_t *pri)
{
	long offset;
	struct statfs32 statfs;

	if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL &&
	    Pread(Proc, &statfs, sizeof (statfs), offset) == sizeof (statfs)) {
		(void) printf(
		    "%s\tfty=%d bsz=%d fsz=%d blk=%d bfr=%d fil=%u ffr=%u\n",
		    pri->pname,
		    statfs.f_fstyp,
		    statfs.f_bsize,
		    statfs.f_frsize,
		    statfs.f_blocks,
		    statfs.f_bfree,
		    statfs.f_files,
		    statfs.f_ffree);
		(void) printf("%s\t    fname=%.6s fpack=%.6s\n",
		    pri->pname,
		    statfs.f_fname,
		    statfs.f_fpack);
	}
}
#endif	/* _LP64 */

void
show_flock32(private_t *pri, long offset)
{
	struct flock32 flock;

	if (Pread(Proc, &flock, sizeof (flock), offset) == sizeof (flock)) {
		const char *str = NULL;

		(void) printf("%s\ttyp=", pri->pname);

		switch (flock.l_type) {
		case F_RDLCK:
			str = "F_RDLCK";
			break;
		case F_WRLCK:
			str = "F_WRLCK";
			break;
		case F_UNLCK:
			str = "F_UNLCK";
			break;
		}
		if (str != NULL)
			(void) printf("%s", str);
		else
			(void) printf("%-7d", flock.l_type);

		str = whencearg(flock.l_whence);
		if (str != NULL)
			(void) printf("  whence=%s", str);
		else
			(void) printf("  whence=%-8u", flock.l_whence);

		(void) printf(
		    " start=%-5d len=%-5d sys=%-2u pid=%d\n",
		    flock.l_start,
		    flock.l_len,
		    flock.l_sysid,
		    flock.l_pid);
	}
}

void
show_flock64(private_t *pri, long offset)
{
	struct flock64 flock;

	if (Pread(Proc, &flock, sizeof (flock), offset) == sizeof (flock)) {
		const char *str = NULL;

		(void) printf("%s\ttyp=", pri->pname);

		switch (flock.l_type) {
		case F_RDLCK:
			str = "F_RDLCK";
			break;
		case F_WRLCK:
			str = "F_WRLCK";
			break;
		case F_UNLCK:
			str = "F_UNLCK";
			break;
		}
		if (str != NULL)
			(void) printf("%s", str);
		else
			(void) printf("%-7d", flock.l_type);

		str = whencearg(flock.l_whence);
		if (str != NULL)
			(void) printf("  whence=%s", str);
		else
			(void) printf("  whence=%-8u", flock.l_whence);

		(void) printf(
		    " start=%-5lld len=%-5lld sys=%-2u pid=%d\n",
		    (long long)flock.l_start,
		    (long long)flock.l_len,
		    flock.l_sysid,
		    (int)flock.l_pid);
	}
}

void
show_share(private_t *pri, long offset)
{
	struct fshare fshare;

	if (Pread(Proc, &fshare, sizeof (fshare), offset) == sizeof (fshare)) {
		const char *str = NULL;
		int manddny = 0;

		(void) printf("%s\taccess=", pri->pname);

		switch (fshare.f_access) {
		case F_RDACC:
			str = "F_RDACC";
			break;
		case F_WRACC:
			str = "F_WRACC";
			break;
		case F_RWACC:
			str = "F_RWACC";
			break;
		}
		if (str != NULL)
			(void) printf("%s", str);
		else
			(void) printf("%-7d", fshare.f_access);

		str = NULL;
		if (fshare.f_deny & F_MANDDNY) {
			fshare.f_deny &= ~F_MANDDNY;
			manddny = 1;
		}
		switch (fshare.f_deny) {
		case F_NODNY:
			str = "F_NODNY";
			break;
		case F_RDDNY:
			str = "F_RDDNY";
			break;
		case F_WRDNY:
			str = "F_WRDNY";
			break;
		case F_RWDNY:
			str = "F_RWDNY";
			break;
		case F_COMPAT:
			str = "F_COMPAT";
			break;
		}
		if (str != NULL) {
			if (manddny)
				(void) printf("  deny=F_MANDDNY|%s", str);
			else
				(void) printf("  deny=%s", str);
		} else {
			(void) printf("  deny=0x%x", manddny?
			    fshare.f_deny | F_MANDDNY : fshare.f_deny);
		}

		(void) printf("  id=%x\n", fshare.f_id);
	}
}

void
show_ffg(private_t *pri)
{
	(void) putchar('\t');
	(void) putchar('\t');
	prt_ffg(pri, 0, pri->Rval1);
	(void) puts(pri->sys_string);
}

/* print values in fcntl() pointed-to structure */
void
show_fcntl(private_t *pri)
{
	long offset;

	if (pri->sys_nargs >= 2 && pri->sys_args[1] == F_GETFL) {
		show_ffg(pri);
		return;
	}

	if (pri->sys_nargs < 3 || (offset = pri->sys_args[2]) == NULL)
		return;

	switch (pri->sys_args[1]) {
#ifdef _LP64
	case F_GETLK:
	case F_SETLK:
	case F_SETLKW:
	case F_FREESP:
	case F_ALLOCSP:
	case F_SETLK_NBMAND:
		if (data_model == PR_MODEL_LP64)
			show_flock64(pri, offset);
		else
			show_flock32(pri, offset);
		break;
	case 33:	/* F_GETLK64 */
	case 34:	/* F_SETLK64 */
	case 35:	/* F_SETLKW64 */
	case 27:	/* F_FREESP64 */
	case 28:	/* F_ALLOCSP64 */
	case 44:	/* F_SETLK64_NBMAND */
		show_flock64(pri, offset);
		break;
#else	/* _LP64 */
	case F_GETLK:
	case F_SETLK:
	case F_SETLKW:
	case F_FREESP:
	case F_ALLOCSP:
	case F_SETLK_NBMAND:
		show_flock32(pri, offset);
		break;
	case F_GETLK64:
	case F_SETLK64:
	case F_SETLKW64:
	case F_FREESP64:
	case F_ALLOCSP64:
	case F_SETLK64_NBMAND:
		show_flock64(pri, offset);
		break;
#endif	/* _LP64 */
	case F_SHARE:
	case F_UNSHARE:
		show_share(pri, offset);
		break;
	}
}

void
show_strbuf(private_t *pri, long offset, const char *name, int dump)
{
	struct strbuf strbuf;

	if (Pread(Proc, &strbuf, sizeof (strbuf), offset) == sizeof (strbuf))
		print_strbuf(pri, &strbuf, name, dump);
}

#ifdef _LP64
void
show_strbuf32(private_t *pri, long offset, const char *name, int dump)
{
	struct strbuf32 strbuf;

	if (Pread(Proc, &strbuf, sizeof (strbuf), offset) == sizeof (strbuf))
		print_strbuf32(pri, &strbuf, name, dump);
}
#endif	/* _LP64 */

void
show_gp_msg(private_t *pri, int what)
{
	long offset;
	int dump = FALSE;
	int fdp1 = pri->sys_args[0] + 1;

	switch (what) {
	case SYS_getmsg:
	case SYS_getpmsg:
		if (pri->Errno == 0 && prismember(&readfd, fdp1))
			dump = TRUE;
		break;
	case SYS_putmsg:
	case SYS_putpmsg:
		if (prismember(&writefd, fdp1))
			dump = TRUE;
		break;
	}

	/* enter region of lengthy output */
	if (dump)
		Eserialize();

#ifdef _LP64
	if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL) {
		if (data_model == PR_MODEL_LP64)
			show_strbuf(pri, offset, "ctl", dump);
		else
			show_strbuf32(pri, offset, "ctl", dump);
	}
	if (pri->sys_nargs >= 3 && (offset = pri->sys_args[2]) != NULL) {
		if (data_model == PR_MODEL_LP64)
			show_strbuf(pri, offset, "dat", dump);
		else
			show_strbuf32(pri, offset, "dat", dump);
	}
#else	/* _LP64 */
	if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL)
		show_strbuf(pri, offset, "ctl", dump);
	if (pri->sys_nargs >= 3 && (offset = pri->sys_args[2]) != NULL)
		show_strbuf(pri, offset, "dat", dump);
#endif	/* _LP64 */

	/* exit region of lengthy output */
	if (dump)
		Xserialize();
}

void
show_int(private_t *pri, long offset, const char *name)
{
	int value;

	if (offset != 0 &&
	    Pread(Proc, &value, sizeof (value), offset) == sizeof (value))
		(void) printf("%s\t%s:\t%d\n",
		    pri->pname,
		    name,
		    value);
}

void
show_hhex_int(private_t *pri, long offset, const char *name)
{
	int value;

	if (Pread(Proc, &value, sizeof (value), offset) == sizeof (value))
		(void) printf("%s\t%s:\t0x%.4X\n",
		    pri->pname,
		    name,
		    value);
}

#define	ALL_POLL_FLAGS	(POLLIN|POLLPRI|POLLOUT| \
	POLLRDNORM|POLLRDBAND|POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)

const char *
pollevent(private_t *pri, int arg)
{
	char *str = pri->code_buf;

	if (arg == 0)
		return ("0");
	if (arg & ~ALL_POLL_FLAGS) {
		(void) sprintf(str, "0x%-5X", arg);
		return ((const char *)str);
	}

	*str = '\0';
	if (arg & POLLIN)
		(void) strcat(str, "|POLLIN");
	if (arg & POLLPRI)
		(void) strcat(str, "|POLLPRI");
	if (arg & POLLOUT)
		(void) strcat(str, "|POLLOUT");
	if (arg & POLLRDNORM)
		(void) strcat(str, "|POLLRDNORM");
	if (arg & POLLRDBAND)
		(void) strcat(str, "|POLLRDBAND");
	if (arg & POLLWRBAND)
		(void) strcat(str, "|POLLWRBAND");
	if (arg & POLLERR)
		(void) strcat(str, "|POLLERR");
	if (arg & POLLHUP)
		(void) strcat(str, "|POLLHUP");
	if (arg & POLLNVAL)
		(void) strcat(str, "|POLLNVAL");

	return ((const char *)(str+1));
}

static void
show_one_pollfd(private_t *pri, struct pollfd *ppollfd)
{
	/*
	 * can't print both events and revents in same printf.
	 * pollevent() returns a pointer to a TSD location.
	 */
	(void) printf("%s\tfd=%-2d ev=%s",
	    pri->pname, ppollfd->fd, pollevent(pri, ppollfd->events));
	(void) printf(" rev=%s\n", pollevent(pri, ppollfd->revents));
}

static void
show_all_pollfds(private_t *pri, long offset, int nfds)
{
	struct pollfd pollfd[2];
	int skip = -1;

	for (; nfds && !interrupt; nfds--, offset += sizeof (struct pollfd)) {
		if (Pread(Proc, &pollfd[0], sizeof (struct pollfd), offset) !=
		    sizeof (struct pollfd))
			continue;

		if (skip >= 0 && pollfd[0].fd == pollfd[1].fd &&
		    pollfd[0].events == pollfd[1].events &&
		    pollfd[0].revents == pollfd[1].revents) {
			skip++;
			continue;
		}

		if (skip > 0)
			(void) printf("%s\t...last pollfd structure"
			    " repeated %d time%s...\n",
			    pri->pname, skip, (skip == 1 ? "" : "s"));

		skip = 0;
		show_one_pollfd(pri, &pollfd[0]);
		pollfd[1] = pollfd[0];
	}

	if (skip > 0)
		(void) printf(
		    "%s\t...last pollfd structure repeated %d time%s...\n",
		    pri->pname, skip, (skip == 1 ? "" : "s"));
}

void
show_pollsys(private_t *pri)
{
	long offset;
	int nfds;
	int serial = 0;

	if (pri->sys_nargs < 2)
		return;

	offset = pri->sys_args[0];
	nfds = pri->sys_args[1];

	/* enter region of lengthy output */
	if (offset != NULL && nfds > 32) {
		Eserialize();
		serial = 1;
	}

	if (offset != NULL && nfds > 0)
		show_all_pollfds(pri, offset, nfds);

	if (pri->sys_nargs > 2)
		show_timestruc(pri, (long)pri->sys_args[2], "timeout");

	if (pri->sys_nargs > 3)
		show_sigset(pri, (long)pri->sys_args[3], "sigmask");

	/* exit region of lengthy output */
	if (serial)
		Xserialize();
}

static void
show_perm64(private_t *pri, struct ipc_perm64 *ip)
{
	(void) printf("%s\tu=%-5u g=%-5u cu=%-5u cg=%-5u z=%-5d "
	    "m=0%.6o key=%d projid=%-5d\n",
	    pri->pname,
	    ip->ipcx_uid,
	    ip->ipcx_gid,
	    ip->ipcx_cuid,
	    ip->ipcx_cgid,
	    (int)ip->ipcx_zoneid,
	    (unsigned int)ip->ipcx_mode,
	    ip->ipcx_key,
	    (int)ip->ipcx_projid);
}

void
show_perm(private_t *pri, struct ipc_perm *ip)
{
	(void) printf(
	    "%s\tu=%-5u g=%-5u cu=%-5u cg=%-5u m=0%.6o seq=%u key=%d\n",
	    pri->pname,
	    ip->uid,
	    ip->gid,
	    ip->cuid,
	    ip->cgid,
	    (int)ip->mode,
	    ip->seq,
	    ip->key);
}

#ifdef _LP64
void
show_perm32(private_t *pri, struct ipc_perm32 *ip)
{
	(void) printf(
	    "%s\tu=%-5u g=%-5u cu=%-5u cg=%-5u m=0%.6o seq=%u key=%d\n",
	    pri->pname,
	    ip->uid,
	    ip->gid,
	    ip->cuid,
	    ip->cgid,
	    ip->mode,
	    ip->seq,
	    ip->key);
}
#endif	/* _LP64 */

static void
show_msgctl64(private_t *pri, long offset)
{
	struct msqid_ds64 msgq;

	if (offset != NULL &&
	    Pread(Proc, &msgq, sizeof (msgq), offset) == sizeof (msgq)) {
		show_perm64(pri, &msgq.msgx_perm);

		(void) printf("%s\tbytes=%-5llu msgs=%-5llu maxby=%-5llu "
		    "lspid=%-5d lrpid=%-5d\n", pri->pname,
		    (unsigned long long)msgq.msgx_cbytes,
		    (unsigned long long)msgq.msgx_qnum,
		    (unsigned long long)msgq.msgx_qbytes,
		    (int)msgq.msgx_lspid,
		    (int)msgq.msgx_lrpid);

		prtime(pri, "    st = ", (time_t)msgq.msgx_stime);
		prtime(pri, "    rt = ", (time_t)msgq.msgx_rtime);
		prtime(pri, "    ct = ", (time_t)msgq.msgx_ctime);
	}
}

void
show_msgctl(private_t *pri, long offset)
{
	struct msqid_ds msgq;

	if (offset != NULL &&
	    Pread(Proc, &msgq, sizeof (msgq), offset) == sizeof (msgq)) {
		show_perm(pri, &msgq.msg_perm);

		(void) printf(
	"%s\tbytes=%-5lu msgs=%-5lu maxby=%-5lu lspid=%-5u lrpid=%-5u\n",
		    pri->pname,
		    msgq.msg_cbytes,
		    msgq.msg_qnum,
		    msgq.msg_qbytes,
		    (int)msgq.msg_lspid,
		    (int)msgq.msg_lrpid);

		prtime(pri, "    st = ", msgq.msg_stime);
		prtime(pri, "    rt = ", msgq.msg_rtime);
		prtime(pri, "    ct = ", msgq.msg_ctime);
	}
}

#ifdef _LP64
void
show_msgctl32(private_t *pri, long offset)
{
	struct msqid_ds32 msgq;

	if (offset != NULL &&
	    Pread(Proc, &msgq, sizeof (msgq), offset) == sizeof (msgq)) {
		show_perm32(pri, &msgq.msg_perm);

		(void) printf(
	"%s\tbytes=%-5u msgs=%-5u maxby=%-5u lspid=%-5u lrpid=%-5u\n",
		    pri->pname,
		    msgq.msg_cbytes,
		    msgq.msg_qnum,
		    msgq.msg_qbytes,
		    msgq.msg_lspid,
		    msgq.msg_lrpid);

		prtime(pri, "    st = ", msgq.msg_stime);
		prtime(pri, "    rt = ", msgq.msg_rtime);
		prtime(pri, "    ct = ", msgq.msg_ctime);
	}
}
#endif	/* _LP64 */

void
show_msgbuf(private_t *pri, long offset, long msgsz)
{
	struct msgbuf msgb;

	if (offset != NULL &&
	    Pread(Proc, &msgb, sizeof (msgb.mtype), offset) ==
	    sizeof (msgb.mtype)) {
		/* enter region of lengthy output */
		if (msgsz > MYBUFSIZ / 4)
			Eserialize();

		(void) printf("%s\tmtype=%lu  mtext[]=\n",
		    pri->pname,
		    msgb.mtype);
		showbuffer(pri,
		    (long)(offset + sizeof (msgb.mtype)), msgsz);

		/* exit region of lengthy output */
		if (msgsz > MYBUFSIZ / 4)
			Xserialize();
	}
}

#ifdef _LP64
void
show_msgbuf32(private_t *pri, long offset, long msgsz)
{
	struct ipcmsgbuf32 msgb;

	if (offset != NULL &&
	    Pread(Proc, &msgb, sizeof (msgb.mtype), offset) ==
	    sizeof (msgb.mtype)) {
		/* enter region of lengthy output */
		if (msgsz > MYBUFSIZ / 4)
			Eserialize();

		(void) printf("%s\tmtype=%u  mtext[]=\n",
		    pri->pname,
		    msgb.mtype);
		showbuffer(pri,
		    (long)(offset + sizeof (msgb.mtype)), msgsz);

		/* exit region of lengthy output */
		if (msgsz > MYBUFSIZ / 4)
			Xserialize();
	}
}
#endif	/* _LP64 */

#ifdef _LP64
void
show_msgsys(private_t *pri, long msgsz)
{
	switch (pri->sys_args[0]) {
	case 0:			/* msgget() */
		break;
	case 1:			/* msgctl() */
		if (pri->sys_nargs > 3) {
			switch (pri->sys_args[2]) {
			case IPC_STAT:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET:
				if (data_model == PR_MODEL_LP64)
					show_msgctl(pri,
					    (long)pri->sys_args[3]);
				else
					show_msgctl32(pri,
					    (long)pri->sys_args[3]);
				break;
			case IPC_STAT64:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET64:
				show_msgctl64(pri, (long)pri->sys_args[3]);
				break;
			}
		}
		break;
	case 2:			/* msgrcv() */
		if (!pri->Errno && pri->sys_nargs > 2) {
			if (data_model == PR_MODEL_LP64)
				show_msgbuf(pri, pri->sys_args[2], msgsz);
			else
				show_msgbuf32(pri, pri->sys_args[2], msgsz);
		}
		break;
	case 3:			/* msgsnd() */
		if (pri->sys_nargs > 3) {
			if (data_model == PR_MODEL_LP64)
				show_msgbuf(pri, pri->sys_args[2],
				    pri->sys_args[3]);
			else
				show_msgbuf32(pri, pri->sys_args[2],
				    pri->sys_args[3]);
		}
		break;
	case 4:			/* msgids() */
	case 5:			/* msgsnap() */
	default:		/* unexpected subcode */
		break;
	}
}
#else	/* _LP64 */
void
show_msgsys(private_t *pri, long msgsz)
{
	switch (pri->sys_args[0]) {
	case 0:			/* msgget() */
		break;
	case 1:			/* msgctl() */
		if (pri->sys_nargs > 3) {
			switch (pri->sys_args[2]) {
			case IPC_STAT:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET:
				show_msgctl(pri, (long)pri->sys_args[3]);
				break;
			case IPC_STAT64:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET64:
				show_msgctl64(pri, (long)pri->sys_args[3]);
				break;
			}
		}
		break;
	case 2:			/* msgrcv() */
		if (!pri->Errno && pri->sys_nargs > 2)
			show_msgbuf(pri, pri->sys_args[2], msgsz);
		break;
	case 3:			/* msgsnd() */
		if (pri->sys_nargs > 3)
			show_msgbuf(pri, pri->sys_args[2],
			    pri->sys_args[3]);
		break;
	case 4:			/* msgids() */
	case 5:			/* msgsnap() */
	default:		/* unexpected subcode */
		break;
	}
}
#endif	/* _LP64 */

static void
show_semctl64(private_t *pri, long offset)
{
	struct semid_ds64 semds;

	if (offset != NULL &&
	    Pread(Proc, &semds, sizeof (semds), offset) == sizeof (semds)) {
		show_perm64(pri, &semds.semx_perm);

		(void) printf("%s\tnsems=%u\n", pri->pname, semds.semx_nsems);

		prtime(pri, "    ot = ", (time_t)semds.semx_otime);
		prtime(pri, "    ct = ", (time_t)semds.semx_ctime);
	}
}

void
show_semctl(private_t *pri, long offset)
{
	struct semid_ds semds;

	if (offset != NULL &&
	    Pread(Proc, &semds, sizeof (semds), offset) == sizeof (semds)) {
		show_perm(pri, &semds.sem_perm);

		(void) printf("%s\tnsems=%u\n",
		    pri->pname,
		    semds.sem_nsems);

		prtime(pri, "    ot = ", semds.sem_otime);
		prtime(pri, "    ct = ", semds.sem_ctime);
	}
}

#ifdef _LP64
void
show_semctl32(private_t *pri, long offset)
{
	struct semid_ds32 semds;

	if (offset != NULL &&
	    Pread(Proc, &semds, sizeof (semds), offset) == sizeof (semds)) {
		show_perm32(pri, &semds.sem_perm);

		(void) printf("%s\tnsems=%u\n",
		    pri->pname,
		    semds.sem_nsems);

		prtime(pri, "    ot = ", semds.sem_otime);
		prtime(pri, "    ct = ", semds.sem_ctime);
	}
}
#endif	/* _LP64 */

void
show_semop(private_t *pri, long offset, long nsops, long timeout)
{
	struct sembuf sembuf;
	const char *str;

	if (offset == 0)
		return;

	if (nsops > 40)		/* let's not be ridiculous */
		nsops = 40;

	for (; nsops > 0 && !interrupt; --nsops, offset += sizeof (sembuf)) {
		if (Pread(Proc, &sembuf, sizeof (sembuf), offset) !=
		    sizeof (sembuf))
			break;

		(void) printf("%s\tsemnum=%-5u semop=%-5d semflg=",
		    pri->pname,
		    sembuf.sem_num,
		    sembuf.sem_op);

		if (sembuf.sem_flg == 0)
			(void) printf("0\n");
		else if ((str = semflags(pri, sembuf.sem_flg)) != NULL)
			(void) printf("%s\n", str);
		else
			(void) printf("0%.6o\n", sembuf.sem_flg);
	}
	if (timeout)
		show_timestruc(pri, timeout, "timeout");
}

void
show_semsys(private_t *pri)
{
	switch (pri->sys_args[0]) {
	case 0:			/* semctl() */
		if (pri->sys_nargs > 4) {
			switch (pri->sys_args[3]) {
			case IPC_STAT:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET:
#ifdef _LP64
				if (data_model == PR_MODEL_LP64)
					show_semctl(pri,
					    (long)pri->sys_args[4]);
				else
					show_semctl32(pri,
					    (long)pri->sys_args[4]);
#else
				show_semctl(pri, (long)pri->sys_args[4]);
#endif
				break;
			case IPC_STAT64:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET64:
				show_semctl64(pri, (long)pri->sys_args[4]);
				break;
			}
		}
		break;
	case 1:			/* semget() */
		break;
	case 2:			/* semop() */
		if (pri->sys_nargs > 3)
			show_semop(pri, (long)pri->sys_args[2],
			    pri->sys_args[3], 0);
		break;
	case 3:			/* semids() */
		break;
	case 4:			/* semtimedop() */
		if (pri->sys_nargs > 4)
			show_semop(pri, (long)pri->sys_args[2],
			    pri->sys_args[3], pri->sys_args[4]);
		break;
	default:		/* unexpected subcode */
		break;
	}
}

static void
show_shmctl64(private_t *pri, long offset)
{
	struct shmid_ds64 shmds;

	if (offset != NULL &&
	    Pread(Proc, &shmds, sizeof (shmds), offset) == sizeof (shmds)) {
		show_perm64(pri, &shmds.shmx_perm);

		(void) printf(
		    "%s\tsize=%-6llu lpid=%-5d cpid=%-5d na=%-5llu cna=%llu\n",
		    pri->pname,
		    (unsigned long long)shmds.shmx_segsz,
		    (int)shmds.shmx_lpid,
		    (int)shmds.shmx_cpid,
		    (unsigned long long)shmds.shmx_nattch,
		    (unsigned long long)shmds.shmx_cnattch);

		prtime(pri, "    at = ", (time_t)shmds.shmx_atime);
		prtime(pri, "    dt = ", (time_t)shmds.shmx_dtime);
		prtime(pri, "    ct = ", (time_t)shmds.shmx_ctime);
	}
}

void
show_shmctl(private_t *pri, long offset)
{
	struct shmid_ds shmds;

	if (offset != NULL &&
	    Pread(Proc, &shmds, sizeof (shmds), offset) == sizeof (shmds)) {
		show_perm(pri, &shmds.shm_perm);

		(void) printf(
		    "%s\tsize=%-6lu lpid=%-5u cpid=%-5u na=%-5lu cna=%lu\n",
		    pri->pname,
		    (ulong_t)shmds.shm_segsz,
		    (int)shmds.shm_lpid,
		    (int)shmds.shm_cpid,
		    shmds.shm_nattch,
		    shmds.shm_cnattch);

		prtime(pri, "    at = ", shmds.shm_atime);
		prtime(pri, "    dt = ", shmds.shm_dtime);
		prtime(pri, "    ct = ", shmds.shm_ctime);
	}
}

#ifdef _LP64
void
show_shmctl32(private_t *pri, long offset)
{
	struct shmid_ds32 shmds;

	if (offset != NULL &&
	    Pread(Proc, &shmds, sizeof (shmds), offset) == sizeof (shmds)) {
		show_perm32(pri, &shmds.shm_perm);

		(void) printf(
		    "%s\tsize=%-6u lpid=%-5u cpid=%-5u na=%-5u cna=%u\n",
		    pri->pname,
		    shmds.shm_segsz,
		    shmds.shm_lpid,
		    shmds.shm_cpid,
		    shmds.shm_nattch,
		    shmds.shm_cnattch);

		prtime(pri, "    at = ", shmds.shm_atime);
		prtime(pri, "    dt = ", shmds.shm_dtime);
		prtime(pri, "    ct = ", shmds.shm_ctime);
	}
}
#endif	/* _LP64 */

void
show_shmsys(private_t *pri)
{
	switch (pri->sys_args[0]) {
	case 0:			/* shmat() */
		break;
	case 1:			/* shmctl() */
		if (pri->sys_nargs > 3) {
			switch (pri->sys_args[2]) {
			case IPC_STAT:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET:
#ifdef _LP64
				if (data_model == PR_MODEL_LP64)
					show_shmctl(pri,
					    (long)pri->sys_args[3]);
				else
					show_shmctl32(pri,
					    (long)pri->sys_args[3]);
#else
				show_shmctl(pri, (long)pri->sys_args[3]);
#endif
				break;
			case IPC_STAT64:
				if (pri->Errno)
					break;
				/*FALLTHROUGH*/
			case IPC_SET64:
				show_shmctl64(pri, (long)pri->sys_args[3]);
				break;
			}
		}
		break;
	case 2:			/* shmdt() */
	case 3:			/* shmget() */
	case 4:			/* shmids() */
	default:		/* unexpected subcode */
		break;
	}
}

void
show_groups(private_t *pri, long offset, long count)
{
	int groups[100];

	if (count > 100)
		count = 100;

	if (count > 0 && offset != NULL &&
	    Pread(Proc, &groups[0], count*sizeof (int), offset) ==
	    count*sizeof (int)) {
		int n;

		(void) printf("%s\t", pri->pname);
		for (n = 0; !interrupt && n < count; n++) {
			if (n != 0 && n%10 == 0)
				(void) printf("\n%s\t", pri->pname);
			(void) printf(" %5d", groups[n]);
		}
		(void) fputc('\n', stdout);
	}
}

/*
 * This assumes that a sigset_t is simply an array of ints.
 */
char *
sigset_string(private_t *pri, sigset_t *sp)
{
	char *s = pri->code_buf;
	int n = sizeof (*sp) / sizeof (int32_t);
	int32_t *lp = (int32_t *)sp;

	while (--n >= 0) {
		int32_t val = *lp++;

		if (val == 0)
			s += sprintf(s, " 0");
		else
			s += sprintf(s, " 0x%.8X", val);
	}

	return (pri->code_buf);
}

void
show_sigset(private_t *pri, long offset, const char *name)
{
	sigset_t sigset;

	if (offset != NULL &&
	    Pread(Proc, &sigset, sizeof (sigset), offset) == sizeof (sigset)) {
		(void) printf("%s\t%s =%s\n",
		    pri->pname, name, sigset_string(pri, &sigset));
	}
}

#ifdef _LP64
void
show_sigaltstack32(private_t *pri, long offset, const char *name)
{
	struct sigaltstack32 altstack;

	if (offset != NULL &&
	    Pread(Proc, &altstack, sizeof (altstack), offset) ==
	    sizeof (altstack)) {
		(void) printf("%s\t%s: sp=0x%.8X size=%u flags=0x%.4X\n",
		    pri->pname,
		    name,
		    altstack.ss_sp,
		    altstack.ss_size,
		    altstack.ss_flags);
	}
}
#endif	/* _LP64 */

void
show_sigaltstack(private_t *pri, long offset, const char *name)
{
	struct sigaltstack altstack;

#ifdef _LP64
	if (data_model != PR_MODEL_LP64) {
		show_sigaltstack32(pri, offset, name);
		return;
	}
#endif
	if (offset != NULL &&
	    Pread(Proc, &altstack, sizeof (altstack), offset) ==
	    sizeof (altstack)) {
		(void) printf("%s\t%s: sp=0x%.8lX size=%lu flags=0x%.4X\n",
		    pri->pname,
		    name,
		    (ulong_t)altstack.ss_sp,
		    (ulong_t)altstack.ss_size,
		    altstack.ss_flags);
	}
}

#ifdef _LP64
void
show_sigaction32(private_t *pri, long offset, const char *name, long odisp)
{
	struct sigaction32 sigaction;

	if (offset != NULL &&
	    Pread(Proc, &sigaction, sizeof (sigaction), offset) ==
	    sizeof (sigaction)) {
		/* This is stupid, we shouldn't have to do this */
		if (odisp != NULL)
			sigaction.sa_handler = (caddr32_t)odisp;
		(void) printf(
		    "%s    %s: hand = 0x%.8X mask =%s flags = 0x%.4X\n",
		    pri->pname,
		    name,
		    sigaction.sa_handler,
		    sigset_string(pri, (sigset_t *)&sigaction.sa_mask),
		    sigaction.sa_flags);
	}
}
#endif	/* _LP64 */

void
show_sigaction(private_t *pri, long offset, const char *name, long odisp)
{
	struct sigaction sigaction;

#ifdef _LP64
	if (data_model != PR_MODEL_LP64) {
		show_sigaction32(pri, offset, name, odisp);
		return;
	}
#endif
	if (offset != NULL &&
	    Pread(Proc, &sigaction, sizeof (sigaction), offset) ==
	    sizeof (sigaction)) {
		/* This is stupid, we shouldn't have to do this */
		if (odisp != NULL)
			sigaction.sa_handler = (void (*)())odisp;
		(void) printf(
		    "%s    %s: hand = 0x%.8lX mask =%s flags = 0x%.4X\n",
		    pri->pname,
		    name,
		    (long)sigaction.sa_handler,
		    sigset_string(pri, &sigaction.sa_mask),
		    sigaction.sa_flags);
	}
}

#ifdef _LP64
void
print_siginfo32(private_t *pri, const siginfo32_t *sip)
{
	const char *code = NULL;

	(void) printf("%s      siginfo: %s", pri->pname,
	    signame(pri, sip->si_signo));

	if (sip->si_signo != 0 && SI_FROMUSER(sip) && sip->si_pid != 0) {
		(void) printf(" pid=%d uid=%d", sip->si_pid, sip->si_uid);
		if (sip->si_code != 0)
			(void) printf(" code=%d", sip->si_code);
		(void) fputc('\n', stdout);
		return;
	}

	switch (sip->si_signo) {
	default:
		(void) fputc('\n', stdout);
		return;
	case SIGILL:
	case SIGTRAP:
	case SIGFPE:
	case SIGSEGV:
	case SIGBUS:
	case SIGEMT:
	case SIGCLD:
	case SIGPOLL:
	case SIGXFSZ:
		break;
	}

	switch (sip->si_signo) {
	case SIGILL:
		switch (sip->si_code) {
		case ILL_ILLOPC:	code = "ILL_ILLOPC";	break;
		case ILL_ILLOPN:	code = "ILL_ILLOPN";	break;
		case ILL_ILLADR:	code = "ILL_ILLADR";	break;
		case ILL_ILLTRP:	code = "ILL_ILLTRP";	break;
		case ILL_PRVOPC:	code = "ILL_PRVOPC";	break;
		case ILL_PRVREG:	code = "ILL_PRVREG";	break;
		case ILL_COPROC:	code = "ILL_COPROC";	break;
		case ILL_BADSTK:	code = "ILL_BADSTK";	break;
		}
		break;
	case SIGTRAP:
		switch (sip->si_code) {
		case TRAP_BRKPT:	code = "TRAP_BRKPT";	break;
		case TRAP_TRACE:	code = "TRAP_TRACE";	break;
		case TRAP_RWATCH:	code = "TRAP_RWATCH";	break;
		case TRAP_WWATCH:	code = "TRAP_WWATCH";	break;
		case TRAP_XWATCH:	code = "TRAP_XWATCH";	break;
		case TRAP_DTRACE:	code = "TRAP_DTRACE";	break;
		}
		break;
	case SIGFPE:
		switch (sip->si_code) {
		case FPE_INTDIV:	code = "FPE_INTDIV";	break;
		case FPE_INTOVF:	code = "FPE_INTOVF";	break;
		case FPE_FLTDIV:	code = "FPE_FLTDIV";	break;
		case FPE_FLTOVF:	code = "FPE_FLTOVF";	break;
		case FPE_FLTUND:	code = "FPE_FLTUND";	break;
		case FPE_FLTRES:	code = "FPE_FLTRES";	break;
		case FPE_FLTINV:	code = "FPE_FLTINV";	break;
		case FPE_FLTSUB:	code = "FPE_FLTSUB";	break;
#if defined(FPE_FLTDEN)
		case FPE_FLTDEN:	code = "FPE_FLTDEN";	break;
#endif
		}
		break;
	case SIGSEGV:
		switch (sip->si_code) {
		case SEGV_MAPERR:	code = "SEGV_MAPERR";	break;
		case SEGV_ACCERR:	code = "SEGV_ACCERR";	break;
		}
		break;
	case SIGEMT:
		switch (sip->si_code) {
#ifdef EMT_TAGOVF
		case EMT_TAGOVF:	code = "EMT_TAGOVF";	break;
#endif
		case EMT_CPCOVF:	code = "EMT_CPCOVF";	break;
		}
		break;
	case SIGBUS:
		switch (sip->si_code) {
		case BUS_ADRALN:	code = "BUS_ADRALN";	break;
		case BUS_ADRERR:	code = "BUS_ADRERR";	break;
		case BUS_OBJERR:	code = "BUS_OBJERR";	break;
		}
		break;
	case SIGCLD:
		switch (sip->si_code) {
		case CLD_EXITED:	code = "CLD_EXITED";	break;
		case CLD_KILLED:	code = "CLD_KILLED";	break;
		case CLD_DUMPED:	code = "CLD_DUMPED";	break;
		case CLD_TRAPPED:	code = "CLD_TRAPPED";	break;
		case CLD_STOPPED:	code = "CLD_STOPPED";	break;
		case CLD_CONTINUED:	code = "CLD_CONTINUED";	break;
		}
		break;
	case SIGPOLL:
		switch (sip->si_code) {
		case POLL_IN:		code = "POLL_IN";	break;
		case POLL_OUT:		code = "POLL_OUT";	break;
		case POLL_MSG:		code = "POLL_MSG";	break;
		case POLL_ERR:		code = "POLL_ERR";	break;
		case POLL_PRI:		code = "POLL_PRI";	break;
		case POLL_HUP:		code = "POLL_HUP";	break;
		}
		break;
	}

	if (code == NULL) {
		(void) sprintf(pri->code_buf, "code=%d", sip->si_code);
		code = (const char *)pri->code_buf;
	}

	switch (sip->si_signo) {
	case SIGILL:
	case SIGTRAP:
	case SIGFPE:
	case SIGSEGV:
	case SIGBUS:
	case SIGEMT:
		(void) printf(" %s addr=0x%.8X",
		    code,
		    sip->si_addr);
		break;
	case SIGCLD:
		(void) printf(" %s pid=%d status=0x%.4X",
		    code,
		    sip->si_pid,
		    sip->si_status);
		break;
	case SIGPOLL:
	case SIGXFSZ:
		(void) printf(" %s fd=%d band=%d",
		    code,
		    sip->si_fd,
		    sip->si_band);
		break;
	}

	if (sip->si_errno != 0) {
		const char *ename = errname(sip->si_errno);

		(void) printf(" errno=%d", sip->si_errno);
		if (ename != NULL)
			(void) printf("(%s)", ename);
	}

	(void) fputc('\n', stdout);
}
#endif	/* _LP64 */

void
print_siginfo(private_t *pri, const siginfo_t *sip)
{
	const char *code = NULL;

	(void) printf("%s      siginfo: %s", pri->pname,
	    signame(pri, sip->si_signo));

	if (sip->si_signo != 0 && SI_FROMUSER(sip) && sip->si_pid != 0) {
		(void) printf(" pid=%d uid=%u",
		    (int)sip->si_pid,
		    sip->si_uid);
		if (sip->si_code != 0)
			(void) printf(" code=%d", sip->si_code);
		(void) fputc('\n', stdout);
		return;
	}

	switch (sip->si_signo) {
	default:
		(void) fputc('\n', stdout);
		return;
	case SIGILL:
	case SIGTRAP:
	case SIGFPE:
	case SIGSEGV:
	case SIGBUS:
	case SIGEMT:
	case SIGCLD:
	case SIGPOLL:
	case SIGXFSZ:
		break;
	}

	switch (sip->si_signo) {
	case SIGILL:
		switch (sip->si_code) {
		case ILL_ILLOPC:	code = "ILL_ILLOPC";	break;
		case ILL_ILLOPN:	code = "ILL_ILLOPN";	break;
		case ILL_ILLADR:	code = "ILL_ILLADR";	break;
		case ILL_ILLTRP:	code = "ILL_ILLTRP";	break;
		case ILL_PRVOPC:	code = "ILL_PRVOPC";	break;
		case ILL_PRVREG:	code = "ILL_PRVREG";	break;
		case ILL_COPROC:	code = "ILL_COPROC";	break;
		case ILL_BADSTK:	code = "ILL_BADSTK";	break;
		}
		break;
	case SIGTRAP:
		switch (sip->si_code) {
		case TRAP_BRKPT:	code = "TRAP_BRKPT";	break;
		case TRAP_TRACE:	code = "TRAP_TRACE";	break;
		case TRAP_RWATCH:	code = "TRAP_RWATCH";	break;
		case TRAP_WWATCH:	code = "TRAP_WWATCH";	break;
		case TRAP_XWATCH:	code = "TRAP_XWATCH";	break;
		case TRAP_DTRACE:	code = "TRAP_DTRACE";	break;
		}
		break;
	case SIGFPE:
		switch (sip->si_code) {
		case FPE_INTDIV:	code = "FPE_INTDIV";	break;
		case FPE_INTOVF:	code = "FPE_INTOVF";	break;
		case FPE_FLTDIV:	code = "FPE_FLTDIV";	break;
		case FPE_FLTOVF:	code = "FPE_FLTOVF";	break;
		case FPE_FLTUND:	code = "FPE_FLTUND";	break;
		case FPE_FLTRES:	code = "FPE_FLTRES";	break;
		case FPE_FLTINV:	code = "FPE_FLTINV";	break;
		case FPE_FLTSUB:	code = "FPE_FLTSUB";	break;
#if defined(FPE_FLTDEN)
		case FPE_FLTDEN:	code = "FPE_FLTDEN";	break;
#endif
		}
		break;
	case SIGSEGV:
		switch (sip->si_code) {
		case SEGV_MAPERR:	code = "SEGV_MAPERR";	break;
		case SEGV_ACCERR:	code = "SEGV_ACCERR";	break;
		}
		break;
	case SIGEMT:
		switch (sip->si_code) {
#ifdef EMT_TAGOVF
		case EMT_TAGOVF:	code = "EMT_TAGOVF";	break;
#endif
		case EMT_CPCOVF:	code = "EMT_CPCOVF";	break;
		}
		break;
	case SIGBUS:
		switch (sip->si_code) {
		case BUS_ADRALN:	code = "BUS_ADRALN";	break;
		case BUS_ADRERR:	code = "BUS_ADRERR";	break;
		case BUS_OBJERR:	code = "BUS_OBJERR";	break;
		}
		break;
	case SIGCLD:
		switch (sip->si_code) {
		case CLD_EXITED:	code = "CLD_EXITED";	break;
		case CLD_KILLED:	code = "CLD_KILLED";	break;
		case CLD_DUMPED:	code = "CLD_DUMPED";	break;
		case CLD_TRAPPED:	code = "CLD_TRAPPED";	break;
		case CLD_STOPPED:	code = "CLD_STOPPED";	break;
		case CLD_CONTINUED:	code = "CLD_CONTINUED";	break;
		}
		break;
	case SIGPOLL:
		switch (sip->si_code) {
		case POLL_IN:		code = "POLL_IN";	break;
		case POLL_OUT:		code = "POLL_OUT";	break;
		case POLL_MSG:		code = "POLL_MSG";	break;
		case POLL_ERR:		code = "POLL_ERR";	break;
		case POLL_PRI:		code = "POLL_PRI";	break;
		case POLL_HUP:		code = "POLL_HUP";	break;
		}
		break;
	}

	if (code == NULL) {
		(void) sprintf(pri->code_buf, "code=%d", sip->si_code);
		code = (const char *)pri->code_buf;
	}

	switch (sip->si_signo) {
	case SIGILL:
	case SIGTRAP:
	case SIGFPE:
	case SIGSEGV:
	case SIGBUS:
	case SIGEMT:
		(void) printf(" %s addr=0x%.8lX",
		    code,
		    (long)sip->si_addr);
		break;
	case SIGCLD:
		(void) printf(" %s pid=%d status=0x%.4X",
		    code,
		    (int)sip->si_pid,
		    sip->si_status);
		break;
	case SIGPOLL:
	case SIGXFSZ:
		(void) printf(" %s fd=%d band=%ld",
		    code,
		    sip->si_fd,
		    sip->si_band);
		break;
	}

	if (sip->si_errno != 0) {
		const char *ename = errname(sip->si_errno);

		(void) printf(" errno=%d", sip->si_errno);
		if (ename != NULL)
			(void) printf("(%s)", ename);
	}

	(void) fputc('\n', stdout);
}

#ifdef _LP64
void
show_siginfo32(private_t *pri, long offset)
{
	struct siginfo32 siginfo;

	if (offset != NULL &&
	    Pread(Proc, &siginfo, sizeof (siginfo), offset) == sizeof (siginfo))
		print_siginfo32(pri, &siginfo);
}
#endif	/* _LP64 */

void
show_siginfo(private_t *pri, long offset)
{
	struct siginfo siginfo;

#ifdef _LP64
	if (data_model != PR_MODEL_LP64) {
		show_siginfo32(pri, offset);
		return;
	}
#endif
	if (offset != NULL &&
	    Pread(Proc, &siginfo, sizeof (siginfo), offset) == sizeof (siginfo))
		print_siginfo(pri, &siginfo);
}

void
show_bool(private_t *pri, long offset, int count)
{
	int serial = (count > MYBUFSIZ / 4);

	/* enter region of lengthy output */
	if (serial)
		Eserialize();

	while (count > 0) {
		char buf[32];
		int nb = (count < 32)? count : 32;
		int i;

		if (Pread(Proc, buf, (size_t)nb, offset) != nb)
			break;

		(void) printf("%s   ", pri->pname);
		for (i = 0; i < nb; i++)
			(void) printf(" %d", buf[i]);
		(void) fputc('\n', stdout);

		count -= nb;
		offset += nb;
	}

	/* exit region of lengthy output */
	if (serial)
		Xserialize();
}

#ifdef _LP64
void
show_iovec32(private_t *pri, long offset, int niov, int showbuf, long count)
{
	iovec32_t iovec[16];
	iovec32_t *ip;
	long nb;
	int serial = (count > MYBUFSIZ / 4 && showbuf);

	if (niov > 16)		/* is this the real limit? */
		niov = 16;

	if (offset != NULL && niov > 0 &&
	    Pread(Proc, &iovec[0], niov*sizeof (iovec32_t), offset)
	    == niov*sizeof (iovec32_t)) {
		/* enter region of lengthy output */
		if (serial)
			Eserialize();

		for (ip = &iovec[0]; niov-- && !interrupt; ip++) {
			(void) printf("%s\tiov_base = 0x%.8X  iov_len = %d\n",
			    pri->pname,
			    ip->iov_base,
			    ip->iov_len);
			if ((nb = count) > 0) {
				if (nb > ip->iov_len)
					nb = ip->iov_len;
				if (nb > 0)
					count -= nb;
			}
			if (showbuf && nb > 0)
				showbuffer(pri, (long)ip->iov_base, nb);
		}

		/* exit region of lengthy output */
		if (serial)
			Xserialize();
	}
}
#endif	/* _LP64 */

void
show_iovec(private_t *pri, long offset, long niov, int showbuf, long count)
{
	iovec_t iovec[16];
	iovec_t *ip;
	long nb;
	int serial = (count > MYBUFSIZ / 4 && showbuf);

#ifdef _LP64
	if (data_model != PR_MODEL_LP64) {
		show_iovec32(pri, offset, niov, showbuf, count);
		return;
	}
#endif
	if (niov > 16)		/* is this the real limit? */
		niov = 16;

	if (offset != NULL && niov > 0 &&
	    Pread(Proc, &iovec[0], niov*sizeof (iovec_t), offset)
	    == niov*sizeof (iovec_t)) {
		/* enter region of lengthy output */
		if (serial)
			Eserialize();

		for (ip = &iovec[0]; niov-- && !interrupt; ip++) {
			(void) printf("%s\tiov_base = 0x%.8lX  iov_len = %lu\n",
			    pri->pname,
			    (long)ip->iov_base,
			    ip->iov_len);
			if ((nb = count) > 0) {
				if (nb > ip->iov_len)
					nb = ip->iov_len;
				if (nb > 0)
					count -= nb;
			}
			if (showbuf && nb > 0)
				showbuffer(pri, (long)ip->iov_base, nb);
		}

		/* exit region of lengthy output */
		if (serial)
			Xserialize();
	}
}

void
show_dents32(private_t *pri, long offset, long count)
{
	long buf[MYBUFSIZ / sizeof (long)];
	struct dirent32 *dp;
	int serial = (count > 100);

	if (offset == 0)
		return;

	/* enter region of lengthy output */
	if (serial)
		Eserialize();

	while (count > 0 && !interrupt) {
		int nb = count < MYBUFSIZ? (int)count : MYBUFSIZ;

		if ((nb = Pread(Proc, &buf[0], (size_t)nb, offset)) <= 0)
			break;

		dp = (struct dirent32 *)&buf[0];
		if (nb < (int)(dp->d_name - (char *)dp))
			break;
		if ((unsigned)nb < dp->d_reclen) {
			/* getdents() error? */
			(void) printf(
			    "%s    ino=%-5u off=%-4d rlen=%-3d\n",
			    pri->pname,
			    dp->d_ino,
			    dp->d_off,
			    dp->d_reclen);
			break;
		}

		while (!interrupt &&
		    nb >= (int)(dp->d_name - (char *)dp) &&
		    (unsigned)nb >= dp->d_reclen) {
			(void) printf(
			    "%s    ino=%-5u off=%-4d rlen=%-3d \"%.*s\"\n",
			    pri->pname,
			    dp->d_ino,
			    dp->d_off,
			    dp->d_reclen,
			    dp->d_reclen - (int)(dp->d_name - (char *)dp),
			    dp->d_name);
			nb -= dp->d_reclen;
			count -= dp->d_reclen;
			offset += dp->d_reclen;
			/* LINTED improper alignment */
			dp = (struct dirent32 *)((char *)dp + dp->d_reclen);
		}
	}

	/* exit region of lengthy output */
	if (serial)
		Xserialize();
}

void
show_dents64(private_t *pri, long offset, long count)
{
	long long buf[MYBUFSIZ / sizeof (long long)];
	struct dirent64 *dp;
	int serial = (count > 100);

	if (offset == 0)
		return;

	/* enter region of lengthy output */
	if (serial)
		Eserialize();

	while (count > 0 && !interrupt) {
		int nb = count < MYBUFSIZ? (int)count : MYBUFSIZ;

		if ((nb = Pread(Proc, &buf[0], (size_t)nb, offset)) <= 0)
			break;

		dp = (struct dirent64 *)&buf[0];
		if (nb < (int)(dp->d_name - (char *)dp))
			break;
		if ((unsigned)nb < dp->d_reclen) {
			/* getdents() error? */
			(void) printf(
			    "%s    ino=%-5llu off=%-4lld rlen=%-3d\n",
			    pri->pname,
			    (long long)dp->d_ino,
			    (long long)dp->d_off,
			    dp->d_reclen);
			break;
		}

		while (!interrupt &&
		    nb >= (int)(dp->d_name - (char *)dp) &&
		    (unsigned)nb >= dp->d_reclen) {
			(void) printf(
			    "%s    ino=%-5llu off=%-4lld rlen=%-3d \"%.*s\"\n",
			    pri->pname,
			    (long long)dp->d_ino,
			    (long long)dp->d_off,
			    dp->d_reclen,
			    dp->d_reclen - (int)(dp->d_name - (char *)dp),
			    dp->d_name);
			nb -= dp->d_reclen;
			count -= dp->d_reclen;
			offset += dp->d_reclen;
			/* LINTED improper alignment */
			dp = (struct dirent64 *)((char *)dp + dp->d_reclen);
		}
	}

	/* exit region of lengthy output */
	if (serial)
		Xserialize();
}

void
show_rlimit32(private_t *pri, long offset)
{
	struct rlimit32 rlimit;

	if (offset != NULL &&
	    Pread(Proc, &rlimit, sizeof (rlimit), offset) == sizeof (rlimit)) {
		(void) printf("%s\t", pri->pname);
		switch (rlimit.rlim_cur) {
		case RLIM32_INFINITY:
			(void) fputs("cur = RLIM_INFINITY", stdout);
			break;
		case RLIM32_SAVED_MAX:
			(void) fputs("cur = RLIM_SAVED_MAX", stdout);
			break;
		case RLIM32_SAVED_CUR:
			(void) fputs("cur = RLIM_SAVED_CUR", stdout);
			break;
		default:
			(void) printf("cur = %lu", (long)rlimit.rlim_cur);
			break;
		}
		switch (rlimit.rlim_max) {
		case RLIM32_INFINITY:
			(void) fputs("  max = RLIM_INFINITY\n", stdout);
			break;
		case RLIM32_SAVED_MAX:
			(void) fputs("  max = RLIM_SAVED_MAX\n", stdout);
			break;
		case RLIM32_SAVED_CUR:
			(void) fputs("  max = RLIM_SAVED_CUR\n", stdout);
			break;
		default:
			(void) printf("  max = %lu\n", (long)rlimit.rlim_max);
			break;
		}
	}
}

void
show_rlimit64(private_t *pri, long offset)
{
	struct rlimit64 rlimit;

	if (offset != NULL &&
	    Pread(Proc, &rlimit, sizeof (rlimit), offset) == sizeof (rlimit)) {
		(void) printf("%s\t", pri->pname);
		switch (rlimit.rlim_cur) {
		case RLIM64_INFINITY:
			(void) fputs("cur = RLIM64_INFINITY", stdout);
			break;
		case RLIM64_SAVED_MAX:
			(void) fputs("cur = RLIM64_SAVED_MAX", stdout);
			break;
		case RLIM64_SAVED_CUR:
			(void) fputs("cur = RLIM64_SAVED_CUR", stdout);
			break;
		default:
			(void) printf("cur = %llu",
			    (unsigned long long)rlimit.rlim_cur);
			break;
		}
		switch (rlimit.rlim_max) {
		case RLIM64_INFINITY:
			(void) fputs("  max = RLIM64_INFINITY\n", stdout);
			break;
		case RLIM64_SAVED_MAX:
			(void) fputs("  max = RLIM64_SAVED_MAX\n", stdout);
			break;
		case RLIM64_SAVED_CUR:
			(void) fputs("  max = RLIM64_SAVED_CUR\n", stdout);
			break;
		default:
			(void) printf("  max = %llu\n",
			    (unsigned long long)rlimit.rlim_max);
			break;
		}
	}
}

void
show_nuname(private_t *pri, long offset)
{
	struct utsname ubuf;

	if (offset != NULL &&
	    Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
		(void) printf(
		    "%s\tsys=%s nod=%s rel=%s ver=%s mch=%s\n",
		    pri->pname,
		    ubuf.sysname,
		    ubuf.nodename,
		    ubuf.release,
		    ubuf.version,
		    ubuf.machine);
	}
}

void
show_adjtime(private_t *pri, long off1, long off2)
{
	show_timeval(pri, off1, "   delta");
	show_timeval(pri, off2, "olddelta");
}

void
show_sockaddr(private_t *pri,
	const char *str, long addroff, long lenoff, long len)
{
	/*
	 * A buffer large enough for PATH_MAX size AF_UNIX address, which is
	 * also large enough to store a sockaddr_in or a sockaddr_in6.
	 */
	long buf[(sizeof (short) + PATH_MAX + sizeof (long) - 1)
	    / sizeof (long)];
	struct sockaddr *sa = (struct sockaddr *)buf;
	struct sockaddr_in *sin = (struct sockaddr_in *)buf;
	struct sockaddr_un *soun = (struct sockaddr_un *)buf;
	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
	char addrbuf[INET6_ADDRSTRLEN];

	if (lenoff != 0) {
		uint_t ilen;
		if (Pread(Proc, &ilen, sizeof (ilen), lenoff) != sizeof (ilen))
			return;
		len = ilen;
	}

	if (len >= sizeof (buf))	/* protect against ridiculous length */
		len = sizeof (buf) - 1;
	if (Pread(Proc, buf, len, addroff) != len)
		return;

	switch (sa->sa_family) {
	case AF_INET6:
		(void) printf("%s\tAF_INET6  %s = %s  port = %u\n",
		    pri->pname, str,
		    inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf,
		    sizeof (addrbuf)),
		    ntohs(sin6->sin6_port));
		(void) printf("%s\tscope id = %u  source id = 0x%x\n"
		    "%s\tflow class = 0x%02x  flow label = 0x%05x\n",
		    pri->pname, ntohl(sin6->sin6_scope_id),
		    ntohl(sin6->__sin6_src_id),
		    pri->pname,
		    ntohl((sin6->sin6_flowinfo & IPV6_FLOWINFO_TCLASS) >> 20),
		    ntohl(sin6->sin6_flowinfo & IPV6_FLOWINFO_FLOWLABEL));
		break;
	case AF_INET:
		(void) printf("%s\tAF_%s  %s = %s  port = %u\n",
		    pri->pname, "INET",
		    str, inet_ntop(AF_INET, &sin->sin_addr, addrbuf,
		    sizeof (addrbuf)), ntohs(sin->sin_port));
		break;
	case AF_UNIX:
		len -= sizeof (soun->sun_family);
		if (len >= 0) {
			/* Null terminate */
			soun->sun_path[len] = NULL;
			(void) printf("%s\tAF_UNIX  %s = %s\n", pri->pname,
			    str, soun->sun_path);
		}
		break;
	}
}

void
show_msghdr(private_t *pri, long offset)
{
	const lwpstatus_t *Lsp = pri->lwpstat;
	int what = Lsp->pr_what;
	int err = pri->Errno;
	struct msghdr msg;
	int showbuf = FALSE;
	int i = pri->sys_args[0]+1;
	long nb = (what == SYS_recvmsg)? pri->Rval1 : 32*1024;

	if (Pread(Proc, &msg, sizeof (msg), offset) != sizeof (msg))
		return;

	if (msg.msg_name != NULL && msg.msg_namelen != 0)
		show_sockaddr(pri, "msg_name",
		    (long)msg.msg_name, 0, (long)msg.msg_namelen);

	/*
	 * Print the iovec if the syscall was successful and the fd is
	 * part of the set being traced.
	 */
	if ((what == SYS_recvmsg && !err &&
	    prismember(&readfd, i)) ||
	    (what == SYS_sendmsg &&
	    prismember(&writefd, i)))
		showbuf = TRUE;

	show_iovec(pri, (long)msg.msg_iov, msg.msg_iovlen, showbuf, nb);

}

#ifdef _LP64
void
show_msghdr32(private_t *pri, long offset)
{
	struct msghdr32 {
		caddr32_t	msg_name;
		uint32_t	msg_namelen;
		caddr32_t 	msg_iov;
		int32_t		msg_iovlen;
	} msg;
	const lwpstatus_t *Lsp = pri->lwpstat;
	int what = Lsp->pr_what;
	int err = pri->Errno;
	int showbuf = FALSE;
	int i = pri->sys_args[0]+1;
	long nb = (what == SYS_recvmsg)? pri->Rval1 : 32*1024;

	if (Pread(Proc, &msg, sizeof (msg), offset) != sizeof (msg))
		return;

	if (msg.msg_name != NULL && msg.msg_namelen != 0)
		show_sockaddr(pri, "msg_name",
		    (long)msg.msg_name, 0, (long)msg.msg_namelen);
	/*
	 * Print the iovec if the syscall was successful and the fd is
	 * part of the set being traced.
	 */
	if ((what == SYS_recvmsg && !err &&
	    prismember(&readfd, i)) ||
	    (what == SYS_sendmsg &&
	    prismember(&writefd, i)))
		showbuf = TRUE;

	show_iovec32(pri, (long)msg.msg_iov, msg.msg_iovlen, showbuf, nb);

}
#endif	/* _LP64 */

static void
show_doorargs(private_t *pri, long offset)
{
	door_arg_t args;

	if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
		(void) printf("%s\tdata_ptr=0x%lX data_size=%lu\n",
		    pri->pname,
		    (ulong_t)args.data_ptr,
		    (ulong_t)args.data_size);
		(void) printf("%s\tdesc_ptr=0x%lX desc_num=%u\n",
		    pri->pname,
		    (ulong_t)args.desc_ptr,
		    args.desc_num);
		(void) printf("%s\trbuf=0x%lX rsize=%lu\n",
		    pri->pname,
		    (ulong_t)args.rbuf,
		    (ulong_t)args.rsize);
	}
}

static void
show_ucred_privsets(private_t *pri, ucred_t *uc)
{
	int i = 0;
	const priv_set_t *s;
	priv_ptype_t sn;
	char *str;

	while ((sn = priv_getsetbynum(i++)) != NULL) {
		s = ucred_getprivset(uc, sn);

		if (s == NULL)
			continue;

		(void) printf("%s\t%c: %s\n",
		    pri->pname,
		    *sn,
		    str = priv_set_to_str(s, ',', PRIV_STR_SHORT));

		free(str);
	}
}

static void
show_ucred(private_t *pri, long offset)
{
	ucred_t *uc = _ucred_alloc();
	size_t sz;

	if (uc == NULL)
		return;

	sz = Pread(Proc, uc, uc->uc_size, offset);

	/*
	 * A new uc_size is read, it could be smaller than the previously
	 * value.  We accept short reads that fill the whole header.
	 */
	if (sz >= sizeof (ucred_t) && sz >= uc->uc_size) {
		(void) printf("%s\teuid=%u egid=%u\n",
		    pri->pname,
		    ucred_geteuid(uc),
		    ucred_getegid(uc));
		(void) printf("%s\truid=%u rgid=%u\n",
		    pri->pname,
		    ucred_getruid(uc),
		    ucred_getrgid(uc));
		(void) printf("%s\tpid=%d zoneid=%d\n",
		    pri->pname,
		    (int)ucred_getpid(uc),
		    (int)ucred_getzoneid(uc));
		show_ucred_privsets(pri, uc);
	}
	ucred_free(uc);
}

static void
show_privset(private_t *pri, long offset, size_t size, char *label)
{
	priv_set_t *tmp = priv_allocset();
	size_t sz;

	if (tmp == NULL)
		return;

	sz = Pread(Proc, tmp, size, offset);

	if (sz == size) {
		char *str = priv_set_to_str(tmp, ',', PRIV_STR_SHORT);
		if (str != NULL) {
			(void) printf("%s\t%s%s\n", pri->pname, label, str);
			free(str);
		}
	}
	priv_freeset(tmp);
}

static void
show_doorinfo(private_t *pri, long offset)
{
	door_info_t info;
	door_attr_t attr;

	if (Pread(Proc, &info, sizeof (info), offset) != sizeof (info))
		return;
	(void) printf("%s\ttarget=%d proc=0x%llX data=0x%llX\n",
	    pri->pname,
	    (int)info.di_target,
	    info.di_proc,
	    info.di_data);
	attr = info.di_attributes;
	(void) printf("%s\tattributes=%s\n", pri->pname, door_flags(pri, attr));
	(void) printf("%s\tuniquifier=%llu\n", pri->pname, info.di_uniquifier);
}

static void
show_doorparam(private_t *pri, long offset)
{
	ulong_t val;

	if (Pread(Proc, &val, sizeof (val), offset) == sizeof (val)) {
		(void) printf("%s\tvalue=%lu\n",
		    pri->pname,
		    val);
	}
}

#ifdef _LP64

static void
show_doorargs32(private_t *pri, long offset)
{
	struct door_arg32 args;

	if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
		(void) printf("%s\tdata_ptr=%X data_size=%u\n",
		    pri->pname,
		    args.data_ptr,
		    args.data_size);
		(void) printf("%s\tdesc_ptr=0x%X desc_num=%u\n",
		    pri->pname,
		    args.desc_ptr,
		    args.desc_num);
		(void) printf("%s\trbuf=0x%X rsize=%u\n",
		    pri->pname,
		    args.rbuf,
		    args.rsize);
	}
}

static void
show_doorparam32(private_t *pri, long offset)
{
	uint_t val;

	if (Pread(Proc, &val, sizeof (val), offset) == sizeof (val)) {
		(void) printf("%s\tvalue=%u\n",
		    pri->pname,
		    val);
	}
}

#endif	/* _LP64 */

static void
show_doors(private_t *pri)
{
	switch (pri->sys_args[5]) {
	case DOOR_CALL:
#ifdef _LP64
		if (data_model == PR_MODEL_LP64)
			show_doorargs(pri, (long)pri->sys_args[1]);
		else
			show_doorargs32(pri, (long)pri->sys_args[1]);
#else
		show_doorargs(pri, (long)pri->sys_args[1]);
#endif
		break;
	case DOOR_UCRED:
		if (!pri->Errno)
			show_ucred(pri, (long)pri->sys_args[0]);
		break;
	case DOOR_INFO:
		if (!pri->Errno)
			show_doorinfo(pri, (long)pri->sys_args[1]);
		break;
	case DOOR_GETPARAM:
		if (!pri->Errno) {
#ifdef _LP64
			if (data_model == PR_MODEL_LP64)
				show_doorparam(pri, (long)pri->sys_args[2]);
			else
				show_doorparam32(pri, (long)pri->sys_args[2]);
#else
			show_doorparam(pri, (long)pri->sys_args[2]);
#endif
		}
		break;
	}
}

static void
show_portargs(private_t *pri, long offset)
{
	port_event_t args;

	if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
		(void) printf("%s\tevents=0x%x source=%u\n",
		    pri->pname,
		    args.portev_events,
		    args.portev_source);
		(void) printf("%s\tobject=0x%p user=0x%p\n",
		    pri->pname,
		    (void *)args.portev_object,
		    (void *)args.portev_user);
	}
}


#ifdef _LP64

static void
show_portargs32(private_t *pri, long offset)
{
	port_event32_t args;

	if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
		(void) printf("%s\tevents=0x%x source=%u\n",
		    pri->pname,
		    args.portev_events,
		    args.portev_source);
		(void) printf("%s\tobject=0x%x user=0x%x\n",
		    pri->pname,
		    args.portev_object,
		    args.portev_user);
	}
}

#endif	/* _LP64 */

static void
show_ports(private_t *pri)
{
	switch (pri->sys_args[0]) {
	case PORT_GET:
#ifdef _LP64
		if (data_model == PR_MODEL_LP64)
			show_portargs(pri, (long)pri->sys_args[2]);
		else
			show_portargs32(pri, (long)pri->sys_args[2]);
#else
		show_portargs(pri, (long)pri->sys_args[2]);
#endif
		break;
	}
}

#define	MAX_SNDFL_PRD 16

#ifdef _LP64

static void
show_ksendfilevec32(private_t *pri, int fd,
    ksendfilevec32_t *sndvec, int sfvcnt)
{
	ksendfilevec32_t *snd_ptr, snd[MAX_SNDFL_PRD];
	size_t cpy_rqst;

	Eserialize();
	while (sfvcnt > 0) {
		cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
		sfvcnt -= cpy_rqst;
		cpy_rqst *= sizeof (snd[0]);

		if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
			break;

		snd_ptr = &snd[0];

		while (cpy_rqst) {
			(void) printf(
			    "sfv_fd=%d\tsfv_flag=0x%x\t"
			    "sfv_off=%d\tsfv_len=%u\n",
			    snd_ptr->sfv_fd,
			    snd_ptr->sfv_flag,
			    snd_ptr->sfv_off,
			    snd_ptr->sfv_len);

			if (snd_ptr->sfv_fd == SFV_FD_SELF &&
			    prismember(&writefd, fd)) {
				showbuffer(pri,
				    (long)snd_ptr->sfv_off & 0xffffffff,
				    (long)snd_ptr->sfv_len);
			}

			cpy_rqst -= sizeof (snd[0]);
			snd_ptr++;
		}

		sndvec += MAX_SNDFL_PRD;
	}
	Xserialize();
}

static void
show_ksendfilevec64(private_t *pri, int fd,
    ksendfilevec64_t *sndvec, int sfvcnt)
{
	ksendfilevec64_t *snd_ptr, snd[MAX_SNDFL_PRD];
	size_t cpy_rqst;

	Eserialize();
	while (sfvcnt > 0) {
		cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
		sfvcnt -= cpy_rqst;
		cpy_rqst *= sizeof (snd[0]);

		if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
			break;

		snd_ptr = &snd[0];

		while (cpy_rqst) {
			(void) printf(
			    "sfv_fd=%d\tsfv_flag=0x%x\t"
			    "sfv_off=%ld\tsfv_len=%u\n",
			    snd_ptr->sfv_fd,
			    snd_ptr->sfv_flag,
			    snd_ptr->sfv_off,
			    snd_ptr->sfv_len);

			if (snd_ptr->sfv_fd == SFV_FD_SELF &&
			    prismember(&writefd, fd)) {
				showbuffer(pri,
				    (long)snd_ptr->sfv_off & 0xffffffff,
				    (long)snd_ptr->sfv_len);
			}

			cpy_rqst -= sizeof (snd[0]);
			snd_ptr++;
		}

		sndvec += MAX_SNDFL_PRD;
	}
	Xserialize();
}

#endif /* _LP64 */

/*ARGSUSED*/
static void
show_sendfilevec(private_t *pri, int fd, sendfilevec_t *sndvec, int sfvcnt)
{
	sendfilevec_t *snd_ptr, snd[MAX_SNDFL_PRD];
	size_t cpy_rqst;

#ifdef _LP64
	if (data_model != PR_MODEL_LP64) {
		show_ksendfilevec32(pri, fd,
		    (ksendfilevec32_t *)sndvec, sfvcnt);
		return;
	}
#endif
	Eserialize();
	while (sfvcnt > 0) {
		cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
		sfvcnt -= cpy_rqst;
		cpy_rqst *= sizeof (snd[0]);

		if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
			break;

		snd_ptr = &snd[0];

		while (cpy_rqst) {
			(void) printf(
			    "sfv_fd=%d\tsfv_flag=0x%x\t"
			    "sfv_off=%ld\tsfv_len=%lu\n",
			    snd_ptr->sfv_fd,
			    snd_ptr->sfv_flag,
			    snd_ptr->sfv_off,
			    (ulong_t)snd_ptr->sfv_len);

			if (snd_ptr->sfv_fd == SFV_FD_SELF &&
			    prismember(&writefd, fd)) {
				showbuffer(pri, (long)snd_ptr->sfv_off,
				    (long)snd_ptr->sfv_len);
			}

			cpy_rqst -= sizeof (snd[0]);
			snd_ptr++;
		}

		sndvec += MAX_SNDFL_PRD;
	}
	Xserialize();
}

/*ARGSUSED*/
static void
show_sendfilevec64(private_t *pri, int fd, sendfilevec64_t *sndvec, int sfvcnt)
{
	sendfilevec64_t *snd_ptr, snd[MAX_SNDFL_PRD];
	size_t cpy_rqst;

#ifdef _LP64
	if (data_model != PR_MODEL_LP64) {
		show_ksendfilevec64(pri, fd,
		    (ksendfilevec64_t *)sndvec, sfvcnt);
		return;
	}
#endif

	Eserialize();
	while (sfvcnt > 0) {
		cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
		sfvcnt -= cpy_rqst;
		cpy_rqst *= sizeof (snd[0]);

		if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
			break;

		snd_ptr = &snd[0];

		while (cpy_rqst) {
			(void) printf(
#ifdef _LP64
			    "sfv_fd=%d\tsfv_flag=0x%x\t"
			    "sfv_off=%ld\tsfv_len=%lu\n",
#else
			    "sfv_fd=%d\tsfv_flag=0x%x\t"
			    "sfv_off=%lld\tsfv_len=%lu\n",
#endif
			    snd_ptr->sfv_fd,
			    snd_ptr->sfv_flag,
			    snd_ptr->sfv_off,
			    (ulong_t)snd_ptr->sfv_len);

			if (snd_ptr->sfv_fd == SFV_FD_SELF &&
			    prismember(&writefd, fd)) {
				showbuffer(pri, (long)snd_ptr->sfv_off,
				    (long)snd_ptr->sfv_len);
			}

			cpy_rqst -= sizeof (snd[0]);
			snd_ptr++;
		}

		sndvec += MAX_SNDFL_PRD;
	}
	Xserialize();
}

static void
show_memcntl_mha(private_t *pri, long offset)
{
	struct memcntl_mha mha;
	const char *s = NULL;

	if (Pread(Proc, &mha, sizeof (mha), offset) == sizeof (mha)) {
		switch (mha.mha_cmd) {
		case MHA_MAPSIZE_VA:	    s = "MHA_MAPSIZE_VA";	break;
		case MHA_MAPSIZE_BSSBRK:    s = "MHA_MAPSIZE_BSSBRK";	break;
		case MHA_MAPSIZE_STACK:	    s = "MHA_MAPSIZE_STACK";	break;
		}
		if (s)
			(void) printf("%s\tmha_cmd=%s mha_flags=0x%x"
			    " mha_pagesize=%lu\n",
			    pri->pname, s, mha.mha_flags,
			    (ulong_t)mha.mha_pagesize);
		else
			(void) printf("%s\tmha_cmd=0x%.8x mha_flags=0x%x"
			    " mha_pagesize=%lu\n",
			    pri->pname, mha.mha_cmd, mha.mha_flags,
			    (ulong_t)mha.mha_pagesize);
	}
}

#ifdef _LP64

static void
show_memcntl_mha32(private_t *pri, long offset)
{
	struct memcntl_mha32 mha32;
	const char *s = NULL;

	if (Pread(Proc, &mha32, sizeof (mha32), offset) ==
	    sizeof (mha32)) {
		switch (mha32.mha_cmd) {
		case MHA_MAPSIZE_VA:	    s = "MHA_MAPSIZE_VA";	break;
		case MHA_MAPSIZE_BSSBRK:    s = "MHA_MAPSIZE_BSSBRK";	break;
		case MHA_MAPSIZE_STACK:	    s = "MHA_MAPSIZE_STACK";	break;
		}
		if (s)
			(void) printf("%s\tmha_cmd=%s mha_flags=0x%x"
			    " mha_pagesize=%u\n",
			    pri->pname, s, mha32.mha_flags, mha32.mha_pagesize);
		else
			(void) printf("%s\tmha_cmd=0x%.8x mha_flags=0x%x"
			    " mha_pagesize=%u\n",
			    pri->pname, mha32.mha_cmd, mha32.mha_flags,
			    mha32.mha_pagesize);
	}
}

#endif	/* _LP64 */

static void
show_memcntl(private_t *pri)
{

	if ((int)pri->sys_args[2] != MC_HAT_ADVISE)
		return;
#ifdef _LP64
	if (data_model == PR_MODEL_LP64)
		show_memcntl_mha(pri, (long)pri->sys_args[3]);
	else
		show_memcntl_mha32(pri, (long)pri->sys_args[3]);
#else
	show_memcntl_mha(pri, (long)pri->sys_args[3]);
#endif
}

void
show_ids(private_t *pri, long offset, int count)
{
	id_t buf[MYBUFSIZ / sizeof (id_t)];
	id_t *idp;
	int serial = (count > MYBUFSIZ / 48);

	if (offset == 0)
		return;

	/* enter region of lengthy output */
	if (serial)
		Eserialize();

	while (count > 0 && !interrupt) {
		ssize_t nb = (count * sizeof (id_t) < MYBUFSIZ)?
		    count * sizeof (id_t) : MYBUFSIZ;

		if ((nb = Pread(Proc, &buf[0], (size_t)nb, offset)) < 0 ||
		    nb < sizeof (id_t))
			break;

		idp = buf;
		while (!interrupt && nb >= sizeof (id_t)) {
			(void) printf("%s\t%8d\n", pri->pname, (int)*idp);
			offset += sizeof (id_t);
			nb -= sizeof (id_t);
			idp++;
			count--;
		}
	}

	/* exit region of lengthy output */
	if (serial)
		Xserialize();
}

void
show_ntp_gettime(private_t *pri)
{
	struct ntptimeval ntv;
	long offset;

	if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
		return;

	if (data_model == PR_MODEL_NATIVE) {
		if (Pread(Proc, &ntv, sizeof (ntv), offset)
		    != sizeof (ntv))
			return;
	} else {
		struct ntptimeval32 ntv32;

		if (Pread(Proc, &ntv32, sizeof (ntv32), offset)
		    != sizeof (ntv32))
			return;

		TIMEVAL32_TO_TIMEVAL(&ntv.time, &ntv32.time);
		ntv.maxerror = ntv32.maxerror;
		ntv.esterror = ntv32.esterror;
	}

	(void) printf("\ttime:     %ld.%6.6ld sec\n",
	    ntv.time.tv_sec, ntv.time.tv_usec);
	(void) printf("\tmaxerror: %11d usec\n", ntv.maxerror);
	(void) printf("\testerror: %11d usec\n", ntv.esterror);
}

static char *
get_timex_modes(private_t *pri, uint32_t val)
{
	char *str = pri->code_buf;
	size_t used = 0;

	*str = '\0';
	if (val & MOD_OFFSET)
		used = strlcat(str, "|MOD_OFFSET", sizeof (pri->code_buf));
	if (val & MOD_FREQUENCY)
		used = strlcat(str, "|MOD_FREQUENCY", sizeof (pri->code_buf));
	if (val & MOD_MAXERROR)
		used = strlcat(str, "|MOD_MAXERROR", sizeof (pri->code_buf));
	if (val & MOD_ESTERROR)
		used = strlcat(str, "|MOD_ESTERROR", sizeof (pri->code_buf));
	if (val & MOD_STATUS)
		used = strlcat(str, "|MOD_STATUS", sizeof (pri->code_buf));
	if (val & MOD_TIMECONST)
		used = strlcat(str, "|MOD_TIMECONST", sizeof (pri->code_buf));
	if (val & MOD_CLKB)
		used = strlcat(str, "|MOD_CLKB", sizeof (pri->code_buf));
	if (val & MOD_CLKA)
		used = strlcat(str, "|MOD_CLKA", sizeof (pri->code_buf));

	if (used == 0 || used >= sizeof (pri->code_buf))
		(void) snprintf(str, sizeof (pri->code_buf), " 0x%.4x", val);

	return (str + 1);
}

static char *
get_timex_status(private_t *pri, int32_t val)
{
	char *str = pri->code_buf;
	size_t used = 0;

	*str = '\0';
	if (val & STA_PLL)
		used = strlcat(str, "|STA_PLL", sizeof (pri->code_buf));
	if (val & STA_PPSFREQ)
		used = strlcat(str, "|STA_PPSFREQ", sizeof (pri->code_buf));
	if (val & STA_PPSTIME)
		used = strlcat(str, "|STA_PPSTIME", sizeof (pri->code_buf));
	if (val & STA_FLL)
		used = strlcat(str, "|STA_FLL", sizeof (pri->code_buf));

	if (val & STA_INS)
		used = strlcat(str, "|STA_INS", sizeof (pri->code_buf));
	if (val & STA_DEL)
		used = strlcat(str, "|STA_DEL", sizeof (pri->code_buf));
	if (val & STA_UNSYNC)
		used = strlcat(str, "|STA_UNSYNC", sizeof (pri->code_buf));
	if (val & STA_FREQHOLD)
		used = strlcat(str, "|STA_FREQHOLD", sizeof (pri->code_buf));

	if (val & STA_PPSSIGNAL)
		used = strlcat(str, "|STA_PPSSIGNAL", sizeof (pri->code_buf));
	if (val & STA_PPSJITTER)
		used = strlcat(str, "|STA_PPSJITTER", sizeof (pri->code_buf));
	if (val & STA_PPSWANDER)
		used = strlcat(str, "|STA_PPSWANDER", sizeof (pri->code_buf));
	if (val & STA_PPSERROR)
		used = strlcat(str, "|STA_PPSERROR", sizeof (pri->code_buf));

	if (val & STA_CLOCKERR)
		used = strlcat(str, "|STA_CLOCKERR", sizeof (pri->code_buf));

	if (used == 0 || used >= sizeof (pri->code_buf))
		(void) snprintf(str, sizeof (pri->code_buf), " 0x%.4x", val);

	return (str + 1);
}

void
show_ntp_adjtime(private_t *pri)
{
	struct timex timex;
	long offset;

	if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
		return;

	if (Pread(Proc, &timex, sizeof (timex), offset) != sizeof (timex))
		return;

	(void) printf("\tmodes:     %s\n", get_timex_modes(pri, timex.modes));
	(void) printf("\toffset:    %11d usec\n", timex.offset);
	(void) printf("\tfreq:      %11d scaled ppm\n", timex.freq);
	(void) printf("\tmaxerror:  %11d usec\n", timex.maxerror);
	(void) printf("\testerror:  %11d usec\n", timex.esterror);
	(void) printf("\tstatus:    %s\n", get_timex_status(pri, timex.status));
	(void) printf("\tconstant:  %11d\n", timex.constant);
	(void) printf("\tprecision: %11d usec\n", timex.precision);
	(void) printf("\ttolerance: %11d scaled ppm\n", timex.tolerance);
	(void) printf("\tppsfreq:   %11d scaled ppm\n", timex.ppsfreq);
	(void) printf("\tjitter:    %11d usec\n", timex.jitter);
	(void) printf("\tshift:     %11d sec\n", timex.shift);
	(void) printf("\tstabil:    %11d scaled ppm\n", timex.stabil);
	(void) printf("\tjitcnt:    %11d\n", timex.jitcnt);
	(void) printf("\tcalcnt:    %11d\n", timex.calcnt);
	(void) printf("\terrcnt:    %11d\n", timex.errcnt);
	(void) printf("\tstbcnt:    %11d\n", timex.stbcnt);
}

void
show_getrusage(long offset)
{
	struct rusage r;
	if (Pread(Proc, &r, sizeof (r), offset) != sizeof (r))
		return;
	(void) printf("\t       user time: %ld.%6.6ld sec\n",
	    r.ru_utime.tv_sec,
	    r.ru_utime.tv_usec);
	(void) printf("\t     system time: %ld.%6.6ld sec\n",
	    r.ru_stime.tv_sec,
	    r.ru_stime.tv_usec);
	(void) printf("\t         max rss: <unimpl> %ld\n",
	    r.ru_maxrss);
	(void) printf("\t     shared data: <unimpl> %ld\n",
	    r.ru_ixrss);
	(void) printf("\t   unshared data: <unimpl> %ld\n",
	    r.ru_idrss);
	(void) printf("\t  unshared stack: <unimpl> %ld\n",
	    r.ru_isrss);
	(void) printf("\t    minor faults: %ld\n",
	    r.ru_minflt);
	(void) printf("\t    major faults: %ld\n",
	    r.ru_majflt);
	(void) printf("\t      # of swaps: %ld\n",
	    r.ru_nswap);
	(void) printf("\t  blocked inputs: %ld\n",
	    r.ru_inblock);
	(void) printf("\t blocked outputs: %ld\n",
	    r.ru_oublock);
	(void) printf("\t       msgs sent: %ld\n",
	    r.ru_msgsnd);
	(void) printf("\t      msgs rcv'd: %ld\n",
	    r.ru_msgrcv);
	(void) printf("\t   signals rcv'd: %ld\n",
	    r.ru_nsignals);
	(void) printf("\tvol cntxt swtchs: %ld\n",
	    r.ru_nvcsw);
	(void) printf("\tinv cntxt swtchs: %ld\n",
	    r.ru_nivcsw);
}

#ifdef _LP64
void
show_getrusage32(long offset)
{
	struct rusage32 r;
	if (Pread(Proc, &r, sizeof (r), offset) != sizeof (r))
		return;
	(void) printf("\t       user time: %d.%6.6d sec\n",
	    r.ru_utime.tv_sec,
	    r.ru_utime.tv_usec);
	(void) printf("\t     system time: %d.%6.6d sec\n",
	    r.ru_stime.tv_sec,
	    r.ru_stime.tv_usec);
	(void) printf("\t         max rss: <unimpl> %d\n",
	    r.ru_maxrss);
	(void) printf("\t     shared data: <unimpl> %d\n",
	    r.ru_ixrss);
	(void) printf("\t   unshared data: <unimpl> %d\n",
	    r.ru_idrss);
	(void) printf("\t  unshared stack: <unimpl> %d\n",
	    r.ru_isrss);
	(void) printf("\t    minor faults: %d\n",
	    r.ru_minflt);
	(void) printf("\t    major faults: %d\n",
	    r.ru_majflt);
	(void) printf("\t      # of swaps: %d\n",
	    r.ru_nswap);
	(void) printf("\t  blocked inputs: %d\n",
	    r.ru_inblock);
	(void) printf("\t blocked outputs: %d\n",
	    r.ru_oublock);
	(void) printf("\t       msgs sent: %d\n",
	    r.ru_msgsnd);
	(void) printf("\t      msgs rcv'd: %d\n",
	    r.ru_msgrcv);
	(void) printf("\t   signals rcv'd: %d\n",
	    r.ru_nsignals);
	(void) printf("\tvol cntxt swtchs: %d\n",
	    r.ru_nvcsw);
	(void) printf("\tinv cntxt swtchs: %d\n",
	    r.ru_nivcsw);
}
#endif

/*
 * Utility function to print a packed nvlist by unpacking
 * and calling the libnvpair pretty printer.  Frees all
 * allocated memory internally.
 */
static void
show_packed_nvlist(private_t *pri, uintptr_t offset, size_t size)
{
	nvlist_t *nvl = NULL;
	size_t readsize;
	char *buf;

	if ((offset == 0) || (size == 0)) {
		return;
	}

	buf = my_malloc(size, "nvlist decode buffer");
	readsize = Pread(Proc, buf, size, offset);
	if (readsize != size) {
		(void) printf("%s\t<?>", pri->pname);
	} else {
		int result;

		result = nvlist_unpack(buf, size, &nvl, 0);
		if (result == 0) {
			nvlist_print(stdout, nvl);
			nvlist_free(nvl);
		} else {
			(void) printf("%s\tunpack of nvlist"
			    " failed: %d\n", pri->pname, result);
		}
	}
	free(buf);
}

static void
show_zone_create_args(private_t *pri, long offset)
{
	zone_def args;
	char zone_name[ZONENAME_MAX];
	char zone_root[MAXPATHLEN];
	char *zone_zfs = NULL;

	if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {

		if (Pread_string(Proc, zone_name, sizeof (zone_name),
		    (uintptr_t)args.zone_name) == -1)
			(void) strcpy(zone_name, "<?>");

		if (Pread_string(Proc, zone_root, sizeof (zone_root),
		    (uintptr_t)args.zone_root) == -1)
			(void) strcpy(zone_root, "<?>");

		if (args.zfsbufsz > 0) {
			zone_zfs = malloc(MIN(4, args.zfsbufsz));
			if (zone_zfs != NULL) {
				if (Pread(Proc, zone_zfs, args.zfsbufsz,
				    (uintptr_t)args.zfsbuf) == -1)
					(void) strcpy(zone_zfs, "<?>");
			}
		} else {
			zone_zfs = "";
		}

		(void) printf("%s\t     zone_name: %s\n", pri->pname,
		    zone_name);
		(void) printf("%s\t     zone_root: %s\n", pri->pname,
		    zone_root);

		show_privset(pri, (uintptr_t)args.zone_privs,
		    args.zone_privssz, "    zone_privs: ");

		(void) printf("%s\t       rctlbuf: 0x%p\n", pri->pname,
		    (void *)args.rctlbuf);
		(void) printf("%s\t     rctlbufsz: %lu\n", pri->pname,
		    (ulong_t)args.rctlbufsz);

		show_packed_nvlist(pri, (uintptr_t)args.rctlbuf,
		    args.rctlbufsz);

		(void) printf("%s\t           zfs: %s\n", pri->pname, zone_zfs);

		(void) printf("%s\textended_error: 0x%p\n", pri->pname,
		    (void *)args.extended_error);

		if (is_system_labeled()) {
			char		*label_str = NULL;
			bslabel_t	zone_label;

			(void) printf("%s\t         match: %d\n", pri->pname,
			    args.match);
			(void) printf("%s\t           doi: %d\n", pri->pname,
			    args.doi);

			if (Pread_string(Proc, (char *)&zone_label,
			    sizeof (zone_label), (uintptr_t)args.label) != -1) {
				/* show the label as string */
				if (label_to_str(&zone_label, &label_str,
				    M_LABEL, SHORT_NAMES) != 0) {
					/* have to dump label as raw string */
					(void) label_to_str(&zone_label,
					    &label_str, M_INTERNAL,
					    SHORT_NAMES);
				}
			}

			(void) printf("%s\t         label: %s\n",
			    pri->pname, label_str != NULL ? label_str : "<?>");
			if (label_str)
				free(label_str);
		}

		if (args.zfsbufsz > 0)
			free(zone_zfs);
	}
}


#ifdef _LP64

static void
show_zone_create_args32(private_t *pri, long offset)
{
	zone_def32 args;
	char zone_name[ZONENAME_MAX];
	char zone_root[MAXPATHLEN];
	char *zone_zfs = NULL;

	if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {

		if (Pread_string(Proc, zone_name, sizeof (zone_name),
		    (uintptr_t)args.zone_name) == -1)
			(void) strcpy(zone_name, "<?>");

		if (Pread_string(Proc, zone_root, sizeof (zone_root),
		    (uintptr_t)args.zone_root) == -1)
			(void) strcpy(zone_root, "<?>");

		if (args.zfsbufsz > 0) {
			zone_zfs = malloc(MIN(4, args.zfsbufsz));
			if (zone_zfs != NULL) {
				if (Pread(Proc, zone_zfs, args.zfsbufsz,
				    (uintptr_t)args.zfsbuf) == -1)
					(void) strcpy(zone_zfs, "<?>");
			}
		} else {
			zone_zfs = "";
		}

		(void) printf("%s\t     zone_name: %s\n", pri->pname,
		    zone_name);
		(void) printf("%s\t     zone_root: %s\n", pri->pname,
		    zone_root);

		show_privset(pri, (uintptr_t)args.zone_privs,
		    args.zone_privssz, "    zone_privs: ");

		(void) printf("%s\t       rctlbuf: 0x%x\n", pri->pname,
		    (caddr32_t)args.rctlbuf);
		(void) printf("%s\t     rctlbufsz: %lu\n", pri->pname,
		    (ulong_t)args.rctlbufsz);

		show_packed_nvlist(pri, (uintptr_t)args.rctlbuf,
		    args.rctlbufsz);

		(void) printf("%s\t           zfs: %s\n", pri->pname, zone_zfs);

		(void) printf("%s\textended_error: 0x%x\n", pri->pname,
		    (caddr32_t)args.extended_error);

		if (is_system_labeled()) {
			char		*label_str = NULL;
			bslabel_t	zone_label;

			(void) printf("%s\t         match: %d\n", pri->pname,
			    args.match);
			(void) printf("%s\t           doi: %d\n", pri->pname,
			    args.doi);

			if (Pread_string(Proc, (char *)&zone_label,
			    sizeof (zone_label), (caddr32_t)args.label) != -1) {
				/* show the label as string */
				if (label_to_str(&zone_label, &label_str,
				    M_LABEL, SHORT_NAMES) != 0) {
					/* have to dump label as raw string */
					(void) label_to_str(&zone_label,
					    &label_str, M_INTERNAL,
					    SHORT_NAMES);
				}
			}
			(void) printf("%s\t         label: %s\n",
			    pri->pname, label_str != NULL ? label_str : "<?>");
			if (label_str)
				free(label_str);
		}

		if (args.zfsbufsz > 0)
			free(zone_zfs);
	}
}

#endif

static void
show_zones(private_t *pri)
{
	switch (pri->sys_args[0]) {
	case ZONE_CREATE:
#ifdef _LP64
		if (data_model == PR_MODEL_LP64)
			show_zone_create_args(pri, (long)pri->sys_args[1]);
		else
			show_zone_create_args32(pri, (long)pri->sys_args[1]);
#else
		show_zone_create_args(pri, (long)pri->sys_args[1]);
#endif
		break;
	}
}

static void
show_rctlblk(private_t *pri, long _rctlblk)
{
	rctlblk_t *blk;
	int size = rctlblk_size();
	size_t readsize;
	const char *s;

	blk = my_malloc(size, "rctlblk decode buffer");
	readsize = Pread(Proc, blk, size, _rctlblk);
	if (readsize != size) {
		(void) printf("%s\t\t<?>", pri->pname);
	} else {
		(void) printf("%s\t\t     Privilege: 0x%x\n",
		    pri->pname,
		    rctlblk_get_privilege(blk));
		(void) printf("%s\t\t         Value: %lld\n",
		    pri->pname,
		    rctlblk_get_value(blk));
		(void) printf("%s\t\tEnforced Value: %lld\n",
		    pri->pname,
		    rctlblk_get_enforced_value(blk));

		{
			int sig, act;
			act = rctlblk_get_local_action(blk, &sig);

			s = rctl_local_action(pri, act);
			if (s == NULL) {
				(void) printf("%s\t\t  Local action: 0x%x\n",
				    pri->pname, act);
			} else {
				(void) printf("%s\t\t  Local action: %s\n",
				    pri->pname, s);
			}

			if (act & RCTL_LOCAL_SIGNAL) {
				(void) printf("%s\t\t                "
				    "For signal %s\n",
				    pri->pname, signame(pri, sig));
			}
		}

		s = rctl_local_flags(pri, rctlblk_get_local_flags(blk));
		if (s == NULL) {
			(void) printf("%s\t\t   Local flags: 0x%x\n",
			    pri->pname, rctlblk_get_local_flags(blk));
		} else {
			(void) printf("%s\t\t   Local flags: %s\n",
			    pri->pname, s);
		}

#ifdef _LP64
		(void) printf("%s\t\t Recipient PID: %d\n",
		    pri->pname,
		    rctlblk_get_recipient_pid(blk));
#else
		(void) printf("%s\t\t Recipient PID: %ld\n",
		    pri->pname,
		    rctlblk_get_recipient_pid(blk));
#endif
		(void) printf("%s\t\t   Firing Time: %lld\n",
		    pri->pname,
		    rctlblk_get_firing_time(blk));
	}
	free(blk);
}

static void
show_rctls(private_t *pri)
{
	int entry;

	switch (pri->sys_args[0]) {
	case 0:	/* getrctl */
	case 1: /* setrctl */
		/*
		 * If these offsets look a little odd, remember that they're
		 * into the _raw_ system call
		 */
		(void) printf("%s\tOld rctlblk: 0x%lx\n", pri->pname,
		    pri->sys_args[2]);
		if (pri->sys_args[2] != NULL) {
			show_rctlblk(pri, pri->sys_args[2]);
		}
		(void) printf("%s\tNew rctlblk: 0x%lx\n", pri->pname,
		    pri->sys_args[3]);
		if (pri->sys_args[3] != NULL) {
			show_rctlblk(pri, pri->sys_args[3]);
		}
		break;
	case 4: /* setprojrctl */
		for (entry = 0; entry < pri->sys_args[4]; entry++) {
			(void) printf("%s\tNew rctlblk[%d]: 0x%lx\n",
			    pri->pname, entry,
			    (long)RCTLBLK_INC(pri->sys_args[3], entry));
			if (RCTLBLK_INC(pri->sys_args[3], entry) != NULL) {
				show_rctlblk(pri,
				    (long)RCTLBLK_INC(pri->sys_args[3], entry));
			}
		}
	}
}

void
show_utimesys(private_t *pri)
{
	switch (pri->sys_args[0]) {
	case 0:			/* futimens() */
		if (pri->sys_nargs > 2)
			show_utimens(pri, (long)pri->sys_args[2]);
		break;
	case 1:			/* utimensat */
		if (pri->sys_nargs > 3)
			show_utimens(pri, (long)pri->sys_args[3]);
		break;
	default:		/* unexpected subcode */
		break;
	}
}

/* expound verbosely upon syscall arguments */
/*ARGSUSED*/
void
expound(private_t *pri, long r0, int raw)
{
	const lwpstatus_t *Lsp = pri->lwpstat;
	int lp64 = (data_model == PR_MODEL_LP64);
	int what = Lsp->pr_what;
	int err = pri->Errno;		/* don't display output parameters */
					/* for a failed system call */
#ifndef _LP64
	/* We are a 32-bit truss; we can't grok a 64-bit process */
	if (lp64)
		return;
#endif
	/* for reporting sleeping system calls */
	if (what == 0 && (Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP)))
		what = Lsp->pr_syscall;

	switch (what) {
	case SYS_gettimeofday:
		if (!err)
			show_timeofday(pri);
		break;
	case SYS_getitimer:
		if (!err && pri->sys_nargs > 1)
			show_itimerval(pri, (long)pri->sys_args[1],
			    " value");
		break;
	case SYS_setitimer:
		if (pri->sys_nargs > 1)
			show_itimerval(pri, (long)pri->sys_args[1],
			    " value");
		if (!err && pri->sys_nargs > 2)
			show_itimerval(pri, (long)pri->sys_args[2],
			    "ovalue");
		break;
	case SYS_stime:
		show_stime(pri);
		break;
	case SYS_times:
		if (!err)
			show_times(pri);
		break;
	case SYS_utssys:
		if (err)
			break;
#ifdef _LP64
		if (lp64)
			show_utssys(pri, r0);
		else
			show_utssys32(pri, r0);
#else
		show_utssys(pri, r0);
#endif
		break;
	case SYS_ioctl:
		if (pri->sys_nargs >= 3) /* each case must decide for itself */
			show_ioctl(pri, pri->sys_args[1],
			    (long)pri->sys_args[2]);
		break;
	case SYS_fstatat:
		if (!err && pri->sys_nargs >= 3)
			show_stat(pri, (long)pri->sys_args[2]);
		break;
	case SYS_fstatat64:
		if (!err && pri->sys_nargs >= 3)
			show_stat64_32(pri, (long)pri->sys_args[2]);
		break;
	case SYS_stat:
	case SYS_fstat:
	case SYS_lstat:
		if (!err && pri->sys_nargs >= 2)
			show_stat(pri, (long)pri->sys_args[1]);
		break;
	case SYS_stat64:
	case SYS_fstat64:
	case SYS_lstat64:
		if (!err && pri->sys_nargs >= 2)
			show_stat64_32(pri, (long)pri->sys_args[1]);
		break;
	case SYS_statvfs:
	case SYS_fstatvfs:
		if (err)
			break;
#ifdef _LP64
		if (!lp64) {
			show_statvfs32(pri);
			break;
		}
#endif
		show_statvfs(pri);
		break;
	case SYS_statvfs64:
	case SYS_fstatvfs64:
		if (err)
			break;
		show_statvfs64(pri);
		break;
	case SYS_statfs:
	case SYS_fstatfs:
		if (err)
			break;
#ifdef _LP64
		if (lp64)
			show_statfs(pri);
		else
			show_statfs32(pri);
#else
		show_statfs(pri);
#endif
		break;
	case SYS_fcntl:
		show_fcntl(pri);
		break;
	case SYS_msgsys:
		show_msgsys(pri, r0); /* each case must decide for itself */
		break;
	case SYS_semsys:
		show_semsys(pri);	/* each case must decide for itself */
		break;
	case SYS_shmsys:
		show_shmsys(pri);	/* each case must decide for itself */
		break;
	case SYS_getdents:
		if (err || pri->sys_nargs <= 1 || r0 <= 0)
			break;
#ifdef _LP64
		if (!lp64) {
			show_dents32(pri, (long)pri->sys_args[1], r0);
			break;
		}
		/* FALLTHROUGH */
#else
		show_dents32(pri, (long)pri->sys_args[1], r0);
		break;
#endif
	case SYS_getdents64:
		if (err || pri->sys_nargs <= 1 || r0 <= 0)
			break;
		show_dents64(pri, (long)pri->sys_args[1], r0);
		break;
	case SYS_getmsg:
		show_gp_msg(pri, what);
		if (pri->sys_nargs > 3)
			show_hhex_int(pri, (long)pri->sys_args[3], "flags");
		break;
	case SYS_getpmsg:
		show_gp_msg(pri, what);
		if (pri->sys_nargs > 3)
			show_hhex_int(pri, (long)pri->sys_args[3], "band");
		if (pri->sys_nargs > 4)
			show_hhex_int(pri, (long)pri->sys_args[4], "flags");
		break;
	case SYS_putmsg:
	case SYS_putpmsg:
		show_gp_msg(pri, what);
		break;
	case SYS_pollsys:
		show_pollsys(pri);
		break;
	case SYS_setgroups:
		if (pri->sys_nargs > 1 && (r0 = pri->sys_args[0]) > 0)
			show_groups(pri, (long)pri->sys_args[1], r0);
		break;
	case SYS_getgroups:
		if (!err && pri->sys_nargs > 1 && pri->sys_args[0] > 0)
			show_groups(pri, (long)pri->sys_args[1], r0);
		break;
	case SYS_sigprocmask:
		if (pri->sys_nargs > 1)
			show_sigset(pri, (long)pri->sys_args[1], " set");
		if (!err && pri->sys_nargs > 2)
			show_sigset(pri, (long)pri->sys_args[2], "oset");
		break;
	case SYS_sigsuspend:
	case SYS_sigtimedwait:
		if (pri->sys_nargs > 0)
			show_sigset(pri, (long)pri->sys_args[0], "sigmask");
		if (!err && pri->sys_nargs > 1)
			show_siginfo(pri, (long)pri->sys_args[1]);
		if (pri->sys_nargs > 2)
			show_timestruc(pri, (long)pri->sys_args[2], "timeout");
		break;
	case SYS_sigaltstack:
		if (pri->sys_nargs > 0)
			show_sigaltstack(pri, (long)pri->sys_args[0],
			    "new");
		if (!err && pri->sys_nargs > 1)
			show_sigaltstack(pri, (long)pri->sys_args[1],
			    "old");
		break;
	case SYS_sigaction:
		if (pri->sys_nargs > 1)
			show_sigaction(pri, (long)pri->sys_args[1],
			    "new", NULL);
		if (!err && pri->sys_nargs > 2)
			show_sigaction(pri, (long)pri->sys_args[2],
			    "old", r0);
		break;
	case SYS_signotify:
		if (pri->sys_nargs > 1)
			show_siginfo(pri, (long)pri->sys_args[1]);
		break;
	case SYS_sigresend:
		if (pri->sys_nargs > 1)
			show_siginfo(pri, (long)pri->sys_args[1]);
		if (pri->sys_nargs > 2)
			show_sigset(pri, (long)pri->sys_args[2], "sigmask");
		break;
	case SYS_sigpending:
		if (!err && pri->sys_nargs > 1)
			show_sigset(pri, (long)pri->sys_args[1], "sigmask");
		break;
	case SYS_waitid:
		if (!err && pri->sys_nargs > 2)
			show_siginfo(pri, (long)pri->sys_args[2]);
		break;
	case SYS_sigsendsys:
		if (pri->sys_nargs > 0)
			show_procset(pri, (long)pri->sys_args[0]);
		break;
	case SYS_priocntlsys:
		if (pri->sys_nargs > 1)
			show_procset(pri, (long)pri->sys_args[1]);
		break;
	case SYS_mincore:
		if (!err && pri->sys_nargs > 2)
			show_bool(pri, (long)pri->sys_args[2],
			    (pri->sys_args[1] + pagesize - 1) / pagesize);
		break;
	case SYS_readv:
	case SYS_writev:
		if (pri->sys_nargs > 2) {
			int i = pri->sys_args[0]+1;
			int showbuf = FALSE;
			long nb = (what == SYS_readv)? r0 : 32*1024;

			if ((what == SYS_readv && !err &&
			    prismember(&readfd, i)) ||
			    (what == SYS_writev &&
			    prismember(&writefd, i)))
				showbuf = TRUE;
			show_iovec(pri, (long)pri->sys_args[1],
			    pri->sys_args[2], showbuf, nb);
		}
		break;
	case SYS_getrlimit:
		if (err)
			break;
		/*FALLTHROUGH*/
	case SYS_setrlimit:
		if (pri->sys_nargs <= 1)
			break;
#ifdef _LP64
		if (lp64)
			show_rlimit64(pri, (long)pri->sys_args[1]);
		else
			show_rlimit32(pri, (long)pri->sys_args[1]);
#else
		show_rlimit32(pri, (long)pri->sys_args[1]);
#endif
		break;
	case SYS_getrlimit64:
		if (err)
			break;
		/*FALLTHROUGH*/
	case SYS_setrlimit64:
		if (pri->sys_nargs <= 1)
			break;
		show_rlimit64(pri, (long)pri->sys_args[1]);
		break;
	case SYS_uname:
		if (!err && pri->sys_nargs > 0)
			show_nuname(pri, (long)pri->sys_args[0]);
		break;
	case SYS_adjtime:
		if (!err && pri->sys_nargs > 1)
			show_adjtime(pri, (long)pri->sys_args[0],
			    (long)pri->sys_args[1]);
		break;
	case SYS_lwp_info:
		if (!err && pri->sys_nargs > 0)
			show_timestruc(pri, (long)pri->sys_args[0], "cpu time");
		break;
	case SYS_lwp_wait:
		if (!err && pri->sys_nargs > 1)
			show_int(pri, (long)pri->sys_args[1], "lwpid");
		break;
	case SYS_lwp_mutex_wakeup:
	case SYS_lwp_mutex_unlock:
	case SYS_lwp_mutex_trylock:
	case SYS_lwp_mutex_register:
		if (pri->sys_nargs > 0)
			show_mutex(pri, (long)pri->sys_args[0]);
		break;
	case SYS_lwp_mutex_timedlock:
		if (pri->sys_nargs > 0)
			show_mutex(pri, (long)pri->sys_args[0]);
		if (pri->sys_nargs > 1)
			show_timestruc(pri, (long)pri->sys_args[1], "timeout");
		break;
	case SYS_lwp_cond_wait:
		if (pri->sys_nargs > 0)
			show_condvar(pri, (long)pri->sys_args[0]);
		if (pri->sys_nargs > 1)
			show_mutex(pri, (long)pri->sys_args[1]);
		if (pri->sys_nargs > 2)
			show_timestruc(pri, (long)pri->sys_args[2], "timeout");
		break;
	case SYS_lwp_cond_signal:
	case SYS_lwp_cond_broadcast:
		if (pri->sys_nargs > 0)
			show_condvar(pri, (long)pri->sys_args[0]);
		break;
	case SYS_lwp_sema_trywait:
	case SYS_lwp_sema_post:
		if (pri->sys_nargs > 0)
			show_sema(pri, (long)pri->sys_args[0]);
		break;
	case SYS_lwp_sema_timedwait:
		if (pri->sys_nargs > 0)
			show_sema(pri, (long)pri->sys_args[0]);
		if (pri->sys_nargs > 1)
			show_timestruc(pri, (long)pri->sys_args[1], "timeout");
		break;
	case SYS_lwp_rwlock_sys:
		if (pri->sys_nargs > 1)
			show_rwlock(pri, (long)pri->sys_args[1]);
		if (pri->sys_nargs > 2 &&
		    (pri->sys_args[0] == 0 || pri->sys_args[0] == 1))
			show_timestruc(pri, (long)pri->sys_args[2], "timeout");
		break;
	case SYS_lwp_create:
		/* XXX print some values in ucontext ??? */
		if (!err && pri->sys_nargs > 2)
			show_int(pri, (long)pri->sys_args[2], "lwpid");
		break;
	case SYS_kaio:
		if (pri->sys_args[0] == AIOWAIT && !err && pri->sys_nargs > 1)
			show_timeval(pri, (long)pri->sys_args[1], "timeout");
		break;
	case SYS_nanosleep:
		if (pri->sys_nargs > 0)
			show_timestruc(pri, (long)pri->sys_args[0], "tmout");
		if (pri->sys_nargs > 1 && (err == 0 || err == EINTR))
			show_timestruc(pri, (long)pri->sys_args[1], "resid");
		break;
	case SYS_privsys:
		switch (pri->sys_args[0]) {
		case PRIVSYS_SETPPRIV:
		case PRIVSYS_GETPPRIV:
			if (!err)
				show_privset(pri, (long)pri->sys_args[3],
				    (size_t)pri->sys_args[4], "");
		}
		break;
	case SYS_ucredsys:
		switch (pri->sys_args[0]) {
		case UCREDSYS_UCREDGET:
		case UCREDSYS_GETPEERUCRED:
			if (err == 0)
				show_ucred(pri, (long)pri->sys_args[2]);
			break;
		}
		break;
	case SYS_bind:
	case SYS_connect:
		if (pri->sys_nargs > 2)
			show_sockaddr(pri, "name", (long)pri->sys_args[1],
			    0, (long)pri->sys_args[2]);
		break;
	case SYS_sendto:
		if (pri->sys_nargs > 5)
			show_sockaddr(pri, "to", (long)pri->sys_args[4], 0,
			    pri->sys_args[5]);
		break;
	case SYS_accept:
		if (!err && pri->sys_nargs > 2)
			show_sockaddr(pri, "name", (long)pri->sys_args[1],
			    (long)pri->sys_args[2], 0);
		break;
	case SYS_getsockname:
	case SYS_getpeername:
		if (!err && pri->sys_nargs > 2)
			show_sockaddr(pri, "name", (long)pri->sys_args[1],
			    (long)pri->sys_args[2], 0);
		break;
	case SYS_cladm:
		if (!err && pri->sys_nargs > 2)
			show_cladm(pri, pri->sys_args[0], pri->sys_args[1],
			    (long)pri->sys_args[2]);
		break;
	case SYS_recvfrom:
		if (!err && pri->sys_nargs > 5)
			show_sockaddr(pri, "from", (long)pri->sys_args[4],
			    (long)pri->sys_args[5], 0);
		break;
	case SYS_recvmsg:
		if (err)
			break;
		/* FALLTHROUGH */
	case SYS_sendmsg:
		if (pri->sys_nargs <= 2)
			break;
#ifdef _LP64
		if (lp64)
			show_msghdr(pri, pri->sys_args[1]);
		else
			show_msghdr32(pri, pri->sys_args[1]);
#else
		show_msghdr(pri, pri->sys_args[1]);
#endif
		break;
	case SYS_door:
		show_doors(pri);
		break;
	case SYS_sendfilev:
		if (pri->sys_nargs != 5)
			break;

		if (pri->sys_args[0] == SENDFILEV) {
			show_sendfilevec(pri, (int)pri->sys_args[1],
			    (sendfilevec_t *)pri->sys_args[2],
			    (int)pri->sys_args[3]);
		} else if (pri->sys_args[0] == SENDFILEV64) {
			show_sendfilevec64(pri, (int)pri->sys_args[1],
			    (sendfilevec64_t *)pri->sys_args[2],
			    (int)pri->sys_args[3]);
		}
		break;
	case SYS_memcntl:
		show_memcntl(pri);
		break;
	case SYS_lwp_park:
		/*
		 * subcode 0: lwp_park(timespec_t *, id_t)
		 * subcode 4: lwp_set_park(timespec_t *, id_t)
		 */
		if (pri->sys_nargs > 1 &&
		    (pri->sys_args[0] == 0 || pri->sys_args[0] == 4))
			show_timestruc(pri, (long)pri->sys_args[1], "timeout");
		/* subcode 2: lwp_unpark_all(id_t *, int) */
		if (pri->sys_nargs > 2 && pri->sys_args[0] == 2)
			show_ids(pri, (long)pri->sys_args[1],
			    (int)pri->sys_args[2]);
		break;
	case SYS_ntp_gettime:
		if (!err)
			show_ntp_gettime(pri);
		break;
	case SYS_ntp_adjtime:
		if (!err)
			show_ntp_adjtime(pri);
		break;
	case SYS_rusagesys:
		if (!err)
			if (pri->sys_args[0] == _RUSAGESYS_GETRUSAGE) {
#ifdef _LP64
				if (!lp64)
					show_getrusage32(pri->sys_args[1]);
				else
#endif
					show_getrusage(pri->sys_args[1]);
			}
		break;
	case SYS_port:
		show_ports(pri);
		break;
	case SYS_zone:
		show_zones(pri);
		break;
	case SYS_rctlsys:
		show_rctls(pri);
		break;
	case SYS_utimesys:
		show_utimesys(pri);
		break;
	}
}