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 * syseventadm - command to administer the sysevent.conf registry 31*7c478bd9Sstevel@tonic-gate * - administers the general purpose event framework 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * The current implementation of the registry using files in 34*7c478bd9Sstevel@tonic-gate * /etc/sysevent/config, files are named as event specifications 35*7c478bd9Sstevel@tonic-gate * are added with the combination of the vendor, publisher, event 36*7c478bd9Sstevel@tonic-gate * class and subclass strings: 37*7c478bd9Sstevel@tonic-gate * 38*7c478bd9Sstevel@tonic-gate * [<vendor>,][<publisher>,][<class>,]sysevent.conf 39*7c478bd9Sstevel@tonic-gate * 40*7c478bd9Sstevel@tonic-gate */ 41*7c478bd9Sstevel@tonic-gate #include <stdio.h> 42*7c478bd9Sstevel@tonic-gate #include <ctype.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 44*7c478bd9Sstevel@tonic-gate #include <dirent.h> 45*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 46*7c478bd9Sstevel@tonic-gate #include <stddef.h> 47*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 48*7c478bd9Sstevel@tonic-gate #include <dlfcn.h> 49*7c478bd9Sstevel@tonic-gate #include <door.h> 50*7c478bd9Sstevel@tonic-gate #include <errno.h> 51*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 52*7c478bd9Sstevel@tonic-gate #include <signal.h> 53*7c478bd9Sstevel@tonic-gate #include <strings.h> 54*7c478bd9Sstevel@tonic-gate #include <unistd.h> 55*7c478bd9Sstevel@tonic-gate #include <synch.h> 56*7c478bd9Sstevel@tonic-gate #include <syslog.h> 57*7c478bd9Sstevel@tonic-gate #include <thread.h> 58*7c478bd9Sstevel@tonic-gate #include <limits.h> 59*7c478bd9Sstevel@tonic-gate #include <locale.h> 60*7c478bd9Sstevel@tonic-gate #include <assert.h> 61*7c478bd9Sstevel@tonic-gate #include <libsysevent.h> 62*7c478bd9Sstevel@tonic-gate #include <zone.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/sysevent_impl.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #include "syseventadm.h" 71*7c478bd9Sstevel@tonic-gate #include "syseventadm_msg.h" 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #ifndef DEBUG 74*7c478bd9Sstevel@tonic-gate #undef assert 75*7c478bd9Sstevel@tonic-gate #define assert(EX) ((void)0) 76*7c478bd9Sstevel@tonic-gate #endif 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate static char *whoami = NULL; 79*7c478bd9Sstevel@tonic-gate static char *root_dir = ""; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate static char *arg_vendor = NULL; 82*7c478bd9Sstevel@tonic-gate static char *arg_publisher = NULL; 83*7c478bd9Sstevel@tonic-gate static char *arg_class = NULL; 84*7c478bd9Sstevel@tonic-gate static char *arg_subclass = NULL; 85*7c478bd9Sstevel@tonic-gate static char *arg_username = NULL; 86*7c478bd9Sstevel@tonic-gate static char *arg_path = NULL; 87*7c478bd9Sstevel@tonic-gate static int arg_nargs = 0; 88*7c478bd9Sstevel@tonic-gate static char **arg_args = NULL; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static int lock_fd; 91*7c478bd9Sstevel@tonic-gate static char lock_file[PATH_MAX + 1]; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate extern char *optarg; 94*7c478bd9Sstevel@tonic-gate extern int optind; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate static int 97*7c478bd9Sstevel@tonic-gate usage_gen() 98*7c478bd9Sstevel@tonic-gate { 99*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_USAGE_INTRO); 100*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_USAGE_OPTIONS); 101*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n" 102*7c478bd9Sstevel@tonic-gate "\tsyseventadm add ...\n" 103*7c478bd9Sstevel@tonic-gate "\tsyseventadm remove ...\n" 104*7c478bd9Sstevel@tonic-gate "\tsyseventadm list ...\n" 105*7c478bd9Sstevel@tonic-gate "\tsyseventadm restart\n" 106*7c478bd9Sstevel@tonic-gate "\tsyseventadm help\n"); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate return (EXIT_USAGE); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static int 112*7c478bd9Sstevel@tonic-gate serve_syseventdotconf(int argc, char **argv, char *cmd) 113*7c478bd9Sstevel@tonic-gate { 114*7c478bd9Sstevel@tonic-gate int c; 115*7c478bd9Sstevel@tonic-gate int rval; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "R:v:p:c:s:u:")) != EOF) { 118*7c478bd9Sstevel@tonic-gate switch (c) { 119*7c478bd9Sstevel@tonic-gate case 'R': 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Alternate root path for install, etc. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate set_root_dir(optarg); 124*7c478bd9Sstevel@tonic-gate break; 125*7c478bd9Sstevel@tonic-gate case 'v': 126*7c478bd9Sstevel@tonic-gate arg_vendor = optarg; 127*7c478bd9Sstevel@tonic-gate break; 128*7c478bd9Sstevel@tonic-gate case 'p': 129*7c478bd9Sstevel@tonic-gate arg_publisher = optarg; 130*7c478bd9Sstevel@tonic-gate break; 131*7c478bd9Sstevel@tonic-gate case 'c': 132*7c478bd9Sstevel@tonic-gate arg_class = optarg; 133*7c478bd9Sstevel@tonic-gate break; 134*7c478bd9Sstevel@tonic-gate case 's': 135*7c478bd9Sstevel@tonic-gate arg_subclass = optarg; 136*7c478bd9Sstevel@tonic-gate break; 137*7c478bd9Sstevel@tonic-gate case 'u': 138*7c478bd9Sstevel@tonic-gate arg_username = optarg; 139*7c478bd9Sstevel@tonic-gate break; 140*7c478bd9Sstevel@tonic-gate default: 141*7c478bd9Sstevel@tonic-gate return (usage()); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate if (optind < argc) { 146*7c478bd9Sstevel@tonic-gate arg_path = argv[optind++]; 147*7c478bd9Sstevel@tonic-gate if (optind < argc) { 148*7c478bd9Sstevel@tonic-gate arg_nargs = argc - optind; 149*7c478bd9Sstevel@tonic-gate arg_args = argv + optind; 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate enter_lock(root_dir); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if (strcmp(cmd, "add") == 0) { 156*7c478bd9Sstevel@tonic-gate rval = add_cmd(); 157*7c478bd9Sstevel@tonic-gate } else if (strcmp(cmd, "list") == 0) { 158*7c478bd9Sstevel@tonic-gate rval = list_remove_cmd(CMD_LIST); 159*7c478bd9Sstevel@tonic-gate } else if (strcmp(cmd, "remove") == 0) { 160*7c478bd9Sstevel@tonic-gate rval = list_remove_cmd(CMD_REMOVE); 161*7c478bd9Sstevel@tonic-gate } else if (strcmp(cmd, "restart") == 0) { 162*7c478bd9Sstevel@tonic-gate rval = restart_cmd(); 163*7c478bd9Sstevel@tonic-gate } else { 164*7c478bd9Sstevel@tonic-gate rval = usage(); 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate exit_lock(); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate return (rval); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate int 174*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 175*7c478bd9Sstevel@tonic-gate { 176*7c478bd9Sstevel@tonic-gate char *cmd; 177*7c478bd9Sstevel@tonic-gate int rval; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 181*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if ((whoami = strrchr(argv[0], '/')) == NULL) { 184*7c478bd9Sstevel@tonic-gate whoami = argv[0]; 185*7c478bd9Sstevel@tonic-gate } else { 186*7c478bd9Sstevel@tonic-gate whoami++; 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (argc == 1) { 190*7c478bd9Sstevel@tonic-gate return (usage_gen()); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate cmd = argv[optind++]; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate /* Allow non-privileged users to get the help messages */ 196*7c478bd9Sstevel@tonic-gate if (strcmp(cmd, "help") == 0) { 197*7c478bd9Sstevel@tonic-gate rval = usage_gen(); 198*7c478bd9Sstevel@tonic-gate return (rval); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (getuid() != 0) { 202*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_NOT_ROOT, whoami); 203*7c478bd9Sstevel@tonic-gate exit(EXIT_PERM); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate if (strcmp(cmd, "evc") != 0 && getzoneid() != GLOBAL_ZONEID) { 207*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_NOT_GLOBAL, whoami); 208*7c478bd9Sstevel@tonic-gate exit(EXIT_PERM); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if (strcmp(cmd, "add") == 0 || 212*7c478bd9Sstevel@tonic-gate strcmp(cmd, "remove") == 0 || strcmp(cmd, "list") == 0 || 213*7c478bd9Sstevel@tonic-gate strcmp(cmd, "restart") == 0) { 214*7c478bd9Sstevel@tonic-gate rval = serve_syseventdotconf(argc, argv, cmd); 215*7c478bd9Sstevel@tonic-gate } else { 216*7c478bd9Sstevel@tonic-gate rval = usage_gen(); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate return (rval); 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate static void 223*7c478bd9Sstevel@tonic-gate enter_lock(char *root_dir) 224*7c478bd9Sstevel@tonic-gate { 225*7c478bd9Sstevel@tonic-gate struct flock lock; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate if (snprintf(lock_file, sizeof (lock_file), "%s%s/%s", root_dir, 228*7c478bd9Sstevel@tonic-gate SYSEVENT_CONFIG_DIR, LOCK_FILENAME) >= sizeof (lock_file)) { 229*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_PATH_ERR, whoami, lock_file); 230*7c478bd9Sstevel@tonic-gate exit(EXIT_CMD_FAILED); 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate lock_fd = open(lock_file, O_CREAT|O_RDWR, 0644); 233*7c478bd9Sstevel@tonic-gate if (lock_fd < 0) { 234*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_CREATE_ERR, 235*7c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 236*7c478bd9Sstevel@tonic-gate exit(EXIT_CMD_FAILED); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 240*7c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 241*7c478bd9Sstevel@tonic-gate lock.l_start = 0; 242*7c478bd9Sstevel@tonic-gate lock.l_len = 0; 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate retry: 245*7c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLKW, &lock) == -1) { 246*7c478bd9Sstevel@tonic-gate if (errno == EAGAIN || errno == EINTR) 247*7c478bd9Sstevel@tonic-gate goto retry; 248*7c478bd9Sstevel@tonic-gate (void) close(lock_fd); 249*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_SET_ERR, 250*7c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 251*7c478bd9Sstevel@tonic-gate exit(EXIT_CMD_FAILED); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate static void 257*7c478bd9Sstevel@tonic-gate exit_lock() 258*7c478bd9Sstevel@tonic-gate { 259*7c478bd9Sstevel@tonic-gate struct flock lock; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate lock.l_type = F_UNLCK; 262*7c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 263*7c478bd9Sstevel@tonic-gate lock.l_start = 0; 264*7c478bd9Sstevel@tonic-gate lock.l_len = 0; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLK, &lock) == -1) { 267*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_CLR_ERR, 268*7c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate if (close(lock_fd) == -1) { 272*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_CLOSE_ERR, 273*7c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate static void 279*7c478bd9Sstevel@tonic-gate set_root_dir(char *dir) 280*7c478bd9Sstevel@tonic-gate { 281*7c478bd9Sstevel@tonic-gate root_dir = sc_strdup(dir); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate static char *usage_msg[] = { 286*7c478bd9Sstevel@tonic-gate "\n" 287*7c478bd9Sstevel@tonic-gate "\tsyseventadm add [-R <rootdir>] [-v vendor] [-p publisher]\n" 288*7c478bd9Sstevel@tonic-gate "\t[-c class] [-s subclass] [-u username] path [args]\n" 289*7c478bd9Sstevel@tonic-gate "\n" 290*7c478bd9Sstevel@tonic-gate "\tsyseventadm remove [-R <rootdir>] [-v vendor] [-p publisher]\n" 291*7c478bd9Sstevel@tonic-gate "\t[-c class] [-s subclass] [-u username] [path [args]]\n" 292*7c478bd9Sstevel@tonic-gate "\n" 293*7c478bd9Sstevel@tonic-gate "\tsyseventadm list [-R <rootdir>] [-v vendor] [-p publisher]\n" 294*7c478bd9Sstevel@tonic-gate "\t[-c class] [-s subclass] [-u username] [path [args]]\n" 295*7c478bd9Sstevel@tonic-gate }; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate static int 298*7c478bd9Sstevel@tonic-gate usage() 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate char **msgs; 301*7c478bd9Sstevel@tonic-gate int i; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate msgs = usage_msg; 304*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (usage_msg)/sizeof (char *); i++) { 305*7c478bd9Sstevel@tonic-gate (void) fputs(*msgs++, stderr); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate return (EXIT_USAGE); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate static int 313*7c478bd9Sstevel@tonic-gate add_cmd(void) 314*7c478bd9Sstevel@tonic-gate { 315*7c478bd9Sstevel@tonic-gate char fname[MAXPATHLEN+1]; 316*7c478bd9Sstevel@tonic-gate int need_comma = 0; 317*7c478bd9Sstevel@tonic-gate int noptions = 0; 318*7c478bd9Sstevel@tonic-gate struct stat st; 319*7c478bd9Sstevel@tonic-gate FILE *fp; 320*7c478bd9Sstevel@tonic-gate str_t *line; 321*7c478bd9Sstevel@tonic-gate int i; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * At least one of vendor/publisher/class must be specified. 325*7c478bd9Sstevel@tonic-gate * Subclass is only defined within the context of class. 326*7c478bd9Sstevel@tonic-gate * For add, path must also be specified. 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate if (arg_vendor) 329*7c478bd9Sstevel@tonic-gate noptions++; 330*7c478bd9Sstevel@tonic-gate if (arg_publisher) 331*7c478bd9Sstevel@tonic-gate noptions++; 332*7c478bd9Sstevel@tonic-gate if (arg_class) 333*7c478bd9Sstevel@tonic-gate noptions++; 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if (noptions == 0 || (arg_subclass && arg_class == NULL)) { 336*7c478bd9Sstevel@tonic-gate return (usage()); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate if (arg_path == NULL) 340*7c478bd9Sstevel@tonic-gate return (usage()); 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate /* 343*7c478bd9Sstevel@tonic-gate * Generate the sysevent.conf file name 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate (void) strcpy(fname, root_dir); 346*7c478bd9Sstevel@tonic-gate (void) strcat(fname, SYSEVENT_CONFIG_DIR); 347*7c478bd9Sstevel@tonic-gate (void) strcat(fname, "/"); 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate if (arg_vendor) { 350*7c478bd9Sstevel@tonic-gate (void) strcat(fname, arg_vendor); 351*7c478bd9Sstevel@tonic-gate need_comma = 1; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate if (arg_publisher) { 354*7c478bd9Sstevel@tonic-gate if (need_comma) 355*7c478bd9Sstevel@tonic-gate (void) strcat(fname, ","); 356*7c478bd9Sstevel@tonic-gate (void) strcat(fname, arg_publisher); 357*7c478bd9Sstevel@tonic-gate need_comma = 1; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate if (arg_class) { 360*7c478bd9Sstevel@tonic-gate if (need_comma) 361*7c478bd9Sstevel@tonic-gate (void) strcat(fname, ","); 362*7c478bd9Sstevel@tonic-gate (void) strcat(fname, arg_class); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate (void) strcat(fname, SYSEVENT_CONF_SUFFIX); 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * Prepare the line to be written to the sysevent.conf file 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate line = initstr(128); 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate strcats(line, arg_class == NULL ? "-" : arg_class); 372*7c478bd9Sstevel@tonic-gate strcatc(line, ' '); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate strcats(line, arg_subclass == NULL ? "-" : arg_subclass); 375*7c478bd9Sstevel@tonic-gate strcatc(line, ' '); 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate strcats(line, arg_vendor == NULL ? "-" : arg_vendor); 378*7c478bd9Sstevel@tonic-gate strcatc(line, ' '); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate strcats(line, arg_publisher == NULL ? "-" : arg_publisher); 381*7c478bd9Sstevel@tonic-gate strcatc(line, ' '); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate strcats(line, arg_username == NULL ? "-" : arg_username); 384*7c478bd9Sstevel@tonic-gate strcatc(line, ' '); 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate strcats(line, "- - "); 387*7c478bd9Sstevel@tonic-gate strcats(line, arg_path); 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate if (arg_nargs) { 390*7c478bd9Sstevel@tonic-gate for (i = 0; i < arg_nargs; i++) { 391*7c478bd9Sstevel@tonic-gate strcatc(line, ' '); 392*7c478bd9Sstevel@tonic-gate strcats(line, arg_args[i]); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate if (stat(fname, &st) == -1) { 397*7c478bd9Sstevel@tonic-gate if (creat(fname, 0644) == -1) { 398*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_CREATE, 399*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 400*7c478bd9Sstevel@tonic-gate freestr(line); 401*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate fp = fopen(fname, "a"); 406*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 407*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 408*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 409*7c478bd9Sstevel@tonic-gate freestr(line); 410*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", line->s_str); 414*7c478bd9Sstevel@tonic-gate freestr(line); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate if (fclose(fp) == -1) { 417*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CLOSE_ERROR, 418*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 419*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate if (chmod(fname, 0444) == -1) { 423*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CHMOD_ERROR, 424*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 425*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate return (EXIT_OK); 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate static int 432*7c478bd9Sstevel@tonic-gate list_remove_cmd(int cmd) 433*7c478bd9Sstevel@tonic-gate { 434*7c478bd9Sstevel@tonic-gate struct dirent *dp; 435*7c478bd9Sstevel@tonic-gate DIR *dir; 436*7c478bd9Sstevel@tonic-gate char path[MAXPATHLEN+1]; 437*7c478bd9Sstevel@tonic-gate char fname[MAXPATHLEN+1]; 438*7c478bd9Sstevel@tonic-gate char *suffix; 439*7c478bd9Sstevel@tonic-gate char **dirlist = NULL; 440*7c478bd9Sstevel@tonic-gate int list_size = 0; 441*7c478bd9Sstevel@tonic-gate int list_alloc = 0; 442*7c478bd9Sstevel@tonic-gate char **p; 443*7c478bd9Sstevel@tonic-gate int rval; 444*7c478bd9Sstevel@tonic-gate int result; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * For the remove cmd, at least one of vendor/publisher/class/username 448*7c478bd9Sstevel@tonic-gate * path must be specified. Subclass is only defined within the 449*7c478bd9Sstevel@tonic-gate * context of a class. 450*7c478bd9Sstevel@tonic-gate */ 451*7c478bd9Sstevel@tonic-gate if (cmd == CMD_REMOVE) { 452*7c478bd9Sstevel@tonic-gate int noptions = 0; 453*7c478bd9Sstevel@tonic-gate if (arg_vendor) 454*7c478bd9Sstevel@tonic-gate noptions++; 455*7c478bd9Sstevel@tonic-gate if (arg_publisher) 456*7c478bd9Sstevel@tonic-gate noptions++; 457*7c478bd9Sstevel@tonic-gate if (arg_class) 458*7c478bd9Sstevel@tonic-gate noptions++; 459*7c478bd9Sstevel@tonic-gate if (arg_username) 460*7c478bd9Sstevel@tonic-gate noptions++; 461*7c478bd9Sstevel@tonic-gate if (arg_path) 462*7c478bd9Sstevel@tonic-gate noptions++; 463*7c478bd9Sstevel@tonic-gate if (noptions == 0 || (arg_subclass && arg_class == NULL)) { 464*7c478bd9Sstevel@tonic-gate return (usage()); 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate (void) strcpy(path, root_dir); 469*7c478bd9Sstevel@tonic-gate (void) strcat(path, SYSEVENT_CONFIG_DIR); 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate if ((dir = opendir(path)) == NULL) { 472*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN_DIR, 473*7c478bd9Sstevel@tonic-gate whoami, path, strerror(errno)); 474*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate while ((dp = readdir(dir)) != NULL) { 478*7c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.') 479*7c478bd9Sstevel@tonic-gate continue; 480*7c478bd9Sstevel@tonic-gate if ((strlen(dp->d_name) == 0) || 481*7c478bd9Sstevel@tonic-gate (strcmp(dp->d_name, "lost+found") == 0)) 482*7c478bd9Sstevel@tonic-gate continue; 483*7c478bd9Sstevel@tonic-gate suffix = strrchr(dp->d_name, ','); 484*7c478bd9Sstevel@tonic-gate if (suffix && strcmp(suffix, SYSEVENT_CONF_SUFFIX) == 0) { 485*7c478bd9Sstevel@tonic-gate (void) strcpy(fname, path); 486*7c478bd9Sstevel@tonic-gate (void) strcat(fname, "/"); 487*7c478bd9Sstevel@tonic-gate (void) strcat(fname, dp->d_name); 488*7c478bd9Sstevel@tonic-gate dirlist = build_strlist(dirlist, 489*7c478bd9Sstevel@tonic-gate &list_size, &list_alloc, fname); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate if (closedir(dir) == -1) { 494*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CLOSE_DIR_ERROR, 495*7c478bd9Sstevel@tonic-gate whoami, path, strerror(errno)); 496*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate rval = EXIT_NO_MATCH; 500*7c478bd9Sstevel@tonic-gate if (dirlist) { 501*7c478bd9Sstevel@tonic-gate for (p = dirlist; *p != NULL; p++) { 502*7c478bd9Sstevel@tonic-gate switch (cmd) { 503*7c478bd9Sstevel@tonic-gate case CMD_LIST: 504*7c478bd9Sstevel@tonic-gate result = list_file(*p); 505*7c478bd9Sstevel@tonic-gate break; 506*7c478bd9Sstevel@tonic-gate case CMD_REMOVE: 507*7c478bd9Sstevel@tonic-gate result = remove_file(*p); 508*7c478bd9Sstevel@tonic-gate break; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate if (rval == EXIT_NO_MATCH && 511*7c478bd9Sstevel@tonic-gate result != EXIT_NO_MATCH) 512*7c478bd9Sstevel@tonic-gate rval = result; 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate return (rval); 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate static int 520*7c478bd9Sstevel@tonic-gate list_file(char *fname) 521*7c478bd9Sstevel@tonic-gate { 522*7c478bd9Sstevel@tonic-gate FILE *fp; 523*7c478bd9Sstevel@tonic-gate str_t *line; 524*7c478bd9Sstevel@tonic-gate serecord_t *sep; 525*7c478bd9Sstevel@tonic-gate int rval = EXIT_NO_MATCH; 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate fp = fopen(fname, "r"); 528*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 529*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 530*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 531*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate for (;;) { 534*7c478bd9Sstevel@tonic-gate line = read_next_line(fp); 535*7c478bd9Sstevel@tonic-gate if (line == NULL) 536*7c478bd9Sstevel@tonic-gate break; 537*7c478bd9Sstevel@tonic-gate sep = parse_line(line); 538*7c478bd9Sstevel@tonic-gate if (sep != NULL) { 539*7c478bd9Sstevel@tonic-gate if (matches_serecord(sep)) { 540*7c478bd9Sstevel@tonic-gate print_serecord(stdout, sep); 541*7c478bd9Sstevel@tonic-gate rval = EXIT_OK; 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate free_serecord(sep); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate freestr(line); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate return (rval); 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate static int 554*7c478bd9Sstevel@tonic-gate remove_file(char *fname) 555*7c478bd9Sstevel@tonic-gate { 556*7c478bd9Sstevel@tonic-gate FILE *fp; 557*7c478bd9Sstevel@tonic-gate FILE *tmp_fp; 558*7c478bd9Sstevel@tonic-gate str_t *line; 559*7c478bd9Sstevel@tonic-gate char *raw_line; 560*7c478bd9Sstevel@tonic-gate serecord_t *sep; 561*7c478bd9Sstevel@tonic-gate char tmp_name[MAXPATHLEN+1]; 562*7c478bd9Sstevel@tonic-gate int is_empty = 1; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate fp = fopen(fname, "r"); 565*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 566*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 567*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 568*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate if (check_for_removes(fp) == 0) { 572*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 573*7c478bd9Sstevel@tonic-gate return (EXIT_NO_MATCH); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate rewind(fp); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate (void) strcpy(tmp_name, root_dir); 579*7c478bd9Sstevel@tonic-gate (void) strcat(tmp_name, SYSEVENT_CONFIG_DIR); 580*7c478bd9Sstevel@tonic-gate (void) strcat(tmp_name, "/tmp.XXXXXX"); 581*7c478bd9Sstevel@tonic-gate if (mktemp(tmp_name) == NULL) { 582*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unable to make tmp file name\n"); 583*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate if (creat(tmp_name, 0644) == -1) { 587*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_CREATE, 588*7c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 589*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate tmp_fp = fopen(tmp_name, "a"); 593*7c478bd9Sstevel@tonic-gate if (tmp_fp == NULL) { 594*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 595*7c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 596*7c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 597*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 598*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate for (;;) { 602*7c478bd9Sstevel@tonic-gate line = read_next_line(fp); 603*7c478bd9Sstevel@tonic-gate if (line == NULL) 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate raw_line = sc_strdup(line->s_str); 606*7c478bd9Sstevel@tonic-gate sep = parse_line(line); 607*7c478bd9Sstevel@tonic-gate if (sep == NULL) { 608*7c478bd9Sstevel@tonic-gate (void) fputs(line->s_str, tmp_fp); 609*7c478bd9Sstevel@tonic-gate } else { 610*7c478bd9Sstevel@tonic-gate if (!matches_serecord(sep)) { 611*7c478bd9Sstevel@tonic-gate is_empty = 0; 612*7c478bd9Sstevel@tonic-gate (void) fprintf(tmp_fp, "%s\n", raw_line); 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate free_serecord(sep); 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate freestr(line); 617*7c478bd9Sstevel@tonic-gate sc_strfree(raw_line); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 620*7c478bd9Sstevel@tonic-gate if (fclose(tmp_fp) == -1) { 621*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CLOSE_ERROR, 622*7c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate if (is_empty) { 626*7c478bd9Sstevel@tonic-gate if (unlink(tmp_name) == -1) { 627*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_UNLINK, 628*7c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 629*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate if (unlink(fname) == -1) { 632*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_UNLINK, 633*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 634*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate } else { 637*7c478bd9Sstevel@tonic-gate if (unlink(fname) == -1) { 638*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_UNLINK, 639*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 640*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate if (rename(tmp_name, fname) == -1) { 643*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_RENAME, 644*7c478bd9Sstevel@tonic-gate whoami, tmp_name, fname, strerror(errno)); 645*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate if (chmod(fname, 0444) == -1) { 648*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CHMOD_ERROR, 649*7c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 650*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate return (EXIT_OK); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate static int 658*7c478bd9Sstevel@tonic-gate check_for_removes(FILE *fp) 659*7c478bd9Sstevel@tonic-gate { 660*7c478bd9Sstevel@tonic-gate str_t *line; 661*7c478bd9Sstevel@tonic-gate serecord_t *sep; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate for (;;) { 664*7c478bd9Sstevel@tonic-gate line = read_next_line(fp); 665*7c478bd9Sstevel@tonic-gate if (line == NULL) 666*7c478bd9Sstevel@tonic-gate break; 667*7c478bd9Sstevel@tonic-gate sep = parse_line(line); 668*7c478bd9Sstevel@tonic-gate if (sep != NULL) { 669*7c478bd9Sstevel@tonic-gate if (matches_serecord(sep)) { 670*7c478bd9Sstevel@tonic-gate free_serecord(sep); 671*7c478bd9Sstevel@tonic-gate freestr(line); 672*7c478bd9Sstevel@tonic-gate return (1); 673*7c478bd9Sstevel@tonic-gate } 674*7c478bd9Sstevel@tonic-gate free_serecord(sep); 675*7c478bd9Sstevel@tonic-gate } 676*7c478bd9Sstevel@tonic-gate freestr(line); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate return (0); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate static int 684*7c478bd9Sstevel@tonic-gate matches_serecord(serecord_t *sep) 685*7c478bd9Sstevel@tonic-gate { 686*7c478bd9Sstevel@tonic-gate char *line; 687*7c478bd9Sstevel@tonic-gate char *lp; 688*7c478bd9Sstevel@tonic-gate char *token; 689*7c478bd9Sstevel@tonic-gate int i; 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate if (arg_vendor && 692*7c478bd9Sstevel@tonic-gate strcmp(arg_vendor, sep->se_vendor) != 0) { 693*7c478bd9Sstevel@tonic-gate return (0); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate if (arg_publisher && 697*7c478bd9Sstevel@tonic-gate strcmp(arg_publisher, sep->se_publisher) != 0) { 698*7c478bd9Sstevel@tonic-gate return (0); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate if (arg_class && 702*7c478bd9Sstevel@tonic-gate strcmp(arg_class, sep->se_class) != 0) { 703*7c478bd9Sstevel@tonic-gate return (0); 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate if (arg_subclass && 707*7c478bd9Sstevel@tonic-gate strcmp(arg_subclass, sep->se_subclass) != 0) { 708*7c478bd9Sstevel@tonic-gate return (0); 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate if (arg_username && 712*7c478bd9Sstevel@tonic-gate strcmp(arg_username, sep->se_user) != 0) { 713*7c478bd9Sstevel@tonic-gate return (0); 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate 716*7c478bd9Sstevel@tonic-gate if (arg_path && 717*7c478bd9Sstevel@tonic-gate strcmp(arg_path, sep->se_path) != 0) { 718*7c478bd9Sstevel@tonic-gate return (0); 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate if (arg_nargs > 0) { 722*7c478bd9Sstevel@tonic-gate line = sc_strdup(sep->se_args); 723*7c478bd9Sstevel@tonic-gate lp = line; 724*7c478bd9Sstevel@tonic-gate for (i = 0; i < arg_nargs; i++) { 725*7c478bd9Sstevel@tonic-gate token = next_field(&lp); 726*7c478bd9Sstevel@tonic-gate if (strcmp(arg_args[i], token) != 0) { 727*7c478bd9Sstevel@tonic-gate sc_strfree(line); 728*7c478bd9Sstevel@tonic-gate return (0); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate sc_strfree(line); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate return (1); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate static void 738*7c478bd9Sstevel@tonic-gate print_serecord(FILE *fp, serecord_t *sep) 739*7c478bd9Sstevel@tonic-gate { 740*7c478bd9Sstevel@tonic-gate str_t *line; 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate line = initstr(128); 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate if (strcmp(sep->se_vendor, "-") != 0) { 745*7c478bd9Sstevel@tonic-gate strcats(line, "vendor="); 746*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_vendor); 747*7c478bd9Sstevel@tonic-gate strcats(line, " "); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate if (strcmp(sep->se_publisher, "-") != 0) { 750*7c478bd9Sstevel@tonic-gate strcats(line, "publisher="); 751*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_publisher); 752*7c478bd9Sstevel@tonic-gate strcats(line, " "); 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate if (strcmp(sep->se_class, "-") != 0) { 755*7c478bd9Sstevel@tonic-gate strcats(line, "class="); 756*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_class); 757*7c478bd9Sstevel@tonic-gate strcats(line, " "); 758*7c478bd9Sstevel@tonic-gate if (strcmp(sep->se_subclass, "-") != 0) { 759*7c478bd9Sstevel@tonic-gate strcats(line, "subclass="); 760*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_subclass); 761*7c478bd9Sstevel@tonic-gate strcats(line, " "); 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate if (strcmp(sep->se_user, "-") != 0) { 765*7c478bd9Sstevel@tonic-gate strcats(line, "username="); 766*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_user); 767*7c478bd9Sstevel@tonic-gate strcats(line, " "); 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_path); 770*7c478bd9Sstevel@tonic-gate if (sep->se_args) { 771*7c478bd9Sstevel@tonic-gate strcats(line, " "); 772*7c478bd9Sstevel@tonic-gate strcats(line, sep->se_args); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate strcats(line, "\n"); 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate (void) fputs(line->s_str, fp); 777*7c478bd9Sstevel@tonic-gate freestr(line); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate static int 784*7c478bd9Sstevel@tonic-gate restart_cmd(void) 785*7c478bd9Sstevel@tonic-gate { 786*7c478bd9Sstevel@tonic-gate if (system("pkill -HUP syseventd") == -1) { 787*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_RESTART_FAILED, 788*7c478bd9Sstevel@tonic-gate whoami, strerror(errno)); 789*7c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate return (EXIT_OK); 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate static str_t * 796*7c478bd9Sstevel@tonic-gate read_next_line(FILE *fp) 797*7c478bd9Sstevel@tonic-gate { 798*7c478bd9Sstevel@tonic-gate char *lp; 799*7c478bd9Sstevel@tonic-gate str_t *line; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate line = initstr(128); 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate lp = fstrgets(line, fp); 804*7c478bd9Sstevel@tonic-gate if (lp == NULL) { 805*7c478bd9Sstevel@tonic-gate freestr(line); 806*7c478bd9Sstevel@tonic-gate return (NULL); 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate *(lp + strlen(lp)-1) = 0; 810*7c478bd9Sstevel@tonic-gate return (line); 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate static serecord_t * 815*7c478bd9Sstevel@tonic-gate parse_line(str_t *line) 816*7c478bd9Sstevel@tonic-gate { 817*7c478bd9Sstevel@tonic-gate char *lp; 818*7c478bd9Sstevel@tonic-gate char *vendor, *publisher; 819*7c478bd9Sstevel@tonic-gate char *class, *subclass; 820*7c478bd9Sstevel@tonic-gate char *user; 821*7c478bd9Sstevel@tonic-gate char *reserved1, *reserved2; 822*7c478bd9Sstevel@tonic-gate char *path, *args; 823*7c478bd9Sstevel@tonic-gate serecord_t *sep; 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate lp = line->s_str; 826*7c478bd9Sstevel@tonic-gate if (*lp == 0 || *lp == '#') { 827*7c478bd9Sstevel@tonic-gate return (NULL); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate if ((class = next_field(&lp)) != NULL) { 831*7c478bd9Sstevel@tonic-gate subclass = next_field(&lp); 832*7c478bd9Sstevel@tonic-gate if (lp == NULL) 833*7c478bd9Sstevel@tonic-gate return (NULL); 834*7c478bd9Sstevel@tonic-gate vendor = next_field(&lp); 835*7c478bd9Sstevel@tonic-gate if (lp == NULL) 836*7c478bd9Sstevel@tonic-gate return (NULL); 837*7c478bd9Sstevel@tonic-gate publisher = next_field(&lp); 838*7c478bd9Sstevel@tonic-gate if (lp == NULL) 839*7c478bd9Sstevel@tonic-gate return (NULL); 840*7c478bd9Sstevel@tonic-gate user = next_field(&lp); 841*7c478bd9Sstevel@tonic-gate if (lp == NULL) 842*7c478bd9Sstevel@tonic-gate return (NULL); 843*7c478bd9Sstevel@tonic-gate reserved1 = next_field(&lp); 844*7c478bd9Sstevel@tonic-gate if (lp == NULL) 845*7c478bd9Sstevel@tonic-gate return (NULL); 846*7c478bd9Sstevel@tonic-gate reserved2 = next_field(&lp); 847*7c478bd9Sstevel@tonic-gate if (lp == NULL) 848*7c478bd9Sstevel@tonic-gate return (NULL); 849*7c478bd9Sstevel@tonic-gate path = next_field(&lp); 850*7c478bd9Sstevel@tonic-gate if (lp == NULL) 851*7c478bd9Sstevel@tonic-gate return (NULL); 852*7c478bd9Sstevel@tonic-gate args = skip_spaces(&lp); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate sep = sc_malloc(sizeof (serecord_t)); 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate sep->se_vendor = sc_strdup(vendor); 858*7c478bd9Sstevel@tonic-gate sep->se_publisher = sc_strdup(publisher); 859*7c478bd9Sstevel@tonic-gate sep->se_class = sc_strdup(class); 860*7c478bd9Sstevel@tonic-gate sep->se_subclass = sc_strdup(subclass); 861*7c478bd9Sstevel@tonic-gate sep->se_user = sc_strdup(user); 862*7c478bd9Sstevel@tonic-gate sep->se_reserved1 = sc_strdup(reserved1); 863*7c478bd9Sstevel@tonic-gate sep->se_reserved2 = sc_strdup(reserved2); 864*7c478bd9Sstevel@tonic-gate sep->se_path = sc_strdup(path); 865*7c478bd9Sstevel@tonic-gate sep->se_args = (args == NULL) ? NULL : sc_strdup(args); 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate return (sep); 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate static void 872*7c478bd9Sstevel@tonic-gate free_serecord(serecord_t *sep) 873*7c478bd9Sstevel@tonic-gate { 874*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_vendor); 875*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_publisher); 876*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_class); 877*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_subclass); 878*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_user); 879*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved1); 880*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved2); 881*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_path); 882*7c478bd9Sstevel@tonic-gate sc_strfree(sep->se_args); 883*7c478bd9Sstevel@tonic-gate sc_free(sep, sizeof (serecord_t)); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate /* 888*7c478bd9Sstevel@tonic-gate * skip_spaces() - skip to next non-space character 889*7c478bd9Sstevel@tonic-gate */ 890*7c478bd9Sstevel@tonic-gate static char * 891*7c478bd9Sstevel@tonic-gate skip_spaces(char **cpp) 892*7c478bd9Sstevel@tonic-gate { 893*7c478bd9Sstevel@tonic-gate char *cp = *cpp; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 896*7c478bd9Sstevel@tonic-gate cp++; 897*7c478bd9Sstevel@tonic-gate if (*cp == 0) { 898*7c478bd9Sstevel@tonic-gate *cpp = 0; 899*7c478bd9Sstevel@tonic-gate return (NULL); 900*7c478bd9Sstevel@tonic-gate } 901*7c478bd9Sstevel@tonic-gate return (cp); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * Get next white-space separated field. 907*7c478bd9Sstevel@tonic-gate * next_field() will not check any characters on next line. 908*7c478bd9Sstevel@tonic-gate * Each entry is composed of a single line. 909*7c478bd9Sstevel@tonic-gate */ 910*7c478bd9Sstevel@tonic-gate static char * 911*7c478bd9Sstevel@tonic-gate next_field(char **cpp) 912*7c478bd9Sstevel@tonic-gate { 913*7c478bd9Sstevel@tonic-gate char *cp = *cpp; 914*7c478bd9Sstevel@tonic-gate char *start; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 917*7c478bd9Sstevel@tonic-gate cp++; 918*7c478bd9Sstevel@tonic-gate if (*cp == 0) { 919*7c478bd9Sstevel@tonic-gate *cpp = 0; 920*7c478bd9Sstevel@tonic-gate return (NULL); 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate start = cp; 923*7c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t') 924*7c478bd9Sstevel@tonic-gate cp++; 925*7c478bd9Sstevel@tonic-gate if (*cp != 0) 926*7c478bd9Sstevel@tonic-gate *cp++ = 0; 927*7c478bd9Sstevel@tonic-gate *cpp = cp; 928*7c478bd9Sstevel@tonic-gate return (start); 929*7c478bd9Sstevel@tonic-gate } 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * The following functions are simple wrappers/equivalents 935*7c478bd9Sstevel@tonic-gate * for malloc, realloc, free, strdup and a special free 936*7c478bd9Sstevel@tonic-gate * for strdup. 937*7c478bd9Sstevel@tonic-gate */ 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate static void * 940*7c478bd9Sstevel@tonic-gate sc_malloc(size_t n) 941*7c478bd9Sstevel@tonic-gate { 942*7c478bd9Sstevel@tonic-gate void *p; 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate p = malloc(n); 945*7c478bd9Sstevel@tonic-gate if (p == NULL) { 946*7c478bd9Sstevel@tonic-gate no_mem_err(); 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate return (p); 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 952*7c478bd9Sstevel@tonic-gate static void * 953*7c478bd9Sstevel@tonic-gate sc_realloc(void *p, size_t current, size_t n) 954*7c478bd9Sstevel@tonic-gate { 955*7c478bd9Sstevel@tonic-gate p = realloc(p, n); 956*7c478bd9Sstevel@tonic-gate if (p == NULL) { 957*7c478bd9Sstevel@tonic-gate no_mem_err(); 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate return (p); 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 964*7c478bd9Sstevel@tonic-gate static void 965*7c478bd9Sstevel@tonic-gate sc_free(void *p, size_t n) 966*7c478bd9Sstevel@tonic-gate { 967*7c478bd9Sstevel@tonic-gate free(p); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate static char * 972*7c478bd9Sstevel@tonic-gate sc_strdup(char *cp) 973*7c478bd9Sstevel@tonic-gate { 974*7c478bd9Sstevel@tonic-gate char *new; 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate new = malloc((unsigned)(strlen(cp) + 1)); 977*7c478bd9Sstevel@tonic-gate if (new == NULL) { 978*7c478bd9Sstevel@tonic-gate no_mem_err(); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate (void) strcpy(new, cp); 981*7c478bd9Sstevel@tonic-gate return (new); 982*7c478bd9Sstevel@tonic-gate } 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate static void 986*7c478bd9Sstevel@tonic-gate sc_strfree(char *s) 987*7c478bd9Sstevel@tonic-gate { 988*7c478bd9Sstevel@tonic-gate if (s) 989*7c478bd9Sstevel@tonic-gate free(s); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate 993*7c478bd9Sstevel@tonic-gate /* 994*7c478bd9Sstevel@tonic-gate * The following functions provide some simple dynamic string 995*7c478bd9Sstevel@tonic-gate * capability. This module has no hard-coded maximum string 996*7c478bd9Sstevel@tonic-gate * lengths and should be able to parse and generate arbitrarily 997*7c478bd9Sstevel@tonic-gate * long strings, macro expansion and command lines. 998*7c478bd9Sstevel@tonic-gate * 999*7c478bd9Sstevel@tonic-gate * Each string must be explicitly allocated and freed. 1000*7c478bd9Sstevel@tonic-gate */ 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate /* 1003*7c478bd9Sstevel@tonic-gate * Allocate a dynamic string, with a hint to indicate how 1004*7c478bd9Sstevel@tonic-gate * much memory to dynamically add to the string as it grows 1005*7c478bd9Sstevel@tonic-gate * beyond its existing bounds, so as to avoid excessive 1006*7c478bd9Sstevel@tonic-gate * reallocs as a string grows. 1007*7c478bd9Sstevel@tonic-gate */ 1008*7c478bd9Sstevel@tonic-gate static str_t * 1009*7c478bd9Sstevel@tonic-gate initstr(int hint) 1010*7c478bd9Sstevel@tonic-gate { 1011*7c478bd9Sstevel@tonic-gate str_t *str; 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate str = sc_malloc(sizeof (str_t)); 1014*7c478bd9Sstevel@tonic-gate str->s_str = NULL; 1015*7c478bd9Sstevel@tonic-gate str->s_len = 0; 1016*7c478bd9Sstevel@tonic-gate str->s_alloc = 0; 1017*7c478bd9Sstevel@tonic-gate str->s_hint = hint; 1018*7c478bd9Sstevel@tonic-gate return (str); 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate /* 1023*7c478bd9Sstevel@tonic-gate * Free a dynamically-allocated string 1024*7c478bd9Sstevel@tonic-gate */ 1025*7c478bd9Sstevel@tonic-gate static void 1026*7c478bd9Sstevel@tonic-gate freestr(str_t *str) 1027*7c478bd9Sstevel@tonic-gate { 1028*7c478bd9Sstevel@tonic-gate if (str->s_str) { 1029*7c478bd9Sstevel@tonic-gate sc_free(str->s_str, str->s_alloc); 1030*7c478bd9Sstevel@tonic-gate } 1031*7c478bd9Sstevel@tonic-gate sc_free(str, sizeof (str_t)); 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate /* 1036*7c478bd9Sstevel@tonic-gate * Reset a dynamically-allocated string, allows reuse 1037*7c478bd9Sstevel@tonic-gate * rather than freeing the old and allocating a new one. 1038*7c478bd9Sstevel@tonic-gate */ 1039*7c478bd9Sstevel@tonic-gate static void 1040*7c478bd9Sstevel@tonic-gate resetstr(str_t *str) 1041*7c478bd9Sstevel@tonic-gate { 1042*7c478bd9Sstevel@tonic-gate str->s_len = 0; 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate /* 1047*7c478bd9Sstevel@tonic-gate * Concatenate a (simple) string onto a dynamically-allocated string 1048*7c478bd9Sstevel@tonic-gate */ 1049*7c478bd9Sstevel@tonic-gate static void 1050*7c478bd9Sstevel@tonic-gate strcats(str_t *str, char *s) 1051*7c478bd9Sstevel@tonic-gate { 1052*7c478bd9Sstevel@tonic-gate char *new_str; 1053*7c478bd9Sstevel@tonic-gate int len = str->s_len + strlen(s) + 1; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 1056*7c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : 1057*7c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 1058*7c478bd9Sstevel@tonic-gate str->s_str = new_str; 1059*7c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 1060*7c478bd9Sstevel@tonic-gate } 1061*7c478bd9Sstevel@tonic-gate (void) strcpy(str->s_str + str->s_len, s); 1062*7c478bd9Sstevel@tonic-gate str->s_len = len - 1; 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate /* 1067*7c478bd9Sstevel@tonic-gate * Concatenate a character onto a dynamically-allocated string 1068*7c478bd9Sstevel@tonic-gate */ 1069*7c478bd9Sstevel@tonic-gate static void 1070*7c478bd9Sstevel@tonic-gate strcatc(str_t *str, int c) 1071*7c478bd9Sstevel@tonic-gate { 1072*7c478bd9Sstevel@tonic-gate char *new_str; 1073*7c478bd9Sstevel@tonic-gate int len = str->s_len + 2; 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 1076*7c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : 1077*7c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 1078*7c478bd9Sstevel@tonic-gate str->s_str = new_str; 1079*7c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 1080*7c478bd9Sstevel@tonic-gate } 1081*7c478bd9Sstevel@tonic-gate *(str->s_str + str->s_len) = (char)c; 1082*7c478bd9Sstevel@tonic-gate *(str->s_str + str->s_len + 1) = 0; 1083*7c478bd9Sstevel@tonic-gate str->s_len++; 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate 1086*7c478bd9Sstevel@tonic-gate /* 1087*7c478bd9Sstevel@tonic-gate * fgets() equivalent using a dynamically-allocated string 1088*7c478bd9Sstevel@tonic-gate */ 1089*7c478bd9Sstevel@tonic-gate static char * 1090*7c478bd9Sstevel@tonic-gate fstrgets(str_t *line, FILE *fp) 1091*7c478bd9Sstevel@tonic-gate { 1092*7c478bd9Sstevel@tonic-gate int c; 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate resetstr(line); 1095*7c478bd9Sstevel@tonic-gate while ((c = fgetc(fp)) != EOF) { 1096*7c478bd9Sstevel@tonic-gate strcatc(line, c); 1097*7c478bd9Sstevel@tonic-gate if (c == '\n') 1098*7c478bd9Sstevel@tonic-gate break; 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate if (line->s_len == 0) 1101*7c478bd9Sstevel@tonic-gate return (NULL); 1102*7c478bd9Sstevel@tonic-gate return (line->s_str); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate #define INITIAL_LISTSIZE 4 1108*7c478bd9Sstevel@tonic-gate #define INCR_LISTSIZE 4 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate static char ** 1111*7c478bd9Sstevel@tonic-gate build_strlist( 1112*7c478bd9Sstevel@tonic-gate char **argvlist, 1113*7c478bd9Sstevel@tonic-gate int *size, 1114*7c478bd9Sstevel@tonic-gate int *alloc, 1115*7c478bd9Sstevel@tonic-gate char *str) 1116*7c478bd9Sstevel@tonic-gate { 1117*7c478bd9Sstevel@tonic-gate int n; 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate if (*size + 1 > *alloc) { 1120*7c478bd9Sstevel@tonic-gate if (*alloc == 0) { 1121*7c478bd9Sstevel@tonic-gate *alloc = INITIAL_LISTSIZE; 1122*7c478bd9Sstevel@tonic-gate n = sizeof (char *) * (*alloc + 1); 1123*7c478bd9Sstevel@tonic-gate argvlist = (char **)malloc(n); 1124*7c478bd9Sstevel@tonic-gate if (argvlist == NULL) 1125*7c478bd9Sstevel@tonic-gate no_mem_err(); 1126*7c478bd9Sstevel@tonic-gate } else { 1127*7c478bd9Sstevel@tonic-gate *alloc += INCR_LISTSIZE; 1128*7c478bd9Sstevel@tonic-gate n = sizeof (char *) * (*alloc + 1); 1129*7c478bd9Sstevel@tonic-gate argvlist = (char **)realloc(argvlist, n); 1130*7c478bd9Sstevel@tonic-gate if (argvlist == NULL) 1131*7c478bd9Sstevel@tonic-gate no_mem_err(); 1132*7c478bd9Sstevel@tonic-gate } 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate argvlist[*size] = strdup(str); 1136*7c478bd9Sstevel@tonic-gate *size += 1; 1137*7c478bd9Sstevel@tonic-gate argvlist[*size] = NULL; 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate return (argvlist); 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate 1142*7c478bd9Sstevel@tonic-gate static void 1143*7c478bd9Sstevel@tonic-gate no_mem_err() 1144*7c478bd9Sstevel@tonic-gate { 1145*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_NO_MEM, whoami); 1146*7c478bd9Sstevel@tonic-gate exit_lock(); 1147*7c478bd9Sstevel@tonic-gate exit(EXIT_NO_MEM); 1148*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1149*7c478bd9Sstevel@tonic-gate } 1150