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 2004 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 /* 30*7c478bd9Sstevel@tonic-gate * rcm scripting module: 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * This module implements rcm scripting interfaces. 33*7c478bd9Sstevel@tonic-gate * It translates rcm module based interfaces to rcm script based 34*7c478bd9Sstevel@tonic-gate * interfaces. 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Entry points: 37*7c478bd9Sstevel@tonic-gate * 38*7c478bd9Sstevel@tonic-gate * int script_main_init() 39*7c478bd9Sstevel@tonic-gate * Initialize the rcm scripting framework. 40*7c478bd9Sstevel@tonic-gate * Called during the rcm daemon initialization 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * int script_main_fini() 43*7c478bd9Sstevel@tonic-gate * Called at the time of the rcm daemon exit. 44*7c478bd9Sstevel@tonic-gate * 45*7c478bd9Sstevel@tonic-gate * struct rcm_mod_ops *script_init(module_t *module) 46*7c478bd9Sstevel@tonic-gate * Initialize the given script. 47*7c478bd9Sstevel@tonic-gate * module->name contains the name of the script. 48*7c478bd9Sstevel@tonic-gate * Called at the time of loading scripts. 49*7c478bd9Sstevel@tonic-gate * Semantics are similar to module init. 50*7c478bd9Sstevel@tonic-gate * 51*7c478bd9Sstevel@tonic-gate * char *script_info(module_t *module) 52*7c478bd9Sstevel@tonic-gate * Called when the rcm daemon wishes to get the script information. 53*7c478bd9Sstevel@tonic-gate * module->name contains the name of the script. 54*7c478bd9Sstevel@tonic-gate * Semantics are similar to module info. 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * int script_fini(module_t *module) 57*7c478bd9Sstevel@tonic-gate * Called before removing the script. 58*7c478bd9Sstevel@tonic-gate * module->name contains the name of the script. 59*7c478bd9Sstevel@tonic-gate * Semantics are similar to module fini. 60*7c478bd9Sstevel@tonic-gate * 61*7c478bd9Sstevel@tonic-gate * In addition to the above entry points rcm_mod_ops structure contains 62*7c478bd9Sstevel@tonic-gate * the other entry points. A pointer to this structure is returned when 63*7c478bd9Sstevel@tonic-gate * script_init() is called. 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #include "rcm_impl.h" 67*7c478bd9Sstevel@tonic-gate #include "rcm_script_impl.h" 68*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 69*7c478bd9Sstevel@tonic-gate #include <procfs.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 71*7c478bd9Sstevel@tonic-gate #include <ctype.h> 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * All rcm scripting commands are enumerated here. 75*7c478bd9Sstevel@tonic-gate * NOTE: command positions in script_cmd_id_t and script_cmd_name must match. 76*7c478bd9Sstevel@tonic-gate */ 77*7c478bd9Sstevel@tonic-gate typedef enum { 78*7c478bd9Sstevel@tonic-gate C_SCRIPTINFO, 79*7c478bd9Sstevel@tonic-gate C_RESOURCEINFO, 80*7c478bd9Sstevel@tonic-gate C_REGISTER, 81*7c478bd9Sstevel@tonic-gate C_QUERYREMOVE, 82*7c478bd9Sstevel@tonic-gate C_PREREMOVE, 83*7c478bd9Sstevel@tonic-gate C_POSTREMOVE, 84*7c478bd9Sstevel@tonic-gate C_UNDOREMOVE, 85*7c478bd9Sstevel@tonic-gate C_QUERYCAPACITY, 86*7c478bd9Sstevel@tonic-gate C_PRECAPACITY, 87*7c478bd9Sstevel@tonic-gate C_POSTCAPACITY, 88*7c478bd9Sstevel@tonic-gate C_QUERYSUSPEND, 89*7c478bd9Sstevel@tonic-gate C_PRESUSPEND, 90*7c478bd9Sstevel@tonic-gate C_POSTRESUME, 91*7c478bd9Sstevel@tonic-gate C_CANCELSUSPEND 92*7c478bd9Sstevel@tonic-gate } script_cmd_id_t; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* NOTE: command positions in script_cmd_id_t and script_cmd_name must match */ 95*7c478bd9Sstevel@tonic-gate static char *script_cmd_name[] = { 96*7c478bd9Sstevel@tonic-gate "scriptinfo", 97*7c478bd9Sstevel@tonic-gate "resourceinfo", 98*7c478bd9Sstevel@tonic-gate "register", 99*7c478bd9Sstevel@tonic-gate "queryremove", 100*7c478bd9Sstevel@tonic-gate "preremove", 101*7c478bd9Sstevel@tonic-gate "postremove", 102*7c478bd9Sstevel@tonic-gate "undoremove", 103*7c478bd9Sstevel@tonic-gate "querycapacity", 104*7c478bd9Sstevel@tonic-gate "precapacity", 105*7c478bd9Sstevel@tonic-gate "postcapacity", 106*7c478bd9Sstevel@tonic-gate "querysuspend", 107*7c478bd9Sstevel@tonic-gate "presuspend", 108*7c478bd9Sstevel@tonic-gate "postresume", 109*7c478bd9Sstevel@tonic-gate "cancelsuspend", 110*7c478bd9Sstevel@tonic-gate NULL 111*7c478bd9Sstevel@tonic-gate }; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * All rcm scripting data items are enumerated here. 115*7c478bd9Sstevel@tonic-gate * NOTE: data item positions in script_data_item_id_t and 116*7c478bd9Sstevel@tonic-gate * script_data_item_name must match. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate typedef enum { 119*7c478bd9Sstevel@tonic-gate D_SCRIPT_VERSION, 120*7c478bd9Sstevel@tonic-gate D_SCRIPT_FUNC_INFO, 121*7c478bd9Sstevel@tonic-gate D_CMD_TIMEOUT, 122*7c478bd9Sstevel@tonic-gate D_RESOURCE_NAME, 123*7c478bd9Sstevel@tonic-gate D_RESOURCE_USAGE_INFO, 124*7c478bd9Sstevel@tonic-gate D_FAILURE_REASON, 125*7c478bd9Sstevel@tonic-gate D_LOG_ERR, 126*7c478bd9Sstevel@tonic-gate D_LOG_WARN, 127*7c478bd9Sstevel@tonic-gate D_LOG_INFO, 128*7c478bd9Sstevel@tonic-gate D_LOG_DEBUG 129*7c478bd9Sstevel@tonic-gate } script_data_item_id_t; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate /* 132*7c478bd9Sstevel@tonic-gate * NOTE: data item positions in script_data_item_id_t and 133*7c478bd9Sstevel@tonic-gate * script_data_item_name must match. 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate static const char *script_data_item_name[] = { 136*7c478bd9Sstevel@tonic-gate "rcm_script_version", 137*7c478bd9Sstevel@tonic-gate "rcm_script_func_info", 138*7c478bd9Sstevel@tonic-gate "rcm_cmd_timeout", 139*7c478bd9Sstevel@tonic-gate "rcm_resource_name", 140*7c478bd9Sstevel@tonic-gate "rcm_resource_usage_info", 141*7c478bd9Sstevel@tonic-gate "rcm_failure_reason", 142*7c478bd9Sstevel@tonic-gate "rcm_log_err", 143*7c478bd9Sstevel@tonic-gate "rcm_log_warn", 144*7c478bd9Sstevel@tonic-gate "rcm_log_info", 145*7c478bd9Sstevel@tonic-gate "rcm_log_debug", 146*7c478bd9Sstevel@tonic-gate NULL 147*7c478bd9Sstevel@tonic-gate }; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * Maximum number of rcm scripts that can run in parallel. 151*7c478bd9Sstevel@tonic-gate * RCM daemon has no limit on the number of scripts supported. But 152*7c478bd9Sstevel@tonic-gate * at most it runs script_max_parallelism number of scripts in parallel. 153*7c478bd9Sstevel@tonic-gate * For each running script rcm daemon consumes two file descriptors 154*7c478bd9Sstevel@tonic-gate * in order to communicate with the script via pipes. 155*7c478bd9Sstevel@tonic-gate * So maximum number of file descriptor entries consumed by rcm daemon 156*7c478bd9Sstevel@tonic-gate * on behalf of rcm scripts is "script_max_parallelism * 2" 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate static const int script_max_parallelism = 64; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* 161*7c478bd9Sstevel@tonic-gate * semaphore to limit the number of rcm script processes running in 162*7c478bd9Sstevel@tonic-gate * parallel to script_max_parallelism. 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate static sema_t script_process_sema; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* mutex to protect the any global data */ 167*7c478bd9Sstevel@tonic-gate static mutex_t script_lock; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* contains head to a queue of script_info structures */ 170*7c478bd9Sstevel@tonic-gate static rcm_queue_t script_info_q; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * This mmapped state file is used to store the process id and 174*7c478bd9Sstevel@tonic-gate * rcm script name of all currently running rcm scripts. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate static const char *script_ps_state_file = "/var/run/rcm_script_state"; 177*7c478bd9Sstevel@tonic-gate static state_file_descr_t script_ps_statefd; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate static char *script_env_noforce = "RCM_ENV_FORCE=FALSE"; 180*7c478bd9Sstevel@tonic-gate static char *script_env_force = "RCM_ENV_FORCE=TRUE"; 181*7c478bd9Sstevel@tonic-gate static char *script_env_interval = "RCM_ENV_INTERVAL=%ld"; 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate #define RSCR_TRACE RCM_TRACE1 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* rcm script base environment */ 186*7c478bd9Sstevel@tonic-gate static char *script_env[MAX_ENV_PARAMS]; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate struct rlimit file_limit; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate /* function prototypes */ 191*7c478bd9Sstevel@tonic-gate static void build_env(void); 192*7c478bd9Sstevel@tonic-gate static void copy_env(char *[], char *[]); 193*7c478bd9Sstevel@tonic-gate static void open_state_file(const char *, state_file_descr_t *, size_t, int, 194*7c478bd9Sstevel@tonic-gate uint32_t); 195*7c478bd9Sstevel@tonic-gate static void truncate_state_file(state_file_descr_t *); 196*7c478bd9Sstevel@tonic-gate static void close_state_file(const char *, state_file_descr_t *); 197*7c478bd9Sstevel@tonic-gate static void grow_state_file(state_file_descr_t *); 198*7c478bd9Sstevel@tonic-gate static void *get_state_element(state_file_descr_t *, int, int *); 199*7c478bd9Sstevel@tonic-gate static void *allocate_state_element(state_file_descr_t *, int *); 200*7c478bd9Sstevel@tonic-gate static void free_state_element(void *); 201*7c478bd9Sstevel@tonic-gate static void script_ps_state_file_kill_pids(void); 202*7c478bd9Sstevel@tonic-gate static void script_ps_state_file_add_entry(pid_t, char *); 203*7c478bd9Sstevel@tonic-gate static void script_ps_state_file_remove_entry(pid_t); 204*7c478bd9Sstevel@tonic-gate static int dname_to_id(char *); 205*7c478bd9Sstevel@tonic-gate static void script_process_sema_wait(void); 206*7c478bd9Sstevel@tonic-gate static int run_script(script_info_t *, char *[], char *[], char **); 207*7c478bd9Sstevel@tonic-gate static int get_line(int fd, char *, char *, int, size_t *, time_t, int *); 208*7c478bd9Sstevel@tonic-gate static void script_exited(script_info_t *); 209*7c478bd9Sstevel@tonic-gate static int kill_pid(pid_t); 210*7c478bd9Sstevel@tonic-gate static void kill_script(script_info_t *); 211*7c478bd9Sstevel@tonic-gate static char *flags_to_name(int, char *, int); 212*7c478bd9Sstevel@tonic-gate static void fill_argv(script_info_t *, char *[], char *); 213*7c478bd9Sstevel@tonic-gate static void *read_stderr(script_info_t *); 214*7c478bd9Sstevel@tonic-gate static int process_dataitem(script_info_t *, int, char *, char **); 215*7c478bd9Sstevel@tonic-gate static int do_cmd(script_info_t *, char *[], char *[], char **); 216*7c478bd9Sstevel@tonic-gate static int do_script_info(script_info_t *); 217*7c478bd9Sstevel@tonic-gate static int do_dr(script_info_t *, char *[], char *[], char **); 218*7c478bd9Sstevel@tonic-gate static int script_get_info(rcm_handle_t *, char *, pid_t, uint_t, char **, 219*7c478bd9Sstevel@tonic-gate char **, nvlist_t *, rcm_info_t **); 220*7c478bd9Sstevel@tonic-gate static void add_for_unregister(script_info_t *); 221*7c478bd9Sstevel@tonic-gate static void remove_from_unregister(script_info_t *, char *); 222*7c478bd9Sstevel@tonic-gate static void complete_unregister(script_info_t *); 223*7c478bd9Sstevel@tonic-gate static int script_register_interest(rcm_handle_t *); 224*7c478bd9Sstevel@tonic-gate static void add_drreq(script_info_t *, char *); 225*7c478bd9Sstevel@tonic-gate static void remove_drreq(script_info_t *, char *); 226*7c478bd9Sstevel@tonic-gate static void remove_drreq_all(script_info_t *); 227*7c478bd9Sstevel@tonic-gate static int script_request_offline(rcm_handle_t *, char *, pid_t, uint_t, 228*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 229*7c478bd9Sstevel@tonic-gate static int script_notify_online(rcm_handle_t *, char *, pid_t, uint_t, 230*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 231*7c478bd9Sstevel@tonic-gate static int script_notify_remove(rcm_handle_t *, char *, pid_t, uint_t, 232*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 233*7c478bd9Sstevel@tonic-gate static int script_request_suspend(rcm_handle_t *, char *, pid_t, timespec_t *, 234*7c478bd9Sstevel@tonic-gate uint_t, char **, rcm_info_t **); 235*7c478bd9Sstevel@tonic-gate static int script_notify_resume(rcm_handle_t *, char *, pid_t, uint_t, 236*7c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 237*7c478bd9Sstevel@tonic-gate static capacity_descr_t *get_capacity_descr(char *); 238*7c478bd9Sstevel@tonic-gate static int build_env_for_capacity(script_info_t *, char *, uint_t, nvlist_t *, 239*7c478bd9Sstevel@tonic-gate char *[], int *, char **); 240*7c478bd9Sstevel@tonic-gate static int script_request_capacity_change(rcm_handle_t *, char *, pid_t, 241*7c478bd9Sstevel@tonic-gate uint_t, nvlist_t *, char **, rcm_info_t **); 242*7c478bd9Sstevel@tonic-gate static int script_notify_capacity_change(rcm_handle_t *, char *, pid_t, 243*7c478bd9Sstevel@tonic-gate uint_t, nvlist_t *, char **, rcm_info_t **); 244*7c478bd9Sstevel@tonic-gate static void log_msg(script_info_t *, int, char *); 245*7c478bd9Sstevel@tonic-gate static char *dup_err(int, char *, ...); 246*7c478bd9Sstevel@tonic-gate static void rcmscript_snprintf(char **, int *, char **, char *, ...); 247*7c478bd9Sstevel@tonic-gate static char *rcmscript_strdup(char *); 248*7c478bd9Sstevel@tonic-gate static void *rcmscript_malloc(size_t); 249*7c478bd9Sstevel@tonic-gate static void *rcmscript_calloc(size_t, size_t); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate static struct rcm_mod_ops script_ops = 253*7c478bd9Sstevel@tonic-gate { 254*7c478bd9Sstevel@tonic-gate RCM_MOD_OPS_VERSION, 255*7c478bd9Sstevel@tonic-gate script_register_interest, /* register */ 256*7c478bd9Sstevel@tonic-gate script_register_interest, /* unregister */ 257*7c478bd9Sstevel@tonic-gate script_get_info, 258*7c478bd9Sstevel@tonic-gate script_request_suspend, 259*7c478bd9Sstevel@tonic-gate script_notify_resume, 260*7c478bd9Sstevel@tonic-gate script_request_offline, 261*7c478bd9Sstevel@tonic-gate script_notify_online, 262*7c478bd9Sstevel@tonic-gate script_notify_remove, 263*7c478bd9Sstevel@tonic-gate script_request_capacity_change, 264*7c478bd9Sstevel@tonic-gate script_notify_capacity_change, 265*7c478bd9Sstevel@tonic-gate NULL 266*7c478bd9Sstevel@tonic-gate }; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * Messages fall into two categories: 270*7c478bd9Sstevel@tonic-gate * framework messages (MF_..) 271*7c478bd9Sstevel@tonic-gate * errors directly attributable to scripts (MS_..) 272*7c478bd9Sstevel@tonic-gate */ 273*7c478bd9Sstevel@tonic-gate #define MF_MEMORY_ALLOCATION_ERR \ 274*7c478bd9Sstevel@tonic-gate gettext("rcm: failed to allocate memory: %1$s\n") 275*7c478bd9Sstevel@tonic-gate #define MF_STATE_FILE_ERR \ 276*7c478bd9Sstevel@tonic-gate gettext("rcm: state file error: %1$s: %2$s\n") 277*7c478bd9Sstevel@tonic-gate #define MF_FUNC_CALL_ERR \ 278*7c478bd9Sstevel@tonic-gate gettext("rcm: %1$s: %2$s\n") 279*7c478bd9Sstevel@tonic-gate #define MF_NV_ERR \ 280*7c478bd9Sstevel@tonic-gate gettext("rcm: required name-value parameters missing (%1$s)\n") 281*7c478bd9Sstevel@tonic-gate #define MF_UNKNOWN_RSRC_ERR \ 282*7c478bd9Sstevel@tonic-gate gettext("rcm: unknown resource name %1$s (%2$s)\n") 283*7c478bd9Sstevel@tonic-gate #define MS_REGISTER_RSRC_ERR \ 284*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: failed to register %2$s\n") 285*7c478bd9Sstevel@tonic-gate #define MS_REGISTER_ERR \ 286*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: register: %2$s\n") 287*7c478bd9Sstevel@tonic-gate #define MS_SCRIPTINFO_ERR \ 288*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: scriptinfo: %2$s\n") 289*7c478bd9Sstevel@tonic-gate #define MS_PROTOCOL_ERR \ 290*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: scripting protocol error\n") 291*7c478bd9Sstevel@tonic-gate #define MS_TIMEOUT_ERR \ 292*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: timeout error\n") 293*7c478bd9Sstevel@tonic-gate #define MS_UNSUPPORTED_VER \ 294*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: unsupported version %2$d\n") 295*7c478bd9Sstevel@tonic-gate #define MS_SCRIPT_ERR \ 296*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: error: %2$s\n") 297*7c478bd9Sstevel@tonic-gate #define MS_UNKNOWN_ERR \ 298*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: unknown error\n") 299*7c478bd9Sstevel@tonic-gate #define MS_LOG_MSG \ 300*7c478bd9Sstevel@tonic-gate gettext("rcm script %1$s: %2$s\n") 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate /* 304*7c478bd9Sstevel@tonic-gate * Initialize rcm scripting framework. 305*7c478bd9Sstevel@tonic-gate * Called during initialization of rcm daemon. 306*7c478bd9Sstevel@tonic-gate */ 307*7c478bd9Sstevel@tonic-gate int 308*7c478bd9Sstevel@tonic-gate script_main_init(void) 309*7c478bd9Sstevel@tonic-gate { 310*7c478bd9Sstevel@tonic-gate #define PS_STATE_FILE_CHUNK_SIZE 32 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* set base script environment */ 313*7c478bd9Sstevel@tonic-gate build_env(); 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate rcm_init_queue(&script_info_q); 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* 318*7c478bd9Sstevel@tonic-gate * Initialize the semaphore to limit the number of rcm script 319*7c478bd9Sstevel@tonic-gate * process running in parallel to script_max_parallelism. 320*7c478bd9Sstevel@tonic-gate */ 321*7c478bd9Sstevel@tonic-gate (void) sema_init(&script_process_sema, script_max_parallelism, 322*7c478bd9Sstevel@tonic-gate USYNC_THREAD, NULL); 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate (void) mutex_init(&script_lock, USYNC_THREAD, NULL); 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* save original file limit */ 327*7c478bd9Sstevel@tonic-gate (void) getrlimit(RLIMIT_NOFILE, &file_limit); 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate open_state_file(script_ps_state_file, &script_ps_statefd, 330*7c478bd9Sstevel@tonic-gate sizeof (ps_state_element_t), 331*7c478bd9Sstevel@tonic-gate PS_STATE_FILE_CHUNK_SIZE, 332*7c478bd9Sstevel@tonic-gate PS_STATE_FILE_VER); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * If any pids exist in the ps state file since the last incarnation of 336*7c478bd9Sstevel@tonic-gate * the rcm daemon, kill the pids. 337*7c478bd9Sstevel@tonic-gate * On a normal daemon exit no pids should exist in the ps state file. 338*7c478bd9Sstevel@tonic-gate * But on an abnormal daemon exit pids may exist in the ps state file. 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate if (script_ps_statefd.state_file) { 341*7c478bd9Sstevel@tonic-gate script_ps_state_file_kill_pids(); 342*7c478bd9Sstevel@tonic-gate truncate_state_file(&script_ps_statefd); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate return (0); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * Do any cleanup. 350*7c478bd9Sstevel@tonic-gate * Called at the time of normal rcm daemon exit. 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate int 353*7c478bd9Sstevel@tonic-gate script_main_fini(void) 354*7c478bd9Sstevel@tonic-gate { 355*7c478bd9Sstevel@tonic-gate script_ps_state_file_kill_pids(); 356*7c478bd9Sstevel@tonic-gate close_state_file(script_ps_state_file, &script_ps_statefd); 357*7c478bd9Sstevel@tonic-gate return (0); 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Initialize the given rcm script. 362*7c478bd9Sstevel@tonic-gate * module->name contains the name of the rcm script. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate struct rcm_mod_ops * 365*7c478bd9Sstevel@tonic-gate script_init(module_t *module) 366*7c478bd9Sstevel@tonic-gate { 367*7c478bd9Sstevel@tonic-gate script_info_t *rsi; 368*7c478bd9Sstevel@tonic-gate size_t len; 369*7c478bd9Sstevel@tonic-gate char *script_path; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_init: script name = %s\n", 372*7c478bd9Sstevel@tonic-gate module->name); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate module->rsi = NULL; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if ((script_path = rcm_get_script_dir(module->name)) == NULL) 377*7c478bd9Sstevel@tonic-gate return (NULL); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate len = strlen(script_path) + strlen(module->name) + 2; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* calloc also zeros the contents */ 382*7c478bd9Sstevel@tonic-gate rsi = (script_info_t *)rcmscript_calloc(1, sizeof (script_info_t)); 383*7c478bd9Sstevel@tonic-gate rsi->script_full_name = (char *)rcmscript_calloc(1, len); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate rsi->module = module; 386*7c478bd9Sstevel@tonic-gate rcm_init_queue(&rsi->drreq_q); 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate (void) mutex_init(&rsi->channel_lock, USYNC_THREAD, NULL); 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate (void) snprintf(rsi->script_full_name, len, "%s%s", script_path, 391*7c478bd9Sstevel@tonic-gate module->name); 392*7c478bd9Sstevel@tonic-gate rsi->script_name = strrchr(rsi->script_full_name, '/') + 1; 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate rsi->cmd_timeout = -1; /* don't time scriptinfo command */ 397*7c478bd9Sstevel@tonic-gate if (do_script_info(rsi) == RCM_SUCCESS) { 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * if the script hasn't specified a timeout value set it to 400*7c478bd9Sstevel@tonic-gate * default 401*7c478bd9Sstevel@tonic-gate */ 402*7c478bd9Sstevel@tonic-gate if (rsi->cmd_timeout == -1) 403*7c478bd9Sstevel@tonic-gate rsi->cmd_timeout = SCRIPT_CMD_TIMEOUT; 404*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* put rsi on script_info_q */ 407*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&script_lock); 408*7c478bd9Sstevel@tonic-gate rcm_enqueue_tail(&script_info_q, &rsi->queue); 409*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&script_lock); 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate module->rsi = rsi; 412*7c478bd9Sstevel@tonic-gate return (&script_ops); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate free(rsi->script_full_name); 418*7c478bd9Sstevel@tonic-gate free(rsi); 419*7c478bd9Sstevel@tonic-gate return (NULL); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate /* 423*7c478bd9Sstevel@tonic-gate * Returns a string describing the script's functionality. 424*7c478bd9Sstevel@tonic-gate * module->name contains the name of the rcm script for which information 425*7c478bd9Sstevel@tonic-gate * is requested. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate char * 428*7c478bd9Sstevel@tonic-gate script_info(module_t *module) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate script_info_t *rsi = module->rsi; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_info: script name = %s\n", 433*7c478bd9Sstevel@tonic-gate rsi->script_name); 434*7c478bd9Sstevel@tonic-gate return (rsi->func_info_buf); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * Called before unloading the script. 439*7c478bd9Sstevel@tonic-gate * module->name contains the name of the rcm script which is being unloaded. 440*7c478bd9Sstevel@tonic-gate * Do any cleanup. 441*7c478bd9Sstevel@tonic-gate */ 442*7c478bd9Sstevel@tonic-gate int 443*7c478bd9Sstevel@tonic-gate script_fini(module_t *module) 444*7c478bd9Sstevel@tonic-gate { 445*7c478bd9Sstevel@tonic-gate script_info_t *rsi = module->rsi; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_fini: script name = %s\n", 448*7c478bd9Sstevel@tonic-gate rsi->script_name); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate /* remove rsi from script_info_q */ 451*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&script_lock); 452*7c478bd9Sstevel@tonic-gate rcm_dequeue(&rsi->queue); 453*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&script_lock); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate remove_drreq_all(rsi); 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (rsi->func_info_buf) 458*7c478bd9Sstevel@tonic-gate free(rsi->func_info_buf); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate free(rsi->script_full_name); 461*7c478bd9Sstevel@tonic-gate free(rsi); 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate module->rsi = NULL; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate /* build base environment for scripts */ 469*7c478bd9Sstevel@tonic-gate static void 470*7c478bd9Sstevel@tonic-gate build_env(void) 471*7c478bd9Sstevel@tonic-gate { 472*7c478bd9Sstevel@tonic-gate const char *env_list[] = { "LANG", "LC_COLLATE", "LC_CTYPE", 473*7c478bd9Sstevel@tonic-gate "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", "LC_TIME", 474*7c478bd9Sstevel@tonic-gate "LC_ALL", "TZ", NULL }; 475*7c478bd9Sstevel@tonic-gate char *x; 476*7c478bd9Sstevel@tonic-gate int len; 477*7c478bd9Sstevel@tonic-gate int i, j = 0; 478*7c478bd9Sstevel@tonic-gate int d; 479*7c478bd9Sstevel@tonic-gate extern int debug_level; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate script_env[j++] = rcmscript_strdup("PATH=/usr/sbin:/usr/bin"); 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate for (i = 0; env_list[i] != NULL; i++) { 484*7c478bd9Sstevel@tonic-gate x = getenv(env_list[i]); 485*7c478bd9Sstevel@tonic-gate if (x) { 486*7c478bd9Sstevel@tonic-gate len = strlen(env_list[i]) + strlen(x) + 2; 487*7c478bd9Sstevel@tonic-gate script_env[j] = (char *)rcmscript_malloc(len); 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate (void) snprintf(script_env[j++], len, "%s=%s", 490*7c478bd9Sstevel@tonic-gate env_list[i], x); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate len = strlen("RCM_ENV_DEBUG_LEVEL") + 3; 495*7c478bd9Sstevel@tonic-gate script_env[j] = (char *)rcmscript_malloc(len); 496*7c478bd9Sstevel@tonic-gate 497*7c478bd9Sstevel@tonic-gate if (debug_level < 0) 498*7c478bd9Sstevel@tonic-gate d = 0; 499*7c478bd9Sstevel@tonic-gate else if (debug_level > 9) 500*7c478bd9Sstevel@tonic-gate d = 9; 501*7c478bd9Sstevel@tonic-gate else 502*7c478bd9Sstevel@tonic-gate d = debug_level; 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate (void) snprintf(script_env[j++], len, "RCM_ENV_DEBUG_LEVEL=%d", d); 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate script_env[j] = NULL; 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate static void 510*7c478bd9Sstevel@tonic-gate copy_env(char *src[], char *dst[]) 511*7c478bd9Sstevel@tonic-gate { 512*7c478bd9Sstevel@tonic-gate int i; 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate for (i = 0; src[i] != NULL; i++) 515*7c478bd9Sstevel@tonic-gate dst[i] = src[i]; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate dst[i] = NULL; 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate /* 521*7c478bd9Sstevel@tonic-gate * Open (or create if the file does not exist) the given state file 522*7c478bd9Sstevel@tonic-gate * and mmap it. 523*7c478bd9Sstevel@tonic-gate */ 524*7c478bd9Sstevel@tonic-gate static void 525*7c478bd9Sstevel@tonic-gate open_state_file(const char *filename, 526*7c478bd9Sstevel@tonic-gate state_file_descr_t *statefd, 527*7c478bd9Sstevel@tonic-gate size_t element_size, 528*7c478bd9Sstevel@tonic-gate int chunk_size, 529*7c478bd9Sstevel@tonic-gate uint32_t version) 530*7c478bd9Sstevel@tonic-gate { 531*7c478bd9Sstevel@tonic-gate struct stat stats; 532*7c478bd9Sstevel@tonic-gate int error_num; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate if ((statefd->fd = open(filename, O_CREAT|O_RDWR, 0600)) == 535*7c478bd9Sstevel@tonic-gate -1) { 536*7c478bd9Sstevel@tonic-gate error_num = errno; 537*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_STATE_FILE_ERR, 538*7c478bd9Sstevel@tonic-gate "open", strerror(error_num)); 539*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 540*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate if (fstat(statefd->fd, &stats) != 0) { 544*7c478bd9Sstevel@tonic-gate error_num = errno; 545*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_STATE_FILE_ERR, 546*7c478bd9Sstevel@tonic-gate "fstat", strerror(error_num)); 547*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 548*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate if (stats.st_size != 0) { 552*7c478bd9Sstevel@tonic-gate /* LINTED */ 553*7c478bd9Sstevel@tonic-gate statefd->state_file = (state_file_t *)mmap(NULL, 554*7c478bd9Sstevel@tonic-gate stats.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, 555*7c478bd9Sstevel@tonic-gate statefd->fd, 0); 556*7c478bd9Sstevel@tonic-gate 557*7c478bd9Sstevel@tonic-gate if (statefd->state_file == MAP_FAILED) { 558*7c478bd9Sstevel@tonic-gate error_num = errno; 559*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_STATE_FILE_ERR, 560*7c478bd9Sstevel@tonic-gate "mmap", strerror(error_num)); 561*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 562*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate if (statefd->state_file->version != version) { 566*7c478bd9Sstevel@tonic-gate (void) munmap((void *)statefd->state_file, 567*7c478bd9Sstevel@tonic-gate stats.st_size); 568*7c478bd9Sstevel@tonic-gate statefd->state_file = NULL; 569*7c478bd9Sstevel@tonic-gate (void) ftruncate(statefd->fd, 0); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate } else { 572*7c478bd9Sstevel@tonic-gate statefd->state_file = NULL; 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate statefd->version = version; 576*7c478bd9Sstevel@tonic-gate statefd->element_size = sizeof (state_element_t) + 577*7c478bd9Sstevel@tonic-gate RSCR_ROUNDUP(element_size, 8); 578*7c478bd9Sstevel@tonic-gate statefd->chunk_size = chunk_size; 579*7c478bd9Sstevel@tonic-gate statefd->index = 0; 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate static void 583*7c478bd9Sstevel@tonic-gate truncate_state_file(state_file_descr_t *statefd) 584*7c478bd9Sstevel@tonic-gate { 585*7c478bd9Sstevel@tonic-gate size_t size; 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate if (statefd->state_file) { 588*7c478bd9Sstevel@tonic-gate size = sizeof (state_file_t) + statefd->element_size * 589*7c478bd9Sstevel@tonic-gate statefd->state_file->max_elements; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate (void) munmap((void *)statefd->state_file, size); 592*7c478bd9Sstevel@tonic-gate statefd->state_file = NULL; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate (void) ftruncate(statefd->fd, 0); 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate static void 598*7c478bd9Sstevel@tonic-gate close_state_file(const char *filename, state_file_descr_t *statefd) 599*7c478bd9Sstevel@tonic-gate { 600*7c478bd9Sstevel@tonic-gate truncate_state_file(statefd); 601*7c478bd9Sstevel@tonic-gate (void) close(statefd->fd); 602*7c478bd9Sstevel@tonic-gate (void) unlink(filename); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate /* 606*7c478bd9Sstevel@tonic-gate * Grow the state file by the chunk size specified in statefd 607*7c478bd9Sstevel@tonic-gate * and mmap it. 608*7c478bd9Sstevel@tonic-gate */ 609*7c478bd9Sstevel@tonic-gate static void 610*7c478bd9Sstevel@tonic-gate grow_state_file(state_file_descr_t *statefd) 611*7c478bd9Sstevel@tonic-gate { 612*7c478bd9Sstevel@tonic-gate size_t size; 613*7c478bd9Sstevel@tonic-gate int max_elements; 614*7c478bd9Sstevel@tonic-gate int error_num; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate max_elements = statefd->chunk_size; 617*7c478bd9Sstevel@tonic-gate if (statefd->state_file) 618*7c478bd9Sstevel@tonic-gate max_elements += statefd->state_file->max_elements; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate size = sizeof (state_file_t) + 621*7c478bd9Sstevel@tonic-gate statefd->element_size * max_elements; 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (ftruncate(statefd->fd, size) != 0) { 624*7c478bd9Sstevel@tonic-gate error_num = errno; 625*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_STATE_FILE_ERR, 626*7c478bd9Sstevel@tonic-gate "ftruncate", strerror(error_num)); 627*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 628*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* LINTED */ 632*7c478bd9Sstevel@tonic-gate statefd->state_file = (state_file_t *)mmap(NULL, size, 633*7c478bd9Sstevel@tonic-gate PROT_READ|PROT_WRITE, MAP_SHARED, statefd->fd, 0); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate if (statefd->state_file == MAP_FAILED) { 636*7c478bd9Sstevel@tonic-gate error_num = errno; 637*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_STATE_FILE_ERR, 638*7c478bd9Sstevel@tonic-gate "mmap", strerror(error_num)); 639*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 640*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate statefd->index = statefd->state_file->max_elements; 644*7c478bd9Sstevel@tonic-gate statefd->state_file->max_elements = max_elements; 645*7c478bd9Sstevel@tonic-gate statefd->state_file->version = statefd->version; 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate /* 649*7c478bd9Sstevel@tonic-gate * Given index into state element array, get the pointer to the actual 650*7c478bd9Sstevel@tonic-gate * state element. 651*7c478bd9Sstevel@tonic-gate * If flag is non-null set *flag to 652*7c478bd9Sstevel@tonic-gate * TRUE if the state element is currently is use. 653*7c478bd9Sstevel@tonic-gate * FALSE if the state element is free. 654*7c478bd9Sstevel@tonic-gate */ 655*7c478bd9Sstevel@tonic-gate static void * 656*7c478bd9Sstevel@tonic-gate get_state_element(state_file_descr_t *statefd, int index, int *flag) 657*7c478bd9Sstevel@tonic-gate { 658*7c478bd9Sstevel@tonic-gate char *ptr; 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate if (statefd->state_file && 661*7c478bd9Sstevel@tonic-gate (index < statefd->state_file->max_elements)) { 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate ptr = (char *)(statefd->state_file); 664*7c478bd9Sstevel@tonic-gate ptr += sizeof (state_file_t) + 665*7c478bd9Sstevel@tonic-gate index * statefd->element_size; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate if (flag) { 668*7c478bd9Sstevel@tonic-gate *flag = (((state_element_t *)((void *)ptr))->flags & 669*7c478bd9Sstevel@tonic-gate STATE_ELEMENT_IN_USE) ? 1 : 0; 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate ptr += sizeof (state_element_t); 673*7c478bd9Sstevel@tonic-gate } else 674*7c478bd9Sstevel@tonic-gate ptr = NULL; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate return ((void *)ptr); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /* 680*7c478bd9Sstevel@tonic-gate * Allocate a state element entry in the state file and return a pointer 681*7c478bd9Sstevel@tonic-gate * to the allocated entry. 682*7c478bd9Sstevel@tonic-gate * If index is non-null set *index to index into the state element array 683*7c478bd9Sstevel@tonic-gate * of the allocated entry. 684*7c478bd9Sstevel@tonic-gate */ 685*7c478bd9Sstevel@tonic-gate static void * 686*7c478bd9Sstevel@tonic-gate allocate_state_element(state_file_descr_t *statefd, int *index) 687*7c478bd9Sstevel@tonic-gate { 688*7c478bd9Sstevel@tonic-gate void *x; 689*7c478bd9Sstevel@tonic-gate int i; 690*7c478bd9Sstevel@tonic-gate int flag; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate if (statefd->state_file) { 693*7c478bd9Sstevel@tonic-gate /* find an empty slot */ 694*7c478bd9Sstevel@tonic-gate for (i = 0; i < statefd->state_file->max_elements; i++) { 695*7c478bd9Sstevel@tonic-gate x = get_state_element(statefd, statefd->index, 696*7c478bd9Sstevel@tonic-gate &flag); 697*7c478bd9Sstevel@tonic-gate assert(x != NULL); 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate if (flag == 0) 700*7c478bd9Sstevel@tonic-gate /* entry is free */ 701*7c478bd9Sstevel@tonic-gate break; 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate statefd->index++; 704*7c478bd9Sstevel@tonic-gate if (statefd->index >= statefd->state_file->max_elements) 705*7c478bd9Sstevel@tonic-gate statefd->index = 0; 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate if (statefd->state_file == NULL || 710*7c478bd9Sstevel@tonic-gate i == statefd->state_file->max_elements) { 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate /* All entries are in use. Grow the list */ 713*7c478bd9Sstevel@tonic-gate grow_state_file(statefd); 714*7c478bd9Sstevel@tonic-gate x = get_state_element(statefd, statefd->index, &flag); 715*7c478bd9Sstevel@tonic-gate assert(flag == 0); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate if (index != NULL) 719*7c478bd9Sstevel@tonic-gate *index = statefd->index; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate statefd->index++; 722*7c478bd9Sstevel@tonic-gate if (statefd->index >= statefd->state_file->max_elements) 723*7c478bd9Sstevel@tonic-gate statefd->index = 0; 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate ((state_element_t *)x - 1)->flags |= STATE_ELEMENT_IN_USE; 726*7c478bd9Sstevel@tonic-gate return (x); 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate 729*7c478bd9Sstevel@tonic-gate static void 730*7c478bd9Sstevel@tonic-gate free_state_element(void *x) 731*7c478bd9Sstevel@tonic-gate { 732*7c478bd9Sstevel@tonic-gate ((state_element_t *)x - 1)->flags &= ~STATE_ELEMENT_IN_USE; 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate /* 736*7c478bd9Sstevel@tonic-gate * Kill the pids contained in ps state file. 737*7c478bd9Sstevel@tonic-gate */ 738*7c478bd9Sstevel@tonic-gate static void 739*7c478bd9Sstevel@tonic-gate script_ps_state_file_kill_pids(void) 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate ps_state_element_t *x; 742*7c478bd9Sstevel@tonic-gate char procfile[80]; 743*7c478bd9Sstevel@tonic-gate psinfo_t psi; 744*7c478bd9Sstevel@tonic-gate int fd, i, flag; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate /* LINTED */ 747*7c478bd9Sstevel@tonic-gate for (i = 0; 1; i++) { 748*7c478bd9Sstevel@tonic-gate if ((x = (ps_state_element_t *)get_state_element( 749*7c478bd9Sstevel@tonic-gate &script_ps_statefd, i, &flag)) == NULL) 750*7c478bd9Sstevel@tonic-gate break; 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate if (flag == 1) { /* the entry is in use */ 753*7c478bd9Sstevel@tonic-gate (void) snprintf(procfile, 80, "/proc/%ld/psinfo", 754*7c478bd9Sstevel@tonic-gate (long)x->pid); 755*7c478bd9Sstevel@tonic-gate if ((fd = open(procfile, O_RDONLY)) != -1 && 756*7c478bd9Sstevel@tonic-gate read(fd, &psi, sizeof (psi)) == sizeof (psi) && 757*7c478bd9Sstevel@tonic-gate strcmp(psi.pr_fname, 758*7c478bd9Sstevel@tonic-gate x->script_name) == 0) { 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate (void) close(fd); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate /* 763*7c478bd9Sstevel@tonic-gate * just a safety check to not to blow up 764*7c478bd9Sstevel@tonic-gate * system processes if the file is ever corrupt 765*7c478bd9Sstevel@tonic-gate */ 766*7c478bd9Sstevel@tonic-gate if (x->pid > 1) { 767*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 768*7c478bd9Sstevel@tonic-gate "script_ps_state_file_kill_pids: " 769*7c478bd9Sstevel@tonic-gate "killing script_name = %s pid = %ld\n", 770*7c478bd9Sstevel@tonic-gate x->script_name, x->pid); 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate /* kill the process group */ 773*7c478bd9Sstevel@tonic-gate (void) kill(-(x->pid), SIGKILL); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate } else { 776*7c478bd9Sstevel@tonic-gate if (fd != -1) 777*7c478bd9Sstevel@tonic-gate (void) close(fd); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate free_state_element((void *)x); 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate /* 785*7c478bd9Sstevel@tonic-gate * Add a state element entry to ps state file. 786*7c478bd9Sstevel@tonic-gate */ 787*7c478bd9Sstevel@tonic-gate static void 788*7c478bd9Sstevel@tonic-gate script_ps_state_file_add_entry(pid_t pid, char *script_name) 789*7c478bd9Sstevel@tonic-gate { 790*7c478bd9Sstevel@tonic-gate ps_state_element_t *x; 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&script_lock); 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate x = (ps_state_element_t *)allocate_state_element( 795*7c478bd9Sstevel@tonic-gate &script_ps_statefd, NULL); 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate x->pid = pid; 798*7c478bd9Sstevel@tonic-gate (void) strlcpy(x->script_name, script_name, MAXNAMELEN); 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate (void) fsync(script_ps_statefd.fd); 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&script_lock); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate /* 806*7c478bd9Sstevel@tonic-gate * Remove the state element entry corresponding to pid from the 807*7c478bd9Sstevel@tonic-gate * ps state file. 808*7c478bd9Sstevel@tonic-gate */ 809*7c478bd9Sstevel@tonic-gate static void 810*7c478bd9Sstevel@tonic-gate script_ps_state_file_remove_entry(pid_t pid) 811*7c478bd9Sstevel@tonic-gate { 812*7c478bd9Sstevel@tonic-gate ps_state_element_t *x; 813*7c478bd9Sstevel@tonic-gate int flag, i; 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&script_lock); 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate /* LINTED */ 818*7c478bd9Sstevel@tonic-gate for (i = 0; 1; i++) { 819*7c478bd9Sstevel@tonic-gate if ((x = (ps_state_element_t *)get_state_element( 820*7c478bd9Sstevel@tonic-gate &script_ps_statefd, i, &flag)) == NULL) 821*7c478bd9Sstevel@tonic-gate break; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate /* if the state element entry is in use and pid matches */ 824*7c478bd9Sstevel@tonic-gate if (flag == 1 && x->pid == pid) { 825*7c478bd9Sstevel@tonic-gate free_state_element((void *)x); 826*7c478bd9Sstevel@tonic-gate break; 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&script_lock); 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate /* 834*7c478bd9Sstevel@tonic-gate * Get data item id given data item name 835*7c478bd9Sstevel@tonic-gate */ 836*7c478bd9Sstevel@tonic-gate static int 837*7c478bd9Sstevel@tonic-gate dname_to_id(char *dname) 838*7c478bd9Sstevel@tonic-gate { 839*7c478bd9Sstevel@tonic-gate int i; 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate for (i = 0; script_data_item_name[i] != NULL; i++) { 842*7c478bd9Sstevel@tonic-gate if (strcmp(dname, script_data_item_name[i]) == 0) 843*7c478bd9Sstevel@tonic-gate return (i); 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate return (-1); 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /* 850*7c478bd9Sstevel@tonic-gate * Called before running any script. 851*7c478bd9Sstevel@tonic-gate * This routine waits until the number of script processes running in 852*7c478bd9Sstevel@tonic-gate * parallel drops down below to script_max_parallelism. 853*7c478bd9Sstevel@tonic-gate */ 854*7c478bd9Sstevel@tonic-gate static void 855*7c478bd9Sstevel@tonic-gate script_process_sema_wait(void) 856*7c478bd9Sstevel@tonic-gate { 857*7c478bd9Sstevel@tonic-gate int error_num; 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate /* LINTED */ 860*7c478bd9Sstevel@tonic-gate while (1) { 861*7c478bd9Sstevel@tonic-gate if (sema_wait(&script_process_sema) == 0) 862*7c478bd9Sstevel@tonic-gate return; 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if (errno != EINTR && errno != EAGAIN) { 865*7c478bd9Sstevel@tonic-gate error_num = errno; 866*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_FUNC_CALL_ERR, 867*7c478bd9Sstevel@tonic-gate "sema_wait", strerror(error_num)); 868*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 869*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * Fork and execute the script. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate static int 880*7c478bd9Sstevel@tonic-gate run_script(script_info_t *rsi, char *argv[], char *envp[], char **errmsg) 881*7c478bd9Sstevel@tonic-gate { 882*7c478bd9Sstevel@tonic-gate int i, p1 = -1, p2 = -1; 883*7c478bd9Sstevel@tonic-gate struct rlimit rlp; 884*7c478bd9Sstevel@tonic-gate struct stat stats; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "run_script: script name = %s\n", 887*7c478bd9Sstevel@tonic-gate rsi->script_full_name); 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate for (i = 0; argv[i] != NULL; i++) 890*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "run_script: argv[%d] = %s\n", 891*7c478bd9Sstevel@tonic-gate i, argv[i]); 892*7c478bd9Sstevel@tonic-gate 893*7c478bd9Sstevel@tonic-gate *errmsg = NULL; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate /* check that the script exists */ 896*7c478bd9Sstevel@tonic-gate if (stat(rsi->script_full_name, &stats) != 0) 897*7c478bd9Sstevel@tonic-gate goto error; 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate /* 900*7c478bd9Sstevel@tonic-gate * If the syscall pipe fails because of reaching the max open file 901*7c478bd9Sstevel@tonic-gate * count per process then dynamically increase the limit on the max 902*7c478bd9Sstevel@tonic-gate * open file count. 903*7c478bd9Sstevel@tonic-gate * 904*7c478bd9Sstevel@tonic-gate * At present the rcm_daemon consumes file descriptor 905*7c478bd9Sstevel@tonic-gate * entries for the following files. 906*7c478bd9Sstevel@tonic-gate * RCM_STATE_FILE - /var/run/rcm_daemon_state 907*7c478bd9Sstevel@tonic-gate * DAEMON_LOCK_FILE - /var/run/rcm_daemon_lock 908*7c478bd9Sstevel@tonic-gate * RCM_SERVICE_DOOR - /var/run/rcm_daemon_door 909*7c478bd9Sstevel@tonic-gate * proc files in the format "/proc/pid/as" for each pid 910*7c478bd9Sstevel@tonic-gate * communicating with the rcm_daemon via doors 911*7c478bd9Sstevel@tonic-gate * dlopen for each rcm module 912*7c478bd9Sstevel@tonic-gate * When in daemon mode stdin, stdout and stderr are closed; 913*7c478bd9Sstevel@tonic-gate * /dev/null opened and duped to stdout, and stderr 914*7c478bd9Sstevel@tonic-gate * openlog 915*7c478bd9Sstevel@tonic-gate * Some files which are opened briefly and closed such as 916*7c478bd9Sstevel@tonic-gate * directory files. 917*7c478bd9Sstevel@tonic-gate * Two file descriptors for each script in running state. 918*7c478bd9Sstevel@tonic-gate * Note that the constant script_max_parallelism sets an 919*7c478bd9Sstevel@tonic-gate * upper cap on how many rcm scripts can run in 920*7c478bd9Sstevel@tonic-gate * parallel. 921*7c478bd9Sstevel@tonic-gate */ 922*7c478bd9Sstevel@tonic-gate if ((p1 = pipe(rsi->pipe1)) == -1 || (p2 = pipe(rsi->pipe2)) == -1) { 923*7c478bd9Sstevel@tonic-gate if ((errno == EMFILE) && 924*7c478bd9Sstevel@tonic-gate (getrlimit(RLIMIT_NOFILE, &rlp) == 0)) { 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate rlp.rlim_cur += 16; 927*7c478bd9Sstevel@tonic-gate if (rlp.rlim_max < rlp.rlim_cur) 928*7c478bd9Sstevel@tonic-gate rlp.rlim_max = rlp.rlim_cur; 929*7c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_NOFILE, &rlp); 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate if (p1 == -1) { 932*7c478bd9Sstevel@tonic-gate if ((p1 = pipe(rsi->pipe1)) == -1) 933*7c478bd9Sstevel@tonic-gate goto error; 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate if ((p2 = pipe(rsi->pipe2)) == -1) 936*7c478bd9Sstevel@tonic-gate goto error; 937*7c478bd9Sstevel@tonic-gate } else 938*7c478bd9Sstevel@tonic-gate goto error; 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate forkagain: 942*7c478bd9Sstevel@tonic-gate if ((rsi->pid = fork1()) == (pid_t)-1) { 943*7c478bd9Sstevel@tonic-gate if (errno == EINTR || errno == EAGAIN) 944*7c478bd9Sstevel@tonic-gate goto forkagain; 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate goto error; 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate if (rsi->pid == 0) { 950*7c478bd9Sstevel@tonic-gate /* child process */ 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate (void) setsid(); 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate /* close stdin, stdout and stderr */ 955*7c478bd9Sstevel@tonic-gate (void) close(0); 956*7c478bd9Sstevel@tonic-gate (void) close(1); 957*7c478bd9Sstevel@tonic-gate (void) close(2); 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate /* set stdin to /dev/null */ 960*7c478bd9Sstevel@tonic-gate (void) open("/dev/null", O_RDWR, 0); 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate /* redirect stdout and stderr to pipe */ 963*7c478bd9Sstevel@tonic-gate (void) dup2(rsi->pipe1[CHILD_END_OF_PIPE], 1); 964*7c478bd9Sstevel@tonic-gate (void) dup2(rsi->pipe2[CHILD_END_OF_PIPE], 2); 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate /* close all other file descriptors */ 967*7c478bd9Sstevel@tonic-gate closefrom(3); 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate /* restore original file limit */ 970*7c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_NOFILE, &file_limit); 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate /* set current working dir */ 973*7c478bd9Sstevel@tonic-gate if (stats.st_uid == 0) { 974*7c478bd9Sstevel@tonic-gate /* root */ 975*7c478bd9Sstevel@tonic-gate if (chdir("/var/run") == -1) 976*7c478bd9Sstevel@tonic-gate _exit(127); 977*7c478bd9Sstevel@tonic-gate } else { 978*7c478bd9Sstevel@tonic-gate if (chdir("/tmp") == -1) 979*7c478bd9Sstevel@tonic-gate _exit(127); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate /* 983*7c478bd9Sstevel@tonic-gate * setuid sets real, effective and saved user ids to the 984*7c478bd9Sstevel@tonic-gate * given id. 985*7c478bd9Sstevel@tonic-gate * setgid sets real, effective and saved group ids to the 986*7c478bd9Sstevel@tonic-gate * given id. 987*7c478bd9Sstevel@tonic-gate */ 988*7c478bd9Sstevel@tonic-gate (void) setgid(stats.st_gid); 989*7c478bd9Sstevel@tonic-gate (void) setuid(stats.st_uid); 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate (void) execve(rsi->script_full_name, argv, envp); 992*7c478bd9Sstevel@tonic-gate _exit(127); 993*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe1[CHILD_END_OF_PIPE]); 997*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe2[CHILD_END_OF_PIPE]); 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate script_ps_state_file_add_entry(rsi->pid, rsi->script_name); 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate return (0); 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate error: 1004*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MS_SCRIPT_ERR, 1005*7c478bd9Sstevel@tonic-gate rsi->script_name, strerror(errno)); 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate if (p1 != -1) { 1008*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe1[PARENT_END_OF_PIPE]); 1009*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe1[CHILD_END_OF_PIPE]); 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate if (p2 != -1) { 1013*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe2[PARENT_END_OF_PIPE]); 1014*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe2[CHILD_END_OF_PIPE]); 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate return (-1); 1018*7c478bd9Sstevel@tonic-gate } 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate /* 1021*7c478bd9Sstevel@tonic-gate * Reads one line of input (including the newline character) from the 1022*7c478bd9Sstevel@tonic-gate * given file descriptor "fd" to buf. 1023*7c478bd9Sstevel@tonic-gate * maxbuflen specifies the size of memory allocated for buf. 1024*7c478bd9Sstevel@tonic-gate * Timeoutval is the max timeout value in seconds for the script to supply 1025*7c478bd9Sstevel@tonic-gate * input. A timeoutval of 0 implies no timeout. 1026*7c478bd9Sstevel@tonic-gate * 1027*7c478bd9Sstevel@tonic-gate * Upon return *buflen contains the number of bytes read. 1028*7c478bd9Sstevel@tonic-gate * 1029*7c478bd9Sstevel@tonic-gate * Return values: 1030*7c478bd9Sstevel@tonic-gate * 0 success 1031*7c478bd9Sstevel@tonic-gate * -1 an error occured 1032*7c478bd9Sstevel@tonic-gate * -2 timeout occurred 1033*7c478bd9Sstevel@tonic-gate * -3 script exited 1034*7c478bd9Sstevel@tonic-gate */ 1035*7c478bd9Sstevel@tonic-gate static int 1036*7c478bd9Sstevel@tonic-gate get_line(int fd, 1037*7c478bd9Sstevel@tonic-gate char *fdname, 1038*7c478bd9Sstevel@tonic-gate char *buf, 1039*7c478bd9Sstevel@tonic-gate int maxbuflen, 1040*7c478bd9Sstevel@tonic-gate size_t *buflen, 1041*7c478bd9Sstevel@tonic-gate time_t timeoutval, 1042*7c478bd9Sstevel@tonic-gate int *error_num) 1043*7c478bd9Sstevel@tonic-gate { 1044*7c478bd9Sstevel@tonic-gate char c = '\0'; 1045*7c478bd9Sstevel@tonic-gate struct pollfd fds[1]; 1046*7c478bd9Sstevel@tonic-gate int x; 1047*7c478bd9Sstevel@tonic-gate size_t len = 0; 1048*7c478bd9Sstevel@tonic-gate char *ptr; 1049*7c478bd9Sstevel@tonic-gate int timeit; 1050*7c478bd9Sstevel@tonic-gate time_t deadline; 1051*7c478bd9Sstevel@tonic-gate int rval = 0; 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate if (timeoutval) { 1054*7c478bd9Sstevel@tonic-gate timeit = TRUE; 1055*7c478bd9Sstevel@tonic-gate deadline = time(NULL) + timeoutval; 1056*7c478bd9Sstevel@tonic-gate fds[0].fd = fd; 1057*7c478bd9Sstevel@tonic-gate fds[0].events = POLLIN; 1058*7c478bd9Sstevel@tonic-gate } else 1059*7c478bd9Sstevel@tonic-gate timeit = FALSE; 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate ptr = buf; 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate while (c != '\n' && len < (maxbuflen -1)) { 1064*7c478bd9Sstevel@tonic-gate if (timeit) { 1065*7c478bd9Sstevel@tonic-gate pollagain: 1066*7c478bd9Sstevel@tonic-gate fds[0].revents = 0; 1067*7c478bd9Sstevel@tonic-gate timeoutval = deadline - time(NULL); 1068*7c478bd9Sstevel@tonic-gate if (timeoutval <= 0) { 1069*7c478bd9Sstevel@tonic-gate rval = -2; 1070*7c478bd9Sstevel@tonic-gate break; 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate x = poll(fds, 1, timeoutval*1000); 1073*7c478bd9Sstevel@tonic-gate if (x <= 0) { 1074*7c478bd9Sstevel@tonic-gate if (x == 0) 1075*7c478bd9Sstevel@tonic-gate /* poll timedout */ 1076*7c478bd9Sstevel@tonic-gate rval = -2; 1077*7c478bd9Sstevel@tonic-gate else { 1078*7c478bd9Sstevel@tonic-gate if (errno == EINTR || errno == EAGAIN) 1079*7c478bd9Sstevel@tonic-gate goto pollagain; 1080*7c478bd9Sstevel@tonic-gate *error_num = errno; 1081*7c478bd9Sstevel@tonic-gate rval = -1; 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate break; 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate readagain: 1087*7c478bd9Sstevel@tonic-gate if ((x = read(fd, &c, 1)) != 1) { 1088*7c478bd9Sstevel@tonic-gate if (x == 0) 1089*7c478bd9Sstevel@tonic-gate /* 1090*7c478bd9Sstevel@tonic-gate * Script exited. Or more specifically the 1091*7c478bd9Sstevel@tonic-gate * script has closed its end of the pipe. 1092*7c478bd9Sstevel@tonic-gate */ 1093*7c478bd9Sstevel@tonic-gate rval = -3; 1094*7c478bd9Sstevel@tonic-gate else { 1095*7c478bd9Sstevel@tonic-gate if (errno == EINTR || errno == EAGAIN) 1096*7c478bd9Sstevel@tonic-gate goto readagain; 1097*7c478bd9Sstevel@tonic-gate *error_num = errno; 1098*7c478bd9Sstevel@tonic-gate rval = -1; 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate break; 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate 1103*7c478bd9Sstevel@tonic-gate *ptr++ = c; 1104*7c478bd9Sstevel@tonic-gate len++; 1105*7c478bd9Sstevel@tonic-gate } 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 1108*7c478bd9Sstevel@tonic-gate *buflen = len; 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 1111*7c478bd9Sstevel@tonic-gate "get_line(%s): rval = %d buflen = %d line = %s\n", 1112*7c478bd9Sstevel@tonic-gate fdname, rval, *buflen, buf); 1113*7c478bd9Sstevel@tonic-gate return (rval); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate static void 1117*7c478bd9Sstevel@tonic-gate script_exited(script_info_t *rsi) 1118*7c478bd9Sstevel@tonic-gate { 1119*7c478bd9Sstevel@tonic-gate if (rsi->flags & STDERR_THREAD_CREATED) { 1120*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 1121*7c478bd9Sstevel@tonic-gate "script_exited: doing thr_join (%s)\n", rsi->script_name); 1122*7c478bd9Sstevel@tonic-gate (void) thr_join(rsi->tid, NULL, NULL); 1123*7c478bd9Sstevel@tonic-gate rsi->flags &= ~STDERR_THREAD_CREATED; 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe1[PARENT_END_OF_PIPE]); 1127*7c478bd9Sstevel@tonic-gate (void) close(rsi->pipe2[PARENT_END_OF_PIPE]); 1128*7c478bd9Sstevel@tonic-gate rsi->pipe1[PARENT_END_OF_PIPE] = -1; 1129*7c478bd9Sstevel@tonic-gate rsi->pipe2[PARENT_END_OF_PIPE] = -1; 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate script_ps_state_file_remove_entry(rsi->pid); 1132*7c478bd9Sstevel@tonic-gate rsi->pid = 0; 1133*7c478bd9Sstevel@tonic-gate (void) sema_post(&script_process_sema); 1134*7c478bd9Sstevel@tonic-gate } 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate /* 1137*7c478bd9Sstevel@tonic-gate * Kill the specified process group 1138*7c478bd9Sstevel@tonic-gate */ 1139*7c478bd9Sstevel@tonic-gate static int 1140*7c478bd9Sstevel@tonic-gate kill_pid(pid_t pid) 1141*7c478bd9Sstevel@tonic-gate { 1142*7c478bd9Sstevel@tonic-gate time_t deadline, timeleft; 1143*7c478bd9Sstevel@tonic-gate int child_status; 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate /* kill the entire process group */ 1146*7c478bd9Sstevel@tonic-gate (void) kill(-(pid), SIGKILL); 1147*7c478bd9Sstevel@tonic-gate 1148*7c478bd9Sstevel@tonic-gate /* give some time for the script to be killed */ 1149*7c478bd9Sstevel@tonic-gate deadline = time(NULL) + SCRIPT_KILL_TIMEOUT; 1150*7c478bd9Sstevel@tonic-gate do { 1151*7c478bd9Sstevel@tonic-gate if (waitpid(pid, &child_status, WNOHANG) == pid) 1152*7c478bd9Sstevel@tonic-gate return (0); 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate /* wait for 100 ms */ 1155*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, 100); 1156*7c478bd9Sstevel@tonic-gate 1157*7c478bd9Sstevel@tonic-gate timeleft = deadline - time(NULL); 1158*7c478bd9Sstevel@tonic-gate } while (timeleft > 0); 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate /* script process was not killed successfully */ 1161*7c478bd9Sstevel@tonic-gate return (-1); 1162*7c478bd9Sstevel@tonic-gate } 1163*7c478bd9Sstevel@tonic-gate 1164*7c478bd9Sstevel@tonic-gate /* 1165*7c478bd9Sstevel@tonic-gate * Kill the specified script. 1166*7c478bd9Sstevel@tonic-gate */ 1167*7c478bd9Sstevel@tonic-gate static void 1168*7c478bd9Sstevel@tonic-gate kill_script(script_info_t *rsi) 1169*7c478bd9Sstevel@tonic-gate { 1170*7c478bd9Sstevel@tonic-gate if (rsi->pid > 1) { 1171*7c478bd9Sstevel@tonic-gate (void) kill_pid(rsi->pid); 1172*7c478bd9Sstevel@tonic-gate script_exited(rsi); 1173*7c478bd9Sstevel@tonic-gate remove_drreq_all(rsi); 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate } 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate /* 1178*7c478bd9Sstevel@tonic-gate * Convert rcm flags parameter to a string. 1179*7c478bd9Sstevel@tonic-gate * Used for debug prints. 1180*7c478bd9Sstevel@tonic-gate */ 1181*7c478bd9Sstevel@tonic-gate static char * 1182*7c478bd9Sstevel@tonic-gate flags_to_name(int flags, char *buf, int maxbuflen) 1183*7c478bd9Sstevel@tonic-gate { 1184*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, maxbuflen, "%s%s", 1185*7c478bd9Sstevel@tonic-gate (flags & RCM_QUERY) ? "RCM_QUERY " : "", 1186*7c478bd9Sstevel@tonic-gate (flags & RCM_FORCE) ? "RCM_FORCE" : ""); 1187*7c478bd9Sstevel@tonic-gate 1188*7c478bd9Sstevel@tonic-gate return (buf); 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate 1191*7c478bd9Sstevel@tonic-gate static void 1192*7c478bd9Sstevel@tonic-gate fill_argv(script_info_t *rsi, char *argv[], char *resource_name) 1193*7c478bd9Sstevel@tonic-gate { 1194*7c478bd9Sstevel@tonic-gate argv[0] = rsi->script_full_name; 1195*7c478bd9Sstevel@tonic-gate argv[1] = script_cmd_name[rsi->cmd]; 1196*7c478bd9Sstevel@tonic-gate if (resource_name) { 1197*7c478bd9Sstevel@tonic-gate argv[2] = resource_name; 1198*7c478bd9Sstevel@tonic-gate argv[3] = NULL; 1199*7c478bd9Sstevel@tonic-gate } else 1200*7c478bd9Sstevel@tonic-gate argv[2] = NULL; 1201*7c478bd9Sstevel@tonic-gate } 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate /* 1204*7c478bd9Sstevel@tonic-gate * stderr thread: 1205*7c478bd9Sstevel@tonic-gate * Reads stderr and logs to syslog. 1206*7c478bd9Sstevel@tonic-gate * Runs as a separate thread. 1207*7c478bd9Sstevel@tonic-gate */ 1208*7c478bd9Sstevel@tonic-gate static void * 1209*7c478bd9Sstevel@tonic-gate read_stderr(script_info_t *rsi) 1210*7c478bd9Sstevel@tonic-gate { 1211*7c478bd9Sstevel@tonic-gate char buf[MAX_LINE_LEN]; 1212*7c478bd9Sstevel@tonic-gate size_t buflen; 1213*7c478bd9Sstevel@tonic-gate int error_num; 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate while ((get_line(rsi->pipe2[PARENT_END_OF_PIPE], "stderr", 1216*7c478bd9Sstevel@tonic-gate buf, MAX_LINE_LEN, &buflen, 0, &error_num)) == 0) { 1217*7c478bd9Sstevel@tonic-gate log_msg(rsi, RCM_ERROR, buf); 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate if (buflen) 1221*7c478bd9Sstevel@tonic-gate log_msg(rsi, RCM_ERROR, buf); 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate return (NULL); 1224*7c478bd9Sstevel@tonic-gate } 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate /* process return data items passed by scripts to the framework */ 1227*7c478bd9Sstevel@tonic-gate static int 1228*7c478bd9Sstevel@tonic-gate process_dataitem(script_info_t *rsi, int token, char *value, char **errmsg) 1229*7c478bd9Sstevel@tonic-gate { 1230*7c478bd9Sstevel@tonic-gate char *ptr; 1231*7c478bd9Sstevel@tonic-gate int status; 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate *errmsg = NULL; 1234*7c478bd9Sstevel@tonic-gate 1235*7c478bd9Sstevel@tonic-gate if (*value == '\0') 1236*7c478bd9Sstevel@tonic-gate goto error; 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate switch (token) { 1239*7c478bd9Sstevel@tonic-gate case D_SCRIPT_VERSION: 1240*7c478bd9Sstevel@tonic-gate if (rsi->cmd != C_SCRIPTINFO) 1241*7c478bd9Sstevel@tonic-gate goto error; 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate /* check that value contains only digits */ 1244*7c478bd9Sstevel@tonic-gate for (ptr = value; *ptr != '\0'; ptr++) 1245*7c478bd9Sstevel@tonic-gate if (isdigit((int)(*ptr)) == 0) 1246*7c478bd9Sstevel@tonic-gate break; 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate if (*ptr == '\0') 1249*7c478bd9Sstevel@tonic-gate rsi->ver = atoi(value); 1250*7c478bd9Sstevel@tonic-gate else 1251*7c478bd9Sstevel@tonic-gate goto error; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate break; 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate case D_SCRIPT_FUNC_INFO: 1256*7c478bd9Sstevel@tonic-gate if (rsi->cmd != C_SCRIPTINFO) 1257*7c478bd9Sstevel@tonic-gate goto error; 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&rsi->func_info_buf, 1260*7c478bd9Sstevel@tonic-gate &rsi->func_info_buf_len, 1261*7c478bd9Sstevel@tonic-gate &rsi->func_info_buf_curptr, 1262*7c478bd9Sstevel@tonic-gate "%s", value); 1263*7c478bd9Sstevel@tonic-gate break; 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate case D_CMD_TIMEOUT: 1266*7c478bd9Sstevel@tonic-gate if (rsi->cmd != C_SCRIPTINFO) 1267*7c478bd9Sstevel@tonic-gate goto error; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate /* check that value contains only digits */ 1270*7c478bd9Sstevel@tonic-gate for (ptr = value; *ptr != '\0'; ptr++) 1271*7c478bd9Sstevel@tonic-gate if (isdigit((int)(*ptr)) == 0) 1272*7c478bd9Sstevel@tonic-gate break; 1273*7c478bd9Sstevel@tonic-gate 1274*7c478bd9Sstevel@tonic-gate if (*ptr == '\0') 1275*7c478bd9Sstevel@tonic-gate rsi->cmd_timeout = atoi(value); 1276*7c478bd9Sstevel@tonic-gate else 1277*7c478bd9Sstevel@tonic-gate goto error; 1278*7c478bd9Sstevel@tonic-gate break; 1279*7c478bd9Sstevel@tonic-gate 1280*7c478bd9Sstevel@tonic-gate case D_RESOURCE_NAME: 1281*7c478bd9Sstevel@tonic-gate if (rsi->cmd != C_REGISTER) 1282*7c478bd9Sstevel@tonic-gate goto error; 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate if (get_capacity_descr(value) != NULL) 1285*7c478bd9Sstevel@tonic-gate status = rcm_register_capacity(rsi->hdl, value, 1286*7c478bd9Sstevel@tonic-gate 0, NULL); 1287*7c478bd9Sstevel@tonic-gate else 1288*7c478bd9Sstevel@tonic-gate status = rcm_register_interest(rsi->hdl, value, 0, 1289*7c478bd9Sstevel@tonic-gate NULL); 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate if (status == RCM_FAILURE && errno == EALREADY) 1292*7c478bd9Sstevel@tonic-gate status = RCM_SUCCESS; 1293*7c478bd9Sstevel@tonic-gate 1294*7c478bd9Sstevel@tonic-gate if (status != RCM_SUCCESS) { 1295*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MS_REGISTER_RSRC_ERR, 1296*7c478bd9Sstevel@tonic-gate rsi->script_name, value); 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate remove_from_unregister(rsi, value); 1300*7c478bd9Sstevel@tonic-gate break; 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate case D_RESOURCE_USAGE_INFO: 1303*7c478bd9Sstevel@tonic-gate if (rsi->cmd != C_RESOURCEINFO) 1304*7c478bd9Sstevel@tonic-gate goto error; 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&rsi->resource_usage_info_buf, 1307*7c478bd9Sstevel@tonic-gate &rsi->resource_usage_info_buf_len, 1308*7c478bd9Sstevel@tonic-gate &rsi->resource_usage_info_buf_curptr, 1309*7c478bd9Sstevel@tonic-gate "%s", value); 1310*7c478bd9Sstevel@tonic-gate break; 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate case D_FAILURE_REASON: 1313*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&rsi->failure_reason_buf, 1314*7c478bd9Sstevel@tonic-gate &rsi->failure_reason_buf_len, 1315*7c478bd9Sstevel@tonic-gate &rsi->failure_reason_buf_curptr, 1316*7c478bd9Sstevel@tonic-gate "%s", value); 1317*7c478bd9Sstevel@tonic-gate break; 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate default: 1320*7c478bd9Sstevel@tonic-gate goto error; 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate 1323*7c478bd9Sstevel@tonic-gate return (0); 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate error: 1326*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MS_PROTOCOL_ERR, rsi->script_name); 1327*7c478bd9Sstevel@tonic-gate return (-1); 1328*7c478bd9Sstevel@tonic-gate } 1329*7c478bd9Sstevel@tonic-gate 1330*7c478bd9Sstevel@tonic-gate /* Send the given command to the script and process return data */ 1331*7c478bd9Sstevel@tonic-gate static int 1332*7c478bd9Sstevel@tonic-gate do_cmd(script_info_t *rsi, char *argv[], char *envp[], char **errmsg) 1333*7c478bd9Sstevel@tonic-gate { 1334*7c478bd9Sstevel@tonic-gate char buf[MAX_LINE_LEN]; 1335*7c478bd9Sstevel@tonic-gate size_t buflen; 1336*7c478bd9Sstevel@tonic-gate int loglevel = -1, continuelog = 0; 1337*7c478bd9Sstevel@tonic-gate char *ptr, *dname, *value; 1338*7c478bd9Sstevel@tonic-gate time_t maxsecs; 1339*7c478bd9Sstevel@tonic-gate time_t deadline; 1340*7c478bd9Sstevel@tonic-gate int sigaborted = 0; 1341*7c478bd9Sstevel@tonic-gate int rval, child_status, token; 1342*7c478bd9Sstevel@tonic-gate int error_num; 1343*7c478bd9Sstevel@tonic-gate int cmd_timeout = rsi->cmd_timeout; 1344*7c478bd9Sstevel@tonic-gate 1345*7c478bd9Sstevel@tonic-gate *errmsg = NULL; 1346*7c478bd9Sstevel@tonic-gate 1347*7c478bd9Sstevel@tonic-gate script_process_sema_wait(); 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate if (run_script(rsi, argv, envp, errmsg) == -1) { 1350*7c478bd9Sstevel@tonic-gate (void) sema_post(&script_process_sema); 1351*7c478bd9Sstevel@tonic-gate goto error2; 1352*7c478bd9Sstevel@tonic-gate } 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate (void) time(&rsi->lastrun); 1355*7c478bd9Sstevel@tonic-gate deadline = rsi->lastrun + cmd_timeout; 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate if (thr_create(NULL, 0, (void *(*)(void *))read_stderr, rsi, 1358*7c478bd9Sstevel@tonic-gate 0, &rsi->tid) != 0) { 1359*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MF_FUNC_CALL_ERR, 1360*7c478bd9Sstevel@tonic-gate "thr_create", strerror(errno)); 1361*7c478bd9Sstevel@tonic-gate goto error1; 1362*7c478bd9Sstevel@tonic-gate } 1363*7c478bd9Sstevel@tonic-gate rsi->flags |= STDERR_THREAD_CREATED; 1364*7c478bd9Sstevel@tonic-gate 1365*7c478bd9Sstevel@tonic-gate /* LINTED */ 1366*7c478bd9Sstevel@tonic-gate while (1) { 1367*7c478bd9Sstevel@tonic-gate if (cmd_timeout > 0) { 1368*7c478bd9Sstevel@tonic-gate maxsecs = deadline - time(NULL); 1369*7c478bd9Sstevel@tonic-gate if (maxsecs <= 0) 1370*7c478bd9Sstevel@tonic-gate goto timedout; 1371*7c478bd9Sstevel@tonic-gate } else 1372*7c478bd9Sstevel@tonic-gate maxsecs = 0; 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate rval = get_line(rsi->pipe1[PARENT_END_OF_PIPE], 1375*7c478bd9Sstevel@tonic-gate "stdout", buf, MAX_LINE_LEN, &buflen, 1376*7c478bd9Sstevel@tonic-gate maxsecs, &error_num); 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate if (buflen) { 1379*7c478bd9Sstevel@tonic-gate if (continuelog) 1380*7c478bd9Sstevel@tonic-gate log_msg(rsi, loglevel, buf); 1381*7c478bd9Sstevel@tonic-gate else { 1382*7c478bd9Sstevel@tonic-gate if ((ptr = strchr(buf, '=')) == NULL) 1383*7c478bd9Sstevel@tonic-gate goto error; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate *ptr = '\0'; 1386*7c478bd9Sstevel@tonic-gate dname = buf; 1387*7c478bd9Sstevel@tonic-gate value = ptr + 1; 1388*7c478bd9Sstevel@tonic-gate if ((token = dname_to_id(dname)) == -1) 1389*7c478bd9Sstevel@tonic-gate goto error; 1390*7c478bd9Sstevel@tonic-gate 1391*7c478bd9Sstevel@tonic-gate switch (token) { 1392*7c478bd9Sstevel@tonic-gate case D_LOG_ERR: 1393*7c478bd9Sstevel@tonic-gate loglevel = RCM_ERROR; 1394*7c478bd9Sstevel@tonic-gate break; 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate case D_LOG_WARN: 1397*7c478bd9Sstevel@tonic-gate loglevel = RCM_WARNING; 1398*7c478bd9Sstevel@tonic-gate break; 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate case D_LOG_INFO: 1401*7c478bd9Sstevel@tonic-gate loglevel = RCM_INFO; 1402*7c478bd9Sstevel@tonic-gate break; 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate case D_LOG_DEBUG: 1405*7c478bd9Sstevel@tonic-gate loglevel = RCM_DEBUG; 1406*7c478bd9Sstevel@tonic-gate break; 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate default: 1409*7c478bd9Sstevel@tonic-gate loglevel = -1; 1410*7c478bd9Sstevel@tonic-gate break; 1411*7c478bd9Sstevel@tonic-gate } 1412*7c478bd9Sstevel@tonic-gate 1413*7c478bd9Sstevel@tonic-gate if (loglevel != -1) { 1414*7c478bd9Sstevel@tonic-gate log_msg(rsi, loglevel, value); 1415*7c478bd9Sstevel@tonic-gate if (buf[buflen - 1] == '\n') 1416*7c478bd9Sstevel@tonic-gate continuelog = 0; 1417*7c478bd9Sstevel@tonic-gate else 1418*7c478bd9Sstevel@tonic-gate continuelog = 1; 1419*7c478bd9Sstevel@tonic-gate } else { 1420*7c478bd9Sstevel@tonic-gate if (buf[buflen - 1] != '\n') 1421*7c478bd9Sstevel@tonic-gate goto error; 1422*7c478bd9Sstevel@tonic-gate 1423*7c478bd9Sstevel@tonic-gate buf[buflen - 1] = '\0'; 1424*7c478bd9Sstevel@tonic-gate if (process_dataitem(rsi, token, 1425*7c478bd9Sstevel@tonic-gate value, errmsg) != 0) 1426*7c478bd9Sstevel@tonic-gate goto error1; 1427*7c478bd9Sstevel@tonic-gate } 1428*7c478bd9Sstevel@tonic-gate } 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate if (rval == -3) { 1432*7c478bd9Sstevel@tonic-gate /* script exited */ 1433*7c478bd9Sstevel@tonic-gate waitagain: 1434*7c478bd9Sstevel@tonic-gate if (waitpid(rsi->pid, &child_status, 0) 1435*7c478bd9Sstevel@tonic-gate != rsi->pid) { 1436*7c478bd9Sstevel@tonic-gate if (errno == EINTR || errno == EAGAIN) 1437*7c478bd9Sstevel@tonic-gate goto waitagain; 1438*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MS_SCRIPT_ERR, 1439*7c478bd9Sstevel@tonic-gate rsi->script_name, strerror(errno)); 1440*7c478bd9Sstevel@tonic-gate goto error1; 1441*7c478bd9Sstevel@tonic-gate } 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate if (WIFEXITED(child_status)) { 1444*7c478bd9Sstevel@tonic-gate script_exited(rsi); 1445*7c478bd9Sstevel@tonic-gate rsi->exit_status = WEXITSTATUS(child_status); 1446*7c478bd9Sstevel@tonic-gate } else { 1447*7c478bd9Sstevel@tonic-gate if (sigaborted) 1448*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, 1449*7c478bd9Sstevel@tonic-gate MS_TIMEOUT_ERR, rsi->script_name); 1450*7c478bd9Sstevel@tonic-gate else 1451*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, 1452*7c478bd9Sstevel@tonic-gate MS_UNKNOWN_ERR, rsi->script_name); 1453*7c478bd9Sstevel@tonic-gate 1454*7c478bd9Sstevel@tonic-gate /* kill any remaining processes in the pgrp */ 1455*7c478bd9Sstevel@tonic-gate (void) kill(-(rsi->pid), SIGKILL); 1456*7c478bd9Sstevel@tonic-gate script_exited(rsi); 1457*7c478bd9Sstevel@tonic-gate goto error2; 1458*7c478bd9Sstevel@tonic-gate } 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate break; 1461*7c478bd9Sstevel@tonic-gate } 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate if (rval == -1) { 1464*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MS_SCRIPT_ERR, 1465*7c478bd9Sstevel@tonic-gate rsi->script_name, strerror(errno)); 1466*7c478bd9Sstevel@tonic-gate goto error1; 1467*7c478bd9Sstevel@tonic-gate } 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate if (rval == -2) { 1470*7c478bd9Sstevel@tonic-gate timedout: 1471*7c478bd9Sstevel@tonic-gate /* timeout occurred */ 1472*7c478bd9Sstevel@tonic-gate if (sigaborted == 0) { 1473*7c478bd9Sstevel@tonic-gate (void) kill(rsi->pid, SIGABRT); 1474*7c478bd9Sstevel@tonic-gate sigaborted = 1; 1475*7c478bd9Sstevel@tonic-gate /* extend deadline */ 1476*7c478bd9Sstevel@tonic-gate deadline += SCRIPT_ABORT_TIMEOUT; 1477*7c478bd9Sstevel@tonic-gate } else { 1478*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, 1479*7c478bd9Sstevel@tonic-gate MS_TIMEOUT_ERR, rsi->script_name); 1480*7c478bd9Sstevel@tonic-gate goto error1; 1481*7c478bd9Sstevel@tonic-gate } 1482*7c478bd9Sstevel@tonic-gate } 1483*7c478bd9Sstevel@tonic-gate } 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate return (0); 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate error: 1488*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MS_PROTOCOL_ERR, rsi->script_name); 1489*7c478bd9Sstevel@tonic-gate 1490*7c478bd9Sstevel@tonic-gate error1: 1491*7c478bd9Sstevel@tonic-gate kill_script(rsi); 1492*7c478bd9Sstevel@tonic-gate 1493*7c478bd9Sstevel@tonic-gate error2: 1494*7c478bd9Sstevel@tonic-gate return (-1); 1495*7c478bd9Sstevel@tonic-gate } 1496*7c478bd9Sstevel@tonic-gate 1497*7c478bd9Sstevel@tonic-gate static int 1498*7c478bd9Sstevel@tonic-gate do_script_info(script_info_t *rsi) 1499*7c478bd9Sstevel@tonic-gate { 1500*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 1501*7c478bd9Sstevel@tonic-gate int status = RCM_FAILURE; 1502*7c478bd9Sstevel@tonic-gate int err = 0; 1503*7c478bd9Sstevel@tonic-gate char *errmsg = NULL; 1504*7c478bd9Sstevel@tonic-gate 1505*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "do_script_info: script name = %s\n", 1506*7c478bd9Sstevel@tonic-gate rsi->script_name); 1507*7c478bd9Sstevel@tonic-gate 1508*7c478bd9Sstevel@tonic-gate rsi->cmd = C_SCRIPTINFO; 1509*7c478bd9Sstevel@tonic-gate rsi->func_info_buf = NULL; 1510*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf = NULL; 1511*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, NULL); 1512*7c478bd9Sstevel@tonic-gate 1513*7c478bd9Sstevel@tonic-gate if (do_cmd(rsi, argv, script_env, &errmsg) == 0) { 1514*7c478bd9Sstevel@tonic-gate switch (rsi->exit_status) { 1515*7c478bd9Sstevel@tonic-gate case E_SUCCESS: 1516*7c478bd9Sstevel@tonic-gate if (rsi->func_info_buf != NULL && 1517*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf == NULL) { 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate if (rsi->ver >= SCRIPT_API_MIN_VER && 1520*7c478bd9Sstevel@tonic-gate rsi->ver <= SCRIPT_API_MAX_VER) 1521*7c478bd9Sstevel@tonic-gate status = RCM_SUCCESS; 1522*7c478bd9Sstevel@tonic-gate else 1523*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 1524*7c478bd9Sstevel@tonic-gate MS_UNSUPPORTED_VER, rsi->script_name, 1525*7c478bd9Sstevel@tonic-gate rsi->ver); 1526*7c478bd9Sstevel@tonic-gate } else 1527*7c478bd9Sstevel@tonic-gate err = 1; 1528*7c478bd9Sstevel@tonic-gate break; 1529*7c478bd9Sstevel@tonic-gate 1530*7c478bd9Sstevel@tonic-gate case E_FAILURE: 1531*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf != NULL) { 1532*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MS_SCRIPTINFO_ERR, 1533*7c478bd9Sstevel@tonic-gate rsi->script_name, 1534*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf); 1535*7c478bd9Sstevel@tonic-gate } else 1536*7c478bd9Sstevel@tonic-gate err = 1; 1537*7c478bd9Sstevel@tonic-gate break; 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate default: 1540*7c478bd9Sstevel@tonic-gate err = 1; 1541*7c478bd9Sstevel@tonic-gate break; 1542*7c478bd9Sstevel@tonic-gate } 1543*7c478bd9Sstevel@tonic-gate if (err) 1544*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MS_PROTOCOL_ERR, 1545*7c478bd9Sstevel@tonic-gate rsi->script_name); 1546*7c478bd9Sstevel@tonic-gate } else if (errmsg) 1547*7c478bd9Sstevel@tonic-gate (void) free(errmsg); 1548*7c478bd9Sstevel@tonic-gate 1549*7c478bd9Sstevel@tonic-gate if (status != RCM_SUCCESS && rsi->func_info_buf != NULL) 1550*7c478bd9Sstevel@tonic-gate free(rsi->func_info_buf); 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf) 1553*7c478bd9Sstevel@tonic-gate free(rsi->failure_reason_buf); 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate return (status); 1556*7c478bd9Sstevel@tonic-gate } 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate static int 1559*7c478bd9Sstevel@tonic-gate do_dr(script_info_t *rsi, char *argv[], char *envp[], char **info) 1560*7c478bd9Sstevel@tonic-gate { 1561*7c478bd9Sstevel@tonic-gate int status = RCM_FAILURE; 1562*7c478bd9Sstevel@tonic-gate int err = 0; 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf = NULL; 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate if (do_cmd(rsi, argv, envp, info) == 0) { 1567*7c478bd9Sstevel@tonic-gate switch (rsi->exit_status) { 1568*7c478bd9Sstevel@tonic-gate case E_SUCCESS: 1569*7c478bd9Sstevel@tonic-gate case E_UNSUPPORTED_CMD: 1570*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf == NULL) 1571*7c478bd9Sstevel@tonic-gate status = RCM_SUCCESS; 1572*7c478bd9Sstevel@tonic-gate else 1573*7c478bd9Sstevel@tonic-gate err = 1; 1574*7c478bd9Sstevel@tonic-gate break; 1575*7c478bd9Sstevel@tonic-gate 1576*7c478bd9Sstevel@tonic-gate case E_FAILURE: 1577*7c478bd9Sstevel@tonic-gate case E_REFUSE: 1578*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf != NULL) { 1579*7c478bd9Sstevel@tonic-gate *info = rsi->failure_reason_buf; 1580*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf = NULL; 1581*7c478bd9Sstevel@tonic-gate } else 1582*7c478bd9Sstevel@tonic-gate err = 1; 1583*7c478bd9Sstevel@tonic-gate break; 1584*7c478bd9Sstevel@tonic-gate 1585*7c478bd9Sstevel@tonic-gate default: 1586*7c478bd9Sstevel@tonic-gate err = 1; 1587*7c478bd9Sstevel@tonic-gate break; 1588*7c478bd9Sstevel@tonic-gate } 1589*7c478bd9Sstevel@tonic-gate 1590*7c478bd9Sstevel@tonic-gate if (err) 1591*7c478bd9Sstevel@tonic-gate *info = dup_err(RCM_ERROR, MS_PROTOCOL_ERR, 1592*7c478bd9Sstevel@tonic-gate rsi->script_name); 1593*7c478bd9Sstevel@tonic-gate } 1594*7c478bd9Sstevel@tonic-gate 1595*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf) 1596*7c478bd9Sstevel@tonic-gate free(rsi->failure_reason_buf); 1597*7c478bd9Sstevel@tonic-gate 1598*7c478bd9Sstevel@tonic-gate return (status); 1599*7c478bd9Sstevel@tonic-gate } 1600*7c478bd9Sstevel@tonic-gate 1601*7c478bd9Sstevel@tonic-gate /* 1602*7c478bd9Sstevel@tonic-gate * get_info entry point 1603*7c478bd9Sstevel@tonic-gate */ 1604*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1605*7c478bd9Sstevel@tonic-gate static int 1606*7c478bd9Sstevel@tonic-gate script_get_info(rcm_handle_t *hdl, 1607*7c478bd9Sstevel@tonic-gate char *resource_name, 1608*7c478bd9Sstevel@tonic-gate pid_t pid, 1609*7c478bd9Sstevel@tonic-gate uint_t flag, 1610*7c478bd9Sstevel@tonic-gate char **info, 1611*7c478bd9Sstevel@tonic-gate char **error, 1612*7c478bd9Sstevel@tonic-gate nvlist_t *props, 1613*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 1614*7c478bd9Sstevel@tonic-gate { 1615*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 1616*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 1617*7c478bd9Sstevel@tonic-gate int status = RCM_FAILURE; 1618*7c478bd9Sstevel@tonic-gate int err = 0; 1619*7c478bd9Sstevel@tonic-gate 1620*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_get_info: resource = %s\n", 1621*7c478bd9Sstevel@tonic-gate resource_name); 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate *info = NULL; 1624*7c478bd9Sstevel@tonic-gate *error = NULL; 1625*7c478bd9Sstevel@tonic-gate 1626*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 1627*7c478bd9Sstevel@tonic-gate 1628*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 1629*7c478bd9Sstevel@tonic-gate rsi->cmd = C_RESOURCEINFO; 1630*7c478bd9Sstevel@tonic-gate rsi->resource_usage_info_buf = NULL; 1631*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf = NULL; 1632*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate if (do_cmd(rsi, argv, script_env, error) == 0) { 1635*7c478bd9Sstevel@tonic-gate switch (rsi->exit_status) { 1636*7c478bd9Sstevel@tonic-gate case E_SUCCESS: 1637*7c478bd9Sstevel@tonic-gate if (rsi->resource_usage_info_buf != NULL && 1638*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf == NULL) { 1639*7c478bd9Sstevel@tonic-gate 1640*7c478bd9Sstevel@tonic-gate *info = rsi->resource_usage_info_buf; 1641*7c478bd9Sstevel@tonic-gate rsi->resource_usage_info_buf = NULL; 1642*7c478bd9Sstevel@tonic-gate status = RCM_SUCCESS; 1643*7c478bd9Sstevel@tonic-gate } else 1644*7c478bd9Sstevel@tonic-gate err = 1; 1645*7c478bd9Sstevel@tonic-gate break; 1646*7c478bd9Sstevel@tonic-gate 1647*7c478bd9Sstevel@tonic-gate case E_FAILURE: 1648*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf != NULL) { 1649*7c478bd9Sstevel@tonic-gate *error = rsi->failure_reason_buf; 1650*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf = NULL; 1651*7c478bd9Sstevel@tonic-gate } else 1652*7c478bd9Sstevel@tonic-gate err = 1; 1653*7c478bd9Sstevel@tonic-gate break; 1654*7c478bd9Sstevel@tonic-gate 1655*7c478bd9Sstevel@tonic-gate default: 1656*7c478bd9Sstevel@tonic-gate err = 1; 1657*7c478bd9Sstevel@tonic-gate break; 1658*7c478bd9Sstevel@tonic-gate } 1659*7c478bd9Sstevel@tonic-gate if (err) 1660*7c478bd9Sstevel@tonic-gate *error = dup_err(RCM_ERROR, MS_PROTOCOL_ERR, 1661*7c478bd9Sstevel@tonic-gate rsi->script_name); 1662*7c478bd9Sstevel@tonic-gate } 1663*7c478bd9Sstevel@tonic-gate 1664*7c478bd9Sstevel@tonic-gate if (rsi->resource_usage_info_buf) 1665*7c478bd9Sstevel@tonic-gate free(rsi->resource_usage_info_buf); 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf) 1668*7c478bd9Sstevel@tonic-gate free(rsi->failure_reason_buf); 1669*7c478bd9Sstevel@tonic-gate 1670*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 1671*7c478bd9Sstevel@tonic-gate 1672*7c478bd9Sstevel@tonic-gate return (status); 1673*7c478bd9Sstevel@tonic-gate } 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate static void 1676*7c478bd9Sstevel@tonic-gate add_for_unregister(script_info_t *rsi) 1677*7c478bd9Sstevel@tonic-gate { 1678*7c478bd9Sstevel@tonic-gate module_t *module = rsi->module; 1679*7c478bd9Sstevel@tonic-gate client_t *client; 1680*7c478bd9Sstevel@tonic-gate rcm_queue_t *head; 1681*7c478bd9Sstevel@tonic-gate rcm_queue_t *q; 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rcm_req_lock); 1684*7c478bd9Sstevel@tonic-gate 1685*7c478bd9Sstevel@tonic-gate head = &module->client_q; 1686*7c478bd9Sstevel@tonic-gate 1687*7c478bd9Sstevel@tonic-gate for (q = head->next; q != head; q = q->next) { 1688*7c478bd9Sstevel@tonic-gate client = RCM_STRUCT_BASE_ADDR(client_t, q, queue); 1689*7c478bd9Sstevel@tonic-gate client->prv_flags |= RCM_NEED_TO_UNREGISTER; 1690*7c478bd9Sstevel@tonic-gate } 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rcm_req_lock); 1693*7c478bd9Sstevel@tonic-gate } 1694*7c478bd9Sstevel@tonic-gate 1695*7c478bd9Sstevel@tonic-gate static void 1696*7c478bd9Sstevel@tonic-gate remove_from_unregister(script_info_t *rsi, char *resource_name) 1697*7c478bd9Sstevel@tonic-gate { 1698*7c478bd9Sstevel@tonic-gate module_t *module = rsi->module; 1699*7c478bd9Sstevel@tonic-gate client_t *client; 1700*7c478bd9Sstevel@tonic-gate rcm_queue_t *head; 1701*7c478bd9Sstevel@tonic-gate rcm_queue_t *q; 1702*7c478bd9Sstevel@tonic-gate 1703*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rcm_req_lock); 1704*7c478bd9Sstevel@tonic-gate 1705*7c478bd9Sstevel@tonic-gate head = &module->client_q; 1706*7c478bd9Sstevel@tonic-gate 1707*7c478bd9Sstevel@tonic-gate for (q = head->next; q != head; q = q->next) { 1708*7c478bd9Sstevel@tonic-gate client = RCM_STRUCT_BASE_ADDR(client_t, q, queue); 1709*7c478bd9Sstevel@tonic-gate if (strcmp(client->alias, resource_name) == 0) { 1710*7c478bd9Sstevel@tonic-gate client->prv_flags &= ~RCM_NEED_TO_UNREGISTER; 1711*7c478bd9Sstevel@tonic-gate break; 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate 1715*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rcm_req_lock); 1716*7c478bd9Sstevel@tonic-gate } 1717*7c478bd9Sstevel@tonic-gate 1718*7c478bd9Sstevel@tonic-gate static void 1719*7c478bd9Sstevel@tonic-gate complete_unregister(script_info_t *rsi) 1720*7c478bd9Sstevel@tonic-gate { 1721*7c478bd9Sstevel@tonic-gate module_t *module = rsi->module; 1722*7c478bd9Sstevel@tonic-gate client_t *client; 1723*7c478bd9Sstevel@tonic-gate rcm_queue_t *head; 1724*7c478bd9Sstevel@tonic-gate rcm_queue_t *q; 1725*7c478bd9Sstevel@tonic-gate 1726*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rcm_req_lock); 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate head = &module->client_q; 1729*7c478bd9Sstevel@tonic-gate 1730*7c478bd9Sstevel@tonic-gate for (q = head->next; q != head; q = q->next) { 1731*7c478bd9Sstevel@tonic-gate client = RCM_STRUCT_BASE_ADDR(client_t, q, queue); 1732*7c478bd9Sstevel@tonic-gate if (client->prv_flags & RCM_NEED_TO_UNREGISTER) { 1733*7c478bd9Sstevel@tonic-gate client->prv_flags &= ~RCM_NEED_TO_UNREGISTER; 1734*7c478bd9Sstevel@tonic-gate client->state = RCM_STATE_REMOVE; 1735*7c478bd9Sstevel@tonic-gate } 1736*7c478bd9Sstevel@tonic-gate } 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rcm_req_lock); 1739*7c478bd9Sstevel@tonic-gate } 1740*7c478bd9Sstevel@tonic-gate 1741*7c478bd9Sstevel@tonic-gate /* 1742*7c478bd9Sstevel@tonic-gate * register_interest entry point 1743*7c478bd9Sstevel@tonic-gate */ 1744*7c478bd9Sstevel@tonic-gate static int 1745*7c478bd9Sstevel@tonic-gate script_register_interest(rcm_handle_t *hdl) 1746*7c478bd9Sstevel@tonic-gate { 1747*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 1748*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 1749*7c478bd9Sstevel@tonic-gate int status = RCM_FAILURE; 1750*7c478bd9Sstevel@tonic-gate int err = 0; 1751*7c478bd9Sstevel@tonic-gate char *errmsg = NULL; 1752*7c478bd9Sstevel@tonic-gate 1753*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 1754*7c478bd9Sstevel@tonic-gate "script_register_interest: script name = %s\n", 1755*7c478bd9Sstevel@tonic-gate rsi->script_name); 1756*7c478bd9Sstevel@tonic-gate 1757*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 1758*7c478bd9Sstevel@tonic-gate 1759*7c478bd9Sstevel@tonic-gate if (rsi->drreq_q.next != &rsi->drreq_q) { 1760*7c478bd9Sstevel@tonic-gate /* if DR is already in progress no need to register again */ 1761*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 1762*7c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 1763*7c478bd9Sstevel@tonic-gate } 1764*7c478bd9Sstevel@tonic-gate 1765*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 1766*7c478bd9Sstevel@tonic-gate rsi->cmd = C_REGISTER; 1767*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf = NULL; 1768*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, NULL); 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate add_for_unregister(rsi); 1771*7c478bd9Sstevel@tonic-gate 1772*7c478bd9Sstevel@tonic-gate if (do_cmd(rsi, argv, script_env, &errmsg) == 0) { 1773*7c478bd9Sstevel@tonic-gate switch (rsi->exit_status) { 1774*7c478bd9Sstevel@tonic-gate case E_SUCCESS: 1775*7c478bd9Sstevel@tonic-gate status = RCM_SUCCESS; 1776*7c478bd9Sstevel@tonic-gate break; 1777*7c478bd9Sstevel@tonic-gate 1778*7c478bd9Sstevel@tonic-gate case E_FAILURE: 1779*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf != NULL) { 1780*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MS_REGISTER_ERR, 1781*7c478bd9Sstevel@tonic-gate rsi->script_name, 1782*7c478bd9Sstevel@tonic-gate rsi->failure_reason_buf); 1783*7c478bd9Sstevel@tonic-gate } else 1784*7c478bd9Sstevel@tonic-gate err = 1; 1785*7c478bd9Sstevel@tonic-gate break; 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate default: 1788*7c478bd9Sstevel@tonic-gate err = 1; 1789*7c478bd9Sstevel@tonic-gate break; 1790*7c478bd9Sstevel@tonic-gate } 1791*7c478bd9Sstevel@tonic-gate if (err) 1792*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MS_PROTOCOL_ERR, 1793*7c478bd9Sstevel@tonic-gate rsi->script_name); 1794*7c478bd9Sstevel@tonic-gate } else if (errmsg) 1795*7c478bd9Sstevel@tonic-gate (void) free(errmsg); 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate complete_unregister(rsi); 1798*7c478bd9Sstevel@tonic-gate 1799*7c478bd9Sstevel@tonic-gate if (rsi->failure_reason_buf) 1800*7c478bd9Sstevel@tonic-gate free(rsi->failure_reason_buf); 1801*7c478bd9Sstevel@tonic-gate 1802*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate return (status); 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate /* 1808*7c478bd9Sstevel@tonic-gate * Add the specified resource name to the drreq_q. 1809*7c478bd9Sstevel@tonic-gate */ 1810*7c478bd9Sstevel@tonic-gate static void 1811*7c478bd9Sstevel@tonic-gate add_drreq(script_info_t *rsi, char *resource_name) 1812*7c478bd9Sstevel@tonic-gate { 1813*7c478bd9Sstevel@tonic-gate rcm_queue_t *head = &rsi->drreq_q; 1814*7c478bd9Sstevel@tonic-gate rcm_queue_t *q; 1815*7c478bd9Sstevel@tonic-gate drreq_t *drreq; 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate /* check if the dr req is already in the list */ 1818*7c478bd9Sstevel@tonic-gate for (q = head->next; q != head; q = q->next) { 1819*7c478bd9Sstevel@tonic-gate drreq = RCM_STRUCT_BASE_ADDR(drreq_t, q, queue); 1820*7c478bd9Sstevel@tonic-gate if (strcmp(drreq->resource_name, resource_name) == 0) 1821*7c478bd9Sstevel@tonic-gate /* dr req is already present in the queue */ 1822*7c478bd9Sstevel@tonic-gate return; 1823*7c478bd9Sstevel@tonic-gate } 1824*7c478bd9Sstevel@tonic-gate 1825*7c478bd9Sstevel@tonic-gate drreq = (drreq_t *)rcmscript_calloc(1, sizeof (drreq_t)); 1826*7c478bd9Sstevel@tonic-gate drreq->resource_name = rcmscript_strdup(resource_name); 1827*7c478bd9Sstevel@tonic-gate 1828*7c478bd9Sstevel@tonic-gate rcm_enqueue_tail(&rsi->drreq_q, &drreq->queue); 1829*7c478bd9Sstevel@tonic-gate } 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate /* 1832*7c478bd9Sstevel@tonic-gate * Remove the dr req for the specified resource name from the drreq_q. 1833*7c478bd9Sstevel@tonic-gate */ 1834*7c478bd9Sstevel@tonic-gate static void 1835*7c478bd9Sstevel@tonic-gate remove_drreq(script_info_t *rsi, char *resource_name) 1836*7c478bd9Sstevel@tonic-gate { 1837*7c478bd9Sstevel@tonic-gate rcm_queue_t *head = &rsi->drreq_q; 1838*7c478bd9Sstevel@tonic-gate rcm_queue_t *q; 1839*7c478bd9Sstevel@tonic-gate drreq_t *drreq; 1840*7c478bd9Sstevel@tonic-gate 1841*7c478bd9Sstevel@tonic-gate /* search for dr req and remove from the list */ 1842*7c478bd9Sstevel@tonic-gate for (q = head->next; q != head; q = q->next) { 1843*7c478bd9Sstevel@tonic-gate drreq = RCM_STRUCT_BASE_ADDR(drreq_t, q, queue); 1844*7c478bd9Sstevel@tonic-gate if (strcmp(drreq->resource_name, resource_name) == 0) 1845*7c478bd9Sstevel@tonic-gate break; 1846*7c478bd9Sstevel@tonic-gate } 1847*7c478bd9Sstevel@tonic-gate 1848*7c478bd9Sstevel@tonic-gate if (q != head) { 1849*7c478bd9Sstevel@tonic-gate /* found drreq on the queue */ 1850*7c478bd9Sstevel@tonic-gate rcm_dequeue(&drreq->queue); 1851*7c478bd9Sstevel@tonic-gate free(drreq->resource_name); 1852*7c478bd9Sstevel@tonic-gate free(drreq); 1853*7c478bd9Sstevel@tonic-gate } 1854*7c478bd9Sstevel@tonic-gate } 1855*7c478bd9Sstevel@tonic-gate 1856*7c478bd9Sstevel@tonic-gate /* 1857*7c478bd9Sstevel@tonic-gate * Remove all dr req's. 1858*7c478bd9Sstevel@tonic-gate */ 1859*7c478bd9Sstevel@tonic-gate static void 1860*7c478bd9Sstevel@tonic-gate remove_drreq_all(script_info_t *rsi) 1861*7c478bd9Sstevel@tonic-gate { 1862*7c478bd9Sstevel@tonic-gate drreq_t *drreq; 1863*7c478bd9Sstevel@tonic-gate 1864*7c478bd9Sstevel@tonic-gate while (rsi->drreq_q.next != &rsi->drreq_q) { 1865*7c478bd9Sstevel@tonic-gate drreq = RCM_STRUCT_BASE_ADDR(drreq_t, 1866*7c478bd9Sstevel@tonic-gate rsi->drreq_q.next, queue); 1867*7c478bd9Sstevel@tonic-gate remove_drreq(rsi, drreq->resource_name); 1868*7c478bd9Sstevel@tonic-gate } 1869*7c478bd9Sstevel@tonic-gate } 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate /* 1872*7c478bd9Sstevel@tonic-gate * request_offline entry point 1873*7c478bd9Sstevel@tonic-gate */ 1874*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1875*7c478bd9Sstevel@tonic-gate static int 1876*7c478bd9Sstevel@tonic-gate script_request_offline(rcm_handle_t *hdl, 1877*7c478bd9Sstevel@tonic-gate char *resource_name, 1878*7c478bd9Sstevel@tonic-gate pid_t pid, 1879*7c478bd9Sstevel@tonic-gate uint_t flag, 1880*7c478bd9Sstevel@tonic-gate char **info, 1881*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 1882*7c478bd9Sstevel@tonic-gate { 1883*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 1884*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 1885*7c478bd9Sstevel@tonic-gate char *envp[MAX_ENV_PARAMS]; 1886*7c478bd9Sstevel@tonic-gate char flags_name[MAX_FLAGS_NAME_LEN]; 1887*7c478bd9Sstevel@tonic-gate int status; 1888*7c478bd9Sstevel@tonic-gate int i; 1889*7c478bd9Sstevel@tonic-gate 1890*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 1891*7c478bd9Sstevel@tonic-gate "script_request_offline: resource = %s flags = %s\n", 1892*7c478bd9Sstevel@tonic-gate resource_name, 1893*7c478bd9Sstevel@tonic-gate flags_to_name(flag, flags_name, MAX_FLAGS_NAME_LEN)); 1894*7c478bd9Sstevel@tonic-gate 1895*7c478bd9Sstevel@tonic-gate *info = NULL; 1896*7c478bd9Sstevel@tonic-gate 1897*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 1898*7c478bd9Sstevel@tonic-gate 1899*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 1900*7c478bd9Sstevel@tonic-gate rsi->cmd = (flag & RCM_QUERY) ? C_QUERYREMOVE : C_PREREMOVE; 1901*7c478bd9Sstevel@tonic-gate 1902*7c478bd9Sstevel@tonic-gate if (rsi->cmd == C_PREREMOVE) 1903*7c478bd9Sstevel@tonic-gate add_drreq(rsi, resource_name); 1904*7c478bd9Sstevel@tonic-gate 1905*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 1906*7c478bd9Sstevel@tonic-gate copy_env(script_env, envp); 1907*7c478bd9Sstevel@tonic-gate for (i = 0; envp[i] != NULL; i++) 1908*7c478bd9Sstevel@tonic-gate ; 1909*7c478bd9Sstevel@tonic-gate envp[i++] = (flag & RCM_FORCE) ? script_env_force : script_env_noforce; 1910*7c478bd9Sstevel@tonic-gate envp[i] = NULL; 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, envp, info); 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 1915*7c478bd9Sstevel@tonic-gate return (status); 1916*7c478bd9Sstevel@tonic-gate } 1917*7c478bd9Sstevel@tonic-gate 1918*7c478bd9Sstevel@tonic-gate /* 1919*7c478bd9Sstevel@tonic-gate * notify_online entry point 1920*7c478bd9Sstevel@tonic-gate */ 1921*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1922*7c478bd9Sstevel@tonic-gate static int 1923*7c478bd9Sstevel@tonic-gate script_notify_online(rcm_handle_t *hdl, 1924*7c478bd9Sstevel@tonic-gate char *resource_name, 1925*7c478bd9Sstevel@tonic-gate pid_t pid, 1926*7c478bd9Sstevel@tonic-gate uint_t flag, 1927*7c478bd9Sstevel@tonic-gate char **info, 1928*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 1929*7c478bd9Sstevel@tonic-gate { 1930*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 1931*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 1932*7c478bd9Sstevel@tonic-gate int status; 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_notify_online: resource = %s\n", 1935*7c478bd9Sstevel@tonic-gate resource_name); 1936*7c478bd9Sstevel@tonic-gate 1937*7c478bd9Sstevel@tonic-gate *info = NULL; 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 1940*7c478bd9Sstevel@tonic-gate 1941*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 1942*7c478bd9Sstevel@tonic-gate rsi->cmd = C_UNDOREMOVE; 1943*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, script_env, info); 1946*7c478bd9Sstevel@tonic-gate 1947*7c478bd9Sstevel@tonic-gate remove_drreq(rsi, resource_name); 1948*7c478bd9Sstevel@tonic-gate 1949*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 1950*7c478bd9Sstevel@tonic-gate return (status); 1951*7c478bd9Sstevel@tonic-gate } 1952*7c478bd9Sstevel@tonic-gate 1953*7c478bd9Sstevel@tonic-gate /* 1954*7c478bd9Sstevel@tonic-gate * notify_remove entry point 1955*7c478bd9Sstevel@tonic-gate */ 1956*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1957*7c478bd9Sstevel@tonic-gate static int 1958*7c478bd9Sstevel@tonic-gate script_notify_remove(rcm_handle_t *hdl, 1959*7c478bd9Sstevel@tonic-gate char *resource_name, 1960*7c478bd9Sstevel@tonic-gate pid_t pid, 1961*7c478bd9Sstevel@tonic-gate uint_t flag, 1962*7c478bd9Sstevel@tonic-gate char **info, 1963*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 1964*7c478bd9Sstevel@tonic-gate { 1965*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 1966*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 1967*7c478bd9Sstevel@tonic-gate int status; 1968*7c478bd9Sstevel@tonic-gate 1969*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_notify_remove: resource = %s\n", 1970*7c478bd9Sstevel@tonic-gate resource_name); 1971*7c478bd9Sstevel@tonic-gate 1972*7c478bd9Sstevel@tonic-gate *info = NULL; 1973*7c478bd9Sstevel@tonic-gate 1974*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 1975*7c478bd9Sstevel@tonic-gate 1976*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 1977*7c478bd9Sstevel@tonic-gate rsi->cmd = C_POSTREMOVE; 1978*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, script_env, info); 1981*7c478bd9Sstevel@tonic-gate 1982*7c478bd9Sstevel@tonic-gate remove_drreq(rsi, resource_name); 1983*7c478bd9Sstevel@tonic-gate 1984*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 1985*7c478bd9Sstevel@tonic-gate return (status); 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate /* 1989*7c478bd9Sstevel@tonic-gate * request_suspend entry point 1990*7c478bd9Sstevel@tonic-gate */ 1991*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1992*7c478bd9Sstevel@tonic-gate static int 1993*7c478bd9Sstevel@tonic-gate script_request_suspend(rcm_handle_t *hdl, 1994*7c478bd9Sstevel@tonic-gate char *resource_name, 1995*7c478bd9Sstevel@tonic-gate pid_t pid, 1996*7c478bd9Sstevel@tonic-gate timespec_t *interval, 1997*7c478bd9Sstevel@tonic-gate uint_t flag, 1998*7c478bd9Sstevel@tonic-gate char **info, 1999*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 2000*7c478bd9Sstevel@tonic-gate { 2001*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 2002*7c478bd9Sstevel@tonic-gate char *buf = NULL; 2003*7c478bd9Sstevel@tonic-gate char *curptr = NULL; 2004*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 2005*7c478bd9Sstevel@tonic-gate char *envp[MAX_ENV_PARAMS]; 2006*7c478bd9Sstevel@tonic-gate char flags_name[MAX_FLAGS_NAME_LEN]; 2007*7c478bd9Sstevel@tonic-gate int buflen = 0; 2008*7c478bd9Sstevel@tonic-gate long seconds; 2009*7c478bd9Sstevel@tonic-gate int status; 2010*7c478bd9Sstevel@tonic-gate int i; 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 2013*7c478bd9Sstevel@tonic-gate "script_request_suspend: resource = %s flags = %s\n", resource_name, 2014*7c478bd9Sstevel@tonic-gate flags_to_name(flag, flags_name, MAX_FLAGS_NAME_LEN)); 2015*7c478bd9Sstevel@tonic-gate 2016*7c478bd9Sstevel@tonic-gate *info = NULL; 2017*7c478bd9Sstevel@tonic-gate 2018*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 2021*7c478bd9Sstevel@tonic-gate rsi->cmd = (flag & RCM_QUERY) ? C_QUERYSUSPEND : C_PRESUSPEND; 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate if (rsi->cmd == C_PRESUSPEND) 2024*7c478bd9Sstevel@tonic-gate add_drreq(rsi, resource_name); 2025*7c478bd9Sstevel@tonic-gate 2026*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 2027*7c478bd9Sstevel@tonic-gate 2028*7c478bd9Sstevel@tonic-gate copy_env(script_env, envp); 2029*7c478bd9Sstevel@tonic-gate for (i = 0; envp[i] != NULL; i++); 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate envp[i++] = (flag & RCM_FORCE) ? script_env_force : script_env_noforce; 2032*7c478bd9Sstevel@tonic-gate 2033*7c478bd9Sstevel@tonic-gate if (interval) { 2034*7c478bd9Sstevel@tonic-gate /* 2035*7c478bd9Sstevel@tonic-gate * Merge the seconds and nanoseconds, rounding up if there 2036*7c478bd9Sstevel@tonic-gate * are any remainder nanoseconds. 2037*7c478bd9Sstevel@tonic-gate */ 2038*7c478bd9Sstevel@tonic-gate seconds = interval->tv_sec + (interval->tv_nsec / 1000000000L); 2039*7c478bd9Sstevel@tonic-gate if (interval->tv_nsec % 1000000000L) 2040*7c478bd9Sstevel@tonic-gate seconds += (interval->tv_sec > 0) ? 1L : -1L; 2041*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, script_env_interval, 2042*7c478bd9Sstevel@tonic-gate seconds); 2043*7c478bd9Sstevel@tonic-gate envp[i++] = buf; 2044*7c478bd9Sstevel@tonic-gate } 2045*7c478bd9Sstevel@tonic-gate 2046*7c478bd9Sstevel@tonic-gate envp[i] = NULL; 2047*7c478bd9Sstevel@tonic-gate 2048*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, envp, info); 2049*7c478bd9Sstevel@tonic-gate 2050*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 2051*7c478bd9Sstevel@tonic-gate if (buf) 2052*7c478bd9Sstevel@tonic-gate free(buf); 2053*7c478bd9Sstevel@tonic-gate return (status); 2054*7c478bd9Sstevel@tonic-gate } 2055*7c478bd9Sstevel@tonic-gate 2056*7c478bd9Sstevel@tonic-gate /* 2057*7c478bd9Sstevel@tonic-gate * notify_resume entry point 2058*7c478bd9Sstevel@tonic-gate */ 2059*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2060*7c478bd9Sstevel@tonic-gate static int 2061*7c478bd9Sstevel@tonic-gate script_notify_resume(rcm_handle_t *hdl, 2062*7c478bd9Sstevel@tonic-gate char *resource_name, 2063*7c478bd9Sstevel@tonic-gate pid_t pid, 2064*7c478bd9Sstevel@tonic-gate uint_t flag, 2065*7c478bd9Sstevel@tonic-gate char **info, 2066*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 2067*7c478bd9Sstevel@tonic-gate { 2068*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 2069*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 2070*7c478bd9Sstevel@tonic-gate int status; 2071*7c478bd9Sstevel@tonic-gate 2072*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, "script_notify_resume: resource = %s\n", 2073*7c478bd9Sstevel@tonic-gate resource_name); 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate *info = NULL; 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 2078*7c478bd9Sstevel@tonic-gate 2079*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 2080*7c478bd9Sstevel@tonic-gate rsi->cmd = (flag & RCM_SUSPENDED) ? C_POSTRESUME : C_CANCELSUSPEND; 2081*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, script_env, info); 2084*7c478bd9Sstevel@tonic-gate 2085*7c478bd9Sstevel@tonic-gate remove_drreq(rsi, resource_name); 2086*7c478bd9Sstevel@tonic-gate 2087*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 2088*7c478bd9Sstevel@tonic-gate return (status); 2089*7c478bd9Sstevel@tonic-gate } 2090*7c478bd9Sstevel@tonic-gate 2091*7c478bd9Sstevel@tonic-gate static capacity_descr_t capacity_type[] = { 2092*7c478bd9Sstevel@tonic-gate { "SUNW_memory", MATCH_EXACT, 2093*7c478bd9Sstevel@tonic-gate "new_pages", "RCM_ENV_CAPACITY", 2094*7c478bd9Sstevel@tonic-gate "page_size", "RCM_ENV_UNIT_SIZE", 2095*7c478bd9Sstevel@tonic-gate "", ""}, 2096*7c478bd9Sstevel@tonic-gate { "SUNW_cpu", MATCH_EXACT, 2097*7c478bd9Sstevel@tonic-gate "new_total", "RCM_ENV_CAPACITY", 2098*7c478bd9Sstevel@tonic-gate "new_cpu_list", "RCM_ENV_CPU_IDS", 2099*7c478bd9Sstevel@tonic-gate "", ""}, 2100*7c478bd9Sstevel@tonic-gate { "SUNW_cpu/set", MATCH_PREFIX, 2101*7c478bd9Sstevel@tonic-gate "new_total", "RCM_ENV_CAPACITY", 2102*7c478bd9Sstevel@tonic-gate "new_cpu_list", "RCM_ENV_CPU_IDS", 2103*7c478bd9Sstevel@tonic-gate "", ""}, 2104*7c478bd9Sstevel@tonic-gate { "", MATCH_INVALID, "", "" } 2105*7c478bd9Sstevel@tonic-gate }; 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate static capacity_descr_t * 2108*7c478bd9Sstevel@tonic-gate get_capacity_descr(char *resource_name) 2109*7c478bd9Sstevel@tonic-gate { 2110*7c478bd9Sstevel@tonic-gate int i; 2111*7c478bd9Sstevel@tonic-gate 2112*7c478bd9Sstevel@tonic-gate for (i = 0; *capacity_type[i].resource_name != '\0'; i++) { 2113*7c478bd9Sstevel@tonic-gate if ((capacity_type[i].match_type == MATCH_EXACT && 2114*7c478bd9Sstevel@tonic-gate strcmp(capacity_type[i].resource_name, 2115*7c478bd9Sstevel@tonic-gate resource_name) == 0) || 2116*7c478bd9Sstevel@tonic-gate (capacity_type[i].match_type == MATCH_PREFIX && 2117*7c478bd9Sstevel@tonic-gate strncmp(capacity_type[i].resource_name, 2118*7c478bd9Sstevel@tonic-gate resource_name, 2119*7c478bd9Sstevel@tonic-gate strlen(capacity_type[i].resource_name)) == 0)) 2120*7c478bd9Sstevel@tonic-gate 2121*7c478bd9Sstevel@tonic-gate return (&capacity_type[i]); 2122*7c478bd9Sstevel@tonic-gate } 2123*7c478bd9Sstevel@tonic-gate 2124*7c478bd9Sstevel@tonic-gate return (NULL); 2125*7c478bd9Sstevel@tonic-gate } 2126*7c478bd9Sstevel@tonic-gate 2127*7c478bd9Sstevel@tonic-gate static int 2128*7c478bd9Sstevel@tonic-gate build_env_for_capacity(script_info_t *rsi, 2129*7c478bd9Sstevel@tonic-gate char *resource_name, 2130*7c478bd9Sstevel@tonic-gate uint_t flag, 2131*7c478bd9Sstevel@tonic-gate nvlist_t *capacity_info, 2132*7c478bd9Sstevel@tonic-gate char *envp[], 2133*7c478bd9Sstevel@tonic-gate int *dynamic_env_index, 2134*7c478bd9Sstevel@tonic-gate char **errmsg) 2135*7c478bd9Sstevel@tonic-gate { 2136*7c478bd9Sstevel@tonic-gate int p, i; 2137*7c478bd9Sstevel@tonic-gate capacity_descr_t *capa = NULL; 2138*7c478bd9Sstevel@tonic-gate nvpair_t *nvpair; 2139*7c478bd9Sstevel@tonic-gate char *buf; 2140*7c478bd9Sstevel@tonic-gate char *curptr; 2141*7c478bd9Sstevel@tonic-gate int buflen; 2142*7c478bd9Sstevel@tonic-gate int error; 2143*7c478bd9Sstevel@tonic-gate uint_t n; 2144*7c478bd9Sstevel@tonic-gate 2145*7c478bd9Sstevel@tonic-gate copy_env(script_env, envp); 2146*7c478bd9Sstevel@tonic-gate for (p = 0; envp[p] != NULL; p++) 2147*7c478bd9Sstevel@tonic-gate ; 2148*7c478bd9Sstevel@tonic-gate 2149*7c478bd9Sstevel@tonic-gate if (rsi->cmd == C_QUERYCAPACITY || rsi->cmd == C_PRECAPACITY) 2150*7c478bd9Sstevel@tonic-gate envp[p++] = (flag & RCM_FORCE) ? script_env_force : 2151*7c478bd9Sstevel@tonic-gate script_env_noforce; 2152*7c478bd9Sstevel@tonic-gate 2153*7c478bd9Sstevel@tonic-gate envp[p] = NULL; 2154*7c478bd9Sstevel@tonic-gate *dynamic_env_index = p; 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate if ((capa = get_capacity_descr(resource_name)) == NULL) { 2157*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MF_UNKNOWN_RSRC_ERR, 2158*7c478bd9Sstevel@tonic-gate resource_name, rsi->script_name); 2159*7c478bd9Sstevel@tonic-gate return (-1); 2160*7c478bd9Sstevel@tonic-gate } 2161*7c478bd9Sstevel@tonic-gate 2162*7c478bd9Sstevel@tonic-gate for (i = 0; *capa->param[i].nvname != '\0'; i++) { 2163*7c478bd9Sstevel@tonic-gate nvpair = NULL; 2164*7c478bd9Sstevel@tonic-gate while ((nvpair = nvlist_next_nvpair(capacity_info, nvpair)) 2165*7c478bd9Sstevel@tonic-gate != NULL) { 2166*7c478bd9Sstevel@tonic-gate if (strcmp(nvpair_name(nvpair), 2167*7c478bd9Sstevel@tonic-gate capa->param[i].nvname) == 0) 2168*7c478bd9Sstevel@tonic-gate break; 2169*7c478bd9Sstevel@tonic-gate } 2170*7c478bd9Sstevel@tonic-gate 2171*7c478bd9Sstevel@tonic-gate if (nvpair == NULL) { 2172*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MF_NV_ERR, 2173*7c478bd9Sstevel@tonic-gate rsi->script_name); 2174*7c478bd9Sstevel@tonic-gate return (-1); 2175*7c478bd9Sstevel@tonic-gate } 2176*7c478bd9Sstevel@tonic-gate 2177*7c478bd9Sstevel@tonic-gate error = 0; 2178*7c478bd9Sstevel@tonic-gate buf = NULL; 2179*7c478bd9Sstevel@tonic-gate 2180*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, "%s=", 2181*7c478bd9Sstevel@tonic-gate capa->param[i].envname); 2182*7c478bd9Sstevel@tonic-gate 2183*7c478bd9Sstevel@tonic-gate switch (nvpair_type(nvpair)) { 2184*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT16: 2185*7c478bd9Sstevel@tonic-gate { 2186*7c478bd9Sstevel@tonic-gate int16_t x; 2187*7c478bd9Sstevel@tonic-gate 2188*7c478bd9Sstevel@tonic-gate if (nvpair_value_int16(nvpair, &x) == 0) { 2189*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2190*7c478bd9Sstevel@tonic-gate "%hd", (short)x); 2191*7c478bd9Sstevel@tonic-gate } else 2192*7c478bd9Sstevel@tonic-gate error = 1; 2193*7c478bd9Sstevel@tonic-gate break; 2194*7c478bd9Sstevel@tonic-gate } 2195*7c478bd9Sstevel@tonic-gate 2196*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT16: 2197*7c478bd9Sstevel@tonic-gate { 2198*7c478bd9Sstevel@tonic-gate uint16_t x; 2199*7c478bd9Sstevel@tonic-gate 2200*7c478bd9Sstevel@tonic-gate if (nvpair_value_uint16(nvpair, &x) == 0) { 2201*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2202*7c478bd9Sstevel@tonic-gate "%hu", (unsigned short)x); 2203*7c478bd9Sstevel@tonic-gate } else 2204*7c478bd9Sstevel@tonic-gate error = 1; 2205*7c478bd9Sstevel@tonic-gate break; 2206*7c478bd9Sstevel@tonic-gate } 2207*7c478bd9Sstevel@tonic-gate 2208*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT32: 2209*7c478bd9Sstevel@tonic-gate { 2210*7c478bd9Sstevel@tonic-gate int32_t x; 2211*7c478bd9Sstevel@tonic-gate 2212*7c478bd9Sstevel@tonic-gate if (nvpair_value_int32(nvpair, &x) == 0) { 2213*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2214*7c478bd9Sstevel@tonic-gate "%d", (int)x); 2215*7c478bd9Sstevel@tonic-gate } else 2216*7c478bd9Sstevel@tonic-gate error = 1; 2217*7c478bd9Sstevel@tonic-gate break; 2218*7c478bd9Sstevel@tonic-gate } 2219*7c478bd9Sstevel@tonic-gate 2220*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT32: 2221*7c478bd9Sstevel@tonic-gate { 2222*7c478bd9Sstevel@tonic-gate uint32_t x; 2223*7c478bd9Sstevel@tonic-gate 2224*7c478bd9Sstevel@tonic-gate if (nvpair_value_uint32(nvpair, &x) == 0) { 2225*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2226*7c478bd9Sstevel@tonic-gate "%u", (uint_t)x); 2227*7c478bd9Sstevel@tonic-gate } else 2228*7c478bd9Sstevel@tonic-gate error = 1; 2229*7c478bd9Sstevel@tonic-gate break; 2230*7c478bd9Sstevel@tonic-gate } 2231*7c478bd9Sstevel@tonic-gate 2232*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT64: 2233*7c478bd9Sstevel@tonic-gate { 2234*7c478bd9Sstevel@tonic-gate int64_t x; 2235*7c478bd9Sstevel@tonic-gate 2236*7c478bd9Sstevel@tonic-gate if (nvpair_value_int64(nvpair, &x) == 0) { 2237*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2238*7c478bd9Sstevel@tonic-gate "%lld", (long long)x); 2239*7c478bd9Sstevel@tonic-gate } else 2240*7c478bd9Sstevel@tonic-gate error = 1; 2241*7c478bd9Sstevel@tonic-gate break; 2242*7c478bd9Sstevel@tonic-gate } 2243*7c478bd9Sstevel@tonic-gate 2244*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT64: 2245*7c478bd9Sstevel@tonic-gate { 2246*7c478bd9Sstevel@tonic-gate uint64_t x; 2247*7c478bd9Sstevel@tonic-gate 2248*7c478bd9Sstevel@tonic-gate if (nvpair_value_uint64(nvpair, &x) == 0) { 2249*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2250*7c478bd9Sstevel@tonic-gate "%llu", (unsigned long long)x); 2251*7c478bd9Sstevel@tonic-gate } else 2252*7c478bd9Sstevel@tonic-gate error = 1; 2253*7c478bd9Sstevel@tonic-gate break; 2254*7c478bd9Sstevel@tonic-gate } 2255*7c478bd9Sstevel@tonic-gate 2256*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT16_ARRAY: 2257*7c478bd9Sstevel@tonic-gate { 2258*7c478bd9Sstevel@tonic-gate int16_t *x; 2259*7c478bd9Sstevel@tonic-gate 2260*7c478bd9Sstevel@tonic-gate if (nvpair_value_int16_array(nvpair, &x, &n) == 0) { 2261*7c478bd9Sstevel@tonic-gate while (n--) { 2262*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, 2263*7c478bd9Sstevel@tonic-gate &curptr, "%hd%s", 2264*7c478bd9Sstevel@tonic-gate (short)(*x), 2265*7c478bd9Sstevel@tonic-gate (n == 0) ? "" : " "); 2266*7c478bd9Sstevel@tonic-gate x++; 2267*7c478bd9Sstevel@tonic-gate } 2268*7c478bd9Sstevel@tonic-gate } else 2269*7c478bd9Sstevel@tonic-gate error = 1; 2270*7c478bd9Sstevel@tonic-gate break; 2271*7c478bd9Sstevel@tonic-gate } 2272*7c478bd9Sstevel@tonic-gate 2273*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT16_ARRAY: 2274*7c478bd9Sstevel@tonic-gate { 2275*7c478bd9Sstevel@tonic-gate uint16_t *x; 2276*7c478bd9Sstevel@tonic-gate 2277*7c478bd9Sstevel@tonic-gate if (nvpair_value_uint16_array(nvpair, &x, &n) == 0) { 2278*7c478bd9Sstevel@tonic-gate while (n--) { 2279*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, 2280*7c478bd9Sstevel@tonic-gate &curptr, "%hu%s", 2281*7c478bd9Sstevel@tonic-gate (unsigned short)(*x), 2282*7c478bd9Sstevel@tonic-gate (n == 0) ? "" : " "); 2283*7c478bd9Sstevel@tonic-gate x++; 2284*7c478bd9Sstevel@tonic-gate } 2285*7c478bd9Sstevel@tonic-gate } else 2286*7c478bd9Sstevel@tonic-gate error = 1; 2287*7c478bd9Sstevel@tonic-gate break; 2288*7c478bd9Sstevel@tonic-gate } 2289*7c478bd9Sstevel@tonic-gate 2290*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT32_ARRAY: 2291*7c478bd9Sstevel@tonic-gate { 2292*7c478bd9Sstevel@tonic-gate int32_t *x; 2293*7c478bd9Sstevel@tonic-gate 2294*7c478bd9Sstevel@tonic-gate if (nvpair_value_int32_array(nvpair, &x, &n) == 0) { 2295*7c478bd9Sstevel@tonic-gate while (n--) { 2296*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, 2297*7c478bd9Sstevel@tonic-gate &curptr, "%d%s", 2298*7c478bd9Sstevel@tonic-gate (int)(*x), 2299*7c478bd9Sstevel@tonic-gate (n == 0) ? "" : " "); 2300*7c478bd9Sstevel@tonic-gate x++; 2301*7c478bd9Sstevel@tonic-gate } 2302*7c478bd9Sstevel@tonic-gate } else 2303*7c478bd9Sstevel@tonic-gate error = 1; 2304*7c478bd9Sstevel@tonic-gate break; 2305*7c478bd9Sstevel@tonic-gate } 2306*7c478bd9Sstevel@tonic-gate 2307*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT32_ARRAY: 2308*7c478bd9Sstevel@tonic-gate { 2309*7c478bd9Sstevel@tonic-gate uint32_t *x; 2310*7c478bd9Sstevel@tonic-gate 2311*7c478bd9Sstevel@tonic-gate if (nvpair_value_uint32_array(nvpair, &x, &n) == 0) { 2312*7c478bd9Sstevel@tonic-gate while (n--) { 2313*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, 2314*7c478bd9Sstevel@tonic-gate &curptr, "%u%s", 2315*7c478bd9Sstevel@tonic-gate (uint_t)(*x), 2316*7c478bd9Sstevel@tonic-gate (n == 0) ? "" : " "); 2317*7c478bd9Sstevel@tonic-gate x++; 2318*7c478bd9Sstevel@tonic-gate } 2319*7c478bd9Sstevel@tonic-gate } else 2320*7c478bd9Sstevel@tonic-gate error = 1; 2321*7c478bd9Sstevel@tonic-gate break; 2322*7c478bd9Sstevel@tonic-gate } 2323*7c478bd9Sstevel@tonic-gate 2324*7c478bd9Sstevel@tonic-gate case DATA_TYPE_INT64_ARRAY: 2325*7c478bd9Sstevel@tonic-gate { 2326*7c478bd9Sstevel@tonic-gate int64_t *x; 2327*7c478bd9Sstevel@tonic-gate 2328*7c478bd9Sstevel@tonic-gate if (nvpair_value_int64_array(nvpair, &x, &n) == 0) { 2329*7c478bd9Sstevel@tonic-gate while (n--) { 2330*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, 2331*7c478bd9Sstevel@tonic-gate &curptr, "%lld%s", 2332*7c478bd9Sstevel@tonic-gate (long long)(*x), 2333*7c478bd9Sstevel@tonic-gate (n == 0) ? "" : " "); 2334*7c478bd9Sstevel@tonic-gate x++; 2335*7c478bd9Sstevel@tonic-gate } 2336*7c478bd9Sstevel@tonic-gate } else 2337*7c478bd9Sstevel@tonic-gate error = 1; 2338*7c478bd9Sstevel@tonic-gate break; 2339*7c478bd9Sstevel@tonic-gate } 2340*7c478bd9Sstevel@tonic-gate 2341*7c478bd9Sstevel@tonic-gate case DATA_TYPE_UINT64_ARRAY: 2342*7c478bd9Sstevel@tonic-gate { 2343*7c478bd9Sstevel@tonic-gate uint64_t *x; 2344*7c478bd9Sstevel@tonic-gate 2345*7c478bd9Sstevel@tonic-gate if (nvpair_value_uint64_array(nvpair, &x, &n) == 0) { 2346*7c478bd9Sstevel@tonic-gate while (n--) { 2347*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, 2348*7c478bd9Sstevel@tonic-gate &curptr, "%llu%s", 2349*7c478bd9Sstevel@tonic-gate (unsigned long long)(*x), 2350*7c478bd9Sstevel@tonic-gate (n == 0) ? "" : " "); 2351*7c478bd9Sstevel@tonic-gate x++; 2352*7c478bd9Sstevel@tonic-gate } 2353*7c478bd9Sstevel@tonic-gate } else 2354*7c478bd9Sstevel@tonic-gate error = 1; 2355*7c478bd9Sstevel@tonic-gate break; 2356*7c478bd9Sstevel@tonic-gate } 2357*7c478bd9Sstevel@tonic-gate 2358*7c478bd9Sstevel@tonic-gate case DATA_TYPE_STRING: 2359*7c478bd9Sstevel@tonic-gate { 2360*7c478bd9Sstevel@tonic-gate char *x; 2361*7c478bd9Sstevel@tonic-gate 2362*7c478bd9Sstevel@tonic-gate if (nvpair_value_string(nvpair, &x) == 0) { 2363*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(&buf, &buflen, &curptr, 2364*7c478bd9Sstevel@tonic-gate "%s", x); 2365*7c478bd9Sstevel@tonic-gate } else 2366*7c478bd9Sstevel@tonic-gate error = 1; 2367*7c478bd9Sstevel@tonic-gate break; 2368*7c478bd9Sstevel@tonic-gate } 2369*7c478bd9Sstevel@tonic-gate 2370*7c478bd9Sstevel@tonic-gate 2371*7c478bd9Sstevel@tonic-gate default: 2372*7c478bd9Sstevel@tonic-gate error = 1; 2373*7c478bd9Sstevel@tonic-gate break; 2374*7c478bd9Sstevel@tonic-gate } 2375*7c478bd9Sstevel@tonic-gate 2376*7c478bd9Sstevel@tonic-gate envp[p++] = buf; 2377*7c478bd9Sstevel@tonic-gate 2378*7c478bd9Sstevel@tonic-gate if (error) { 2379*7c478bd9Sstevel@tonic-gate envp[p] = NULL; 2380*7c478bd9Sstevel@tonic-gate for (p = *dynamic_env_index; envp[p] != NULL; p++) 2381*7c478bd9Sstevel@tonic-gate free(envp[p]); 2382*7c478bd9Sstevel@tonic-gate *errmsg = dup_err(RCM_ERROR, MF_NV_ERR, 2383*7c478bd9Sstevel@tonic-gate rsi->script_name); 2384*7c478bd9Sstevel@tonic-gate return (-1); 2385*7c478bd9Sstevel@tonic-gate } 2386*7c478bd9Sstevel@tonic-gate } 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate envp[p] = NULL; 2389*7c478bd9Sstevel@tonic-gate 2390*7c478bd9Sstevel@tonic-gate return (0); 2391*7c478bd9Sstevel@tonic-gate } 2392*7c478bd9Sstevel@tonic-gate 2393*7c478bd9Sstevel@tonic-gate /* 2394*7c478bd9Sstevel@tonic-gate * request_capacity_change entry point 2395*7c478bd9Sstevel@tonic-gate */ 2396*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2397*7c478bd9Sstevel@tonic-gate static int 2398*7c478bd9Sstevel@tonic-gate script_request_capacity_change(rcm_handle_t *hdl, 2399*7c478bd9Sstevel@tonic-gate char *resource_name, 2400*7c478bd9Sstevel@tonic-gate pid_t pid, 2401*7c478bd9Sstevel@tonic-gate uint_t flag, 2402*7c478bd9Sstevel@tonic-gate nvlist_t *capacity_info, 2403*7c478bd9Sstevel@tonic-gate char **info, 2404*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 2405*7c478bd9Sstevel@tonic-gate { 2406*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 2407*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 2408*7c478bd9Sstevel@tonic-gate char *envp[MAX_ENV_PARAMS]; 2409*7c478bd9Sstevel@tonic-gate char flags_name[MAX_FLAGS_NAME_LEN]; 2410*7c478bd9Sstevel@tonic-gate int status; 2411*7c478bd9Sstevel@tonic-gate int dynamic_env_index; 2412*7c478bd9Sstevel@tonic-gate 2413*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 2414*7c478bd9Sstevel@tonic-gate "script_request_capacity_change: resource = %s flags = %s\n", 2415*7c478bd9Sstevel@tonic-gate resource_name, 2416*7c478bd9Sstevel@tonic-gate flags_to_name(flag, flags_name, MAX_FLAGS_NAME_LEN)); 2417*7c478bd9Sstevel@tonic-gate 2418*7c478bd9Sstevel@tonic-gate *info = NULL; 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 2421*7c478bd9Sstevel@tonic-gate 2422*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 2423*7c478bd9Sstevel@tonic-gate rsi->cmd = (flag & RCM_QUERY) ? C_QUERYCAPACITY : C_PRECAPACITY; 2424*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 2425*7c478bd9Sstevel@tonic-gate 2426*7c478bd9Sstevel@tonic-gate if (build_env_for_capacity(rsi, resource_name, flag, 2427*7c478bd9Sstevel@tonic-gate capacity_info, envp, &dynamic_env_index, info) == 0) { 2428*7c478bd9Sstevel@tonic-gate 2429*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, envp, info); 2430*7c478bd9Sstevel@tonic-gate 2431*7c478bd9Sstevel@tonic-gate while (envp[dynamic_env_index] != NULL) { 2432*7c478bd9Sstevel@tonic-gate free(envp[dynamic_env_index]); 2433*7c478bd9Sstevel@tonic-gate dynamic_env_index++; 2434*7c478bd9Sstevel@tonic-gate } 2435*7c478bd9Sstevel@tonic-gate } else 2436*7c478bd9Sstevel@tonic-gate status = RCM_FAILURE; 2437*7c478bd9Sstevel@tonic-gate 2438*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 2439*7c478bd9Sstevel@tonic-gate return (status); 2440*7c478bd9Sstevel@tonic-gate } 2441*7c478bd9Sstevel@tonic-gate 2442*7c478bd9Sstevel@tonic-gate /* 2443*7c478bd9Sstevel@tonic-gate * notify_capacity_change entry point 2444*7c478bd9Sstevel@tonic-gate */ 2445*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2446*7c478bd9Sstevel@tonic-gate static int 2447*7c478bd9Sstevel@tonic-gate script_notify_capacity_change(rcm_handle_t *hdl, 2448*7c478bd9Sstevel@tonic-gate char *resource_name, 2449*7c478bd9Sstevel@tonic-gate pid_t pid, 2450*7c478bd9Sstevel@tonic-gate uint_t flag, 2451*7c478bd9Sstevel@tonic-gate nvlist_t *capacity_info, 2452*7c478bd9Sstevel@tonic-gate char **info, 2453*7c478bd9Sstevel@tonic-gate rcm_info_t **dependent_info) 2454*7c478bd9Sstevel@tonic-gate { 2455*7c478bd9Sstevel@tonic-gate script_info_t *rsi = hdl->module->rsi; 2456*7c478bd9Sstevel@tonic-gate char *argv[MAX_ARGS]; 2457*7c478bd9Sstevel@tonic-gate char *envp[MAX_ENV_PARAMS]; 2458*7c478bd9Sstevel@tonic-gate int status; 2459*7c478bd9Sstevel@tonic-gate int dynamic_env_index; 2460*7c478bd9Sstevel@tonic-gate 2461*7c478bd9Sstevel@tonic-gate rcm_log_message(RSCR_TRACE, 2462*7c478bd9Sstevel@tonic-gate "script_notify_capacity_change: resource = %s\n", resource_name); 2463*7c478bd9Sstevel@tonic-gate 2464*7c478bd9Sstevel@tonic-gate *info = NULL; 2465*7c478bd9Sstevel@tonic-gate 2466*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&rsi->channel_lock); 2467*7c478bd9Sstevel@tonic-gate 2468*7c478bd9Sstevel@tonic-gate rsi->hdl = hdl; 2469*7c478bd9Sstevel@tonic-gate rsi->cmd = C_POSTCAPACITY; 2470*7c478bd9Sstevel@tonic-gate fill_argv(rsi, argv, resource_name); 2471*7c478bd9Sstevel@tonic-gate 2472*7c478bd9Sstevel@tonic-gate if (build_env_for_capacity(rsi, resource_name, flag, 2473*7c478bd9Sstevel@tonic-gate capacity_info, envp, &dynamic_env_index, info) == 0) { 2474*7c478bd9Sstevel@tonic-gate 2475*7c478bd9Sstevel@tonic-gate status = do_dr(rsi, argv, envp, info); 2476*7c478bd9Sstevel@tonic-gate 2477*7c478bd9Sstevel@tonic-gate while (envp[dynamic_env_index] != NULL) { 2478*7c478bd9Sstevel@tonic-gate free(envp[dynamic_env_index]); 2479*7c478bd9Sstevel@tonic-gate dynamic_env_index++; 2480*7c478bd9Sstevel@tonic-gate } 2481*7c478bd9Sstevel@tonic-gate } else 2482*7c478bd9Sstevel@tonic-gate status = RCM_FAILURE; 2483*7c478bd9Sstevel@tonic-gate 2484*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&rsi->channel_lock); 2485*7c478bd9Sstevel@tonic-gate return (status); 2486*7c478bd9Sstevel@tonic-gate } 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate /* Log the message to syslog */ 2489*7c478bd9Sstevel@tonic-gate static void 2490*7c478bd9Sstevel@tonic-gate log_msg(script_info_t *rsi, int level, char *msg) 2491*7c478bd9Sstevel@tonic-gate { 2492*7c478bd9Sstevel@tonic-gate rcm_log_msg(level, MS_LOG_MSG, rsi->script_name, msg); 2493*7c478bd9Sstevel@tonic-gate } 2494*7c478bd9Sstevel@tonic-gate 2495*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 2496*7c478bd9Sstevel@tonic-gate static char * 2497*7c478bd9Sstevel@tonic-gate dup_err(int level, char *format, ...) 2498*7c478bd9Sstevel@tonic-gate { 2499*7c478bd9Sstevel@tonic-gate va_list ap; 2500*7c478bd9Sstevel@tonic-gate char buf1[1]; 2501*7c478bd9Sstevel@tonic-gate char *buf2; 2502*7c478bd9Sstevel@tonic-gate int n; 2503*7c478bd9Sstevel@tonic-gate 2504*7c478bd9Sstevel@tonic-gate va_start(ap, format); 2505*7c478bd9Sstevel@tonic-gate n = vsnprintf(buf1, 1, format, ap); 2506*7c478bd9Sstevel@tonic-gate va_end(ap); 2507*7c478bd9Sstevel@tonic-gate 2508*7c478bd9Sstevel@tonic-gate if (n > 0) { 2509*7c478bd9Sstevel@tonic-gate n++; 2510*7c478bd9Sstevel@tonic-gate if (buf2 = (char *)malloc(n)) { 2511*7c478bd9Sstevel@tonic-gate va_start(ap, format); 2512*7c478bd9Sstevel@tonic-gate n = vsnprintf(buf2, n, format, ap); 2513*7c478bd9Sstevel@tonic-gate va_end(ap); 2514*7c478bd9Sstevel@tonic-gate if (n > 0) { 2515*7c478bd9Sstevel@tonic-gate if (level != -1) 2516*7c478bd9Sstevel@tonic-gate rcm_log_message(level, buf2); 2517*7c478bd9Sstevel@tonic-gate return (buf2); 2518*7c478bd9Sstevel@tonic-gate } 2519*7c478bd9Sstevel@tonic-gate free(buf2); 2520*7c478bd9Sstevel@tonic-gate } 2521*7c478bd9Sstevel@tonic-gate } 2522*7c478bd9Sstevel@tonic-gate 2523*7c478bd9Sstevel@tonic-gate return (NULL); 2524*7c478bd9Sstevel@tonic-gate } 2525*7c478bd9Sstevel@tonic-gate 2526*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE4*/ 2527*7c478bd9Sstevel@tonic-gate static void 2528*7c478bd9Sstevel@tonic-gate rcmscript_snprintf(char **buf, int *buflen, char **curptr, char *format, ...) 2529*7c478bd9Sstevel@tonic-gate { 2530*7c478bd9Sstevel@tonic-gate /* must be power of 2 otherwise RSCR_ROUNDUP would break */ 2531*7c478bd9Sstevel@tonic-gate #define SPRINTF_CHUNK_LEN 512 2532*7c478bd9Sstevel@tonic-gate #define SPRINTF_MIN_CHUNK_LEN 64 2533*7c478bd9Sstevel@tonic-gate 2534*7c478bd9Sstevel@tonic-gate va_list ap; 2535*7c478bd9Sstevel@tonic-gate int offset, bytesneeded, bytesleft, error_num; 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate if (*buf == NULL) { 2538*7c478bd9Sstevel@tonic-gate *buflen = 0; 2539*7c478bd9Sstevel@tonic-gate *curptr = NULL; 2540*7c478bd9Sstevel@tonic-gate } 2541*7c478bd9Sstevel@tonic-gate 2542*7c478bd9Sstevel@tonic-gate offset = *curptr - *buf; 2543*7c478bd9Sstevel@tonic-gate bytesneeded = SPRINTF_MIN_CHUNK_LEN; 2544*7c478bd9Sstevel@tonic-gate bytesleft = *buflen - offset; 2545*7c478bd9Sstevel@tonic-gate 2546*7c478bd9Sstevel@tonic-gate /* LINTED */ 2547*7c478bd9Sstevel@tonic-gate while (1) { 2548*7c478bd9Sstevel@tonic-gate if (bytesneeded > bytesleft) { 2549*7c478bd9Sstevel@tonic-gate *buflen += RSCR_ROUNDUP(bytesneeded - bytesleft, 2550*7c478bd9Sstevel@tonic-gate SPRINTF_CHUNK_LEN); 2551*7c478bd9Sstevel@tonic-gate if ((*buf = (char *)realloc(*buf, *buflen)) == NULL) { 2552*7c478bd9Sstevel@tonic-gate error_num = errno; 2553*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 2554*7c478bd9Sstevel@tonic-gate MF_MEMORY_ALLOCATION_ERR, 2555*7c478bd9Sstevel@tonic-gate strerror(error_num)); 2556*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 2557*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2558*7c478bd9Sstevel@tonic-gate } 2559*7c478bd9Sstevel@tonic-gate *curptr = *buf + offset; 2560*7c478bd9Sstevel@tonic-gate bytesleft = *buflen - offset; 2561*7c478bd9Sstevel@tonic-gate } 2562*7c478bd9Sstevel@tonic-gate 2563*7c478bd9Sstevel@tonic-gate va_start(ap, format); 2564*7c478bd9Sstevel@tonic-gate bytesneeded = vsnprintf(*curptr, bytesleft, format, ap); 2565*7c478bd9Sstevel@tonic-gate va_end(ap); 2566*7c478bd9Sstevel@tonic-gate 2567*7c478bd9Sstevel@tonic-gate if (bytesneeded < 0) { 2568*7c478bd9Sstevel@tonic-gate /* vsnprintf encountered an error */ 2569*7c478bd9Sstevel@tonic-gate error_num = errno; 2570*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_FUNC_CALL_ERR, 2571*7c478bd9Sstevel@tonic-gate "vsnprintf", strerror(error_num)); 2572*7c478bd9Sstevel@tonic-gate rcmd_exit(error_num); 2573*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2574*7c478bd9Sstevel@tonic-gate 2575*7c478bd9Sstevel@tonic-gate } else if (bytesneeded < bytesleft) { 2576*7c478bd9Sstevel@tonic-gate /* vsnprintf succeeded */ 2577*7c478bd9Sstevel@tonic-gate *curptr += bytesneeded; 2578*7c478bd9Sstevel@tonic-gate return; 2579*7c478bd9Sstevel@tonic-gate 2580*7c478bd9Sstevel@tonic-gate } else { 2581*7c478bd9Sstevel@tonic-gate bytesneeded++; /* to account for storage for '\0' */ 2582*7c478bd9Sstevel@tonic-gate } 2583*7c478bd9Sstevel@tonic-gate } 2584*7c478bd9Sstevel@tonic-gate } 2585*7c478bd9Sstevel@tonic-gate 2586*7c478bd9Sstevel@tonic-gate static char * 2587*7c478bd9Sstevel@tonic-gate rcmscript_strdup(char *str) 2588*7c478bd9Sstevel@tonic-gate { 2589*7c478bd9Sstevel@tonic-gate char *dupstr; 2590*7c478bd9Sstevel@tonic-gate 2591*7c478bd9Sstevel@tonic-gate if ((dupstr = strdup(str)) == NULL) { 2592*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_MEMORY_ALLOCATION_ERR, 2593*7c478bd9Sstevel@tonic-gate strerror(errno)); 2594*7c478bd9Sstevel@tonic-gate rcmd_exit(errno); 2595*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2596*7c478bd9Sstevel@tonic-gate } 2597*7c478bd9Sstevel@tonic-gate 2598*7c478bd9Sstevel@tonic-gate return (dupstr); 2599*7c478bd9Sstevel@tonic-gate } 2600*7c478bd9Sstevel@tonic-gate 2601*7c478bd9Sstevel@tonic-gate static void * 2602*7c478bd9Sstevel@tonic-gate rcmscript_malloc(size_t len) 2603*7c478bd9Sstevel@tonic-gate { 2604*7c478bd9Sstevel@tonic-gate void *ptr; 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate if ((ptr = malloc(len)) == NULL) { 2607*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_MEMORY_ALLOCATION_ERR, 2608*7c478bd9Sstevel@tonic-gate strerror(errno)); 2609*7c478bd9Sstevel@tonic-gate rcmd_exit(errno); 2610*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2611*7c478bd9Sstevel@tonic-gate } 2612*7c478bd9Sstevel@tonic-gate 2613*7c478bd9Sstevel@tonic-gate return (ptr); 2614*7c478bd9Sstevel@tonic-gate } 2615*7c478bd9Sstevel@tonic-gate 2616*7c478bd9Sstevel@tonic-gate static void * 2617*7c478bd9Sstevel@tonic-gate rcmscript_calloc(size_t nelem, size_t elsize) 2618*7c478bd9Sstevel@tonic-gate { 2619*7c478bd9Sstevel@tonic-gate void *ptr; 2620*7c478bd9Sstevel@tonic-gate 2621*7c478bd9Sstevel@tonic-gate if ((ptr = calloc(nelem, elsize)) == NULL) { 2622*7c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, MF_MEMORY_ALLOCATION_ERR, 2623*7c478bd9Sstevel@tonic-gate strerror(errno)); 2624*7c478bd9Sstevel@tonic-gate rcmd_exit(errno); 2625*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2626*7c478bd9Sstevel@tonic-gate } 2627*7c478bd9Sstevel@tonic-gate 2628*7c478bd9Sstevel@tonic-gate return (ptr); 2629*7c478bd9Sstevel@tonic-gate } 2630