commit dfe4f9d2469f5404817543bbaf7619b500ff0cbe
parent 3a4427a8d0bc34970b905a8c8723805ba29056d8
Author: Gerrit Pape <pape@smarden.org>
Date: Sat, 6 Nov 2004 15:38:33 +0000
* svlogd.c: new config option t timeout; config options e and E select and
deselect lines for stderr respectively; new config option N.
* man/svlogd.8: adapt.
* runsv.c: on commands down and exit send CONT after TERM.
* man/runsv.8: adapt.
* etc/2: use -P option to runsvdir.
* src/svlogd.check: end check for t config option.
* chpst.c: new option -n: adjust nice level.
* man/chpst.8: adapt.
Diffstat:
14 files changed, 433 insertions(+), 267 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
DESTDIR=
-PACKAGE=runit-1.0.5
+PACKAGE=runit-1.1.0
DIRS=doc man etc package src
MANPAGES=runit.8 runit-init.8 runsvdir.8 runsv.8 svwaitdown.8 svwaitup.8 \
utmpset.8 runsvchdir.8 runsvstat.8 runsvctrl.8 svlogd.8 chpst.8
diff --git a/doc/install.html b/doc/install.html
@@ -17,14 +17,14 @@ If you don't have a <tt>/package</tt> directory, create it now:
# chmod 1755 /package
</pre>
Download
-<a href="runit-1.0.5.tar.gz">runit-1.0.5.tar.gz</a> into <tt>/package</tt>
+<a href="runit-1.1.0.tar.gz">runit-1.1.0.tar.gz</a> into <tt>/package</tt>
and unpack the archive
<pre>
# cd /package
- # gunzip runit-1.0.5.tar
- # tar -xpf runit-1.0.5.tar
- # rm runit-1.0.5.tar
- # cd admin/runit-1.0.5
+ # gunzip runit-1.1.0.tar
+ # tar -xpf runit-1.1.0.tar
+ # rm runit-1.1.0.tar
+ # cd admin/runit-1.1.0
</pre>
On MacOSX, do
<pre>
@@ -43,7 +43,7 @@ hierarchy, do:
</pre>
To report success:
<pre>
- # mail pape-runit-1.0.5@smarden.org <compile/sysdeps
+ # mail pape-runit-1.1.0@smarden.org <compile/sysdeps
</pre>
If you use <i>runit</i> regularly, please
<a href="http://smarden.org/pape/#contribution">contribute</a> to the project.
diff --git a/doc/replaceinit.html b/doc/replaceinit.html
@@ -117,7 +117,7 @@ default Unix process no 1 <i>runit</i>.
</pre>
To report success:
<pre>
- # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-1.0.5@smarden.org
+ # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-1.1.0@smarden.org
</pre>
<hr>
@@ -206,7 +206,7 @@ This will cause <i>runit</i> to enter stage 3 which runs
<p>
To report success:
<pre>
- # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-1.0.5@smarden.org
+ # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-1.1.0@smarden.org
</pre>
<h3>Step 5: Service migration</h3>
The goal is to migrate all services from <i>/etc/rc.*</i> scheme to the
diff --git a/etc/2 b/etc/2
@@ -3,4 +3,4 @@
PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin
exec env - PATH=$PATH \
-runsvdir /var/service 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................'
+runsvdir -P /var/service 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................'
diff --git a/man/chpst.8 b/man/chpst.8
@@ -12,6 +12,8 @@ chpst \- runs a program with a changed process state
.IR dir ]
[\-/
.IR root ]
+[\-n
+.IR inc ]
[-l|-L
.IR lock ]
[-m
@@ -105,6 +107,17 @@ Change the root directory to
before starting
.IR prog .
.TP
+.B \-n \fIinc
+nice.
+Add
+.I inc
+to the
+.BR nice (2)
+value before starting
+.IR prog .
+.I inc
+must be an integer, and may start with a minus or plus.
+.TP
.B \-l \fIlock
lock.
Open the file
diff --git a/man/runsv.8 b/man/runsv.8
@@ -79,7 +79,7 @@ If the service stops, restart it.
.TP
.B d
Down.
-If the service is running, send it a TERM signal.
+If the service is running, send it a TERM signal, and then a CONT signal.
If ./run exits, start ./finish if it exists.
After it stops, do not restart service.
.TP
@@ -129,7 +129,7 @@ If the service is running, send it a KILL signal.
.TP
.B x \fRor \fBe
Exit.
-If the service is running, send it a TERM signal.
+If the service is running, send it a TERM signal, and then a CONT signal.
Do not restart the service.
If the service is down, and no log service exists,
.B runsv
diff --git a/man/svlogd.8 b/man/svlogd.8
@@ -73,7 +73,8 @@ bytes or more (or there is a new-line within the last
.I len
of
.I size
-bytes)
+bytes), or is older than a specified amount of
+.IR time ,
.I current
is rotated:
.P
@@ -192,6 +193,40 @@ old log files in
after log file rotation, it deletes the oldest one.
Default is 10.
.TP
+.RI N min
+sets the minimum number of old log files
+.B svlogd
+should maintain to
+.IR min .
+.I min
+must be less than
+.IR num .
+If
+.I min
+is set, and
+.B svlogd
+cannot write to
+.I current
+because the filesystem is full, and it sees more than
+.I min
+old log files, it deletes the oldest one.
+.TP
+.RI t timeout
+sets the maximum age of the
+.I current
+log file when
+.B svlogd
+should rotate the current log file to
+.I timeout
+seconds.
+If
+.I current
+is
+.I timeout
+seconds old, and is not empty,
+.B svlogd
+forces log file rotation.
+.TP
.RI ! processor
tells
.B svlogd
@@ -248,21 +283,20 @@ and acts accordingly:
the log message is deselected.
.TP
.RI + pattern
-the log message is selected
+the log message is selected.
.TP
.RI e pattern
-log messages matching
-.I pattern
-are printed to standard error.
+the log message is selected to be printed to standard error.
.TP
.RI E pattern
-log messages not matching
-.I pattern
-are printed to standard error.
+the log message is deselected to be printed to standard error.
.P
-Initially each line is selected.
+Initially each line is selected to be written to
+.IR log/current .
Deselected log messages are discarded from
.IR log .
+Initially each line is deselected to be written to standard err.
+Log messages selected for standard error are written to standard error.
.SH PATTERN MATCHING
.B svlogd
matches a log message against the string
diff --git a/package/CHANGES b/package/CHANGES
@@ -1,3 +1,15 @@
+runit 1.1.0
+Sat, 06 Nov 2004 15:38:54 +0000
+ * svlogd.c: new config option t timeout; config options e and E select and
+ deselect lines for stderr respectively; new config option N.
+ * man/svlogd.8: adapt.
+ * runsv.c: on commands down and exit send CONT after TERM.
+ * man/runsv.8: adapt.
+ * etc/2: use -P option to runsvdir.
+ * src/svlogd.check: end check for t config option.
+ * chpst.c: new option -n: adjust nice level.
+ * man/chpst.8: adapt.
+
runit 1.0.5
Tue, 21 Sep 2004 18:18:14 +0000
* svlogd.c: fix line buffer handling for pattern matching (thx Enrico
diff --git a/package/upgrade b/package/upgrade
@@ -8,9 +8,9 @@ test -d src || sh -cx '! : Wrong working directory.'
here=`env - PATH=$PATH pwd`
parent=`dirname $here`
-echo 'Creating symlink runit -> runit-1.0.5...'
+echo 'Creating symlink runit -> runit-1.1.0...'
rm -f runit
-ln -s runit-1.0.5 runit
+ln -s runit-1.1.0 runit
mv -f runit ..
echo 'Making command links in /command...'
diff --git a/package/versions b/package/versions
@@ -29,3 +29,4 @@
1.0.3
1.0.4
1.0.5
+1.1.0
diff --git a/src/chpst.c b/src/chpst.c
@@ -20,7 +20,7 @@
#include "openreadclose.h"
#include "direntry.h"
-#define USAGE_MAIN " [-vP012] [-u user[:group]] [-U user[:group]] [-e dir] [-/ root] [-l|-L lock] [-m n] [-o n] [-p n] [-f n] [-c n] prog"
+#define USAGE_MAIN " [-vP012] [-u user[:group]] [-U user[:group]] [-e dir] [-/ root] [-n nice] [-l|-L lock] [-m n] [-o n] [-p n] [-f n] [-c n] prog"
#define FATAL "chpst: fatal: "
#define WARNING "chpst: warning: "
@@ -56,6 +56,7 @@ long limitf =-2;
long limitc =-2;
long limitr =-2;
long limitt =-2;
+long nicelvl =0;
const char *lock =0;
const char *root =0;
unsigned int lockdelay;
@@ -109,19 +110,19 @@ void edir(const char *dirname) {
if (d->d_name[0] == '.') continue;
if (openreadclose(d->d_name, &sa, 256) == -1) {
if ((errno == error_isdir) && env_dir) {
- if (verbose)
- strerr_warn6(WARNING, "unable to read ", dirname, "/",
- d->d_name, ": ", &strerr_sys);
- continue;
+ if (verbose)
+ strerr_warn6(WARNING, "unable to read ", dirname, "/",
+ d->d_name, ": ", &strerr_sys);
+ continue;
}
else
strerr_die6sys(111, FATAL, "unable to read ", dirname, "/",
- d->d_name, ": ");
+ d->d_name, ": ");
}
if (sa.len) {
sa.len =byte_chr(sa.s, sa.len, '\n');
while (sa.len && (sa.s[sa.len -1] == ' ' || sa.s[sa.len -1] == '\t'))
- --sa.len;
+ --sa.len;
for (i =0; i < sa.len; ++i) if (! sa.s[i]) sa.s[i] ='\n';
if (! stralloc_0(&sa)) die_nomem();
if (! pathexec_env(d->d_name, sa.s)) die_nomem();
@@ -271,8 +272,8 @@ int main(int argc, const char *const *argv) {
if (str_equal(progname, "setlock")) setlock(argc, argv);
if (str_equal(progname, "softlimit")) softlimit(argc, argv);
- while ((opt =getopt(argc, argv, "u:U:e:m:o:p:f:c:r:t:/:l:L:vP012V"))
- != opteof)
+ while ((opt =getopt(argc, argv, "u:U:e:m:o:p:f:c:r:t:/:n:l:L:vP012V"))
+ != opteof)
switch(opt) {
case 'u': set_user =(char*)optarg; break;
case 'U': env_user =(char*)optarg; break;
@@ -288,6 +289,18 @@ int main(int argc, const char *const *argv) {
case 'r': if (optarg[scan_ulong(optarg, &limitr)]) usage(); break;
case 't': if (optarg[scan_ulong(optarg, &limitt)]) usage(); break;
case '/': root =optarg; break;
+ case 'n':
+ switch (*optarg) {
+ case '-':
+ if (optarg[scan_ulong(++optarg, &nicelvl)]) usage();
+ nicelvl *=-1;
+ break;
+ case '+': ++optarg;
+ default:
+ if (optarg[scan_ulong(optarg, &nicelvl)]) usage();
+ break;
+ }
+ break;
case 'l': if (lock) usage(); lock =optarg; lockdelay =1; break;
case 'L': if (lock) usage(); lock =optarg; lockdelay =0; break;
case 'v': verbose =1; break;
@@ -314,7 +327,11 @@ int main(int argc, const char *const *argv) {
if (nostdin) if (close(0) == -1) fatal("unable to close stdin");
if (nostdout) if (close(1) == -1) fatal("unable to close stdout");
if (nostderr) if (close(2) == -1) fatal("unable to close stderr");
-
+ if (nicelvl) {
+ errno =0;
+ if (nice(nicelvl) == -1)
+ if (errno) fatal("unable to set nice level");
+ }
pathexec(argv);
fatal2("unable to run", *argv);
return(0);
diff --git a/src/runsv.c b/src/runsv.c
@@ -105,14 +105,14 @@ void update_status(struct svdir *s) {
close(fd);
if (s->islog) {
if (rename("supervise/pid.new", "log/supervise/pid") == -1) {
- warn("unable to rename supervise/pid.new to log/supervise/pid");
- return;
+ warn("unable to rename supervise/pid.new to log/supervise/pid");
+ return;
}
}
else {
if (rename("supervise/pid.new", "supervise/pid") == -1) {
- warn("unable to rename supervise/pid.new to supervise/pid");
- return;
+ warn("unable to rename supervise/pid.new to supervise/pid");
+ return;
}
}
pidchanged =0;
@@ -205,6 +205,7 @@ void stopservice(struct svdir *s) {
if (s->pid) kill(s->pid, SIGTERM);
s->ctrl |=C_TERM;
update_status(s);
+ if ((s->want == W_DOWN) || (s->want == W_EXIT)) kill(s->pid, SIGCONT);
}
void startservice(struct svdir *s) {
@@ -226,16 +227,16 @@ void startservice(struct svdir *s) {
/* child */
if (haslog) {
if (s->islog) {
- if (fd_copy(0, logpipe[0]) == -1)
- fatal("unable to setup filedescriptor for ./log/run");
- close(logpipe[1]);
- if (chdir("./log") == -1)
- fatal("unable to change directory to ./log");
+ if (fd_copy(0, logpipe[0]) == -1)
+ fatal("unable to setup filedescriptor for ./log/run");
+ close(logpipe[1]);
+ if (chdir("./log") == -1)
+ fatal("unable to change directory to ./log");
}
else {
- if (fd_copy(1, logpipe[1]) == -1)
- fatal("unable to setup filedescriptor for ./run");
- close(logpipe[0]);
+ if (fd_copy(1, logpipe[1]) == -1)
+ fatal("unable to setup filedescriptor for ./run");
+ close(logpipe[0]);
}
}
sig_uncatch(sig_child);
@@ -367,9 +368,9 @@ int main(int argc, char **argv) {
svd[1].islog =1;
taia_now(&svd[1].start);
if (stat("log/down", &s) != -1)
- svd[1].want =W_DOWN;
+ svd[1].want =W_DOWN;
if (pipe(logpipe) == -1)
- fatal("unable to create log pipe");
+ fatal("unable to create log pipe");
coe(logpipe[0]);
coe(logpipe[1]);
}
@@ -378,13 +379,13 @@ int main(int argc, char **argv) {
if (mkdir("supervise", 0700) == -1) {
if ((r =readlink("supervise", buf, 256)) != -1) {
if (r == 256)
- fatalx("unable to readlink ./supervise: ", "name too long");
+ fatalx("unable to readlink ./supervise: ", "name too long");
buf[r] =0;
mkdir(buf, 0700);
}
else {
if ((errno != ENOENT) && (errno != EINVAL))
- fatal("unable to readlink ./supervise");
+ fatal("unable to readlink ./supervise");
}
}
if ((svd[0].fdlock =open_append("supervise/lock")) == -1)
@@ -394,21 +395,21 @@ int main(int argc, char **argv) {
if (haslog) {
if (mkdir("log/supervise", 0700) == -1) {
if ((r =readlink("log/supervise", buf, 256)) != -1) {
- if (r == 256)
- fatalx("unable to readlink ./log/supervise: ", "name too long");
- buf[r] =0;
- if ((fd =open_read(".")) == -1)
- fatal("unable to open current directory");
- if (chdir("./log") == -1)
- fatal("unable to change directory to ./log");
- mkdir(buf, 0700);
- if (fchdir(fd) == -1)
- fatal("unable to change back to service directory");
- close(fd);
+ if (r == 256)
+ fatalx("unable to readlink ./log/supervise: ", "name too long");
+ buf[r] =0;
+ if ((fd =open_read(".")) == -1)
+ fatal("unable to open current directory");
+ if (chdir("./log") == -1)
+ fatal("unable to change directory to ./log");
+ mkdir(buf, 0700);
+ if (fchdir(fd) == -1)
+ fatal("unable to change back to service directory");
+ close(fd);
}
else {
- if ((errno != ENOENT) && (errno != EINVAL))
- fatal("unable to readlink ./log/supervise");
+ if ((errno != ENOENT) && (errno != EINVAL))
+ fatal("unable to readlink ./log/supervise");
}
}
if ((svd[1].fdlock =open_append("log/supervise/lock")) == -1)
@@ -456,7 +457,7 @@ int main(int argc, char **argv) {
if (! svd[1].pid && (svd[1].want == W_UP)) startservice(&svd[1]);
if (! svd[0].pid)
if ((svd[0].want == W_UP) || (svd[0].state == S_FINISH))
- startservice(&svd[0]);
+ startservice(&svd[0]);
x[0].fd =selfpipe[0];
x[0].events =IOPAUSE_READ;
@@ -486,29 +487,29 @@ int main(int argc, char **argv) {
if (!child) break;
if ((child == -1) && (errno != error_intr)) break;
if (child == svd[0].pid) {
- svd[0].pid =0;
- pidchanged =1;
- svd[0].ctrl &=~C_TERM;
- taia_now(&svd[0].start);
- if (svd[0].state != S_FINISH)
- if ((fd =open_read("finish")) != -1) {
- close(fd);
- svd[0].state =S_FINISH;
- update_status(&svd[0]);
- break;
- }
- svd[0].state =S_DOWN;
- update_status(&svd[0]);
+ svd[0].pid =0;
+ pidchanged =1;
+ svd[0].ctrl &=~C_TERM;
+ taia_now(&svd[0].start);
+ if (svd[0].state != S_FINISH)
+ if ((fd =open_read("finish")) != -1) {
+ close(fd);
+ svd[0].state =S_FINISH;
+ update_status(&svd[0]);
+ break;
+ }
+ svd[0].state =S_DOWN;
+ update_status(&svd[0]);
}
if (haslog) {
- if (child == svd[1].pid) {
- svd[1].pid =0;
- pidchanged =1;
- svd[1].state =S_DOWN;
- svd[1].ctrl &=~C_TERM;
- taia_now(&svd[1].start);
- update_status(&svd[1]);
- }
+ if (child == svd[1].pid) {
+ svd[1].pid =0;
+ pidchanged =1;
+ svd[1].state =S_DOWN;
+ svd[1].ctrl &=~C_TERM;
+ taia_now(&svd[1].start);
+ update_status(&svd[1]);
+ }
}
}
if (read(svd[0].fdcontrol, &ch, 1) == 1) ctrl(&svd[0], ch);
@@ -518,11 +519,11 @@ int main(int argc, char **argv) {
if (svd[0].want == W_EXIT && svd[0].state == S_DOWN) {
if (svd[1].pid == 0) _exit(0);
if (svd[1].want != W_EXIT) {
- svd[1].want =W_EXIT;
- /* stopservice(&svd[1]); */
- update_status(&svd[1]);
- if (close(logpipe[1]) == -1) warn("unable to close logpipe[1]");
- if (close(logpipe[0]) == -1) warn("unable to close logpipe[0]");
+ svd[1].want =W_EXIT;
+ /* stopservice(&svd[1]); */
+ update_status(&svd[1]);
+ if (close(logpipe[1]) == -1) warn("unable to close logpipe[1]");
+ if (close(logpipe[0]) == -1) warn("unable to close logpipe[0]");
}
}
}
diff --git a/src/svlogd.c b/src/svlogd.c
@@ -31,8 +31,9 @@
#include "taia.h"
#include "fmt.h"
#include "ndelay.h"
+#include "iopause.h"
-#define USAGE " [-tv] [-r c] [-R abc] [-l n ] [-b n] dir ..."
+#define USAGE " [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ..."
#define VERSION "$Id$"
#define FATAL "svlogd: fatal: "
@@ -57,6 +58,7 @@ struct stat st;
stralloc sa;
int wstat;
struct taia now;
+struct taia trotate;
char *databuf;
buffer data;
@@ -66,7 +68,9 @@ unsigned int exitasap =0;
unsigned int rotateasap =0;
unsigned int reopenasap =0;
unsigned int linecomplete =1;
+unsigned int tmaxflag =0;
int fdudp =-1;
+iopause_fd in;
struct logdir {
int fddir;
@@ -76,6 +80,9 @@ struct logdir {
unsigned long size;
unsigned long sizemax;
unsigned long nmax;
+ unsigned long nmin;
+ unsigned long tmax;
+ struct taia trotate;
stralloc processor;
int ppid;
char fnsave[FMT_PTIME];
@@ -83,6 +90,7 @@ struct logdir {
int fdcur;
int fdlock;
char match;
+ char matcherr;
struct sockaddr_in udpaddr;
unsigned int udponly;
} *dir;
@@ -142,14 +150,14 @@ unsigned int processorstart(struct logdir *ld) {
fatal2("unable to move filedescriptor for processor", ld->name);
if ((fd =open_read("state")) == -1) {
if (errno == error_noent) {
- if ((fd =open_trunc("state")) == -1)
- fatal2("unable to create empty state for processor", ld->name);
- close(fd);
- if ((fd =open_read("state")) == -1)
- fatal2("unable to open state for processor", ld->name);
+ if ((fd =open_trunc("state")) == -1)
+ fatal2("unable to create empty state for processor", ld->name);
+ close(fd);
+ if ((fd =open_read("state")) == -1)
+ fatal2("unable to open state for processor", ld->name);
}
else
- fatal2("unable to open state for processor", ld->name);
+ fatal2("unable to open state for processor", ld->name);
}
if (fd_move(4, fd) == -1)
fatal2("unable to move filedescriptor for processor", ld->name);
@@ -215,8 +223,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->fddir == -1) { ld->tmax =0; return(0); }
if (ld->ppid) while(! processorstop(ld));
while (fchdir(ld->fddir) == -1)
@@ -235,45 +242,53 @@ unsigned int rotate(struct logdir *ld) {
errno =0;
} while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent));
- buffer_flush(&ld->b);
- while (fsync(ld->fdcur) == -1)
- pause2("unable to fsync current logfile", ld->name);
- while (fchmod(ld->fdcur, 0744) == -1)
- pause2("unable to set mode of current", ld->name);
- close(ld->fdcur);
- if (verbose) {
- tmp[0] =' '; tmp[fmt_ulong(tmp +1, ld->size) +1] =0;
- strerr_warn6(INFO, "rename: ", ld->name, "/current ",
- ld->fnsave, tmp, 0);
+ if (ld->tmax && taia_less(&ld->trotate, &now)) {
+ taia_uint(&ld->trotate, ld->tmax);
+ taia_add(&ld->trotate, &now, &ld->trotate);
+ if (taia_less(&ld->trotate, &trotate)) trotate =ld->trotate;
}
- while (rename("current", ld->fnsave) == -1)
- pause2("unable to rename current", ld->name);
- while ((ld->fdcur =open_append("current")) == -1)
- pause2("unable to create new current", ld->name);
- coe(ld->fdcur);
- ld->size =0;
- while (fchmod(ld->fdcur, 0644) == -1)
- pause2("unable to set mode of current", ld->name);
- 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;
- if (str_diff(f->d_name, oldest) < 0) byte_copy(oldest, 27, f->d_name);
+ if (ld->size > 0) {
+ buffer_flush(&ld->b);
+ while (fsync(ld->fdcur) == -1)
+ pause2("unable to fsync current logfile", ld->name);
+ while (fchmod(ld->fdcur, 0744) == -1)
+ pause2("unable to set mode of current", ld->name);
+ close(ld->fdcur);
+ if (verbose) {
+ tmp[0] =' '; tmp[fmt_ulong(tmp +1, ld->size) +1] =0;
+ strerr_warn6(INFO, "rename: ", ld->name, "/current ",
+ ld->fnsave, tmp, 0);
}
- if (errno) warn2("unable to read directory", ld->name);
- closedir(d);
-
- if (ld->nmax && (n >= ld->nmax)) {
- if (verbose) strerr_warn5(INFO, "delete: ", ld->name, "/", oldest, 0);
- if ((*oldest == '@') && (unlink(oldest) == -1))
- warn2("unable to unlink oldest logfile", ld->name);
+ while (rename("current", ld->fnsave) == -1)
+ pause2("unable to rename current", ld->name);
+ while ((ld->fdcur =open_append("current")) == -1)
+ pause2("unable to create new current", ld->name);
+ coe(ld->fdcur);
+ ld->size =0;
+ while (fchmod(ld->fdcur, 0644) == -1)
+ pause2("unable to set mode of current", ld->name);
+
+ 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;
+ if (str_diff(f->d_name, oldest) < 0) byte_copy(oldest, 27, f->d_name);
+ }
+ if (errno) warn2("unable to read directory", ld->name);
+ closedir(d);
+
+ if (ld->nmax && (n >= ld->nmax)) {
+ if (verbose) strerr_warn5(INFO, "delete: ", ld->name, "/", oldest, 0);
+ if ((*oldest == '@') && (unlink(oldest) == -1))
+ warn2("unable to unlink oldest logfile", ld->name);
+ }
+ processorstart(ld);
}
- processorstart(ld);
while (fchdir(fdwdir) == -1)
pause1("unable to change to initial working directory");
return(1);
@@ -287,8 +302,47 @@ int buffer_pwrite(int n, char *s, unsigned int len) {
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);
+ while ((i =write((dir +n)->fdcur, s, len)) == -1) {
+ if ((errno == ENOSPC) && ((dir +n)->nmin < (dir +n)->nmax)) {
+ DIR *d;
+ direntry *f;
+ char oldest[FMT_PTIME];
+ int j =0;
+
+ while (fchdir((dir +n)->fddir) == -1)
+ pause2("unable to change directory, want remove old logfile",
+ (dir +n)->name);
+ oldest[0] ='A'; oldest[1] =oldest[27] =0;
+ while (! (d =opendir(".")))
+ pause2("unable to open directory, want remove old logfile",
+ (dir +n)->name);
+ errno =0;
+ while ((f =readdir(d)))
+ if ((f->d_name[0] == '@') && (str_len(f->d_name) == 27)) {
+ ++j;
+ if (str_diff(f->d_name, oldest) < 0)
+ byte_copy(oldest, 27, f->d_name);
+ }
+ if (errno) warn2("unable to read directory, want remove old logfile",
+ (dir +n)->name);
+ closedir(d);
+ errno =ENOSPC;
+ if (j > (dir +n)->nmin)
+ if (*oldest == '@') {
+ strerr_warn5(WARNING, "out of disk space, delete: ", (dir +n)->name,
+ "/", oldest, 0);
+ errno =0;
+ if (unlink(oldest) == -1) {
+ warn2("unable to unlink oldest logfile", (dir +n)->name);
+ errno =ENOSPC;
+ }
+ while (fchdir(fdwdir) == -1)
+ pause1("unable to change to initial working directory");
+ }
+ }
+ if (errno) pause2("unable to write to current", (dir +n)->name);
+ }
+
(dir +n)->size +=i;
if ((dir +n)->sizemax)
if (s[i -1] == '\n')
@@ -358,7 +412,8 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
ld->size =0;
ld->sizemax =1000000;
- ld->nmax =10;
+ ld->nmax =ld->nmin =10;
+ ld->tmax =0;
ld->name =(char*)fn;
ld->ppid =0;
ld->match ='+';
@@ -377,57 +432,76 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
if (verbose) strerr_warn4(INFO, "read: ", ld->name, "/config", 0);
for (i =0; i +1 < sa.len; ++i) {
if ((len =byte_chr(&sa.s[i], sa.len -i, '\n')) == 1) {
- ++i; continue;
+ ++i; continue;
}
sa.s[len +i] =0;
switch(sa.s[i]) {
case '\n':
case '#':
- break;
+ break;
case '+':
case '-':
case 'e':
case 'E':
- while (! stralloc_catb(&ld->inst, &sa.s[i], len)) pause_nomem();
- while (! stralloc_0(&ld->inst)) pause_nomem();
- break;
+ while (! stralloc_catb(&ld->inst, &sa.s[i], len)) pause_nomem();
+ while (! stralloc_0(&ld->inst)) pause_nomem();
+ break;
case 's':
- scan_ulong(&sa.s[i +1], &ld->sizemax);
- break;
+ switch (sa.s[scan_ulong(&sa.s[i +1], &ld->sizemax) +i +1]) {
+ case 'm': ld->sizemax *=1024;
+ case 'k': ld->sizemax *=1024;
+ }
+ break;
case 'n':
- scan_ulong(&sa.s[i +1], &ld->nmax);
- if (ld->nmax == 1) ld->nmax =2;
- break;
+ scan_ulong(&sa.s[i +1], &ld->nmax);
+ break;
+ case 'N':
+ scan_ulong(&sa.s[i +1], &ld->nmin);
+ break;
+ case 't':
+ switch (sa.s[scan_ulong(&sa.s[i +1], &ld->tmax) +i +1]) {
+ /* case 'd': ld->tmax *=24; */
+ case 'h': ld->tmax *=60;
+ case 'm': ld->tmax *=60;
+ }
+ if (ld->tmax) {
+ taia_uint(&ld->trotate, ld->tmax);
+ taia_add(&ld->trotate, &now, &ld->trotate);
+ if (! tmaxflag || taia_less(&ld->trotate, &trotate))
+ trotate =ld->trotate;
+ tmaxflag =1;
+ }
+ break;
case '!':
- while (! stralloc_copys(&ld->processor, &sa.s[i +1])) pause_nomem();
- while (! stralloc_0(&ld->processor)) pause_nomem();
- break;
+ while (! stralloc_copys(&ld->processor, &sa.s[i +1])) pause_nomem();
+ while (! stralloc_0(&ld->processor)) pause_nomem();
+ break;
case 'U':
- ld->udponly =1;
+ ld->udponly =1;
case 'u':
- if (! (c =ip4_scan(sa.s +i +1, (char *)&ld->udpaddr.sin_addr))) {
- warnx("unable to scan ip address", sa.s +i +1);
- break;
- }
- if (sa.s[i +1 +c] == ':') {
- scan_ulong(sa.s +i +c +2, &port);
- if (port == 0) {
- warnx("unable to scan port number", sa.s +i +c +2);
- break;
- }
- }
- else
- port =514;
- ld->udpaddr.sin_port =htons(port);
- if (fdudp == -1) {
- fdudp =socket(AF_INET, SOCK_DGRAM, 0);
- if (fdudp)
- if (ndelay_on(fdudp) == -1) {
- close(fdudp);
- fdudp =-1;
- }
- }
- break;
+ if (! (c =ip4_scan(sa.s +i +1, (char *)&ld->udpaddr.sin_addr))) {
+ warnx("unable to scan ip address", sa.s +i +1);
+ break;
+ }
+ if (sa.s[i +1 +c] == ':') {
+ scan_ulong(sa.s +i +c +2, &port);
+ if (port == 0) {
+ warnx("unable to scan port number", sa.s +i +c +2);
+ break;
+ }
+ }
+ else
+ port =514;
+ ld->udpaddr.sin_port =htons(port);
+ if (fdudp == -1) {
+ fdudp =socket(AF_INET, SOCK_DGRAM, 0);
+ if (fdudp)
+ if (ndelay_on(fdudp) == -1) {
+ close(fdudp);
+ fdudp =-1;
+ }
+ }
+ break;
}
i +=len;
}
@@ -438,12 +512,12 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
if (st.st_size && ! (st.st_mode & S_IXUSR)) {
ld->fnsave[25] ='.'; ld->fnsave[26] ='u'; ld->fnsave[27] =0;
do {
- taia_now(&now);
- fmt_taia(ld->fnsave, &now);
- errno =0;
+ taia_now(&now);
+ fmt_taia(ld->fnsave, &now);
+ errno =0;
} while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent));
while (rename("current", ld->fnsave) == -1)
- pause2("unable to rename current", ld->name);
+ pause2("unable to rename current", ld->name);
i =-1;
}
else
@@ -454,7 +528,7 @@ unsigned int logdir_open(struct logdir *ld, const char *fn) {
logdir_close(ld);
warn2("unable to stat current", ld->name);
while (fchdir(fdwdir) == -1)
- pause1("unable to change to initial working directory");
+ pause1("unable to change to initial working directory");
return(0);
}
while ((ld->fdcur =open_append("current")) == -1)
@@ -478,6 +552,8 @@ void logdirs_reopen(void) {
int l;
int ok =0;
+ tmaxflag =0;
+ taia_now(&now);
for (l =0; l < dirn; ++l) {
logdir_close(&dir[l]);
if (logdir_open(&dir[l], fndir[l])) ok =1;
@@ -501,16 +577,28 @@ int buffer_pread(int fd, char *s, unsigned int len) {
logdirs_reopen();
reopenasap =0;
}
+ taia_now(&now);
+ taia_uint(&trotate, 2744);
+ taia_add(&trotate, &now, &trotate);
+ for (i =0; i < dirn; ++i)
+ if ((dir +i)->tmax) {
+ if (taia_less(&dir[i].trotate, &now)) rotate(dir +i);
+ if (taia_less(&dir[i].trotate, &trotate)) trotate =dir[i].trotate;
+ }
sig_unblock(sig_term);
sig_unblock(sig_child);
sig_unblock(sig_alarm);
sig_unblock(sig_hangup);
- i =read(fd, s, len);
+ iopause(&in, 1, &trotate, &now);
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");
+ i =read(fd, s, len);
+ if (i == -1) {
+ if (errno == error_again) errno =error_intr;
+ if (errno != error_intr) warn("unable to read standard input");
+ }
if (i > 0) linecomplete =(s[i -1] == '\n');
return(i);
}
@@ -525,9 +613,9 @@ void sig_child_handler(void) {
while ((pid =wait_nohang(&wstat)) > 0)
for (l =0; l < dirn; ++l)
if (dir[l].ppid == pid) {
- dir[l].ppid =0;
- processorstop(&dir[l]);
- break;
+ dir[l].ppid =0;
+ processorstop(&dir[l]);
+ break;
}
}
void sig_alarm_handler(void) {
@@ -543,28 +631,18 @@ void logmatch(struct logdir *ld) {
int i;
ld->match ='+';
+ ld->matcherr ='E';
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];
+ 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);
- }
+ if (pmatch(&ld->inst.s[i +1], line, linelen))
+ ld->matcherr =ld->inst.s[i];
break;
}
i +=byte_chr(&ld->inst.s[i], ld->inst.len -i, 0);
@@ -595,7 +673,7 @@ int main(int argc, const char **argv) {
if (buflen == 0) buflen =1024;
break;
case 't':
- ++timestamp;
+ if (++timestamp > 2) timestamp =2;
break;
case 'v':
++verbose;
@@ -626,6 +704,9 @@ int main(int argc, const char **argv) {
line =(char*)alloc(linemax *sizeof(char));
if (! line) die_nomem();
fndir =argv;
+ in.fd =0;
+ in.events =IOPAUSE_READ;
+ ndelay_on(in.fd);
sig_block(sig_term);
sig_block(sig_child);
@@ -645,93 +726,94 @@ int main(int argc, const char **argv) {
if (exitasap && ! data.p) break; /* data buffer is empty */
for (linelen =0; linelen < linemax; ++linelen) {
if (buffer_GETC(&data, &ch) <= 0) {
- exitasap =1;
- break;
+ exitasap =1;
+ 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;
- }
+ 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;
+ }
}
if (ch == '\n') break;
if (repl) {
- if ((ch < 32) || (ch > 126))
- ch =repl;
- else
- for (i =0; replace[i]; ++i)
- if (ch == replace[i]) {
- ch =repl;
- break;
- }
+ if ((ch < 32) || (ch > 126))
+ ch =repl;
+ else
+ for (i =0; replace[i]; ++i)
+ if (ch == replace[i]) {
+ ch =repl;
+ break;
+ }
}
line[linelen] =ch;
}
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 (dir[i].inst.len) logmatch(&dir[i]);
+ if (dir[i].matcherr == 'e') {
+ buffer_put(buffer_2, line, linelen);
+ if (linelen == linemax) buffer_puts(buffer_2, "...");
+ buffer_put(buffer_2, "\n", 1); buffer_flush(buffer_2);
+ }
+ 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);
- }
+ 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) {
- if (dir[i].match != '+') continue;
- if (! dir[i].udponly) {
- ch ='\n';
- buffer_PUTC(&dir[i].b, ch);
- buffer_flush(&dir[i].b);
- }
+ if (dir[i].match != '+') continue;
+ if (! dir[i].udponly) {
+ ch ='\n';
+ buffer_PUTC(&dir[i].b, ch);
+ buffer_flush(&dir[i].b);
+ }
}
}
diff --git a/src/svlogd.check b/src/svlogd.check
@@ -18,4 +18,10 @@ cat "${ctmp}"/current
( echo foo; echo bar; echo baz ) |svlogd -r: -R fb "${ctmp}"
echo $?
cat "${ctmp}"/current
+
+echo t2 >"${ctmp}"/config
+( echo foo; sleep 3 ) |svlogd "${ctmp}"
+echo $?
+cat "${ctmp}"/current
+
rm -rf "${ctmp}"