From 7c478bd95313f5f23a4c958a745db2134aa03244 Mon Sep 17 00:00:00 2001 From: "stevel@tonic-gate" Date: Tue, 14 Jun 2005 00:00:00 -0700 Subject: OpenSolaris Launch --- usr/src/cmd/syseventadm/Makefile | 67 ++ usr/src/cmd/syseventadm/syseventadm.c | 1149 +++++++++++++++++++++++++++++ usr/src/cmd/syseventadm/syseventadm.h | 138 ++++ usr/src/cmd/syseventadm/syseventadm_msg.h | 103 +++ 4 files changed, 1457 insertions(+) create mode 100644 usr/src/cmd/syseventadm/Makefile create mode 100644 usr/src/cmd/syseventadm/syseventadm.c create mode 100644 usr/src/cmd/syseventadm/syseventadm.h create mode 100644 usr/src/cmd/syseventadm/syseventadm_msg.h (limited to 'usr/src/cmd/syseventadm') diff --git a/usr/src/cmd/syseventadm/Makefile b/usr/src/cmd/syseventadm/Makefile new file mode 100644 index 0000000000..554002269a --- /dev/null +++ b/usr/src/cmd/syseventadm/Makefile @@ -0,0 +1,67 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# cmd/syseventadm/Makefile +# + +PROG = syseventadm + +SRCS = $(PROG).c +OBJS = $(PROG).o + +include ../Makefile.cmd + +OWNER= root +GROUP= sys +FILEMODE= 0555 + +POFILES = $(SRCS:.c=.po) + +all:= TARGET= all +install:= TARGET= install +clean:= TARGET= clean +clobber:= TARGET= clobber +lint:= TARGET= lint +_msg:= TARGET= _msg + + +.KEEP_STATE: + + +all: $(PROG) + +install: all $(ROOTUSRSBINPROG) + +clean: + $(RM) $(OBJS) + +lint: lint_SRCS + +FRC: + +include ../Makefile.targ + diff --git a/usr/src/cmd/syseventadm/syseventadm.c b/usr/src/cmd/syseventadm/syseventadm.c new file mode 100644 index 0000000000..5d17367ac1 --- /dev/null +++ b/usr/src/cmd/syseventadm/syseventadm.c @@ -0,0 +1,1149 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * syseventadm - command to administer the sysevent.conf registry + * - administers the general purpose event framework + * + * The current implementation of the registry using files in + * /etc/sysevent/config, files are named as event specifications + * are added with the combination of the vendor, publisher, event + * class and subclass strings: + * + * [,][,][,]sysevent.conf + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "syseventadm.h" +#include "syseventadm_msg.h" + +#ifndef DEBUG +#undef assert +#define assert(EX) ((void)0) +#endif + +static char *whoami = NULL; +static char *root_dir = ""; + +static char *arg_vendor = NULL; +static char *arg_publisher = NULL; +static char *arg_class = NULL; +static char *arg_subclass = NULL; +static char *arg_username = NULL; +static char *arg_path = NULL; +static int arg_nargs = 0; +static char **arg_args = NULL; + +static int lock_fd; +static char lock_file[PATH_MAX + 1]; + +extern char *optarg; +extern int optind; + +static int +usage_gen() +{ + (void) fprintf(stderr, MSG_USAGE_INTRO); + (void) fprintf(stderr, MSG_USAGE_OPTIONS); + (void) fprintf(stderr, "\n" + "\tsyseventadm add ...\n" + "\tsyseventadm remove ...\n" + "\tsyseventadm list ...\n" + "\tsyseventadm restart\n" + "\tsyseventadm help\n"); + + return (EXIT_USAGE); +} + +static int +serve_syseventdotconf(int argc, char **argv, char *cmd) +{ + int c; + int rval; + + while ((c = getopt(argc, argv, "R:v:p:c:s:u:")) != EOF) { + switch (c) { + case 'R': + /* + * Alternate root path for install, etc. + */ + set_root_dir(optarg); + break; + case 'v': + arg_vendor = optarg; + break; + case 'p': + arg_publisher = optarg; + break; + case 'c': + arg_class = optarg; + break; + case 's': + arg_subclass = optarg; + break; + case 'u': + arg_username = optarg; + break; + default: + return (usage()); + } + } + + if (optind < argc) { + arg_path = argv[optind++]; + if (optind < argc) { + arg_nargs = argc - optind; + arg_args = argv + optind; + } + } + + enter_lock(root_dir); + + if (strcmp(cmd, "add") == 0) { + rval = add_cmd(); + } else if (strcmp(cmd, "list") == 0) { + rval = list_remove_cmd(CMD_LIST); + } else if (strcmp(cmd, "remove") == 0) { + rval = list_remove_cmd(CMD_REMOVE); + } else if (strcmp(cmd, "restart") == 0) { + rval = restart_cmd(); + } else { + rval = usage(); + } + + exit_lock(); + + return (rval); +} + + +int +main(int argc, char **argv) +{ + char *cmd; + int rval; + + + (void) setlocale(LC_ALL, ""); + (void) textdomain(TEXT_DOMAIN); + + if ((whoami = strrchr(argv[0], '/')) == NULL) { + whoami = argv[0]; + } else { + whoami++; + } + + if (argc == 1) { + return (usage_gen()); + } + + cmd = argv[optind++]; + + /* Allow non-privileged users to get the help messages */ + if (strcmp(cmd, "help") == 0) { + rval = usage_gen(); + return (rval); + } + + if (getuid() != 0) { + (void) fprintf(stderr, MSG_NOT_ROOT, whoami); + exit(EXIT_PERM); + } + + if (strcmp(cmd, "evc") != 0 && getzoneid() != GLOBAL_ZONEID) { + (void) fprintf(stderr, MSG_NOT_GLOBAL, whoami); + exit(EXIT_PERM); + } + + if (strcmp(cmd, "add") == 0 || + strcmp(cmd, "remove") == 0 || strcmp(cmd, "list") == 0 || + strcmp(cmd, "restart") == 0) { + rval = serve_syseventdotconf(argc, argv, cmd); + } else { + rval = usage_gen(); + } + return (rval); +} + + +static void +enter_lock(char *root_dir) +{ + struct flock lock; + + if (snprintf(lock_file, sizeof (lock_file), "%s%s/%s", root_dir, + SYSEVENT_CONFIG_DIR, LOCK_FILENAME) >= sizeof (lock_file)) { + (void) fprintf(stderr, MSG_LOCK_PATH_ERR, whoami, lock_file); + exit(EXIT_CMD_FAILED); + } + lock_fd = open(lock_file, O_CREAT|O_RDWR, 0644); + if (lock_fd < 0) { + (void) fprintf(stderr, MSG_LOCK_CREATE_ERR, + whoami, lock_file, strerror(errno)); + exit(EXIT_CMD_FAILED); + } + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + +retry: + if (fcntl(lock_fd, F_SETLKW, &lock) == -1) { + if (errno == EAGAIN || errno == EINTR) + goto retry; + (void) close(lock_fd); + (void) fprintf(stderr, MSG_LOCK_SET_ERR, + whoami, lock_file, strerror(errno)); + exit(EXIT_CMD_FAILED); + } +} + + +static void +exit_lock() +{ + struct flock lock; + + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + if (fcntl(lock_fd, F_SETLK, &lock) == -1) { + (void) fprintf(stderr, MSG_LOCK_CLR_ERR, + whoami, lock_file, strerror(errno)); + } + + if (close(lock_fd) == -1) { + (void) fprintf(stderr, MSG_LOCK_CLOSE_ERR, + whoami, lock_file, strerror(errno)); + } +} + + +static void +set_root_dir(char *dir) +{ + root_dir = sc_strdup(dir); +} + + +static char *usage_msg[] = { + "\n" + "\tsyseventadm add [-R ] [-v vendor] [-p publisher]\n" + "\t[-c class] [-s subclass] [-u username] path [args]\n" + "\n" + "\tsyseventadm remove [-R ] [-v vendor] [-p publisher]\n" + "\t[-c class] [-s subclass] [-u username] [path [args]]\n" + "\n" + "\tsyseventadm list [-R ] [-v vendor] [-p publisher]\n" + "\t[-c class] [-s subclass] [-u username] [path [args]]\n" +}; + +static int +usage() +{ + char **msgs; + int i; + + msgs = usage_msg; + for (i = 0; i < sizeof (usage_msg)/sizeof (char *); i++) { + (void) fputs(*msgs++, stderr); + } + + return (EXIT_USAGE); +} + + +static int +add_cmd(void) +{ + char fname[MAXPATHLEN+1]; + int need_comma = 0; + int noptions = 0; + struct stat st; + FILE *fp; + str_t *line; + int i; + + /* + * At least one of vendor/publisher/class must be specified. + * Subclass is only defined within the context of class. + * For add, path must also be specified. + */ + if (arg_vendor) + noptions++; + if (arg_publisher) + noptions++; + if (arg_class) + noptions++; + + if (noptions == 0 || (arg_subclass && arg_class == NULL)) { + return (usage()); + } + + if (arg_path == NULL) + return (usage()); + + /* + * Generate the sysevent.conf file name + */ + (void) strcpy(fname, root_dir); + (void) strcat(fname, SYSEVENT_CONFIG_DIR); + (void) strcat(fname, "/"); + + if (arg_vendor) { + (void) strcat(fname, arg_vendor); + need_comma = 1; + } + if (arg_publisher) { + if (need_comma) + (void) strcat(fname, ","); + (void) strcat(fname, arg_publisher); + need_comma = 1; + } + if (arg_class) { + if (need_comma) + (void) strcat(fname, ","); + (void) strcat(fname, arg_class); + } + (void) strcat(fname, SYSEVENT_CONF_SUFFIX); + + /* + * Prepare the line to be written to the sysevent.conf file + */ + line = initstr(128); + + strcats(line, arg_class == NULL ? "-" : arg_class); + strcatc(line, ' '); + + strcats(line, arg_subclass == NULL ? "-" : arg_subclass); + strcatc(line, ' '); + + strcats(line, arg_vendor == NULL ? "-" : arg_vendor); + strcatc(line, ' '); + + strcats(line, arg_publisher == NULL ? "-" : arg_publisher); + strcatc(line, ' '); + + strcats(line, arg_username == NULL ? "-" : arg_username); + strcatc(line, ' '); + + strcats(line, "- - "); + strcats(line, arg_path); + + if (arg_nargs) { + for (i = 0; i < arg_nargs; i++) { + strcatc(line, ' '); + strcats(line, arg_args[i]); + } + } + + if (stat(fname, &st) == -1) { + if (creat(fname, 0644) == -1) { + (void) fprintf(stderr, MSG_CANNOT_CREATE, + whoami, fname, strerror(errno)); + freestr(line); + return (EXIT_CMD_FAILED); + } + } + + fp = fopen(fname, "a"); + if (fp == NULL) { + (void) fprintf(stderr, MSG_CANNOT_OPEN, + whoami, fname, strerror(errno)); + freestr(line); + return (EXIT_CMD_FAILED); + } + + (void) fprintf(fp, "%s\n", line->s_str); + freestr(line); + + if (fclose(fp) == -1) { + (void) fprintf(stderr, MSG_CLOSE_ERROR, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + + if (chmod(fname, 0444) == -1) { + (void) fprintf(stderr, MSG_CHMOD_ERROR, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + return (EXIT_OK); +} + + +static int +list_remove_cmd(int cmd) +{ + struct dirent *dp; + DIR *dir; + char path[MAXPATHLEN+1]; + char fname[MAXPATHLEN+1]; + char *suffix; + char **dirlist = NULL; + int list_size = 0; + int list_alloc = 0; + char **p; + int rval; + int result; + + /* + * For the remove cmd, at least one of vendor/publisher/class/username + * path must be specified. Subclass is only defined within the + * context of a class. + */ + if (cmd == CMD_REMOVE) { + int noptions = 0; + if (arg_vendor) + noptions++; + if (arg_publisher) + noptions++; + if (arg_class) + noptions++; + if (arg_username) + noptions++; + if (arg_path) + noptions++; + if (noptions == 0 || (arg_subclass && arg_class == NULL)) { + return (usage()); + } + } + + (void) strcpy(path, root_dir); + (void) strcat(path, SYSEVENT_CONFIG_DIR); + + if ((dir = opendir(path)) == NULL) { + (void) fprintf(stderr, MSG_CANNOT_OPEN_DIR, + whoami, path, strerror(errno)); + return (EXIT_CMD_FAILED); + } + + while ((dp = readdir(dir)) != NULL) { + if (dp->d_name[0] == '.') + continue; + if ((strlen(dp->d_name) == 0) || + (strcmp(dp->d_name, "lost+found") == 0)) + continue; + suffix = strrchr(dp->d_name, ','); + if (suffix && strcmp(suffix, SYSEVENT_CONF_SUFFIX) == 0) { + (void) strcpy(fname, path); + (void) strcat(fname, "/"); + (void) strcat(fname, dp->d_name); + dirlist = build_strlist(dirlist, + &list_size, &list_alloc, fname); + } + } + + if (closedir(dir) == -1) { + (void) fprintf(stderr, MSG_CLOSE_DIR_ERROR, + whoami, path, strerror(errno)); + return (EXIT_CMD_FAILED); + } + + rval = EXIT_NO_MATCH; + if (dirlist) { + for (p = dirlist; *p != NULL; p++) { + switch (cmd) { + case CMD_LIST: + result = list_file(*p); + break; + case CMD_REMOVE: + result = remove_file(*p); + break; + } + if (rval == EXIT_NO_MATCH && + result != EXIT_NO_MATCH) + rval = result; + } + } + return (rval); +} + + +static int +list_file(char *fname) +{ + FILE *fp; + str_t *line; + serecord_t *sep; + int rval = EXIT_NO_MATCH; + + fp = fopen(fname, "r"); + if (fp == NULL) { + (void) fprintf(stderr, MSG_CANNOT_OPEN, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + for (;;) { + line = read_next_line(fp); + if (line == NULL) + break; + sep = parse_line(line); + if (sep != NULL) { + if (matches_serecord(sep)) { + print_serecord(stdout, sep); + rval = EXIT_OK; + } + free_serecord(sep); + } + freestr(line); + } + (void) fclose(fp); + + return (rval); +} + + +static int +remove_file(char *fname) +{ + FILE *fp; + FILE *tmp_fp; + str_t *line; + char *raw_line; + serecord_t *sep; + char tmp_name[MAXPATHLEN+1]; + int is_empty = 1; + + fp = fopen(fname, "r"); + if (fp == NULL) { + (void) fprintf(stderr, MSG_CANNOT_OPEN, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + + if (check_for_removes(fp) == 0) { + (void) fclose(fp); + return (EXIT_NO_MATCH); + } + + rewind(fp); + + (void) strcpy(tmp_name, root_dir); + (void) strcat(tmp_name, SYSEVENT_CONFIG_DIR); + (void) strcat(tmp_name, "/tmp.XXXXXX"); + if (mktemp(tmp_name) == NULL) { + (void) fprintf(stderr, "unable to make tmp file name\n"); + return (EXIT_CMD_FAILED); + } + + if (creat(tmp_name, 0644) == -1) { + (void) fprintf(stderr, MSG_CANNOT_CREATE, + whoami, tmp_name, strerror(errno)); + return (EXIT_CMD_FAILED); + } + + tmp_fp = fopen(tmp_name, "a"); + if (tmp_fp == NULL) { + (void) fprintf(stderr, MSG_CANNOT_OPEN, + whoami, tmp_name, strerror(errno)); + (void) unlink(tmp_name); + (void) fclose(fp); + return (EXIT_CMD_FAILED); + } + + for (;;) { + line = read_next_line(fp); + if (line == NULL) + break; + raw_line = sc_strdup(line->s_str); + sep = parse_line(line); + if (sep == NULL) { + (void) fputs(line->s_str, tmp_fp); + } else { + if (!matches_serecord(sep)) { + is_empty = 0; + (void) fprintf(tmp_fp, "%s\n", raw_line); + } + free_serecord(sep); + } + freestr(line); + sc_strfree(raw_line); + } + (void) fclose(fp); + if (fclose(tmp_fp) == -1) { + (void) fprintf(stderr, MSG_CLOSE_ERROR, + whoami, tmp_name, strerror(errno)); + } + + if (is_empty) { + if (unlink(tmp_name) == -1) { + (void) fprintf(stderr, MSG_CANNOT_UNLINK, + whoami, tmp_name, strerror(errno)); + return (EXIT_CMD_FAILED); + } + if (unlink(fname) == -1) { + (void) fprintf(stderr, MSG_CANNOT_UNLINK, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + } else { + if (unlink(fname) == -1) { + (void) fprintf(stderr, MSG_CANNOT_UNLINK, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + if (rename(tmp_name, fname) == -1) { + (void) fprintf(stderr, MSG_CANNOT_RENAME, + whoami, tmp_name, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + if (chmod(fname, 0444) == -1) { + (void) fprintf(stderr, MSG_CHMOD_ERROR, + whoami, fname, strerror(errno)); + return (EXIT_CMD_FAILED); + } + } + + return (EXIT_OK); +} + +static int +check_for_removes(FILE *fp) +{ + str_t *line; + serecord_t *sep; + + for (;;) { + line = read_next_line(fp); + if (line == NULL) + break; + sep = parse_line(line); + if (sep != NULL) { + if (matches_serecord(sep)) { + free_serecord(sep); + freestr(line); + return (1); + } + free_serecord(sep); + } + freestr(line); + } + + return (0); +} + + +static int +matches_serecord(serecord_t *sep) +{ + char *line; + char *lp; + char *token; + int i; + + if (arg_vendor && + strcmp(arg_vendor, sep->se_vendor) != 0) { + return (0); + } + + if (arg_publisher && + strcmp(arg_publisher, sep->se_publisher) != 0) { + return (0); + } + + if (arg_class && + strcmp(arg_class, sep->se_class) != 0) { + return (0); + } + + if (arg_subclass && + strcmp(arg_subclass, sep->se_subclass) != 0) { + return (0); + } + + if (arg_username && + strcmp(arg_username, sep->se_user) != 0) { + return (0); + } + + if (arg_path && + strcmp(arg_path, sep->se_path) != 0) { + return (0); + } + + if (arg_nargs > 0) { + line = sc_strdup(sep->se_args); + lp = line; + for (i = 0; i < arg_nargs; i++) { + token = next_field(&lp); + if (strcmp(arg_args[i], token) != 0) { + sc_strfree(line); + return (0); + } + } + sc_strfree(line); + } + + return (1); +} + +static void +print_serecord(FILE *fp, serecord_t *sep) +{ + str_t *line; + + line = initstr(128); + + if (strcmp(sep->se_vendor, "-") != 0) { + strcats(line, "vendor="); + strcats(line, sep->se_vendor); + strcats(line, " "); + } + if (strcmp(sep->se_publisher, "-") != 0) { + strcats(line, "publisher="); + strcats(line, sep->se_publisher); + strcats(line, " "); + } + if (strcmp(sep->se_class, "-") != 0) { + strcats(line, "class="); + strcats(line, sep->se_class); + strcats(line, " "); + if (strcmp(sep->se_subclass, "-") != 0) { + strcats(line, "subclass="); + strcats(line, sep->se_subclass); + strcats(line, " "); + } + } + if (strcmp(sep->se_user, "-") != 0) { + strcats(line, "username="); + strcats(line, sep->se_user); + strcats(line, " "); + } + strcats(line, sep->se_path); + if (sep->se_args) { + strcats(line, " "); + strcats(line, sep->se_args); + } + strcats(line, "\n"); + + (void) fputs(line->s_str, fp); + freestr(line); +} + + + + +static int +restart_cmd(void) +{ + if (system("pkill -HUP syseventd") == -1) { + (void) fprintf(stderr, MSG_RESTART_FAILED, + whoami, strerror(errno)); + return (EXIT_CMD_FAILED); + } + return (EXIT_OK); +} + + +static str_t * +read_next_line(FILE *fp) +{ + char *lp; + str_t *line; + + line = initstr(128); + + lp = fstrgets(line, fp); + if (lp == NULL) { + freestr(line); + return (NULL); + } + + *(lp + strlen(lp)-1) = 0; + return (line); +} + + +static serecord_t * +parse_line(str_t *line) +{ + char *lp; + char *vendor, *publisher; + char *class, *subclass; + char *user; + char *reserved1, *reserved2; + char *path, *args; + serecord_t *sep; + + lp = line->s_str; + if (*lp == 0 || *lp == '#') { + return (NULL); + } + + if ((class = next_field(&lp)) != NULL) { + subclass = next_field(&lp); + if (lp == NULL) + return (NULL); + vendor = next_field(&lp); + if (lp == NULL) + return (NULL); + publisher = next_field(&lp); + if (lp == NULL) + return (NULL); + user = next_field(&lp); + if (lp == NULL) + return (NULL); + reserved1 = next_field(&lp); + if (lp == NULL) + return (NULL); + reserved2 = next_field(&lp); + if (lp == NULL) + return (NULL); + path = next_field(&lp); + if (lp == NULL) + return (NULL); + args = skip_spaces(&lp); + } + + sep = sc_malloc(sizeof (serecord_t)); + + sep->se_vendor = sc_strdup(vendor); + sep->se_publisher = sc_strdup(publisher); + sep->se_class = sc_strdup(class); + sep->se_subclass = sc_strdup(subclass); + sep->se_user = sc_strdup(user); + sep->se_reserved1 = sc_strdup(reserved1); + sep->se_reserved2 = sc_strdup(reserved2); + sep->se_path = sc_strdup(path); + sep->se_args = (args == NULL) ? NULL : sc_strdup(args); + + return (sep); +} + + +static void +free_serecord(serecord_t *sep) +{ + sc_strfree(sep->se_vendor); + sc_strfree(sep->se_publisher); + sc_strfree(sep->se_class); + sc_strfree(sep->se_subclass); + sc_strfree(sep->se_user); + sc_strfree(sep->se_reserved1); + sc_strfree(sep->se_reserved2); + sc_strfree(sep->se_path); + sc_strfree(sep->se_args); + sc_free(sep, sizeof (serecord_t)); +} + + +/* + * skip_spaces() - skip to next non-space character + */ +static char * +skip_spaces(char **cpp) +{ + char *cp = *cpp; + + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == 0) { + *cpp = 0; + return (NULL); + } + return (cp); +} + + +/* + * Get next white-space separated field. + * next_field() will not check any characters on next line. + * Each entry is composed of a single line. + */ +static char * +next_field(char **cpp) +{ + char *cp = *cpp; + char *start; + + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == 0) { + *cpp = 0; + return (NULL); + } + start = cp; + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + if (*cp != 0) + *cp++ = 0; + *cpp = cp; + return (start); +} + + + +/* + * The following functions are simple wrappers/equivalents + * for malloc, realloc, free, strdup and a special free + * for strdup. + */ + +static void * +sc_malloc(size_t n) +{ + void *p; + + p = malloc(n); + if (p == NULL) { + no_mem_err(); + } + return (p); +} + +/*ARGSUSED*/ +static void * +sc_realloc(void *p, size_t current, size_t n) +{ + p = realloc(p, n); + if (p == NULL) { + no_mem_err(); + } + return (p); +} + + +/*ARGSUSED*/ +static void +sc_free(void *p, size_t n) +{ + free(p); +} + + +static char * +sc_strdup(char *cp) +{ + char *new; + + new = malloc((unsigned)(strlen(cp) + 1)); + if (new == NULL) { + no_mem_err(); + } + (void) strcpy(new, cp); + return (new); +} + + +static void +sc_strfree(char *s) +{ + if (s) + free(s); +} + + +/* + * The following functions provide some simple dynamic string + * capability. This module has no hard-coded maximum string + * lengths and should be able to parse and generate arbitrarily + * long strings, macro expansion and command lines. + * + * Each string must be explicitly allocated and freed. + */ + +/* + * Allocate a dynamic string, with a hint to indicate how + * much memory to dynamically add to the string as it grows + * beyond its existing bounds, so as to avoid excessive + * reallocs as a string grows. + */ +static str_t * +initstr(int hint) +{ + str_t *str; + + str = sc_malloc(sizeof (str_t)); + str->s_str = NULL; + str->s_len = 0; + str->s_alloc = 0; + str->s_hint = hint; + return (str); +} + + +/* + * Free a dynamically-allocated string + */ +static void +freestr(str_t *str) +{ + if (str->s_str) { + sc_free(str->s_str, str->s_alloc); + } + sc_free(str, sizeof (str_t)); +} + + +/* + * Reset a dynamically-allocated string, allows reuse + * rather than freeing the old and allocating a new one. + */ +static void +resetstr(str_t *str) +{ + str->s_len = 0; +} + + +/* + * Concatenate a (simple) string onto a dynamically-allocated string + */ +static void +strcats(str_t *str, char *s) +{ + char *new_str; + int len = str->s_len + strlen(s) + 1; + + if (str->s_alloc < len) { + new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : + sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); + str->s_str = new_str; + str->s_alloc = len + str->s_hint; + } + (void) strcpy(str->s_str + str->s_len, s); + str->s_len = len - 1; +} + + +/* + * Concatenate a character onto a dynamically-allocated string + */ +static void +strcatc(str_t *str, int c) +{ + char *new_str; + int len = str->s_len + 2; + + if (str->s_alloc < len) { + new_str = (str->s_str == NULL) ? sc_malloc(len+str->s_hint) : + sc_realloc(str->s_str, str->s_alloc, len+str->s_hint); + str->s_str = new_str; + str->s_alloc = len + str->s_hint; + } + *(str->s_str + str->s_len) = (char)c; + *(str->s_str + str->s_len + 1) = 0; + str->s_len++; +} + +/* + * fgets() equivalent using a dynamically-allocated string + */ +static char * +fstrgets(str_t *line, FILE *fp) +{ + int c; + + resetstr(line); + while ((c = fgetc(fp)) != EOF) { + strcatc(line, c); + if (c == '\n') + break; + } + if (line->s_len == 0) + return (NULL); + return (line->s_str); +} + + + +#define INITIAL_LISTSIZE 4 +#define INCR_LISTSIZE 4 + +static char ** +build_strlist( + char **argvlist, + int *size, + int *alloc, + char *str) +{ + int n; + + if (*size + 1 > *alloc) { + if (*alloc == 0) { + *alloc = INITIAL_LISTSIZE; + n = sizeof (char *) * (*alloc + 1); + argvlist = (char **)malloc(n); + if (argvlist == NULL) + no_mem_err(); + } else { + *alloc += INCR_LISTSIZE; + n = sizeof (char *) * (*alloc + 1); + argvlist = (char **)realloc(argvlist, n); + if (argvlist == NULL) + no_mem_err(); + } + } + + argvlist[*size] = strdup(str); + *size += 1; + argvlist[*size] = NULL; + + return (argvlist); +} + +static void +no_mem_err() +{ + (void) fprintf(stderr, MSG_NO_MEM, whoami); + exit_lock(); + exit(EXIT_NO_MEM); + /*NOTREACHED*/ +} diff --git a/usr/src/cmd/syseventadm/syseventadm.h b/usr/src/cmd/syseventadm/syseventadm.h new file mode 100644 index 0000000000..0fb39f9d70 --- /dev/null +++ b/usr/src/cmd/syseventadm/syseventadm.h @@ -0,0 +1,138 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYSEVENTADM_H +#define _SYSEVENTADM_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Directory where sysevent.conf files reside + */ +#define SYSEVENT_CONFIG_DIR "/etc/sysevent/config" + +/* + * Lock file name to serialize registry updates + */ +#define LOCK_FILENAME "sysevent.lock" + +/* + * Required suffix for all sysevent.conf files + */ +#define SYSEVENT_CONF_SUFFIX ",sysevent.conf" + +/* + * cmd types for list/remove + */ +#define CMD_LIST 0 +#define CMD_REMOVE 1 + +/* + * Exit codes + */ +#define EXIT_OK 0 +#define EXIT_NO_MATCH 1 +#define EXIT_USAGE 2 +#define EXIT_PERM 3 +#define EXIT_CMD_FAILED 4 +#define EXIT_NO_MEM 5 + +/* + * sysevent.conf record + */ +typedef struct serecord { + char *se_vendor; /* vendor */ + char *se_publisher; /* publisher */ + char *se_class; /* event class */ + char *se_subclass; /* event subclass */ + char *se_user; /* user */ + char *se_reserved1; /* reserved1 */ + char *se_reserved2; /* reserved2 */ + char *se_path; /* event path */ + char *se_args; /* optional args */ +} serecord_t; + + +/* + * Structures for building arbitarily long strings and argument lists + */ +typedef struct str { + char *s_str; + int s_len; + int s_alloc; + int s_hint; +} str_t; + + +/* + * Prototypes + */ +int main(int argc, char **argv); +static void enter_lock(char *root_dir); +static void exit_lock(void); +static void set_root_dir(char *dir); +static int usage(void); +static int add_cmd(void); +static int list_remove_cmd(int cmd); +static int list_file(char *fname); +static int remove_file(char *fname); +static int check_for_removes(FILE *fp); +static int restart_cmd(void); + +static str_t *read_next_line(FILE *fp); +static serecord_t *parse_line(str_t *line); + +static int matches_serecord(serecord_t *sep); +static void print_serecord(FILE *fp, serecord_t *sep); +static void free_serecord(serecord_t *sep); + +static char *skip_spaces(char **cpp); +static char *next_field(char **cpp); +static void *sc_malloc(size_t n); +static void *sc_realloc(void *p, size_t current, size_t n); +static void sc_free(void *p, size_t n); +static char *sc_strdup(char *cp); +static void sc_strfree(char *s); + +static str_t *initstr(int hint); +static void freestr(str_t *str); +static void resetstr(str_t *str); +static void strcats(str_t *str, char *s); +static void strcatc(str_t *str, int c); +static char *fstrgets(str_t *str, FILE *fp); +static char **build_strlist(char **, int *, int *, char *); + +static void no_mem_err(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSEVENTADM_H */ diff --git a/usr/src/cmd/syseventadm/syseventadm_msg.h b/usr/src/cmd/syseventadm/syseventadm_msg.h new file mode 100644 index 0000000000..c2e1b2e4bf --- /dev/null +++ b/usr/src/cmd/syseventadm/syseventadm_msg.h @@ -0,0 +1,103 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYSEVENTADM_MSG_H +#define _SYSEVENTADM_MSG_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Gettext strings for internationalization + */ +#define MSG_NOT_ROOT \ + gettext("%s: must be root\n") + +#define MSG_NOT_GLOBAL \ + gettext("%s: must be in global zone\n") + +#define MSG_CANNOT_CREATE \ + gettext("%s: cannot create %s - %s\n") + +#define MSG_CANNOT_OPEN \ + gettext("%s: cannot open %s - %s\n") + +#define MSG_CLOSE_ERROR \ + gettext("%s: close of %s failed - %s\n") + +#define MSG_CHMOD_ERROR \ + gettext("%s: cannot chmod %s to 0444 - %s\n") + +#define MSG_CANNOT_OPEN_DIR \ + gettext("%s: cannot open directory %s - %s\n") + +#define MSG_CLOSE_DIR_ERROR \ + gettext("%s: close of directory %s failed - %s\n") + +#define MSG_TMP_FILE \ + gettext("%s: unable to make tmp file name\n") + +#define MSG_CANNOT_UNLINK \ + gettext("%s: cannot unlink %s - %s\n") + +#define MSG_CANNOT_RENAME \ + gettext("%s: cannot rename %s to %s - %s\n") + +#define MSG_RESTART_FAILED \ + gettext("%s: restart failed - %s\n") + +#define MSG_NO_MEM \ + gettext("%s: out of memory\n") + +#define MSG_USAGE_INTRO \ + gettext("usage: syseventadm ...\n") + +#define MSG_USAGE_OPTIONS \ + gettext("where the possible commands and options for each are:\n") + +#define MSG_LOCK_CREATE_ERR \ + gettext("%s: error creating lock %s - %s\n") + +#define MSG_LOCK_PATH_ERR \ + gettext("%s: error creating lock %s - file path invalid\n") + +#define MSG_LOCK_SET_ERR \ + gettext("%s: error setting lock in %s - %s\n") + +#define MSG_LOCK_CLR_ERR \ + gettext("%s: error clearing lock in %s - %s\n") + +#define MSG_LOCK_CLOSE_ERR \ + gettext("%s: error closing lock %s - %s\n") + +#ifdef __cplusplus +} +#endif + +#endif /* _SYSEVENTADM_MSG_H */ -- cgit v1.2.3