diff options
Diffstat (limited to 'usr/src/lib/libproc/common/proc_names.c')
-rw-r--r-- | usr/src/lib/libproc/common/proc_names.c | 711 |
1 files changed, 711 insertions, 0 deletions
diff --git a/usr/src/lib/libproc/common/proc_names.c b/usr/src/lib/libproc/common/proc_names.c new file mode 100644 index 0000000000..249b9745a3 --- /dev/null +++ b/usr/src/lib/libproc/common/proc_names.c @@ -0,0 +1,711 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#define __EXTENSIONS__ +#include <string.h> +#undef __EXTENSIONS__ +#include <signal.h> +#include <alloca.h> +#include <errno.h> +#include "libproc.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); +} + +/* + * Return the name of a fault. + * Manufacture a name for unknown fault. + */ +char * +proc_fltname(int flt, char *buf, size_t bufsz) +{ + const char *name = rawfltname(flt); + size_t len; + + if (bufsz == 0) /* force a program failure */ + return (NULL); + + if (name != NULL) { + len = strlen(name); + (void) strncpy(buf, name, bufsz); + } else { + len = snprintf(buf, bufsz, "FLT#%d", flt); + } + + if (len >= bufsz) /* ensure null-termination */ + buf[bufsz-1] = '\0'; + + return (buf); +} + +/* + * Return the name of a signal. + * Manufacture a name for unknown signal. + */ +char * +proc_signame(int sig, char *buf, size_t bufsz) +{ + char name[SIG2STR_MAX+4]; + size_t len; + + if (bufsz == 0) /* force a program failure */ + return (NULL); + + /* sig2str() omits the leading "SIG" */ + (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) /* ensure null-termination */ + buf[bufsz-1] = '\0'; + + return (buf); +} + +static const char *const systable[] = { + NULL, /* 0 */ + "_exit", /* 1 */ + "forkall", /* 2 */ + "read", /* 3 */ + "write", /* 4 */ + "open", /* 5 */ + "close", /* 6 */ + "wait", /* 7 */ + "creat", /* 8 */ + "link", /* 9 */ + "unlink", /* 10 */ + "exec", /* 11 */ + "chdir", /* 12 */ + "time", /* 13 */ + "mknod", /* 14 */ + "chmod", /* 15 */ + "chown", /* 16 */ + "brk", /* 17 */ + "stat", /* 18 */ + "lseek", /* 19 */ + "getpid", /* 20 */ + "mount", /* 21 */ + "umount", /* 22 */ + "setuid", /* 23 */ + "getuid", /* 24 */ + "stime", /* 25 */ + "ptrace", /* 26 */ + "alarm", /* 27 */ + "fstat", /* 28 */ + "pause", /* 29 */ + "utime", /* 30 */ + "stty", /* 31 */ + "gtty", /* 32 */ + "access", /* 33 */ + "nice", /* 34 */ + "statfs", /* 35 */ + "sync", /* 36 */ + "kill", /* 37 */ + "fstatfs", /* 38 */ + "pgrpsys", /* 39 */ + NULL, /* 40 was xenix */ + "dup", /* 41 */ + "pipe", /* 42 */ + "times", /* 43 */ + "profil", /* 44 */ + "plock", /* 45 */ + "setgid", /* 46 */ + "getgid", /* 47 */ + "signal", /* 48 */ + "msgsys", /* 49 */ + "sysi86", /* 50 */ + "acct", /* 51 */ + "shmsys", /* 52 */ + "semsys", /* 53 */ + "ioctl", /* 54 */ + "uadmin", /* 55 */ + NULL, /* 56 */ + "utssys", /* 57 */ + "fdsync", /* 58 */ + "execve", /* 59 */ + "umask", /* 60 */ + "chroot", /* 61 */ + "fcntl", /* 62 */ + "ulimit", /* 63 */ + + /* The following 6 entries were reserved for the UNIX PC */ + NULL, /* 64 */ + NULL, /* 65 */ + NULL, /* 66 */ + NULL, /* 67 */ + NULL, /* 68 */ + NULL, /* 69 */ + + "tasksys", /* 70 */ + "acctctl", /* 71 */ + "exacctsys", /* 72 */ + "getpagesizes", /* 73 */ + "rctlsys", /* 74 */ + "issetugid", /* 75 */ + "fsat", /* 76 */ + "lwp_park", /* 77 */ + "sendfilev", /* 78 */ + "rmdir", /* 79 */ + "mkdir", /* 80 */ + "getdents", /* 81 */ + "privsys", /* 82 */ + "ucredsys", /* 83 */ + "sysfs", /* 84 */ + "getmsg", /* 85 */ + "putmsg", /* 86 */ + "poll", /* 87 */ + "lstat", /* 88 */ + "symlink", /* 89 */ + "readlink", /* 90 */ + "setgroups", /* 91 */ + "getgroups", /* 92 */ + "fchmod", /* 93 */ + "fchown", /* 94 */ + "sigprocmask", /* 95 */ + "sigsuspend", /* 96 */ + "sigaltstack", /* 97 */ + "sigaction", /* 98 */ + "sigpending", /* 99 */ + "context", /* 100 */ + "evsys", /* 101 */ + "evtrapret", /* 102 */ + "statvfs", /* 103 */ + "fstatvfs", /* 104 */ + "getloadavg", /* 105 */ + "nfssys", /* 106 */ + "waitid", /* 107 */ + "sigsendsys", /* 108 */ + "hrtsys", /* 109 */ + "acancel", /* 110 */ + "async", /* 111 */ + "priocntlsys", /* 112 */ + "pathconf", /* 113 */ + "mincore", /* 114 */ + "mmap", /* 115 */ + "mprotect", /* 116 */ + "munmap", /* 117 */ + "fpathconf", /* 118 */ + "vfork", /* 119 */ + "fchdir", /* 120 */ + "readv", /* 121 */ + "writev", /* 122 */ + "xstat", /* 123 */ + "lxstat", /* 124 */ + "fxstat", /* 125 */ + "xmknod", /* 126 */ + "NULL", /* 127 */ + "setrlimit", /* 128 */ + "getrlimit", /* 129 */ + "lchown", /* 130 */ + "memcntl", /* 131 */ + "getpmsg", /* 132 */ + "putpmsg", /* 133 */ + "rename", /* 134 */ + "uname", /* 135 */ + "setegid", /* 136 */ + "sysconfig", /* 137 */ + "adjtime", /* 138 */ + "systeminfo", /* 139 */ + NULL, /* 140 */ + "seteuid", /* 141 */ + NULL, /* 142 */ + "fork1", /* 143 */ + "sigtimedwait", /* 144 */ + "lwp_info", /* 145 */ + "yield", /* 146 */ + "lwp_sema_wait", /* 147 */ + "lwp_sema_post", /* 148 */ + "lwp_sema_trywait", /* 149 */ + "lwp_detatch", /* 150 */ + "corectl", /* 151 */ + "modctl", /* 152 */ + "fchroot", /* 153 */ + "utimes", /* 154 */ + "vhangup", /* 155 */ + "gettimeofday", /* 156 */ + "getitimer", /* 157 */ + "setitimer", /* 158 */ + "lwp_create", /* 159 */ + "lwp_exit", /* 160 */ + "lwp_suspend", /* 161 */ + "lwp_continue", /* 162 */ + "lwp_kill", /* 163 */ + "lwp_self", /* 164 */ + "lwp_sigmask", /* 165 */ + "lwp_private", /* 166 */ + "lwp_wait", /* 167 */ + "lwp_mutex_unlock", /* 168 */ + "lwp_mutex_lock", /* 169 */ + "lwp_cond_wait", /* 170 */ + "lwp_cond_signal", /* 171 */ + "lwp_cond_broadcast", /* 172 */ + "pread", /* 173 */ + "pwrite", /* 174 */ + "llseek", /* 175 */ + "inst_sync", /* 176 */ + NULL, /* 177 */ + "kaio", /* 178 */ + "cpc", /* 179 */ + "lgrpsys", /* 180 */ + "rusagesys", /* 181 */ + "portfs", /* 182 */ + "pollsys", /* 183 */ + NULL, /* 184 */ + "acl", /* 185 */ + "auditsys", /* 186 */ + "processor_bind", /* 187 */ + "processor_info", /* 188 */ + "p_online", /* 189 */ + "sigqueue", /* 190 */ + "clock_gettime", /* 191 */ + "clock_settime", /* 192 */ + "clock_getres", /* 193 */ + "timer_create", /* 194 */ + "timer_delete", /* 195 */ + "timer_settime", /* 196 */ + "timer_gettime", /* 197 */ + "timer_getoverrun", /* 198 */ + "nanosleep", /* 199 */ + "facl", /* 200 */ + "door", /* 201 */ + "setreuid", /* 202 */ + "setregid", /* 203 */ + "install_utrap", /* 204 */ + "signotify", /* 205 */ + "schedctl", /* 206 */ + "pset", /* 207 */ + "sparc_utrap_install", /* 208 */ + "resolvepath", /* 209 */ + "lwp_mutex_timedlock", /* 210 */ + "lwp_sema_timedwait", /* 211 */ + "lwp_rwlock_sys", /* 212 */ + "getdents64", /* 213 */ + "mmap64", /* 214 */ + "stat64", /* 215 */ + "lstat64", /* 216 */ + "fstat64", /* 217 */ + "statvfs64", /* 218 */ + "fstatvfs64", /* 219 */ + "setrlimit64", /* 220 */ + "getrlimit64", /* 221 */ + "pread64", /* 222 */ + "pwrite64", /* 223 */ + "creat64", /* 224 */ + "open64", /* 225 */ + "rpcmod", /* 226 */ + "zone", /* 227 */ + "autofssys", /* 228 */ + "getcwd", /* 229 */ + "so_socket", /* 230 */ + "so_socketpair", /* 231 */ + "bind", /* 232 */ + "listen", /* 233 */ + "accept", /* 234 */ + "connect", /* 235 */ + "shutdown", /* 236 */ + "recv", /* 237 */ + "recvfrom", /* 238 */ + "recvmsg", /* 239 */ + "send", /* 240 */ + "sendmsg", /* 241 */ + "sendto", /* 242 */ + "getpeername", /* 243 */ + "getsockname", /* 244 */ + "getsockopt", /* 245 */ + "setsockopt", /* 246 */ + "sockconfig", /* 247 */ + "ntp_gettime", /* 248 */ + "ntp_adjtime", /* 249 */ + "lwp_mutex_unlock", /* 250 */ + "lwp_mutex_trylock", /* 251 */ + "lwp_mutex_init", /* 252 */ + "cladm", /* 253 */ + NULL, /* 254 */ + "umount2" /* 255 */ +}; + +/* SYSEND == max syscall number + 1 */ +#define SYSEND (sizeof (systable) / sizeof (systable[0])) + +/* + * Return the name of a system call. + * Manufacture a name for unknown system call. + */ +char * +proc_sysname(int sys, char *buf, size_t bufsz) +{ + const char *name; + size_t len; + + if (bufsz == 0) /* force a program failure */ + 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) /* ensure null-termination */ + buf[bufsz-1] = '\0'; + + return (buf); +} + +/* + * Convert a string representation of a fault to the corresponding number. + */ +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); +} + +/* + * Convert a string representation of a signal to the signal number. This + * functionality is already available in libc, but the interface doesn't + * optionally accept a "SIG" prefix. We strip that first, and then call libc. + */ +int +proc_str2sig(const char *str, int *signum) +{ + if (strncasecmp(str, "SIG", 3) == 0) + str += 3; /* skip prefix */ + + return (str2sig(str, signum)); +} + +/* + * Convert a string representation of a system call to the corresponding number. + * We do this by performing a simple linear search of the table above. + */ +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); +} + +/* + * Convert a fltset_t to a string representation consisting of canonical + * machine fault names separated by the given delimeter string. If + * m is non-zero (TRUE), set members are printed. If m is zero (FALSE), set + * non-members are printed. If the specified buf is too small to hold the + * complete formatted set, NULL is returned; otherwise buf is returned. + */ +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'; /* Set first byte to \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; /* Output was truncated */ + return (NULL); + } + len -= n; + p += n; + } + } + return (buf); +} + +/* + * Convert a sigset_t to a string representation consisting of canonical signal + * names (without the SIG prefix). Parameters and return values analogous to + * proc_fltset2str(). + */ +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); /* Make sure m is 0 or 1 */ + buf[0] = '\0'; /* Set first byte to \0 */ + + /* + * Unlike proc_fltset2str() and proc_sysset2str(), we don't loop + * until i <= NSIG here, because sigismember() rejects i == NSIG. + */ + 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; /* Output was truncated */ + return (NULL); + } + + len -= n; + p += n; + } + } + + return (buf); +} + +/* + * Convert a sysset_t to a string representation consisting of canonical system + * call names. Parameters and return values analogous to proc_fltset2str(). + */ +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'; /* Set first byte to \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; /* Output was truncated */ + return (NULL); + } + len -= n; + p += n; + } + } + return (buf); +} + +/* + * Convert a string representation of a fault set (names separated by + * one or more of the given delimeters) to a fltset_t. + * If m is non-zero (TRUE), members of the string representation are set. + * If m is zero (FALSE), non-members of the string representation are set. + * This function returns NULL for success. Otherwise it returns a pointer + * to the token of the string that couldn't be identified as a string + * representation of a fault. + */ +char * +proc_str2fltset(const char *s, const char *delim, int m, fltset_t *set) +{ + char *p, *q, *t = alloca(strlen(s) + 1); + int flt; + + if (m) { + premptyset(set); + } else { + prfillset(set); + } + + (void) strcpy(t, 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); +} + +/* + * Convert a string representation of a signal set (names with or without the + * SIG prefix separated by one or more of the given delimeters) to a sigset_t. + * Parameters and return values analogous to proc_str2fltset(). + */ +char * +proc_str2sigset(const char *s, const char *delim, int m, sigset_t *set) +{ + char *p, *q, *t = alloca(strlen(s) + 1); + int sig; + + if (m) { + premptyset(set); + } else { + prfillset(set); + } + + (void) strcpy(t, 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); +} + +/* + * Convert a string representation of a system call set (names separated by + * one or more of the given delimeters) to a sysset_t. Parameters and return + * values analogous to proc_str2fltset(). + */ +char * +proc_str2sysset(const char *s, const char *delim, int m, sysset_t *set) +{ + char *p, *q, *t = alloca(strlen(s) + 1); + int sys; + + if (m) { + premptyset(set); + } else { + prfillset(set); + } + + (void) strcpy(t, 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); +} |