17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59acbbeafSnn35248 * Common Development and Distribution License (the "License"). 69acbbeafSnn35248 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21ed9c9f97SRoger A. Faulkner 227c478bd9Sstevel@tonic-gate /* 23*23a1cceaSRoger A. Faulkner * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/stat.h> 28ed9c9f97SRoger A. Faulkner #include <sys/proc.h> 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <libgen.h> 317c478bd9Sstevel@tonic-gate #include <limits.h> 327c478bd9Sstevel@tonic-gate #include <alloca.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <fcntl.h> 367c478bd9Sstevel@tonic-gate #include <ctype.h> 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <dirent.h> 397c478bd9Sstevel@tonic-gate 409acbbeafSnn35248 #include "Pcontrol.h" 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate static int 437c478bd9Sstevel@tonic-gate open_psinfo(const char *arg, int *perr) 447c478bd9Sstevel@tonic-gate { 457c478bd9Sstevel@tonic-gate /* 469acbbeafSnn35248 * Allocate enough space for procfs_path + arg + "/psinfo" 477c478bd9Sstevel@tonic-gate */ 489acbbeafSnn35248 char *path = alloca(strlen(arg) + strlen(procfs_path) + 9); 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate struct stat64 st; 517c478bd9Sstevel@tonic-gate int fd; 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate if (strchr(arg, '/') == NULL) { 549acbbeafSnn35248 (void) strcpy(path, procfs_path); 559acbbeafSnn35248 (void) strcat(path, "/"); 567c478bd9Sstevel@tonic-gate (void) strcat(path, arg); 577c478bd9Sstevel@tonic-gate } else 587c478bd9Sstevel@tonic-gate (void) strcpy(path, arg); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate (void) strcat(path, "/psinfo"); 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * Attempt to open the psinfo file, and return the fd if we can 647c478bd9Sstevel@tonic-gate * confirm this is a regular file provided by /proc. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate if ((fd = open64(path, O_RDONLY)) >= 0) { 677c478bd9Sstevel@tonic-gate if (fstat64(fd, &st) != 0 || !S_ISREG(st.st_mode) || 687c478bd9Sstevel@tonic-gate strcmp(st.st_fstype, "proc") != 0) { 697c478bd9Sstevel@tonic-gate (void) close(fd); 707c478bd9Sstevel@tonic-gate fd = -1; 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate } else if (errno == EACCES || errno == EPERM) 737c478bd9Sstevel@tonic-gate *perr = G_PERM; 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate return (fd); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static int 797c478bd9Sstevel@tonic-gate open_core(const char *arg, int *perr) 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN 827c478bd9Sstevel@tonic-gate uchar_t order = ELFDATA2MSB; 837c478bd9Sstevel@tonic-gate #else 847c478bd9Sstevel@tonic-gate uchar_t order = ELFDATA2LSB; 857c478bd9Sstevel@tonic-gate #endif 867c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 877c478bd9Sstevel@tonic-gate int fd; 887c478bd9Sstevel@tonic-gate int is_noelf = -1; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * Attempt to open the core file, and return the fd if we can confirm 927c478bd9Sstevel@tonic-gate * this is an ELF file of type ET_CORE. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate if ((fd = open64(arg, O_RDONLY)) >= 0) { 957c478bd9Sstevel@tonic-gate if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) { 967c478bd9Sstevel@tonic-gate (void) close(fd); 977c478bd9Sstevel@tonic-gate fd = -1; 987c478bd9Sstevel@tonic-gate } else if ((is_noelf = memcmp(&ehdr.e_ident[EI_MAG0], ELFMAG, 997c478bd9Sstevel@tonic-gate SELFMAG)) != 0 || ehdr.e_type != ET_CORE) { 1007c478bd9Sstevel@tonic-gate (void) close(fd); 1017c478bd9Sstevel@tonic-gate fd = -1; 1027c478bd9Sstevel@tonic-gate if (is_noelf == 0 && 1037c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] != order) 1047c478bd9Sstevel@tonic-gate *perr = G_ISAINVAL; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate } else if (errno == EACCES || errno == EPERM) 1077c478bd9Sstevel@tonic-gate *perr = G_PERM; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate return (fd); 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * Make the error message precisely match the type of arguments the caller 1147c478bd9Sstevel@tonic-gate * wanted to process. This ensures that a tool which only accepts pids does 1157c478bd9Sstevel@tonic-gate * not produce an error message saying "no such process or core file 'foo'". 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate static int 1187c478bd9Sstevel@tonic-gate open_error(int oflag) 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate if ((oflag & PR_ARG_ANY) == PR_ARG_PIDS) 1217c478bd9Sstevel@tonic-gate return (G_NOPROC); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if ((oflag & PR_ARG_ANY) == PR_ARG_CORES) 1247c478bd9Sstevel@tonic-gate return (G_NOCORE); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate return (G_NOPROCORCORE); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate static void * 1307c478bd9Sstevel@tonic-gate proc_grab_common(const char *arg, const char *path, int oflag, int gflag, 1317c478bd9Sstevel@tonic-gate int *perr, const char **lwps, psinfo_t *psp) 1327c478bd9Sstevel@tonic-gate { 1337c478bd9Sstevel@tonic-gate psinfo_t psinfo; 1347c478bd9Sstevel@tonic-gate char *core; 1357c478bd9Sstevel@tonic-gate int fd; 1367c478bd9Sstevel@tonic-gate char *slash; 1377c478bd9Sstevel@tonic-gate struct ps_prochandle *Pr; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate *perr = 0; 1407c478bd9Sstevel@tonic-gate if (lwps) 1417c478bd9Sstevel@tonic-gate *lwps = NULL; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if (lwps != NULL && (slash = strrchr(arg, '/')) != NULL) { 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Check to see if the user has supplied an lwp range. First, 1467c478bd9Sstevel@tonic-gate * try to grab it as a pid/lwp combo. 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate *slash = '\0'; 1497c478bd9Sstevel@tonic-gate if ((oflag & PR_ARG_PIDS) && 1507c478bd9Sstevel@tonic-gate (fd = open_psinfo(arg, perr)) != -1) { 1517c478bd9Sstevel@tonic-gate if (read(fd, &psinfo, 1527c478bd9Sstevel@tonic-gate sizeof (psinfo_t)) == sizeof (psinfo_t)) { 1537c478bd9Sstevel@tonic-gate (void) close(fd); 1547c478bd9Sstevel@tonic-gate *lwps = slash + 1; 1557c478bd9Sstevel@tonic-gate *slash = '/'; 1567c478bd9Sstevel@tonic-gate if (proc_lwp_range_valid(*lwps) != 0) { 1577c478bd9Sstevel@tonic-gate *perr = G_BADLWPS; 1587c478bd9Sstevel@tonic-gate return (NULL); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate if (psp) { 1617c478bd9Sstevel@tonic-gate *psp = psinfo; 1627c478bd9Sstevel@tonic-gate return (psp); 1637c478bd9Sstevel@tonic-gate } else { 1647c478bd9Sstevel@tonic-gate return (Pgrab(psinfo.pr_pid, gflag, 1657c478bd9Sstevel@tonic-gate perr)); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate (void) close(fd); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * Next, try grabbing it as a corefile. 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate if ((oflag & PR_ARG_CORES) && 1757c478bd9Sstevel@tonic-gate (fd = open_core(arg, perr)) != -1) { 1767c478bd9Sstevel@tonic-gate *lwps = slash + 1; 1777c478bd9Sstevel@tonic-gate *slash = '/'; 1787c478bd9Sstevel@tonic-gate if (proc_lwp_range_valid(*lwps) != 0) { 1797c478bd9Sstevel@tonic-gate *perr = G_BADLWPS; 1807c478bd9Sstevel@tonic-gate return (NULL); 1817c478bd9Sstevel@tonic-gate } 182*23a1cceaSRoger A. Faulkner core = strdupa(arg); 1837c478bd9Sstevel@tonic-gate if ((Pr = Pfgrab_core(fd, path == NULL ? 1847c478bd9Sstevel@tonic-gate dirname(core) : path, perr)) != NULL) { 1857c478bd9Sstevel@tonic-gate if (psp) { 1867c478bd9Sstevel@tonic-gate (void) memcpy(psp, Ppsinfo(Pr), 1877c478bd9Sstevel@tonic-gate sizeof (psinfo_t)); 1887c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 1897c478bd9Sstevel@tonic-gate return (psp); 1907c478bd9Sstevel@tonic-gate } else { 1917c478bd9Sstevel@tonic-gate return (Pr); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate *slash = '/'; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if ((oflag & PR_ARG_PIDS) && (fd = open_psinfo(arg, perr)) != -1) { 2007c478bd9Sstevel@tonic-gate if (read(fd, &psinfo, sizeof (psinfo_t)) == sizeof (psinfo_t)) { 2017c478bd9Sstevel@tonic-gate (void) close(fd); 2027c478bd9Sstevel@tonic-gate if (psp) { 2037c478bd9Sstevel@tonic-gate *psp = psinfo; 2047c478bd9Sstevel@tonic-gate return (psp); 2057c478bd9Sstevel@tonic-gate } else { 2067c478bd9Sstevel@tonic-gate return (Pgrab(psinfo.pr_pid, gflag, perr)); 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * If the read failed, the process may have gone away; 2117c478bd9Sstevel@tonic-gate * we continue checking for core files or fail with G_NOPROC 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate (void) close(fd); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if ((oflag & PR_ARG_CORES) && (fd = open_core(arg, perr)) != -1) { 217*23a1cceaSRoger A. Faulkner core = strdupa(arg); 2187c478bd9Sstevel@tonic-gate if ((Pr = Pfgrab_core(fd, path == NULL ? dirname(core) : path, 2197c478bd9Sstevel@tonic-gate perr)) != NULL) { 2207c478bd9Sstevel@tonic-gate if (psp) { 2217c478bd9Sstevel@tonic-gate (void) memcpy(psp, Ppsinfo(Pr), 2227c478bd9Sstevel@tonic-gate sizeof (psinfo_t)); 2237c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 2247c478bd9Sstevel@tonic-gate return (psp); 2257c478bd9Sstevel@tonic-gate } else { 2267c478bd9Sstevel@tonic-gate return (Pr); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * We were unable to open the corefile. If we have no meaningful 2337c478bd9Sstevel@tonic-gate * information, report the (ambiguous) error from open_error(). 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate if (*perr == 0) 2377c478bd9Sstevel@tonic-gate *perr = open_error(oflag); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate return (NULL); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate struct ps_prochandle * 2437c478bd9Sstevel@tonic-gate proc_arg_xgrab(const char *arg, const char *path, int oflag, int gflag, 2447c478bd9Sstevel@tonic-gate int *perr, const char **lwps) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate return (proc_grab_common(arg, path, oflag, gflag, perr, lwps, NULL)); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate struct ps_prochandle * 2507c478bd9Sstevel@tonic-gate proc_arg_grab(const char *arg, int oflag, int gflag, int *perr) 2517c478bd9Sstevel@tonic-gate { 2527c478bd9Sstevel@tonic-gate return (proc_grab_common(arg, NULL, oflag, gflag, perr, NULL, NULL)); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate pid_t 2567c478bd9Sstevel@tonic-gate proc_arg_psinfo(const char *arg, int oflag, psinfo_t *psp, int *perr) 2577c478bd9Sstevel@tonic-gate { 2587c478bd9Sstevel@tonic-gate psinfo_t psinfo; 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if (psp == NULL) 2617c478bd9Sstevel@tonic-gate psp = &psinfo; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (proc_grab_common(arg, NULL, oflag, 0, perr, NULL, psp) == NULL) 2647c478bd9Sstevel@tonic-gate return (-1); 2657c478bd9Sstevel@tonic-gate else 2667c478bd9Sstevel@tonic-gate return (psp->pr_pid); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate pid_t 2707c478bd9Sstevel@tonic-gate proc_arg_xpsinfo(const char *arg, int oflag, psinfo_t *psp, int *perr, 2717c478bd9Sstevel@tonic-gate const char **lwps) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate psinfo_t psinfo; 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (psp == NULL) 2767c478bd9Sstevel@tonic-gate psp = &psinfo; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate if (proc_grab_common(arg, NULL, oflag, 0, perr, lwps, psp) == NULL) 2797c478bd9Sstevel@tonic-gate return (-1); 2807c478bd9Sstevel@tonic-gate else 2817c478bd9Sstevel@tonic-gate return (psp->pr_pid); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate /* 2857c478bd9Sstevel@tonic-gate * Convert psinfo_t.pr_psargs string into itself, replacing unprintable 2867c478bd9Sstevel@tonic-gate * characters with space along the way. Stop on a null character. 2877c478bd9Sstevel@tonic-gate */ 2887c478bd9Sstevel@tonic-gate void 2897c478bd9Sstevel@tonic-gate proc_unctrl_psinfo(psinfo_t *psp) 2907c478bd9Sstevel@tonic-gate { 2917c478bd9Sstevel@tonic-gate char *s = &psp->pr_psargs[0]; 2927c478bd9Sstevel@tonic-gate size_t n = PRARGSZ; 2937c478bd9Sstevel@tonic-gate int c; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate while (n-- != 0 && (c = (*s & UCHAR_MAX)) != '\0') { 2967c478bd9Sstevel@tonic-gate if (!isprint(c)) 2977c478bd9Sstevel@tonic-gate c = ' '; 2987c478bd9Sstevel@tonic-gate *s++ = (char)c; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate *s = '\0'; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate static int 3057c478bd9Sstevel@tonic-gate proc_lwp_get_range(char *range, id_t *low, id_t *high) 3067c478bd9Sstevel@tonic-gate { 3077c478bd9Sstevel@tonic-gate if (*range == '-') 3087c478bd9Sstevel@tonic-gate *low = 0; 3097c478bd9Sstevel@tonic-gate else 3107c478bd9Sstevel@tonic-gate *low = (id_t)strtol(range, &range, 10); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if (*range == '\0' || *range == ',') { 3137c478bd9Sstevel@tonic-gate *high = *low; 3147c478bd9Sstevel@tonic-gate return (0); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate if (*range != '-') { 3177c478bd9Sstevel@tonic-gate return (-1); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate range++; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate if (*range == '\0') 3227c478bd9Sstevel@tonic-gate *high = INT_MAX; 3237c478bd9Sstevel@tonic-gate else 3247c478bd9Sstevel@tonic-gate *high = (id_t)strtol(range, &range, 10); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if (*range != '\0' && *range != ',') { 3277c478bd9Sstevel@tonic-gate return (-1); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if (*high < *low) { 3317c478bd9Sstevel@tonic-gate id_t tmp = *high; 3327c478bd9Sstevel@tonic-gate *high = *low; 3337c478bd9Sstevel@tonic-gate *low = tmp; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate return (0); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * Determine if the specified lwpid is in the given set of lwpids. 3417c478bd9Sstevel@tonic-gate * The set can include multiple lwpid ranges separated by commas 3427c478bd9Sstevel@tonic-gate * and has the following syntax: 3437c478bd9Sstevel@tonic-gate * 3447c478bd9Sstevel@tonic-gate * lwp_range[,lwp_range]* 3457c478bd9Sstevel@tonic-gate * 3467c478bd9Sstevel@tonic-gate * where lwp_range is specifed as: 3477c478bd9Sstevel@tonic-gate * 3487c478bd9Sstevel@tonic-gate * -n lwpid <= n 3497c478bd9Sstevel@tonic-gate * n-m n <= lwpid <= m 3507c478bd9Sstevel@tonic-gate * n- lwpid >= n 3517c478bd9Sstevel@tonic-gate * n lwpid == n 3527c478bd9Sstevel@tonic-gate */ 3537c478bd9Sstevel@tonic-gate int 3547c478bd9Sstevel@tonic-gate proc_lwp_in_set(const char *set, lwpid_t lwpid) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate id_t low, high; 3577c478bd9Sstevel@tonic-gate id_t id = (id_t)lwpid; 3587c478bd9Sstevel@tonic-gate char *comma; 3597c478bd9Sstevel@tonic-gate char *range = (char *)set; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3627c478bd9Sstevel@tonic-gate * A NULL set indicates that all LWPs are valid. 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate if (set == NULL) 3657c478bd9Sstevel@tonic-gate return (1); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate while (range != NULL) { 3687c478bd9Sstevel@tonic-gate comma = strchr(range, ','); 3697c478bd9Sstevel@tonic-gate if (comma != NULL) 3707c478bd9Sstevel@tonic-gate *comma = '\0'; 3717c478bd9Sstevel@tonic-gate if (proc_lwp_get_range(range, &low, &high) != 0) { 3727c478bd9Sstevel@tonic-gate if (comma != NULL) 3737c478bd9Sstevel@tonic-gate *comma = ','; 3747c478bd9Sstevel@tonic-gate return (0); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate if (comma != NULL) { 3777c478bd9Sstevel@tonic-gate *comma = ','; 3787c478bd9Sstevel@tonic-gate range = comma + 1; 3797c478bd9Sstevel@tonic-gate } else { 3807c478bd9Sstevel@tonic-gate range = NULL; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate if (id >= low && id <= high) 3837c478bd9Sstevel@tonic-gate return (1); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate return (0); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate int 3907c478bd9Sstevel@tonic-gate proc_lwp_range_valid(const char *set) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate char *comma; 3937c478bd9Sstevel@tonic-gate char *range = (char *)set; 3947c478bd9Sstevel@tonic-gate id_t low, high; 3957c478bd9Sstevel@tonic-gate int ret; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate if (range == NULL || *range == '\0' || *range == ',') 3987c478bd9Sstevel@tonic-gate return (-1); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate while (range != NULL) { 4017c478bd9Sstevel@tonic-gate comma = strchr(range, ','); 4027c478bd9Sstevel@tonic-gate if (comma != NULL) 4037c478bd9Sstevel@tonic-gate *comma = '\0'; 4047c478bd9Sstevel@tonic-gate if ((ret = proc_lwp_get_range(range, &low, &high)) != 0) { 4057c478bd9Sstevel@tonic-gate if (comma != NULL) 4067c478bd9Sstevel@tonic-gate *comma = ','; 4077c478bd9Sstevel@tonic-gate return (ret); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate if (comma != NULL) { 4107c478bd9Sstevel@tonic-gate *comma = ','; 4117c478bd9Sstevel@tonic-gate range = comma + 1; 4127c478bd9Sstevel@tonic-gate } else { 4137c478bd9Sstevel@tonic-gate range = NULL; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate return (0); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Walk all processes or LWPs in /proc and call func() for each. 422ed9c9f97SRoger A. Faulkner * Omit system processes (like process-IDs 0, 2, and 3). 4237c478bd9Sstevel@tonic-gate * Stop calling func() if it returns non 0 value and return it. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate int 4267c478bd9Sstevel@tonic-gate proc_walk(proc_walk_f *func, void *arg, int flag) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate DIR *procdir; 4297c478bd9Sstevel@tonic-gate struct dirent *dirent; 4307c478bd9Sstevel@tonic-gate char *errptr; 4319acbbeafSnn35248 char pidstr[PATH_MAX]; 4327c478bd9Sstevel@tonic-gate psinfo_t psinfo; 4337c478bd9Sstevel@tonic-gate lwpsinfo_t *lwpsinfo; 4347c478bd9Sstevel@tonic-gate prheader_t prheader; 4357c478bd9Sstevel@tonic-gate void *buf; 4367c478bd9Sstevel@tonic-gate char *ptr; 4377c478bd9Sstevel@tonic-gate int bufsz; 4387c478bd9Sstevel@tonic-gate id_t pid; 4397c478bd9Sstevel@tonic-gate int fd, i; 4407c478bd9Sstevel@tonic-gate int ret = 0; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate if (flag != PR_WALK_PROC && flag != PR_WALK_LWP) { 4437c478bd9Sstevel@tonic-gate errno = EINVAL; 4447c478bd9Sstevel@tonic-gate return (-1); 4457c478bd9Sstevel@tonic-gate } 4469acbbeafSnn35248 if ((procdir = opendir(procfs_path)) == NULL) 4477c478bd9Sstevel@tonic-gate return (-1); 4487c478bd9Sstevel@tonic-gate while (dirent = readdir(procdir)) { 4497c478bd9Sstevel@tonic-gate if (dirent->d_name[0] == '.') /* skip . and .. */ 4507c478bd9Sstevel@tonic-gate continue; 4517c478bd9Sstevel@tonic-gate pid = (id_t)strtol(dirent->d_name, &errptr, 10); 4527c478bd9Sstevel@tonic-gate if (errptr != NULL && *errptr != '\0') 4537c478bd9Sstevel@tonic-gate continue; 4547c478bd9Sstevel@tonic-gate /* PR_WALK_PROC case */ 4557c478bd9Sstevel@tonic-gate (void) snprintf(pidstr, sizeof (pidstr), 4569acbbeafSnn35248 "%s/%ld/psinfo", procfs_path, pid); 4577c478bd9Sstevel@tonic-gate fd = open(pidstr, O_RDONLY); 4587c478bd9Sstevel@tonic-gate if (fd < 0) 4597c478bd9Sstevel@tonic-gate continue; 460ed9c9f97SRoger A. Faulkner if (read(fd, &psinfo, sizeof (psinfo)) != sizeof (psinfo) || 461ed9c9f97SRoger A. Faulkner (psinfo.pr_flag & SSYS)) { 4627c478bd9Sstevel@tonic-gate (void) close(fd); 4637c478bd9Sstevel@tonic-gate continue; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate (void) close(fd); 4667c478bd9Sstevel@tonic-gate if (flag == PR_WALK_PROC) { 4677c478bd9Sstevel@tonic-gate if ((ret = func(&psinfo, &psinfo.pr_lwp, arg)) != 0) 4687c478bd9Sstevel@tonic-gate break; 4697c478bd9Sstevel@tonic-gate continue; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate /* PR_WALK_LWP case */ 4727c478bd9Sstevel@tonic-gate (void) snprintf(pidstr, sizeof (pidstr), 4739acbbeafSnn35248 "%s/%ld/lpsinfo", procfs_path, pid); 4747c478bd9Sstevel@tonic-gate fd = open(pidstr, O_RDONLY); 4757c478bd9Sstevel@tonic-gate if (fd < 0) 4767c478bd9Sstevel@tonic-gate continue; 4777c478bd9Sstevel@tonic-gate if (read(fd, &prheader, sizeof (prheader)) != 4787c478bd9Sstevel@tonic-gate sizeof (prheader)) { 4797c478bd9Sstevel@tonic-gate (void) close(fd); 4807c478bd9Sstevel@tonic-gate continue; 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate bufsz = prheader.pr_nent * prheader.pr_entsize; 4837c478bd9Sstevel@tonic-gate if ((buf = malloc(bufsz)) == NULL) { 4847c478bd9Sstevel@tonic-gate (void) close(fd); 4857c478bd9Sstevel@tonic-gate ret = -1; 4867c478bd9Sstevel@tonic-gate break; 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate ptr = buf; 4897c478bd9Sstevel@tonic-gate if (pread(fd, buf, bufsz, sizeof (prheader)) != bufsz) { 4907c478bd9Sstevel@tonic-gate free(buf); 4917c478bd9Sstevel@tonic-gate (void) close(fd); 4927c478bd9Sstevel@tonic-gate continue; 4937c478bd9Sstevel@tonic-gate } 4947c478bd9Sstevel@tonic-gate (void) close(fd); 4957c478bd9Sstevel@tonic-gate for (i = 0; i < prheader.pr_nent; 4967c478bd9Sstevel@tonic-gate i++, ptr += prheader.pr_entsize) { 4977c478bd9Sstevel@tonic-gate /*LINTED ALIGNMENT*/ 4987c478bd9Sstevel@tonic-gate lwpsinfo = (lwpsinfo_t *)ptr; 4997c478bd9Sstevel@tonic-gate if ((ret = func(&psinfo, lwpsinfo, arg)) != 0) { 5007c478bd9Sstevel@tonic-gate free(buf); 5017c478bd9Sstevel@tonic-gate break; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate free(buf); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate (void) closedir(procdir); 5077c478bd9Sstevel@tonic-gate return (ret); 5087c478bd9Sstevel@tonic-gate } 509