commit b633c0e3d484184d56c3ab17e2d3bbf1279f9a1e
parent 9b282e5c956ab9511bc07f129c4e32b0345752cc
Author: Gerrit Pape <pape@smarden.org>
Date: Mon, 20 Sep 2004 19:53:10 +0000
* svlogd.c: fix line buffer handling for pattern matching (thx Enrico
Scholz); minor bug fixes.
* doc/index.html: wording; add link to useinit.html; remove link to runit
on LinuxFromScratch.
* doc/runscripts.html: add hint, some getties need to be run in a new
session/process group (thx Dan Melomedman).
* man/svlogd.8: minor fixes.
* man/svwaitdown.8: remove hint about -x option.
Diffstat:
8 files changed, 286 insertions(+), 284 deletions(-)
diff --git a/doc/index.html b/doc/index.html
@@ -78,23 +78,23 @@ if this is started by the kernel.
terminate.
The system's one time initialization tasks are done here.
<tt>/etc/runit/1</tt> has full control over <tt>/dev/console</tt> to be
- able to start an emergency shell if the one time initialization tasks
- fail.
+ able to start an emergency shell in case the one time initialization
+ tasks fail.
<li><b>Stage 2:</b><br>
<i>runit</i> starts <tt>/etc/runit/2</tt> which should not return
until the system is going to halt or reboot; if it crashes, it will be
restarted.
Normally, <tt>/etc/runit/2</tt> runs
<a href="runsvdir.8.html">runsvdir</a>.
- In Stage 2 <i>runit</i> optionally handles an INT signal (ctrl-alt-del
+ In Stage 2 <i>runit</i> optionally handles the INT signal (ctrl-alt-del
keyboard request on Linux/i386).
<li><b>Stage 3:</b><br>
- If <i>runit</i> is told to halt or reboot the system, or the Stage 2
- returns without errors, it terminates Stage 2 if it is running and runs
+ If <i>runit</i> is told to halt or reboot the system, or Stage 2 returns
+ without errors, it terminates Stage 2 if it is running, and runs
<tt>/etc/runit/3</tt>.
The systems tasks to shutdown and halt or reboot are done here.
</ul>
-These are working examples for Debian woody:
+These are working examples for Debian sarge:
<a href="debian/1">/etc/runit/1</a>,
<a href="debian/2">/etc/runit/2</a>,
<a href="debian/3">/etc/runit/3</a>.
@@ -185,6 +185,8 @@ Of course also the <tt>smarden.org</tt> content server is running with
See <a href="install.html">How to install runit</a> for installing
<i>runit</i>, and <a href="replaceinit.html">How to replace init</a> for
configuring <i>runit</i> to run as process no 1.
+See <a href="useinit.html">How to use with current init</a> if you want to
+use <i>runit</i> without replacing the current init scheme.
<hr>
If <i>runit</i> on Linux is compiled and linked with the
<a href="http://www.fefe.de/dietlibc/">dietlibc</a>, it yields in a
@@ -208,8 +210,6 @@ runit Debian package</a>
runit-run Debian package</a>
<li><a href="http://www.freshports.org/sysutils/runit/">
runit FreeBSD port</a>
-<li><a href="http://www.109bean.org.uk/betterboot/index.html">
-runit on LinuxFromScratch</a> - by Richard A Downing FBCS
<li><a href="http://rpmfind.net/linux/rpm2html/search.php?query=runit">
runit RPMs</a>
<li><a href="http://www.fefe.de/minit/">
diff --git a/doc/runscripts.html b/doc/runscripts.html
@@ -339,6 +339,11 @@ Debian's <tt>mingetty</tt> creates its own utmp record.
#!/bin/sh
exec chpst -P fgetty tty4
</pre>
+The <a href="runsv.8.html">runsv</a> program does not automatically create
+a new session and separate process group for run scripts, which can
+cause some <i>getties</i> to fail due to limited permissions.
+The <a href="chpst.8.html">chpst</a> program can be used to alter the
+process state for those <i>getties</i>.
<hr>
<h3><a name="gpm">A <tt>gpm</tt> run script</a></h3>
(<i>LFS</i>)
diff --git a/doc/svlogd.8.html b/doc/svlogd.8.html
@@ -12,7 +12,7 @@
svlogd - runit’s service logging daemon
<h2><a name='sect1'>Synopsis</a></h2>
<b>svlogd</b> [-ttv] [-r <i>c]</i> [-R
-<i>xyz]</i> [-l <i>n]</i> [-b <i>n]</i> <i>logs</i>
+<i>xyz]</i> [-l <i>len]</i> [-b <i>buflen]</i> <i>logs</i>
<h2><a name='sect2'>Description</a></h2>
<i>logs</i> consists of one or more arguments,
each specifying a directory. <p>
@@ -21,78 +21,78 @@ standard input, optionally filters log messages, and writes the data to
one or more automatically rotated <i>logs</i>. <p>
Recent log files can automatically
be processed by an arbitrary processor program when they are rotated, and
-<b>svlogd</b> can be told to alert selected log messages to standard error. <p>
-<b>svlogd</b>
-runs until it sees end-of-file on standard input or is sent a TERM signal,
-see below.
+<b>svlogd</b> can be told to alert selected log messages to standard error, and
+through udp. <p>
+<b>svlogd</b> runs until it sees end-of-file on standard input or is
+sent a TERM signal, see below.
<h3><a name='sect3'>Log Directory</a></h3>
-A log directory <i>log</i> contains some number of old
-log files, and the current log file <i>current</i>. Old log files have a file name
-starting with <i>@</i> followed by a precise timestamp (see <i><b>tai64n</b>(8)</i>), indicating
-when <i>current</i> was rotated and renamed to this file. <p>
-A log directory additionally
-contains the lock file <i>lock</i>, maybe <i>state</i> and <i>newstate</i>, and optionally the
-file <i>config</i>. <b>svlogd</b> creates necessary files if they don’t exist. <p>
-If <b>svlogd</b>
-has trouble opening a log directory, it prints a warning, and ignores this
-log directory. If <b>svlogd</b> is unable to open all log directories given at
-the command line, it exits with an error. This can happen on start-up or
-after receiving a HUP signal.
+A log directory <i>log</i> contains
+some number of old log files, and the current log file <i>current</i>. Old log
+files have a file name starting with <i>@</i> followed by a precise timestamp
+(see <i><b>tai64n</b>(8)</i>), indicating when <i>current</i> was rotated and renamed to this
+file. <p>
+A log directory additionally contains the lock file <i>lock</i>, maybe <i>state</i>
+and <i>newstate</i>, and optionally the file <i>config</i>. <b>svlogd</b> creates necessary files
+if they don’t exist. <p>
+If <b>svlogd</b> has trouble opening a log directory, it prints
+a warning, and ignores this log directory. If <b>svlogd</b> is unable to open all
+log directories given at the command line, it exits with an error. This
+can happen on start-up or after receiving a HUP signal.
<h3><a name='sect4'>Log File Rotation</a></h3>
-<b>svlogd</b> appends selected log
-messages to the <i>current</i> log file. If <i>current</i> has <i>size</i> bytes or more size
-(or there is a new-line within the last <i>len</i> of <i>size</i> bytes) <i>current</i> is rotated:
-<p>
-<b>svlogd</b> closes <i>current</i>, changes permission of <i>current</i> to 0755, renames <i>current</i>
-to @<i>timestamp.s,</i> and starts with a new empty <i>current</i>. If <b>svlogd</b> sees <i>num</i>
-or more old log files in <i>dir</i>, it removes the oldest.
+<b>svlogd</b>
+appends selected log messages to the <i>current</i> log file. If <i>current</i> has <i>size</i>
+bytes or more (or there is a new-line within the last <i>len</i> of <i>size</i> bytes)
+<i>current</i> is rotated: <p>
+<b>svlogd</b> closes <i>current</i>, changes permission of <i>current</i>
+to 0755, renames <i>current</i> to @<i>timestamp.s,</i> and starts with a new empty <i>current</i>.
+If <b>svlogd</b> sees <i>num</i> or more old log files in <i>dir</i>, it removes the oldest
+one.
<h3><a name='sect5'>Processor</a></h3>
-If <b>svlogd</b>
-is told to process recent log files, it saves <i>current</i> to @<i>timestamp.u,</i> feeds
-@<i>timestamp.u</i> through ‘‘sh -c "<i>processor</i>"’’ and writes the output to @<i>timestamp.t.</i>
-If the <i>processor</i> finishes successfully, @<i>timestamp.u</i> is deleted and @<i>timestamp.t</i>
-is renamed to @<i>timestamp.s,</i> otherwise @<i>timestamp.t</i> is deleted and the <i>processor</i>
-is started again. <b>svlogd</b> also saves any output that the <i>processor</i> writes
-to file descriptor 5, and make that output available on file descriptor
-4 when it runs <i>processor</i> on the next log file rotation. <p>
-A <i>processor</i> is run
-in the background. If <b>svlogd</b> sees a previously started <i>processor</i> still running
-when trying to start a new one for the same <i>log</i>, it blocks until the currently
-running <i>processor</i> has finished successfully. Only the HUP signal works in
-that situation. Note that this may block any program feeding its log data
-to <b>svlogd.</b>
+If <b>svlogd</b> is told to process recent log files, it saves <i>current</i>
+to @<i>timestamp.u,</i> feeds @<i>timestamp.u</i> through ‘‘sh -c "<i>processor</i>"’’ and writes the
+output to @<i>timestamp.t.</i> If the <i>processor</i> finishes successfully, @<i>timestamp.u</i>
+is deleted and @<i>timestamp.t</i> is renamed to @<i>timestamp.s,</i> otherwise @<i>timestamp.t</i>
+is deleted and the <i>processor</i> is started again. <b>svlogd</b> also saves any output
+that the <i>processor</i> writes to file descriptor 5, and makes that output available
+on file descriptor 4 when running <i>processor</i> on the next log file rotation.
+<p>
+A <i>processor</i> is run in the background. If <b>svlogd</b> sees a previously started
+<i>processor</i> still running when trying to start a new one for the same <i>log</i>,
+it blocks until the currently running <i>processor</i> has finished successfully.
+Only the HUP signal works in that situation. Note that this may block any
+program feeding its log data to <b>svlogd.</b>
<p>
<h3><a name='sect6'>Config</a></h3>
-On startup, and after receiving a HUP signal, <b>svlogd</b> checks
-for each <i>log</i> if the configuration file <i>log/config</i> exists, and if so, reads
-the file line by line and adjusts configuration for <i>log</i> as follows: <p>
-If
-the line is empty, less than two characters long, or starts with a ‘‘#’’, it
-is ignored. A line of the form
+On startup, and after receiving
+a HUP signal, <b>svlogd</b> checks for each <i>log</i> if the configuration file <i>log/config</i>
+exists, and if so, reads the file line by line and adjusts configuration
+for <i>log</i> as follows: <p>
+If the line is empty, less than two characters long,
+or starts with a ‘‘#’’, it is ignored. A line of the form
<dl>
<dt>s<i>size</i> </dt>
-<dd>sets the maximum file size of <i>current</i>
-when <b>svlogd</b> should rotate the current log file to <i>size</i> bytes. Default is
-1000000. If <i>size</i> is zero, <b>svlogd</b> doesn’t rotate log files. You should set
-<i>size</i> to at least (2 * <i>len</i>). </dd>
+<dd>sets the maximum
+file size of <i>current</i> when <b>svlogd</b> should rotate the current log file to
+<i>size</i> bytes. Default is 1000000. If <i>size</i> is zero, <b>svlogd</b> doesn’t rotate log
+files. You should set <i>size</i> to at least (2 * <i>len</i>). </dd>
<dt>n<i>num</i> </dt>
-<dd>sets the maximum number of old log files
-<b>svlogd</b> should maintain to <i>num</i>. If <b>svlogd</b> sees more that <i>num</i> old log files
-in <i>log</i> after log file rotation, it deletes the oldest one. Default is 10.
-</dd>
+<dd>sets the maximum number
+of old log files <b>svlogd</b> should maintain to <i>num</i>. If <b>svlogd</b> sees more that
+<i>num</i> old log files in <i>log</i> after log file rotation, it deletes the oldest
+one. Default is 10. </dd>
<dt>!<i>processor</i> </dt>
-<dd>tells <b>svlogd</b> to feed each recent log file through <i>processor</i>
-(see above) on log file rotation. By default log files are not processed.
-</dd>
+<dd>tells <b>svlogd</b> to feed each recent log file
+through <i>processor</i> (see above) on log file rotation. By default log files
+are not processed. </dd>
<dt>u<i>a.b.c.d[:port]</i> </dt>
-<dd>tells <b>svlogd</b> to transmit the first <i>len</i> characters of selected
-log messages to the IP address <i>a.b.c.d</i>, port number <i>port</i>. If <i>port</i> isn’t set,
-the default port for syslog is used (514). <i>len</i> can be set through the -l
-option, see below. If <b>svlogd</b> has trouble sending udp packets, it writes
+<dd>tells <b>svlogd</b> to transmit the first <i>len</i> characters
+of selected log messages to the IP address <i>a.b.c.d</i>, port number <i>port</i>. If <i>port</i>
+isn’t set, the default port for syslog is used (514). <i>len</i> can be set through
+the -l option, see below. If <b>svlogd</b> has trouble sending udp packets, it writes
error messages to the log directory. Attention: logging through udp is unreliable,
and should be used in private networks only. </dd>
diff --git a/doc/svwaitdown.8.html b/doc/svwaitdown.8.html
@@ -43,25 +43,23 @@ signal. </dd>
<dt><b>-x</b> </dt>
<dd>Exit. Send each <i>service</i> the ‘‘exit’’ command additionally to the ‘‘down’’
command, and wait for the corresponding <i><b>runsv</b>(8)</i> processes to exit instead
-for the <i>services</i> to be down. This option should only be used by <i><b>runit</b>(8)</i>
-in stage 3 when <i><b>runsvdir</b>(8)</i> is already stopped. </dd>
+for the <i>services</i> to be down. </dd>
</dl>
<h2><a name='sect4'>Exit Codes</a></h2>
-<b>svwaitdown</b> returns
-0 as soon as all <i>services</i> are down. <p>
-If a <i>service</i> is usually controlled by
-<i><b>runsv (8)</b></i> or <i><b>supervise</b>(8)</i>, but no supervisor process is currently running,
-<b>svwaitdown</b> treats this <i>service</i> as if it would be down. <p>
-For each <i>service</i>
-that causes an error while checking, <b>svwaitdown</b> increases the exit code
-by one and exits non zero. The maximum is 100. <p>
-<b>svwaitdown</b> returns 111 if
-the timeout <i>sec</i> was reached.
+<b>svwaitdown</b> returns 0 as soon as all
+<i>services</i> are down. <p>
+If a <i>service</i> is usually controlled by <i><b>runsv (8)</b></i> or <i><b>supervise</b>(8)</i>,
+but no supervisor process is currently running, <b>svwaitdown</b> treats this
+<i>service</i> as if it would be down. <p>
+For each <i>service</i> that causes an error while
+checking, <b>svwaitdown</b> increases the exit code by one and exits non zero.
+The maximum is 100. <p>
+<b>svwaitdown</b> returns 111 if the timeout <i>sec</i> was reached.
+
<h2><a name='sect5'>See Also</a></h2>
-<i>svwaitup(8)</i>, <i>runsv(8)</i>, <i>runsvctrl(8)</i>,
-<i>runsvstat(8)</i>, <i>chpst(8)</i>, <i>svlogd(8)</i>, <i>runit(8)</i>, <i>runit-init(8)</i>, <i>runsvdir(8)</i>,
-<i>runsvchdir(8)</i>, <i>utmpset(8)</i> <p>
+<i>svwaitup(8)</i>, <i>runsv(8)</i>, <i>runsvctrl(8)</i>, <i>runsvstat(8)</i>, <i>chpst(8)</i>, <i>svlogd(8)</i>,
+<i>runit(8)</i>, <i>runit-init(8)</i>, <i>runsvdir(8)</i>, <i>runsvchdir(8)</i>, <i>utmpset(8)</i> <p>
<i>http://smarden.org/runit/</i><br>
<i>http://cr.yp.to/daemontools.html</i><br>
diff --git a/man/svlogd.8 b/man/svlogd.8
@@ -6,8 +6,8 @@ svlogd \- runit's service logging daemon
[\-ttv] [\-r
.I c\fR] [\-R
.I xyz\fR] [\-l
-.I n\fR] [\-b
-.I n\fR]
+.I len\fR] [\-b
+.I buflen\fR]
.I logs
.SH DESCRIPTION
.I logs
@@ -21,7 +21,8 @@ messages, and writes the data to one or more automatically rotated
Recent log files can automatically be processed by an arbitrary processor
program when they are rotated, and
.B svlogd
-can be told to alert selected log messages to standard error.
+can be told to alert selected log messages to standard error, and through
+udp.
.P
.B svlogd
runs until it sees end-of-file on standard input or is sent a TERM signal,
@@ -68,7 +69,7 @@ If
.I current
has
.I size
-bytes or more size (or there is a new-line within the last
+bytes or more (or there is a new-line within the last
.I len
of
.I size
@@ -93,7 +94,7 @@ sees
.I num
or more old log files in
.IR dir ,
-it removes the oldest.
+it removes the oldest one.
.SS PROCESSOR
If
.B svlogd
@@ -122,8 +123,8 @@ is started again.
.B svlogd
also saves any output that the
.I processor
-writes to file descriptor 5, and make that output available on file
-descriptor 4 when it runs
+writes to file descriptor 5, and makes that output available on file
+descriptor 4 when running
.I processor
on the next log file rotation.
.P
diff --git a/man/svwaitdown.8 b/man/svwaitdown.8
@@ -68,11 +68,6 @@ corresponding
processes to exit instead for the
.I services
to be down.
-This option should only be used by
-.BR runit (8)
-in stage 3 when
-.BR runsvdir (8)
-is already stopped.
.SH EXIT CODES
.B svwaitdown
returns 0 as soon as all
diff --git a/package/CHANGES b/package/CHANGES
@@ -1,3 +1,14 @@
+runit 1.0.5
+Mon, 20 Sep 2004 13:14:42 +0000
+ * svlogd.c: fix line buffer handling for pattern matching (thx Enrico
+ Scholz); minor bug fixes.
+ * doc/index.html: wording; add link to useinit.html; remove link to runit
+ on LinuxFromScratch.
+ * doc/runscripts.html: add hint, some getties need to be run in a new
+ session/process group (thx Dan Melomedman).
+ * man/svlogd.8: minor fixes.
+ * man/svwaitdown.8: remove hint about -x option.
+
runit 1.0.4
Sun, 01 Aug 2004 18:29:36 +0000
* doc/runlevels.html, doc/upgrade.html, doc/useinit.html, man/runsvdir.8,
diff --git a/src/svlogd.c b/src/svlogd.c
@@ -7,7 +7,6 @@
#include <sys/time.h>
#include <dirent.h>
#include <unistd.h>
-#include <dirent.h>
#include <stdio.h>
#include "pmatch.h"
#include "fmt_ptime.h"
@@ -45,8 +44,10 @@ const char *progname;
unsigned int verbose =0;
unsigned int timestamp =0;
-unsigned long linelen =1000;
+unsigned long linemax =1000;
unsigned long buflen =1024;
+unsigned long linelen;
+
const char *replace ="";
char repl =0;
@@ -62,6 +63,9 @@ buffer data;
char *line;
char stamp[FMT_PTIME];
unsigned int exitasap =0;
+unsigned int rotateasap =0;
+unsigned int reopenasap =0;
+unsigned int linecomplete =1;
int fdudp =-1;
struct logdir {
@@ -78,7 +82,7 @@ struct logdir {
char *name;
int fdcur;
int fdlock;
- unsigned int match;
+ char match;
struct sockaddr_in udpaddr;
unsigned int udponly;
} *dir;
@@ -125,6 +129,8 @@ unsigned int processorstart(struct logdir *ld) {
sig_unblock(sig_alarm);
sig_unblock(sig_hangup);
+ if (verbose)
+ strerr_warn5(INFO, "processing: ", ld->name, "/", ld->fnsave, 0);
if ((fd =open_read(ld->fnsave)) == -1)
fatal2("unable to open input for processor", ld->name);
if (fd_move(0, fd) == -1)
@@ -160,7 +166,7 @@ unsigned int processorstart(struct logdir *ld) {
fatal2("unable to run processor", ld->name);
}
ld->ppid =pid;
- return(1);
+ return(1);
}
unsigned int processorstop(struct logdir *ld) {
char f[28];
@@ -172,14 +178,15 @@ unsigned int processorstop(struct logdir *ld) {
sig_block(sig_hangup);
ld->ppid =0;
}
+ if (ld->fddir == -1) return(1);
while (fchdir(ld->fddir) == -1)
pause2("unable to change directory, want processor", ld->name);
if (wait_exitcode(wstat) != 0) {
- warnx("processor crashed, restart", ld->name);
+ warnx("processor failed, restart", ld->name);
ld->fnsave[26] ='t';
unlink(ld->fnsave);
ld->fnsave[26] ='u';
- if (ld->processor.len) processorstart(ld);
+ processorstart(ld);
while (fchdir(fdwdir) == -1)
pause1("unable to change to initial working directory");
return(ld->processor.len ? 0 : 1);
@@ -195,6 +202,7 @@ unsigned int processorstop(struct logdir *ld) {
pause2("unable to set mode of processed", ld->name);
while (rename("newstate", "state") == -1)
pause2("unable to rename state", ld->name);
+ if (verbose) strerr_warn5(INFO, "processed: ", ld->name, "/", f, 0);
while (fchdir(fdwdir) == -1)
pause1("unable to change to initial working directory");
return(1);
@@ -207,6 +215,7 @@ unsigned int rotate(struct logdir *ld) {
char tmp[FMT_ULONG +1];
char oldest[FMT_PTIME];
+ if (ld->fddir == -1) return(0);
if (ld->size <= 0) return(1);
if (ld->ppid) while(! processorstop(ld));
@@ -245,11 +254,11 @@ unsigned int rotate(struct logdir *ld) {
ld->size =0;
while (fchmod(ld->fdcur, 0644) == -1)
pause2("unable to set mode of current", ld->name);
- buffer_init(&ld->b, buffer_unixwrite, ld->fdcur, ld->btmp, sizeof ld->btmp);
- oldest[0] ='A'; oldest[1] =oldest[27] =0; errno =0;
+ oldest[0] ='A'; oldest[1] =oldest[27] =0;
while (! (d =opendir(".")))
pause2("unable to open directory, want rotate", ld->name);
+ errno =0;
while ((f =readdir(d)))
if ((f->d_name[0] == '@') && (str_len(f->d_name) == 27)) {
++n;
@@ -264,14 +273,29 @@ unsigned int rotate(struct logdir *ld) {
warn2("unable to unlink oldest logfile", ld->name);
}
- if (ld->processor.len) {
- processorstart(ld);
- }
+ processorstart(ld);
while (fchdir(fdwdir) == -1)
pause1("unable to change to initial working directory");
return(1);
}
+int buffer_pwrite(int n, char *s, unsigned int len) {
+ int i;
+
+ if ((dir +n)->sizemax) {
+ if ((dir +n)->size >= (dir +n)->sizemax) rotate(dir +n);
+ if (len > ((dir +n)->sizemax -(dir +n)->size))
+ len =(dir +n)->sizemax -(dir +n)->size;
+ }
+ while ((i =write((dir +n)->fdcur, s, len)) == -1)
+ pause2("unable to write to current", (dir +n)->name);
+ (dir +n)->size +=i;
+ if ((dir +n)->sizemax)
+ if (s[i -1] == '\n')
+ if ((dir +n)->size >= ((dir +n)->sizemax -linemax)) rotate(dir +n);
+ return(i);
+}
+
void logdir_close(struct logdir *ld) {
if (ld->fddir == -1) return;
if (verbose) strerr_warn3(INFO, "close: ", ld->name, 0);
@@ -288,6 +312,7 @@ void logdir_close(struct logdir *ld) {
if (ld->fdlock == -1) return; /* impossible */
close(ld->fdlock);
ld->fdlock =-1;
+ while (! stralloc_copys(&ld->processor, "")) pause_nomem();
}
/* taken from libdjbdns */
@@ -335,7 +360,8 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
ld->sizemax =1000000;
ld->nmax =10;
ld->name =(char*)fn;
- ld->match =0;
+ ld->ppid =0;
+ ld->match ='+';
ld->udpaddr.sin_port =0;
ld->udponly =0;
while (! stralloc_copys(&ld->inst, "")) pause_nomem();
@@ -367,9 +393,6 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
break;
case 's':
scan_ulong(&sa.s[i +1], &ld->sizemax);
- /*
- if (ld->sizemax && (ld->sizemax < linelen)) ld->sizemax =2 *linelen;
- */
break;
case 'n':
scan_ulong(&sa.s[i +1], &ld->nmax);
@@ -421,6 +444,7 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
} while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent));
while (rename("current", ld->fnsave) == -1)
pause2("unable to rename current", ld->name);
+ i =-1;
}
else
ld->size =st.st_size;
@@ -438,7 +462,7 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
coe(ld->fdcur);
while (fchmod(ld->fdcur, 0644) == -1)
pause2("unable to set mode of current", ld->name);
- buffer_init(&ld->b, buffer_unixwrite, ld->fdcur, ld->btmp, sizeof ld->btmp);
+ buffer_init(&ld->b, buffer_pwrite, ld -dir, ld->btmp, buflen);
if (verbose) {
if (i == 0) strerr_warn4(INFO, "append: ", ld->name, "/current", 0);
@@ -461,121 +485,43 @@ void logdirs_reopen(void) {
if (! ok) fatalx("no functional log directories.");
}
-unsigned int linestart(struct logdir *ld, char *s, int len) {
+int buffer_pread(int fd, char *s, unsigned int len) {
int i;
- /* check inst, set match */
- ld->match ='+';
- if (ld->inst.len) {
- for (i =0; i < ld->inst.len; ++i) {
- switch(ld->inst.s[i]) {
- case '+':
- case '-':
- if (pmatch(&ld->inst.s[i +1], s, len))
- ld->match =ld->inst.s[i];
- break;
- case 'e':
- if (pmatch(&ld->inst.s[i +1], s, len)) {
- if (timestamp) buffer_puts(buffer_2, stamp);
- buffer_put(buffer_2, s, len);
- if (len == linelen) buffer_puts(buffer_2, "...");
- buffer_putflush(buffer_2, "\n", 1);
- }
- break;
- case 'E':
- if (! pmatch(&ld->inst.s[i +1], s, len)) {
- if (timestamp) buffer_puts(buffer_2, stamp);
- buffer_put(buffer_2, s, len);
- if (len == linelen) buffer_puts(buffer_2, "...");
- buffer_putflush(buffer_2, "\n", 1);
- }
- break;
- }
- i +=byte_chr(&ld->inst.s[i], ld->inst.len -i, 0);
- }
- }
- if (ld->match == '-') return(0);
- if (! ld->udponly) {
- if (timestamp) {
- buffer_puts(&ld->b, stamp);
- if (timestamp != 3) ld->size +=26;
- else ld->size +=20;
- }
- buffer_put(&ld->b, s, len);
- ld->size +=len;
- }
- if (ld->udpaddr.sin_port != 0) {
- if (fdudp == -1) {
- buffer_puts(&ld->b, "warning: no udp socket available: ");
- buffer_put(&ld->b, s, len);
- buffer_putflush(&ld->b, "\n", 1);
- }
- else {
- if (len >= linelen -1) {
- s[linelen -4] =s[linelen -3] =s[linelen -2] ='.';
- len =linelen -1;
- }
- if (s[len -1] != '\n') s[len++] ='\n';
- if (sendto(fdudp, s, len, 0, (struct sockaddr *)&ld->udpaddr,
- sizeof(ld->udpaddr)) != len) {
- buffer_puts(&ld->b, "warning: failure sending through udp: ");
- buffer_put(&ld->b, s, len);
- buffer_putflush(&ld->b, "\n", 1);
- }
- }
+ for (i =0; i < dirn; ++i) buffer_flush(&dir[i].b);
+ if (rotateasap) {
+ for (i =0; i < dirn; ++i) rotate(dir +i);
+ rotateasap =0;
}
- return(1);
-}
-unsigned int lineadd(struct logdir *ld, char *s, int len) {
- if ((ld->match != '+') || ld->udponly) return(0);
- buffer_put(&ld->b, s, len);
- ld->size +=len;
- /* if (ld->sizemax && (ld->size >= ld->sizemax)) rotate(ld); */
- return(1);
-}
-unsigned int lineflush(struct logdir *ld, char *s, int len) {
- switch(ld->match) {
- case '-':
- ld->match =0;
- return(0);
- case 0:
- linestart(ld, s, len);
- break;
- case '+':
- if (ld->udponly) {
- ld->match =0;
- return(0);
- }
- buffer_put(&ld->b, s, len);
- ld->size +=len;
- break;
+ if (exitasap) {
+ if (linecomplete) return(0);
+ len =1;
}
- if (ld->match == '+') {
- buffer_putflush(&ld->b, "\n", 1);
- ld->size +=1;
- ld->match =0;
- if (ld->sizemax)
- if ((linelen > ld->sizemax) || (ld->size >= (ld->sizemax -linelen)))
- rotate(ld);
- return(1);
+ if (reopenasap) {
+ logdirs_reopen();
+ reopenasap =0;
}
- ld->match =0;
- return(0);
-}
-int buffer_pread(int fd, char *s, unsigned int len) {
- int rc;
-
- rc =read(fd, s, len);
- if ((rc == -1) && (errno == error_intr)) return(0);
- return(rc);
+ sig_unblock(sig_term);
+ sig_unblock(sig_child);
+ sig_unblock(sig_alarm);
+ sig_unblock(sig_hangup);
+ i =read(fd, s, len);
+ sig_block(sig_term);
+ sig_block(sig_child);
+ sig_block(sig_alarm);
+ sig_block(sig_hangup);
+ if (i == -1) if (errno != error_intr) warn("unable to read standard input");
+ if (i > 0) linecomplete =(s[i -1] == '\n');
+ return(i);
}
void sig_term_handler(void) {
- exitasap =1;
if (verbose) strerr_warn2(INFO, "sigterm received.", 0);
+ exitasap =1;
}
void sig_child_handler(void) {
int pid, l;
+ if (verbose) strerr_warn2(INFO, "sigchild received.", 0);
while ((pid =wait_nohang(&wstat)) > 0)
for (l =0; l < dirn; ++l)
if (dir[l].ppid == pid) {
@@ -583,26 +529,50 @@ void sig_child_handler(void) {
processorstop(&dir[l]);
break;
}
- if (verbose) strerr_warn2(INFO, "sigchild received.", 0);
}
void sig_alarm_handler(void) {
- int l;
-
- for (l =0; l < dirn; ++l)
- if (dir[l].fddir != -1)
- if (dir[l].size > 0)
- rotate(&dir[l]);
if (verbose) strerr_warn2(INFO, "sigalarm received.", 0);
+ rotateasap =1;
}
void sig_hangup_handler(void) {
- logdirs_reopen();
if (verbose) strerr_warn2(INFO, "sighangup received.", 0);
+ reopenasap =1;
}
+void logmatch(struct logdir *ld) {
+ int i;
+
+ ld->match ='+';
+ for (i =0; i < ld->inst.len; ++i) {
+ switch(ld->inst.s[i]) {
+ case '+':
+ case '-':
+ if (pmatch(&ld->inst.s[i +1], line, linelen))
+ ld->match =ld->inst.s[i];
+ break;
+ case 'e':
+ if (pmatch(&ld->inst.s[i +1], line, linelen)) {
+ if (timestamp) buffer_puts(buffer_2, stamp);
+ buffer_put(buffer_2, line, linelen);
+ if (linelen == linemax) buffer_puts(buffer_2, "...");
+ buffer_put(buffer_2, "\n", 1); buffer_flush(buffer_2);
+ }
+ break;
+ case 'E':
+ if (! pmatch(&ld->inst.s[i +1], line, linelen)) {
+ if (timestamp) buffer_puts(buffer_2, stamp);
+ buffer_put(buffer_2, line, linelen);
+ if (linelen == linemax) buffer_puts(buffer_2, "...");
+ buffer_put(buffer_2, "\n", 1); buffer_flush(buffer_2);
+ }
+ break;
+ }
+ i +=byte_chr(&ld->inst.s[i], ld->inst.len -i, 0);
+ }
+}
int main(int argc, const char **argv) {
int i;
int opt;
- unsigned int eol;
progname =*argv;
@@ -617,8 +587,8 @@ int main(int argc, const char **argv) {
if (! repl || *(optarg +1)) usage();
break;
case 'l':
- scan_ulong(optarg, &linelen);
- if (linelen == 0) linelen =1000;
+ scan_ulong(optarg, &linemax);
+ if (linemax == 0) linemax =1000;
break;
case 'b':
scan_ulong(optarg, &buflen);
@@ -638,7 +608,7 @@ int main(int argc, const char **argv) {
dirn =argc -optind;
if (dirn <= 0) usage();
- if (buflen <= linelen) usage();
+ if (buflen <= linemax) usage();
if ((fdwdir =open_read(".")) == -1)
fatal("unable to open current working directory");
coe(fdwdir);
@@ -653,7 +623,7 @@ int main(int argc, const char **argv) {
databuf =(char*)alloc(buflen *sizeof(char));
if (! databuf) die_nomem();
buffer_init(&data, buffer_pread, 0, databuf, buflen);
- line =(char*)alloc(linelen *sizeof(char));
+ line =(char*)alloc(linemax *sizeof(char));
if (! line) die_nomem();
fndir =argv;
@@ -668,79 +638,101 @@ int main(int argc, const char **argv) {
logdirs_reopen();
- for(eol =0;;) {
- int r, len;
- char *ch;
-
- if (exitasap && ! data.p) break; /* buffer is empty */
-
- sig_unblock(sig_term);
- sig_unblock(sig_child);
- sig_unblock(sig_alarm);
- sig_unblock(sig_hangup);
- errno =0;
- r =buffer_feed(&data);
- sig_block(sig_term);
- sig_block(sig_child);
- sig_block(sig_alarm);
- sig_block(sig_hangup);
+ for(;;) {
+ char ch;
- if (r == -1) {
- warn("unable to read standard input");
- continue;
- }
- if (r == 0) {
- if (errno == error_intr) continue;
- break; /* eof */
- }
- if (r > linelen) r =linelen;
- if (timestamp && (eol == 0)) {
- taia_now(&now);
- switch (timestamp) {
- case 1:
- stamp[fmt_taia(stamp, &now)] =' ';
- stamp[26] =0;
- break;
- case 2:
- stamp[fmt_ptime(stamp, &now)] =' ';
- stamp[26] =0;
- break;
- case 3:
- stamp[fmt_ptime(stamp, &now)] =0;
- stamp[19] =' '; stamp[20] =0;
+ linelen =0;
+ if (exitasap && ! data.p) break; /* data buffer is empty */
+ for (linelen =0; linelen < linemax; ++linelen) {
+ if (buffer_GETC(&data, &ch) <= 0) {
+ exitasap =1;
break;
}
- }
- ch =buffer_peek(&data);
- for (len =0; len < r; ++len, ++ch) {
- if (*ch == '\n') {
- eol =2;
- break;
+ if (! linelen && timestamp) {
+ taia_now(&now);
+ switch (timestamp) {
+ case 1:
+ stamp[fmt_taia(stamp, &now)] =' ';
+ stamp[26] =0;
+ break;
+ case 2:
+ stamp[fmt_ptime(stamp, &now)] =' ';
+ stamp[26] =0;
+ break;
+ case 3:
+ stamp[fmt_ptime(stamp, &now)] =0;
+ stamp[19] =' '; stamp[20] =0;
+ break;
+ }
}
- line[len] =*ch;
-
+ if (ch == '\n') break;
if (repl) {
- if ((line[len] < 33) || (line[len] > 126))
- line[len] =repl;
+ if ((ch < 32) || (ch > 126))
+ ch =repl;
else
for (i =0; replace[i]; ++i)
- if (line[len] == replace[i]) {
- line[len] =repl;
+ if (ch == replace[i]) {
+ ch =repl;
break;
}
}
+ line[linelen] =ch;
}
- buffer_seek(&data, len);
+ if (! linelen) continue;
+ for (i =0; i < dirn; ++i)
+ if (dir[i].fddir != -1) {
+ if (dir[i].inst.len) logmatch(&dir[i]);
+ if (dir[i].match != '+') continue;
+ if (! dir[i].udponly) {
+ if (timestamp) buffer_puts(&dir[i].b, stamp);
+ buffer_put(&dir[i].b, line, linelen);
+ }
+ if (dir[i].udpaddr.sin_port != 0) {
+ if (fdudp == -1) {
+ buffer_puts(&dir[i].b, "warning: no udp socket available: ");
+ buffer_put(&dir[i].b, line, linelen);
+ buffer_put(&dir[i].b, "\n", 1);
+ buffer_flush(&dir[i].b);
+ }
+ else {
+ if (linelen >= linemax -1) {
+ line[linemax -4] =line[linemax -3] =line[linemax -2] ='.';
+ linelen =linemax -1;
+ }
+ if (line[linelen -1] != '\n') line[linelen++] ='\n';
+ if (sendto(fdudp, line, linelen, 0,
+ (struct sockaddr *)&dir[i].udpaddr,
+ sizeof(dir[i].udpaddr)) != linelen) {
+ buffer_puts(&dir[i].b, "warning: failure sending through udp: ");
+ buffer_put(&dir[i].b, line, linelen);
+ buffer_put(&dir[i].b, "\n", 1);
+ buffer_flush(&dir[i].b);
+ }
+ }
+ }
+ }
+ if (linelen == linemax)
+ for (;;) {
+ if (buffer_GETC(&data, &ch) <= 0) {
+ exitasap =1;
+ break;
+ }
+ if (ch == '\n') break;
+ for (i =0; i < dirn; ++i)
+ if (dir[i].fddir != -1) {
+ if (dir[i].match != '+') continue;
+ if (! dir[i].udponly) buffer_PUTC(&dir[i].b, ch);
+ }
+ }
for (i =0; i < dirn; ++i)
if (dir[i].fddir != -1) {
- switch(eol) {
- case 0: linestart(&dir[i], line, len); break;
- case 1: lineadd(&dir[i], line, len); break;
- case 2: lineflush(&dir[i], line, len); break;
+ if (dir[i].match != '+') continue;
+ if (! dir[i].udponly) {
+ ch ='\n';
+ buffer_PUTC(&dir[i].b, ch);
+ buffer_flush(&dir[i].b);
}
}
- if (eol == 0) eol =1;
- if (eol == 2) { eol =0; buffer_seek(&data, 1); }
}
for (i =0; i < dirn; ++i) {