servicelog-1.1.15/0000755000175000017500000000000013614561645014120 5ustar fbonnardfbonnardservicelog-1.1.15/src/0000755000175000017500000000000013614561602014700 5ustar fbonnardfbonnardservicelog-1.1.15/src/servicelog_switch.c0000644000175000017500000001264113614560767020606 0ustar fbonnardfbonnard/* * servicelog_switch.c: the servicelog commands' front end. * Execs either the v0.2.9 version of servicelog or the v1+ version, * depending on which command-line options are specified. * * Copyright (C) 2009 IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #include "config.h" #include "platform.h" static struct option long_options[] = { /* v0.2.9 options: */ {"id", required_argument, NULL, 'i'}, {"type", required_argument, NULL, 't'}, {"start_time", required_argument, NULL, 's'}, {"end_time", required_argument, NULL, 'e'}, {"severity", required_argument, NULL, 'E'}, {"serviceable", required_argument, NULL, 'S'}, {"repair_action", required_argument, NULL, 'R'}, {"event_repaired", required_argument, NULL, 'r'}, // {"location", required_argument, NULL, 'l'}, /* v1 options: */ {"query", required_argument, NULL, 'q'}, {"dump", no_argument, NULL, 'd'}, /* common options */ {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {0,0,0,0} }; static char *cmd; static char v29_cmd[PATH_MAX]; static char v1_cmd[PATH_MAX]; static char *v29_usage[] = { v29_cmd, "-h", NULL }; static char *v1_usage[] = { v1_cmd, "-h", NULL }; static void setup_failed(const char *why) { fprintf(stderr, "%s: cannot find v1_servicelog and/or v29_servicelog\n", cmd); fprintf(stderr, "%s\n", why); } /* * Set up the pathnames for the v0.2.9 and v1+ executables. Wherever * they are, they should be in the same directory as this one, whose * pathname is referenced by the /proc/self/exe symlink. */ static void set_up_commands(void) { char self_dir[PATH_MAX]; ssize_t pathlen; char *last_slash; pathlen = readlink("/proc/self/exe", self_dir, PATH_MAX); /* Leave room because "v29_servicelog" is longer than "servicelog". */ if (pathlen < 0 || pathlen > PATH_MAX-10) { setup_failed("readlink of /proc/self/exe failed"); perror("/proc/self/exe"); exit(2); } self_dir[pathlen] = '\0'; /* since readlink doesn't provide it */ last_slash = strrchr(self_dir, '/'); if (!last_slash) { setup_failed("pathname lacks /"); exit(2); } last_slash[1] = '\0'; (void) strncpy(v1_cmd, self_dir, PATH_MAX - 1); (void) strncat(v1_cmd, "v1_servicelog", (PATH_MAX - strlen(v1_cmd) - 1 )); (void) strncpy(v29_cmd, self_dir, PATH_MAX - 1); (void) strncat(v29_cmd, "v29_servicelog", (PATH_MAX - strlen(v29_cmd) - 1)); } static void exec_command(int argc, char **argv) { execv(argv[0], argv); fprintf(stderr, "could not execute %s\n", argv[0]); perror("execv"); exit(2); } static void run_command(int argc, char **argv) { pid_t pid = fork(); if (pid == 0) { /* I'm the child. */ exec_command(argc, argv); /* NOTREACHED */ } else if (pid > 0) { /* I'm the parent. */ int status = 0; (void) wait(&status); } else { perror("fork"); exit(2); } } static void print_usage(void) { printf( "This command supports two mutually exclusive sets of command-line options.\n"); printf( "Here are the command-line options supported for compatibility with the\n" "0.2.9 version of servicelog:\n"); printf("\n"); fflush(stdout); run_command(2, v29_usage); printf("\n"); printf( "Here are the command-line options for the current (%s) version of\n" "servicelog:\n", VERSION); printf("\n"); fflush(stdout); run_command(2, v1_usage); } int main(int argc, char **argv) { int v29_opts = 0, v1_opts = 0; int option_index, rc; int platform = 0; cmd = argv[0]; platform = get_platform(); switch (platform) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", cmd, __power_platform_name(platform)); exit(1); } set_up_commands(); for (;;) { option_index = 0; rc = getopt_long(argc, argv, "dE:e:hi:q:R:r:S:s:t:Vv", long_options, &option_index); if (rc == -1) break; switch (rc) { case 'd': case 'q': v1_opts++; break; case 'E': case 'e': case 'i': case 'R': case 'r': case 'S': case 's': case 't': v29_opts++; break; case 'V': printf("%s: Version %s\n", cmd, VERSION); exit(0); case 'v': break; case 'h': case '?': print_usage(); exit(0); default: print_usage(); exit(1); /* NOTREACHED */ } } if (v1_opts && v29_opts) { fprintf(stderr, "You cannot mix v0.2.9 options with v1+ options.\n\n"); print_usage(); exit(1); } if (v29_opts) { argv[0] = v29_cmd; exec_command(argc, argv); } else { argv[0] = v1_cmd; exec_command(argc, argv); } /* NOTREACHED */ exit(2); } servicelog-1.1.15/src/servicelog.c0000644000175000017500000002140513614561602017210 0ustar fbonnardfbonnard/** * @file servicelog.c * @brief Program for querying the servicelog database * * Copyright (C) 2005, 2008, 2009, 2012 IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #define _GNU_SOURCE #include #include #include #include "config.h" #include "platform.h" static char *cmd; static struct option long_options[] = { {"query", required_argument, NULL, 'q'}, {"dump", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {0,0,0,0} }; /** * print_usage * @brief Print the usage message * * @param cmd the name of the command (argv[0] in main) */ static void print_usage(char *cmd) { printf("Usage: %s {[--dump] | [--query='']} [-vVh]\n", cmd); printf(" Without any command-line arguments, prints the statistics\n"); printf(" of the current servicelog database contents.\n\n"); printf(" --dump Dumps all of the events in the\n"); printf(" servicelog database.\n"); printf(" --query='' Prints all of the events that match the\n"); printf(" query string. is formatted like\n"); printf(" the WHERE clause of an SQL statement\n"); // Don't advertise -v. It doesn't do anything, but it might be used by // Director or some such. // printf(" --verbose | -v Verbose output\n"); printf(" --version | -V Print the version of the command and exit\n"); printf(" --help | -h Print this help text and exit\n\n"); printf(" Sample Queries:\n"); printf(" servicelog --query='id=12'\n"); printf(" prints the event with an ID of 12\n"); printf(" servicelog --query='serviceable=1 AND closed=0'\n"); printf(" prints all open (unfixed) serviceable events\n"); printf(" servicelog --query='severity>=$WARNING AND closed=0'\n"); printf(" prints all open events with a sev of WARNING or greater\n"); printf(" servicelog --query=\"time_event>'2008-02-08'\"\n"); printf(" prints all events that occurred after Feb 08, 2008\n"); return; } void check_event(struct sl_event *e, int *open, int *close, int *info) { if (e->serviceable) { if (e->closed) (*close)++; else (*open)++; } else (*info)++; } /** * main * @brief Parse command line args and execute diagnostics * * @param argc the number of command-line arguments * @param argv array of command-line arguments * @return exit status: 0 for normal exit, 1 for usage error, >1 for other error */ int main(int argc, char *argv[]) { int option_index, rc; int dump = 0; int platform = 0; char *query = NULL; servicelog *slog; struct sl_event *event; cmd = argv[0]; platform = get_platform(); switch (platform) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", cmd, __power_platform_name(platform)); exit(1); } for (;;) { option_index = 0; rc = getopt_long(argc, argv, "dq:vVh", long_options, &option_index); if (rc == -1) break; switch (rc) { case 'd': dump = 1; break; case 'q': query = optarg; break; case 'v': /* obsolete */ break; case 'V': printf("%s: Version %s\n", argv[0], VERSION); exit(0); break; case 'h': /* help */ print_usage(argv[0]); exit(0); break; case '?': print_usage(argv[0]); exit(1); break; default: fprintf(stderr, "Encountered a problem while parsing " "options; report a bug to the maintainers " "(%s).\n", PACKAGE_BUGREPORT); exit(1); } } if (dump && query) { fprintf(stderr, "The dump and query flags cannot be specified " "on the same command line.\n\n"); print_usage(argv[0]); exit(1); } rc = servicelog_open(&slog, 0); if (rc) { fprintf(stderr, "Error opening servicelog: %s\n", strerror(rc)); exit(2); } if (dump) { rc = servicelog_event_query(slog, "", &event); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } rc = servicelog_event_print(stdout, event, 1); if (rc < 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } servicelog_event_free(event); } else if (query) { rc = servicelog_event_query(slog, query, &event); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } rc = servicelog_event_print(stdout, event, 1); if (rc < 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } servicelog_event_free(event); } else { struct sl_event *e; struct sl_repair_action *repair, *r; struct sl_notify *notify, *n; int n_repair = 0, n_notify = 0; int n_events = 0, n_open = 0; /* _o = open events, _c = closed events, _i = info events */ int n_basic = 0, n_basic_o = 0, n_basic_c = 0, n_basic_i=0; int n_os = 0, n_os_o = 0, n_os_c = 0, n_os_i=0; int n_rtas = 0, n_rtas_o = 0, n_rtas_c = 0, n_rtas_i=0; int n_encl = 0, n_encl_o = 0, n_encl_c = 0, n_encl_i=0; int n_bmc = 0, n_bmc_o = 0, n_bmc_c = 0, n_bmc_i=0; /* Print a summary of the database contents */ printf("Servicelog Statistics:\n\n"); rc = servicelog_event_query(slog, "", &event); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } e = event; while (e) { n_events++; if (e->serviceable && !(e->closed)) n_open++; switch (e->type) { case SL_TYPE_BASIC: n_basic++; check_event(e, &n_basic_o, &n_basic_c, &n_basic_i); break; case SL_TYPE_OS: n_os++; check_event(e, &n_os_o, &n_os_c, &n_os_i); break; case SL_TYPE_RTAS: n_rtas++; check_event(e, &n_rtas_o, &n_rtas_c, &n_rtas_i); break; case SL_TYPE_ENCLOSURE: n_encl++; check_event(e, &n_encl_o, &n_encl_c, &n_encl_i); break; case SL_TYPE_BMC: n_bmc++; check_event(e, &n_bmc_o, &n_bmc_c, &n_bmc_i); break; default: fprintf(stderr, "Event ""%" PRIu64 "has unknown type " "%d\n", e->id, e->type); } e = e->next; } servicelog_event_free(event); if (n_open == 0) printf("There are no open events that require action." "\n\n"); else if (n_open == 1) printf("There is 1 open event requiring action.\n\n"); else printf("There are %d open events requiring action.\n\n", n_open); printf("Summary of Logged Events:\n\n"); printf(" %10s %7s %7s %7s %7s\n\n", "Type", "Total", "Open", "Closed", "Info"); if (n_basic) printf(" %10s %7d %7d %7d %7d\n", "Basic", n_basic, n_basic_o, n_basic_c, n_basic_i); if (n_os) printf(" %10s %7d %7d %7d %7d\n", "OS", n_os, n_os_o, n_os_c, n_os_i); if (n_rtas) printf(" %10s %7d %7d %7d %7d\n", "RTAS", n_rtas, n_rtas_o, n_rtas_c, n_rtas_i); if (n_encl) printf(" %10s %7d %7d %7d %7d\n", "Enclosure", n_encl, n_encl_o, n_encl_c, n_encl_i); if (n_bmc) printf(" %10s %7d %7d %7d %7d\n", "BMC", n_bmc, n_bmc_o, n_bmc_c, n_bmc_i); printf(" %10s -------------------------------\n", ""); printf(" %10s %7d %7d %7d %7d\n\n", "", n_basic + n_os + n_rtas + n_encl + n_bmc, n_basic_o + n_os_o + n_rtas_o + n_encl_o + n_bmc_o, n_basic_c + n_os_c + n_rtas_c + n_encl_c + n_bmc_c, n_basic_i + n_os_i + n_rtas_i + n_encl_i + n_bmc_i); rc = servicelog_repair_query(slog, "", &repair); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } r = repair; while (r) { n_repair++; r = r->next; } servicelog_repair_free(repair); printf("Logged Repair Actions: %d\n", n_repair); rc = servicelog_notify_query(slog, "", ¬ify); if (rc != 0) { fprintf(stderr, "%s\n", servicelog_error(slog)); servicelog_close(slog); exit(2); } n = notify; while (n) { n_notify++; n = n->next; } servicelog_notify_free(notify); printf("Registered Notification Tools: %d\n", n_notify); } servicelog_close(slog); return 0; } servicelog-1.1.15/src/servicelog_notify.c0000644000175000017500000004274713614561602020614 0ustar fbonnardfbonnard/** * @file servicelog_notify.c * @brief Program for registering/manipulating servicelog notification tools * * Copyright (C) 2005, 2008, 2013 IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include "config.h" #include "platform.h" #define ACTION_TOOMANY -1 #define ACTION_UNSPECIFIED 0 #define ACTION_ADD 1 #define ACTION_LIST 2 #define ACTION_REMOVE 3 #define ACTION_QUERY 4 #define TYPE_EVENTS 0x1 #define TYPE_REPAIRS 0x2 #define ARG_LIST "alrqi:t:E:R:S:c:M:m:h" static char *cmd; static struct option long_options[] = { {"add", no_argument, NULL, 'a'}, {"remove", no_argument, NULL, 'r'}, {"list", no_argument, NULL, 'l'}, {"match", required_argument, NULL, 'm'}, {"type", required_argument, NULL, 't'}, {"command", required_argument, NULL, 'c'}, {"method", required_argument, NULL, 'M'}, {"id", required_argument, NULL, 'i'}, {"help", no_argument, NULL, 'h'}, /* v29-only command line options */ {"severity", required_argument, NULL, 'E'}, {"repair_action", required_argument, NULL, 'R'}, {"serviceable", required_argument, NULL, 'S'}, {"query", no_argument, NULL, 'q'}, {0,0,0,0} }; /** * print_usage * @brief Print the usage message */ static void print_usage() { printf("Usage: %s {--add | --remove | --list} [flags]\n", cmd); printf(" Add Flags:\n"); printf(" --command=\"\" command to be run when notified\n"); printf(" --type=EVENT|REPAIR notify on events or repair actions?\n"); printf(" --match= notify on events matching query\n"); printf(" --method={num_stdin|num_arg|text_stdin|pairs_stdin}\n"); printf(" Remove Flags: One of --id or --command must be specified.\n"); printf(" List Flags: At most one of --id or --command may be specified.\n"); printf(" --id= ID of registered tool to list or remove\n"); printf(" Flags supported for backward compatibility:\n"); printf(" --type=\"\" notify on specified event type(s).\n"); printf(" Can be: [os|ppc64_encl|ppc64_rtas|ppc64_bmc],\n"); printf(" or multiple with '|' between\n"); printf(" --severity= notify only of events with at least\n"); printf(" severity. (Range 1 (lowest) to 7 (fatal))\n"); printf(" --repair_action={yes|no|all}\n"); printf(" --serviceable={yes|no|all}\n"); printf(" --query Like --list, but requires --id or --command.\n"); printf(" Other Flags:\n"); printf(" --help Print this help text and exit\n"); return; } /** * valid_yna_arg * @brief validate an arg as either "yes", "no" or "all" * * @param arg command-line option that is being validated * @param optarg argument to validate * @return converted value if its is valid, -1 otherwise */ static int valid_yna_arg(const char *optarg) { if (strncmp(optarg, "yes", 3) == 0) return SL_QUERY_YES; if (strncmp(optarg, "no", 2) == 0) return SL_QUERY_NO; if (strncmp(optarg, "all", 3) == 0) return SL_QUERY_ALL; fprintf(stderr, "The \"%s\" argument is not valid\n", optarg); print_usage(); return -1; } /** * valid_method_arg * @brief validate an arg as either "num_stdin", "num_arg" or "text_stdin" * * @param arg argument to validate * @return converted value if it is valid, -1 otherwise */ static int valid_method_arg(const char *arg) { if (strncmp(arg, "num_stdin", 9) == 0) return SL_METHOD_NUM_VIA_STDIN; else if (strncmp(arg, "num_arg", 7) == 0) return SL_METHOD_NUM_VIA_CMD_LINE; else if (strncmp(arg, "text_stdin", 10) == 0) return SL_METHOD_PRETTY_VIA_STDIN; else if (strncmp(arg, "pairs_stdin", 11) == 0) return SL_METHOD_SIMPLE_VIA_STDIN; return -1; } /** * main * @brief Parse command line args and execute diagnostics * * @param argc the number of command-line arguments * @param argv array of command-line arguments * @return exit status: 0 for normal exit, 1 for usage error, >1 for other error */ int main(int argc, char *argv[]) { int option_index, rc, action=ACTION_UNSPECIFIED; int flag_id=0; int add_flags=0, method=0, servicable = 0; /* * Once again, it was necessary to make some tradeoffs in adding * v29 support to v1. In the case of a --type argument, * v1 permits EVENT or REPAIR, which is then passed * in during the add in notify_struct->notify. v29 permitted * --type=os|app|ppc_rtas etc, which is transformed into a * MATCH string in v1. (Unlike v29, we don't support multiple * --type options.) So, type_match is the match * string we generate to encode any v29-style filters on * event type, severity, or serviceability. (In v1, such * filters are specified with the -m option.) * * If the user specifies both a v1 -m option and one or more * v29 type, severity, or serviceability options, we use the * -m match string and ignore type_match (!). * * All this needs to be revisited. */ char type_match[1024], *type_tmp = NULL; char *next = type_match, *end = next + sizeof(type_match) - 1; int notify_flag = 0; uint64_t id=0; char *command=NULL, *match=NULL, query[256], cmdbuf[256]; char *next_char; struct servicelog *servlog; struct sl_notify *notify, *current; struct stat sbuf; char *tSev = NULL; int tRepAct = 0; int platform = 0; char *connector = ""; cmd = argv[0]; platform = get_platform(); switch (platform) { case PLATFORM_UNKNOWN: case PLATFORM_POWERNV: fprintf(stderr, "%s: is not supported on the %s platform\n", cmd, __power_platform_name(platform)); exit(1); } if (argc <= 1) { print_usage(); exit(0); } memset(&servlog, 0, sizeof(servlog)); for (;;) { option_index = 0; rc = getopt_long(argc, argv, ARG_LIST, long_options, &option_index); if (rc == -1) break; switch (rc) { case 'a': if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_ADD; break; case 'r': if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_REMOVE; break; case 'l': if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_LIST; break; case 'q': if (action != ACTION_UNSPECIFIED) action = ACTION_TOOMANY; if (action != ACTION_TOOMANY) action = ACTION_QUERY; break; case 'i': /* event ID */ id = strtoul(optarg, &next_char, 10); if (optarg[0] == '\0' || *next_char != '\0' || (long)id <= 0) { fprintf(stderr,"--id argument invalid.\n\n"); print_usage(); exit(1); } flag_id = 1; break; case 't': type_tmp = optarg; add_flags++; break; case 'c': command = optarg; /* verify command argument */ snprintf(cmdbuf, 256, "%s", command); next_char = strchr(cmdbuf, ' '); if (next_char != NULL) *next_char = '\0'; if (stat(cmdbuf, &sbuf) < 0) { fprintf(stderr, "Command '%s' does not exist.\n", cmdbuf); exit(1); } if (!S_ISREG(sbuf.st_mode)) { fprintf(stderr, "'%s' is not a valid command.\n", cmdbuf); exit(1); } if (!(sbuf.st_mode & S_IXUSR)) { fprintf(stderr, "'%s' does not have execute " "permission.\n", cmdbuf); exit(1); } break; case 'm': match = optarg; add_flags++; break; case 'M': method = valid_method_arg(optarg); if (method == -1) { fprintf(stderr, "--method or -M argument invalid\n"); print_usage(); exit(1); } add_flags++; break; case 'h': /* help */ print_usage(); exit(0); break; case'E': tSev = optarg; add_flags++; break; case'R': tRepAct = valid_yna_arg(optarg); switch (tRepAct) { case SL_QUERY_YES: notify_flag = TYPE_REPAIRS; break; case SL_QUERY_NO: notify_flag = TYPE_EVENTS; break; case SL_QUERY_ALL: notify_flag = TYPE_EVENTS | TYPE_REPAIRS; break; default: fprintf(stderr, "--repair_action or -R argument invalid\n"); print_usage(); exit(1); } add_flags++; break; case'S': servicable = valid_yna_arg(optarg); if (servicable < 0) { fprintf(stderr, "--serviceable or -S argument invalid\n"); print_usage(); exit(1); } // This seems odd. if (servicable < 2) // Yes or All notify_flag |= TYPE_EVENTS; add_flags++; break; case '?': fprintf(stderr, "Unknown flag: -%c\n", rc); print_usage(); exit(1); break; default: fprintf(stderr, "Invalid argument\n"); } } /* Command-line validation */ if (action == ACTION_UNSPECIFIED) { fprintf(stderr, "One of --add, --remove, --query or --list " "is required.\n\n"); print_usage(); exit(1); } *next = '\0'; if (type_tmp) { /* convert type arg to a valid v1 match string */ /* * This code is pretty bad. It permits only one --type * option, and that could contain all sorts of garbage we * we wouldn't notice. */ uint64_t type_bitmap = 0; extern char *v29_types_to_v1_match(char*, uint64_t); extern uint32_t convert_type_to_v29(uint32_t v1_type); if (strstr(type_tmp, "EVENT") != NULL) { notify_flag = notify_flag | TYPE_EVENTS; } if (strstr(type_tmp, "REPAIR") != NULL) { notify_flag = notify_flag | TYPE_REPAIRS; } if (strstr(type_tmp, "ppc64_rtas") != NULL) { type_bitmap |= (1 << convert_type_to_v29(SL_TYPE_RTAS)); } if (strstr(type_tmp, "os") != NULL) { type_bitmap |= (1 << convert_type_to_v29(SL_TYPE_OS)); } if (strstr(type_tmp, "ppc64_encl") != NULL) { type_bitmap |= (1 << convert_type_to_v29(SL_TYPE_ENCLOSURE)); } if (type_bitmap) { next = v29_types_to_v1_match(next, type_bitmap); connector = " and "; } } if (action == ACTION_TOOMANY) { fprintf(stderr, "Only one of the --add, --remove, or " "--list options may be specified.\n\n"); print_usage(); exit(1); } if ((action == ACTION_QUERY) && ((!command) && (!flag_id))) { fprintf(stderr, "--query must be accompanies by --command='command path' or --id=.\n\n"); print_usage(); exit(1); } rc = servicelog_open(&servlog, 0); if (rc != 0) { fprintf(stderr, "%s\n", strerror(rc)); return 2; } /* Added for v0.2.9 backwards compatibility */ // Build a match string out of the provided params if (tSev) { next += snprintf(next, (end - next), "%s severity>=%s", connector, tSev); connector = " and "; } if (servicable) { if (servicable == SL_QUERY_NO) { next += snprintf(next, (end - next), "%s serviceable=0", connector); connector = " and "; } else if (servicable == SL_QUERY_YES) { next += snprintf(next, (end - next), "%s serviceable=1", connector); connector = " and "; } } switch (action) { case ACTION_ADD: /* bpeters: * Note: In v0.2.9, repair and system event notifications could both be added in * the same command line call. In v1, this is not supported. To circumvent this, * I do two separate action add calls, one for repair and one for events. * Default is to add an event notification. */ /* Default to adding an event notification type */ if (!notify_flag) notify_flag = TYPE_EVENTS; /* additional command line validation */ if (flag_id) { fprintf(stderr, "The --id flag may not be used with " "the --add option.\n\n"); print_usage(); rc = 1; goto err_out; } if (command == NULL) { fprintf(stderr, "The --command flag must be specified " "with the --add option.\n\n"); print_usage(); rc = 1; goto err_out; } /* Must register two events, since in v1 EVENT and REPAIR cannot be done with 1 DB entry */ /* set up an sl_notify struct and call servicelog_notify_log */ if (notify_flag & TYPE_EVENTS) { notify = calloc(1, sizeof(struct sl_notify)); if (!notify) { fprintf(stderr, "malloc failed, while" " allocating notify.\n\n"); rc = 1; goto err_out; } /* calloc */ notify->notify = SL_NOTIFY_EVENTS; notify->method = method; /* A v1 command line arg will take precedence */ if (match) notify->match = strdup(match); else /* * notify->match can't be NULL, but * it can be an empty string. */ notify->match = strdup(type_match); notify->command = strdup(command); rc = servicelog_notify_log(servlog, notify, &id); servicelog_notify_free(notify); if (rc == 0) { printf("Event Notification Registration successful (id: ""%" PRIu64 ")\n", id); } else { fprintf(stderr, "%s\n", servicelog_error(servlog)); rc = 2; goto err_out; } } if (notify_flag & TYPE_REPAIRS) { /* set up an sl_notify struct and call servicelog_notify_log */ notify = calloc(1, sizeof(struct sl_notify)); if (!notify) { fprintf(stderr, "malloc failed, while" " allocating notify.\n\n"); rc = 1; goto err_out; } /* calloc */ notify->notify = SL_NOTIFY_REPAIRS; notify->method = method; /* A v1 command line arg will take precedence */ if (match) notify->match = strdup(match); else /* * None of the filters in type_match * (type, severity, serviceable) * apply to repair_actions, but * servicelog_notify_log() demands * a non-NULL (but possibly empty) * match string. */ notify->match = strdup(""); notify->command = strdup(command); rc = servicelog_notify_log(servlog, notify, &id); servicelog_notify_free(notify); if (rc == 0) { printf("Repair Notification Registration successful (id: ""%" PRIu64 ")\n", id); } else { fprintf(stderr, "%s\n", servicelog_error(servlog)); rc = 2; goto err_out; } } break; case ACTION_LIST: case ACTION_QUERY: /* additional command line validation */ if ((command && flag_id) || add_flags) { fprintf(stderr, "Only one of the --command or --id " "flags may be specified with the --list " "or --query option.\n\n"); print_usage(); rc = 1; goto err_out; } /* * Query the database. * * Note: ppc64-diag's ppc64_diag_setup script expects * us to exit(1) if we print no notification tools... * bugzilla #76334 notwithstanding. */ if (flag_id) { rc = servicelog_notify_get(servlog, id, ¬ify); if (rc) { fprintf(stderr, "%s\n", servicelog_error(servlog)); goto err_out; } else if (notify == NULL) { fprintf(stderr, "Could not find a registered " "notification tool with the specified " "id (""%" PRIu64 ").\n", id); rc = 1; goto err_out; } } else if (command) { snprintf(query, 256, "command = '%s'", command); rc = servicelog_notify_query(servlog, query, ¬ify); if (rc) { fprintf(stderr, "%s\n", servicelog_error(servlog)); goto err_out; } else if (notify == NULL) { fprintf(stderr, "Could not find a registered " "notification tool with the specified " "command ('%s').\n", command); rc = 1; goto err_out; } } else { rc = servicelog_notify_query(servlog, "id>0", ¬ify); if (rc) { fprintf(stderr, "%s\n", servicelog_error(servlog)); goto err_out; } else if (notify == NULL) { fprintf(stderr, "There are no registered " "notification tools.\n"); rc = 1; goto err_out; } } /* display the notification tools */ servicelog_notify_print(stdout, notify, 2); servicelog_notify_free(notify); break; case ACTION_REMOVE: /* additional command line validation */ if ((command == NULL) && (!flag_id)) { fprintf(stderr, "At least one of the --command or --id " "flags must be specified with the --remove " "option.\n\n"); print_usage(); rc = 1; goto err_out; } /* find the registered notification tool to be removed */ if (flag_id) { rc = servicelog_notify_get(servlog, id, ¬ify); if (rc) { fprintf(stderr, "%s\n", servicelog_error(servlog)); goto err_out; } else if (notify == NULL) { fprintf(stderr, "Could not find a registered " "notification tool with the specified " "id (""%" PRIu64 ").\n", id); rc = 1; goto err_out; } } else { /* search for the notify tool by command name */ snprintf(query, 256, "command = '%s'", command); rc = servicelog_notify_query(servlog, query, ¬ify); if (rc) { fprintf(stderr, "%s\n", servicelog_error(servlog)); goto err_out; } else if (notify == NULL) { fprintf(stderr, "Could not find a registered " "notification tool with the specified " "command ('%s').\n", command); rc = 1; goto err_out; } } for (current = notify; current; current = current->next) servicelog_notify_delete(servlog, current->id); servicelog_notify_free(notify); break; default: fprintf(stderr, "Internal error; unknown action %d\n", action); rc = 1; goto err_out; } err_out: servicelog_close(servlog); return rc; } servicelog-1.1.15/src/slog_common_event.c0000644000175000017500000001331713614560767020601 0ustar fbonnardfbonnard/** * @file slog_common_event.c * @brief Common program for logging certain informational events to servicelog * * Copyright (C) 2008 IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ #include #include #include #include #include #include #include #include "config.h" #include "platform.h" static struct option long_options[] = { {"event", required_argument, NULL, 'e'}, {"time", required_argument, NULL, 't'}, {"source", required_argument, NULL, 's'}, {"destination", required_argument, NULL, 'd'}, {"location", required_argument, NULL, 'l'}, {"help", no_argument, NULL, 'h'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {0,0,0,0} }; /** * print_usage * @brief Print the usage message * * @param cmd the name of the command (argv[0] in main) */ static void print_usage(char *cmd) { printf("Usage: %s --event= {other_flags}\n", cmd); printf(" --event= can be one of the following:\n"); printf(" migration\n"); printf(" fw_update\n"); printf(" dump_os\n"); printf(" Other Flags:\n"); printf(" --time=