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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright (c) 2013 by Delphix. All rights reserved. 28 */ 29 30 #include <limits.h> 31 #include <string.h> 32 #include <stdarg.h> 33 #include <stdio.h> 34 #include <errno.h> 35 36 #include "Pcontrol.h" 37 #include "Putil.h" 38 39 /* 40 * Place the new element on the list prior to the existing element. 41 */ 42 void 43 list_link(void *new, void *existing) 44 { 45 plist_t *p = new; 46 plist_t *q = existing; 47 48 if (q) { 49 p->list_forw = q; 50 p->list_back = q->list_back; 51 q->list_back->list_forw = p; 52 q->list_back = p; 53 } else { 54 p->list_forw = p->list_back = p; 55 } 56 } 57 58 /* 59 * Unchain the specified element from a list. 60 */ 61 void 62 list_unlink(void *old) 63 { 64 plist_t *p = old; 65 66 if (p->list_forw != p) { 67 p->list_back->list_forw = p->list_forw; 68 p->list_forw->list_back = p->list_back; 69 } 70 p->list_forw = p->list_back = p; 71 } 72 73 /* 74 * Routines to manipulate sigset_t, fltset_t, or sysset_t. These routines 75 * are provided as equivalents for the <sys/procfs.h> macros prfillset, 76 * premptyset, praddset, and prdelset. These functions are preferable 77 * because they are not macros which rely on using sizeof (*sp), and thus 78 * can be used to create common code to manipulate event sets. The set 79 * size must be passed explicitly, e.g. : prset_fill(&set, sizeof (set)); 80 */ 81 void 82 prset_fill(void *sp, size_t size) 83 { 84 size_t i = size / sizeof (uint32_t); 85 86 while (i != 0) 87 ((uint32_t *)sp)[--i] = (uint32_t)0xFFFFFFFF; 88 } 89 90 void 91 prset_empty(void *sp, size_t size) 92 { 93 size_t i = size / sizeof (uint32_t); 94 95 while (i != 0) 96 ((uint32_t *)sp)[--i] = (uint32_t)0; 97 } 98 99 void 100 prset_add(void *sp, size_t size, uint_t flag) 101 { 102 if (flag - 1 < 32 * size / sizeof (uint32_t)) 103 ((uint32_t *)sp)[(flag - 1) / 32] |= 1U << ((flag - 1) % 32); 104 } 105 106 void 107 prset_del(void *sp, size_t size, uint_t flag) 108 { 109 if (flag - 1 < 32 * size / sizeof (uint32_t)) 110 ((uint32_t *)sp)[(flag - 1) / 32] &= ~(1U << ((flag - 1) % 32)); 111 } 112 113 int 114 prset_ismember(void *sp, size_t size, uint_t flag) 115 { 116 return ((flag - 1 < 32 * size / sizeof (uint32_t)) && 117 (((uint32_t *)sp)[(flag - 1) / 32] & (1U << ((flag - 1) % 32)))); 118 } 119 120 /* 121 * If _libproc_debug is set, printf the debug message to stderr 122 * with an appropriate prefix. 123 */ 124 /*PRINTFLIKE1*/ 125 void 126 dprintf(const char *format, ...) 127 { 128 if (_libproc_debug) { 129 va_list alist; 130 131 va_start(alist, format); 132 (void) fputs("libproc DEBUG: ", stderr); 133 (void) vfprintf(stderr, format, alist); 134 va_end(alist); 135 } 136 } 137 138 /* 139 * Printf-style error reporting function. This is used to supplement the error 140 * return codes from various libproc functions with additional text. Since we 141 * are a library, and should not be spewing messages to stderr, we provide a 142 * default version of this function that does nothing, but by calling this 143 * function we allow the client program to define its own version of the 144 * function that will interpose on our empty default. This may be useful for 145 * clients that wish to display such messages to the user. 146 */ 147 /*ARGSUSED*/ 148 /*PRINTFLIKE2*/ 149 void 150 Perror_printf(struct ps_prochandle *P, const char *format, ...) 151 { 152 /* nothing to do here */ 153 } 154 155 /* 156 * Default operations. 157 */ 158 static ssize_t 159 Pdefault_ssizet() 160 { 161 return (-1); 162 } 163 164 static int 165 Pdefault_int() 166 { 167 return (-1); 168 } 169 170 static void 171 Pdefault_void() 172 { 173 } 174 175 static void * 176 Pdefault_voidp() 177 { 178 return (NULL); 179 } 180 181 static const ps_ops_t P_default_ops = { 182 .pop_pread = (pop_pread_t)Pdefault_ssizet, 183 .pop_pwrite = (pop_pwrite_t)Pdefault_ssizet, 184 .pop_read_maps = (pop_read_maps_t)Pdefault_int, 185 .pop_read_aux = (pop_read_aux_t)Pdefault_void, 186 .pop_cred = (pop_cred_t)Pdefault_int, 187 .pop_priv = (pop_priv_t)Pdefault_int, 188 .pop_psinfo = (pop_psinfo_t)Pdefault_voidp, 189 .pop_status = (pop_status_t)Pdefault_void, 190 .pop_lstatus = (pop_lstatus_t)Pdefault_voidp, 191 .pop_lpsinfo = (pop_lpsinfo_t)Pdefault_voidp, 192 .pop_fini = (pop_fini_t)Pdefault_void, 193 .pop_platform = (pop_platform_t)Pdefault_voidp, 194 .pop_uname = (pop_uname_t)Pdefault_int, 195 .pop_zonename = (pop_zonename_t)Pdefault_voidp, 196 .pop_execname = (pop_execname_t)Pdefault_voidp, 197 .pop_secflags = (pop_secflags_t)Pdefault_int, 198 #if defined(__i386) || defined(__amd64) 199 .pop_ldt = (pop_ldt_t)Pdefault_int 200 #endif 201 }; 202 203 /* 204 * Initialize the destination ops vector with functions from the source. 205 * Functions which are NULL in the source ops vector are set to corresponding 206 * default function in the destination vector. 207 */ 208 void 209 Pinit_ops(ps_ops_t *dst, const ps_ops_t *src) 210 { 211 *dst = P_default_ops; 212 213 if (src->pop_pread != NULL) 214 dst->pop_pread = src->pop_pread; 215 if (src->pop_pwrite != NULL) 216 dst->pop_pwrite = src->pop_pwrite; 217 if (src->pop_read_maps != NULL) 218 dst->pop_read_maps = src->pop_read_maps; 219 if (src->pop_read_aux != NULL) 220 dst->pop_read_aux = src->pop_read_aux; 221 if (src->pop_cred != NULL) 222 dst->pop_cred = src->pop_cred; 223 if (src->pop_priv != NULL) 224 dst->pop_priv = src->pop_priv; 225 if (src->pop_psinfo != NULL) 226 dst->pop_psinfo = src->pop_psinfo; 227 if (src->pop_status != NULL) 228 dst->pop_status = src->pop_status; 229 if (src->pop_lstatus != NULL) 230 dst->pop_lstatus = src->pop_lstatus; 231 if (src->pop_lpsinfo != NULL) 232 dst->pop_lpsinfo = src->pop_lpsinfo; 233 if (src->pop_fini != NULL) 234 dst->pop_fini = src->pop_fini; 235 if (src->pop_platform != NULL) 236 dst->pop_platform = src->pop_platform; 237 if (src->pop_uname != NULL) 238 dst->pop_uname = src->pop_uname; 239 if (src->pop_zonename != NULL) 240 dst->pop_zonename = src->pop_zonename; 241 if (src->pop_execname != NULL) 242 dst->pop_execname = src->pop_execname; 243 if (src->pop_secflags != NULL) 244 dst->pop_secflags = src->pop_secflags; 245 #if defined(__i386) || defined(__amd64) 246 if (src->pop_ldt != NULL) 247 dst->pop_ldt = src->pop_ldt; 248 #endif 249 } 250