Change the argument formatting function to use a stdio FILE object opened

with open_memstream() to build the string for each argument.  This allows
for more complicated argument building without resorting to intermediate
malloc's, etc.

Related, the strsig*() functions no longer return allocated strings but
use a static global buffer instead.
This commit is contained in:
John Baldwin 2015-08-19 00:49:50 +00:00
parent c13244b92e
commit f083f6894c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=286913
2 changed files with 158 additions and 224 deletions

View File

@ -149,15 +149,13 @@ set_etype(struct trussinfo *trussinfo)
char *
strsig(int sig)
{
char *ret;
static char tmp[64];
ret = NULL;
if (sig > 0 && sig < NSIG) {
asprintf(&ret, "SIG%s", sys_signame[sig]);
if (ret == NULL)
return (NULL);
snprintf(tmp, sizeof(tmp), "SIG%s", sys_signame[sig]);
return (tmp);
}
return (ret);
return (NULL);
}
int
@ -340,7 +338,6 @@ main(int ac, char **av)
fprintf(trussinfo->outfile,
"SIGNAL %u (%s)\n", trussinfo->pr_data,
signame == NULL ? "?" : signame);
free(signame);
break;
case S_EXIT:
if (trussinfo->flags & COUNTONLY)

View File

@ -731,12 +731,15 @@ get_string(pid_t pid, void *addr, int max)
static char *
strsig2(int sig)
{
char *tmp;
static char tmp[sizeof(int) * 3 + 1];
char *ret;
tmp = strsig(sig);
if (tmp == NULL)
asprintf(&tmp, "%d", sig);
return (tmp);
ret = strsig(sig);
if (ret == NULL) {
snprintf(tmp, sizeof(tmp), "%d", sig);
ret = tmp;
}
return (ret);
}
/*
@ -753,32 +756,34 @@ char *
print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct trussinfo *trussinfo)
{
FILE *fp;
char *tmp;
size_t tmplen;
pid_t pid;
tmp = NULL;
fp = open_memstream(&tmp, &tmplen);
pid = trussinfo->pid;
switch (sc->type & ARG_MASK) {
case Hex:
asprintf(&tmp, "0x%x", (int)args[sc->offset]);
fprintf(fp, "0x%x", (int)args[sc->offset]);
break;
case Octal:
asprintf(&tmp, "0%o", (int)args[sc->offset]);
fprintf(fp, "0%o", (int)args[sc->offset]);
break;
case Int:
asprintf(&tmp, "%d", (int)args[sc->offset]);
fprintf(fp, "%d", (int)args[sc->offset]);
break;
case LongHex:
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
case Long:
asprintf(&tmp, "%ld", args[sc->offset]);
fprintf(fp, "%ld", args[sc->offset]);
break;
case Name: {
/* NULL-terminated string. */
char *tmp2;
tmp2 = get_string(pid, (void*)args[sc->offset], 0);
asprintf(&tmp, "\"%s\"", tmp2);
fprintf(fp, "\"%s\"", tmp2);
free(tmp2);
break;
}
@ -814,11 +819,11 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
len--;
truncated = 1;
};
asprintf(&tmp, "\"%s\"%s", tmp3, truncated ?
fprintf(fp, "\"%s\"%s", tmp3, truncated ?
"..." : "");
free(tmp3);
} else {
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
}
break;
}
@ -857,37 +862,35 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
}
#ifdef __LP64__
case Quad:
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
#else
case Quad: {
unsigned long long ll;
ll = *(unsigned long long *)(args + sc->offset);
asprintf(&tmp, "0x%llx", ll);
fprintf(fp, "0x%llx", ll);
break;
}
#endif
case Ptr:
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
case Readlinkres: {
char *tmp2;
if (retval == -1) {
tmp = strdup("");
if (retval == -1)
break;
}
tmp2 = get_string(pid, (void*)args[sc->offset], retval);
asprintf(&tmp, "\"%s\"", tmp2);
fprintf(fp, "\"%s\"", tmp2);
free(tmp2);
break;
}
case Ioctl: {
const char *temp = ioctlname(args[sc->offset]);
if (temp)
tmp = strdup(temp);
fputs(temp, fp);
else {
unsigned long arg = args[sc->offset];
asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }",
arg, arg & IOC_OUT ? "R" : "",
arg & IOC_IN ? "W" : "", IOCGROUP(arg),
isprint(IOCGROUP(arg)) ? (char)IOCGROUP(arg) : '?',
@ -899,22 +902,19 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct timespec ts;
if (get_struct(pid, (void *)args[sc->offset], &ts,
sizeof(ts)) != -1)
asprintf(&tmp, "{ %ld.%09ld }", (long)ts.tv_sec,
fprintf(fp, "{ %ld.%09ld }", (long)ts.tv_sec,
ts.tv_nsec);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Timespec2: {
struct timespec ts[2];
FILE *fp;
size_t len;
const char *sep;
unsigned int i;
if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
!= -1) {
fp = open_memstream(&tmp, &len);
fputs("{ ", fp);
sep = "";
for (i = 0; i < nitems(ts); i++) {
@ -934,43 +934,42 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
}
}
fputs(" }", fp);
fclose(fp);
} else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Timeval: {
struct timeval tv;
if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
!= -1)
asprintf(&tmp, "{ %ld.%06ld }", (long)tv.tv_sec,
fprintf(fp, "{ %ld.%06ld }", (long)tv.tv_sec,
tv.tv_usec);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Timeval2: {
struct timeval tv[2];
if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
!= -1)
asprintf(&tmp, "{ %ld.%06ld, %ld.%06ld }",
fprintf(fp, "{ %ld.%06ld, %ld.%06ld }",
(long)tv[0].tv_sec, tv[0].tv_usec,
(long)tv[1].tv_sec, tv[1].tv_usec);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Itimerval: {
struct itimerval itv;
if (get_struct(pid, (void *)args[sc->offset], &itv,
sizeof(itv)) != -1)
asprintf(&tmp, "{ %ld.%06ld, %ld.%06ld }",
fprintf(fp, "{ %ld.%06ld, %ld.%06ld }",
(long)itv.it_interval.tv_sec,
itv.it_interval.tv_usec,
(long)itv.it_value.tv_sec,
itv.it_value.tv_usec);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case LinuxSockArgs:
@ -978,11 +977,11 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct linux_socketcall_args largs;
if (get_struct(pid, (void *)args[sc->offset], (void *)&largs,
sizeof(largs)) != -1)
asprintf(&tmp, "{ %s, 0x%lx }",
fprintf(fp, "{ %s, 0x%lx }",
lookup(linux_socketcall_ops, largs.what, 10),
(long unsigned int)largs.args);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Pollfd: {
@ -992,37 +991,23 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
* syscall.
*/
struct pollfd *pfd;
int numfds = args[sc->offset+1];
int bytes = sizeof(struct pollfd) * numfds;
int i, tmpsize, u, used;
const int per_fd = 100;
int numfds = args[sc->offset + 1];
size_t bytes = sizeof(struct pollfd) * numfds;
int i;
if ((pfd = malloc(bytes)) == NULL)
err(1, "Cannot malloc %d bytes for pollfd array",
err(1, "Cannot malloc %zu bytes for pollfd array",
bytes);
if (get_struct(pid, (void *)args[sc->offset], pfd, bytes)
!= -1) {
used = 0;
tmpsize = 1 + per_fd * numfds + 2;
if ((tmp = malloc(tmpsize)) == NULL)
err(1, "Cannot alloc %d bytes for poll output",
tmpsize);
tmp[used++] = '{';
tmp[used++] = ' ';
fputs("{", fp);
for (i = 0; i < numfds; i++) {
u = snprintf(tmp + used, per_fd, "%s%d/%s",
i > 0 ? " " : "", pfd[i].fd,
fprintf(fp, " %d/%s", pfd[i].fd,
xlookup_bits(poll_flags, pfd[i].events));
if (u > 0)
used += u < per_fd ? u : per_fd;
}
tmp[used++] = ' ';
tmp[used++] = '}';
tmp[used++] = '\0';
fputs(" }", fp);
} else {
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
}
free(pfd);
break;
@ -1035,108 +1020,86 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
*/
fd_set *fds;
int numfds = args[0];
int bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
int i, tmpsize, u, used;
const int per_fd = 20;
size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS;
int i;
if ((fds = malloc(bytes)) == NULL)
err(1, "Cannot malloc %d bytes for fd_set array",
err(1, "Cannot malloc %zu bytes for fd_set array",
bytes);
if (get_struct(pid, (void *)args[sc->offset], fds, bytes)
!= -1) {
used = 0;
tmpsize = 1 + numfds * per_fd + 2;
if ((tmp = malloc(tmpsize)) == NULL)
err(1, "Cannot alloc %d bytes for fd_set "
"output", tmpsize);
tmp[used++] = '{';
tmp[used++] = ' ';
fputs("{", fp);
for (i = 0; i < numfds; i++) {
if (FD_ISSET(i, fds)) {
u = snprintf(tmp + used, per_fd, "%d ",
i);
if (u > 0)
used += u < per_fd ? u : per_fd;
}
if (FD_ISSET(i, fds))
fprintf(fp, " %d", i);
}
tmp[used++] = '}';
tmp[used++] = '\0';
fputs(" }", fp);
} else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
free(fds);
break;
}
case Signal:
tmp = strsig2(args[sc->offset]);
fputs(strsig2(args[sc->offset]), fp);
break;
case Sigset: {
long sig;
sigset_t ss;
int i, used;
char *signame;
int i, first;
sig = args[sc->offset];
if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
sizeof(ss)) == -1) {
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
tmp = malloc(sys_nsig * 8 + 2); /* 7 bytes avg per signal name */
used = 0;
tmp[used++] = '{';
tmp[used++] = ' ';
fputs("{ ", fp);
first = 1;
for (i = 1; i < sys_nsig; i++) {
if (sigismember(&ss, i)) {
signame = strsig(i);
used += sprintf(tmp + used, "%s|", signame);
free(signame);
fprintf(fp, "%s%s", !first ? "|" : "",
strsig(i));
first = 0;
}
}
if (tmp[used - 1] == '|')
used--;
tmp[used++] = ' ';
tmp[used++] = '}';
tmp[used++] = '\0';
if (!first)
fputc(' ', fp);
fputc('}', fp);
break;
}
case Sigprocmask: {
tmp = strdup(xlookup(sigprocmask_ops, args[sc->offset]));
fputs(xlookup(sigprocmask_ops, args[sc->offset]), fp);
break;
}
case Fcntlflag: {
/* XXX output depends on the value of the previous argument */
switch (args[sc->offset-1]) {
case F_SETFD:
tmp = strdup(xlookup_bits(fcntlfd_arg,
args[sc->offset]));
fputs(xlookup_bits(fcntlfd_arg, args[sc->offset]), fp);
break;
case F_SETFL:
tmp = strdup(xlookup_bits(fcntlfl_arg,
args[sc->offset]));
fputs(xlookup_bits(fcntlfl_arg, args[sc->offset]), fp);
break;
case F_GETFD:
case F_GETFL:
case F_GETOWN:
tmp = strdup("");
break;
default:
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
break;
}
case Open:
tmp = strdup(xlookup_bits(open_flags, args[sc->offset]));
fputs(xlookup_bits(open_flags, args[sc->offset]), fp);
break;
case Fcntl:
tmp = strdup(xlookup(fcntl_arg, args[sc->offset]));
fputs(xlookup(fcntl_arg, args[sc->offset]), fp);
break;
case Mprot:
tmp = strdup(xlookup_bits(mprot_flags, args[sc->offset]));
fputs(xlookup_bits(mprot_flags, args[sc->offset]), fp);
break;
case Mmapflags: {
char *base, *alignstr;
int align, flags;
/*
@ -1150,59 +1113,46 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
align = args[sc->offset] & MAP_ALIGNMENT_MASK;
if (align != 0) {
if (align == MAP_ALIGNED_SUPER)
alignstr = strdup("MAP_ALIGNED_SUPER");
fputs("MAP_ALIGNED_SUPER", fp);
else
asprintf(&alignstr, "MAP_ALIGNED(%d)",
fprintf(fp, "MAP_ALIGNED(%d)",
align >> MAP_ALIGNMENT_SHIFT);
if (flags == 0) {
tmp = alignstr;
if (flags == 0)
break;
}
} else
alignstr = NULL;
base = strdup(xlookup_bits(mmap_flags, flags));
if (alignstr == NULL) {
tmp = base;
break;
fputc('|', fp);
}
asprintf(&tmp, "%s|%s", alignstr, base);
free(alignstr);
free(base);
fputs(xlookup_bits(mmap_flags, flags), fp);
break;
}
case Whence:
tmp = strdup(xlookup(whence_arg, args[sc->offset]));
fputs(xlookup(whence_arg, args[sc->offset]), fp);
break;
case Sockdomain:
tmp = strdup(xlookup(sockdomain_arg, args[sc->offset]));
fputs(xlookup(sockdomain_arg, args[sc->offset]), fp);
break;
case Socktype: {
FILE *fp;
size_t len;
int type, flags;
flags = args[sc->offset] & (SOCK_CLOEXEC | SOCK_NONBLOCK);
type = args[sc->offset] & ~flags;
fp = open_memstream(&tmp, &len);
fputs(xlookup(socktype_arg, type), fp);
if (flags & SOCK_CLOEXEC)
fprintf(fp, "|SOCK_CLOEXEC");
if (flags & SOCK_NONBLOCK)
fprintf(fp, "|SOCK_NONBLOCK");
fclose(fp);
break;
}
case Shutdown:
tmp = strdup(xlookup(shutdown_arg, args[sc->offset]));
fputs(xlookup(shutdown_arg, args[sc->offset]), fp);
break;
case Resource:
tmp = strdup(xlookup(resource_arg, args[sc->offset]));
fputs(xlookup(resource_arg, args[sc->offset]), fp);
break;
case Pathconf:
tmp = strdup(xlookup(pathconf_arg, args[sc->offset]));
fputs(xlookup(pathconf_arg, args[sc->offset]), fp);
break;
case Rforkflags:
tmp = strdup(xlookup_bits(rfork_flags, args[sc->offset]));
fputs(xlookup_bits(rfork_flags, args[sc->offset]), fp);
break;
case Sockaddr: {
struct sockaddr_storage ss;
@ -1211,19 +1161,20 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct sockaddr_in6 *lsin6;
struct sockaddr_un *sun;
struct sockaddr *sa;
char *p;
u_char *q;
int i;
if (args[sc->offset] == 0) {
asprintf(&tmp, "NULL");
fputs("NULL", fp);
break;
}
/* yuck: get ss_len */
if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1)
err(1, "get_struct %p", (void *)args[sc->offset]);
sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) {
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
/*
* If ss_len is 0, then try to guess from the sockaddr type.
* AF_UNIX may be initialized incorrectly, so always frob
@ -1234,73 +1185,71 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
case AF_INET:
ss.ss_len = sizeof(*lsin);
break;
case AF_INET6:
ss.ss_len = sizeof(*lsin6);
break;
case AF_UNIX:
ss.ss_len = sizeof(*sun);
break;
default:
/* hurrrr */
break;
}
}
if (get_struct(pid, (void *)args[sc->offset], (void *)&ss,
if (ss.ss_len != 0 &&
get_struct(pid, (void *)args[sc->offset], (void *)&ss,
ss.ss_len) == -1) {
err(2, "get_struct %p", (void *)args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
switch (ss.ss_family) {
case AF_INET:
lsin = (struct sockaddr_in *)&ss;
inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr);
asprintf(&tmp, "{ AF_INET %s:%d }", addr,
fprintf(fp, "{ AF_INET %s:%d }", addr,
htons(lsin->sin_port));
break;
case AF_INET6:
lsin6 = (struct sockaddr_in6 *)&ss;
inet_ntop(AF_INET6, &lsin6->sin6_addr, addr,
sizeof addr);
asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr,
fprintf(fp, "{ AF_INET6 [%s]:%d }", addr,
htons(lsin6->sin6_port));
break;
case AF_UNIX:
sun = (struct sockaddr_un *)&ss;
asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path);
fprintf(fp, "{ AF_UNIX \"%s\" }", sun->sun_path);
break;
default:
sa = (struct sockaddr *)&ss;
asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data "
"= { %n%*s } }", (int)sa->sa_len,
(int)sa->sa_family, &i,
6 * (int)(sa->sa_len - ((char *)&sa->sa_data -
(char *)sa)), "");
if (tmp != NULL) {
p = tmp + i;
for (q = (u_char *)&sa->sa_data;
q < (u_char *)sa + sa->sa_len; q++)
p += sprintf(p, " %#02x,", *q);
}
fprintf(fp,
"{ sa_len = %d, sa_family = %d, sa_data = {",
(int)sa->sa_len, (int)sa->sa_family);
for (q = (u_char *)sa->sa_data;
q < (u_char *)sa + sa->sa_len; q++)
fprintf(fp, "%s 0x%02x",
q == (u_char *)sa->sa_data ? "" : ",",
*q);
fputs(" } }", fp);
}
break;
}
case Sigaction: {
struct sigaction sa;
char *hand;
const char *h;
if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa))
!= -1) {
asprintf(&hand, "%p", sa.sa_handler);
fputs("{ ", fp);
if (sa.sa_handler == SIG_DFL)
h = "SIG_DFL";
fputs("SIG_DFL", fp);
else if (sa.sa_handler == SIG_IGN)
h = "SIG_IGN";
fputs("SIG_IGN", fp);
else
h = hand;
asprintf(&tmp, "{ %s %s ss_t }", h,
fprintf(fp, "%p", sa.sa_handler);
fprintf(fp, " %s ss_t }",
xlookup_bits(sigaction_flags, sa.sa_flags));
free(hand);
} else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Kevent: {
@ -1313,48 +1262,36 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
*/
struct kevent *ke;
int numevents = -1;
int bytes = 0;
int i, tmpsize, u, used;
const int per_ke = 100;
size_t bytes;
int i;
if (sc->offset == 1)
numevents = args[sc->offset+1];
else if (sc->offset == 3 && retval != -1)
numevents = retval;
if (numevents >= 0)
if (numevents >= 0) {
bytes = sizeof(struct kevent) * numevents;
if ((ke = malloc(bytes)) == NULL)
err(1, "Cannot malloc %d bytes for kevent array",
bytes);
if ((ke = malloc(bytes)) == NULL)
err(1,
"Cannot malloc %zu bytes for kevent array",
bytes);
} else
ke = NULL;
if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset],
ke, bytes) != -1) {
used = 0;
tmpsize = 1 + per_ke * numevents + 2;
if ((tmp = malloc(tmpsize)) == NULL)
err(1, "Cannot alloc %d bytes for kevent "
"output", tmpsize);
tmp[used++] = '{';
tmp[used++] = ' ';
for (i = 0; i < numevents; i++) {
u = snprintf(tmp + used, per_ke,
"%s%p,%s,%s,%d,%p,%p",
i > 0 ? " " : "",
fputc('{', fp);
for (i = 0; i < numevents; i++)
fprintf(fp, " %p,%s,%s,%d,%p,%p",
(void *)ke[i].ident,
xlookup(kevent_filters, ke[i].filter),
xlookup_bits(kevent_flags, ke[i].flags),
ke[i].fflags,
(void *)ke[i].data,
(void *)ke[i].udata);
if (u > 0)
used += u < per_ke ? u : per_ke;
}
tmp[used++] = ' ';
tmp[used++] = '}';
tmp[used++] = '\0';
fputs(" }", fp);
} else {
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
}
free(ke);
break;
@ -1365,12 +1302,12 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
!= -1) {
char mode[12];
strmode(st.st_mode, mode);
asprintf(&tmp,
fprintf(fp,
"{ mode=%s,inode=%jd,size=%jd,blksize=%ld }", mode,
(intmax_t)st.st_ino, (intmax_t)st.st_size,
(long)st.st_blksize);
} else {
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
}
break;
}
@ -1378,82 +1315,82 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct rusage ru;
if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru))
!= -1) {
asprintf(&tmp,
fprintf(fp,
"{ u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld }",
(long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec,
(long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
ru.ru_inblock, ru.ru_oublock);
} else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Rlimit: {
struct rlimit rl;
if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl))
!= -1) {
asprintf(&tmp, "{ cur=%ju,max=%ju }",
fprintf(fp, "{ cur=%ju,max=%ju }",
rl.rlim_cur, rl.rlim_max);
} else
asprintf(&tmp, "0x%lx", args[sc->offset]);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case ExitStatus: {
char *signame;
int status;
signame = NULL;
if (get_struct(pid, (void *)args[sc->offset], &status,
sizeof(status)) != -1) {
fputs("{ ", fp);
if (WIFCONTINUED(status))
tmp = strdup("{ CONTINUED }");
fputs("CONTINUED", fp);
else if (WIFEXITED(status))
asprintf(&tmp, "{ EXITED,val=%d }",
fprintf(fp, "EXITED,val=%d",
WEXITSTATUS(status));
else if (WIFSIGNALED(status))
asprintf(&tmp, "{ SIGNALED,sig=%s%s }",
signame = strsig2(WTERMSIG(status)),
fprintf(fp, "SIGNALED,sig=%s%s",
strsig2(WTERMSIG(status)),
WCOREDUMP(status) ? ",cored" : "");
else
asprintf(&tmp, "{ STOPPED,sig=%s }",
signame = strsig2(WTERMSIG(status)));
fprintf(fp, "STOPPED,sig=%s",
strsig2(WTERMSIG(status)));
fputs(" }", fp);
} else
asprintf(&tmp, "0x%lx", args[sc->offset]);
free(signame);
fprintf(fp, "0x%lx", args[sc->offset]);
break;
}
case Waitoptions:
tmp = strdup(xlookup_bits(wait_options, args[sc->offset]));
fputs(xlookup_bits(wait_options, args[sc->offset]), fp);
break;
case Idtype:
tmp = strdup(xlookup(idtype_arg, args[sc->offset]));
fputs(xlookup(idtype_arg, args[sc->offset]), fp);
break;
case Procctl:
tmp = strdup(xlookup(procctl_arg, args[sc->offset]));
fputs(xlookup(procctl_arg, args[sc->offset]), fp);
break;
case Umtxop:
tmp = strdup(xlookup(umtx_ops, args[sc->offset]));
fputs(xlookup(umtx_ops, args[sc->offset]), fp);
break;
case Atfd:
if ((int)args[sc->offset] == AT_FDCWD)
tmp = strdup("AT_FDCWD");
fputs("AT_FDCWD", fp);
else
asprintf(&tmp, "%d", (int)args[sc->offset]);
fprintf(fp, "%d", (int)args[sc->offset]);
break;
case Atflags:
tmp = strdup(xlookup_bits(at_flags, args[sc->offset]));
fputs(xlookup_bits(at_flags, args[sc->offset]), fp);
break;
case Accessmode:
if (args[sc->offset] == F_OK)
tmp = strdup("F_OK");
fputs("F_OK", fp);
else
tmp = strdup(xlookup_bits(access_modes,
args[sc->offset]));
fputs(xlookup_bits(access_modes, args[sc->offset]), fp);
break;
case Sysarch:
tmp = strdup(xlookup(sysarch_ops, args[sc->offset]));
fputs(xlookup(sysarch_ops, args[sc->offset]), fp);
break;
default:
errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
}
fclose(fp);
return (tmp);
}