1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <unistd.h> 30*7c478bd9Sstevel@tonic-gate #include <rctl.h> 31*7c478bd9Sstevel@tonic-gate #include <libproc.h> 32*7c478bd9Sstevel@tonic-gate #include <stdio.h> 33*7c478bd9Sstevel@tonic-gate #include <libintl.h> 34*7c478bd9Sstevel@tonic-gate #include <locale.h> 35*7c478bd9Sstevel@tonic-gate #include <string.h> 36*7c478bd9Sstevel@tonic-gate #include <signal.h> 37*7c478bd9Sstevel@tonic-gate #include <strings.h> 38*7c478bd9Sstevel@tonic-gate #include <ctype.h> 39*7c478bd9Sstevel@tonic-gate #include <project.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate #include <dirent.h> 42*7c478bd9Sstevel@tonic-gate #include <errno.h> 43*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 45*7c478bd9Sstevel@tonic-gate #include <priv.h> 46*7c478bd9Sstevel@tonic-gate #include <zone.h> 47*7c478bd9Sstevel@tonic-gate #include "utils.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* Valid user actions */ 50*7c478bd9Sstevel@tonic-gate #define ACTION_DISABLE 0x01 51*7c478bd9Sstevel@tonic-gate #define ACTION_ENABLE 0x02 52*7c478bd9Sstevel@tonic-gate #define ACTION_SET 0x04 53*7c478bd9Sstevel@tonic-gate #define ACTION_REPLACE 0x08 54*7c478bd9Sstevel@tonic-gate #define ACTION_DELETE 0x10 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #define PRCTL_VALUE_WIDTH 4 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* Maximum string length for deferred errors */ 59*7c478bd9Sstevel@tonic-gate #define GLOBAL_ERR_SZ 1024 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* allow important process values to be passed together easily */ 62*7c478bd9Sstevel@tonic-gate typedef struct pr_info_handle { 63*7c478bd9Sstevel@tonic-gate struct ps_prochandle *pr; 64*7c478bd9Sstevel@tonic-gate pid_t pid; 65*7c478bd9Sstevel@tonic-gate psinfo_t psinfo; 66*7c478bd9Sstevel@tonic-gate taskid_t taskid; 67*7c478bd9Sstevel@tonic-gate projid_t projid; 68*7c478bd9Sstevel@tonic-gate char *projname; 69*7c478bd9Sstevel@tonic-gate zoneid_t zoneid; 70*7c478bd9Sstevel@tonic-gate char *zonename; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate } pr_info_handle_t; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* Structures for list of resource controls */ 75*7c478bd9Sstevel@tonic-gate typedef struct prctl_value { 76*7c478bd9Sstevel@tonic-gate rctlblk_t *rblk; 77*7c478bd9Sstevel@tonic-gate struct prctl_value *next; 78*7c478bd9Sstevel@tonic-gate } prctl_value_t; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate typedef struct prctl_list { 81*7c478bd9Sstevel@tonic-gate char *name; 82*7c478bd9Sstevel@tonic-gate prctl_value_t *val_list; 83*7c478bd9Sstevel@tonic-gate struct prctl_list *next; 84*7c478bd9Sstevel@tonic-gate } prctl_list_t; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate static volatile int interrupt; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static prctl_list_t *global_rctl_list_head = NULL; 89*7c478bd9Sstevel@tonic-gate static prctl_list_t *global_rctl_list_tail = NULL; 90*7c478bd9Sstevel@tonic-gate static char global_error[GLOBAL_ERR_SZ]; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate /* global variables that contain commmand line option info */ 93*7c478bd9Sstevel@tonic-gate static int arg_operation = 0; 94*7c478bd9Sstevel@tonic-gate static int arg_force = 0; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* String and type from -i */ 98*7c478bd9Sstevel@tonic-gate static rctl_entity_t arg_entity_type = RCENTITY_PROCESS; 99*7c478bd9Sstevel@tonic-gate static char *arg_entity_string = NULL; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate /* -n argument */ 102*7c478bd9Sstevel@tonic-gate static char *arg_name = NULL; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate static rctl_entity_t arg_name_entity = 0; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* -t argument value */ 107*7c478bd9Sstevel@tonic-gate static int arg_priv = 0; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* -v argument string */ 110*7c478bd9Sstevel@tonic-gate static char *arg_valuestring = NULL; 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* global flags of rctl name passed to -n */ 113*7c478bd9Sstevel@tonic-gate static int arg_global_flags = 0; 114*7c478bd9Sstevel@tonic-gate static rctl_qty_t arg_global_max; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate /* appropriate scaling variables determined by rctl unit type */ 117*7c478bd9Sstevel@tonic-gate scale_t *arg_scale; 118*7c478bd9Sstevel@tonic-gate static char *arg_unit = NULL; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* -v argument string converted to uint64_t */ 121*7c478bd9Sstevel@tonic-gate static uint64_t arg_value = 0; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* if -v argument is scaled value, points to "K", "M", "G", ... */ 124*7c478bd9Sstevel@tonic-gate static char *arg_modifier = NULL; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* -e/-d argument string */ 127*7c478bd9Sstevel@tonic-gate static char *arg_action_string = NULL; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* Set to RCTL_LOCAL_SIGNAL|DENY based on arg_action_string */ 130*7c478bd9Sstevel@tonic-gate static int arg_action = 0; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate /* if -e/-d arg is signal=XXX, set to signal number of XXX */ 133*7c478bd9Sstevel@tonic-gate static int arg_signal = 0; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate /* -p arg if -p is specified */ 136*7c478bd9Sstevel@tonic-gate static int arg_pid = -1; 137*7c478bd9Sstevel@tonic-gate static char *arg_pid_string = NULL; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate /* Set to 1 if -P is specified */ 140*7c478bd9Sstevel@tonic-gate static int arg_parseable_mode = 0; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* interupt handler */ 143*7c478bd9Sstevel@tonic-gate static void intr(int); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate static int get_rctls(struct ps_prochandle *); 146*7c478bd9Sstevel@tonic-gate static int store_rctls(const char *rctlname, void *walk_data); 147*7c478bd9Sstevel@tonic-gate static prctl_value_t *store_value_entry(rctlblk_t *rblk, prctl_list_t *list); 148*7c478bd9Sstevel@tonic-gate static prctl_list_t *store_list_entry(const char *name); 149*7c478bd9Sstevel@tonic-gate static void free_lists(); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate static int change_action(rctlblk_t *blk); 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate static int prctl_setrctl(struct ps_prochandle *Pr, const char *name, 154*7c478bd9Sstevel@tonic-gate rctlblk_t *, rctlblk_t *, uint_t); 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate static int match_rctl(struct ps_prochandle *Pr, rctlblk_t **rctl, char *name, 157*7c478bd9Sstevel@tonic-gate char *valuestringin, int valuein, rctl_priv_t privin, 158*7c478bd9Sstevel@tonic-gate int pidin); 159*7c478bd9Sstevel@tonic-gate static int match_rctl_blk(rctlblk_t *rctl, char *valuestringin, 160*7c478bd9Sstevel@tonic-gate uint64_t valuein, 161*7c478bd9Sstevel@tonic-gate rctl_priv_t privin, int pidin); 162*7c478bd9Sstevel@tonic-gate static pid_t regrab_process(pid_t pid, pr_info_handle_t *p, int, int *gret); 163*7c478bd9Sstevel@tonic-gate static pid_t grab_process_by_id(char *idname, rctl_entity_t type, 164*7c478bd9Sstevel@tonic-gate pr_info_handle_t *p, int, int *gret); 165*7c478bd9Sstevel@tonic-gate static int grab_process(pr_info_handle_t *p, int *gret); 166*7c478bd9Sstevel@tonic-gate static void release_process(struct ps_prochandle *Pr); 167*7c478bd9Sstevel@tonic-gate static void preserve_error(char *format, ...); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate static void print_rctls(pr_info_handle_t *p); 170*7c478bd9Sstevel@tonic-gate static void print_priv(rctl_priv_t local_priv, char *format); 171*7c478bd9Sstevel@tonic-gate static void print_local_action(int action, int *signalp, char *format); 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate static const char USAGE[] = "" 174*7c478bd9Sstevel@tonic-gate "usage:\n" 175*7c478bd9Sstevel@tonic-gate " Report resource control values and actions:\n" 176*7c478bd9Sstevel@tonic-gate " prctl [-P] [-t [basic | privileged | system]\n" 177*7c478bd9Sstevel@tonic-gate " [-n name] [-i process | task | project | zone] id ...\n" 178*7c478bd9Sstevel@tonic-gate " -P space delimited output\n" 179*7c478bd9Sstevel@tonic-gate " -t privilege level of rctl values to get\n" 180*7c478bd9Sstevel@tonic-gate " -n name of resource control values to get\n" 181*7c478bd9Sstevel@tonic-gate " -i idtype of operand list\n" 182*7c478bd9Sstevel@tonic-gate " Manipulate resource control values:\n" 183*7c478bd9Sstevel@tonic-gate " prctl [-t [basic | privileged | system]\n" 184*7c478bd9Sstevel@tonic-gate " -n name [-srx] [-v value] [-p pid ] [-e | -d action]\n" 185*7c478bd9Sstevel@tonic-gate " [-i process | task | project | zone] id ...\n" 186*7c478bd9Sstevel@tonic-gate " -t privilege level of rctl value to set/replace/delete/modify\n" 187*7c478bd9Sstevel@tonic-gate " -n name of resource control to set/replace/delete/modify\n" 188*7c478bd9Sstevel@tonic-gate " -s set new resource control value\n" 189*7c478bd9Sstevel@tonic-gate " -r replace first rctl value of matching privilege\n" 190*7c478bd9Sstevel@tonic-gate " -x delete first rctl value of matching privilege, value, and \n" 191*7c478bd9Sstevel@tonic-gate " recipient pid\n" 192*7c478bd9Sstevel@tonic-gate " -v value of rctl to set/replace/delete/modify\n" 193*7c478bd9Sstevel@tonic-gate " -p recipient pid of rctl to set/replace/delete/modify\n" 194*7c478bd9Sstevel@tonic-gate " -e enable action of first rctl value of matching privilege,\n" 195*7c478bd9Sstevel@tonic-gate " value, and recipient pid\n" 196*7c478bd9Sstevel@tonic-gate " -d disable action of first rctl value of matching privilege,\n" 197*7c478bd9Sstevel@tonic-gate " value, and recipient pid\n" 198*7c478bd9Sstevel@tonic-gate " -i idtype of operand list\n"; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate static void 202*7c478bd9Sstevel@tonic-gate usage() 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(USAGE)); 205*7c478bd9Sstevel@tonic-gate exit(2); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate int 209*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate int flags; 212*7c478bd9Sstevel@tonic-gate int opt, errflg = 0; 213*7c478bd9Sstevel@tonic-gate rctlblk_t *rctlblkA = NULL; 214*7c478bd9Sstevel@tonic-gate rctlblk_t *rctlblkB = NULL; 215*7c478bd9Sstevel@tonic-gate rctlblk_t *tmp = NULL; 216*7c478bd9Sstevel@tonic-gate pid_t pid; 217*7c478bd9Sstevel@tonic-gate char *target_id; 218*7c478bd9Sstevel@tonic-gate int search_type; 219*7c478bd9Sstevel@tonic-gate int signal; 220*7c478bd9Sstevel@tonic-gate int localaction; 221*7c478bd9Sstevel@tonic-gate int printed = 0; 222*7c478bd9Sstevel@tonic-gate int gret; 223*7c478bd9Sstevel@tonic-gate char *end; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 226*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 227*7c478bd9Sstevel@tonic-gate (void) setprogname(argv[0]); 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "sPp:Fd:e:i:n:rt:v:x")) != EOF) { 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate switch (opt) { 232*7c478bd9Sstevel@tonic-gate case 'F': /* force grabbing (no O_EXCL) */ 233*7c478bd9Sstevel@tonic-gate arg_force = PGRAB_FORCE; 234*7c478bd9Sstevel@tonic-gate break; 235*7c478bd9Sstevel@tonic-gate case 'i': /* id type for arguments */ 236*7c478bd9Sstevel@tonic-gate arg_entity_string = optarg; 237*7c478bd9Sstevel@tonic-gate if (strcmp(optarg, "process") == 0 || 238*7c478bd9Sstevel@tonic-gate strcmp(optarg, "pid") == 0) 239*7c478bd9Sstevel@tonic-gate arg_entity_type = RCENTITY_PROCESS; 240*7c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "project") == 0 || 241*7c478bd9Sstevel@tonic-gate strcmp(optarg, "projid") == 0) 242*7c478bd9Sstevel@tonic-gate arg_entity_type = RCENTITY_PROJECT; 243*7c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "task") == 0 || 244*7c478bd9Sstevel@tonic-gate strcmp(optarg, "taskid") == 0) 245*7c478bd9Sstevel@tonic-gate arg_entity_type = RCENTITY_TASK; 246*7c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "zone") == 0 || 247*7c478bd9Sstevel@tonic-gate strcmp(optarg, "zoneid") == 0) 248*7c478bd9Sstevel@tonic-gate arg_entity_type = RCENTITY_ZONE; 249*7c478bd9Sstevel@tonic-gate else { 250*7c478bd9Sstevel@tonic-gate warn(gettext("unknown idtype %s"), optarg); 251*7c478bd9Sstevel@tonic-gate errflg = 1; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate case 'd': 255*7c478bd9Sstevel@tonic-gate arg_action_string = optarg; 256*7c478bd9Sstevel@tonic-gate arg_operation |= ACTION_DISABLE; 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate case 'e': 259*7c478bd9Sstevel@tonic-gate arg_action_string = optarg; 260*7c478bd9Sstevel@tonic-gate arg_operation |= ACTION_ENABLE; 261*7c478bd9Sstevel@tonic-gate break; 262*7c478bd9Sstevel@tonic-gate case 'n': /* name of rctl */ 263*7c478bd9Sstevel@tonic-gate arg_name = optarg; 264*7c478bd9Sstevel@tonic-gate if (strncmp(optarg, "process.", 265*7c478bd9Sstevel@tonic-gate strlen("process.")) == 0) 266*7c478bd9Sstevel@tonic-gate arg_name_entity = RCENTITY_PROCESS; 267*7c478bd9Sstevel@tonic-gate else if (strncmp(optarg, "project.", 268*7c478bd9Sstevel@tonic-gate strlen("project.")) == 0) 269*7c478bd9Sstevel@tonic-gate arg_name_entity = RCENTITY_PROJECT; 270*7c478bd9Sstevel@tonic-gate else if (strncmp(optarg, "task.", 271*7c478bd9Sstevel@tonic-gate strlen("task.")) == 0) 272*7c478bd9Sstevel@tonic-gate arg_name_entity = RCENTITY_TASK; 273*7c478bd9Sstevel@tonic-gate else if (strncmp(optarg, "zone.", 274*7c478bd9Sstevel@tonic-gate strlen("zone.")) == 0) 275*7c478bd9Sstevel@tonic-gate arg_name_entity = RCENTITY_ZONE; 276*7c478bd9Sstevel@tonic-gate break; 277*7c478bd9Sstevel@tonic-gate case 'r': 278*7c478bd9Sstevel@tonic-gate arg_operation |= ACTION_REPLACE; 279*7c478bd9Sstevel@tonic-gate break; 280*7c478bd9Sstevel@tonic-gate case 't': /* rctl type */ 281*7c478bd9Sstevel@tonic-gate if (strcmp(optarg, "basic") == 0) 282*7c478bd9Sstevel@tonic-gate arg_priv = RCPRIV_BASIC; 283*7c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "privileged") == 0) 284*7c478bd9Sstevel@tonic-gate arg_priv = RCPRIV_PRIVILEGED; 285*7c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "priv") == 0) 286*7c478bd9Sstevel@tonic-gate arg_priv = RCPRIV_PRIVILEGED; 287*7c478bd9Sstevel@tonic-gate else if (strcmp(optarg, "system") == 0) 288*7c478bd9Sstevel@tonic-gate arg_priv = RCPRIV_SYSTEM; 289*7c478bd9Sstevel@tonic-gate else { 290*7c478bd9Sstevel@tonic-gate warn(gettext("unknown privilege %s"), optarg); 291*7c478bd9Sstevel@tonic-gate errflg = 1; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate break; 294*7c478bd9Sstevel@tonic-gate case 'v': /* value */ 295*7c478bd9Sstevel@tonic-gate arg_valuestring = optarg; 296*7c478bd9Sstevel@tonic-gate break; 297*7c478bd9Sstevel@tonic-gate case 's': 298*7c478bd9Sstevel@tonic-gate arg_operation |= ACTION_SET; 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate case 'x': /* delete */ 301*7c478bd9Sstevel@tonic-gate arg_operation |= ACTION_DELETE; 302*7c478bd9Sstevel@tonic-gate break; 303*7c478bd9Sstevel@tonic-gate case 'p': 304*7c478bd9Sstevel@tonic-gate errno = 0; 305*7c478bd9Sstevel@tonic-gate /* Stick with -1 if arg is "-" */ 306*7c478bd9Sstevel@tonic-gate if (strcmp("-", optarg) == 0) 307*7c478bd9Sstevel@tonic-gate break; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate arg_pid_string = optarg; 310*7c478bd9Sstevel@tonic-gate arg_pid = strtoul(optarg, &end, 10); 311*7c478bd9Sstevel@tonic-gate if (errno || *end != '\0' || end == optarg) { 312*7c478bd9Sstevel@tonic-gate warn(gettext("invalid pid %s"), optarg); 313*7c478bd9Sstevel@tonic-gate errflg = 1; 314*7c478bd9Sstevel@tonic-gate break; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate break; 317*7c478bd9Sstevel@tonic-gate case 'P': 318*7c478bd9Sstevel@tonic-gate arg_parseable_mode = 1; 319*7c478bd9Sstevel@tonic-gate break; 320*7c478bd9Sstevel@tonic-gate default: 321*7c478bd9Sstevel@tonic-gate warn(gettext("unknown option")); 322*7c478bd9Sstevel@tonic-gate errflg = 1; 323*7c478bd9Sstevel@tonic-gate break; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate argc -= optind; 327*7c478bd9Sstevel@tonic-gate argv += optind; 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate if (argc < 1) { 330*7c478bd9Sstevel@tonic-gate warn(gettext("no arguments specified")); 331*7c478bd9Sstevel@tonic-gate errflg = 1; 332*7c478bd9Sstevel@tonic-gate goto done_parse; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate /* if -v is specified without -r, -x, -d, or -e, -s is implied */ 335*7c478bd9Sstevel@tonic-gate if (arg_valuestring && 336*7c478bd9Sstevel@tonic-gate (!(arg_operation & (ACTION_REPLACE | ACTION_DELETE | 337*7c478bd9Sstevel@tonic-gate ACTION_DISABLE | ACTION_ENABLE)))) { 338*7c478bd9Sstevel@tonic-gate arg_operation |= ACTION_SET; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate /* operations require -n */ 341*7c478bd9Sstevel@tonic-gate if (arg_operation && (arg_name == NULL)) { 342*7c478bd9Sstevel@tonic-gate warn(gettext("-n is required with -s, -r, -x, -e, or -d")); 343*7c478bd9Sstevel@tonic-gate errflg = 1; 344*7c478bd9Sstevel@tonic-gate goto done_parse; 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate /* enable and disable are exclusive */ 347*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_ENABLE) && 348*7c478bd9Sstevel@tonic-gate (arg_operation & ACTION_DISABLE)) { 349*7c478bd9Sstevel@tonic-gate warn(gettext("options -d and -e are exclusive")); 350*7c478bd9Sstevel@tonic-gate errflg = 1; 351*7c478bd9Sstevel@tonic-gate goto done_parse; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate /* -s, -r, and -x are exclusive */ 354*7c478bd9Sstevel@tonic-gate flags = arg_operation & 355*7c478bd9Sstevel@tonic-gate (ACTION_REPLACE | ACTION_SET | ACTION_DELETE); 356*7c478bd9Sstevel@tonic-gate if (flags & (flags - 1)) { 357*7c478bd9Sstevel@tonic-gate warn(gettext("options -s, -r, and -x are exclusive")); 358*7c478bd9Sstevel@tonic-gate errflg = 1; 359*7c478bd9Sstevel@tonic-gate goto done_parse; 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate /* -e or -d makes no sense with -x */ 362*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_DELETE) & 363*7c478bd9Sstevel@tonic-gate (arg_operation & (ACTION_ENABLE | ACTION_DISABLE))) { 364*7c478bd9Sstevel@tonic-gate warn(gettext("options -e or -d not allowed with -x")); 365*7c478bd9Sstevel@tonic-gate errflg = 1; 366*7c478bd9Sstevel@tonic-gate goto done_parse; 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate /* if -r is specified -v must be as well */ 369*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_REPLACE) && (!arg_valuestring)) { 370*7c478bd9Sstevel@tonic-gate warn(gettext("option -r requires use of option -v")); 371*7c478bd9Sstevel@tonic-gate errflg = 1; 372*7c478bd9Sstevel@tonic-gate goto done_parse; 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate /* if -s is specified -v must be as well */ 375*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_SET) && (!arg_valuestring)) { 376*7c478bd9Sstevel@tonic-gate warn(gettext("option -s requires use of option -v")); 377*7c478bd9Sstevel@tonic-gate errflg = 1; 378*7c478bd9Sstevel@tonic-gate goto done_parse; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate /* Specifying a recipient pid on a non-basic rctl makes no sense */ 381*7c478bd9Sstevel@tonic-gate if (arg_pid != -1 && arg_priv > RCPRIV_BASIC) { 382*7c478bd9Sstevel@tonic-gate warn(gettext("option -p not allowed on non-basic rctl")); 383*7c478bd9Sstevel@tonic-gate errflg = 1; 384*7c478bd9Sstevel@tonic-gate goto done_parse; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate /* Specifying a recipient pid on a privileged rctl makes no sense */ 387*7c478bd9Sstevel@tonic-gate if (arg_pid != -1 && 388*7c478bd9Sstevel@tonic-gate arg_priv == RCPRIV_PRIVILEGED) { 389*7c478bd9Sstevel@tonic-gate warn(gettext("option -p not allowed with privileged rctl")); 390*7c478bd9Sstevel@tonic-gate errflg = 1; 391*7c478bd9Sstevel@tonic-gate goto done_parse; 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate if (arg_operation) { 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate /* do additional checks if there is an operation */ 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate if (arg_parseable_mode == 1) { 398*7c478bd9Sstevel@tonic-gate warn(gettext("-P not valid when manipulating " 399*7c478bd9Sstevel@tonic-gate "resource control values")); 400*7c478bd9Sstevel@tonic-gate errflg = 1; 401*7c478bd9Sstevel@tonic-gate goto done_parse; 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate /* get rctl global flags to determine if actions are valid */ 404*7c478bd9Sstevel@tonic-gate if ((rctlblkA = calloc(1, rctlblk_size())) == NULL) { 405*7c478bd9Sstevel@tonic-gate warn(gettext("malloc failed: %s"), 406*7c478bd9Sstevel@tonic-gate strerror(errno)); 407*7c478bd9Sstevel@tonic-gate errflg = 1; 408*7c478bd9Sstevel@tonic-gate goto done_parse; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate if ((rctlblkB = calloc(1, rctlblk_size())) == NULL) { 411*7c478bd9Sstevel@tonic-gate warn(gettext("malloc failed: %s"), 412*7c478bd9Sstevel@tonic-gate strerror(errno)); 413*7c478bd9Sstevel@tonic-gate errflg = 1; 414*7c478bd9Sstevel@tonic-gate goto done_parse; 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate /* get system rctl to get global flags and max value */ 417*7c478bd9Sstevel@tonic-gate if (getrctl(arg_name, NULL, rctlblkA, RCTL_FIRST)) { 418*7c478bd9Sstevel@tonic-gate warn(gettext("failed to get resource control " 419*7c478bd9Sstevel@tonic-gate "for %s: %s"), arg_name, strerror(errno)); 420*7c478bd9Sstevel@tonic-gate errflg = 1; 421*7c478bd9Sstevel@tonic-gate goto done_parse; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate while (getrctl(arg_name, rctlblkA, rctlblkB, RCTL_NEXT) == 0) { 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* allow user interrupt */ 426*7c478bd9Sstevel@tonic-gate if (interrupt) { 427*7c478bd9Sstevel@tonic-gate errflg = 1; 428*7c478bd9Sstevel@tonic-gate goto done_parse; 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate tmp = rctlblkB; 431*7c478bd9Sstevel@tonic-gate rctlblkB = rctlblkA; 432*7c478bd9Sstevel@tonic-gate rctlblkA = tmp; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate if (rctlblk_get_privilege(rctlblkA) == 435*7c478bd9Sstevel@tonic-gate RCPRIV_SYSTEM) { 436*7c478bd9Sstevel@tonic-gate break; 437*7c478bd9Sstevel@tonic-gate } 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate if (rctlblk_get_privilege(rctlblkA) != RCPRIV_SYSTEM) { 440*7c478bd9Sstevel@tonic-gate warn(gettext("failed to get system resource control " 441*7c478bd9Sstevel@tonic-gate "for %s: %s"), arg_name, strerror(errno)); 442*7c478bd9Sstevel@tonic-gate errflg = 1; 443*7c478bd9Sstevel@tonic-gate goto done_parse; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate /* figure out the correct scale and unit for this rctl */ 446*7c478bd9Sstevel@tonic-gate arg_global_flags = rctlblk_get_global_flags(rctlblkA); 447*7c478bd9Sstevel@tonic-gate arg_global_max = rctlblk_get_value(rctlblkA); 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate if (arg_global_flags & RCTL_GLOBAL_BYTES) { 450*7c478bd9Sstevel@tonic-gate arg_unit = SCALED_UNIT_BYTES; 451*7c478bd9Sstevel@tonic-gate arg_scale = scale_binary; 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate } else if (arg_global_flags & RCTL_GLOBAL_SECONDS) { 454*7c478bd9Sstevel@tonic-gate arg_unit = SCALED_UNIT_SECONDS; 455*7c478bd9Sstevel@tonic-gate arg_scale = scale_metric; 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate } else { 458*7c478bd9Sstevel@tonic-gate arg_unit = SCALED_UNIT_NONE; 459*7c478bd9Sstevel@tonic-gate arg_scale = scale_metric; 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate /* parse -v value string */ 462*7c478bd9Sstevel@tonic-gate if (arg_valuestring) { 463*7c478bd9Sstevel@tonic-gate if (scaledtouint64(arg_valuestring, 464*7c478bd9Sstevel@tonic-gate &arg_value, NULL, &arg_modifier, NULL, 465*7c478bd9Sstevel@tonic-gate arg_scale, arg_unit, 466*7c478bd9Sstevel@tonic-gate SCALED_ALL_FLAGS)) { 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate warn(gettext("invalid -v value %s"), 469*7c478bd9Sstevel@tonic-gate arg_valuestring); 470*7c478bd9Sstevel@tonic-gate errflg = 1; 471*7c478bd9Sstevel@tonic-gate goto done_parse; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate if (arg_value > arg_global_max) { 474*7c478bd9Sstevel@tonic-gate warn(gettext("-v value %s exceeds system " 475*7c478bd9Sstevel@tonic-gate "limit for resource control: %s"), 476*7c478bd9Sstevel@tonic-gate arg_valuestring, arg_name); 477*7c478bd9Sstevel@tonic-gate errflg = 1; 478*7c478bd9Sstevel@tonic-gate goto done_parse; 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate /* parse action */ 482*7c478bd9Sstevel@tonic-gate if (arg_action_string) { 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate char *sigchr; 485*7c478bd9Sstevel@tonic-gate char *iter; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if ((strcmp(arg_action_string, 488*7c478bd9Sstevel@tonic-gate "signal") == 0) || 489*7c478bd9Sstevel@tonic-gate (strcmp(arg_action_string, 490*7c478bd9Sstevel@tonic-gate "sig") == 0)) { 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if (arg_operation & ACTION_ENABLE) { 493*7c478bd9Sstevel@tonic-gate warn(gettext( 494*7c478bd9Sstevel@tonic-gate "signal name or number must be " 495*7c478bd9Sstevel@tonic-gate "specified with -e")); 496*7c478bd9Sstevel@tonic-gate errflg = 1; 497*7c478bd9Sstevel@tonic-gate goto done_parse; 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate arg_action = RCTL_LOCAL_SIGNAL; 500*7c478bd9Sstevel@tonic-gate arg_signal = -1; 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate } else if ((strncmp(arg_action_string, 503*7c478bd9Sstevel@tonic-gate "signal=", strlen("signal=")) == 0) || 504*7c478bd9Sstevel@tonic-gate (strncmp(arg_action_string, 505*7c478bd9Sstevel@tonic-gate "sig=", strlen("sig=")) == 0)) { 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate arg_action = RCTL_LOCAL_SIGNAL; 508*7c478bd9Sstevel@tonic-gate sigchr = strrchr(arg_action_string, '='); 509*7c478bd9Sstevel@tonic-gate sigchr++; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate iter = sigchr; 512*7c478bd9Sstevel@tonic-gate while (*iter) { 513*7c478bd9Sstevel@tonic-gate *iter = toupper(*iter); 514*7c478bd9Sstevel@tonic-gate iter++; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate if (strncmp("SIG", sigchr, 3) == 0) 517*7c478bd9Sstevel@tonic-gate sigchr += 3; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (str2sig(sigchr, &arg_signal) != 0) { 521*7c478bd9Sstevel@tonic-gate warn(gettext("signal invalid")); 522*7c478bd9Sstevel@tonic-gate errflg = 1; 523*7c478bd9Sstevel@tonic-gate goto done_parse; 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate } else if (strcmp(arg_action_string, "deny") == 0) { 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate arg_action = RCTL_LOCAL_DENY; 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate } else if (strcmp(arg_action_string, "all") == 0) { 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate if (arg_operation & ACTION_ENABLE) { 532*7c478bd9Sstevel@tonic-gate warn(gettext( 533*7c478bd9Sstevel@tonic-gate "cannot use action 'all' with -e")); 534*7c478bd9Sstevel@tonic-gate errflg = 1; 535*7c478bd9Sstevel@tonic-gate goto done_parse; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate arg_action = RCTL_LOCAL_DENY | 538*7c478bd9Sstevel@tonic-gate RCTL_LOCAL_SIGNAL; 539*7c478bd9Sstevel@tonic-gate arg_signal = -1; 540*7c478bd9Sstevel@tonic-gate goto done_parse; 541*7c478bd9Sstevel@tonic-gate } else { 542*7c478bd9Sstevel@tonic-gate warn(gettext("action invalid")); 543*7c478bd9Sstevel@tonic-gate errflg = 1; 544*7c478bd9Sstevel@tonic-gate goto done_parse; 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate /* cannot manipulate system rctls */ 548*7c478bd9Sstevel@tonic-gate if (arg_priv == RCPRIV_SYSTEM) { 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate warn(gettext("cannot modify system values")); 551*7c478bd9Sstevel@tonic-gate errflg = 1; 552*7c478bd9Sstevel@tonic-gate goto done_parse; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate /* validate that the privilege is allowed */ 555*7c478bd9Sstevel@tonic-gate if ((arg_priv == RCPRIV_BASIC) && 556*7c478bd9Sstevel@tonic-gate (arg_global_flags & RCTL_GLOBAL_NOBASIC)) { 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate warn(gettext("basic values not allowed on rctl %s"), 559*7c478bd9Sstevel@tonic-gate arg_name); 560*7c478bd9Sstevel@tonic-gate errflg = 1; 561*7c478bd9Sstevel@tonic-gate goto done_parse; 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate /* validate that actions are appropriate for given rctl */ 564*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_ENABLE) && 565*7c478bd9Sstevel@tonic-gate (arg_action & RCTL_LOCAL_DENY) && 566*7c478bd9Sstevel@tonic-gate (arg_global_flags & RCTL_GLOBAL_DENY_NEVER)) { 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate warn(gettext("unable to enable deny on rctl with " 569*7c478bd9Sstevel@tonic-gate "global flag 'no-deny'")); 570*7c478bd9Sstevel@tonic-gate errflg = 1; 571*7c478bd9Sstevel@tonic-gate goto done_parse; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_DISABLE) && 574*7c478bd9Sstevel@tonic-gate (arg_action & RCTL_LOCAL_DENY) && 575*7c478bd9Sstevel@tonic-gate (arg_global_flags & RCTL_GLOBAL_DENY_ALWAYS)) { 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate warn(gettext("unable to disable deny on rctl with " 578*7c478bd9Sstevel@tonic-gate "global flag 'deny'")); 579*7c478bd9Sstevel@tonic-gate errflg = 1; 580*7c478bd9Sstevel@tonic-gate goto done_parse; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate if ((arg_operation & ACTION_ENABLE) && 583*7c478bd9Sstevel@tonic-gate (arg_action & RCTL_LOCAL_SIGNAL) && 584*7c478bd9Sstevel@tonic-gate (arg_global_flags & RCTL_GLOBAL_SIGNAL_NEVER)) { 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate warn(gettext("unable to enable signal on rctl with " 587*7c478bd9Sstevel@tonic-gate "global flag 'no-signal'")); 588*7c478bd9Sstevel@tonic-gate errflg = 1; 589*7c478bd9Sstevel@tonic-gate goto done_parse; 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate /* now set defaults for options not supplied */ 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * default privilege to basic if this is a seting an rctl 595*7c478bd9Sstevel@tonic-gate * operation 596*7c478bd9Sstevel@tonic-gate */ 597*7c478bd9Sstevel@tonic-gate if (arg_operation & ACTION_SET) { 598*7c478bd9Sstevel@tonic-gate if (arg_priv == 0) { 599*7c478bd9Sstevel@tonic-gate arg_priv = RCPRIV_BASIC; 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * -p is required when set a basic task, 604*7c478bd9Sstevel@tonic-gate * project or zone rctl 605*7c478bd9Sstevel@tonic-gate */ 606*7c478bd9Sstevel@tonic-gate if ((arg_pid == -1) && 607*7c478bd9Sstevel@tonic-gate (arg_priv == RCPRIV_BASIC) && 608*7c478bd9Sstevel@tonic-gate (arg_entity_type != RCENTITY_PROCESS) && 609*7c478bd9Sstevel@tonic-gate (arg_operation & ACTION_SET) && 610*7c478bd9Sstevel@tonic-gate (arg_name) && 611*7c478bd9Sstevel@tonic-gate (arg_name_entity == RCENTITY_TASK || 612*7c478bd9Sstevel@tonic-gate arg_name_entity == RCENTITY_PROJECT || 613*7c478bd9Sstevel@tonic-gate arg_name_entity == RCENTITY_ZONE)) { 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate warn(gettext("-p pid required when setting or " 616*7c478bd9Sstevel@tonic-gate "replacing task or project rctl")); 617*7c478bd9Sstevel@tonic-gate errflg = 1; 618*7c478bd9Sstevel@tonic-gate goto done_parse; 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate } else { 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate /* validate for list mode */ 623*7c478bd9Sstevel@tonic-gate /* -p is not valid in list mode */ 624*7c478bd9Sstevel@tonic-gate if (arg_pid != -1) { 625*7c478bd9Sstevel@tonic-gate warn(gettext("-p pid requires -s, -r, -x, -e, or -d")); 626*7c478bd9Sstevel@tonic-gate errflg = 1; 627*7c478bd9Sstevel@tonic-gate goto done_parse; 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate /* getting/setting process rctl on task or project is error */ 631*7c478bd9Sstevel@tonic-gate if ((arg_name && (arg_name_entity == RCENTITY_PROCESS)) && 632*7c478bd9Sstevel@tonic-gate ((arg_entity_type == RCENTITY_TASK) || 633*7c478bd9Sstevel@tonic-gate (arg_entity_type == RCENTITY_PROJECT))) { 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate warn(gettext("cannot get/set process rctl on task " 636*7c478bd9Sstevel@tonic-gate "or project")); 637*7c478bd9Sstevel@tonic-gate errflg = 1; 638*7c478bd9Sstevel@tonic-gate goto done_parse; 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate /* getting/setting task rctl on project is error */ 641*7c478bd9Sstevel@tonic-gate if ((arg_name && (arg_name_entity == RCENTITY_TASK)) && 642*7c478bd9Sstevel@tonic-gate (arg_entity_type == RCENTITY_PROJECT)) { 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate warn(gettext("cannot get/set task rctl on project")); 645*7c478bd9Sstevel@tonic-gate errflg = 1; 646*7c478bd9Sstevel@tonic-gate goto done_parse; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate done_parse: 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate /* free any rctlblk's that we may have allocated */ 652*7c478bd9Sstevel@tonic-gate if (rctlblkA) { 653*7c478bd9Sstevel@tonic-gate free(rctlblkA); 654*7c478bd9Sstevel@tonic-gate rctlblkA = NULL; 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate if (rctlblkB) { 657*7c478bd9Sstevel@tonic-gate free(rctlblkB); 658*7c478bd9Sstevel@tonic-gate rctlblkB = NULL; 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate if (errflg) 661*7c478bd9Sstevel@tonic-gate usage(); 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* catch signals from terminal */ 664*7c478bd9Sstevel@tonic-gate if (sigset(SIGHUP, SIG_IGN) == SIG_DFL) 665*7c478bd9Sstevel@tonic-gate (void) sigset(SIGHUP, intr); 666*7c478bd9Sstevel@tonic-gate if (sigset(SIGINT, SIG_IGN) == SIG_DFL) 667*7c478bd9Sstevel@tonic-gate (void) sigset(SIGINT, intr); 668*7c478bd9Sstevel@tonic-gate if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL) 669*7c478bd9Sstevel@tonic-gate (void) sigset(SIGQUIT, intr); 670*7c478bd9Sstevel@tonic-gate (void) sigset(SIGTERM, intr); 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate while (--argc >= 0 && !interrupt) { 673*7c478bd9Sstevel@tonic-gate pr_info_handle_t p; 674*7c478bd9Sstevel@tonic-gate char *arg = *argv++; 675*7c478bd9Sstevel@tonic-gate int intarg; 676*7c478bd9Sstevel@tonic-gate char *end; 677*7c478bd9Sstevel@tonic-gate errflg = 0; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate gret = 0; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate /* Store int version of arg */ 682*7c478bd9Sstevel@tonic-gate errno = 0; 683*7c478bd9Sstevel@tonic-gate intarg = strtoul(arg, &end, 10); 684*7c478bd9Sstevel@tonic-gate if (errno || *end != '\0' || end == arg) { 685*7c478bd9Sstevel@tonic-gate intarg = -1; 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate /* 689*7c478bd9Sstevel@tonic-gate * -p defaults to arg if basic and collective rctl 690*7c478bd9Sstevel@tonic-gate * and -i process is specified 691*7c478bd9Sstevel@tonic-gate */ 692*7c478bd9Sstevel@tonic-gate if ((arg_pid == -1) && 693*7c478bd9Sstevel@tonic-gate (arg_priv == RCPRIV_BASIC) && 694*7c478bd9Sstevel@tonic-gate (arg_entity_type == RCENTITY_PROCESS) && 695*7c478bd9Sstevel@tonic-gate (arg_name) && 696*7c478bd9Sstevel@tonic-gate (arg_name_entity == RCENTITY_TASK || 697*7c478bd9Sstevel@tonic-gate arg_name_entity == RCENTITY_PROJECT)) { 698*7c478bd9Sstevel@tonic-gate arg_pid_string = arg; 699*7c478bd9Sstevel@tonic-gate errno = 0; 700*7c478bd9Sstevel@tonic-gate arg_pid = intarg; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate /* Specifying a recipient pid and -i pid is redundent */ 703*7c478bd9Sstevel@tonic-gate if (arg_pid != -1 && arg_entity_type == RCENTITY_PROCESS && 704*7c478bd9Sstevel@tonic-gate arg_pid != intarg) { 705*7c478bd9Sstevel@tonic-gate warn(gettext("option -p pid must match -i process")); 706*7c478bd9Sstevel@tonic-gate errflg = 1; 707*7c478bd9Sstevel@tonic-gate continue; 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate /* use recipient pid if we have one */ 710*7c478bd9Sstevel@tonic-gate if (arg_pid_string != NULL) { 711*7c478bd9Sstevel@tonic-gate target_id = arg_pid_string; 712*7c478bd9Sstevel@tonic-gate search_type = RCENTITY_PROCESS; 713*7c478bd9Sstevel@tonic-gate } else { 714*7c478bd9Sstevel@tonic-gate target_id = arg; 715*7c478bd9Sstevel@tonic-gate search_type = arg_entity_type; 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); /* process-at-a-time */ 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate if (arg_operation != 0) { 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate if ((pid = grab_process_by_id(target_id, 722*7c478bd9Sstevel@tonic-gate search_type, &p, arg_priv, &gret)) < 0) { 723*7c478bd9Sstevel@tonic-gate /* 724*7c478bd9Sstevel@tonic-gate * Mark that an error occurred so that the 725*7c478bd9Sstevel@tonic-gate * return value can be set, but continue 726*7c478bd9Sstevel@tonic-gate * on with other processes 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate errflg = 1; 729*7c478bd9Sstevel@tonic-gate continue; 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate /* 733*7c478bd9Sstevel@tonic-gate * At this point, the victim process is held. 734*7c478bd9Sstevel@tonic-gate * Do not call any Pgrab-unsafe functions until 735*7c478bd9Sstevel@tonic-gate * the process is released via release_process(). 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate errflg = get_rctls(p.pr); 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate if (arg_operation & ACTION_DELETE) { 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate /* match by privilege, value, and pid */ 743*7c478bd9Sstevel@tonic-gate if (match_rctl(p.pr, &rctlblkA, arg_name, 744*7c478bd9Sstevel@tonic-gate arg_valuestring, arg_value, arg_priv, 745*7c478bd9Sstevel@tonic-gate arg_pid) != 0 || rctlblkA == NULL) { 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate if (interrupt) 748*7c478bd9Sstevel@tonic-gate goto out; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate preserve_error(gettext("no matching " 751*7c478bd9Sstevel@tonic-gate "resource control found for " 752*7c478bd9Sstevel@tonic-gate "deletion")); 753*7c478bd9Sstevel@tonic-gate errflg = 1; 754*7c478bd9Sstevel@tonic-gate goto out; 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate /* 757*7c478bd9Sstevel@tonic-gate * grab correct process. This is neccessary 758*7c478bd9Sstevel@tonic-gate * if the recipient pid does not match the 759*7c478bd9Sstevel@tonic-gate * one we grabbed 760*7c478bd9Sstevel@tonic-gate */ 761*7c478bd9Sstevel@tonic-gate pid = regrab_process( 762*7c478bd9Sstevel@tonic-gate rctlblk_get_recipient_pid(rctlblkA), 763*7c478bd9Sstevel@tonic-gate &p, arg_priv, &gret); 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate if (pid < 0) { 766*7c478bd9Sstevel@tonic-gate errflg = 1; 767*7c478bd9Sstevel@tonic-gate goto out; 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate if (prctl_setrctl(p.pr, arg_name, NULL, 770*7c478bd9Sstevel@tonic-gate rctlblkA, RCTL_DELETE) != 0) { 771*7c478bd9Sstevel@tonic-gate errflg = 1; 772*7c478bd9Sstevel@tonic-gate goto out; 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate } else if (arg_operation & ACTION_SET) { 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /* match by privilege, value, and pid */ 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate if (match_rctl(p.pr, &rctlblkA, arg_name, 779*7c478bd9Sstevel@tonic-gate arg_valuestring, arg_value, arg_priv, 780*7c478bd9Sstevel@tonic-gate arg_pid) == 0) { 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate if (interrupt) 783*7c478bd9Sstevel@tonic-gate goto out; 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate preserve_error(gettext("resource " 786*7c478bd9Sstevel@tonic-gate "control already exists")); 787*7c478bd9Sstevel@tonic-gate errflg = 1; 788*7c478bd9Sstevel@tonic-gate goto out; 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate rctlblkB = calloc(1, rctlblk_size()); 791*7c478bd9Sstevel@tonic-gate if (rctlblkB == NULL) { 792*7c478bd9Sstevel@tonic-gate preserve_error(gettext( 793*7c478bd9Sstevel@tonic-gate "malloc failed"), strerror(errno)); 794*7c478bd9Sstevel@tonic-gate errflg = 1; 795*7c478bd9Sstevel@tonic-gate goto out; 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblkB, arg_value); 798*7c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblkB, arg_priv); 799*7c478bd9Sstevel@tonic-gate if (change_action(rctlblkB)) { 800*7c478bd9Sstevel@tonic-gate errflg = 1; 801*7c478bd9Sstevel@tonic-gate goto out; 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate if (prctl_setrctl(p.pr, arg_name, NULL, 804*7c478bd9Sstevel@tonic-gate rctlblkB, RCTL_INSERT) != 0) { 805*7c478bd9Sstevel@tonic-gate errflg = 1; 806*7c478bd9Sstevel@tonic-gate goto out; 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate } else if (arg_operation & ACTION_REPLACE) { 809*7c478bd9Sstevel@tonic-gate /* 810*7c478bd9Sstevel@tonic-gate * match rctl for deletion by privilege and 811*7c478bd9Sstevel@tonic-gate * pid only 812*7c478bd9Sstevel@tonic-gate */ 813*7c478bd9Sstevel@tonic-gate if (match_rctl(p.pr, &rctlblkA, arg_name, 814*7c478bd9Sstevel@tonic-gate NULL, 0, arg_priv, 815*7c478bd9Sstevel@tonic-gate arg_pid) != 0 || rctlblkA == NULL) { 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate if (interrupt) 818*7c478bd9Sstevel@tonic-gate goto out; 819*7c478bd9Sstevel@tonic-gate 820*7c478bd9Sstevel@tonic-gate preserve_error(gettext("no matching " 821*7c478bd9Sstevel@tonic-gate "resource control to replace")); 822*7c478bd9Sstevel@tonic-gate errflg = 1; 823*7c478bd9Sstevel@tonic-gate goto out; 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate /* 826*7c478bd9Sstevel@tonic-gate * grab correct process. This is neccessary 827*7c478bd9Sstevel@tonic-gate * if the recipient pid does not match the 828*7c478bd9Sstevel@tonic-gate * one we grabbed 829*7c478bd9Sstevel@tonic-gate */ 830*7c478bd9Sstevel@tonic-gate pid = regrab_process( 831*7c478bd9Sstevel@tonic-gate rctlblk_get_recipient_pid(rctlblkA), 832*7c478bd9Sstevel@tonic-gate &p, arg_priv, &gret); 833*7c478bd9Sstevel@tonic-gate if (pid < 0) { 834*7c478bd9Sstevel@tonic-gate errflg = 1; 835*7c478bd9Sstevel@tonic-gate goto out; 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate pid = rctlblk_get_recipient_pid(rctlblkA); 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate /* 840*7c478bd9Sstevel@tonic-gate * match by privilege, value and pid to 841*7c478bd9Sstevel@tonic-gate * check if new rctl already exists 842*7c478bd9Sstevel@tonic-gate */ 843*7c478bd9Sstevel@tonic-gate if (match_rctl(p.pr, &rctlblkB, arg_name, 844*7c478bd9Sstevel@tonic-gate arg_valuestring, arg_value, arg_priv, 845*7c478bd9Sstevel@tonic-gate pid) < 0) { 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate if (interrupt) 848*7c478bd9Sstevel@tonic-gate goto out; 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate preserve_error(gettext( 851*7c478bd9Sstevel@tonic-gate "Internal Error")); 852*7c478bd9Sstevel@tonic-gate errflg = 1; 853*7c478bd9Sstevel@tonic-gate goto out; 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate /* 856*7c478bd9Sstevel@tonic-gate * If rctl already exists, and it does not 857*7c478bd9Sstevel@tonic-gate * match the one that we will delete, than 858*7c478bd9Sstevel@tonic-gate * the replace will fail. 859*7c478bd9Sstevel@tonic-gate */ 860*7c478bd9Sstevel@tonic-gate if (rctlblkB != NULL && 861*7c478bd9Sstevel@tonic-gate arg_value != 862*7c478bd9Sstevel@tonic-gate rctlblk_get_value(rctlblkA)) { 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate preserve_error(gettext("replacement " 865*7c478bd9Sstevel@tonic-gate "resource control already " 866*7c478bd9Sstevel@tonic-gate "exists")); 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate errflg = 1; 869*7c478bd9Sstevel@tonic-gate goto out; 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate /* create new rctl */ 872*7c478bd9Sstevel@tonic-gate rctlblkB = calloc(1, rctlblk_size()); 873*7c478bd9Sstevel@tonic-gate if (rctlblkB == NULL) { 874*7c478bd9Sstevel@tonic-gate preserve_error(gettext( 875*7c478bd9Sstevel@tonic-gate "malloc failed"), strerror(errno)); 876*7c478bd9Sstevel@tonic-gate errflg = 1; 877*7c478bd9Sstevel@tonic-gate goto out; 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblkB, arg_value); 880*7c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblkB, 881*7c478bd9Sstevel@tonic-gate rctlblk_get_privilege(rctlblkA)); 882*7c478bd9Sstevel@tonic-gate if (change_action(rctlblkB)) { 883*7c478bd9Sstevel@tonic-gate errflg = 1; 884*7c478bd9Sstevel@tonic-gate goto out; 885*7c478bd9Sstevel@tonic-gate } 886*7c478bd9Sstevel@tonic-gate /* do replacement */ 887*7c478bd9Sstevel@tonic-gate if (prctl_setrctl(p.pr, arg_name, rctlblkA, 888*7c478bd9Sstevel@tonic-gate rctlblkB, RCTL_REPLACE) != 0) { 889*7c478bd9Sstevel@tonic-gate errflg = 1; 890*7c478bd9Sstevel@tonic-gate goto out; 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate } else if (arg_operation & 893*7c478bd9Sstevel@tonic-gate (ACTION_ENABLE | ACTION_DISABLE)) { 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate rctlblkB = calloc(1, rctlblk_size()); 896*7c478bd9Sstevel@tonic-gate if (rctlblkB == NULL) { 897*7c478bd9Sstevel@tonic-gate preserve_error(gettext( 898*7c478bd9Sstevel@tonic-gate "malloc failed"), strerror(errno)); 899*7c478bd9Sstevel@tonic-gate errflg = 1; 900*7c478bd9Sstevel@tonic-gate goto out; 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate /* match by privilege, value, and pid */ 903*7c478bd9Sstevel@tonic-gate if (match_rctl(p.pr, &rctlblkA, arg_name, 904*7c478bd9Sstevel@tonic-gate arg_valuestring, arg_value, arg_priv, 905*7c478bd9Sstevel@tonic-gate arg_pid) != 0) { 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate if (interrupt) 908*7c478bd9Sstevel@tonic-gate goto out; 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* if no match, just set new rctl */ 911*7c478bd9Sstevel@tonic-gate if (arg_priv == 0) 912*7c478bd9Sstevel@tonic-gate arg_priv = RCPRIV_BASIC; 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate if ((arg_priv == RCPRIV_BASIC) && 915*7c478bd9Sstevel@tonic-gate (arg_entity_type != 916*7c478bd9Sstevel@tonic-gate RCENTITY_PROCESS) && 917*7c478bd9Sstevel@tonic-gate (arg_pid_string == NULL)) { 918*7c478bd9Sstevel@tonic-gate preserve_error(gettext( 919*7c478bd9Sstevel@tonic-gate "-p required when setting " 920*7c478bd9Sstevel@tonic-gate "basic rctls")); 921*7c478bd9Sstevel@tonic-gate errflg = 1; 922*7c478bd9Sstevel@tonic-gate goto out; 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblkB, 925*7c478bd9Sstevel@tonic-gate arg_value); 926*7c478bd9Sstevel@tonic-gate rctlblk_set_privilege( 927*7c478bd9Sstevel@tonic-gate rctlblkB, arg_priv); 928*7c478bd9Sstevel@tonic-gate if (change_action(rctlblkB)) { 929*7c478bd9Sstevel@tonic-gate errflg = 1; 930*7c478bd9Sstevel@tonic-gate goto out; 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate if (prctl_setrctl(p.pr, 933*7c478bd9Sstevel@tonic-gate arg_name, NULL, rctlblkB, 934*7c478bd9Sstevel@tonic-gate RCTL_INSERT) != 0) { 935*7c478bd9Sstevel@tonic-gate errflg = 1; 936*7c478bd9Sstevel@tonic-gate goto out; 937*7c478bd9Sstevel@tonic-gate } 938*7c478bd9Sstevel@tonic-gate goto out; 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate if (rctlblkA == NULL) { 941*7c478bd9Sstevel@tonic-gate preserve_error(gettext("no matching " 942*7c478bd9Sstevel@tonic-gate "resource control found")); 943*7c478bd9Sstevel@tonic-gate errflg = 1; 944*7c478bd9Sstevel@tonic-gate goto out; 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate /* 947*7c478bd9Sstevel@tonic-gate * grab correct process. This is neccessary 948*7c478bd9Sstevel@tonic-gate * if the recipient pid does not match the 949*7c478bd9Sstevel@tonic-gate * one we grabbed 950*7c478bd9Sstevel@tonic-gate */ 951*7c478bd9Sstevel@tonic-gate pid = regrab_process( 952*7c478bd9Sstevel@tonic-gate rctlblk_get_recipient_pid(rctlblkA), 953*7c478bd9Sstevel@tonic-gate &p, arg_priv, &gret); 954*7c478bd9Sstevel@tonic-gate if (pid < 0) { 955*7c478bd9Sstevel@tonic-gate errflg = 1; 956*7c478bd9Sstevel@tonic-gate goto out; 957*7c478bd9Sstevel@tonic-gate } 958*7c478bd9Sstevel@tonic-gate localaction = 959*7c478bd9Sstevel@tonic-gate rctlblk_get_local_action(rctlblkA, 960*7c478bd9Sstevel@tonic-gate &signal); 961*7c478bd9Sstevel@tonic-gate rctlblk_set_local_action(rctlblkB, localaction, 962*7c478bd9Sstevel@tonic-gate signal); 963*7c478bd9Sstevel@tonic-gate rctlblk_set_privilege(rctlblkB, 964*7c478bd9Sstevel@tonic-gate rctlblk_get_privilege(rctlblkA)); 965*7c478bd9Sstevel@tonic-gate rctlblk_set_value(rctlblkB, 966*7c478bd9Sstevel@tonic-gate rctlblk_get_value(rctlblkA)); 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate if (change_action(rctlblkB)) { 969*7c478bd9Sstevel@tonic-gate errflg = 1; 970*7c478bd9Sstevel@tonic-gate goto out; 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate if (prctl_setrctl(p.pr, arg_name, rctlblkA, 973*7c478bd9Sstevel@tonic-gate rctlblkB, RCTL_REPLACE) != 0) { 974*7c478bd9Sstevel@tonic-gate errflg = 1; 975*7c478bd9Sstevel@tonic-gate goto out; 976*7c478bd9Sstevel@tonic-gate } 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate out: 979*7c478bd9Sstevel@tonic-gate release_process(p.pr); 980*7c478bd9Sstevel@tonic-gate if (rctlblkA) 981*7c478bd9Sstevel@tonic-gate free(rctlblkA); 982*7c478bd9Sstevel@tonic-gate if (rctlblkB) 983*7c478bd9Sstevel@tonic-gate free(rctlblkB); 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate /* Print any errors that occurred */ 986*7c478bd9Sstevel@tonic-gate if (errflg && *global_error != '\0') { 987*7c478bd9Sstevel@tonic-gate proc_unctrl_psinfo(&(p.psinfo)); 988*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%d:\t%.70s\n", 989*7c478bd9Sstevel@tonic-gate (int)p.pid, p.psinfo.pr_psargs); 990*7c478bd9Sstevel@tonic-gate warn("%s\n", global_error); 991*7c478bd9Sstevel@tonic-gate break; 992*7c478bd9Sstevel@tonic-gate } 993*7c478bd9Sstevel@tonic-gate } else { 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate struct project projent; 996*7c478bd9Sstevel@tonic-gate char buf[PROJECT_BUFSZ]; 997*7c478bd9Sstevel@tonic-gate char zonename[ZONENAME_MAX]; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * Hack to allow the user to specify a system 1001*7c478bd9Sstevel@tonic-gate * process. 1002*7c478bd9Sstevel@tonic-gate */ 1003*7c478bd9Sstevel@tonic-gate gret = G_SYS; 1004*7c478bd9Sstevel@tonic-gate pid = grab_process_by_id( 1005*7c478bd9Sstevel@tonic-gate target_id, search_type, &p, RCPRIV_BASIC, &gret); 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate /* 1008*7c478bd9Sstevel@tonic-gate * Print system process if user chose specifically 1009*7c478bd9Sstevel@tonic-gate * to inspect a system process. 1010*7c478bd9Sstevel@tonic-gate */ 1011*7c478bd9Sstevel@tonic-gate if (arg_entity_type == RCENTITY_PROCESS && 1012*7c478bd9Sstevel@tonic-gate pid < 0 && 1013*7c478bd9Sstevel@tonic-gate gret == G_SYS) { 1014*7c478bd9Sstevel@tonic-gate /* 1015*7c478bd9Sstevel@tonic-gate * Add blank lines between output for 1016*7c478bd9Sstevel@tonic-gate * operands. 1017*7c478bd9Sstevel@tonic-gate */ 1018*7c478bd9Sstevel@tonic-gate if (printed) { 1019*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate proc_unctrl_psinfo(&(p.psinfo)); 1023*7c478bd9Sstevel@tonic-gate (void) printf( 1024*7c478bd9Sstevel@tonic-gate "process: %d: %s [ system process ]\n", 1025*7c478bd9Sstevel@tonic-gate (int)p.pid, p.psinfo.pr_psargs); 1026*7c478bd9Sstevel@tonic-gate 1027*7c478bd9Sstevel@tonic-gate printed = 1; 1028*7c478bd9Sstevel@tonic-gate continue; 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate } else if (pid < 0) { 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate /* 1033*7c478bd9Sstevel@tonic-gate * Mark that an error occurred so that the 1034*7c478bd9Sstevel@tonic-gate * return value can be set, but continue 1035*7c478bd9Sstevel@tonic-gate * on with other processes 1036*7c478bd9Sstevel@tonic-gate */ 1037*7c478bd9Sstevel@tonic-gate errflg = 1; 1038*7c478bd9Sstevel@tonic-gate continue; 1039*7c478bd9Sstevel@tonic-gate } 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate errflg = get_rctls(p.pr); 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate release_process(p.pr); 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate /* handle user interrupt of getting rctls */ 1046*7c478bd9Sstevel@tonic-gate if (interrupt) 1047*7c478bd9Sstevel@tonic-gate break; 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate /* add blank lines between output for operands */ 1050*7c478bd9Sstevel@tonic-gate if (printed) { 1051*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate /* First print any errors */ 1054*7c478bd9Sstevel@tonic-gate if (errflg) { 1055*7c478bd9Sstevel@tonic-gate warn("%s\n", global_error); 1056*7c478bd9Sstevel@tonic-gate free_lists(); 1057*7c478bd9Sstevel@tonic-gate break; 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate if (getprojbyid(p.projid, &projent, buf, 1060*7c478bd9Sstevel@tonic-gate sizeof (buf))) { 1061*7c478bd9Sstevel@tonic-gate p.projname = projent.pj_name; 1062*7c478bd9Sstevel@tonic-gate } else { 1063*7c478bd9Sstevel@tonic-gate p.projname = ""; 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate if (getzonenamebyid(p.zoneid, zonename, 1066*7c478bd9Sstevel@tonic-gate sizeof (zonename)) > 0) { 1067*7c478bd9Sstevel@tonic-gate p.zonename = zonename; 1068*7c478bd9Sstevel@tonic-gate } else { 1069*7c478bd9Sstevel@tonic-gate p.zonename = ""; 1070*7c478bd9Sstevel@tonic-gate } 1071*7c478bd9Sstevel@tonic-gate print_rctls(&p); 1072*7c478bd9Sstevel@tonic-gate printed = 1; 1073*7c478bd9Sstevel@tonic-gate /* Free the resource control lists */ 1074*7c478bd9Sstevel@tonic-gate free_lists(); 1075*7c478bd9Sstevel@tonic-gate } 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate if (interrupt) 1078*7c478bd9Sstevel@tonic-gate errflg = 1; 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate /* 1081*7c478bd9Sstevel@tonic-gate * return error if one occurred 1082*7c478bd9Sstevel@tonic-gate */ 1083*7c478bd9Sstevel@tonic-gate return (errflg); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate static void 1088*7c478bd9Sstevel@tonic-gate intr(int sig) 1089*7c478bd9Sstevel@tonic-gate { 1090*7c478bd9Sstevel@tonic-gate interrupt = sig; 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate 1093*7c478bd9Sstevel@tonic-gate /* 1094*7c478bd9Sstevel@tonic-gate * get_rctls(struct ps_prochandle *, const char *) 1095*7c478bd9Sstevel@tonic-gate * 1096*7c478bd9Sstevel@tonic-gate * If controlname is given, store only controls for that named 1097*7c478bd9Sstevel@tonic-gate * resource. If controlname is NULL, store all controls for all 1098*7c478bd9Sstevel@tonic-gate * resources. 1099*7c478bd9Sstevel@tonic-gate * 1100*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 1101*7c478bd9Sstevel@tonic-gate */ 1102*7c478bd9Sstevel@tonic-gate static int 1103*7c478bd9Sstevel@tonic-gate get_rctls(struct ps_prochandle *Pr) 1104*7c478bd9Sstevel@tonic-gate { 1105*7c478bd9Sstevel@tonic-gate int ret = 0; 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate if (arg_name == NULL) { 1108*7c478bd9Sstevel@tonic-gate if (rctl_walk(store_rctls, Pr) != 0) 1109*7c478bd9Sstevel@tonic-gate ret = 1; 1110*7c478bd9Sstevel@tonic-gate } else { 1111*7c478bd9Sstevel@tonic-gate ret = store_rctls(arg_name, Pr); 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate return (ret); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate /* 1117*7c478bd9Sstevel@tonic-gate * store_rctls(const char *, void *) 1118*7c478bd9Sstevel@tonic-gate * 1119*7c478bd9Sstevel@tonic-gate * Store resource controls for the given name in a linked list. 1120*7c478bd9Sstevel@tonic-gate * Honor the user's options, and store only the ones they are 1121*7c478bd9Sstevel@tonic-gate * interested in. If priv is not 0, show only controls that match 1122*7c478bd9Sstevel@tonic-gate * the given privilege. 1123*7c478bd9Sstevel@tonic-gate * 1124*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe 1125*7c478bd9Sstevel@tonic-gate */ 1126*7c478bd9Sstevel@tonic-gate static int 1127*7c478bd9Sstevel@tonic-gate store_rctls(const char *rctlname, void *walk_data) 1128*7c478bd9Sstevel@tonic-gate { 1129*7c478bd9Sstevel@tonic-gate struct ps_prochandle *Pr = walk_data; 1130*7c478bd9Sstevel@tonic-gate rctlblk_t *rblk2, *rblk_tmp, *rblk1 = NULL; 1131*7c478bd9Sstevel@tonic-gate prctl_list_t *list = NULL; 1132*7c478bd9Sstevel@tonic-gate rctl_priv_t rblk_priv; 1133*7c478bd9Sstevel@tonic-gate rctl_entity_t rblk_entity; 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate if (((rblk1 = calloc(1, rctlblk_size())) == NULL) || 1136*7c478bd9Sstevel@tonic-gate ((rblk2 = calloc(1, rctlblk_size())) == NULL)) { 1137*7c478bd9Sstevel@tonic-gate if (rblk1 != NULL) 1138*7c478bd9Sstevel@tonic-gate free(rblk1); 1139*7c478bd9Sstevel@tonic-gate preserve_error(gettext("malloc failed: %s"), 1140*7c478bd9Sstevel@tonic-gate strerror(errno)); 1141*7c478bd9Sstevel@tonic-gate return (1); 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate if (pr_getrctl(Pr, rctlname, NULL, rblk1, RCTL_FIRST)) { 1144*7c478bd9Sstevel@tonic-gate preserve_error(gettext("failed to get resource control " 1145*7c478bd9Sstevel@tonic-gate "for %s: %s"), rctlname, strerror(errno)); 1146*7c478bd9Sstevel@tonic-gate free(rblk1); 1147*7c478bd9Sstevel@tonic-gate free(rblk2); 1148*7c478bd9Sstevel@tonic-gate return (1); 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate /* Store control if it matches privilege and enity type criteria */ 1151*7c478bd9Sstevel@tonic-gate rblk_priv = rctlblk_get_privilege(rblk1); 1152*7c478bd9Sstevel@tonic-gate rblk_entity = 0; 1153*7c478bd9Sstevel@tonic-gate if (strncmp(rctlname, "process.", 1154*7c478bd9Sstevel@tonic-gate strlen("process.")) == 0) 1155*7c478bd9Sstevel@tonic-gate rblk_entity = RCENTITY_PROCESS; 1156*7c478bd9Sstevel@tonic-gate else if (strncmp(rctlname, "project.", 1157*7c478bd9Sstevel@tonic-gate strlen("project.")) == 0) 1158*7c478bd9Sstevel@tonic-gate rblk_entity = RCENTITY_PROJECT; 1159*7c478bd9Sstevel@tonic-gate else if (strncmp(rctlname, "task.", 1160*7c478bd9Sstevel@tonic-gate strlen("task.")) == 0) 1161*7c478bd9Sstevel@tonic-gate rblk_entity = RCENTITY_TASK; 1162*7c478bd9Sstevel@tonic-gate else if (strncmp(rctlname, "zone.", 1163*7c478bd9Sstevel@tonic-gate strlen("zone.")) == 0) 1164*7c478bd9Sstevel@tonic-gate rblk_entity = RCENTITY_ZONE; 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate if (((arg_priv == 0) || (rblk_priv == arg_priv)) && 1167*7c478bd9Sstevel@tonic-gate ((arg_name == NULL) || 1168*7c478bd9Sstevel@tonic-gate strncmp(rctlname, arg_name, 1169*7c478bd9Sstevel@tonic-gate strlen(arg_name)) == 0) && 1170*7c478bd9Sstevel@tonic-gate (arg_entity_string == NULL || 1171*7c478bd9Sstevel@tonic-gate rblk_entity >= arg_entity_type)) { 1172*7c478bd9Sstevel@tonic-gate 1173*7c478bd9Sstevel@tonic-gate /* Once we know we have some controls, store the name */ 1174*7c478bd9Sstevel@tonic-gate if ((list = store_list_entry(rctlname)) == NULL) { 1175*7c478bd9Sstevel@tonic-gate free(rblk1); 1176*7c478bd9Sstevel@tonic-gate free(rblk2); 1177*7c478bd9Sstevel@tonic-gate return (1); 1178*7c478bd9Sstevel@tonic-gate } 1179*7c478bd9Sstevel@tonic-gate if (store_value_entry(rblk1, list) == NULL) { 1180*7c478bd9Sstevel@tonic-gate free(rblk1); 1181*7c478bd9Sstevel@tonic-gate free(rblk2); 1182*7c478bd9Sstevel@tonic-gate return (1); 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate while (pr_getrctl(Pr, rctlname, rblk1, rblk2, RCTL_NEXT) == 0) { 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate /* 1188*7c478bd9Sstevel@tonic-gate * in case this is stuck for some reason, allow manual 1189*7c478bd9Sstevel@tonic-gate * interrupt 1190*7c478bd9Sstevel@tonic-gate */ 1191*7c478bd9Sstevel@tonic-gate if (interrupt) { 1192*7c478bd9Sstevel@tonic-gate free(rblk1); 1193*7c478bd9Sstevel@tonic-gate free(rblk2); 1194*7c478bd9Sstevel@tonic-gate return (1); 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate rblk_priv = rctlblk_get_privilege(rblk2); 1197*7c478bd9Sstevel@tonic-gate /* 1198*7c478bd9Sstevel@tonic-gate * Store control if it matches privilege and entity type 1199*7c478bd9Sstevel@tonic-gate * criteria 1200*7c478bd9Sstevel@tonic-gate */ 1201*7c478bd9Sstevel@tonic-gate if (((arg_priv == 0) || (rblk_priv == arg_priv)) && 1202*7c478bd9Sstevel@tonic-gate ((arg_name == NULL) || 1203*7c478bd9Sstevel@tonic-gate strncmp(rctlname, arg_name, 1204*7c478bd9Sstevel@tonic-gate strlen(arg_name)) == 0) && 1205*7c478bd9Sstevel@tonic-gate (arg_entity_string == NULL || 1206*7c478bd9Sstevel@tonic-gate rblk_entity == arg_entity_type)) { 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate /* May not have created the list yet. */ 1209*7c478bd9Sstevel@tonic-gate if (list == NULL) { 1210*7c478bd9Sstevel@tonic-gate if ((list = store_list_entry(rctlname)) 1211*7c478bd9Sstevel@tonic-gate == NULL) { 1212*7c478bd9Sstevel@tonic-gate free(rblk1); 1213*7c478bd9Sstevel@tonic-gate free(rblk2); 1214*7c478bd9Sstevel@tonic-gate return (1); 1215*7c478bd9Sstevel@tonic-gate } 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate if (store_value_entry(rblk2, list) == NULL) { 1218*7c478bd9Sstevel@tonic-gate free(rblk1); 1219*7c478bd9Sstevel@tonic-gate free(rblk2); 1220*7c478bd9Sstevel@tonic-gate return (1); 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate rblk_tmp = rblk1; 1224*7c478bd9Sstevel@tonic-gate rblk1 = rblk2; 1225*7c478bd9Sstevel@tonic-gate rblk2 = rblk_tmp; 1226*7c478bd9Sstevel@tonic-gate } 1227*7c478bd9Sstevel@tonic-gate free(rblk1); 1228*7c478bd9Sstevel@tonic-gate free(rblk2); 1229*7c478bd9Sstevel@tonic-gate return (0); 1230*7c478bd9Sstevel@tonic-gate } 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate /* 1233*7c478bd9Sstevel@tonic-gate * store_value_entry(rctlblk_t *, prctl_list_t *) 1234*7c478bd9Sstevel@tonic-gate * 1235*7c478bd9Sstevel@tonic-gate * Store an rblk for a given resource control into the global list. 1236*7c478bd9Sstevel@tonic-gate * 1237*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 1238*7c478bd9Sstevel@tonic-gate */ 1239*7c478bd9Sstevel@tonic-gate prctl_value_t * 1240*7c478bd9Sstevel@tonic-gate store_value_entry(rctlblk_t *rblk, prctl_list_t *list) 1241*7c478bd9Sstevel@tonic-gate { 1242*7c478bd9Sstevel@tonic-gate prctl_value_t *e = calloc(1, sizeof (prctl_value_t)); 1243*7c478bd9Sstevel@tonic-gate rctlblk_t *store_blk = calloc(1, rctlblk_size()); 1244*7c478bd9Sstevel@tonic-gate prctl_value_t *iter = list->val_list; 1245*7c478bd9Sstevel@tonic-gate 1246*7c478bd9Sstevel@tonic-gate if (e == NULL || store_blk == NULL) { 1247*7c478bd9Sstevel@tonic-gate preserve_error(gettext("malloc failed %s"), 1248*7c478bd9Sstevel@tonic-gate strerror(errno)); 1249*7c478bd9Sstevel@tonic-gate if (e != NULL) 1250*7c478bd9Sstevel@tonic-gate free(e); 1251*7c478bd9Sstevel@tonic-gate if (store_blk != NULL) 1252*7c478bd9Sstevel@tonic-gate free(store_blk); 1253*7c478bd9Sstevel@tonic-gate return (NULL); 1254*7c478bd9Sstevel@tonic-gate } 1255*7c478bd9Sstevel@tonic-gate if (iter == NULL) 1256*7c478bd9Sstevel@tonic-gate list->val_list = e; 1257*7c478bd9Sstevel@tonic-gate else { 1258*7c478bd9Sstevel@tonic-gate while (iter->next != NULL) { 1259*7c478bd9Sstevel@tonic-gate iter = iter->next; 1260*7c478bd9Sstevel@tonic-gate } 1261*7c478bd9Sstevel@tonic-gate iter->next = e; 1262*7c478bd9Sstevel@tonic-gate } 1263*7c478bd9Sstevel@tonic-gate bcopy(rblk, store_blk, rctlblk_size()); 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate e->rblk = store_blk; 1266*7c478bd9Sstevel@tonic-gate e->next = NULL; 1267*7c478bd9Sstevel@tonic-gate return (e); 1268*7c478bd9Sstevel@tonic-gate } 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate /* 1271*7c478bd9Sstevel@tonic-gate * store_list_entry(const char *) 1272*7c478bd9Sstevel@tonic-gate * 1273*7c478bd9Sstevel@tonic-gate * Store a new resource control value in the global list. No checking 1274*7c478bd9Sstevel@tonic-gate * for duplicates done. 1275*7c478bd9Sstevel@tonic-gate * 1276*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 1277*7c478bd9Sstevel@tonic-gate */ 1278*7c478bd9Sstevel@tonic-gate prctl_list_t * 1279*7c478bd9Sstevel@tonic-gate store_list_entry(const char *name) 1280*7c478bd9Sstevel@tonic-gate { 1281*7c478bd9Sstevel@tonic-gate prctl_list_t *e = calloc(1, sizeof (prctl_list_t)); 1282*7c478bd9Sstevel@tonic-gate 1283*7c478bd9Sstevel@tonic-gate if (e == NULL) { 1284*7c478bd9Sstevel@tonic-gate preserve_error(gettext("malloc failed %s"), 1285*7c478bd9Sstevel@tonic-gate strerror(errno)); 1286*7c478bd9Sstevel@tonic-gate return (NULL); 1287*7c478bd9Sstevel@tonic-gate } 1288*7c478bd9Sstevel@tonic-gate if ((e->name = calloc(1, strlen(name) + 1)) == NULL) { 1289*7c478bd9Sstevel@tonic-gate preserve_error(gettext("malloc failed %s"), 1290*7c478bd9Sstevel@tonic-gate strerror(errno)); 1291*7c478bd9Sstevel@tonic-gate free(e); 1292*7c478bd9Sstevel@tonic-gate return (NULL); 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate (void) strcpy(e->name, name); 1295*7c478bd9Sstevel@tonic-gate e->val_list = NULL; 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate if (global_rctl_list_head == NULL) { 1298*7c478bd9Sstevel@tonic-gate global_rctl_list_head = e; 1299*7c478bd9Sstevel@tonic-gate global_rctl_list_tail = e; 1300*7c478bd9Sstevel@tonic-gate } else { 1301*7c478bd9Sstevel@tonic-gate global_rctl_list_tail->next = e; 1302*7c478bd9Sstevel@tonic-gate global_rctl_list_tail = e; 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate e->next = NULL; 1305*7c478bd9Sstevel@tonic-gate return (e); 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate /* 1309*7c478bd9Sstevel@tonic-gate * free_lists() 1310*7c478bd9Sstevel@tonic-gate * 1311*7c478bd9Sstevel@tonic-gate * Free all resource control blocks and values from the global lists. 1312*7c478bd9Sstevel@tonic-gate * 1313*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 1314*7c478bd9Sstevel@tonic-gate */ 1315*7c478bd9Sstevel@tonic-gate void 1316*7c478bd9Sstevel@tonic-gate free_lists() 1317*7c478bd9Sstevel@tonic-gate { 1318*7c478bd9Sstevel@tonic-gate prctl_list_t *new_list, *old_list = global_rctl_list_head; 1319*7c478bd9Sstevel@tonic-gate prctl_value_t *old_val, *new_val; 1320*7c478bd9Sstevel@tonic-gate 1321*7c478bd9Sstevel@tonic-gate while (old_list != NULL) { 1322*7c478bd9Sstevel@tonic-gate old_val = old_list->val_list; 1323*7c478bd9Sstevel@tonic-gate while (old_val != NULL) { 1324*7c478bd9Sstevel@tonic-gate free(old_val->rblk); 1325*7c478bd9Sstevel@tonic-gate new_val = old_val->next; 1326*7c478bd9Sstevel@tonic-gate free(old_val); 1327*7c478bd9Sstevel@tonic-gate old_val = new_val; 1328*7c478bd9Sstevel@tonic-gate } 1329*7c478bd9Sstevel@tonic-gate free(old_list->name); 1330*7c478bd9Sstevel@tonic-gate new_list = old_list->next; 1331*7c478bd9Sstevel@tonic-gate free(old_list); 1332*7c478bd9Sstevel@tonic-gate old_list = new_list; 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate global_rctl_list_head = NULL; 1335*7c478bd9Sstevel@tonic-gate global_rctl_list_tail = NULL; 1336*7c478bd9Sstevel@tonic-gate } 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate void 1339*7c478bd9Sstevel@tonic-gate print_heading() 1340*7c478bd9Sstevel@tonic-gate { 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate /* print headings */ 1343*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%-8s%-16s%-9s%-7s%-28s%10s\n", 1344*7c478bd9Sstevel@tonic-gate "NAME", "PRIVILEGE", "VALUE", 1345*7c478bd9Sstevel@tonic-gate "FLAG", "ACTION", "RECIPIENT"); 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate 1348*7c478bd9Sstevel@tonic-gate /* 1349*7c478bd9Sstevel@tonic-gate * print_rctls() 1350*7c478bd9Sstevel@tonic-gate * 1351*7c478bd9Sstevel@tonic-gate * Print all resource controls from the global list that was 1352*7c478bd9Sstevel@tonic-gate * previously populated by store_rctls. 1353*7c478bd9Sstevel@tonic-gate */ 1354*7c478bd9Sstevel@tonic-gate void 1355*7c478bd9Sstevel@tonic-gate print_rctls(pr_info_handle_t *p) 1356*7c478bd9Sstevel@tonic-gate { 1357*7c478bd9Sstevel@tonic-gate prctl_list_t *iter_list = global_rctl_list_head; 1358*7c478bd9Sstevel@tonic-gate prctl_value_t *iter_val; 1359*7c478bd9Sstevel@tonic-gate rctl_qty_t rblk_value; 1360*7c478bd9Sstevel@tonic-gate rctl_priv_t rblk_priv; 1361*7c478bd9Sstevel@tonic-gate uint_t local_action; 1362*7c478bd9Sstevel@tonic-gate int signal, local_flags, global_flags; 1363*7c478bd9Sstevel@tonic-gate pid_t pid; 1364*7c478bd9Sstevel@tonic-gate char rctl_valuestring[SCALED_STRLEN]; 1365*7c478bd9Sstevel@tonic-gate char *unit = NULL; 1366*7c478bd9Sstevel@tonic-gate scale_t *scale; 1367*7c478bd9Sstevel@tonic-gate char *string; 1368*7c478bd9Sstevel@tonic-gate int doneheading = 0; 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate if (iter_list == NULL) 1371*7c478bd9Sstevel@tonic-gate return; 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate while (iter_list != NULL) { 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate if (doneheading == 0 && 1376*7c478bd9Sstevel@tonic-gate arg_entity_type == RCENTITY_PROCESS) { 1377*7c478bd9Sstevel@tonic-gate proc_unctrl_psinfo(&(p->psinfo)); 1378*7c478bd9Sstevel@tonic-gate doneheading = 1; 1379*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 1380*7c478bd9Sstevel@tonic-gate "process: %d: %.70s\n", (int)p->pid, 1381*7c478bd9Sstevel@tonic-gate p->psinfo.pr_psargs); 1382*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1383*7c478bd9Sstevel@tonic-gate print_heading(); 1384*7c478bd9Sstevel@tonic-gate } 1385*7c478bd9Sstevel@tonic-gate if (doneheading == 0 && 1386*7c478bd9Sstevel@tonic-gate arg_entity_type == RCENTITY_TASK) { 1387*7c478bd9Sstevel@tonic-gate doneheading = 1; 1388*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "task: %d\n", (int)p->taskid); 1389*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1390*7c478bd9Sstevel@tonic-gate print_heading(); 1391*7c478bd9Sstevel@tonic-gate } 1392*7c478bd9Sstevel@tonic-gate if (doneheading == 0 && 1393*7c478bd9Sstevel@tonic-gate arg_entity_type == RCENTITY_PROJECT) { 1394*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode && doneheading) 1395*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 1396*7c478bd9Sstevel@tonic-gate doneheading = 1; 1397*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 1398*7c478bd9Sstevel@tonic-gate "project: %d: %.70s\n", (int)p->projid, 1399*7c478bd9Sstevel@tonic-gate p->projname); 1400*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1401*7c478bd9Sstevel@tonic-gate print_heading(); 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate if (doneheading == 0 && 1404*7c478bd9Sstevel@tonic-gate arg_entity_type == RCENTITY_ZONE) { 1405*7c478bd9Sstevel@tonic-gate doneheading = 1; 1406*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 1407*7c478bd9Sstevel@tonic-gate "zone: %d: %.70s\n", (int)p->zoneid, 1408*7c478bd9Sstevel@tonic-gate p->zonename); 1409*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1410*7c478bd9Sstevel@tonic-gate print_heading(); 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate /* only print name once in normal output */ 1413*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1414*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s\n", iter_list->name); 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate iter_val = iter_list->val_list; 1417*7c478bd9Sstevel@tonic-gate 1418*7c478bd9Sstevel@tonic-gate /* if for some reason there are no values, skip */ 1419*7c478bd9Sstevel@tonic-gate if (iter_val == 0) 1420*7c478bd9Sstevel@tonic-gate continue; 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate 1423*7c478bd9Sstevel@tonic-gate /* get the global flags the first rctl only */ 1424*7c478bd9Sstevel@tonic-gate global_flags = rctlblk_get_global_flags(iter_val->rblk); 1425*7c478bd9Sstevel@tonic-gate 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate if (global_flags & RCTL_GLOBAL_BYTES) { 1428*7c478bd9Sstevel@tonic-gate unit = SCALED_UNIT_BYTES; 1429*7c478bd9Sstevel@tonic-gate scale = scale_binary; 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate } else if (global_flags & RCTL_GLOBAL_SECONDS) { 1432*7c478bd9Sstevel@tonic-gate unit = SCALED_UNIT_SECONDS; 1433*7c478bd9Sstevel@tonic-gate scale = scale_metric; 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate } else { 1436*7c478bd9Sstevel@tonic-gate unit = SCALED_UNIT_NONE; 1437*7c478bd9Sstevel@tonic-gate scale = scale_metric; 1438*7c478bd9Sstevel@tonic-gate } 1439*7c478bd9Sstevel@tonic-gate /* iterate over an print all control values */ 1440*7c478bd9Sstevel@tonic-gate while (iter_val != NULL) { 1441*7c478bd9Sstevel@tonic-gate 1442*7c478bd9Sstevel@tonic-gate /* print name or empty name field */ 1443*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1444*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%8s", ""); 1445*7c478bd9Sstevel@tonic-gate else 1446*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s ", iter_list->name); 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate rblk_priv = rctlblk_get_privilege(iter_val->rblk); 1450*7c478bd9Sstevel@tonic-gate if (!arg_parseable_mode) 1451*7c478bd9Sstevel@tonic-gate print_priv(rblk_priv, "%-16s"); 1452*7c478bd9Sstevel@tonic-gate else 1453*7c478bd9Sstevel@tonic-gate print_priv(rblk_priv, "%s "); 1454*7c478bd9Sstevel@tonic-gate 1455*7c478bd9Sstevel@tonic-gate rblk_value = rctlblk_get_value(iter_val->rblk); 1456*7c478bd9Sstevel@tonic-gate if (arg_parseable_mode) { 1457*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%llu ", rblk_value); 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate } else { 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate (void) uint64toscaled(rblk_value, 4, "E", 1462*7c478bd9Sstevel@tonic-gate rctl_valuestring, NULL, NULL, 1463*7c478bd9Sstevel@tonic-gate scale, NULL, 0); 1464*7c478bd9Sstevel@tonic-gate 1465*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%5s", 1466*7c478bd9Sstevel@tonic-gate rctl_valuestring); 1467*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%-4s", unit); 1468*7c478bd9Sstevel@tonic-gate } 1469*7c478bd9Sstevel@tonic-gate local_flags = rctlblk_get_local_flags(iter_val->rblk); 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate if (local_flags & RCTL_LOCAL_MAXIMAL) { 1472*7c478bd9Sstevel@tonic-gate 1473*7c478bd9Sstevel@tonic-gate if (global_flags & RCTL_GLOBAL_INFINITE) { 1474*7c478bd9Sstevel@tonic-gate string = "inf"; 1475*7c478bd9Sstevel@tonic-gate } else { 1476*7c478bd9Sstevel@tonic-gate string = "max"; 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate } else { 1479*7c478bd9Sstevel@tonic-gate string = "-"; 1480*7c478bd9Sstevel@tonic-gate } 1481*7c478bd9Sstevel@tonic-gate if (arg_parseable_mode) 1482*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s ", string); 1483*7c478bd9Sstevel@tonic-gate else 1484*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%4s%3s", 1485*7c478bd9Sstevel@tonic-gate string, ""); 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate local_action = rctlblk_get_local_action(iter_val->rblk, 1489*7c478bd9Sstevel@tonic-gate &signal); 1490*7c478bd9Sstevel@tonic-gate 1491*7c478bd9Sstevel@tonic-gate if (arg_parseable_mode) 1492*7c478bd9Sstevel@tonic-gate print_local_action(local_action, &signal, 1493*7c478bd9Sstevel@tonic-gate "%s "); 1494*7c478bd9Sstevel@tonic-gate else 1495*7c478bd9Sstevel@tonic-gate print_local_action(local_action, &signal, 1496*7c478bd9Sstevel@tonic-gate "%-28s"); 1497*7c478bd9Sstevel@tonic-gate 1498*7c478bd9Sstevel@tonic-gate pid = rctlblk_get_recipient_pid(iter_val->rblk); 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate if (arg_parseable_mode) { 1501*7c478bd9Sstevel@tonic-gate if (pid < 0) { 1502*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s\n", "-"); 1503*7c478bd9Sstevel@tonic-gate } else { 1504*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%d\n", 1505*7c478bd9Sstevel@tonic-gate (int)pid); 1506*7c478bd9Sstevel@tonic-gate } 1507*7c478bd9Sstevel@tonic-gate } else { 1508*7c478bd9Sstevel@tonic-gate if (pid < 0) { 1509*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%10s\n", "-"); 1510*7c478bd9Sstevel@tonic-gate } else { 1511*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%10d\n", 1512*7c478bd9Sstevel@tonic-gate (int)pid); 1513*7c478bd9Sstevel@tonic-gate } 1514*7c478bd9Sstevel@tonic-gate } 1515*7c478bd9Sstevel@tonic-gate iter_val = iter_val->next; 1516*7c478bd9Sstevel@tonic-gate } 1517*7c478bd9Sstevel@tonic-gate iter_list = iter_list->next; 1518*7c478bd9Sstevel@tonic-gate } 1519*7c478bd9Sstevel@tonic-gate } 1520*7c478bd9Sstevel@tonic-gate 1521*7c478bd9Sstevel@tonic-gate /* 1522*7c478bd9Sstevel@tonic-gate * 1523*7c478bd9Sstevel@tonic-gate * match_rctl 1524*7c478bd9Sstevel@tonic-gate * 1525*7c478bd9Sstevel@tonic-gate * find the first rctl with matching name, value, priv, and recipient pid 1526*7c478bd9Sstevel@tonic-gate */ 1527*7c478bd9Sstevel@tonic-gate int 1528*7c478bd9Sstevel@tonic-gate match_rctl(struct ps_prochandle *Pr, rctlblk_t **rctl, char *name, 1529*7c478bd9Sstevel@tonic-gate char *valuestringin, int valuein, rctl_priv_t privin, int pidin) 1530*7c478bd9Sstevel@tonic-gate { 1531*7c478bd9Sstevel@tonic-gate rctlblk_t *next; 1532*7c478bd9Sstevel@tonic-gate rctlblk_t *last; 1533*7c478bd9Sstevel@tonic-gate rctlblk_t *tmp; 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate *rctl = NULL; 1536*7c478bd9Sstevel@tonic-gate 1537*7c478bd9Sstevel@tonic-gate next = calloc(1, rctlblk_size()); 1538*7c478bd9Sstevel@tonic-gate last = calloc(1, rctlblk_size()); 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate if ((last == NULL) || (next == NULL)) { 1541*7c478bd9Sstevel@tonic-gate preserve_error(gettext("malloc failed"), strerror(errno)); 1542*7c478bd9Sstevel@tonic-gate return (-1); 1543*7c478bd9Sstevel@tonic-gate } 1544*7c478bd9Sstevel@tonic-gate /* 1545*7c478bd9Sstevel@tonic-gate * For this resource name, now iterate through all 1546*7c478bd9Sstevel@tonic-gate * the controls, looking for a match to the 1547*7c478bd9Sstevel@tonic-gate * user-specified input. 1548*7c478bd9Sstevel@tonic-gate */ 1549*7c478bd9Sstevel@tonic-gate if (pr_getrctl(Pr, name, NULL, next, RCTL_FIRST)) { 1550*7c478bd9Sstevel@tonic-gate preserve_error(gettext("failed to get resource control " 1551*7c478bd9Sstevel@tonic-gate "for %s: %s"), name, strerror(errno)); 1552*7c478bd9Sstevel@tonic-gate return (-1); 1553*7c478bd9Sstevel@tonic-gate } 1554*7c478bd9Sstevel@tonic-gate if (match_rctl_blk(next, valuestringin, valuein, privin, pidin) == 1) { 1555*7c478bd9Sstevel@tonic-gate free(last); 1556*7c478bd9Sstevel@tonic-gate *rctl = next; 1557*7c478bd9Sstevel@tonic-gate return (0); 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate tmp = next; 1560*7c478bd9Sstevel@tonic-gate next = last; 1561*7c478bd9Sstevel@tonic-gate last = tmp; 1562*7c478bd9Sstevel@tonic-gate 1563*7c478bd9Sstevel@tonic-gate while (pr_getrctl(Pr, name, last, next, RCTL_NEXT) == 0) { 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate /* allow user interrupt */ 1566*7c478bd9Sstevel@tonic-gate if (interrupt) 1567*7c478bd9Sstevel@tonic-gate break; 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate if (match_rctl_blk(next, valuestringin, valuein, privin, pidin) 1570*7c478bd9Sstevel@tonic-gate == 1) { 1571*7c478bd9Sstevel@tonic-gate free(last); 1572*7c478bd9Sstevel@tonic-gate *rctl = next; 1573*7c478bd9Sstevel@tonic-gate return (0); 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate tmp = next; 1576*7c478bd9Sstevel@tonic-gate next = last; 1577*7c478bd9Sstevel@tonic-gate last = tmp; 1578*7c478bd9Sstevel@tonic-gate } 1579*7c478bd9Sstevel@tonic-gate free(next); 1580*7c478bd9Sstevel@tonic-gate free(last); 1581*7c478bd9Sstevel@tonic-gate 1582*7c478bd9Sstevel@tonic-gate return (1); 1583*7c478bd9Sstevel@tonic-gate } 1584*7c478bd9Sstevel@tonic-gate 1585*7c478bd9Sstevel@tonic-gate /* 1586*7c478bd9Sstevel@tonic-gate * int match_rctl_blk(rctlblk_t *, char *, uint64, rctl_priv_t, int pid) 1587*7c478bd9Sstevel@tonic-gate * 1588*7c478bd9Sstevel@tonic-gate * Input 1589*7c478bd9Sstevel@tonic-gate * Must supply a valid rctl, value, privilege, and pid to match on. 1590*7c478bd9Sstevel@tonic-gate * If valuestring is NULL, then valuestring and valuein will not be used 1591*7c478bd9Sstevel@tonic-gate * If privilege type is 0 it will not be used. 1592*7c478bd9Sstevel@tonic-gate * If pid is -1 it will not be used. 1593*7c478bd9Sstevel@tonic-gate * 1594*7c478bd9Sstevel@tonic-gate * Return values 1595*7c478bd9Sstevel@tonic-gate * Returns 1 if a matching rctl given matches the parameters specified, and 1596*7c478bd9Sstevel@tonic-gate * 0 if they do not. 1597*7c478bd9Sstevel@tonic-gate * 1598*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 1599*7c478bd9Sstevel@tonic-gate */ 1600*7c478bd9Sstevel@tonic-gate int 1601*7c478bd9Sstevel@tonic-gate match_rctl_blk(rctlblk_t *rctl, char *valuestringin, 1602*7c478bd9Sstevel@tonic-gate uint64_t valuein, rctl_priv_t privin, int pidin) 1603*7c478bd9Sstevel@tonic-gate { 1604*7c478bd9Sstevel@tonic-gate 1605*7c478bd9Sstevel@tonic-gate rctl_qty_t value; 1606*7c478bd9Sstevel@tonic-gate rctl_priv_t priv; 1607*7c478bd9Sstevel@tonic-gate pid_t pid; 1608*7c478bd9Sstevel@tonic-gate int valuematch = 1; 1609*7c478bd9Sstevel@tonic-gate int privmatch = 1; 1610*7c478bd9Sstevel@tonic-gate int pidmatch = 1; 1611*7c478bd9Sstevel@tonic-gate 1612*7c478bd9Sstevel@tonic-gate value = rctlblk_get_value(rctl); 1613*7c478bd9Sstevel@tonic-gate priv = rctlblk_get_privilege(rctl); 1614*7c478bd9Sstevel@tonic-gate pid = rctlblk_get_recipient_pid(rctl); 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate if (valuestringin) { 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate if (arg_modifier == NULL) { 1619*7c478bd9Sstevel@tonic-gate valuematch = (valuein == value); 1620*7c478bd9Sstevel@tonic-gate } else { 1621*7c478bd9Sstevel@tonic-gate valuematch = scaledequint64(valuestringin, value, 1622*7c478bd9Sstevel@tonic-gate PRCTL_VALUE_WIDTH, 1623*7c478bd9Sstevel@tonic-gate arg_scale, arg_unit, 1624*7c478bd9Sstevel@tonic-gate SCALED_ALL_FLAGS); 1625*7c478bd9Sstevel@tonic-gate } 1626*7c478bd9Sstevel@tonic-gate } 1627*7c478bd9Sstevel@tonic-gate if (privin != 0) { 1628*7c478bd9Sstevel@tonic-gate privmatch = (privin == priv); 1629*7c478bd9Sstevel@tonic-gate } 1630*7c478bd9Sstevel@tonic-gate if (pidin != -1) { 1631*7c478bd9Sstevel@tonic-gate pidmatch = (pidin == pid); 1632*7c478bd9Sstevel@tonic-gate } 1633*7c478bd9Sstevel@tonic-gate return (valuematch && privmatch && pidmatch); 1634*7c478bd9Sstevel@tonic-gate } 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate static int 1637*7c478bd9Sstevel@tonic-gate change_action(rctlblk_t *blk) 1638*7c478bd9Sstevel@tonic-gate { 1639*7c478bd9Sstevel@tonic-gate int signal = 0; 1640*7c478bd9Sstevel@tonic-gate int action; 1641*7c478bd9Sstevel@tonic-gate 1642*7c478bd9Sstevel@tonic-gate action = rctlblk_get_local_action(blk, &signal); 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate if (arg_operation & ACTION_ENABLE) { 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate if (arg_action & RCTL_LOCAL_SIGNAL) { 1647*7c478bd9Sstevel@tonic-gate signal = arg_signal; 1648*7c478bd9Sstevel@tonic-gate } 1649*7c478bd9Sstevel@tonic-gate action = action | arg_action; 1650*7c478bd9Sstevel@tonic-gate /* add local action */ 1651*7c478bd9Sstevel@tonic-gate rctlblk_set_local_action(blk, action, signal); 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate } else if (arg_operation & ACTION_DISABLE) { 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate /* 1656*7c478bd9Sstevel@tonic-gate * if deleting signal and signal number is specified, 1657*7c478bd9Sstevel@tonic-gate * then signal number must match 1658*7c478bd9Sstevel@tonic-gate */ 1659*7c478bd9Sstevel@tonic-gate if ((arg_action & RCTL_LOCAL_SIGNAL) && 1660*7c478bd9Sstevel@tonic-gate (arg_signal != -1)) { 1661*7c478bd9Sstevel@tonic-gate if (arg_signal != signal) { 1662*7c478bd9Sstevel@tonic-gate preserve_error(gettext("signal name or number " 1663*7c478bd9Sstevel@tonic-gate "does not match existing action")); 1664*7c478bd9Sstevel@tonic-gate return (-1); 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate } 1667*7c478bd9Sstevel@tonic-gate /* remove local action */ 1668*7c478bd9Sstevel@tonic-gate action = action & (~arg_action); 1669*7c478bd9Sstevel@tonic-gate rctlblk_set_local_action(blk, RCTL_LOCAL_NOACTION, 0); 1670*7c478bd9Sstevel@tonic-gate rctlblk_set_local_action(blk, action, signal); 1671*7c478bd9Sstevel@tonic-gate } 1672*7c478bd9Sstevel@tonic-gate /* enable deny if it must be enabled */ 1673*7c478bd9Sstevel@tonic-gate if (arg_global_flags & RCTL_GLOBAL_DENY_ALWAYS) { 1674*7c478bd9Sstevel@tonic-gate rctlblk_set_local_action(blk, RCTL_LOCAL_DENY | action, 1675*7c478bd9Sstevel@tonic-gate signal); 1676*7c478bd9Sstevel@tonic-gate } 1677*7c478bd9Sstevel@tonic-gate return (0); 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate 1680*7c478bd9Sstevel@tonic-gate /* 1681*7c478bd9Sstevel@tonic-gate * prctl_setrctl 1682*7c478bd9Sstevel@tonic-gate * 1683*7c478bd9Sstevel@tonic-gate * Input 1684*7c478bd9Sstevel@tonic-gate * This function expects that input has been validated. In the 1685*7c478bd9Sstevel@tonic-gate * case of a replace operation, both old_rblk and new_rblk must 1686*7c478bd9Sstevel@tonic-gate * be valid resource controls. If a resource control is being 1687*7c478bd9Sstevel@tonic-gate * created, only new_rblk must be supplied. If a resource control 1688*7c478bd9Sstevel@tonic-gate * is being deleted, only new_rblk must be supplied. 1689*7c478bd9Sstevel@tonic-gate * 1690*7c478bd9Sstevel@tonic-gate * If the privilege is a priviliged type, at this time, the process 1691*7c478bd9Sstevel@tonic-gate * tries to take on superuser privileges. 1692*7c478bd9Sstevel@tonic-gate */ 1693*7c478bd9Sstevel@tonic-gate int 1694*7c478bd9Sstevel@tonic-gate prctl_setrctl(struct ps_prochandle *Pr, const char *name, 1695*7c478bd9Sstevel@tonic-gate rctlblk_t *old_rblk, rctlblk_t *new_rblk, uint_t flags) 1696*7c478bd9Sstevel@tonic-gate { 1697*7c478bd9Sstevel@tonic-gate int ret = 0; 1698*7c478bd9Sstevel@tonic-gate rctl_priv_t rblk_priv; 1699*7c478bd9Sstevel@tonic-gate psinfo_t psinfo; 1700*7c478bd9Sstevel@tonic-gate zoneid_t oldzoneid = GLOBAL_ZONEID; 1701*7c478bd9Sstevel@tonic-gate prpriv_t *old_prpriv = NULL, *new_prpriv = NULL; 1702*7c478bd9Sstevel@tonic-gate priv_set_t *eset, *pset; 1703*7c478bd9Sstevel@tonic-gate boolean_t relinquish_failed = B_FALSE; 1704*7c478bd9Sstevel@tonic-gate 1705*7c478bd9Sstevel@tonic-gate rblk_priv = rctlblk_get_privilege(new_rblk); 1706*7c478bd9Sstevel@tonic-gate 1707*7c478bd9Sstevel@tonic-gate if (rblk_priv == RCPRIV_SYSTEM) { 1708*7c478bd9Sstevel@tonic-gate preserve_error(gettext("cannot modify system values")); 1709*7c478bd9Sstevel@tonic-gate return (1); 1710*7c478bd9Sstevel@tonic-gate } 1711*7c478bd9Sstevel@tonic-gate if (rblk_priv == RCPRIV_PRIVILEGED) { 1712*7c478bd9Sstevel@tonic-gate new_prpriv = proc_get_priv(Pstatus(Pr)->pr_pid); 1713*7c478bd9Sstevel@tonic-gate if (new_prpriv == NULL) { 1714*7c478bd9Sstevel@tonic-gate preserve_error(gettext("cannot get process privileges " 1715*7c478bd9Sstevel@tonic-gate "for pid %d: %s"), Pstatus(Pr)->pr_pid, 1716*7c478bd9Sstevel@tonic-gate strerror(errno)); 1717*7c478bd9Sstevel@tonic-gate return (1); 1718*7c478bd9Sstevel@tonic-gate } 1719*7c478bd9Sstevel@tonic-gate /* 1720*7c478bd9Sstevel@tonic-gate * We only have to change the process privileges if it doesn't 1721*7c478bd9Sstevel@tonic-gate * already have PRIV_SYS_RESOURCE. In addition, we want to make 1722*7c478bd9Sstevel@tonic-gate * sure that we don't leave a process with elevated privileges, 1723*7c478bd9Sstevel@tonic-gate * so we make sure the process dies if we exit unexpectedly. 1724*7c478bd9Sstevel@tonic-gate */ 1725*7c478bd9Sstevel@tonic-gate eset = (priv_set_t *) 1726*7c478bd9Sstevel@tonic-gate &new_prpriv->pr_sets[new_prpriv->pr_setsize * 1727*7c478bd9Sstevel@tonic-gate priv_getsetbyname(PRIV_EFFECTIVE)]; 1728*7c478bd9Sstevel@tonic-gate pset = (priv_set_t *) 1729*7c478bd9Sstevel@tonic-gate &new_prpriv->pr_sets[new_prpriv->pr_setsize * 1730*7c478bd9Sstevel@tonic-gate priv_getsetbyname(PRIV_PERMITTED)]; 1731*7c478bd9Sstevel@tonic-gate if (!priv_ismember(eset, PRIV_SYS_RESOURCE)) { 1732*7c478bd9Sstevel@tonic-gate /* Keep track of original privileges */ 1733*7c478bd9Sstevel@tonic-gate old_prpriv = proc_get_priv(Pstatus(Pr)->pr_pid); 1734*7c478bd9Sstevel@tonic-gate if (old_prpriv == NULL) { 1735*7c478bd9Sstevel@tonic-gate preserve_error(gettext("cannot get process " 1736*7c478bd9Sstevel@tonic-gate "privileges for pid %d: %s"), 1737*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1738*7c478bd9Sstevel@tonic-gate free(new_prpriv); 1739*7c478bd9Sstevel@tonic-gate return (1); 1740*7c478bd9Sstevel@tonic-gate } 1741*7c478bd9Sstevel@tonic-gate (void) priv_addset(eset, PRIV_SYS_RESOURCE); 1742*7c478bd9Sstevel@tonic-gate (void) priv_addset(pset, PRIV_SYS_RESOURCE); 1743*7c478bd9Sstevel@tonic-gate if (Psetflags(Pr, PR_KLC) != 0 || 1744*7c478bd9Sstevel@tonic-gate Psetpriv(Pr, new_prpriv) != 0) { 1745*7c478bd9Sstevel@tonic-gate preserve_error(gettext("cannot set process " 1746*7c478bd9Sstevel@tonic-gate "privileges for pid %d: %s"), 1747*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1748*7c478bd9Sstevel@tonic-gate (void) Punsetflags(Pr, PR_KLC); 1749*7c478bd9Sstevel@tonic-gate free(new_prpriv); 1750*7c478bd9Sstevel@tonic-gate free(old_prpriv); 1751*7c478bd9Sstevel@tonic-gate return (1); 1752*7c478bd9Sstevel@tonic-gate } 1753*7c478bd9Sstevel@tonic-gate } 1754*7c478bd9Sstevel@tonic-gate /* 1755*7c478bd9Sstevel@tonic-gate * If this is a zone.* rctl, it requires more than 1756*7c478bd9Sstevel@tonic-gate * PRIV_SYS_RESOURCE: it wants the process to have global-zone 1757*7c478bd9Sstevel@tonic-gate * credentials. We temporarily grant non-global zone processes 1758*7c478bd9Sstevel@tonic-gate * these credentials, and make sure the process dies if we exit 1759*7c478bd9Sstevel@tonic-gate * unexpectedly. 1760*7c478bd9Sstevel@tonic-gate */ 1761*7c478bd9Sstevel@tonic-gate if (arg_name && 1762*7c478bd9Sstevel@tonic-gate arg_name_entity == RCENTITY_ZONE && 1763*7c478bd9Sstevel@tonic-gate getzoneid() == GLOBAL_ZONEID && 1764*7c478bd9Sstevel@tonic-gate proc_get_psinfo(Pstatus(Pr)->pr_pid, &psinfo) == 0 && 1765*7c478bd9Sstevel@tonic-gate (oldzoneid = psinfo.pr_zoneid) != GLOBAL_ZONEID) { 1766*7c478bd9Sstevel@tonic-gate /* 1767*7c478bd9Sstevel@tonic-gate * We need to give this process superuser 1768*7c478bd9Sstevel@tonic-gate * ("super-zone") privileges. 1769*7c478bd9Sstevel@tonic-gate * 1770*7c478bd9Sstevel@tonic-gate * Must never return without setting this back! 1771*7c478bd9Sstevel@tonic-gate */ 1772*7c478bd9Sstevel@tonic-gate if (Psetflags(Pr, PR_KLC) != 0 || 1773*7c478bd9Sstevel@tonic-gate Psetzoneid(Pr, GLOBAL_ZONEID) < 0) { 1774*7c478bd9Sstevel@tonic-gate preserve_error(gettext( 1775*7c478bd9Sstevel@tonic-gate "cannot set global-zone " 1776*7c478bd9Sstevel@tonic-gate "privileges for pid %d: %s"), 1777*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1778*7c478bd9Sstevel@tonic-gate /* 1779*7c478bd9Sstevel@tonic-gate * We couldn't set the zoneid to begin with, so 1780*7c478bd9Sstevel@tonic-gate * there's no point in warning the user about 1781*7c478bd9Sstevel@tonic-gate * trying to un-set it. 1782*7c478bd9Sstevel@tonic-gate */ 1783*7c478bd9Sstevel@tonic-gate oldzoneid = GLOBAL_ZONEID; 1784*7c478bd9Sstevel@tonic-gate ret = 1; 1785*7c478bd9Sstevel@tonic-gate goto bail; 1786*7c478bd9Sstevel@tonic-gate } 1787*7c478bd9Sstevel@tonic-gate } 1788*7c478bd9Sstevel@tonic-gate } 1789*7c478bd9Sstevel@tonic-gate /* Now, actually populate the rctlblk in the kernel */ 1790*7c478bd9Sstevel@tonic-gate if (flags == RCTL_REPLACE) { 1791*7c478bd9Sstevel@tonic-gate /* 1792*7c478bd9Sstevel@tonic-gate * Replace should be a delete followed by an insert. This 1793*7c478bd9Sstevel@tonic-gate * allows us to replace rctl value blocks which match in 1794*7c478bd9Sstevel@tonic-gate * privilege and value, but have updated actions, etc. 1795*7c478bd9Sstevel@tonic-gate * setrctl() doesn't allow a direct replace, but we 1796*7c478bd9Sstevel@tonic-gate * should do the right thing for the user in the command. 1797*7c478bd9Sstevel@tonic-gate */ 1798*7c478bd9Sstevel@tonic-gate if (pr_setrctl(Pr, name, NULL, 1799*7c478bd9Sstevel@tonic-gate old_rblk, RCTL_DELETE)) { 1800*7c478bd9Sstevel@tonic-gate preserve_error(gettext("failed to delete resource " 1801*7c478bd9Sstevel@tonic-gate "control %s for pid %d: %s"), name, 1802*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1803*7c478bd9Sstevel@tonic-gate ret = 1; 1804*7c478bd9Sstevel@tonic-gate goto bail; 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate if (pr_setrctl(Pr, name, NULL, 1807*7c478bd9Sstevel@tonic-gate new_rblk, RCTL_INSERT)) { 1808*7c478bd9Sstevel@tonic-gate preserve_error(gettext("failed to insert resource " 1809*7c478bd9Sstevel@tonic-gate "control %s for pid %d: %s"), name, 1810*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1811*7c478bd9Sstevel@tonic-gate ret = 1; 1812*7c478bd9Sstevel@tonic-gate goto bail; 1813*7c478bd9Sstevel@tonic-gate } 1814*7c478bd9Sstevel@tonic-gate } else if (flags == RCTL_INSERT) { 1815*7c478bd9Sstevel@tonic-gate if (pr_setrctl(Pr, name, NULL, 1816*7c478bd9Sstevel@tonic-gate new_rblk, RCTL_INSERT)) { 1817*7c478bd9Sstevel@tonic-gate preserve_error(gettext("failed to create resource " 1818*7c478bd9Sstevel@tonic-gate "control %s for pid %d: %s"), name, 1819*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1820*7c478bd9Sstevel@tonic-gate ret = 1; 1821*7c478bd9Sstevel@tonic-gate goto bail; 1822*7c478bd9Sstevel@tonic-gate } 1823*7c478bd9Sstevel@tonic-gate } else if (flags == RCTL_DELETE) { 1824*7c478bd9Sstevel@tonic-gate if (pr_setrctl(Pr, name, NULL, 1825*7c478bd9Sstevel@tonic-gate new_rblk, RCTL_DELETE)) { 1826*7c478bd9Sstevel@tonic-gate preserve_error(gettext("failed to delete resource " 1827*7c478bd9Sstevel@tonic-gate "control %s for pid %d: %s"), name, 1828*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid, strerror(errno)); 1829*7c478bd9Sstevel@tonic-gate ret = 1; 1830*7c478bd9Sstevel@tonic-gate goto bail; 1831*7c478bd9Sstevel@tonic-gate } 1832*7c478bd9Sstevel@tonic-gate } 1833*7c478bd9Sstevel@tonic-gate bail: 1834*7c478bd9Sstevel@tonic-gate if (oldzoneid != GLOBAL_ZONEID) { 1835*7c478bd9Sstevel@tonic-gate if (Psetzoneid(Pr, oldzoneid) != 0) 1836*7c478bd9Sstevel@tonic-gate relinquish_failed = B_TRUE; 1837*7c478bd9Sstevel@tonic-gate } 1838*7c478bd9Sstevel@tonic-gate if (old_prpriv != NULL) { 1839*7c478bd9Sstevel@tonic-gate if (Psetpriv(Pr, old_prpriv) != 0) 1840*7c478bd9Sstevel@tonic-gate relinquish_failed = B_TRUE; 1841*7c478bd9Sstevel@tonic-gate free(old_prpriv); 1842*7c478bd9Sstevel@tonic-gate } 1843*7c478bd9Sstevel@tonic-gate if (relinquish_failed) { 1844*7c478bd9Sstevel@tonic-gate /* 1845*7c478bd9Sstevel@tonic-gate * If this failed, we can't leave a process hanging 1846*7c478bd9Sstevel@tonic-gate * around with elevated privileges, so we'll have to 1847*7c478bd9Sstevel@tonic-gate * release the process from libproc, knowing that it 1848*7c478bd9Sstevel@tonic-gate * will be killed (since we set PR_KLC). 1849*7c478bd9Sstevel@tonic-gate */ 1850*7c478bd9Sstevel@tonic-gate Pdestroy_agent(Pr); 1851*7c478bd9Sstevel@tonic-gate preserve_error(gettext("cannot relinquish privileges " 1852*7c478bd9Sstevel@tonic-gate "for pid %d. The process was killed."), 1853*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid); 1854*7c478bd9Sstevel@tonic-gate } else { 1855*7c478bd9Sstevel@tonic-gate if (Punsetflags(Pr, PR_KLC) != 0) 1856*7c478bd9Sstevel@tonic-gate preserve_error(gettext("cannot relinquish privileges " 1857*7c478bd9Sstevel@tonic-gate "for pid %d. The process was killed."), 1858*7c478bd9Sstevel@tonic-gate Pstatus(Pr)->pr_pid); 1859*7c478bd9Sstevel@tonic-gate } 1860*7c478bd9Sstevel@tonic-gate if (new_prpriv != NULL) 1861*7c478bd9Sstevel@tonic-gate free(new_prpriv); 1862*7c478bd9Sstevel@tonic-gate 1863*7c478bd9Sstevel@tonic-gate return (ret); 1864*7c478bd9Sstevel@tonic-gate } 1865*7c478bd9Sstevel@tonic-gate 1866*7c478bd9Sstevel@tonic-gate void 1867*7c478bd9Sstevel@tonic-gate print_priv(rctl_priv_t local_priv, char *format) 1868*7c478bd9Sstevel@tonic-gate { 1869*7c478bd9Sstevel@tonic-gate char pstring[11]; 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate switch (local_priv) { 1872*7c478bd9Sstevel@tonic-gate case RCPRIV_BASIC: 1873*7c478bd9Sstevel@tonic-gate (void) strcpy(pstring, "basic"); 1874*7c478bd9Sstevel@tonic-gate break; 1875*7c478bd9Sstevel@tonic-gate case RCPRIV_PRIVILEGED: 1876*7c478bd9Sstevel@tonic-gate (void) strcpy(pstring, "privileged"); 1877*7c478bd9Sstevel@tonic-gate break; 1878*7c478bd9Sstevel@tonic-gate case RCPRIV_SYSTEM: 1879*7c478bd9Sstevel@tonic-gate (void) strcpy(pstring, "system"); 1880*7c478bd9Sstevel@tonic-gate break; 1881*7c478bd9Sstevel@tonic-gate default: 1882*7c478bd9Sstevel@tonic-gate (void) sprintf(pstring, "%d", local_priv); 1883*7c478bd9Sstevel@tonic-gate break; 1884*7c478bd9Sstevel@tonic-gate } 1885*7c478bd9Sstevel@tonic-gate /* LINTED */ 1886*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, format, pstring); 1887*7c478bd9Sstevel@tonic-gate } 1888*7c478bd9Sstevel@tonic-gate 1889*7c478bd9Sstevel@tonic-gate void 1890*7c478bd9Sstevel@tonic-gate print_local_action(int action, int *signalp, char *format) 1891*7c478bd9Sstevel@tonic-gate { 1892*7c478bd9Sstevel@tonic-gate char sig[SIG2STR_MAX]; 1893*7c478bd9Sstevel@tonic-gate char sigstring[SIG2STR_MAX + 7]; 1894*7c478bd9Sstevel@tonic-gate char astring[5 + SIG2STR_MAX + 7]; 1895*7c478bd9Sstevel@tonic-gate int set = 0; 1896*7c478bd9Sstevel@tonic-gate 1897*7c478bd9Sstevel@tonic-gate astring[0] = '\0'; 1898*7c478bd9Sstevel@tonic-gate 1899*7c478bd9Sstevel@tonic-gate if (action == RCTL_LOCAL_NOACTION) { 1900*7c478bd9Sstevel@tonic-gate (void) strcat(astring, "none"); 1901*7c478bd9Sstevel@tonic-gate set++; 1902*7c478bd9Sstevel@tonic-gate } 1903*7c478bd9Sstevel@tonic-gate if (action & RCTL_LOCAL_DENY) { 1904*7c478bd9Sstevel@tonic-gate (void) strcat(astring, "deny"); 1905*7c478bd9Sstevel@tonic-gate set++; 1906*7c478bd9Sstevel@tonic-gate } 1907*7c478bd9Sstevel@tonic-gate if ((action & RCTL_LOCAL_DENY) && 1908*7c478bd9Sstevel@tonic-gate (action & RCTL_LOCAL_SIGNAL)) { 1909*7c478bd9Sstevel@tonic-gate (void) strcat(astring, ","); 1910*7c478bd9Sstevel@tonic-gate } 1911*7c478bd9Sstevel@tonic-gate if (action & RCTL_LOCAL_SIGNAL) { 1912*7c478bd9Sstevel@tonic-gate if (sig2str(*signalp, sig)) 1913*7c478bd9Sstevel@tonic-gate (void) snprintf(sigstring, sizeof (astring), 1914*7c478bd9Sstevel@tonic-gate "signal=%d", *signalp); 1915*7c478bd9Sstevel@tonic-gate else 1916*7c478bd9Sstevel@tonic-gate (void) snprintf(sigstring, sizeof (astring), 1917*7c478bd9Sstevel@tonic-gate "signal=%s", sig); 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate (void) strcat(astring, sigstring); 1920*7c478bd9Sstevel@tonic-gate set++; 1921*7c478bd9Sstevel@tonic-gate } 1922*7c478bd9Sstevel@tonic-gate if (set) 1923*7c478bd9Sstevel@tonic-gate /* LINTED */ 1924*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, format, astring); 1925*7c478bd9Sstevel@tonic-gate else 1926*7c478bd9Sstevel@tonic-gate /* LINTED */ 1927*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, format, action); 1928*7c478bd9Sstevel@tonic-gate } 1929*7c478bd9Sstevel@tonic-gate 1930*7c478bd9Sstevel@tonic-gate /* 1931*7c478bd9Sstevel@tonic-gate * This function is used to grab the process matching the recipient pid 1932*7c478bd9Sstevel@tonic-gate */ 1933*7c478bd9Sstevel@tonic-gate pid_t 1934*7c478bd9Sstevel@tonic-gate regrab_process(pid_t pid, pr_info_handle_t *p, int priv, int *gret) 1935*7c478bd9Sstevel@tonic-gate { 1936*7c478bd9Sstevel@tonic-gate 1937*7c478bd9Sstevel@tonic-gate char pidstring[24]; 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate gret = 0; 1940*7c478bd9Sstevel@tonic-gate if (pid == -1) 1941*7c478bd9Sstevel@tonic-gate return (p->pid); 1942*7c478bd9Sstevel@tonic-gate if (p->pid == pid) 1943*7c478bd9Sstevel@tonic-gate return (p->pid); 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate release_process(p->pr); 1946*7c478bd9Sstevel@tonic-gate (void) memset(p, 0, sizeof (*p)); 1947*7c478bd9Sstevel@tonic-gate 1948*7c478bd9Sstevel@tonic-gate (void) snprintf(pidstring, 24, "%d", pid); 1949*7c478bd9Sstevel@tonic-gate return (grab_process_by_id( 1950*7c478bd9Sstevel@tonic-gate pidstring, RCENTITY_PROCESS, p, priv, gret)); 1951*7c478bd9Sstevel@tonic-gate } 1952*7c478bd9Sstevel@tonic-gate 1953*7c478bd9Sstevel@tonic-gate /* 1954*7c478bd9Sstevel@tonic-gate * int grab_process_by_id(char *, rctl_entity_t, pr_info_handle_t *, int, int *) 1955*7c478bd9Sstevel@tonic-gate * 1956*7c478bd9Sstevel@tonic-gate * Input 1957*7c478bd9Sstevel@tonic-gate * Supply a non-NULL string containing: 1958*7c478bd9Sstevel@tonic-gate * - logical project/zone name or project/zone number if type is 1959*7c478bd9Sstevel@tonic-gate * RCENTITY_PROJECT or RCENTITY_ZONE 1960*7c478bd9Sstevel@tonic-gate * - task number if type is RCENTITY_TYPE 1961*7c478bd9Sstevel@tonic-gate * - a pid if type is RCENTITY_PID 1962*7c478bd9Sstevel@tonic-gate * Also supply an un-allocated prochandle, and an allocated info_handle. 1963*7c478bd9Sstevel@tonic-gate * This function assumes that the type is set. 1964*7c478bd9Sstevel@tonic-gate * If priv is not RCPRIV_BASIC, the grabbed process is required to have 1965*7c478bd9Sstevel@tonic-gate * PRIV_SYS_RESOURCE in it's limit set. 1966*7c478bd9Sstevel@tonic-gate * 1967*7c478bd9Sstevel@tonic-gate * Return Values 1968*7c478bd9Sstevel@tonic-gate * Returns 0 on success and 1 on failure. If there is a process 1969*7c478bd9Sstevel@tonic-gate * running under the specified id, success is returned, and 1970*7c478bd9Sstevel@tonic-gate * Pr is pointed to the process. Success will be returned and Pr 1971*7c478bd9Sstevel@tonic-gate * set to NULL if the matching process is our own. 1972*7c478bd9Sstevel@tonic-gate * If success is returned, psinfo will be valid, and pid will 1973*7c478bd9Sstevel@tonic-gate * be the process number. The process will also be held at the 1974*7c478bd9Sstevel@tonic-gate * end, so release_process should be used by the caller. 1975*7c478bd9Sstevel@tonic-gate * 1976*7c478bd9Sstevel@tonic-gate * This function assumes that signals are caught already so that libproc 1977*7c478bd9Sstevel@tonic-gate * can be safely used. 1978*7c478bd9Sstevel@tonic-gate * 1979*7c478bd9Sstevel@tonic-gate * Return Values 1980*7c478bd9Sstevel@tonic-gate * pid - Process found and grabbed 1981*7c478bd9Sstevel@tonic-gate * -1 - Error 1982*7c478bd9Sstevel@tonic-gate */ 1983*7c478bd9Sstevel@tonic-gate pid_t 1984*7c478bd9Sstevel@tonic-gate grab_process_by_id(char *idname, rctl_entity_t type, pr_info_handle_t *p, 1985*7c478bd9Sstevel@tonic-gate int priv, int *gret) 1986*7c478bd9Sstevel@tonic-gate { 1987*7c478bd9Sstevel@tonic-gate char prbuf[PROJECT_BUFSZ]; 1988*7c478bd9Sstevel@tonic-gate projid_t projid; 1989*7c478bd9Sstevel@tonic-gate taskid_t taskid; 1990*7c478bd9Sstevel@tonic-gate zoneid_t zoneid; 1991*7c478bd9Sstevel@tonic-gate zoneid_t zone_self; 1992*7c478bd9Sstevel@tonic-gate struct project proj; 1993*7c478bd9Sstevel@tonic-gate DIR *dirp; 1994*7c478bd9Sstevel@tonic-gate struct dirent *dentp; 1995*7c478bd9Sstevel@tonic-gate int found = 0; 1996*7c478bd9Sstevel@tonic-gate int pid_self; 1997*7c478bd9Sstevel@tonic-gate int ret; 1998*7c478bd9Sstevel@tonic-gate int gret_in; 1999*7c478bd9Sstevel@tonic-gate int intidname; 2000*7c478bd9Sstevel@tonic-gate char *end; 2001*7c478bd9Sstevel@tonic-gate prpriv_t *prpriv; 2002*7c478bd9Sstevel@tonic-gate priv_set_t *prset; 2003*7c478bd9Sstevel@tonic-gate 2004*7c478bd9Sstevel@tonic-gate gret_in = *gret; 2005*7c478bd9Sstevel@tonic-gate 2006*7c478bd9Sstevel@tonic-gate /* get our pid se we do not try to operate on self */ 2007*7c478bd9Sstevel@tonic-gate pid_self = getpid(); 2008*7c478bd9Sstevel@tonic-gate 2009*7c478bd9Sstevel@tonic-gate /* Store integer version of id */ 2010*7c478bd9Sstevel@tonic-gate intidname = strtoul(idname, &end, 10); 2011*7c478bd9Sstevel@tonic-gate if (errno || *end != '\0' || end == idname) { 2012*7c478bd9Sstevel@tonic-gate intidname = -1; 2013*7c478bd9Sstevel@tonic-gate } 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate /* 2016*7c478bd9Sstevel@tonic-gate * get our zoneid so we don't try to operate on a project in 2017*7c478bd9Sstevel@tonic-gate * another zone 2018*7c478bd9Sstevel@tonic-gate */ 2019*7c478bd9Sstevel@tonic-gate zone_self = getzoneid(); 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate if (idname == NULL || strcmp(idname, "") == 0) { 2022*7c478bd9Sstevel@tonic-gate warn(gettext("id name cannot be nuint64\n")); 2023*7c478bd9Sstevel@tonic-gate return (-1); 2024*7c478bd9Sstevel@tonic-gate } 2025*7c478bd9Sstevel@tonic-gate /* 2026*7c478bd9Sstevel@tonic-gate * Set up zoneid, projid or taskid, as appropriate, so that comparisons 2027*7c478bd9Sstevel@tonic-gate * can be done later with the input. 2028*7c478bd9Sstevel@tonic-gate */ 2029*7c478bd9Sstevel@tonic-gate if (type == RCENTITY_ZONE) { 2030*7c478bd9Sstevel@tonic-gate if (zone_get_id(idname, &zoneid) != 0) { 2031*7c478bd9Sstevel@tonic-gate warn(gettext("%s: unknown zone\n"), idname); 2032*7c478bd9Sstevel@tonic-gate return (-1); 2033*7c478bd9Sstevel@tonic-gate } 2034*7c478bd9Sstevel@tonic-gate } else if (type == RCENTITY_PROJECT) { 2035*7c478bd9Sstevel@tonic-gate if (getprojbyname(idname, &proj, prbuf, PROJECT_BUFSZ) 2036*7c478bd9Sstevel@tonic-gate == NULL) { 2037*7c478bd9Sstevel@tonic-gate if (getprojbyid(intidname, &proj, prbuf, 2038*7c478bd9Sstevel@tonic-gate PROJECT_BUFSZ) == NULL) { 2039*7c478bd9Sstevel@tonic-gate warn(gettext("%s: cannot find project\n"), 2040*7c478bd9Sstevel@tonic-gate idname); 2041*7c478bd9Sstevel@tonic-gate return (-1); 2042*7c478bd9Sstevel@tonic-gate } 2043*7c478bd9Sstevel@tonic-gate } 2044*7c478bd9Sstevel@tonic-gate projid = proj.pj_projid; 2045*7c478bd9Sstevel@tonic-gate } else if (type == RCENTITY_TASK) { 2046*7c478bd9Sstevel@tonic-gate taskid = (taskid_t)atol(idname); 2047*7c478bd9Sstevel@tonic-gate } 2048*7c478bd9Sstevel@tonic-gate /* 2049*7c478bd9Sstevel@tonic-gate * Projects and tasks need to search through /proc for 2050*7c478bd9Sstevel@tonic-gate * a parent process. 2051*7c478bd9Sstevel@tonic-gate */ 2052*7c478bd9Sstevel@tonic-gate if (type == RCENTITY_ZONE || type == RCENTITY_PROJECT || 2053*7c478bd9Sstevel@tonic-gate type == RCENTITY_TASK) { 2054*7c478bd9Sstevel@tonic-gate if ((dirp = opendir("/proc")) == NULL) { 2055*7c478bd9Sstevel@tonic-gate warn(gettext("%s: cannot open /proc directory\n"), 2056*7c478bd9Sstevel@tonic-gate idname); 2057*7c478bd9Sstevel@tonic-gate return (-1); 2058*7c478bd9Sstevel@tonic-gate } 2059*7c478bd9Sstevel@tonic-gate /* 2060*7c478bd9Sstevel@tonic-gate * Look through all processes in /proc. For each process, 2061*7c478bd9Sstevel@tonic-gate * check if the pr_projid in their psinfo matches the 2062*7c478bd9Sstevel@tonic-gate * specified id. 2063*7c478bd9Sstevel@tonic-gate */ 2064*7c478bd9Sstevel@tonic-gate while (dentp = readdir(dirp)) { 2065*7c478bd9Sstevel@tonic-gate p->pid = atoi(dentp->d_name); 2066*7c478bd9Sstevel@tonic-gate 2067*7c478bd9Sstevel@tonic-gate /* Skip self */ 2068*7c478bd9Sstevel@tonic-gate if (p->pid == pid_self) 2069*7c478bd9Sstevel@tonic-gate continue; 2070*7c478bd9Sstevel@tonic-gate 2071*7c478bd9Sstevel@tonic-gate if (proc_get_psinfo(p->pid, &(p->psinfo)) != 0) 2072*7c478bd9Sstevel@tonic-gate continue; 2073*7c478bd9Sstevel@tonic-gate 2074*7c478bd9Sstevel@tonic-gate /* Skip process if it is not what we are looking for */ 2075*7c478bd9Sstevel@tonic-gate if (type == RCENTITY_ZONE && 2076*7c478bd9Sstevel@tonic-gate (p->psinfo).pr_zoneid != zoneid) { 2077*7c478bd9Sstevel@tonic-gate continue; 2078*7c478bd9Sstevel@tonic-gate } if (type == RCENTITY_PROJECT && 2079*7c478bd9Sstevel@tonic-gate ((p->psinfo).pr_projid != projid || 2080*7c478bd9Sstevel@tonic-gate (p->psinfo).pr_zoneid != zone_self)) { 2081*7c478bd9Sstevel@tonic-gate continue; 2082*7c478bd9Sstevel@tonic-gate } else if (type == RCENTITY_TASK && 2083*7c478bd9Sstevel@tonic-gate (p->psinfo).pr_taskid != taskid) { 2084*7c478bd9Sstevel@tonic-gate continue; 2085*7c478bd9Sstevel@tonic-gate } 2086*7c478bd9Sstevel@tonic-gate /* attempt to grab process */ 2087*7c478bd9Sstevel@tonic-gate if (grab_process(p, gret) != 0) 2088*7c478bd9Sstevel@tonic-gate continue; 2089*7c478bd9Sstevel@tonic-gate 2090*7c478bd9Sstevel@tonic-gate /* 2091*7c478bd9Sstevel@tonic-gate * Re-confirm that this process is still running as 2092*7c478bd9Sstevel@tonic-gate * part of the specified project or task. If it 2093*7c478bd9Sstevel@tonic-gate * doesn't match, release the process and return an 2094*7c478bd9Sstevel@tonic-gate * error. This should only be done if the Pr struct is 2095*7c478bd9Sstevel@tonic-gate * not NULL. 2096*7c478bd9Sstevel@tonic-gate */ 2097*7c478bd9Sstevel@tonic-gate if (type == RCENTITY_PROJECT) { 2098*7c478bd9Sstevel@tonic-gate if (pr_getprojid(p->pr) != projid || 2099*7c478bd9Sstevel@tonic-gate pr_getzoneid(p->pr) != zone_self) { 2100*7c478bd9Sstevel@tonic-gate release_process(p->pr); 2101*7c478bd9Sstevel@tonic-gate continue; 2102*7c478bd9Sstevel@tonic-gate } 2103*7c478bd9Sstevel@tonic-gate } else if (type == RCENTITY_TASK) { 2104*7c478bd9Sstevel@tonic-gate if (pr_gettaskid(p->pr) != taskid) { 2105*7c478bd9Sstevel@tonic-gate release_process(p->pr); 2106*7c478bd9Sstevel@tonic-gate continue; 2107*7c478bd9Sstevel@tonic-gate } 2108*7c478bd9Sstevel@tonic-gate } else if (type == RCENTITY_ZONE) { 2109*7c478bd9Sstevel@tonic-gate if (pr_getzoneid(p->pr) != zoneid) { 2110*7c478bd9Sstevel@tonic-gate release_process(p->pr); 2111*7c478bd9Sstevel@tonic-gate continue; 2112*7c478bd9Sstevel@tonic-gate } 2113*7c478bd9Sstevel@tonic-gate } 2114*7c478bd9Sstevel@tonic-gate 2115*7c478bd9Sstevel@tonic-gate /* 2116*7c478bd9Sstevel@tonic-gate * If we are setting a privileged resource control, 2117*7c478bd9Sstevel@tonic-gate * verify that process has PRIV_SYS_RESOURCE in it's 2118*7c478bd9Sstevel@tonic-gate * limit set. If it does not, then we will not be 2119*7c478bd9Sstevel@tonic-gate * able to give this process the privilege it needs 2120*7c478bd9Sstevel@tonic-gate * to set the resource control. 2121*7c478bd9Sstevel@tonic-gate */ 2122*7c478bd9Sstevel@tonic-gate if (priv != RCPRIV_BASIC) { 2123*7c478bd9Sstevel@tonic-gate prpriv = proc_get_priv(p->pid); 2124*7c478bd9Sstevel@tonic-gate if (prpriv == NULL) { 2125*7c478bd9Sstevel@tonic-gate release_process(p->pr); 2126*7c478bd9Sstevel@tonic-gate continue; 2127*7c478bd9Sstevel@tonic-gate } 2128*7c478bd9Sstevel@tonic-gate prset = (priv_set_t *) 2129*7c478bd9Sstevel@tonic-gate &prpriv->pr_sets[prpriv->pr_setsize * 2130*7c478bd9Sstevel@tonic-gate priv_getsetbyname(PRIV_LIMIT)]; 2131*7c478bd9Sstevel@tonic-gate if (!priv_ismember(prset, PRIV_SYS_RESOURCE)) { 2132*7c478bd9Sstevel@tonic-gate release_process(p->pr); 2133*7c478bd9Sstevel@tonic-gate continue; 2134*7c478bd9Sstevel@tonic-gate } 2135*7c478bd9Sstevel@tonic-gate } 2136*7c478bd9Sstevel@tonic-gate found = 1; 2137*7c478bd9Sstevel@tonic-gate 2138*7c478bd9Sstevel@tonic-gate p->taskid = pr_gettaskid(p->pr); 2139*7c478bd9Sstevel@tonic-gate p->projid = pr_getprojid(p->pr); 2140*7c478bd9Sstevel@tonic-gate p->zoneid = pr_getzoneid(p->pr); 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate break; 2143*7c478bd9Sstevel@tonic-gate } 2144*7c478bd9Sstevel@tonic-gate (void) closedir(dirp); 2145*7c478bd9Sstevel@tonic-gate 2146*7c478bd9Sstevel@tonic-gate if (found == 0) { 2147*7c478bd9Sstevel@tonic-gate warn(gettext("%s: No controllable process found in " 2148*7c478bd9Sstevel@tonic-gate "task, project, or zone.\n"), idname); 2149*7c478bd9Sstevel@tonic-gate return (-1); 2150*7c478bd9Sstevel@tonic-gate } 2151*7c478bd9Sstevel@tonic-gate return (p->pid); 2152*7c478bd9Sstevel@tonic-gate 2153*7c478bd9Sstevel@tonic-gate } else if (type == RCENTITY_PROCESS) { 2154*7c478bd9Sstevel@tonic-gate 2155*7c478bd9Sstevel@tonic-gate /* fail if self */ 2156*7c478bd9Sstevel@tonic-gate if (p->pid == pid_self) { 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate warn(gettext("%s: cannot control self"), idname); 2159*7c478bd9Sstevel@tonic-gate return (-1); 2160*7c478bd9Sstevel@tonic-gate } 2161*7c478bd9Sstevel@tonic-gate /* 2162*7c478bd9Sstevel@tonic-gate * Process types need to be set up with the correct pid 2163*7c478bd9Sstevel@tonic-gate * and psinfo structure. 2164*7c478bd9Sstevel@tonic-gate */ 2165*7c478bd9Sstevel@tonic-gate if ((p->pid = proc_arg_psinfo(idname, PR_ARG_PIDS, 2166*7c478bd9Sstevel@tonic-gate &(p->psinfo), gret)) == -1) { 2167*7c478bd9Sstevel@tonic-gate warn(gettext("%s: cannot examine: %s"), idname, 2168*7c478bd9Sstevel@tonic-gate Pgrab_error(*gret)); 2169*7c478bd9Sstevel@tonic-gate return (-1); 2170*7c478bd9Sstevel@tonic-gate } 2171*7c478bd9Sstevel@tonic-gate /* grab process */ 2172*7c478bd9Sstevel@tonic-gate ret = grab_process(p, gret); 2173*7c478bd9Sstevel@tonic-gate if (ret == 1) { 2174*7c478bd9Sstevel@tonic-gate /* Don't print error if G_SYS is allowed */ 2175*7c478bd9Sstevel@tonic-gate if (gret_in == G_SYS && *gret == G_SYS) { 2176*7c478bd9Sstevel@tonic-gate return (-1); 2177*7c478bd9Sstevel@tonic-gate } else { 2178*7c478bd9Sstevel@tonic-gate warn(gettext("%s: cannot control: %s"), idname, 2179*7c478bd9Sstevel@tonic-gate Pgrab_error(*gret)); 2180*7c478bd9Sstevel@tonic-gate return (-1); 2181*7c478bd9Sstevel@tonic-gate } 2182*7c478bd9Sstevel@tonic-gate } else if (ret == 2) { 2183*7c478bd9Sstevel@tonic-gate ret = errno; 2184*7c478bd9Sstevel@tonic-gate warn(gettext("%s: cannot control: %s"), idname, 2185*7c478bd9Sstevel@tonic-gate strerror(ret)); 2186*7c478bd9Sstevel@tonic-gate return (-1); 2187*7c478bd9Sstevel@tonic-gate } 2188*7c478bd9Sstevel@tonic-gate p->taskid = pr_gettaskid(p->pr); 2189*7c478bd9Sstevel@tonic-gate p->projid = pr_getprojid(p->pr); 2190*7c478bd9Sstevel@tonic-gate p->zoneid = pr_getzoneid(p->pr); 2191*7c478bd9Sstevel@tonic-gate 2192*7c478bd9Sstevel@tonic-gate return (p->pid); 2193*7c478bd9Sstevel@tonic-gate 2194*7c478bd9Sstevel@tonic-gate } else { 2195*7c478bd9Sstevel@tonic-gate warn(gettext("%s: unknown resource entity type %d\n"), idname, 2196*7c478bd9Sstevel@tonic-gate type); 2197*7c478bd9Sstevel@tonic-gate return (-1); 2198*7c478bd9Sstevel@tonic-gate } 2199*7c478bd9Sstevel@tonic-gate } 2200*7c478bd9Sstevel@tonic-gate 2201*7c478bd9Sstevel@tonic-gate /* 2202*7c478bd9Sstevel@tonic-gate * Do the work required to manipulate a process through libproc. 2203*7c478bd9Sstevel@tonic-gate * If grab_process() returns no errors (0), then release_process() 2204*7c478bd9Sstevel@tonic-gate * must eventually be called. 2205*7c478bd9Sstevel@tonic-gate * 2206*7c478bd9Sstevel@tonic-gate * Return values: 2207*7c478bd9Sstevel@tonic-gate * 0 Successful creation of agent thread 2208*7c478bd9Sstevel@tonic-gate * 1 Error grabbing 2209*7c478bd9Sstevel@tonic-gate * 2 Error creating agent 2210*7c478bd9Sstevel@tonic-gate */ 2211*7c478bd9Sstevel@tonic-gate int 2212*7c478bd9Sstevel@tonic-gate grab_process(pr_info_handle_t *p, int *gret) 2213*7c478bd9Sstevel@tonic-gate { 2214*7c478bd9Sstevel@tonic-gate 2215*7c478bd9Sstevel@tonic-gate if ((p->pr = Pgrab(p->pid, arg_force, gret)) != NULL) { 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate if (Psetflags(p->pr, PR_RLC) != 0) { 2218*7c478bd9Sstevel@tonic-gate Prelease(p->pr, 0); 2219*7c478bd9Sstevel@tonic-gate return (1); 2220*7c478bd9Sstevel@tonic-gate } 2221*7c478bd9Sstevel@tonic-gate if (Pcreate_agent(p->pr) == 0) { 2222*7c478bd9Sstevel@tonic-gate return (0); 2223*7c478bd9Sstevel@tonic-gate 2224*7c478bd9Sstevel@tonic-gate } else { 2225*7c478bd9Sstevel@tonic-gate Prelease(p->pr, 0); 2226*7c478bd9Sstevel@tonic-gate return (2); 2227*7c478bd9Sstevel@tonic-gate } 2228*7c478bd9Sstevel@tonic-gate } else { 2229*7c478bd9Sstevel@tonic-gate return (1); 2230*7c478bd9Sstevel@tonic-gate } 2231*7c478bd9Sstevel@tonic-gate } 2232*7c478bd9Sstevel@tonic-gate 2233*7c478bd9Sstevel@tonic-gate /* 2234*7c478bd9Sstevel@tonic-gate * Release the specified process. This destroys the agent 2235*7c478bd9Sstevel@tonic-gate * and releases the process. If the process is NULL, nothing 2236*7c478bd9Sstevel@tonic-gate * is done. This function should only be called if grab_process() 2237*7c478bd9Sstevel@tonic-gate * has previously been called and returned success. 2238*7c478bd9Sstevel@tonic-gate * 2239*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 2240*7c478bd9Sstevel@tonic-gate */ 2241*7c478bd9Sstevel@tonic-gate void 2242*7c478bd9Sstevel@tonic-gate release_process(struct ps_prochandle *Pr) 2243*7c478bd9Sstevel@tonic-gate { 2244*7c478bd9Sstevel@tonic-gate if (Pr == NULL) 2245*7c478bd9Sstevel@tonic-gate return; 2246*7c478bd9Sstevel@tonic-gate 2247*7c478bd9Sstevel@tonic-gate Pdestroy_agent(Pr); 2248*7c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 2249*7c478bd9Sstevel@tonic-gate } 2250*7c478bd9Sstevel@tonic-gate 2251*7c478bd9Sstevel@tonic-gate /* 2252*7c478bd9Sstevel@tonic-gate * preserve_error(char *, ...) 2253*7c478bd9Sstevel@tonic-gate * 2254*7c478bd9Sstevel@tonic-gate * preserve_error() should be called rather than warn() by any 2255*7c478bd9Sstevel@tonic-gate * function that is called while the victim process is held by Pgrab. 2256*7c478bd9Sstevel@tonic-gate * It will save the error until the process has been un-controlled 2257*7c478bd9Sstevel@tonic-gate * and output is reasonable again. 2258*7c478bd9Sstevel@tonic-gate * 2259*7c478bd9Sstevel@tonic-gate * Note that multiple errors are not stored. Any error in these 2260*7c478bd9Sstevel@tonic-gate * sections should be critical and return immediately. 2261*7c478bd9Sstevel@tonic-gate * 2262*7c478bd9Sstevel@tonic-gate * This function is Pgrab-safe. 2263*7c478bd9Sstevel@tonic-gate * 2264*7c478bd9Sstevel@tonic-gate * Since this function may copy untrusted command line arguments to 2265*7c478bd9Sstevel@tonic-gate * global_error, security practices require that global_error never be 2266*7c478bd9Sstevel@tonic-gate * printed directly. Use printf("%s\n", global_error) or equivalent. 2267*7c478bd9Sstevel@tonic-gate */ 2268*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 2269*7c478bd9Sstevel@tonic-gate void 2270*7c478bd9Sstevel@tonic-gate preserve_error(char *format, ...) 2271*7c478bd9Sstevel@tonic-gate { 2272*7c478bd9Sstevel@tonic-gate va_list alist; 2273*7c478bd9Sstevel@tonic-gate 2274*7c478bd9Sstevel@tonic-gate va_start(alist, format); 2275*7c478bd9Sstevel@tonic-gate 2276*7c478bd9Sstevel@tonic-gate /* 2277*7c478bd9Sstevel@tonic-gate * GLOBAL_ERR_SZ is pretty big. If the error is longer 2278*7c478bd9Sstevel@tonic-gate * than that, just truncate it, rather than chance missing 2279*7c478bd9Sstevel@tonic-gate * the error altogether. 2280*7c478bd9Sstevel@tonic-gate */ 2281*7c478bd9Sstevel@tonic-gate (void) vsnprintf(global_error, GLOBAL_ERR_SZ-1, format, alist); 2282*7c478bd9Sstevel@tonic-gate 2283*7c478bd9Sstevel@tonic-gate va_end(alist); 2284*7c478bd9Sstevel@tonic-gate } 2285