#include <stdio.h>
#define __EXTENSIONS__
#include <string.h>
#undef __EXTENSIONS__
#include <signal.h>
#include <errno.h>
#include "libproc.h"
#include <sys/procfs_isa.h>
static const char *
rawfltname(int flt)
{
const char *name;
switch (flt) {
case FLTILL: name = "FLTILL"; break;
case FLTPRIV: name = "FLTPRIV"; break;
case FLTBPT: name = "FLTBPT"; break;
case FLTTRACE: name = "FLTTRACE"; break;
case FLTACCESS: name = "FLTACCESS"; break;
case FLTBOUNDS: name = "FLTBOUNDS"; break;
case FLTIOVF: name = "FLTIOVF"; break;
case FLTIZDIV: name = "FLTIZDIV"; break;
case FLTFPE: name = "FLTFPE"; break;
case FLTSTACK: name = "FLTSTACK"; break;
case FLTPAGE: name = "FLTPAGE"; break;
case FLTWATCH: name = "FLTWATCH"; break;
case FLTCPCOVF: name = "FLTCPCOVF"; break;
default: name = NULL; break;
}
return (name);
}
char *
proc_fltname(int flt, char *buf, size_t bufsz)
{
const char *name = rawfltname(flt);
size_t len;
if (bufsz == 0)
return (NULL);
if (name != NULL) {
len = strlen(name);
(void) strncpy(buf, name, bufsz);
} else {
len = snprintf(buf, bufsz, "FLT#%d", flt);
}
if (len >= bufsz)
buf[bufsz-1] = '\0';
return (buf);
}
char *
proc_signame(int sig, char *buf, size_t bufsz)
{
char name[SIG2STR_MAX+4];
size_t len;
if (bufsz == 0)
return (NULL);
(void) strcpy(name, "SIG");
if (sig2str(sig, name+3) == 0) {
len = strlen(name);
(void) strncpy(buf, name, bufsz);
} else {
len = snprintf(buf, bufsz, "SIG#%d", sig);
}
if (len >= bufsz)
buf[bufsz-1] = '\0';
return (buf);
}
static const char *const systable[] = {
NULL,
"_exit",
NULL,
"read",
"write",
"open",
"close",
"linkat",
NULL,
"link",
"unlink",
"symlinkat",
"chdir",
"time",
"mknod",
"chmod",
"chown",
"brk",
"stat",
"lseek",
"getpid",
"mount",
"readlinkat",
"setuid",
"getuid",
"stime",
"ptrace",
"alarm",
"fstat",
"pause",
NULL,
"stty",
"gtty",
"access",
"nice",
"statfs",
"sync",
"kill",
"fstatfs",
"pgrpsys",
"uucopystr",
NULL,
"pipe",
"times",
"profil",
"faccessat",
"setgid",
"getgid",
"mknodat",
"msgsys",
"sysi86",
"acct",
"shmsys",
"semsys",
"ioctl",
"uadmin",
"fchownat",
"utssys",
"fdsync",
"execve",
"umask",
"chroot",
"fcntl",
"ulimit",
"renameat",
"unlinkat",
"fstatat",
"fstatat64",
"openat",
"openat64",
"tasksys",
"acctctl",
"exacctsys",
"getpagesizes",
"rctlsys",
"issetugid",
"fsat",
"lwp_park",
"sendfilev",
"rmdir",
"mkdir",
"getdents",
"privsys",
"ucredsys",
"sysfs",
"getmsg",
"putmsg",
NULL,
"lstat",
"symlink",
"readlink",
"setgroups",
"getgroups",
"fchmod",
"fchown",
"sigprocmask",
"sigsuspend",
"sigaltstack",
"sigaction",
"sigpending",
"context",
"fchmodat",
"mkdirat",
"statvfs",
"fstatvfs",
"getloadavg",
"nfssys",
"waitid",
"sigsendsys",
"hrtsys",
"acancel",
"async",
"priocntlsys",
"pathconf",
"mincore",
"mmap",
"mprotect",
"munmap",
"fpathconf",
"vfork",
"fchdir",
"readv",
"writev",
"preadv",
"pwritev",
"upanic",
"getrandom",
"mmapobj",
"setrlimit",
"getrlimit",
"lchown",
"memcntl",
"getpmsg",
"putpmsg",
"rename",
"uname",
"setegid",
"sysconfig",
"adjtime",
"systeminfo",
"sharefs",
"seteuid",
"forksys",
NULL,
"sigtimedwait",
"lwp_info",
"yield",
NULL,
"lwp_sema_post",
"lwp_sema_trywait",
"lwp_detatch",
"corectl",
"modctl",
"fchroot",
NULL,
"vhangup",
"gettimeofday",
"getitimer",
"setitimer",
"lwp_create",
"lwp_exit",
"lwp_suspend",
"lwp_continue",
"lwp_kill",
"lwp_self",
"lwp_sigmask",
"lwp_private",
"lwp_wait",
"lwp_mutex_wakeup",
NULL,
"lwp_cond_wait",
"lwp_cond_signal",
"lwp_cond_broadcast",
"pread",
"pwrite",
"llseek",
"inst_sync",
"brand",
"kaio",
"cpc",
"lgrpsys",
"rusagesys",
"portfs",
"pollsys",
"labelsys",
"acl",
"auditsys",
"processor_bind",
"processor_info",
"p_online",
"sigqueue",
"clock_gettime",
"clock_settime",
"clock_getres",
"timer_create",
"timer_delete",
"timer_settime",
"timer_gettime",
"timer_getoverrun",
"nanosleep",
"facl",
"door",
"setreuid",
"setregid",
"install_utrap",
"signotify",
"schedctl",
"pset",
"sparc_utrap_install",
"resolvepath",
"lwp_mutex_timedlock",
"lwp_sema_timedwait",
"lwp_rwlock_sys",
"getdents64",
"mmap64",
"stat64",
"lstat64",
"fstat64",
"statvfs64",
"fstatvfs64",
"setrlimit64",
"getrlimit64",
"pread64",
"pwrite64",
NULL,
"open64",
"rpcmod",
"zone",
"autofssys",
"getcwd",
"so_socket",
"so_socketpair",
"bind",
"listen",
"accept",
"connect",
"shutdown",
"recv",
"recvfrom",
"recvmsg",
"send",
"sendmsg",
"sendto",
"getpeername",
"getsockname",
"getsockopt",
"setsockopt",
"sockconfig",
"ntp_gettime",
"ntp_adjtime",
"lwp_mutex_unlock",
"lwp_mutex_trylock",
"lwp_mutex_register",
"cladm",
"uucopy",
"umount2"
};
#define SYSEND (sizeof (systable) / sizeof (systable[0]))
char *
proc_sysname(int sys, char *buf, size_t bufsz)
{
const char *name;
size_t len;
if (bufsz == 0)
return (NULL);
if (sys >= 0 && sys < SYSEND)
name = systable[sys];
else
name = NULL;
if (name != NULL) {
len = strlen(name);
(void) strncpy(buf, name, bufsz);
} else {
len = snprintf(buf, bufsz, "SYS#%d", sys);
}
if (len >= bufsz)
buf[bufsz-1] = '\0';
return (buf);
}
int
proc_str2flt(const char *str, int *fltnum)
{
char *next;
int i;
i = strtol(str, &next, 0);
if (i > 0 && i <= PRMAXFAULT && *next == '\0') {
*fltnum = i;
return (0);
}
for (i = 1; i <= PRMAXFAULT; i++) {
const char *s = rawfltname(i);
if (s && (strcasecmp(s, str) == 0 ||
strcasecmp(s + 3, str) == 0)) {
*fltnum = i;
return (0);
}
}
return (-1);
}
int
proc_str2sig(const char *str, int *signum)
{
if (strncasecmp(str, "SIG", 3) == 0)
str += 3;
return (str2sig(str, signum));
}
int
proc_str2sys(const char *str, int *sysnum)
{
char *next;
int i;
i = strtol(str, &next, 0);
if (i > 0 && i <= PRMAXSYS && *next == '\0') {
*sysnum = i;
return (0);
}
for (i = 1; i < SYSEND; i++) {
if (systable[i] != NULL && strcmp(systable[i], str) == 0) {
*sysnum = i;
return (0);
}
}
return (-1);
}
char *
proc_fltset2str(const fltset_t *set, const char *delim, int m,
char *buf, size_t len)
{
char name[FLT2STR_MAX], *p = buf;
size_t n;
int i;
if (buf == NULL || len < 1) {
errno = EINVAL;
return (NULL);
}
buf[0] = '\0';
for (i = 1; i <= PRMAXFAULT; i++) {
if ((prismember(set, i) != 0) ^ (m == 0)) {
(void) proc_fltname(i, name, sizeof (name));
if (buf[0] != '\0')
n = snprintf(p, len, "%s%s", delim, name);
else
n = snprintf(p, len, "%s", name);
if (n != strlen(p)) {
errno = ENAMETOOLONG;
return (NULL);
}
len -= n;
p += n;
}
}
return (buf);
}
char *
proc_sigset2str(const sigset_t *set, const char *delim, int m,
char *buf, size_t len)
{
char name[SIG2STR_MAX], *p = buf;
size_t n;
int i;
if (buf == NULL || len < 1) {
errno = EINVAL;
return (NULL);
}
m = (m != 0);
buf[0] = '\0';
for (i = 1; i < NSIG; i++) {
if (sigismember(set, i) == m) {
(void) sig2str(i, name);
if (buf[0] != '\0')
n = snprintf(p, len, "%s%s", delim, name);
else
n = snprintf(p, len, "%s", name);
if (n != strlen(p)) {
errno = ENAMETOOLONG;
return (NULL);
}
len -= n;
p += n;
}
}
return (buf);
}
char *
proc_sysset2str(const sysset_t *set, const char *delim, int m,
char *buf, size_t len)
{
char name[SYS2STR_MAX], *p = buf;
size_t n;
int i;
if (buf == NULL || len < 1) {
errno = EINVAL;
return (NULL);
}
buf[0] = '\0';
for (i = 1; i <= PRMAXSYS; i++) {
if ((prismember(set, i) != 0) ^ (m == 0)) {
(void) proc_sysname(i, name, sizeof (name));
if (buf[0] != '\0')
n = snprintf(p, len, "%s%s", delim, name);
else
n = snprintf(p, len, "%s", name);
if (n != strlen(p)) {
errno = ENAMETOOLONG;
return (NULL);
}
len -= n;
p += n;
}
}
return (buf);
}
char *
proc_str2fltset(const char *s, const char *delim, int m, fltset_t *set)
{
char *p, *q, *t;
int flt;
if (m) {
premptyset(set);
} else {
prfillset(set);
}
t = strdupa(s);
for (p = strtok_r(t, delim, &q); p != NULL;
p = strtok_r(NULL, delim, &q)) {
if (proc_str2flt(p, &flt) == -1) {
errno = EINVAL;
return ((char *)s + (p - t));
}
if (m)
praddset(set, flt);
else
prdelset(set, flt);
}
return (NULL);
}
char *
proc_str2sigset(const char *s, const char *delim, int m, sigset_t *set)
{
char *p, *q, *t;
int sig;
if (m) {
premptyset(set);
} else {
prfillset(set);
}
t = strdupa(s);
for (p = strtok_r(t, delim, &q); p != NULL;
p = strtok_r(NULL, delim, &q)) {
if (proc_str2sig(p, &sig) == -1) {
errno = EINVAL;
return ((char *)s + (p - t));
}
if (m)
praddset(set, sig);
else
prdelset(set, sig);
}
return (NULL);
}
char *
proc_str2sysset(const char *s, const char *delim, int m, sysset_t *set)
{
char *p, *q, *t;
int sys;
if (m) {
premptyset(set);
} else {
prfillset(set);
}
t = strdupa(s);
for (p = strtok_r(t, delim, &q); p != NULL;
p = strtok_r(NULL, delim, &q)) {
if (proc_str2sys(p, &sys) == -1) {
errno = EINVAL;
return ((char *)s + (p - t));
}
if (m)
praddset(set, sys);
else
prdelset(set, sys);
}
return (NULL);
}
char *
proc_dmodelname(int dmodel, char *buf, size_t bufsz)
{
static const char *const dmdls[] = {
"PR_MODEL_UNKNOWN",
"PR_MODEL_ILP32",
"PR_MODEL_LP64",
NULL
};
size_t len;
if (bufsz == 0)
return (NULL);
if (dmodel > PR_MODEL_LP64 || dmodel < PR_MODEL_UNKNOWN) {
len = snprintf(buf, bufsz, "DMODEL#%d", dmodel);
} else {
len = strlen(dmdls[dmodel]);
(void) strncpy(buf, dmdls[dmodel], bufsz);
}
if (len >= bufsz)
buf[bufsz-1] = '\0';
return (buf);
}