From: Ben Pfaff Date: Thu, 23 Oct 2008 17:45:39 +0000 (-0700) Subject: vlog: Add ability to log to an arbitrary file, and following related changes: X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6eb6bc746ebeee6027929e142f00b72fef57656;p=openvswitch vlog: Add ability to log to an arbitrary file, and following related changes: * New command-line options for configuring log files, hence: - Centralized vlog usage messages. * New vlogconf action for reopening log files. * New vlogconf support for specifying a target by pidfile. --- diff --git a/controller/controller.c b/controller/controller.c index df8ca16b..9a334185 100644 --- a/controller/controller.c +++ b/controller/controller.c @@ -239,13 +239,13 @@ parse_options(int argc, char *argv[]) { enum { OPT_MAX_IDLE = UCHAR_MAX + 1, - OPT_PEER_CA_CERT + OPT_PEER_CA_CERT, + VLOG_OPTION_ENUMS }; static struct option long_options[] = { {"hub", no_argument, 0, 'H'}, {"noflow", no_argument, 0, 'n'}, {"max-idle", required_argument, 0, OPT_MAX_IDLE}, - {"verbose", optional_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, DAEMON_LONG_OPTIONS, @@ -294,10 +294,7 @@ parse_options(int argc, char *argv[]) printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]); exit(EXIT_SUCCESS); - case 'v': - vlog_set_verbosity(optarg); - break; - + VLOG_OPTION_HANDLERS DAEMON_OPTION_HANDLERS #ifdef HAVE_OPENSSL @@ -327,12 +324,11 @@ usage(void) program_name, program_name); vconn_usage(true, true, false); daemon_usage(); + vlog_usage(); printf("\nOther options:\n" " -H, --hub act as hub instead of learning switch\n" " -n, --noflow pass traffic, but don't add flows\n" " --max-idle=SECS max idle time for new flows\n" - " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" - " -v, --verbose set maximum verbosity level\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); diff --git a/include/daemon.h b/include/daemon.h index 94d369aa..821465fd 100644 --- a/include/daemon.h +++ b/include/daemon.h @@ -35,6 +35,7 @@ #define DAEMON_H 1 #include +#include #define DAEMON_LONG_OPTIONS \ {"detach", no_argument, 0, 'D'}, \ @@ -62,5 +63,6 @@ void daemonize(void); void die_if_already_running(void); void ignore_existing_pidfile(void); void daemon_usage(void); +pid_t read_pidfile(const char *name); #endif /* daemon.h */ diff --git a/include/vlog-modules.def b/include/vlog-modules.def index 9edb8a82..3b805c7d 100644 --- a/include/vlog-modules.def +++ b/include/vlog-modules.def @@ -29,6 +29,7 @@ VLOG_MODULE(vconn_stream) VLOG_MODULE(vconn_unix) VLOG_MODULE(vconn) VLOG_MODULE(vlog) +VLOG_MODULE(vlog_socket) #ifdef HAVE_EXT #include "ext/vlogext-modules.def" diff --git a/include/vlog.h b/include/vlog.h index 6530de6a..350475b4 100644 --- a/include/vlog.h +++ b/include/vlog.h @@ -59,7 +59,8 @@ enum vlog_level vlog_get_level_val(const char *name); /* Facilities that we can log to. */ #define VLOG_FACILITIES \ VLOG_FACILITY(SYSLOG, "%05N|%c|%p|%m") \ - VLOG_FACILITY(CONSOLE, "%d{%b %d %H:%M:%S}|%05N|%c|%p|%m") + VLOG_FACILITY(CONSOLE, "%d{%b %d %H:%M:%S}|%05N|%c|%p|%m") \ + VLOG_FACILITY(FILE, "%d{%b %d %H:%M:%S}|%05N|%c|%p|%m") enum vlog_facility { #define VLOG_FACILITY(NAME, PATTERN) VLF_##NAME, VLOG_FACILITIES @@ -115,12 +116,17 @@ struct vlog_rate_limit { /* Configuring how each module logs messages. */ enum vlog_level vlog_get_level(enum vlog_module, enum vlog_facility); void vlog_set_levels(enum vlog_module, enum vlog_facility, enum vlog_level); -void vlog_set_pattern(enum vlog_facility, const char *pattern); char *vlog_set_levels_from_string(const char *); char *vlog_get_levels(void); bool vlog_is_enabled(enum vlog_module, enum vlog_level); void vlog_set_verbosity(const char *arg); +/* Configuring log facilities. */ +void vlog_set_pattern(enum vlog_facility, const char *pattern); +const char *vlog_get_log_file(void); +int vlog_set_log_file(const char *file_name); +int vlog_reopen_log_file(void); + /* Function for actual logging. */ void vlog_init(void); void vlog_exit(void); @@ -164,6 +170,20 @@ void vlog_rate_limit(enum vlog_module, enum vlog_level, #define VLOG_DBG_RL(RL, ...) \ vlog_rate_limit(THIS_MODULE, VLL_DBG, RL, __VA_ARGS__) +/* Command line processing. */ +#define VLOG_OPTION_ENUMS OPT_LOG_FILE +#define VLOG_LONG_OPTIONS \ + {"verbose", optional_argument, 0, 'v'}, \ + {"log-file", optional_argument, 0, OPT_LOG_FILE} +#define VLOG_OPTION_HANDLERS \ + case 'v': \ + vlog_set_verbosity(optarg); \ + break; \ + case OPT_LOG_FILE: \ + vlog_set_log_file(optarg); \ + break; +void vlog_usage(void); + /* Implementation details. */ #define VLOG(LEVEL, ...) \ do { \ @@ -173,4 +193,5 @@ void vlog_rate_limit(enum vlog_module, enum vlog_level, } while (0) extern enum vlog_level min_vlog_levels[VLM_N_MODULES]; + #endif /* vlog.h */ diff --git a/lib/daemon.c b/lib/daemon.c index 8800d0d2..b8fc5afe 100644 --- a/lib/daemon.c +++ b/lib/daemon.c @@ -246,3 +246,51 @@ daemon_usage(void) " -f, --force with -P, start even if already running\n", ofp_rundir, program_name); } + +/* Opens and reads a PID from 'pidfile'. Returns the nonnegative PID if + * successful, otherwise a negative errno value. */ +pid_t +read_pidfile(const char *pidfile) +{ + char line[128]; + struct flock lck; + FILE *file; + int error; + + file = fopen(pidfile, "r"); + if (!file) { + error = errno; + VLOG_WARN("%s: open: %s", pidfile, strerror(error)); + goto error; + } + + lck.l_type = F_WRLCK; + lck.l_whence = SEEK_SET; + lck.l_start = 0; + lck.l_len = 0; + if (fcntl(fileno(file), F_GETLK, &lck)) { + error = errno; + VLOG_WARN("%s: fcntl: %s", pidfile, strerror(error)); + goto error; + } + + if (!fgets(line, sizeof line, file)) { + error = errno; + VLOG_WARN("%s: read: %s", pidfile, strerror(error)); + goto error; + } + + if (lck.l_pid != strtoul(line, NULL, 10)) { + error = ESRCH; + VLOG_WARN("l_pid (%ld) != %s pid (%s)", + (long int) lck.l_pid, pidfile, line); + goto error; + } + + fclose(file); + return lck.l_pid; + +error: + fclose(file); + return -error; +} diff --git a/lib/vlog-socket.c b/lib/vlog-socket.c index 7fffc131..7cfc5d7c 100644 --- a/lib/vlog-socket.c +++ b/lib/vlog-socket.c @@ -33,6 +33,7 @@ #include #include "vlog-socket.h" +#include #include #include #include @@ -43,16 +44,19 @@ #include #include #include +#include "daemon.h" #include "fatal-signal.h" #include "poll-loop.h" #include "socket-util.h" #include "timeval.h" #include "util.h" -#include "vlog.h" #ifndef SCM_CREDENTIALS #include #endif + +#define THIS_MODULE VLM_vlog_socket +#include "vlog.h" /* Server for Vlog control connection. */ struct vlog_server { @@ -256,6 +260,12 @@ poll_server(int fd UNUSED, short int events, void *server_) reply = msg ? msg : xstrdup("ack"); } else if (!strcmp(cmd_buf, "list")) { reply = vlog_get_levels(); + } else if (!strcmp(cmd_buf, "reopen")) { + int error = vlog_reopen_log_file(); + reply = (error + ? xasprintf("could not reopen log file \"%s\": %s", + vlog_get_log_file(), strerror(error)) + : xstrdup("ack")); } else { reply = xstrdup("nak"); } @@ -274,11 +284,18 @@ struct vlog_client { int fd; }; -/* Connects to a Vlog server socket. If 'path' does not start with '/', then - * it start with a PID as a string. If a non-null, non-absolute name was - * passed to Vlog_server_socket::listen(), then it must follow the PID in - * 'path'. If 'path' starts with '/', then it must be an absolute path that - * gives the exact name of the Unix domain socket to connect to. +/* Connects to a Vlog server socket. 'path' may be: + * + * - A string that starts with a PID. If a non-null, non-absolute name + * was passed to Vlog_server_socket::listen(), then it must follow the + * PID in 'path'. + * + * - An absolute path (starting with '/') to a Vlog server socket or a + * pidfile. If it is a pidfile, the pidfile will be read and translated + * into a Vlog server socket file name. + * + * - A relative path, which is translated into a pidfile name and then + * treated as above. * * Returns 0 if successful, otherwise a positive errno value. If successful, * sets '*clientp' to the new vlog_client, otherwise to NULL. */ @@ -287,29 +304,52 @@ vlog_client_connect(const char *path, struct vlog_client **clientp) { static int counter; struct vlog_client *client; - int fd; + struct stat s; + int error; client = xmalloc(sizeof *client); - client->connect_path = (path[0] == '/' - ? xstrdup(path) - : xasprintf("/tmp/vlogs.%s", path)); - - client->bind_path = xasprintf("/tmp/vlog.%ld.%d", - (long int) getpid(), counter++); - fd = make_unix_socket(SOCK_DGRAM, false, false, - client->bind_path, client->connect_path); - - if (fd >= 0) { - client->fd = fd; - *clientp = client; - return 0; + if (path[0] == '/') { + client->connect_path = xstrdup(path); + } else if (isdigit((unsigned char) path[0])) { + client->connect_path = xasprintf("/tmp/vlogs.%s", path); } else { + client->connect_path = make_pidfile_name(path); + } + client->bind_path = NULL; + + if (stat(client->connect_path, &s)) { + error = errno; + VLOG_WARN("could not stat \"%s\": %s", + client->connect_path, strerror(error)); + goto error; + } else if (S_ISREG(s.st_mode)) { + pid_t pid = read_pidfile(client->connect_path); + if (pid < 0) { + error = -pid; + VLOG_WARN("could not read pidfile \"%s\": %s", + client->connect_path, strerror(error)); + goto error; + } free(client->connect_path); - free(client->bind_path); - free(client); - *clientp = NULL; - return errno; + client->connect_path = xasprintf("/tmp/vlogs.%ld", (long int) pid); } + client->bind_path = xasprintf("/tmp/vlog.%ld.%d", + (long int) getpid(), counter++); + client->fd = make_unix_socket(SOCK_DGRAM, false, false, + client->bind_path, client->connect_path); + if (client->fd < 0) { + error = -client->fd; + goto error; + } + *clientp = client; + return 0; + +error: + free(client->connect_path); + free(client->bind_path); + free(client); + *clientp = NULL; + return error; } /* Destroys 'client'. */ diff --git a/lib/vlog.c b/lib/vlog.c index 756433ca..ddfab761 100644 --- a/lib/vlog.c +++ b/lib/vlog.c @@ -43,6 +43,7 @@ #include #include #include +#include "dirs.h" #include "dynamic-string.h" #include "sat-math.h" #include "timeval.h" @@ -93,6 +94,10 @@ enum vlog_level min_vlog_levels[VLM_N_MODULES]; /* Time at which vlog was initialized, in milliseconds. */ static long long int boot_time; +/* VLF_FILE configuration. */ +static char *log_file_name; +static FILE *log_file; + /* Searches the 'n_names' in 'names'. Returns the index of a match for * 'target', or 'n_names' if no name matches. */ static size_t @@ -179,7 +184,9 @@ update_min_level(enum vlog_module module) enum vlog_facility facility; for (facility = 0; facility < VLF_N_FACILITIES; facility++) { - min_level = MAX(min_level, levels[module][facility]); + if (log_file || facility != VLF_FILE) { + min_level = MAX(min_level, levels[module][facility]); + } } min_vlog_levels[module] = min_level; } @@ -243,6 +250,71 @@ vlog_set_pattern(enum vlog_facility facility, const char *pattern) } } +/* Returns the name of the log file used by VLF_FILE, or a null pointer if no + * log file has been set. (A non-null return value does not assert that the + * named log file is in use: if vlog_set_log_file() or vlog_reopen_log_file() + * fails, it still sets the log file name.) */ +const char * +vlog_get_log_file(void) +{ + return log_file_name; +} + +/* Sets the name of the log file used by VLF_FILE to 'file_name', or to the + * default file name if 'file_name' is null. Returns 0 if successful, + * otherwise a positive errno value. */ +int +vlog_set_log_file(const char *file_name) +{ + char *old_log_file_name; + enum vlog_module module; + int error; + + /* Close old log file. */ + if (log_file) { + VLOG_WARN("closing log file"); + fclose(log_file); + log_file = NULL; + } + + /* Update log file name and free old name. The ordering is important + * because 'file_name' might be 'log_file_name' or some suffix of it. */ + old_log_file_name = log_file_name; + log_file_name = (file_name + ? xstrdup(file_name) + : xasprintf("%s/%s.log", ofp_logdir, program_name)); + free(old_log_file_name); + file_name = NULL; /* Might have been freed. */ + + /* Open new log file and update min_levels[] to reflect whether we actually + * have a log_file. */ + log_file = fopen(log_file_name, "a"); + for (module = 0; module < VLM_N_MODULES; module++) { + update_min_level(module); + } + + /* Log success or failure. */ + if (!log_file) { + VLOG_WARN("failed to open %s for logging: %s", + log_file_name, strerror(errno)); + error = errno; + } else { + VLOG_WARN("opened log file %s", log_file_name); + error = 0; + } + + return error; +} + +/* Closes and then attempts to re-open the current log file. (This is useful + * just after log rotation, to ensure that the new log file starts being used.) + * Returns 0 if successful, otherwise a positive errno value. */ +int +vlog_reopen_log_file(void) +{ + return vlog_set_log_file(log_file_name); +} + /* Set debugging levels: * * mod[:facility[:level]] mod2[:facility[:level]] ... @@ -358,14 +430,15 @@ vlog_get_levels(void) struct ds s = DS_EMPTY_INITIALIZER; enum vlog_module module; - ds_put_format(&s, " console syslog\n"); - ds_put_format(&s, " ------- ------\n"); + ds_put_format(&s, " console syslog file\n"); + ds_put_format(&s, " ------- ------ ------\n"); for (module = 0; module < VLM_N_MODULES; module++) { - ds_put_format(&s, "%-16s %4s %4s\n", + ds_put_format(&s, "%-16s %4s %4s %4s\n", vlog_get_module_name(module), vlog_get_level_name(vlog_get_level(module, VLF_CONSOLE)), - vlog_get_level_name(vlog_get_level(module, VLF_SYSLOG))); + vlog_get_level_name(vlog_get_level(module, VLF_SYSLOG)), + vlog_get_level_name(vlog_get_level(module, VLF_FILE))); } return ds_cstr(&s); @@ -489,9 +562,10 @@ void vlog_valist(enum vlog_module module, enum vlog_level level, const char *message, va_list args) { - bool log_console = levels[module][VLF_CONSOLE] >= level; - bool log_syslog = levels[module][VLF_SYSLOG] >= level; - if (log_console || log_syslog) { + bool log_to_console = levels[module][VLF_CONSOLE] >= level; + bool log_to_syslog = levels[module][VLF_SYSLOG] >= level; + bool log_to_file = levels[module][VLF_FILE] >= level && log_file; + if (log_to_console || log_to_syslog || log_to_file) { int save_errno = errno; static unsigned int msg_num; struct ds s; @@ -500,14 +574,14 @@ vlog_valist(enum vlog_module module, enum vlog_level level, ds_reserve(&s, 1024); msg_num++; - if (log_console) { + if (log_to_console) { format_log_message(module, level, VLF_CONSOLE, msg_num, message, args, &s); ds_put_char(&s, '\n'); fputs(ds_cstr(&s), stderr); } - if (log_syslog) { + if (log_to_syslog) { int syslog_level = syslog_levels[level]; char *save_ptr = NULL; char *line; @@ -520,6 +594,14 @@ vlog_valist(enum vlog_module module, enum vlog_level level, } } + if (log_to_file) { + format_log_message(module, level, VLF_FILE, msg_num, + message, args, &s); + ds_put_char(&s, '\n'); + fputs(ds_cstr(&s), log_file); + fflush(log_file); + } + ds_destroy(&s); errno = save_errno; } @@ -578,3 +660,14 @@ vlog_rate_limit(enum vlog_module module, enum vlog_level level, rl->n_dropped = 0; } } + +void +vlog_usage(void) +{ + printf("\nLogging options:\n" + " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" + " -v, --verbose set maximum verbosity level\n" + " --log-file[=FILE] enable logging to specified FILE\n" + " (default: %s/%s.log)\n", + ofp_logdir, program_name); +} diff --git a/secchan/secchan.c b/secchan/secchan.c index 8311d13c..37f109ad 100644 --- a/secchan/secchan.c +++ b/secchan/secchan.c @@ -2514,7 +2514,8 @@ parse_options(int argc, char *argv[], struct settings *s) OPT_STP, OPT_NO_STP, OPT_OUT_OF_BAND, - OPT_IN_BAND + OPT_IN_BAND, + VLOG_OPTION_ENUMS }; static struct option long_options[] = { {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN}, @@ -2535,6 +2536,7 @@ parse_options(int argc, char *argv[], struct settings *s) {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, DAEMON_LONG_OPTIONS, + VLOG_LONG_OPTIONS, #ifdef HAVE_OPENSSL VCONN_SSL_LONG_OPTIONS {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT}, @@ -2670,12 +2672,10 @@ parse_options(int argc, char *argv[], struct settings *s) printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]); exit(EXIT_SUCCESS); - case 'v': - vlog_set_verbosity(optarg); - break; - DAEMON_OPTION_HANDLERS + VLOG_OPTION_HANDLERS + #ifdef HAVE_OPENSSL VCONN_SSL_OPTION_HANDLERS @@ -2770,9 +2770,8 @@ usage(void) " --rate-limit[=PACKETS] max rate, in packets/s (default: 1000)\n" " --burst-limit=BURST limit on packet credit for idle time\n"); daemon_usage(); + vlog_usage(); printf("\nOther options:\n" - " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" - " -v, --verbose set maximum verbosity level\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); diff --git a/switch/switch.c b/switch/switch.c index e24ea671..84ed8de4 100644 --- a/switch/switch.c +++ b/switch/switch.c @@ -299,9 +299,8 @@ usage(void) " -l, --listen=METHOD allow management connections on METHOD\n" " (a passive OpenFlow connection method)\n"); daemon_usage(); + vlog_usage(); printf("\nOther options:\n" - " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" - " -v, --verbose set maximum verbosity level\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); diff --git a/tests/test-dhcp-client.c b/tests/test-dhcp-client.c index 0a7c1a1f..039ffed8 100644 --- a/tests/test-dhcp-client.c +++ b/tests/test-dhcp-client.c @@ -194,13 +194,12 @@ usage(void) " do not request a specific IP)\n" " --vendor-class=STRING use STRING as vendor class (default:\n" " none); use OpenFlow to imitate secchan\n" - " --no-resolv-conf do not update /etc/resolv.conf\n" - "\nOther options:\n" - " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" - " -v, --verbose set maximum verbosity level\n" - " -h, --help display this help message\n" - " -V, --version display version information\n", + " --no-resolv-conf do not update /etc/resolv.conf\n", program_name, program_name); + vlog_usage(); + printf("\nOther options:\n" + " -h, --help display this help message\n" + " -V, --version display version information\n"); exit(EXIT_SUCCESS); } diff --git a/utilities/dpctl.c b/utilities/dpctl.c index 40f985a2..23b9db4f 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -238,11 +238,10 @@ usage(void) "where each SWITCH is an active OpenFlow connection method.\n", program_name, program_name); vconn_usage(true, false, false); - printf("\nOptions:\n" + vlog_usage(); + printf("\nOther options:\n" " --strict use strict match for flow commands\n" " -t, --timeout=SECS give up after SECS seconds\n" - " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" - " -v, --verbose set maximum verbosity level\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); diff --git a/utilities/ofp-discover.c b/utilities/ofp-discover.c index d48f61ab..402d5897 100644 --- a/utilities/ofp-discover.c +++ b/utilities/ofp-discover.c @@ -405,15 +405,15 @@ usage(void) " --accept-vconn=REGEX accept matching discovered controllers\n" " --exit-without-bind exit after discovery, without binding\n" " --exit-after-bind exit after discovery, after binding\n" - " --no-detach do not detach after discovery\n" - "\nOther options:\n" + " --no-detach do not detach after discovery\n", + program_name, program_name); + vlog_usage(); + printf("\nOther options:\n" " -t, --timeout=SECS give up discovery after SECS seconds\n" " -P, --pidfile[=FILE] create pidfile (default: %s/%s.pid)\n" " -f, --force with -P, start even if already running\n" - " -v, --verbose=MODULE[:FACILITY[:LEVEL]] set logging levels\n" - " -v, --verbose set maximum verbosity level\n" " -h, --help display this help message\n" " -V, --version display version information\n", - program_name, program_name, ofp_rundir, program_name); + ofp_rundir, program_name); exit(EXIT_SUCCESS); } diff --git a/utilities/ofp-kill.c b/utilities/ofp-kill.c index 4518ad7d..a1c1e84e 100644 --- a/utilities/ofp-kill.c +++ b/utilities/ofp-kill.c @@ -43,6 +43,7 @@ #include "daemon.h" #include "timeval.h" #include "util.h" +#include "vlog.h" /* -s, --signal: signal to send. */ static int sig_nr = SIGTERM; @@ -51,7 +52,6 @@ static int sig_nr = SIGTERM; static bool force; static void cond_error(int err_no, const char *, ...) PRINTF_FORMAT(2, 3); -static bool kill_pidfile(const char *pidfile, FILE *); static void parse_options(int argc, char *argv[]); static void usage(void); @@ -64,6 +64,7 @@ main(int argc, char *argv[]) set_program_name(argv[0]); time_init(); + vlog_init(); parse_options(argc, argv); argc -= optind; @@ -77,16 +78,16 @@ main(int argc, char *argv[]) for (i = 0; i < argc; i++) { char *pidfile; - FILE *file; + pid_t pid; pidfile = make_pidfile_name(argv[i]); - file = fopen(pidfile, "r"); - if (!file) { - ok = false; - cond_error(errno, "%s: open", pidfile); + pid = read_pidfile(pidfile); + if (pid >= 0) { + if (kill(pid, sig_nr) < 0) { + cond_error(errno, "%s: kill(%ld)", pidfile, (long int) pid); + } } else { - ok = kill_pidfile(argv[i], file) && ok; - fclose(file); + cond_error(-pid, "could not read %s", pidfile); } free(pidfile); } @@ -94,40 +95,6 @@ main(int argc, char *argv[]) return ok || force ? EXIT_SUCCESS : EXIT_FAILURE; } -static bool -kill_pidfile(const char *pidfile, FILE *file) -{ - char line[128]; - struct flock lck; - - lck.l_type = F_WRLCK; - lck.l_whence = SEEK_SET; - lck.l_start = 0; - lck.l_len = 0; - if (fcntl(fileno(file), F_GETLK, &lck)) { - cond_error(errno, "%s: fcntl", pidfile); - return false; - } - - if (!fgets(line, sizeof line, file)) { - cond_error(errno, "%s: read", pidfile); - return false; - } - - if (lck.l_pid != strtoul(line, NULL, 10)) { - cond_error(errno, "l_pid (%ld) != %s pid (%s)", - (long int) lck.l_pid, pidfile, line); - return false; - } - - if (kill(lck.l_pid, sig_nr) < 0) { - cond_error(errno, "%s: kill(%ld)", pidfile, (long int) lck.l_pid); - return false; - } - - return true; -} - static void parse_options(int argc, char *argv[]) { diff --git a/utilities/vlogconf.c b/utilities/vlogconf.c index 006344ba..6da0c171 100644 --- a/utilities/vlogconf.c +++ b/utilities/vlogconf.c @@ -53,15 +53,17 @@ usage(char *prog_name, int exit_code) printf("Usage: %s [TARGET] [ACTION...]\n" "Targets:\n" " -a, --all Apply to all targets (default)\n" - " -t, --target=TARGET Specify target program, as a pid or an\n" - " absolute path to a Unix domain socket\n" + " -t, --target=TARGET Specify target program, as a pid, a\n" + " pidfile, or an absolute path to a Unix\n" + " domain socket\n" "Actions:\n" " -l, --list List current settings\n" " -s, --set=MODULE[:FACILITY[:LEVEL]]\n" " Set MODULE and FACILITY log level to LEVEL\n" " MODULE may be any valid module name or 'ANY'\n" - " FACILITY may be 'syslog' or 'console' or 'ANY' (default)\n" - " LEVEL may be 'emer', 'err', 'warn', or 'dbg (default)'\n" + " FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n" + " LEVEL may be 'emer', 'err', 'warn', or 'dbg' (default)\n" + " -r, --reopen Make the program reopen its log file\n" " -h, --help Print this helpful information\n", prog_name); exit(exit_code); @@ -147,6 +149,7 @@ int main(int argc, char *argv[]) /* Action options come afterward. */ {"list", no_argument, NULL, 'l'}, {"set", required_argument, NULL, 's'}, + {"reopen", no_argument, NULL, 'r'}, {0, 0, 0, 0}, }; char *short_options; @@ -204,6 +207,15 @@ int main(int argc, char *argv[]) } break; + case 'r': + for (i = 0; i < n_clients; i++) { + struct vlog_client *client = clients[i]; + char *request = xasprintf("reopen"); + transact_ack(client, request, &ok); + free(request); + } + break; + case 'h': usage(argv[0], EXIT_SUCCESS); break;