1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <fcntl.h> 33 #include <string.h> 34 #include "libproc.h" 35 36 /* 37 * These several routines simply get the indicated /proc structures 38 * for a process identified by process ID. They are convenience 39 * functions for one-time operations. They do the mechanics of 40 * open() / read() / close() of the necessary /proc files so the 41 * caller's code can look relatively less cluttered. 42 */ 43 44 /* 45 * 'ngroups' is the number of supplementary group entries allocated in 46 * the caller's cred structure. It should equal zero or one unless extra 47 * space has been allocated for the group list by the caller, like this: 48 * credp = malloc(sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t)); 49 */ 50 int 51 proc_get_cred(pid_t pid, prcred_t *credp, int ngroups) 52 { 53 char fname[64]; 54 int fd; 55 int rv = -1; 56 ssize_t minsize = sizeof (*credp) - sizeof (gid_t); 57 size_t size = minsize + ngroups * sizeof (gid_t); 58 59 (void) snprintf(fname, sizeof (fname), "/proc/%d/cred", (int)pid); 60 if ((fd = open(fname, O_RDONLY)) >= 0) { 61 if (read(fd, credp, size) >= minsize) 62 rv = 0; 63 (void) close(fd); 64 } 65 return (rv); 66 } 67 68 /* 69 * Malloc and return a properly sized structure. 70 */ 71 prpriv_t * 72 proc_get_priv(pid_t pid) 73 { 74 char fname[64]; 75 int fd; 76 struct stat statb; 77 prpriv_t *rv = NULL; 78 79 (void) snprintf(fname, sizeof (fname), "/proc/%d/priv", (int)pid); 80 if ((fd = open(fname, O_RDONLY)) >= 0) { 81 if (fstat(fd, &statb) != 0 || 82 (rv = malloc(statb.st_size)) == NULL || 83 read(fd, rv, statb.st_size) != statb.st_size) { 84 free(rv); 85 rv = NULL; 86 } 87 (void) close(fd); 88 } 89 return (rv); 90 } 91 92 #if defined(__i386) || defined(__amd64) 93 /* 94 * Fill in a pointer to a process LDT structure. 95 * The caller provides a buffer of size 'nldt * sizeof (struct ssd)'; 96 * If pldt == NULL or nldt == 0, we return the number of existing LDT entries. 97 * Otherwise we return the actual number of LDT entries fetched (<= nldt). 98 */ 99 int 100 proc_get_ldt(pid_t pid, struct ssd *pldt, int nldt) 101 { 102 char fname[64]; 103 int fd; 104 struct stat statb; 105 size_t size; 106 ssize_t ssize; 107 108 (void) snprintf(fname, sizeof (fname), "/proc/%d/ldt", (int)pid); 109 if ((fd = open(fname, O_RDONLY)) < 0) 110 return (-1); 111 112 if (pldt == NULL || nldt == 0) { 113 nldt = 0; 114 if (fstat(fd, &statb) == 0) 115 nldt = statb.st_size / sizeof (struct ssd); 116 (void) close(fd); 117 return (nldt); 118 } 119 120 size = nldt * sizeof (struct ssd); 121 if ((ssize = read(fd, pldt, size)) < 0) 122 nldt = -1; 123 else 124 nldt = ssize / sizeof (struct ssd); 125 126 (void) close(fd); 127 return (nldt); 128 } 129 #endif /* __i386 || __amd64 */ 130 131 int 132 proc_get_psinfo(pid_t pid, psinfo_t *psp) 133 { 134 char fname[64]; 135 int fd; 136 int rv = -1; 137 138 (void) snprintf(fname, sizeof (fname), "/proc/%d/psinfo", (int)pid); 139 if ((fd = open(fname, O_RDONLY)) >= 0) { 140 if (read(fd, psp, sizeof (*psp)) == sizeof (*psp)) 141 rv = 0; 142 (void) close(fd); 143 } 144 return (rv); 145 } 146 147 int 148 proc_get_status(pid_t pid, pstatus_t *psp) 149 { 150 char fname[64]; 151 int fd; 152 int rv = -1; 153 154 (void) snprintf(fname, sizeof (fname), "/proc/%d/status", (int)pid); 155 if ((fd = open(fname, O_RDONLY)) >= 0) { 156 if (read(fd, psp, sizeof (*psp)) == sizeof (*psp)) 157 rv = 0; 158 (void) close(fd); 159 } 160 return (rv); 161 } 162 163 /* 164 * Get the process's aux vector. 165 * 'naux' is the number of aux entries in the caller's buffer. 166 * We return the number of aux entries actually fetched from 167 * the process (less than or equal to 'naux') or -1 on failure. 168 */ 169 int 170 proc_get_auxv(pid_t pid, auxv_t *pauxv, int naux) 171 { 172 char fname[64]; 173 int fd; 174 int rv = -1; 175 176 (void) snprintf(fname, sizeof (fname), "/proc/%d/auxv", (int)pid); 177 if ((fd = open(fname, O_RDONLY)) >= 0) { 178 if ((rv = read(fd, pauxv, naux * sizeof (auxv_t))) >= 0) 179 rv /= sizeof (auxv_t); 180 (void) close(fd); 181 } 182 return (rv); 183 } 184