summaryrefslogtreecommitdiff
path: root/usr/src/cmd/logadm/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/logadm/main.c')
-rw-r--r--usr/src/cmd/logadm/main.c80
1 files changed, 52 insertions, 28 deletions
diff --git a/usr/src/cmd/logadm/main.c b/usr/src/cmd/logadm/main.c
index 93a54a60ed..624397d41f 100644
--- a/usr/src/cmd/logadm/main.c
+++ b/usr/src/cmd/logadm/main.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
*
* logadm/main.c -- main routines for logadm
*
@@ -41,6 +41,8 @@
#include <sys/sysmacros.h>
#include <time.h>
#include <utime.h>
+#include <poll.h>
+#include <errno.h>
#include "err.h"
#include "lut.h"
#include "fn.h"
@@ -831,7 +833,7 @@ rotateto(struct fn *fnp, struct opts *opts, int n, struct fn *recentlog,
fn_free(dirname);
/* do the rename */
- if (n == 0 && opts_count(opts, "c") != NULL) {
+ if (n == 0 && opts_count(opts, "c") != 0) {
docopytruncate(opts, fn_s(fnp), fn_s(newfile));
} else if (n == 0 && opts_count(opts, "M")) {
struct fn *rawcmd = fn_new(opts_optarg(opts, "M"));
@@ -1030,16 +1032,11 @@ docmd(struct opts *opts, const char *msg, const char *cmd,
return; /* -n means don't really do it */
/*
- * run the cmd and see if it failed. this function is *not* a
- * generic command runner -- we depend on some knowledge we
- * have about the commands we run. first of all, we expect
- * errors to spew something to stderr, and that something is
- * typically short enough to fit into a pipe so we can wait()
- * for the command to complete and then fetch the error text
- * from the pipe. we also expect the exit codes to make sense.
- * notice also that we only allow a command name which is an
- * absolute pathname, and two args must be supplied (the
- * second may be NULL, or they may both be NULL).
+ * Run the cmd and see if it failed. This function is *not* a generic
+ * command runner. The command name must be an absolute pathname, and
+ * two args must be supplied (the second may be NULL, or they may both
+ * be NULL). Any output (stdout and stderr) from the child process is
+ * logged to stderr and perhaps sent to an email recipient.
*/
if (pipe(errpipe) < 0)
err(EF_SYS, "pipe");
@@ -1048,25 +1045,51 @@ docmd(struct opts *opts, const char *msg, const char *cmd,
err(EF_SYS, "fork");
else if (pid) {
int wstat;
- int count;
+ struct pollfd pfd;
+ boolean_t first = B_TRUE;
/* parent */
(void) close(errpipe[1]);
- if (waitpid(pid, &wstat, 0) < 0)
+
+ pfd.fd = errpipe[0];
+ pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
+ for (;;) {
+
+ pfd.revents = 0;
+ if (poll(&pfd, 1, -1) == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ err(EF_SYS, "poll");
+ break;
+ }
+ if ((pfd.events & pfd.revents) != 0) {
+ if (first) {
+ err(EF_WARN,
+ "command failed: %s%s%s%s%s%s%s",
+ cmd,
+ (arg1) ? " " : "",
+ (arg1) ? arg1 : "",
+ (arg2) ? " " : "",
+ (arg2) ? arg2 : "",
+ (arg3) ? " " : "",
+ (arg3) ? arg3 : "");
+ first = B_FALSE;
+ }
+ err_fromfd(pfd.fd);
+ }
+ if ((pfd.revents & (POLLERR | POLLHUP)) != 0) {
+ break;
+ }
+ }
+ if (waitpid(pid, &wstat, 0) < 0) {
err(EF_SYS, "waitpid");
+ return;
+ }
- /* check for stderr output */
- if (ioctl(errpipe[0], FIONREAD, &count) >= 0 && count) {
- err(EF_WARN, "command failed: %s%s%s%s%s%s%s",
- cmd,
- (arg1) ? " " : "",
- (arg1) ? arg1 : "",
- (arg2) ? " " : "",
- (arg2) ? arg2 : "",
- (arg3) ? " " : "",
- (arg3) ? arg3 : "");
- err_fromfd(errpipe[0]);
- } else if (WIFSIGNALED(wstat))
+ if (!first) {
+ /* Assume the command gave a useful error */
+ } else if (WIFSIGNALED(wstat)) {
err(EF_WARN,
"command died, signal %d: %s%s%s%s%s%s%s",
WTERMSIG(wstat),
@@ -1077,7 +1100,7 @@ docmd(struct opts *opts, const char *msg, const char *cmd,
(arg2) ? arg2 : "",
(arg3) ? " " : "",
(arg3) ? arg3 : "");
- else if (WIFEXITED(wstat) && WEXITSTATUS(wstat))
+ } else if (WIFEXITED(wstat) && WEXITSTATUS(wstat)) {
err(EF_WARN,
"command error, exit %d: %s%s%s%s%s%s%s",
WEXITSTATUS(wstat),
@@ -1088,6 +1111,7 @@ docmd(struct opts *opts, const char *msg, const char *cmd,
(arg2) ? arg2 : "",
(arg3) ? " " : "",
(arg3) ? arg3 : "");
+ }
(void) close(errpipe[0]);
} else {
@@ -1112,7 +1136,7 @@ docopytruncate(struct opts *opts, const char *file, const char *file_copy)
ssize_t len;
/* print info if necessary */
- if (opts_count(opts, "vn") != NULL) {
+ if (opts_count(opts, "vn") != 0) {
(void) out("# log rotation via atomic copy and truncation"
" (-c flag):\n");
(void) out("# copy %s to %s\n", file, file_copy);