#undef LOCAL_DEBUG
-#include "ucw/lib.h"
-#include "ucw/log.h"
-#include "ucw/mainloop.h"
-#include "ucw/clists.h"
-#include "ucw/getopt.h"
-#include "ucw/conf.h"
+#include <ucw/lib.h>
+#include <ucw/log.h>
+#include <ucw/mainloop.h>
+#include <ucw/clists.h>
+#include <ucw/getopt.h>
+#include <ucw/conf.h>
+#include <ucw/process.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
-uns max_line = 1024;
+static uns max_line = 1024;
+static int launch_finish_messages = 1;
+static int nonzero_status_message = 1;
static struct cf_section cfsec_logoutput = {
CF_ITEMS {
- CF_UNS("linemax", &max_line),
+ CF_UNS("LineMax", &max_line),
CF_END
}
};
-
static clist filedescriptors;
struct fds {
}
*eol = 0;
byte *b = r->read_rec_start;
- while (eol - b > max_line) {
+ while ((uns)(eol - b) > max_line) {
char cc = b[max_line];
b[max_line]=0;
do_msg(r->data, b, 1);
if (flags < 0)
die("fcntl(..., F_GETFD, ...) : %m");
flags = (value) ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC;
- if(fcntl(fd, F_SETFD, flags) < 0)
+ if (fcntl(fd, F_SETFD, flags) < 0)
die("fcntl(..., F_SETFD, ...) : %m");
}
{ "logfile", 1, 0, 'f'},
{ "logname", 1, 0, 'n'},
{ "descriptor", 1, 0, 'l'},
+ { "nv", 0, 0, 'q'},
+ { "nonverbose", 0, 0, 'q'},
+ { "non-verbose", 0, 0, 'q'},
+ { "non_verbose", 0, 0, 'q'},
+ { "silent", 0, 0, 's'},
{ NULL, 0, 0, 0}
};
#undef CF_USAGE_TAB
-#define CF_USAGE_TAB "\t\t"
+#define CF_USAGE_TAB "\t "
static char usage[] =
"Usage:\n"
- "logoutput -h|--help\t\tThis help.\n"
- "logoutput <options> -i|--input\tRead filedescriptors and log them.\n"
- "\t\t\t\tdefault: stdin at level I.\n"
+ "logoutput -h|--help\t\t This help.\n"
+ "logoutput <options> -i|--input\t Read file descriptors and log them.\n"
+ "\t\t\t\t default: stdin at level I.\n"
"logoutput <opts> [--] <cmd> [arguments for cmd ...]\n"
- "\t\t\t\tOpen filedescriptors for writing for\n"
- "\t\t\t\tcommand <cmd> and log them.\n"
- "\t\t\t\tdefault: stdout:I, stderr:W.\n"
+ "\t\t\t\t Open file descriptors for writing for command <cmd> and log them.\n"
+ "\t\t\t\t default: stdout:I, stderr:W.\n\n"
"Options:\n"
CF_USAGE
- "-n, --logname <name>\t\t\tUse <name> as program name in logs.\n"
- "-l, --descriptor <fdnum>:<level>\tOpen filedescriptor <fdnum> and log it\n"
- "\t\t\t\t\tat level <level> (discards defaults).\n"
- "-f, --logfile <logfile>\t\t\tLog to file <logfile>.\n";
+ "-n, --logname <name>\t\t Use <name> as program name in logs.\n"
+ "-l, --descriptor <fdnum>:<level> Open file descriptor <fdnum> and log it at level <level> (replaces defaults).\n"
+ "-f, --logfile <logfile>\t\t Log to file <logfile>.\n"
+ "-q, --nv, --nonverbose\t\t Suppress launching and successful finish messages.\n"
+ "-s, --silent\t\t\t Suppress launching message and all finish messages.\n"
+ "\t\t\t\t (i.e., no warning if it terminates with a nonzero exit code or by a signal)\n";
int
main(int argc, char **argv)
struct fds *stderrfd = NULL;
int help = 0;
-
log_init("logoutput");
clist_init(&filedescriptors);
cf_declare_section("LogOutput", &cfsec_logoutput, 0);
}
break;
+ case 's':
+ nonzero_status_message = 0;
+ /* fallthrough */
+ case 'q':
+ launch_finish_messages = 0;
+ break;
+
default:
optind--;
goto opt_done;
}
}
if (help) {
- write(2,usage,sizeof(usage));
+ write(2, usage, sizeof(usage));
return (help == 1) ? 0 : 1;
}
if (loginput) {
/* Just check, that we don't want open stderr for reading. */
- CLIST_FOR_EACH(struct fds*, fd, filedescriptors) {
+ CLIST_FOR_EACH(struct fds *, fd, filedescriptors) {
if (fd->fdnum == 2)
die("Stderr is reserved for output");
}
} else {
/* Open all filedescriptors and their duplicates. */
- CLIST_FOR_EACH(struct fds*, fd, filedescriptors) {
- CLIST_FOR_EACH(struct fds*, fdcheck, filedescriptors) {
+ CLIST_FOR_EACH(struct fds *, fd, filedescriptors) {
+ CLIST_FOR_EACH(struct fds *, fdcheck, filedescriptors) {
/* We do a dummy check for collisions of filedescriptors. */
if (fdcheck == fd)
break;
DBG("---> [%i, %i] for %i", fd->pipe[0], fd->pipe[1], fd->fdnum);
set_cloexec_flag(fd->pipe[0], 1);
set_cloexec_flag(fd->pipe[1], 0);
- /* Our pipe is created, let fd->fdnum be the reading end. */
- fd->fdnum = fd->pipe[0];
}
}
/* Initialize main loop. */
main_init();
- CLIST_FOR_EACH(struct fds*, fd, filedescriptors) {
+ CLIST_FOR_EACH(struct fds *, fd, filedescriptors) {
+ /* Our pipe is created, let fd->fdnum be the reading end. */
+ if (!loginput)
+ fd->fdnum = fd->pipe[0];
fd->rio.read_rec_max = max_line + 1;
rec_io_add(&fd->rio, fd->fdnum);
}
}
/* Close writing filedescriptors. */
- CLIST_FOR_EACH(struct fds*, fd, filedescriptors) {
+ CLIST_FOR_EACH(struct fds *, fd, filedescriptors) {
close(fd->pipe[1]);
}
}
}
buf2[-1] = 0;
- msg(L_INFO, "Launching command: %s", buf);
+ if (launch_finish_messages)
+ msg(L_INFO, "Launching command: %s", buf);
}
/* Set logname. */
- if(logname)
+ if (logname)
log_init(logname);
else if (!loginput)
log_init(argv[optind]);
/* Start reading from pipes. */
- CLIST_FOR_EACH(struct fds*, fd, filedescriptors) {
+ CLIST_FOR_EACH(struct fds *, fd, filedescriptors)
rec_io_start_read(&fd->rio);
- }
main_loop();
if (!loginput) {
}
if (format_exit_status(buf, status)) {
- msg(L_WARN,"Child %s", buf);
+ if (nonzero_status_message)
+ msg(L_WARN, "Child %s", buf);
return WIFEXITED(status) ? WEXITSTATUS(status) : 127;
} else {
- msg(L_INFO,"Child terminated successfully.");
+ if (launch_finish_messages)
+ msg(L_INFO, "Child terminated successfully.");
return 0;
}
}
+
+ return 0;
}