17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*c6fc6dddSEric Schrock * Common Development and Distribution License (the "License"). 6*c6fc6dddSEric Schrock * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*c6fc6dddSEric Schrock * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * syseventadm - command to administer the sysevent.conf registry 287c478bd9Sstevel@tonic-gate * - administers the general purpose event framework 297c478bd9Sstevel@tonic-gate * 307c478bd9Sstevel@tonic-gate * The current implementation of the registry using files in 317c478bd9Sstevel@tonic-gate * /etc/sysevent/config, files are named as event specifications 327c478bd9Sstevel@tonic-gate * are added with the combination of the vendor, publisher, event 337c478bd9Sstevel@tonic-gate * class and subclass strings: 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * [<vendor>,][<publisher>,][<class>,]sysevent.conf 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate */ 387c478bd9Sstevel@tonic-gate #include <stdio.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <dirent.h> 427c478bd9Sstevel@tonic-gate #include <stdarg.h> 437c478bd9Sstevel@tonic-gate #include <stddef.h> 447c478bd9Sstevel@tonic-gate #include <stdlib.h> 457c478bd9Sstevel@tonic-gate #include <dlfcn.h> 467c478bd9Sstevel@tonic-gate #include <door.h> 477c478bd9Sstevel@tonic-gate #include <errno.h> 487c478bd9Sstevel@tonic-gate #include <fcntl.h> 497c478bd9Sstevel@tonic-gate #include <signal.h> 507c478bd9Sstevel@tonic-gate #include <strings.h> 517c478bd9Sstevel@tonic-gate #include <unistd.h> 527c478bd9Sstevel@tonic-gate #include <synch.h> 537c478bd9Sstevel@tonic-gate #include <syslog.h> 547c478bd9Sstevel@tonic-gate #include <thread.h> 557c478bd9Sstevel@tonic-gate #include <limits.h> 567c478bd9Sstevel@tonic-gate #include <locale.h> 577c478bd9Sstevel@tonic-gate #include <assert.h> 587c478bd9Sstevel@tonic-gate #include <libsysevent.h> 597c478bd9Sstevel@tonic-gate #include <zone.h> 607c478bd9Sstevel@tonic-gate #include <sys/sysevent_impl.h> 617c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 627c478bd9Sstevel@tonic-gate #include <sys/param.h> 637c478bd9Sstevel@tonic-gate #include <sys/stat.h> 647c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 657c478bd9Sstevel@tonic-gate #include <sys/wait.h> 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate #include "syseventadm.h" 687c478bd9Sstevel@tonic-gate #include "syseventadm_msg.h" 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #ifndef DEBUG 717c478bd9Sstevel@tonic-gate #undef assert 727c478bd9Sstevel@tonic-gate #define assert(EX) ((void)0) 737c478bd9Sstevel@tonic-gate #endif 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate static char *whoami = NULL; 767c478bd9Sstevel@tonic-gate static char *root_dir = ""; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static char *arg_vendor = NULL; 797c478bd9Sstevel@tonic-gate static char *arg_publisher = NULL; 807c478bd9Sstevel@tonic-gate static char *arg_class = NULL; 817c478bd9Sstevel@tonic-gate static char *arg_subclass = NULL; 827c478bd9Sstevel@tonic-gate static char *arg_username = NULL; 837c478bd9Sstevel@tonic-gate static char *arg_path = NULL; 847c478bd9Sstevel@tonic-gate static int arg_nargs = 0; 857c478bd9Sstevel@tonic-gate static char **arg_args = NULL; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static int lock_fd; 887c478bd9Sstevel@tonic-gate static char lock_file[PATH_MAX + 1]; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate extern char *optarg; 917c478bd9Sstevel@tonic-gate extern int optind; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static int 947c478bd9Sstevel@tonic-gate usage_gen() 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_USAGE_INTRO); 977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_USAGE_OPTIONS); 987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n" 997c478bd9Sstevel@tonic-gate "\tsyseventadm add ...\n" 1007c478bd9Sstevel@tonic-gate "\tsyseventadm remove ...\n" 1017c478bd9Sstevel@tonic-gate "\tsyseventadm list ...\n" 1027c478bd9Sstevel@tonic-gate "\tsyseventadm restart\n" 1037c478bd9Sstevel@tonic-gate "\tsyseventadm help\n"); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate return (EXIT_USAGE); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static int 1097c478bd9Sstevel@tonic-gate serve_syseventdotconf(int argc, char **argv, char *cmd) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate int c; 1127c478bd9Sstevel@tonic-gate int rval; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "R:v:p:c:s:u:")) != EOF) { 1157c478bd9Sstevel@tonic-gate switch (c) { 1167c478bd9Sstevel@tonic-gate case 'R': 1177c478bd9Sstevel@tonic-gate /* 1187c478bd9Sstevel@tonic-gate * Alternate root path for install, etc. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate set_root_dir(optarg); 1217c478bd9Sstevel@tonic-gate break; 1227c478bd9Sstevel@tonic-gate case 'v': 1237c478bd9Sstevel@tonic-gate arg_vendor = optarg; 1247c478bd9Sstevel@tonic-gate break; 1257c478bd9Sstevel@tonic-gate case 'p': 1267c478bd9Sstevel@tonic-gate arg_publisher = optarg; 1277c478bd9Sstevel@tonic-gate break; 1287c478bd9Sstevel@tonic-gate case 'c': 1297c478bd9Sstevel@tonic-gate arg_class = optarg; 1307c478bd9Sstevel@tonic-gate break; 1317c478bd9Sstevel@tonic-gate case 's': 1327c478bd9Sstevel@tonic-gate arg_subclass = optarg; 1337c478bd9Sstevel@tonic-gate break; 1347c478bd9Sstevel@tonic-gate case 'u': 1357c478bd9Sstevel@tonic-gate arg_username = optarg; 1367c478bd9Sstevel@tonic-gate break; 1377c478bd9Sstevel@tonic-gate default: 1387c478bd9Sstevel@tonic-gate return (usage()); 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate if (optind < argc) { 1437c478bd9Sstevel@tonic-gate arg_path = argv[optind++]; 1447c478bd9Sstevel@tonic-gate if (optind < argc) { 1457c478bd9Sstevel@tonic-gate arg_nargs = argc - optind; 1467c478bd9Sstevel@tonic-gate arg_args = argv + optind; 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate enter_lock(root_dir); 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if (strcmp(cmd, "add") == 0) { 1537c478bd9Sstevel@tonic-gate rval = add_cmd(); 1547c478bd9Sstevel@tonic-gate } else if (strcmp(cmd, "list") == 0) { 1557c478bd9Sstevel@tonic-gate rval = list_remove_cmd(CMD_LIST); 1567c478bd9Sstevel@tonic-gate } else if (strcmp(cmd, "remove") == 0) { 1577c478bd9Sstevel@tonic-gate rval = list_remove_cmd(CMD_REMOVE); 1587c478bd9Sstevel@tonic-gate } else if (strcmp(cmd, "restart") == 0) { 1597c478bd9Sstevel@tonic-gate rval = restart_cmd(); 1607c478bd9Sstevel@tonic-gate } else { 1617c478bd9Sstevel@tonic-gate rval = usage(); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate exit_lock(); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate return (rval); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate int 1717c478bd9Sstevel@tonic-gate main(int argc, char **argv) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate char *cmd; 1747c478bd9Sstevel@tonic-gate int rval; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 1787c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate if ((whoami = strrchr(argv[0], '/')) == NULL) { 1817c478bd9Sstevel@tonic-gate whoami = argv[0]; 1827c478bd9Sstevel@tonic-gate } else { 1837c478bd9Sstevel@tonic-gate whoami++; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate if (argc == 1) { 1877c478bd9Sstevel@tonic-gate return (usage_gen()); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate cmd = argv[optind++]; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* Allow non-privileged users to get the help messages */ 1937c478bd9Sstevel@tonic-gate if (strcmp(cmd, "help") == 0) { 1947c478bd9Sstevel@tonic-gate rval = usage_gen(); 1957c478bd9Sstevel@tonic-gate return (rval); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate if (getuid() != 0) { 1997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_NOT_ROOT, whoami); 2007c478bd9Sstevel@tonic-gate exit(EXIT_PERM); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate if (strcmp(cmd, "evc") != 0 && getzoneid() != GLOBAL_ZONEID) { 2047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_NOT_GLOBAL, whoami); 2057c478bd9Sstevel@tonic-gate exit(EXIT_PERM); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if (strcmp(cmd, "add") == 0 || 2097c478bd9Sstevel@tonic-gate strcmp(cmd, "remove") == 0 || strcmp(cmd, "list") == 0 || 2107c478bd9Sstevel@tonic-gate strcmp(cmd, "restart") == 0) { 2117c478bd9Sstevel@tonic-gate rval = serve_syseventdotconf(argc, argv, cmd); 2127c478bd9Sstevel@tonic-gate } else { 2137c478bd9Sstevel@tonic-gate rval = usage_gen(); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate return (rval); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate static void 2207c478bd9Sstevel@tonic-gate enter_lock(char *root_dir) 2217c478bd9Sstevel@tonic-gate { 2227c478bd9Sstevel@tonic-gate struct flock lock; 2237c478bd9Sstevel@tonic-gate 224*c6fc6dddSEric Schrock if (snprintf(lock_file, sizeof (lock_file), "%s%s", root_dir, 225*c6fc6dddSEric Schrock LOCK_FILENAME) >= sizeof (lock_file)) { 2267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_PATH_ERR, whoami, lock_file); 2277c478bd9Sstevel@tonic-gate exit(EXIT_CMD_FAILED); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate lock_fd = open(lock_file, O_CREAT|O_RDWR, 0644); 2307c478bd9Sstevel@tonic-gate if (lock_fd < 0) { 2317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_CREATE_ERR, 2327c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 2337c478bd9Sstevel@tonic-gate exit(EXIT_CMD_FAILED); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 2377c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 2387c478bd9Sstevel@tonic-gate lock.l_start = 0; 2397c478bd9Sstevel@tonic-gate lock.l_len = 0; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate retry: 2427c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLKW, &lock) == -1) { 2437c478bd9Sstevel@tonic-gate if (errno == EAGAIN || errno == EINTR) 2447c478bd9Sstevel@tonic-gate goto retry; 2457c478bd9Sstevel@tonic-gate (void) close(lock_fd); 2467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_SET_ERR, 2477c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 2487c478bd9Sstevel@tonic-gate exit(EXIT_CMD_FAILED); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate static void 2547c478bd9Sstevel@tonic-gate exit_lock() 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate struct flock lock; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate lock.l_type = F_UNLCK; 2597c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 2607c478bd9Sstevel@tonic-gate lock.l_start = 0; 2617c478bd9Sstevel@tonic-gate lock.l_len = 0; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (fcntl(lock_fd, F_SETLK, &lock) == -1) { 2647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_CLR_ERR, 2657c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate if (close(lock_fd) == -1) { 2697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_LOCK_CLOSE_ERR, 2707c478bd9Sstevel@tonic-gate whoami, lock_file, strerror(errno)); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate static void 2767c478bd9Sstevel@tonic-gate set_root_dir(char *dir) 2777c478bd9Sstevel@tonic-gate { 2787c478bd9Sstevel@tonic-gate root_dir = sc_strdup(dir); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate static char *usage_msg[] = { 2837c478bd9Sstevel@tonic-gate "\n" 2847c478bd9Sstevel@tonic-gate "\tsyseventadm add [-R <rootdir>] [-v vendor] [-p publisher]\n" 2857c478bd9Sstevel@tonic-gate "\t[-c class] [-s subclass] [-u username] path [args]\n" 2867c478bd9Sstevel@tonic-gate "\n" 2877c478bd9Sstevel@tonic-gate "\tsyseventadm remove [-R <rootdir>] [-v vendor] [-p publisher]\n" 2887c478bd9Sstevel@tonic-gate "\t[-c class] [-s subclass] [-u username] [path [args]]\n" 2897c478bd9Sstevel@tonic-gate "\n" 2907c478bd9Sstevel@tonic-gate "\tsyseventadm list [-R <rootdir>] [-v vendor] [-p publisher]\n" 2917c478bd9Sstevel@tonic-gate "\t[-c class] [-s subclass] [-u username] [path [args]]\n" 2927c478bd9Sstevel@tonic-gate }; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate static int 2957c478bd9Sstevel@tonic-gate usage() 2967c478bd9Sstevel@tonic-gate { 2977c478bd9Sstevel@tonic-gate char **msgs; 2987c478bd9Sstevel@tonic-gate int i; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate msgs = usage_msg; 3017c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (usage_msg)/sizeof (char *); i++) { 3027c478bd9Sstevel@tonic-gate (void) fputs(*msgs++, stderr); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate return (EXIT_USAGE); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate static int 3107c478bd9Sstevel@tonic-gate add_cmd(void) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate char fname[MAXPATHLEN+1]; 3137c478bd9Sstevel@tonic-gate int need_comma = 0; 3147c478bd9Sstevel@tonic-gate int noptions = 0; 3157c478bd9Sstevel@tonic-gate struct stat st; 3167c478bd9Sstevel@tonic-gate FILE *fp; 3177c478bd9Sstevel@tonic-gate str_t *line; 3187c478bd9Sstevel@tonic-gate int i; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * At least one of vendor/publisher/class must be specified. 3227c478bd9Sstevel@tonic-gate * Subclass is only defined within the context of class. 3237c478bd9Sstevel@tonic-gate * For add, path must also be specified. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate if (arg_vendor) 3267c478bd9Sstevel@tonic-gate noptions++; 3277c478bd9Sstevel@tonic-gate if (arg_publisher) 3287c478bd9Sstevel@tonic-gate noptions++; 3297c478bd9Sstevel@tonic-gate if (arg_class) 3307c478bd9Sstevel@tonic-gate noptions++; 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate if (noptions == 0 || (arg_subclass && arg_class == NULL)) { 3337c478bd9Sstevel@tonic-gate return (usage()); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate if (arg_path == NULL) 3377c478bd9Sstevel@tonic-gate return (usage()); 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * Generate the sysevent.conf file name 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate (void) strcpy(fname, root_dir); 3437c478bd9Sstevel@tonic-gate (void) strcat(fname, SYSEVENT_CONFIG_DIR); 3447c478bd9Sstevel@tonic-gate (void) strcat(fname, "/"); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate if (arg_vendor) { 3477c478bd9Sstevel@tonic-gate (void) strcat(fname, arg_vendor); 3487c478bd9Sstevel@tonic-gate need_comma = 1; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate if (arg_publisher) { 3517c478bd9Sstevel@tonic-gate if (need_comma) 3527c478bd9Sstevel@tonic-gate (void) strcat(fname, ","); 3537c478bd9Sstevel@tonic-gate (void) strcat(fname, arg_publisher); 3547c478bd9Sstevel@tonic-gate need_comma = 1; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate if (arg_class) { 3577c478bd9Sstevel@tonic-gate if (need_comma) 3587c478bd9Sstevel@tonic-gate (void) strcat(fname, ","); 3597c478bd9Sstevel@tonic-gate (void) strcat(fname, arg_class); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate (void) strcat(fname, SYSEVENT_CONF_SUFFIX); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Prepare the line to be written to the sysevent.conf file 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate line = initstr(128); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate strcats(line, arg_class == NULL ? "-" : arg_class); 3697c478bd9Sstevel@tonic-gate strcatc(line, ' '); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate strcats(line, arg_subclass == NULL ? "-" : arg_subclass); 3727c478bd9Sstevel@tonic-gate strcatc(line, ' '); 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate strcats(line, arg_vendor == NULL ? "-" : arg_vendor); 3757c478bd9Sstevel@tonic-gate strcatc(line, ' '); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate strcats(line, arg_publisher == NULL ? "-" : arg_publisher); 3787c478bd9Sstevel@tonic-gate strcatc(line, ' '); 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate strcats(line, arg_username == NULL ? "-" : arg_username); 3817c478bd9Sstevel@tonic-gate strcatc(line, ' '); 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate strcats(line, "- - "); 3847c478bd9Sstevel@tonic-gate strcats(line, arg_path); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (arg_nargs) { 3877c478bd9Sstevel@tonic-gate for (i = 0; i < arg_nargs; i++) { 3887c478bd9Sstevel@tonic-gate strcatc(line, ' '); 3897c478bd9Sstevel@tonic-gate strcats(line, arg_args[i]); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate if (stat(fname, &st) == -1) { 3947c478bd9Sstevel@tonic-gate if (creat(fname, 0644) == -1) { 3957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_CREATE, 3967c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 3977c478bd9Sstevel@tonic-gate freestr(line); 3987c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate fp = fopen(fname, "a"); 4037c478bd9Sstevel@tonic-gate if (fp == NULL) { 4047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 4057c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 4067c478bd9Sstevel@tonic-gate freestr(line); 4077c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s\n", line->s_str); 4117c478bd9Sstevel@tonic-gate freestr(line); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (fclose(fp) == -1) { 4147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CLOSE_ERROR, 4157c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 4167c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate if (chmod(fname, 0444) == -1) { 4207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CHMOD_ERROR, 4217c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 4227c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate return (EXIT_OK); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate static int 4297c478bd9Sstevel@tonic-gate list_remove_cmd(int cmd) 4307c478bd9Sstevel@tonic-gate { 4317c478bd9Sstevel@tonic-gate struct dirent *dp; 4327c478bd9Sstevel@tonic-gate DIR *dir; 4337c478bd9Sstevel@tonic-gate char path[MAXPATHLEN+1]; 4347c478bd9Sstevel@tonic-gate char fname[MAXPATHLEN+1]; 4357c478bd9Sstevel@tonic-gate char *suffix; 4367c478bd9Sstevel@tonic-gate char **dirlist = NULL; 4377c478bd9Sstevel@tonic-gate int list_size = 0; 4387c478bd9Sstevel@tonic-gate int list_alloc = 0; 4397c478bd9Sstevel@tonic-gate char **p; 4407c478bd9Sstevel@tonic-gate int rval; 4417c478bd9Sstevel@tonic-gate int result; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * For the remove cmd, at least one of vendor/publisher/class/username 4457c478bd9Sstevel@tonic-gate * path must be specified. Subclass is only defined within the 4467c478bd9Sstevel@tonic-gate * context of a class. 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate if (cmd == CMD_REMOVE) { 4497c478bd9Sstevel@tonic-gate int noptions = 0; 4507c478bd9Sstevel@tonic-gate if (arg_vendor) 4517c478bd9Sstevel@tonic-gate noptions++; 4527c478bd9Sstevel@tonic-gate if (arg_publisher) 4537c478bd9Sstevel@tonic-gate noptions++; 4547c478bd9Sstevel@tonic-gate if (arg_class) 4557c478bd9Sstevel@tonic-gate noptions++; 4567c478bd9Sstevel@tonic-gate if (arg_username) 4577c478bd9Sstevel@tonic-gate noptions++; 4587c478bd9Sstevel@tonic-gate if (arg_path) 4597c478bd9Sstevel@tonic-gate noptions++; 4607c478bd9Sstevel@tonic-gate if (noptions == 0 || (arg_subclass && arg_class == NULL)) { 4617c478bd9Sstevel@tonic-gate return (usage()); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate (void) strcpy(path, root_dir); 4667c478bd9Sstevel@tonic-gate (void) strcat(path, SYSEVENT_CONFIG_DIR); 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate if ((dir = opendir(path)) == NULL) { 4697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN_DIR, 4707c478bd9Sstevel@tonic-gate whoami, path, strerror(errno)); 4717c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate while ((dp = readdir(dir)) != NULL) { 4757c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.') 4767c478bd9Sstevel@tonic-gate continue; 4777c478bd9Sstevel@tonic-gate if ((strlen(dp->d_name) == 0) || 4787c478bd9Sstevel@tonic-gate (strcmp(dp->d_name, "lost+found") == 0)) 4797c478bd9Sstevel@tonic-gate continue; 4807c478bd9Sstevel@tonic-gate suffix = strrchr(dp->d_name, ','); 4817c478bd9Sstevel@tonic-gate if (suffix && strcmp(suffix, SYSEVENT_CONF_SUFFIX) == 0) { 4827c478bd9Sstevel@tonic-gate (void) strcpy(fname, path); 4837c478bd9Sstevel@tonic-gate (void) strcat(fname, "/"); 4847c478bd9Sstevel@tonic-gate (void) strcat(fname, dp->d_name); 4857c478bd9Sstevel@tonic-gate dirlist = build_strlist(dirlist, 4867c478bd9Sstevel@tonic-gate &list_size, &list_alloc, fname); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate if (closedir(dir) == -1) { 4917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CLOSE_DIR_ERROR, 4927c478bd9Sstevel@tonic-gate whoami, path, strerror(errno)); 4937c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate rval = EXIT_NO_MATCH; 4977c478bd9Sstevel@tonic-gate if (dirlist) { 4987c478bd9Sstevel@tonic-gate for (p = dirlist; *p != NULL; p++) { 4997c478bd9Sstevel@tonic-gate switch (cmd) { 5007c478bd9Sstevel@tonic-gate case CMD_LIST: 5017c478bd9Sstevel@tonic-gate result = list_file(*p); 5027c478bd9Sstevel@tonic-gate break; 5037c478bd9Sstevel@tonic-gate case CMD_REMOVE: 5047c478bd9Sstevel@tonic-gate result = remove_file(*p); 5057c478bd9Sstevel@tonic-gate break; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate if (rval == EXIT_NO_MATCH && 5087c478bd9Sstevel@tonic-gate result != EXIT_NO_MATCH) 5097c478bd9Sstevel@tonic-gate rval = result; 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate return (rval); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate static int 5177c478bd9Sstevel@tonic-gate list_file(char *fname) 5187c478bd9Sstevel@tonic-gate { 5197c478bd9Sstevel@tonic-gate FILE *fp; 5207c478bd9Sstevel@tonic-gate str_t *line; 5217c478bd9Sstevel@tonic-gate serecord_t *sep; 5227c478bd9Sstevel@tonic-gate int rval = EXIT_NO_MATCH; 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate fp = fopen(fname, "r"); 5257c478bd9Sstevel@tonic-gate if (fp == NULL) { 5267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 5277c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 5287c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate for (;;) { 5317c478bd9Sstevel@tonic-gate line = read_next_line(fp); 5327c478bd9Sstevel@tonic-gate if (line == NULL) 5337c478bd9Sstevel@tonic-gate break; 5347c478bd9Sstevel@tonic-gate sep = parse_line(line); 5357c478bd9Sstevel@tonic-gate if (sep != NULL) { 5367c478bd9Sstevel@tonic-gate if (matches_serecord(sep)) { 5377c478bd9Sstevel@tonic-gate print_serecord(stdout, sep); 5387c478bd9Sstevel@tonic-gate rval = EXIT_OK; 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate free_serecord(sep); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate freestr(line); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate (void) fclose(fp); 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate return (rval); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate static int 5517c478bd9Sstevel@tonic-gate remove_file(char *fname) 5527c478bd9Sstevel@tonic-gate { 5537c478bd9Sstevel@tonic-gate FILE *fp; 5547c478bd9Sstevel@tonic-gate FILE *tmp_fp; 5557c478bd9Sstevel@tonic-gate str_t *line; 5567c478bd9Sstevel@tonic-gate char *raw_line; 5577c478bd9Sstevel@tonic-gate serecord_t *sep; 5587c478bd9Sstevel@tonic-gate char tmp_name[MAXPATHLEN+1]; 5597c478bd9Sstevel@tonic-gate int is_empty = 1; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate fp = fopen(fname, "r"); 5627c478bd9Sstevel@tonic-gate if (fp == NULL) { 5637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 5647c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 5657c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate if (check_for_removes(fp) == 0) { 5697c478bd9Sstevel@tonic-gate (void) fclose(fp); 5707c478bd9Sstevel@tonic-gate return (EXIT_NO_MATCH); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate rewind(fp); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate (void) strcpy(tmp_name, root_dir); 5767c478bd9Sstevel@tonic-gate (void) strcat(tmp_name, SYSEVENT_CONFIG_DIR); 5777c478bd9Sstevel@tonic-gate (void) strcat(tmp_name, "/tmp.XXXXXX"); 5787c478bd9Sstevel@tonic-gate if (mktemp(tmp_name) == NULL) { 5797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unable to make tmp file name\n"); 5807c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if (creat(tmp_name, 0644) == -1) { 5847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_CREATE, 5857c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 5867c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate tmp_fp = fopen(tmp_name, "a"); 5907c478bd9Sstevel@tonic-gate if (tmp_fp == NULL) { 5917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_OPEN, 5927c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 5937c478bd9Sstevel@tonic-gate (void) unlink(tmp_name); 5947c478bd9Sstevel@tonic-gate (void) fclose(fp); 5957c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate for (;;) { 5997c478bd9Sstevel@tonic-gate line = read_next_line(fp); 6007c478bd9Sstevel@tonic-gate if (line == NULL) 6017c478bd9Sstevel@tonic-gate break; 6027c478bd9Sstevel@tonic-gate raw_line = sc_strdup(line->s_str); 6037c478bd9Sstevel@tonic-gate sep = parse_line(line); 6047c478bd9Sstevel@tonic-gate if (sep == NULL) { 6057c478bd9Sstevel@tonic-gate (void) fputs(line->s_str, tmp_fp); 6067c478bd9Sstevel@tonic-gate } else { 6077c478bd9Sstevel@tonic-gate if (!matches_serecord(sep)) { 6087c478bd9Sstevel@tonic-gate is_empty = 0; 6097c478bd9Sstevel@tonic-gate (void) fprintf(tmp_fp, "%s\n", raw_line); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate free_serecord(sep); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate freestr(line); 6147c478bd9Sstevel@tonic-gate sc_strfree(raw_line); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate (void) fclose(fp); 6177c478bd9Sstevel@tonic-gate if (fclose(tmp_fp) == -1) { 6187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CLOSE_ERROR, 6197c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate if (is_empty) { 6237c478bd9Sstevel@tonic-gate if (unlink(tmp_name) == -1) { 6247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_UNLINK, 6257c478bd9Sstevel@tonic-gate whoami, tmp_name, strerror(errno)); 6267c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate if (unlink(fname) == -1) { 6297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_UNLINK, 6307c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 6317c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate } else { 6347c478bd9Sstevel@tonic-gate if (unlink(fname) == -1) { 6357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_UNLINK, 6367c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 6377c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate if (rename(tmp_name, fname) == -1) { 6407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CANNOT_RENAME, 6417c478bd9Sstevel@tonic-gate whoami, tmp_name, fname, strerror(errno)); 6427c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate if (chmod(fname, 0444) == -1) { 6457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_CHMOD_ERROR, 6467c478bd9Sstevel@tonic-gate whoami, fname, strerror(errno)); 6477c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate return (EXIT_OK); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate static int 6557c478bd9Sstevel@tonic-gate check_for_removes(FILE *fp) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate str_t *line; 6587c478bd9Sstevel@tonic-gate serecord_t *sep; 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate for (;;) { 6617c478bd9Sstevel@tonic-gate line = read_next_line(fp); 6627c478bd9Sstevel@tonic-gate if (line == NULL) 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate sep = parse_line(line); 6657c478bd9Sstevel@tonic-gate if (sep != NULL) { 6667c478bd9Sstevel@tonic-gate if (matches_serecord(sep)) { 6677c478bd9Sstevel@tonic-gate free_serecord(sep); 6687c478bd9Sstevel@tonic-gate freestr(line); 6697c478bd9Sstevel@tonic-gate return (1); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate free_serecord(sep); 6727c478bd9Sstevel@tonic-gate } 6737c478bd9Sstevel@tonic-gate freestr(line); 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate return (0); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate static int 6817c478bd9Sstevel@tonic-gate matches_serecord(serecord_t *sep) 6827c478bd9Sstevel@tonic-gate { 6837c478bd9Sstevel@tonic-gate char *line; 6847c478bd9Sstevel@tonic-gate char *lp; 6857c478bd9Sstevel@tonic-gate char *token; 6867c478bd9Sstevel@tonic-gate int i; 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate if (arg_vendor && 6897c478bd9Sstevel@tonic-gate strcmp(arg_vendor, sep->se_vendor) != 0) { 6907c478bd9Sstevel@tonic-gate return (0); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if (arg_publisher && 6947c478bd9Sstevel@tonic-gate strcmp(arg_publisher, sep->se_publisher) != 0) { 6957c478bd9Sstevel@tonic-gate return (0); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if (arg_class && 6997c478bd9Sstevel@tonic-gate strcmp(arg_class, sep->se_class) != 0) { 7007c478bd9Sstevel@tonic-gate return (0); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate if (arg_subclass && 7047c478bd9Sstevel@tonic-gate strcmp(arg_subclass, sep->se_subclass) != 0) { 7057c478bd9Sstevel@tonic-gate return (0); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (arg_username && 7097c478bd9Sstevel@tonic-gate strcmp(arg_username, sep->se_user) != 0) { 7107c478bd9Sstevel@tonic-gate return (0); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (arg_path && 7147c478bd9Sstevel@tonic-gate strcmp(arg_path, sep->se_path) != 0) { 7157c478bd9Sstevel@tonic-gate return (0); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate if (arg_nargs > 0) { 7197c478bd9Sstevel@tonic-gate line = sc_strdup(sep->se_args); 7207c478bd9Sstevel@tonic-gate lp = line; 7217c478bd9Sstevel@tonic-gate for (i = 0; i < arg_nargs; i++) { 7227c478bd9Sstevel@tonic-gate token = next_field(&lp); 7237c478bd9Sstevel@tonic-gate if (strcmp(arg_args[i], token) != 0) { 7247c478bd9Sstevel@tonic-gate sc_strfree(line); 7257c478bd9Sstevel@tonic-gate return (0); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate sc_strfree(line); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate return (1); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate static void 7357c478bd9Sstevel@tonic-gate print_serecord(FILE *fp, serecord_t *sep) 7367c478bd9Sstevel@tonic-gate { 7377c478bd9Sstevel@tonic-gate str_t *line; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate line = initstr(128); 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate if (strcmp(sep->se_vendor, "-") != 0) { 7427c478bd9Sstevel@tonic-gate strcats(line, "vendor="); 7437c478bd9Sstevel@tonic-gate strcats(line, sep->se_vendor); 7447c478bd9Sstevel@tonic-gate strcats(line, " "); 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate if (strcmp(sep->se_publisher, "-") != 0) { 7477c478bd9Sstevel@tonic-gate strcats(line, "publisher="); 7487c478bd9Sstevel@tonic-gate strcats(line, sep->se_publisher); 7497c478bd9Sstevel@tonic-gate strcats(line, " "); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate if (strcmp(sep->se_class, "-") != 0) { 7527c478bd9Sstevel@tonic-gate strcats(line, "class="); 7537c478bd9Sstevel@tonic-gate strcats(line, sep->se_class); 7547c478bd9Sstevel@tonic-gate strcats(line, " "); 7557c478bd9Sstevel@tonic-gate if (strcmp(sep->se_subclass, "-") != 0) { 7567c478bd9Sstevel@tonic-gate strcats(line, "subclass="); 7577c478bd9Sstevel@tonic-gate strcats(line, sep->se_subclass); 7587c478bd9Sstevel@tonic-gate strcats(line, " "); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate if (strcmp(sep->se_user, "-") != 0) { 7627c478bd9Sstevel@tonic-gate strcats(line, "username="); 7637c478bd9Sstevel@tonic-gate strcats(line, sep->se_user); 7647c478bd9Sstevel@tonic-gate strcats(line, " "); 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate strcats(line, sep->se_path); 7677c478bd9Sstevel@tonic-gate if (sep->se_args) { 7687c478bd9Sstevel@tonic-gate strcats(line, " "); 7697c478bd9Sstevel@tonic-gate strcats(line, sep->se_args); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate strcats(line, "\n"); 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate (void) fputs(line->s_str, fp); 7747c478bd9Sstevel@tonic-gate freestr(line); 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate static int 7817c478bd9Sstevel@tonic-gate restart_cmd(void) 7827c478bd9Sstevel@tonic-gate { 7837c478bd9Sstevel@tonic-gate if (system("pkill -HUP syseventd") == -1) { 7847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_RESTART_FAILED, 7857c478bd9Sstevel@tonic-gate whoami, strerror(errno)); 7867c478bd9Sstevel@tonic-gate return (EXIT_CMD_FAILED); 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate return (EXIT_OK); 7897c478bd9Sstevel@tonic-gate } 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate static str_t * 7937c478bd9Sstevel@tonic-gate read_next_line(FILE *fp) 7947c478bd9Sstevel@tonic-gate { 7957c478bd9Sstevel@tonic-gate char *lp; 7967c478bd9Sstevel@tonic-gate str_t *line; 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate line = initstr(128); 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate lp = fstrgets(line, fp); 8017c478bd9Sstevel@tonic-gate if (lp == NULL) { 8027c478bd9Sstevel@tonic-gate freestr(line); 8037c478bd9Sstevel@tonic-gate return (NULL); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate *(lp + strlen(lp)-1) = 0; 8077c478bd9Sstevel@tonic-gate return (line); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate static serecord_t * 8127c478bd9Sstevel@tonic-gate parse_line(str_t *line) 8137c478bd9Sstevel@tonic-gate { 8147c478bd9Sstevel@tonic-gate char *lp; 8157c478bd9Sstevel@tonic-gate char *vendor, *publisher; 8167c478bd9Sstevel@tonic-gate char *class, *subclass; 8177c478bd9Sstevel@tonic-gate char *user; 8187c478bd9Sstevel@tonic-gate char *reserved1, *reserved2; 8197c478bd9Sstevel@tonic-gate char *path, *args; 8207c478bd9Sstevel@tonic-gate serecord_t *sep; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate lp = line->s_str; 8237c478bd9Sstevel@tonic-gate if (*lp == 0 || *lp == '#') { 8247c478bd9Sstevel@tonic-gate return (NULL); 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate if ((class = next_field(&lp)) != NULL) { 8287c478bd9Sstevel@tonic-gate subclass = next_field(&lp); 8297c478bd9Sstevel@tonic-gate if (lp == NULL) 8307c478bd9Sstevel@tonic-gate return (NULL); 8317c478bd9Sstevel@tonic-gate vendor = next_field(&lp); 8327c478bd9Sstevel@tonic-gate if (lp == NULL) 8337c478bd9Sstevel@tonic-gate return (NULL); 8347c478bd9Sstevel@tonic-gate publisher = next_field(&lp); 8357c478bd9Sstevel@tonic-gate if (lp == NULL) 8367c478bd9Sstevel@tonic-gate return (NULL); 8377c478bd9Sstevel@tonic-gate user = next_field(&lp); 8387c478bd9Sstevel@tonic-gate if (lp == NULL) 8397c478bd9Sstevel@tonic-gate return (NULL); 8407c478bd9Sstevel@tonic-gate reserved1 = next_field(&lp); 8417c478bd9Sstevel@tonic-gate if (lp == NULL) 8427c478bd9Sstevel@tonic-gate return (NULL); 8437c478bd9Sstevel@tonic-gate reserved2 = next_field(&lp); 8447c478bd9Sstevel@tonic-gate if (lp == NULL) 8457c478bd9Sstevel@tonic-gate return (NULL); 8467c478bd9Sstevel@tonic-gate path = next_field(&lp); 8477c478bd9Sstevel@tonic-gate if (lp == NULL) 8487c478bd9Sstevel@tonic-gate return (NULL); 8497c478bd9Sstevel@tonic-gate args = skip_spaces(&lp); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate sep = sc_malloc(sizeof (serecord_t)); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate sep->se_vendor = sc_strdup(vendor); 8557c478bd9Sstevel@tonic-gate sep->se_publisher = sc_strdup(publisher); 8567c478bd9Sstevel@tonic-gate sep->se_class = sc_strdup(class); 8577c478bd9Sstevel@tonic-gate sep->se_subclass = sc_strdup(subclass); 8587c478bd9Sstevel@tonic-gate sep->se_user = sc_strdup(user); 8597c478bd9Sstevel@tonic-gate sep->se_reserved1 = sc_strdup(reserved1); 8607c478bd9Sstevel@tonic-gate sep->se_reserved2 = sc_strdup(reserved2); 8617c478bd9Sstevel@tonic-gate sep->se_path = sc_strdup(path); 8627c478bd9Sstevel@tonic-gate sep->se_args = (args == NULL) ? NULL : sc_strdup(args); 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate return (sep); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate static void 8697c478bd9Sstevel@tonic-gate free_serecord(serecord_t *sep) 8707c478bd9Sstevel@tonic-gate { 8717c478bd9Sstevel@tonic-gate sc_strfree(sep->se_vendor); 8727c478bd9Sstevel@tonic-gate sc_strfree(sep->se_publisher); 8737c478bd9Sstevel@tonic-gate sc_strfree(sep->se_class); 8747c478bd9Sstevel@tonic-gate sc_strfree(sep->se_subclass); 8757c478bd9Sstevel@tonic-gate sc_strfree(sep->se_user); 8767c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved1); 8777c478bd9Sstevel@tonic-gate sc_strfree(sep->se_reserved2); 8787c478bd9Sstevel@tonic-gate sc_strfree(sep->se_path); 8797c478bd9Sstevel@tonic-gate sc_strfree(sep->se_args); 8807c478bd9Sstevel@tonic-gate sc_free(sep, sizeof (serecord_t)); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* 8857c478bd9Sstevel@tonic-gate * skip_spaces() - skip to next non-space character 8867c478bd9Sstevel@tonic-gate */ 8877c478bd9Sstevel@tonic-gate static char * 8887c478bd9Sstevel@tonic-gate skip_spaces(char **cpp) 8897c478bd9Sstevel@tonic-gate { 8907c478bd9Sstevel@tonic-gate char *cp = *cpp; 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 8937c478bd9Sstevel@tonic-gate cp++; 8947c478bd9Sstevel@tonic-gate if (*cp == 0) { 8957c478bd9Sstevel@tonic-gate *cpp = 0; 8967c478bd9Sstevel@tonic-gate return (NULL); 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate return (cp); 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate /* 9037c478bd9Sstevel@tonic-gate * Get next white-space separated field. 9047c478bd9Sstevel@tonic-gate * next_field() will not check any characters on next line. 9057c478bd9Sstevel@tonic-gate * Each entry is composed of a single line. 9067c478bd9Sstevel@tonic-gate */ 9077c478bd9Sstevel@tonic-gate static char * 9087c478bd9Sstevel@tonic-gate next_field(char **cpp) 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate char *cp = *cpp; 9117c478bd9Sstevel@tonic-gate char *start; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate while (*cp == ' ' || *cp == '\t') 9147c478bd9Sstevel@tonic-gate cp++; 9157c478bd9Sstevel@tonic-gate if (*cp == 0) { 9167c478bd9Sstevel@tonic-gate *cpp = 0; 9177c478bd9Sstevel@tonic-gate return (NULL); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate start = cp; 9207c478bd9Sstevel@tonic-gate while (*cp && *cp != ' ' && *cp != '\t') 9217c478bd9Sstevel@tonic-gate cp++; 9227c478bd9Sstevel@tonic-gate if (*cp != 0) 9237c478bd9Sstevel@tonic-gate *cp++ = 0; 9247c478bd9Sstevel@tonic-gate *cpp = cp; 9257c478bd9Sstevel@tonic-gate return (start); 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate /* 9317c478bd9Sstevel@tonic-gate * The following functions are simple wrappers/equivalents 9327c478bd9Sstevel@tonic-gate * for malloc, realloc, free, strdup and a special free 9337c478bd9Sstevel@tonic-gate * for strdup. 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate static void * 9377c478bd9Sstevel@tonic-gate sc_malloc(size_t n) 9387c478bd9Sstevel@tonic-gate { 9397c478bd9Sstevel@tonic-gate void *p; 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate p = malloc(n); 9427c478bd9Sstevel@tonic-gate if (p == NULL) { 9437c478bd9Sstevel@tonic-gate no_mem_err(); 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate return (p); 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 9497c478bd9Sstevel@tonic-gate static void * 9507c478bd9Sstevel@tonic-gate sc_realloc(void *p, size_t current, size_t n) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate p = realloc(p, n); 9537c478bd9Sstevel@tonic-gate if (p == NULL) { 9547c478bd9Sstevel@tonic-gate no_mem_err(); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate return (p); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 9617c478bd9Sstevel@tonic-gate static void 9627c478bd9Sstevel@tonic-gate sc_free(void *p, size_t n) 9637c478bd9Sstevel@tonic-gate { 9647c478bd9Sstevel@tonic-gate free(p); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate static char * 9697c478bd9Sstevel@tonic-gate sc_strdup(char *cp) 9707c478bd9Sstevel@tonic-gate { 9717c478bd9Sstevel@tonic-gate char *new; 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate new = malloc((unsigned)(strlen(cp) + 1)); 9747c478bd9Sstevel@tonic-gate if (new == NULL) { 9757c478bd9Sstevel@tonic-gate no_mem_err(); 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate (void) strcpy(new, cp); 9787c478bd9Sstevel@tonic-gate return (new); 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate static void 9837c478bd9Sstevel@tonic-gate sc_strfree(char *s) 9847c478bd9Sstevel@tonic-gate { 9857c478bd9Sstevel@tonic-gate if (s) 9867c478bd9Sstevel@tonic-gate free(s); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate /* 9917c478bd9Sstevel@tonic-gate * The following functions provide some simple dynamic string 9927c478bd9Sstevel@tonic-gate * capability. This module has no hard-coded maximum string 9937c478bd9Sstevel@tonic-gate * lengths and should be able to parse and generate arbitrarily 9947c478bd9Sstevel@tonic-gate * long strings, macro expansion and command lines. 9957c478bd9Sstevel@tonic-gate * 9967c478bd9Sstevel@tonic-gate * Each string must be explicitly allocated and freed. 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* 10007c478bd9Sstevel@tonic-gate * Allocate a dynamic string, with a hint to indicate how 10017c478bd9Sstevel@tonic-gate * much memory to dynamically add to the string as it grows 10027c478bd9Sstevel@tonic-gate * beyond its existing bounds, so as to avoid excessive 10037c478bd9Sstevel@tonic-gate * reallocs as a string grows. 10047c478bd9Sstevel@tonic-gate */ 10057c478bd9Sstevel@tonic-gate static str_t * 10067c478bd9Sstevel@tonic-gate initstr(int hint) 10077c478bd9Sstevel@tonic-gate { 10087c478bd9Sstevel@tonic-gate str_t *str; 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate str = sc_malloc(sizeof (str_t)); 10117c478bd9Sstevel@tonic-gate str->s_str = NULL; 10127c478bd9Sstevel@tonic-gate str->s_len = 0; 10137c478bd9Sstevel@tonic-gate str->s_alloc = 0; 10147c478bd9Sstevel@tonic-gate str->s_hint = hint; 10157c478bd9Sstevel@tonic-gate return (str); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate /* 10207c478bd9Sstevel@tonic-gate * Free a dynamically-allocated string 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate static void 10237c478bd9Sstevel@tonic-gate freestr(str_t *str) 10247c478bd9Sstevel@tonic-gate { 10257c478bd9Sstevel@tonic-gate if (str->s_str) { 10267c478bd9Sstevel@tonic-gate sc_free(str->s_str, str->s_alloc); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate sc_free(str, sizeof (str_t)); 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 10337c478bd9Sstevel@tonic-gate * Reset a dynamically-allocated string, allows reuse 10347c478bd9Sstevel@tonic-gate * rather than freeing the old and allocating a new one. 10357c478bd9Sstevel@tonic-gate */ 10367c478bd9Sstevel@tonic-gate static void 10377c478bd9Sstevel@tonic-gate resetstr(str_t *str) 10387c478bd9Sstevel@tonic-gate { 10397c478bd9Sstevel@tonic-gate str->s_len = 0; 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* 10447c478bd9Sstevel@tonic-gate * Concatenate a (simple) string onto a dynamically-allocated string 10457c478bd9Sstevel@tonic-gate */ 10467c478bd9Sstevel@tonic-gate static void 10477c478bd9Sstevel@tonic-gate strcats(str_t *str, char *s) 10487c478bd9Sstevel@tonic-gate { 10497c478bd9Sstevel@tonic-gate char *new_str; 10507c478bd9Sstevel@tonic-gate int len = str->s_len + strlen(s) + 1; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 10537c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : 10547c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 10557c478bd9Sstevel@tonic-gate str->s_str = new_str; 10567c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate (void) strcpy(str->s_str + str->s_len, s); 10597c478bd9Sstevel@tonic-gate str->s_len = len - 1; 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate /* 10647c478bd9Sstevel@tonic-gate * Concatenate a character onto a dynamically-allocated string 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate static void 10677c478bd9Sstevel@tonic-gate strcatc(str_t *str, int c) 10687c478bd9Sstevel@tonic-gate { 10697c478bd9Sstevel@tonic-gate char *new_str; 10707c478bd9Sstevel@tonic-gate int len = str->s_len + 2; 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate if (str->s_alloc < len) { 10737c478bd9Sstevel@tonic-gate new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : 10747c478bd9Sstevel@tonic-gate sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); 10757c478bd9Sstevel@tonic-gate str->s_str = new_str; 10767c478bd9Sstevel@tonic-gate str->s_alloc = len + str->s_hint; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate *(str->s_str + str->s_len) = (char)c; 10797c478bd9Sstevel@tonic-gate *(str->s_str + str->s_len + 1) = 0; 10807c478bd9Sstevel@tonic-gate str->s_len++; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* 10847c478bd9Sstevel@tonic-gate * fgets() equivalent using a dynamically-allocated string 10857c478bd9Sstevel@tonic-gate */ 10867c478bd9Sstevel@tonic-gate static char * 10877c478bd9Sstevel@tonic-gate fstrgets(str_t *line, FILE *fp) 10887c478bd9Sstevel@tonic-gate { 10897c478bd9Sstevel@tonic-gate int c; 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate resetstr(line); 10927c478bd9Sstevel@tonic-gate while ((c = fgetc(fp)) != EOF) { 10937c478bd9Sstevel@tonic-gate strcatc(line, c); 10947c478bd9Sstevel@tonic-gate if (c == '\n') 10957c478bd9Sstevel@tonic-gate break; 10967c478bd9Sstevel@tonic-gate } 10977c478bd9Sstevel@tonic-gate if (line->s_len == 0) 10987c478bd9Sstevel@tonic-gate return (NULL); 10997c478bd9Sstevel@tonic-gate return (line->s_str); 11007c478bd9Sstevel@tonic-gate } 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate #define INITIAL_LISTSIZE 4 11057c478bd9Sstevel@tonic-gate #define INCR_LISTSIZE 4 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate static char ** 11087c478bd9Sstevel@tonic-gate build_strlist( 11097c478bd9Sstevel@tonic-gate char **argvlist, 11107c478bd9Sstevel@tonic-gate int *size, 11117c478bd9Sstevel@tonic-gate int *alloc, 11127c478bd9Sstevel@tonic-gate char *str) 11137c478bd9Sstevel@tonic-gate { 11147c478bd9Sstevel@tonic-gate int n; 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate if (*size + 1 > *alloc) { 11177c478bd9Sstevel@tonic-gate if (*alloc == 0) { 11187c478bd9Sstevel@tonic-gate *alloc = INITIAL_LISTSIZE; 11197c478bd9Sstevel@tonic-gate n = sizeof (char *) * (*alloc + 1); 11207c478bd9Sstevel@tonic-gate argvlist = (char **)malloc(n); 11217c478bd9Sstevel@tonic-gate if (argvlist == NULL) 11227c478bd9Sstevel@tonic-gate no_mem_err(); 11237c478bd9Sstevel@tonic-gate } else { 11247c478bd9Sstevel@tonic-gate *alloc += INCR_LISTSIZE; 11257c478bd9Sstevel@tonic-gate n = sizeof (char *) * (*alloc + 1); 11267c478bd9Sstevel@tonic-gate argvlist = (char **)realloc(argvlist, n); 11277c478bd9Sstevel@tonic-gate if (argvlist == NULL) 11287c478bd9Sstevel@tonic-gate no_mem_err(); 11297c478bd9Sstevel@tonic-gate } 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate argvlist[*size] = strdup(str); 11337c478bd9Sstevel@tonic-gate *size += 1; 11347c478bd9Sstevel@tonic-gate argvlist[*size] = NULL; 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate return (argvlist); 11377c478bd9Sstevel@tonic-gate } 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate static void 11407c478bd9Sstevel@tonic-gate no_mem_err() 11417c478bd9Sstevel@tonic-gate { 11427c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_NO_MEM, whoami); 11437c478bd9Sstevel@tonic-gate exit_lock(); 11447c478bd9Sstevel@tonic-gate exit(EXIT_NO_MEM); 11457c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 11467c478bd9Sstevel@tonic-gate } 1147