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 }