diff options
Diffstat (limited to 'runit-2.1.2')
270 files changed, 14542 insertions, 0 deletions
diff --git a/runit-2.1.2/doc/benefits.html b/runit-2.1.2/doc/benefits.html new file mode 100644 index 0000000..b1687d9 --- /dev/null +++ b/runit-2.1.2/doc/benefits.html @@ -0,0 +1,187 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - benefits</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - benefits</h1> +<hr> +<a href="#supervision">Service supervision</a><br> +<a href="#state">Clean process state</a><br> +<a href="#log">Reliable logging facility</a><br> +<a href="#fast">Fast system boot up and shutdown</a><br> +<a href="#portability">Portability</a><br> +<a href="#packaging">Packaging friendly</a><br> +<a href="#smallcode">Small code size</a> +<hr> +<a name="supervision"><h3>Service supervision</h3></a> +Each service is associated with a <i>service directory</i>, and each +service daemon runs as a child process of a supervising +<a href="runsv.8.html">runsv</a> process running in this directory. +The <a href="runsv.8.html">runsv</a> program provides a reliable interface +for signalling the service daemon and controlling the service and +supervisor. +Normally the <a href="sv.8.html">sv</a> program is used to send commands +through this interface, and to query status informations about the service. +<p> +The <a href="runsv.8.html">runsv</a> program supervises the corresponding +service daemon. +By default a service is defined to be up, that means, if the service daemon +dies, it will be restarted. +Of course you can <a href="sv.8.html">tell runsv</a> otherwise. +<p> +This reliable interface to control daemons and supervisors obsoletes +pid-guessing programs, such as <tt>pidof</tt>, <tt>killall</tt>, +<tt>start-stop-daemon</tt>, which, due to guessing, are prone to failures +by design. +It also obsoletes so called <tt>pid-files</tt>, no need for each and every +service daemon to include code to daemonize, to write the new process id +into a file, and to take care that the file is removed properly on shutdown, +which might be very difficult in case of a crash. +<hr> +<a name="state"><h3>Clean process state</h3></a> +<i>runit</i> guarantees each service a clean process state, no matter if the +service is activated for the first time or automatically at boot time, +reactivated, or simply restarted. +This means that the service always is started with the same environment, +resource limits, open file descriptors, and controlling terminals. +<p> +You don't necessarily have that with <i>sysv init</i> scripts for example. +It requires a carefully written init script that reliably cleans up and sets +the process state before starting the service daemon. +This adds even more complexity to the init script in comparison with a run +script used by <i>runit</i>. +Many of today's init scripts don't provide a clean process state, here is +an example on what could happen: +<pre> + # /etc/init.d/foo-daemon start + Starting foo daemon: food. + # +</pre> +Fine. +Everything works, nothing to worry about. +After rebooting the system this shows up on the screen: +<pre> + ... + Starting foo daemon: food: command not found + failed. + ... +</pre> +The <tt>food</tt> program is installed in <tt>/opt/foo/bin/</tt>. +When starting the service for the first time using the init script, the +<tt>PATH</tt> environment variable contained <tt>/opt/foo/bin</tt>. +After reboot <tt>init</tt> started the service using the init script, but +with a different value for the <tt>PATH</tt> variable, not containing +<tt>/opt/foo/bin</tt>. +Of course the init script should have set <tt>PATH</tt> before starting the +daemon; the problem is that it worked in the first place, and that the error +didn't show up until system reboot. +<p> +With bad init scripts miraculous things could also happen when just doing +<pre> + # /etc/init.d/foo-daemon restart +</pre> +at the command line. +<p> +The clean process state includes open file descriptors, obsoleting the +widely used hack in many service daemons to force-close all file descriptors +that might be open, up to the limit of available file descriptors for the +daemon process (often results in 1024 unnecessary close() system calls in a +great number of service daemon implementations). +<hr> +<a name="log"><h3>Reliable logging facility</h3></a> +The <a href="runsv.8.html">runsv</a> program provides a reliable logging +facility for the service daemon. +If configured, <a href="runsv.8.html">runsv</a> creates a pipe, starts and +supervises an additional log service, redirects the log daemon's standard +input to read from the pipe, and redirects the service daemon's standard +output to write to the pipe. +Restarting the service does not require restarting the log service, and vice +versa. +A good choice for a log daemon is <i>runit</i>'s service logging daemon +<a href="svlogd.8.html">svlogd</a>. +<p> +The service daemon and the log daemon can run with different process states, +and under different user id's. +<i>runit</i> supports easy and reliable logging for service daemons running +chroot'ed. +<p> +If <a href="runsv.8.html">runsv</a> is told to shutdown a service, e.g. at +system shutdown, it ensures that the log service stays up as long as the +corresponding service daemon is running and possibly writing to the log. +<hr> +<a name="fast"><h3>Fast system boot up and shutdown</h3></a> +After the system's one time tasks (stage 1) are done, the system services +are started up in parallel. +The operating system's process scheduler takes care of having the services +available as soon as possible. +<p> +On system shutdown, stage 3 uses <a href="runsv.8.html">runsv</a>'s control +interface to wait until each service daemon is terminated and all logs are +written. +Again, services are taken down in parallel. +As soon as all services are down, system halt or system reboot is initiated. +<hr> +<a name="portability"><h3>Portability</h3></a> +<i>runit</i> comes ready-to-run for Debian GNU/Linux and BSD systems, and +can easily be configured to run on other UNIX systems. +The UNIX system's one time initialization tasks and tasks to shutdown the +system must be identified and <i>runit</i>'s stages 1 and 3 configured +accordingly. +<p> +Stages 1 and 3 handle one time tasks. +They only run for short and exit soon. +Stage 2 handles the system's uptime tasks (via the +<a href="runsvdir.8.html">runsvdir</a> program) and is running the whole +system's uptime. +<p> +<i>runit</i>'s stage 2 is portable across UNIX systems. +<i>runit</i> is well suited for server systems and embedded systems, and +also does its job well on desktop systems. +<hr> +<a name="packaging"><h3>Packaging friendly</h3></a> +<i>runit</i>'s stages 1 and 3 are distribution specific. +They normally are shell scripts, and an operating system distribution with +software package management should adapt these scripts if they need support +for their package management. +The +<a href="http://packages.debian.org/unstable/admin/runit-run.html"> +runit-run</a> +Debian package is an attempt to integrate <i>runit</i> into +<a href="http://www.debian.org/">Debian GNU/Linux</a> as an alternative to +the default +<a href="http://packages.debian.org/unstable/base/sysvinit.html"> +sysvinit</a>. +<p> +Stage 2 is packaging friendly: +all a software package that provides a service needs to do is to include +a <i>service directory</i> in the package, and to provide a symbolic link +to this directory in <tt>/service/</tt>. +The service will be started within five seconds, and automatically at boot +time. +The package's install and update scripts can use the reliable control +interface to stop, start, restart, or send signals to the service. +On package removal, the symbolic link simply is removed. +The service will be taken down automatically. +<hr> +<a name="smallcode"><h3>Small code size</h3></a> +One of the <i>runit</i> project's principles is to keep the code size +small. +As of version 1.0.0 of <i>runit</i>, the <tt>runit.c</tt> source contains +330 lines of code; the <tt>runsvdir.c</tt> source is 274 lines of code, the +<tt>runsv.c</tt> source 509. +This minimizes the possibility of bugs introduced by programmer's fault, +and makes it more easy for security related people to proofread the source +code. +<p> +The <i>runit</i> core programs have a very small memory footprint and do not +allocate memory dynamically. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/chpst.8.html b/runit-2.1.2/doc/chpst.8.html new file mode 100644 index 0000000..97d90f2 --- /dev/null +++ b/runit-2.1.2/doc/chpst.8.html @@ -0,0 +1,152 @@ + + + +<html> +<head> +<title>chpst(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +chpst - runs a program with a changed process state +<h2><a name='sect1'>Synopsis</a></h2> +<b>chpst</b> [-vP012] +[-u <i>user</i>] [-U <i>user</i>] [-b <i>argv0</i>] [-e <i>dir</i>] [-/ <i>root</i>] [-n <i>inc</i>] [-l|-L <i>lock</i>] [-m <i>bytes</i>] [-d <i>bytes</i>] +[-o <i>n</i>] [-p <i>n</i>] [-f <i>bytes</i>] [-c <i>bytes</i>] <i>prog</i> +<h2><a name='sect2'>Description</a></h2> +<i>prog</i> consists of one or +more arguments. <p> +<b>chpst</b> changes the process state according to the given options, +and runs <i>prog</i>. +<h2><a name='sect3'>Options</a></h2> + +<dl> + +<dt><b>-u <i>[:]user[:group]</b> </i></dt> +<dd>setuidgid. Set uid and gid to the +<i>user</i>’s uid and gid, as found in <i>/etc/passwd</i>. If <i>user</i> is followed by a colon +and a <i>group</i>, set the gid to <i>group</i>’s gid, as found in <i>/etc/group</i>, instead +of <i>user</i>’s gid. If <i>group</i> consists of a colon-separated list of group names, +<b>chpst</b> sets the group ids of all listed groups. If <i>user</i> is prefixed with +a colon, the <i>user</i> and all <i>group</i> arguments are interpreted as uid and gids +respectivly, and not looked up in the password or group file. All initial +supplementary groups are removed. </dd> + +<dt><b>-U <i>[:]user[:group]</b> </i></dt> +<dd>envuidgid. Set the environment +variables $UID and $GID to the <i>user</i>’s uid and gid, as found in <i>/etc/passwd</i>. +If <i>user</i> is followed by a colon and a <i>group</i>, set $GID to the <i>group</i>’s gid, +as found in <i>/etc/group</i>, instead of <i>user</i>’s gid. If <i>user</i> is prefixed with a +colon, the <i>user</i> and <i>group</i> arguments are interpreted as uid and gid respectivly, +and not looked up in the password or group file. </dd> + +<dt><b>-b <i>argv0</b> </i></dt> +<dd>argv0. Run <i>prog</i> +with <i>argv0</i> as the 0th argument. </dd> + +<dt><b>-e <i>dir</b> </i></dt> +<dd>envdir. Set various +environment variables as specified by files in the directory <i>dir</i>: If <i>dir</i> +contains a file named <i>k</i> whose first line is <i>v</i>, <b>chpst</b> removes the environment +variable <i>k</i> if it exists, and then adds the environment variable <i>k</i> with +the value <i>v</i>. The name <i>k</i> must not contain =. Spaces and tabs at the end of +<i>v</i> are removed, and nulls in <i>v</i> are changed to newlines. If the file <i>k</i> is +empty (0 bytes long), <b>chpst</b> removes the environment variable <i>k</i> if it exists, +without adding a new variable. </dd> + +<dt><b>-/ <i>root</b> </i></dt> +<dd>chroot. Change the root directory to +<i>root</i> before starting <i>prog</i>. </dd> + +<dt><b>-n <i>inc</b> </i></dt> +<dd>nice. Add <i>inc</i> to the <i><b>nice</b>(2)</i> value before +starting <i>prog</i>. <i>inc</i> must be an integer, and may start with a minus or plus. +</dd> + +<dt><b>-l <i>lock</b> </i></dt> +<dd>lock. Open the file <i>lock</i> for writing, and obtain an exclusive lock +on it. <i>lock</i> will be created if it does not exist. If <i>lock</i> is locked by another +process, wait until a new lock can be obtained. </dd> + +<dt><b>-L <i>lock</b> </i></dt> +<dd>The same as -l, but +fail immediately if <i>lock</i> is locked by another process. </dd> + +<dt><b>-m <i>bytes</b> </i></dt> +<dd>limit memory. +Limit the data segment, stack segment, locked physical pages, and total +of all segment per process to <i>bytes</i> bytes each. </dd> + +<dt><b>-d <i>bytes</b> </i></dt> +<dd>limit data segment. +Limit the data segment per process to <i>bytes</i> bytes. </dd> + +<dt><b>-o <i>n</b> </i></dt> +<dd>limit open files. +Limit the number of open file descriptors per process to <i>n</i>. </dd> + +<dt><b>-p <i>n</b> </i></dt> +<dd>limit processes. +Limit the number of processes per uid to <i>n</i>. </dd> + +<dt><b>-f <i>bytes</b> </i></dt> +<dd>limit output size. Limit +the output file size to <i>bytes</i> bytes. </dd> + +<dt><b>-c <i>bytes</b> </i></dt> +<dd>limit core size. Limit the core +file size to <i>bytes</i> bytes. </dd> + +<dt><b>-v</b> </dt> +<dd>verbose. Print verbose messages to standard error. +This includes warnings about limits unsupported by the system. </dd> + +<dt><b>-P</b> </dt> +<dd>pgrphack. +Run <i>prog</i> in a new process group. </dd> + +<dt><b>-0</b> </dt> +<dd>Close standard input before starting +<i>prog</i>. </dd> + +<dt><b>-1</b> </dt> +<dd>Close standard output before starting <i>prog</i>. </dd> + +<dt><b>-2</b> </dt> +<dd>Close standard error +before starting <i>prog</i>. </dd> +</dl> + +<h2><a name='sect4'>Exit Codes</a></h2> +<b>chpst</b> exits 100 when called with wrong options. +It prints an error message and exits 111 if it has trouble changing the +process state. Otherwise its exit code is the same as that of <i>prog</i>. +<h2><a name='sect5'>Emulation</a></h2> +If +<b>chpst</b> is called as <b>envdir</b>, <b>envuidgid</b>, <b>pgrphack</b>, <b>setlock</b>, <b>setuidgid</b>, or +<b>softlimit</b>, it emulates the functionality of these programs from the daemontools +package respectively. +<h2><a name='sect6'>See Also</a></h2> +<i>sv(8)</i>, <i>runsv(8)</i>, <i>setsid(2)</i>, <i>runit(8)</i>, <i>runit-init(8)</i>, +<i>runsvdir(8)</i>, <i>runsvchdir(8)</i> <p> + <i>http://smarden.org/runit/</i><br> + <i>http://cr.yp.to/daemontools.html</i><br> + +<h2><a name='sect7'>Author</a></h2> +Gerrit Pape <pape@smarden.org> <p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Options</a></li> +<li><a name='toc4' href='#sect4'>Exit Codes</a></li> +<li><a name='toc5' href='#sect5'>Emulation</a></li> +<li><a name='toc6' href='#sect6'>See Also</a></li> +<li><a name='toc7' href='#sect7'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/debian b/runit-2.1.2/doc/debian new file mode 120000 index 0000000..8784129 --- /dev/null +++ b/runit-2.1.2/doc/debian @@ -0,0 +1 @@ +../etc/debian \ No newline at end of file diff --git a/runit-2.1.2/doc/dependencies.html b/runit-2.1.2/doc/dependencies.html new file mode 100644 index 0000000..452b56c --- /dev/null +++ b/runit-2.1.2/doc/dependencies.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit -service dependencies</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - service dependencies</h1> +<hr> +<i>runit</i>'s service supervision resolves dependencies for service daemons +designed to be run by a supervisor process automatically. +The service daemon (or the corresponding <tt>run</tt> scripts) should behave +as follows: +<ul> + <li>before providing the service, check if all services it depends on are + available. + If not, exit with an error, the supervisor will then try again. + <li>write all logs through <i>runit</i>'s logging facility. + The <a href="runsv.8.html">runsv</a> program takes care that all logs for + the service are written safely to disk. + Therefore there's no need to depend on a system logging service. + <li>optionally when the service is told to become down, take down other + services that depend on this one after disabling the service. +</ul> +If you want to run service daemons that do not support service supervision +as described above, please refer to +<a href="http://smarden.org/pape/djb/daemontools/noinit.html">this page</a> +about service dependencies I wrote some time ago. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/faq.html b/runit-2.1.2/doc/faq.html new file mode 100644 index 0000000..a2eae27 --- /dev/null +++ b/runit-2.1.2/doc/faq.html @@ -0,0 +1,438 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - Frequently asked questions</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - Frequently asked questions</h1> +<hr> +<a href="#what"> +What's runit, why is it that different +</a><br> +<a href="#help"> +I need some help with runit, what should I do +</a><br> +<!-- +<a href="#service"> +What is a service, what a service daemon +</a><br> +--> +<a href="#license"> +What's the license, is runit free software +</a><br> +<p> +<a href="#run"> +How do I run a service under runit service supervision +</a><br> +<a href="#create"> +How do I create a new service directory +</a><br> +<!-- +<a href="#log"> +What is a log service +</a><br> +--> +<a href="#createlog"> +How do I create a new service directory with an appendant log service +</a><br> +<a href="#tell"> +How do I tell runit about a new service +</a><br> +<a href="#control"> +How do I start, stop, or restart a service +</a><br> +<a href="#signal"> +How can I send signals to a service daemon +</a><br> +<a href="#status"> +How can I query the status of a service +</a><br> +<a href="#remove"> +How do I remove a service +</a><br> +<p> +<a href="#depends"> +How do I make a service depend on another service +</a><br> +<!-- +<a href="#strongdepends"> +How can I make a service affect a dependant service +</a><br> +--> +<p> +<a href="#runlevels"> +What about runlevels +</a><br> +<a href="#lsb"> +What about LSB init scripts compliance +</a><br> +<p> +<a href="#user"> +Is it possible to allow a user other than root to control a service +</a><br> +<a href="#userservices"> +Does runit support user-specific services? +</a><br> +<a href="#readonlyfs"> +Does runit work on a read-only filesystem +</a><br> + +<hr> +<a name="what"><h3> +What's runit, why is it that different +</h3></a> +What is this runit init scheme about? +Why is it that different from sysvinit and other init schemes? +<p> +Answer: +Please see the <a href="index.html">introduction</a>, and web page about +runit's <a href="benefits.html">benefits</a>. + +<hr> +<a name="help"><h3> +I need some help with runit, what should I do +</h3></a> +I have a question, runit is doing something wrong, or I'm doing something +wrong, what should I do? +<p> +Answer: +First see the documentation, especially this list of +<a href="faq.html">frequently asked questions</a>, and the man pages +if you have a question about a specific runit program. +If that still doesn't answer your question, try to search the +<a href="http://news.gmane.org/gmane.comp.sysutils.supervision.general"> +supervision mailing list archive</a>. +Finally, if this fails, feel free to post your question to the +<a href="http://skarnet.org/lists/">supervision mailing list</a>. + +<!-- +<hr> +<a name="service"><h3> +What is a service, what a service daemon +</h3></a> +The runit documentation talks about services and service daemons. +What actually is a service, and what a service daemon? +<p> +Answer: +--> + +<hr> +<a name="license"><h3> +What's the license, is runit free software +</h3></a> +I would like to distribute runit, in source and binary form. +Am I allowed to do so? +<p> +Answer: +runit is free software, it's licensed under a three-clause BSD alike +license. +See the file <tt>package/COPYING</tt> in the runit tarball. + +<hr> +<a name="run"><h3> +How do I run a service under runit service supervision +</h3></a> +I want a service to be run under runit service supervision, so that it's +automatically started on system boot, and supervised while system uptime. +How does that work? +<p> +Answer: +runit doesn't use the usual <tt>/etc/init.d/</tt> init script interface, +but uses a directory per service. +To integrate a service into the runit init scheme, +<a href="#create">create a service directory</a> for the service, and +<a href="#tell">tell runit</a> about it. + +<hr> +<a name="create"><h3> +How do I create a new service directory +</h3></a> +How do I create a service directory for the use with runit? +<p> +Answer: +Service directories usually are placed into the <tt>/etc/sv/</tt> +directory. +Create a new directory for your service in <tt>/etc/sv/</tt>, put a +<tt>./run</tt> script into it, and make the script executable. +Note that for the use with runit, +<a href="#service">service daemons</a> must not put themself into the +background, but must run in the foreground. +Here's a simple example for a <tt>getty</tt> service: +<pre> + $ cat /etc/sv/getty-2/run + #!/bin/sh + exec getty 38400 tty2 linux + $ +</pre> +Note the <tt>exec</tt> in the last line, it tells the shell that +interprets the script to replace itself with the service daemon +<tt>getty</tt>; this is necessary to make +<a href="#control">controlling the service</a> work properly. + +<!-- +<hr> +<a name="log"><h3> +What is a log service +</h3></a> +Additionally to supervising a service runit can supervise an appendant +log service. +What does that mean? +<p> +Answer: +--> + +<hr> +<a name="createlog"><h3> +How do I create a new service directory with an appendant log service +</h3></a> +How do I create a service directory with an appendant log service for the +use with runit? +<p> +Answer: +First <a href="#create">create the service directory</a> for the service. +Then create a subdirectory <tt>./log</tt> in the service directory, again +put a <tt>./run</tt> script into it, and make the script executable. +The <tt>./run</tt> script must run a service logging daemon, normally +this is the <a href="svlogd.8.html">svlogd</a> program. +See the <a href="runsv.8.html">runsv</a> man page for details. +Here's an example of a <tt>./log/run</tt> script: +<pre> + $ cat /etc/sv/socklog-klog/log/run + #!/bin/sh + exec chpst -ulog svlogd -tt ./main + $ +</pre> + +<hr> +<a name="tell"><h3> +How do I tell runit about a new service +</h3></a> +I created a service directory for a service that should run under runit +service supervision. +How do I tell runit about the new service directory, so that it picks +up and runs the service by default? +<p> +Answer: +Create a symbolic link in <tt>/service/</tt> pointing to the service +directory, runit will pick up the service within the next five seconds, +and automatically start it on system boot. +E.g.: +<pre> + # ln -s /etc/sv/getty-2 /service/ +</pre> + +<hr> +<a name="control"><h3> +How do I start, stop, or restart a service +</h3></a> +I want to stop a service temporarily, and probably restart is later, or +I want to have it restarted immediately. +How can I control a service running under runit service supervision? +<p> +Answer: +Use the <a href="sv.8.html">sv</a> program. +E.g., to restart the <tt>socklog-unix</tt> service, do: +<pre> + # sv restart socklog-unix +</pre> + +<hr> +<a name="signal"><h3> +How can I send signals to a service daemon +</h3></a> +I want to send a service daemon the HUP signal, to have it re-read its +configuration, or I want to send it the INT signal. +How can a send signals to a service daemon? +<p> +Answer: +Use the <a href="sv.8.html">sv</a> program. +E.g., to send the <tt>dhcp</tt> service the HUP signal, do: +<pre> + # sv hup dhcp +</pre> + +<hr> +<a name="status"><h3> +How can I query the status of a service +</a></h3> +I want to now the status of a service, whether it is up and available, +or down as requested, or so. +How can I find out this information? +<p> +Answer: +User the <a href="sv.8.html">sv</a> program. +E.g., to query or check the status of the <tt>socklog-unix</tt> service, +do: +<pre> + # sv status socklog-unix +</pre> +or +<pre> + # sv check socklog-unix +</pre> + +<hr> +<a name="remove"><h3> +How do I remove a service +</h3></a> +I want to remove a service that currently runs under runit service +supervision. +How do I tell runit? +<p> +Answer: +Remove the symbolic link in <tt>/service/</tt> pointing to the service +directory, runit recognizes the removed service within the next five +seconds, then stops the service, the optional log service, and finally the +supervisor process. +E.g.: +<pre> + # rm /service/getty-2 +</pre> + +<hr> +<a name="depends"><h3> +How do I make a service depend on another service +</a></h3> +I have a service that needs another service to be available before it can +start. +How can I tell runit about this dependency? +<p> +Answer: +Make sure in the <tt>./run</tt> script of the dependant service that the +service it depends on is available before the service daemon starts. +The <a href="sv.8.html">sv</a> program can be used for that. +E.g. the <tt>cron</tt> service wants the <tt>socklog-unix</tt> system +logging service to be available before starting the <tt>cron</tt> service +daemon, so no logs get lost: +<pre> + $ cat /etc/sv/cron/run + #!/bin/sh + sv start socklog-unix || exit 1 + exec cron -f + $ +</pre> +See also the <a href="dependencies.html">documentation</a>. + +<!-- +<hr> +<a name="strongdepends"><h3> +How can I make a service affect a dependant service +</a></h3> +<a href="#depends">This dependency</a> is not enough. +I have a service that needs to be stopped or restarted, whenever a service +it depends on stops or restarts. +How can I tell runit about that a service affects a dependant service in +such a way? +<p> +Answer: +First think about whether you really need this, it almost never should be +necessary. +If you really need this, +--> + +<hr> +<a name="runlevels"><h3> +What about runlevels +</a></h3> +Other init schemes support runlevels, what about runit? +<p> +Answer: +runit supports runlevels, even more flexible than traditional init schemes. +See <a href="runlevels.html">the documentation</a>. + +<hr> +<a name="lsb"><h3> +What about LSB init scripts compliance +</a></h3> +I know about the <a href="sv.8.html">sv</a> program to control a service, +but have applications that rely on the <tt>/etc/init.d/</tt> scripts +interface as defined through LSB. +Do I need to change the application to work with runit? +<p> +Answer: +You don't need to change the application. +The <a href="sv.8.html">sv</a> program supports the <tt>/etc/init.d/</tt> +script interface +<a href="http://refspecs.freestandards.org/LSB_2.1.0/LSB-generic/LSB-generic/iniscrptact.html"> +as defined through LSB</a>. +To make this script interface work for a service, create a symbolic link +in <tt>/etc/init.d/</tt>, named as the service daemon, pointing to the +<a href="sv.8.html">sv</a> program, e.g. for the <tt>cron</tt> service: +<pre> + # ln -s /bin/sv /etc/init.d/cron + # /etc/init.d/cron restart + ok: run: cron: (pid 5869) 0s + # +</pre> + +<hr> +<a name="user"><h3> +Is it possible to allow a user other than root to control a service +</a></h3> +Using the <a href="sv.8.html">sv</a> program to control a service, or query +its status informations, only works as root. +Is it possible to allow non-root users to control a service too? +<p> +Answer: +Yes, you simply need to adjust file system permissions for the +<tt>./supervise/</tt> subdirectory in the service directory. +E.g.: to allow the user <tt>burdon</tt> to control the service +<tt>dhcp</tt>, change to the <tt>dhcp</tt> service directory, and do +<pre> + # chmod 755 ./supervise + # chown burdon ./supervise/ok ./supervise/control ./supervise/status +</pre> +This works similarly with groups, of course. + +<hr> +<a name="userservices"><h3> +Does runit support user-specific services? +</a></h3> +It's very nice to simply +<a href="#tell">create symbolic links</a> to add system-wide services. +Does this work for user-specific services too? +<p> +Answer: +Yes. +E.g.: to provide the user <tt>floyd</tt> with facility to manage services +through <tt>~/service/</tt>, <a href="#createlog">create a service</a> +<tt>runsvdir-floyd</tt> with the following run script and a usual log/run +script, and <a href="#tell">tell runit</a> about the service +<pre> + #!/bin/sh + exec 2>&1 + exec chpst -ufloyd runsvdir /home/floyd/service +</pre> +Now <tt>floyd</tt> can create services on his own, and manage them through +symbolic links in <tt>~/service/</tt> to have them run under his user id. + +<hr> +<a name="readonlyfs"><h3> +Does runit work on a read-only filesystem +</a></h3> +On my system <tt>/etc/</tt> is mounted read-only by default. +runit uses many files in <tt>/etc/</tt> it needs to write to, like +<tt>/etc/runit/stopit</tt>, and the <tt>./supervise/</tt> +subdirectories in the service directories. +How can I make runit work on my system? +<p> +Answer: +Use symbolic links, runit deals with them well, even with dangling +symlinks. +E.g., make a ramdisk available at a moint point, say <tt>/var/run/</tt>, +and create symbolic links for the files and directories that runit needs +to write access to pointing into <tt>/var/run/</tt>: +<pre> + # ln -s /var/run/runit.stopit /etc/runit/stopit + # ln -s /var/run/sv.getty-2 /etc/sv/getty-2/supervise +</pre> + +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/index.html b/runit-2.1.2/doc/index.html new file mode 100644 index 0000000..85bb01b --- /dev/null +++ b/runit-2.1.2/doc/index.html @@ -0,0 +1,261 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - a UNIX init scheme with service supervision</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a> +<hr> +<h1>runit - a UNIX init scheme with service supervision</h1> +<hr> +<a href="install.html">How to install runit</a><br> +<a href="upgrade.html">Upgrading from previous versions of runit</a> +<p> +<a href="benefits.html">Benefits</a><br> +<a href="replaceinit.html">How to replace init</a><br> +<a href="useinit.html">How to use runit with current init</a><br> +<a href="usedietlibc.html">How to use dietlibc</a><br> +<a href="faq.html">Frequently asked questions</a><br> +<p> +<a href="runlevels.html">Runlevels</a><br> +<a href="dependencies.html">Service dependencies</a><br> +<a href="runscripts.html">A collection of run scripts</a><br> +<p> +<a href="runit.8.html">The <tt>runit</tt> program</a><br> +<a href="runit-init.8.html">The <tt>runit-init</tt> program</a><br> +<br> +<a href="sv.8.html">The <tt>sv</tt> program</a><br> +<br> +<a href="runsvdir.8.html">The <tt>runsvdir</tt> program</a><br> +<a href="runsvchdir.8.html">The <tt>runsvchdir</tt> program</a><br> +<a href="runsv.8.html">The <tt>runsv</tt> program</a><br> +<br> +<a href="svlogd.8.html">The <tt>svlogd</tt> program</a><br> +<br> +<a href="chpst.8.html">The <tt>chpst</tt> program</a><br> +<a href="utmpset.8.html">The <tt>utmpset</tt> program</a><br> +<hr> +<i>runit</i> is a +cross-platform Unix init scheme with service supervision, a replacement for +<a href="ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/">sysvinit</a>, +and other init schemes. +It runs on <b>GNU/Linux</b>, <b>*BSD</b>, <b>MacOSX</b>, <b>Solaris</b>, +and can easily be adapted to other Unix operating systems. +If <i>runit</i> runs for you on any other operating system, please +<a href="mailto:supervision@list.skarnet.org">let me know</a>. +<hr> +<i>runit</i> is discussed on the +<a href="http://skarnet.org/lists/#supervision"> +<supervision@list.skarnet.org></a> +mailing list. +Please contact this list and not me privately. +<p> +To subscribe send an empty email to +<a href="mailto:supervision-subscribe@list.skarnet.org"> +<supervision-subscribe@list.skarnet.org></a>. +<p> +Mailing list archives are available at +<a href="http://skarnet.org/lists/archive.cgi?2">skarnet.org</a>, and +<a href="http://news.gmane.org/gmane.comp.sysutils.supervision.general"> +gmane.org</a>. +<hr> +The program <a href="runit.8.html">runit</a> is intended to run as Unix +process no 1, it is automatically started by the +<a href="runit-init.8.html">runit-init</a> <tt>/sbin/init</tt>-replacement +if this is started by the kernel. +<p> +<a href="runit.8.html">runit</a> performs the system's <i>booting</i>, +<i>running</i> and <i>shutting down</i> in <b>three stages</b>: +<ul> + <li><b>Stage 1:</b><br> + <i>runit</i> starts <tt>/etc/runit/1</tt> and waits for it to + 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 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 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 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 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>. +<p> +The program <a href="runit-init.8.html">runit-init</a> is intended to +replace <tt>/sbin/init</tt>. +The command <b><tt>init 0</tt></b> tells <i>runit</i> to halt the system, +and <b><tt>init 6</tt></b> to reboot. +<a href="runlevels.html">Runlevels</a> are handled through the +<a href="runsvdir.8.html">runsvdir</a> and +<a href="runsvchdir.8.html">runsvchdir</a> programs. +Service <a href="dependencies.html">dependencies</a> are resolved +automatically. +<p> +<i>runit</i> is optimized for reliability and small size. +The amount of code in process no 1 should be minimal. +<hr> +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. +Please read the list of +<a href="faq.html">Frequently asked questions with answers</a>. +<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 +statically linked <tt>runit</tt> binary of 8.5k size and this +<tt>ps axuw</tt> output on my system: +<pre> + USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND + root 1 0.0 0.0 20 16 ? S 2002 0:02 runit +</pre> +I recommend doing this; for instructions, see +<a href="usedietlibc.html">How to use dietlibc</a>. +<hr> +The following distributions are known to include or package <i>runit</i>: +<ul> +<li><a href="http://packages.qa.debian.org/runit"> +Debian GNU/Linux</a> (as alternative init scheme) +<li><a href="http://www.freshports.org/sysutils/runit/"> +FreeBSD</a> +<li><a href="http://www.openbsd.org/cgi-bin/cvsweb/ports/sysutils/runit/"> +OpenBSD</a> +<li><a href="http://pkgsrc.se/wip/runit/"> +NetBSD</a> +<li><a href="http://packages.ubuntu.com/runit"> +Ubuntu</a> (as alternative init scheme) +<li><a href="http://packages.gentoo.org/package/sys-process/runit"> +Gentoo</a> +<li><a href="https://code.google.com/p/runit-for-lfs/"> +Linux from Scratch</a> +<li><a href="http://www.finnix.org/"> +Finnix</a> +<li><a href="http://www.smeserver.org/"> +SME server</a> +<li><a href="http://linux-vserver.org/Running_runit-supervised_services_inside_a_vserver"> +Linux-VServer</a> +<li><a href="http://www.t2-project.org/"> +T2</a> +<li><a href="http://www.gobolinux.org/"> +GoboLinux</a> +<li><a href="http://www.dragora.org/"> +Dragora GNU/Linux</a> (as default init scheme) +<li><a href="https://wiki.archlinux.org/index.php/Runit"> +ArchLinux</a> +<li><a href="http://www.opensde.org/"> +OpenSDE</a> +<li><a href="http://zinux.cynicbytrade.com/"> +Zinux Linux</a> (as default init scheme) +<li><a href="http://deepofix.org/"> +deepOfix Mail Server</a> (as default init scheme) +</ul> +If you know of more distributions, please +<a href="mailto:supervision@list.skarnet.org">let me know</a>. +<hr> +<b><i>runit</i> in use</b>: +I replaced <i>sysvinit</i> successfully with <i>runit</i> on several server +systems and a laptop running Debian/GNU Linux sarge, woody, and potato. +Here is an example: +<pre> + # strings /proc/1/exe |grep Id + $Id: runit.c,v 1.7 2002/02/13 09:59:52 pape Exp $ + # uptime + 11:59:13 up 365 days, 23:22, 3 users, load average: 0.01, 0.02, 0.00 + # ps axuw |head -n20 + USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND + root 1 0.0 0.0 20 16 ? S 2002 0:07 runit + root 2 0.0 0.0 0 0 ? SW 2002 0:00 [keventd] + root 3 0.0 0.0 0 0 ? SWN 2002 0:51 [ksoftirqd_CPU0] + root 4 0.0 0.0 0 0 ? SW 2002 144:38 [kswapd] + root 5 0.0 0.0 0 0 ? SW 2002 0:08 [bdflush] + root 6 0.0 0.0 0 0 ? SW 2002 7:24 [kupdated] + root 168 0.0 0.0 1652 168 ? S 2002 0:27 /usr/sbin/cron + root 174 0.0 0.0 36 24 ? S 2002 1:06 runsvdir /var/service log: ............................................................................................... + root 176 0.0 0.0 20 20 ? S 2002 0:00 runsv qmail-send + root 177 0.0 0.0 20 20 ? S 2002 0:00 runsv getty-5 + root 178 0.0 0.0 20 20 ? S 2002 0:00 runsv getty-4 + root 179 0.0 0.0 20 20 ? S 2002 0:00 runsv getty-3 + root 180 0.0 0.0 20 20 ? S 2002 0:00 runsv getty-2 + root 182 0.0 0.0 20 20 ? S 2002 0:00 runsv socklog-unix + root 183 0.0 0.0 1256 4 tty5 S 2002 0:00 /sbin/getty 38400 tty5 linux + root 184 0.0 0.0 1256 4 tty3 S 2002 0:00 getty 38400 tty3 linux + root 185 0.0 0.0 20 20 ? S 2002 0:00 runsv socklog-klog + root 186 0.0 0.0 20 20 ? S 2002 0:00 runsv ssh + root 187 0.0 0.0 1256 4 tty4 S 2002 0:00 getty 38400 tty4 linux + # pstree + runit-+-bdflush + |-cron + |-gcache + |-keventd + |-ksoftirqd_CPU0 + |-kswapd + |-kupdated + `-runsvdir-+-runsv-+-multilog + | `-qmail-send-+-qmail-clean + | |-qmail-lspawn + | `-qmail-rspawn---qmail-remote + |-4*[runsv---getty] + |-2*[runsv-+-multilog] + | `-socklog] + |-runsv-+-multilog + | `-sshd-+-sshd---sshd---bash---bash---pstree + | `-sshd---sshd---rsync + |-runsv---clockspeed + |-runsv-+-dnscache + | `-multilog + |-runsv---apache-ssl-+-9*[apache-ssl] + | |-gcache + | `-4*[multilog] + |-7*[runsv-+-multilog] + | `-tcpserver] + |-4*[runsv-+-multilog] + | `-tinydns] + |-runsv---uncat + |-2*[runsv-+-multilog] + | `-tcpsvd] + |-runsv-+-svlogd + | `-tcpsvd-+-smtpfront-qmail + | `-smtpfront-qmail---qmail-queue + `-runsv-+-svlogd + `-tcpsvd---bincimap-up---bincimapd +</pre> +<hr> +See <a href="http://smarden.org/runit/">http://smarden.org/runit/</a> +for recent informations. +<hr> +Related links: +<ul> +<li><a href="http://www.fefe.de/minit/"> +minit</a> - a small yet feature-complete init +<li><a href="http://multivac.cwru.edu/svscan-1/"> +svscan as process 1</a> - by Paul Jarc +<li><a href="ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/"> +sysvinit</a> - source code +<li><a href="http://www.freebsd.org/cgi/cvsweb.cgi/src/sbin/init/"> +FreeBSD's init</a> - CVS repository +<li><a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sbin/init/"> +NetBSD's init</a> - CVS repository +<li><a href="http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/init/"> +OpenBSD's init</a> - CVS repository +<li><a href="http://www.atnf.csiro.au/~rgooch/linux/boot-scripts/"> +Linux Boot Scripts</a> - by Richard Gooch +</ul> +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/install.html b/runit-2.1.2/doc/install.html new file mode 100644 index 0000000..fb3b2c4 --- /dev/null +++ b/runit-2.1.2/doc/install.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - installation</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - installation</h1> +<hr> +<i>runit</i> installs into +<a href="http://cr.yp.to/slashpackage.html">/package</a>. +If you don't have a <tt>/package</tt> directory, create it now: +<pre> + # mkdir -p /package + # chmod 1755 /package +</pre> +Download +<a href="runit-2.1.2.tar.gz">runit-2.1.2.tar.gz</a> into <tt>/package</tt> +and unpack the archive +<pre> + # cd /package + # gunzip runit-2.1.2.tar + # tar -xpf runit-2.1.2.tar + # rm runit-2.1.2.tar + # cd admin/runit-2.1.2 +</pre> +On MacOSX, do +<pre> + # echo 'cc -Xlinker -x' >src/conf-ld + # cp src/Makefile src/Makefile.old + # sed -e 's/ -static//' <src/Makefile.old >src/Makefile +</pre> +Now compile and install the <i>runit</i> programs +<pre> + # package/install +</pre> +If you want to make the man pages available in the <tt>/usr/local/man/</tt> +hierarchy, do: +<pre> + # package/install-man +</pre> +To report success: +<pre> + # mail pape-runit-2.1.2@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. +<p> +Refer to <a href="replaceinit.html">replacing init</a> for +replacing <i>init</i> with <i>runit</i>, or to +<a href="useinit.html">use with traditional init</a> for running +<i>runit</i>'s service supervision with your system's current <i>init</i> +scheme. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/replaceinit.html b/runit-2.1.2/doc/replaceinit.html new file mode 100644 index 0000000..70f6f7d --- /dev/null +++ b/runit-2.1.2/doc/replaceinit.html @@ -0,0 +1,254 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - replacing init</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a> +<hr> +<h1>runit - replacing init</h1> +<hr> +<a href="#sysv">How to replace sysvinit on GNU/Linux</a><br> +<a href="#bsd">How to replace init on *BSD</a><br> +<a href="#macosx">How to replace init on MacOSX</a><br> +<a href="#solaris">How to replace init on Solaris</a> +<hr> +<a name="sysv"><h2>Replacing sysvinit (GNU/Linux)</h2></a> +Follow these steps to migrate from <i>sysvinit</i> to <i>runit</i> on +<a href="http://www.debian.org/releases/woody/">Debian GNU/Linux (woody)</a>. +The <tt>/sbin/init</tt> binary is not replaced until step 6, <i>runit</i> is +the default Unix process no 1 after step 7. +<p> +If you have installed the precompiled Debian package, start at step 3. +<h3>Step 1: The three stages</h3> +<i>runit</i> looks for the three stages implementing the system's +<i>booting</i>, <i>running</i> and <i>shutdown</i> in <tt>/etc/runit/1</tt>, +<tt>/etc/runit/2</tt> and <tt>/etc/runit/3</tt>, create the files now: +<pre> + # mkdir -p /etc/runit + # cp -p /package/admin/runit/etc/debian/[123] /etc/runit/ +</pre> +Create also a getty service directory: +<pre> + # mkdir -p /etc/sv/getty-5 + # cp -p /package/admin/runit/etc/debian/getty-tty5/run /etc/sv/getty-5/ + # cp -p /package/admin/runit/etc/debian/getty-tty5/finish /etc/sv/getty-5/ +</pre> +If you want <i>runit</i> to handle the ctrl-alt-del keyboard request, do: +<pre> + # cp -p /package/admin/runit/etc/debian/ctrlaltdel /etc/runit/ +</pre> +<h3>Step 2: The runit programs</h3> +The <i>runit</i> programs must reside on the root partition, copy them to +<tt>/sbin</tt>: +<pre> + # cp -p /package/admin/runit/command/runit* /sbin/ +</pre> +<h3>Step 3: The getties</h3> +At least one getty must run in stage 2 so that you are able to login. +Choose a free <tt>tty</tt>, say <tt>tty5</tt>, where <i>sysvinit</i> is not +running any getty (edit <tt>/etc/inittab</tt> and <tt>kill -HUP 1</tt> if +needed), and tell <a href="runsvdir.8.html">runsvdir</a> about the getty-5 +<i>service</i>: +<pre> + # mkdir -p /service + # ln -s /etc/sv/getty-5 /service/ +</pre> +Start <i>runit</i>'s stage 2 for testing: +<pre> + # /etc/runit/2 & +</pre> +And check that the getty is running. +<h3>Step 4: Reboot into runit for testing</h3> +Boot your system with <i>runit</i> for the first time. +This does not change the default boot behavior of your system, <i>lilo</i> +will be told to use <i>runit</i> just once: +<ul> +<li>reboot the system +<li>enter the following on the lilo prompt:<br> +<tt>init=/sbin/runit-init</tt> +<li>watch the console output while <i>runit</i> boots up the system +<li>switch to <tt>tty5</tt> when stage 2 is reached, a <tt>getty</tt> +should run there, you are able to login. +</ul> +If you are not using <i>lilo</i> as boot loader, refer to the documentation +of your boot loader on how to pass <tt>init=/sbin/runit-init</tt> to the +kernel. +<h3>Step 5: Service migration</h3> +The goal is to migrate all services from <i>sysvinit</i> scheme to the +<i>runit</i> service supervision design; take a look at these +<a href="runscripts.html">run scripts</a> for popular services. +The migration can be done smoothly. +For those services that are not migrated to use <tt>run</tt> scripts yet, +add the corresponding <tt>init</tt>-script startup to <tt>/etc/runit/1</tt>, +e.g.: +<pre> + #!/bin/sh + # one time tasks + + /etc/init.d/kerneld start + /etc/init.d/rmnologin + + touch /etc/runit/stopit + chmod 0 /etc/runit/stopit +</pre> +It is possible to just add <tt>/etc/init.d/rc 2</tt> for having all services +from the former runlevel 2 started as one time tasks, but keep the goal above +in mind, supervising services has great advantages. +<p> +To migrate a service, +<a href="faq.html#create">create a service directory</a>, disable the service +if it is running, disable the service in <tt>/etc/rc.conf</tt> or remove the +service startup from the <tt>/etc/rc.*</tt> scripts and +<a href="faq.html#tell">tell runsvdir</a> about the new service. +<p> +Repeat step 4 and 5, using <tt><b>/sbin/runit-init 6</b></tt> to reboot the +system, until you are satisfied with your services startup. +If anything goes wrong, reboot the system into the default <i>sysvinit</i> +<tt>/sbin/init</tt> and repair the <i>runit</i> stages, then start again at +step 4. +<h3>Step 6: Replace /sbin/init</h3> +Now it is time to replace the <i>sysvinit</i> <tt>/sbin/init</tt> binary: +<pre> + # mv /sbin/init /sbin/init.sysv + # ln -s runit-init /sbin/init +</pre> +<h3>Step 7: Final reboot</h3> +The last step is to do the final reboot to boot the system with the new +default Unix process no 1 <i>runit</i>. +<pre> + # init 6 +</pre> +To report success: +<pre> + # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-2.1.2@smarden.org +</pre> +<hr> + +<a name="bsd"><h2>Replacing init (*BSD)</h2></a> +Follow these steps to migrate from <i>init</i> to <i>runit</i> on +<a href="http://www.openbsd.org/">OpenBSD 2.9</a> or +<a href="http://www.freebsd.org/">FreeBSD 4.4</a>. +The <tt>/sbin/init</tt> binary is not replaced until step 4. +<h3>Step 1: The three stages</h3> +<i>runit</i> looks for the three stages implementing the system's +<i>booting</i>, <i>running</i> and <i>shutdown</i> in <tt>/etc/runit/1</tt>, +<tt>/etc/runit/2</tt> and <tt>/etc/runit/3</tt> respectively. +Create the scripts now: +<pre> + # mkdir -p /etc/runit + +OpenBSD 2.9: + # cp -p /package/admin/runit/etc/openbsd/[123] /etc/runit/ + +FreeBSD 4.4: + # cp -p /package/admin/runit/etc/freebsd/[123] /etc/runit/ +</pre> +Remove the <tt>svscanboot</tt> startup from <tt>/etc/rc.local</tt> by +deleting the line <tt>csh -cf '/command/svscanboot &'</tt> (this normally +is the last one); <i>runit</i> will start +<a href="runsvdir.8.html">runsvdir</a> in stage 2 after running +<tt>rc.local</tt> in stage 1. +<pre> + # vi /etc/rc.local +</pre> +<h3>Step 2: The runit programs</h3> +The <i>runit</i> programs must reside on the root partition, install them +into <tt>/sbin</tt>: +<pre> + # install -m0500 /package/admin/runit/command/runit* /sbin/ +</pre> +<h3>Step 3: The getties</h3> +At least one getty must run in stage 2 so that you are able to login. +To have it run on the virtual console no 5, create the getty-5 service +directory: +<pre> + # mkdir -p /etc/sv/getty-5 + +OpenBSD 2.9: + # cp -p /package/admin/runit/etc/openbsd/getty-ttyC4/run /etc/sv/getty-5/ + # cp -p /package/admin/runit/etc/openbsd/getty-ttyC4/finish /etc/sv/getty-5/ + +FreeBSD 4.4: + # cp -p /package/admin/runit/etc/freebsd/getty-ttyv4/run /etc/sv/getty-5/ + # cp -p /package/admin/runit/etc/freebsd/getty-ttyv4/finish /etc/sv/getty-5/ +</pre> +and tell <a href="runsvdir.8.html">runsvdir</a> about the <tt>getty-5</tt> +<i>service</i>: +<pre> + # mkdir -p /service + # ln -s /etc/sv/getty-5 /service/ +</pre> +Start <i>runit</i>'s stage 2 for testing: +<pre> + # /etc/runit/2 & +</pre> +And check that the getty is running. +<h3>Step 4: Replace the <tt>/sbin/init</tt> binary</h3> +Before replacing the <tt>init</tt> binary, make sure that you are able +to boot your system alternatively, e.g. with a boot floppy, to restore the +former <tt>/sbin/init</tt> if anything goes wrong. +<p> +Make a backup copy of the current <tt>/sbin/init</tt> program and replace +it with <tt>/sbin/runit-init</tt>: +<pre> + # cp -p /sbin/init /sbin/init.bsd + # install /sbin/runit-init /sbin/init +</pre> +Boot your system with <i>runit</i> for the first time: +<pre> + # reboot +</pre> +Watch the console output while <i>runit</i> boots up the system. +Switch to the virtual console 5 (CTRL-ALT-F5) when stage 2 is reached, a +getty should run there, you are able to login. +<p> +Use <b>init 6</b> to reboot and <b>init 0</b> to halt a system that runs +<i>runit</i>. +This will cause <i>runit</i> to enter stage 3 which runs +<tt>/sbin/reboot</tt> or <tt>/sbin/halt</tt> as last command. +<p> +To report success: +<pre> + # ( uname -a ; cat /etc/runit/[123] ) |mail pape-runit-2.1.2@smarden.org +</pre> +<h3>Step 5: Service migration</h3> +The goal is to migrate all services from <i>/etc/rc.*</i> scheme to the +<i>runit</i> service supervision design; take a look at these +<a href="runscripts.html">run scripts</a> for popular services. +The migration can be done smoothly. +By default <i>runit</i> runs the <tt>/etc/rc</tt> scripts in stage 1 as a +one time task, so the services are started automatically: +<pre> + #!/bin/sh + # system one time tasks + + /bin/sh /etc/rc autoboot + + touch /etc/runit/stopit + chmod 0 /etc/runit/stopit +</pre> +To migrate a service, +<a href="faq.html#create">create a service directory</a>, disable the service +if it is running, disable the service in <tt>/etc/rc.conf</tt> or remove the +service startup from the <tt>/etc/rc.*</tt> scripts and +<a href="faq.html#tell">tell runsvdir</a> about the new service. +<hr> + +<a name="macosx"><h2>Replacing init on MacOSX</h2></a> +Replacing init on MacOSX is not yet supported. +Please refer to the <a href="useinit.html">instructions</a> on how to use +<i>runit</i> service supervision with the MacOSX init scheme. +<hr> + +<a name="solaris"><h2>Replacing init on Solaris</h2></a> +Replacing init on Solaris is not yet supported. +Please refer to the <a href="useinit.html">instructions</a> on how to use +<i>runit</i> service supervision with the Solaris sysvinit scheme. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/runit-init.8.html b/runit-2.1.2/doc/runit-init.8.html new file mode 100644 index 0000000..014d2f1 --- /dev/null +++ b/runit-2.1.2/doc/runit-init.8.html @@ -0,0 +1,60 @@ + + + +<html> +<head> +<title>runit-init(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +init - a UNIX process no 1 +<h2><a name='sect1'>Synopsis</a></h2> +<b>init</b> [ 0 | 6 ] +<h2><a name='sect2'>Description</a></h2> +<b>runit-init</b> +is the first process the kernel starts. If <b>runit-init</b> is started as process +no 1, it runs and replaces itself with <i><b>runit</b>(8)</i>. <p> +If <b>runit-init</b> is started +while the system is up, it must be either called as <b>init 0</b> or <b>init 6:</b> +<dl> + +<dt><b>init +0</b> </dt> +<dd>tells the Unix process no 1 to shutdown and halt the system. To signal +<i><b>runit</b>(8)</i> the system halt request, <b>runit-init</b> removes all permissions of +the file <i>/etc/runit/reboot</i> (chmod 0), and sets the execute by owner permission +of the file <i>/etc/runit/stopit</i> (chmod 100). Then a CONT signal is sent to +<i><b>runit</b>(8)</i>. </dd> + +<dt><b>init 6</b> </dt> +<dd>tells the Unix process no 1 to shutdown and reboot the +system. To signal <i><b>runit</b>(8)</i> the system reboot request, <b>runit-init</b> sets the +execute by owner permission of the files <i>/etc/runit/reboot</i> and <i>/etc/runit/stopit</i> +(chmod 100). Then a CONT signal is sent to <i><b>runit</b>(8)</i>. </dd> +</dl> + +<h2><a name='sect3'>Exit Codes</a></h2> +<b>runit-init</b> +returns 111 on error, 0 in all other cases. +<h2><a name='sect4'>See Also</a></h2> +<i>runit(8)</i>, <i>runsvdir(8)</i>, +<i>runsvchdir(8)</i>, <i>sv(8)</i>, <i>runsv(8)</i>, <i>chpst(8)</i>, <i>utmpset(8)</i>, <i>svlogd(8)</i> <p> +<i>http://smarden.org/runit/</i> + +<h2><a name='sect5'>Author</a></h2> +Gerrit Pape <pape@smarden.org> <p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Exit Codes</a></li> +<li><a name='toc4' href='#sect4'>See Also</a></li> +<li><a name='toc5' href='#sect5'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/runit.8.html b/runit-2.1.2/doc/runit.8.html new file mode 100644 index 0000000..6c46b39 --- /dev/null +++ b/runit-2.1.2/doc/runit.8.html @@ -0,0 +1,74 @@ + + + +<html> +<head> +<title>runit(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +runit - a UNIX process no 1 +<h2><a name='sect1'>Synopsis</a></h2> +<b>runit</b> +<h2><a name='sect2'>Description</a></h2> +<b>runit</b> must be run +as Unix process no 1. It performs the system’s booting, running, and shutdown +in three stages: +<h2><a name='sect3'>Stage 1</a></h2> +<b>runit</b> runs <i>/etc/runit/1</i> and waits for it to terminate. +The system’s one time tasks are done here. <i>/etc/runit/1</i> has full control +of <i>/dev/console</i> to be able to start an emergency shell if the one time +initialization tasks fail. If <i>/etc/runit/1</i> crashes, or exits 100, <b>runit</b> +will skip stage 2 and enter stage 3. +<h2><a name='sect4'>Stage 2</a></h2> +<b>runit</b> runs <i>/etc/runit/2</i>, which +should not return until system shutdown; if it crashes, or exits 111, it +will be restarted. Normally <i>/etc/runit/2</i> starts <i><b>runsvdir</b>(8)</i>. <b>runit</b> is able +to handle the ctrl-alt-del keyboard request in stage 2, see below. +<h2><a name='sect5'>Stage 3</a></h2> +If +<b>runit</b> is told to shutdown the system, or stage 2 returns, it terminates +stage 2 if it is running, and runs <i>/etc/runit/3</i>. The systems tasks to shutdown +and possibly halt or reboot the system are done here. If stage 3 returns, +<b>runit</b> checks if the file <i>/etc/runit/reboot</i> exists and has the execute by +owner permission set. If so, the system is rebooted, it’s halted otherwise. + +<h2><a name='sect6'>Ctrl-alt-del</a></h2> +If <b>runit</b> receives the ctrl-alt-del keyboard request and the file +<i>/etc/runit/ctrlaltdel</i> exists and has the execute by owner permission set, +<b>runit</b> runs <i>/etc/runit/ctrlaltdel</i>, waits for it to terminate, and then sends +itself a CONT signal. +<h2><a name='sect7'>Signals</a></h2> +<b>runit</b> only accepts signals in stage 2. <p> +If <b>runit</b> +receives a CONT signal and the file <i>/etc/runit/stopit</i> exists and has the +execute by owner permission set, <b>runit</b> is told to shutdown the system. <p> +if +<b>runit</b> receives an INT signal, a ctrl-alt-del keyboard request is triggered. + +<h2><a name='sect8'>See Also</a></h2> +<i>runit-init(8)</i>, <i>runsvdir(8)</i>, <i>runsvchdir(8)</i>, <i>sv(8)</i>, <i>runsv(8)</i>, <i>chpst(8)</i>, +<i>utmpset(8)</i>, <i>svlogd(8)</i> <p> +<i>http://smarden.org/runit/</i> +<h2><a name='sect9'>Author</a></h2> +Gerrit Pape <pape@smarden.org> +<p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Stage 1</a></li> +<li><a name='toc4' href='#sect4'>Stage 2</a></li> +<li><a name='toc5' href='#sect5'>Stage 3</a></li> +<li><a name='toc6' href='#sect6'>Ctrl-alt-del</a></li> +<li><a name='toc7' href='#sect7'>Signals</a></li> +<li><a name='toc8' href='#sect8'>See Also</a></li> +<li><a name='toc9' href='#sect9'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/runlevels.html b/runit-2.1.2/doc/runlevels.html new file mode 100644 index 0000000..c0e49c3 --- /dev/null +++ b/runit-2.1.2/doc/runlevels.html @@ -0,0 +1,98 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - runlevels</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - runlevels</h1> +<hr> +<a href="#prepare">Prepare runit for using runlevels</a><br> +<a href="#switch">Switching runlevels</a><br> +<a href="#create">Creating runlevels</a> +<hr> +<a name="prepare"><h3>Prepare runit</h3></a> +If not yet done, configure your system to use +<a href="runit.8.html">runit</a> as process no 1 by following the +<a href="replaceinit.html">instructions</a>. +<p> +Create the following directories and symbolic links: +<pre> + # mkdir -p /etc/runit/runsvdir/default + # mkdir -p /etc/runit/runsvdir/single + # ln -s /etc/sv/getty-5 /etc/runit/runsvdir/single/ + # ln -s default /etc/runit/runsvdir/current +</pre> +Copy the contents of <tt>/service/</tt> to +<tt>/etc/runit/runsvdir/current/</tt> and replace <tt>/service/</tt> +with a symbolic link: +<pre> + # cp -pR /service/* /etc/runit/runsvdir/current/ + # mv -f /service /service.old && \ + ln -s /etc/runit/runsvdir/current /service +</pre> +You have now created two runlevels: <tt>default</tt> and <tt>single</tt>. +The <tt>current</tt> runlevel is <tt>default</tt>. +It is safe to remove <tt>/service.old/</tt> if you don't need it anymore. +<p> +Finally edit <tt>/etc/runit/2</tt> to set the <tt>default</tt> runlevel when +stage 2 starts: +<pre> + $ cat /etc/runit/2 + #!/bin/sh + PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin + + <b>runsvchdir default >/dev/null</b> + + exec env - PATH=$PATH \ + runsvdir /service 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................' +</pre> +<hr> +<a name="switch"><h3>Switching runlevels</h3></a> +Switching runlevels with <i>runit</i> is done by switching the directory the +<a href="runsvdir.8.html">runsvdir</a> program is running in. +This is done by the <a href="runsvchdir.8.html">runsvchdir</a> program, e.g. +to switch to the <tt>single</tt> user runlevel, do: +<pre> + # runsvchdir single +</pre> +To switch back to the <tt>default</tt> runlevel, do: +<pre> + # runsvchdir default +</pre> +See <a href="runsvdir.8.html">the runsvdir program</a> for a description of +what happens when <i>runsvdir</i> sees the directory changed. +Note that there is no guarantee that all services from the <tt>previous</tt> +runlevel will stop, the <a href="runsv.8.html">runsv</a> processes have sent +the service daemons a SIGTERM and wait for them to terminate. +You can check the status of the <tt>previous</tt> runlevel through +<tt>/etc/runit/runsvdir/previous/</tt>. +<hr> +<a name="create"><h3>Creating new runlevels</h3></a> +To create a new runlevel, simply create a new directory in +<tt>/etc/runit/runsvdir/</tt>. +The name of the directory is the name of the new runlevel. +The name must not start with a dot and must not be <tt>current</tt>, +<tt>current.new</tt>, or <tt>previous</tt>, e.g.: +<pre> + # mkdir /etc/runit/runsvdir/maintenance +</pre> +Add the services you want to run in the runlevel <tt>maintenance</tt> to the +newly created directory, e.g.: +<pre> + # ln -s /etc/sv/getty-5 /etc/runit/runsvdir/maintenance/ + # ln -s /etc/sv/ssh /etc/runit/runsvdir/maintenance/ + # ln -s /etc/sv/dnscache /etc/runit/runsvdir/maintenance/ +</pre> +If you want to switch to the runlevel <tt>maintenance</tt>, do: +<pre> + # runsvchdir maintenance +</pre> +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/runscripts.html b/runit-2.1.2/doc/runscripts.html new file mode 100644 index 0000000..f832b63 --- /dev/null +++ b/runit-2.1.2/doc/runscripts.html @@ -0,0 +1,1058 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - collection of run scripts</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<a href="replaceinit.html">How to replace init</a> +<hr> +<h1>runit - collection of run scripts</h1> +<hr> +This is a collection of <tt>run</tt> scripts for popular services to have +them monitored by the +<a href="http://cr.yp.to/daemontools.html">daemontools</a> or +<a href="http://smarden.org/runit/">runit</a> package. +If you have additional run scripts or one of these run scripts works for you on +an operating system not stated here, please +<a href="mailto:supervision@list.skarnet.org">let me know</a>. +<p> +Thanks go to the following people for contributing run scripts: +<small> +Alessandro Bono, Robin S. Socha, Claus Alboege, Paul Jarc, clemens fischer, +Jesse Cablek, Lukas Beeler, Thomas Baden, Ralf Hildebrandt, Antonio Dias, +Erich Schubert, Lang Martin, Tomasz Nidecki, Marek Bartnikowski, +Thomas Schwinge, Gael Canal, Woon Wai Keen, Richard A Downing, Phil Genera, +Stefan Karrmann, Kevin Berry, Karl Chen, Sascha Huedepohl, Jason Smith, +Kevin, marlowe, ed neville, xavier dutoit. +</small> +<p> +See also +<a href="http://thedjbway.org/services.html">here</a> for some more run +scripts. +<hr> +<a href="#atftpd">atftpd</a><br> +<a href="#apache">apache</a><br> +<a href="#apache2">apache2</a><br> +<a href="#atd">atd</a><br> +<a href="#bind9">bind9</a><br> +<a href="#boa">boa</a><br> +<a href="#cfengine">cfengine</a><br> +<a href="#cfsd">cfsd</a><br> +<a href="#chrony">chrony</a><br> +<a href="#clamav">clamav</a><br> +<a href="#clamsmtpd">clamsmtpd</a><br> +<a href="#courier-imap">courier-imap</a><br> +<a href="#cron">cron</a><br> +<a href="#cups">cups</a><br> +<a href="#dhclient">dhclient</a><br> +<a href="#dhcpcd">dhcpcd</a><br> +<a href="#dhcpd">dhcpd</a><br> +<a href="#dictd">dictd</a><br> +<a href="#dropbear">dropbear</a><br> +<a href="#exim">exim</a><br> +<a href="#expireproctitle">expireproctitle</a><br> +<a href="#fam">fam</a><br> +<a href="#fcron">fcron</a><br> +<a href="#fetchmail">fetchmail</a><br> +<a href="#gdm">gdm</a><br> +<a href="#getty">getty</a><br> +<a href="#gpm">gpm</a><br> +<a href="#hotwayd">hotwayd</a><br> +<a href="#identd">identd</a><br> +<a href="#inn">inn</a><br> +<a href="#jabberd">jabberd</a><br> +<a href="#junkbuster">junkbuster</a><br> +<a href="#kdm">kdm</a><br> +<a href="#keepalived">keepalived</a><br> +<a href="#klogd">klogd</a><br> +<a href="#leafnode">leafnode</a><br> +<a href="#loglinuxkernel">logging Linux kernel messages</a><br> +<a href="http://multivac.cwru.edu./fdtools/grabconsole/"> +logging console messages</a><br> +<a href="#mdadm">mdadm</a><br> +<a href="#minidentd">minidentd</a><br> +<a href="#mpd">mpd</a><br> +<a href="#nscd">nscd</a><br> +<a href="#ntpd">ntpd</a><br> +<a href="#nullidentd">nullidentd</a><br> +<a href="#polipo">polipo</a><br> +<a href="#pop3-ssl">pop3-ssl</a><br> +<a href="#pop3vscan">pop3vscan</a><br> +<a href="#portmap">portmap</a><br> +<a href="#postfix">postfix</a><br> +<a href="#postgresql">postgresql</a><br> +<a href="#powernowd">powernowd</a><br> +<a href="#ppp">ppp</a><br> +<a href="#privoxy">privoxy</a><br> +<a href="#proftpd">proftpd</a><br> +<a href="#pure-ftpd">pure-ftpd</a><br> +<a href="#radiusd">radiusd</a><br> +<a href="#rmrtg">rmrtg</a><br> +<a href="#rsyncd">rsyncd</a><br> +<a href="#samba">samba (smbd, nmbd)</a><br> +<a href="#shoutcast">shoutcast</a><br> +<a href="#spamd">spamd</a><br> +<a href="#squid">squid</a><br> +<a href="#sshd">sshd</a><br> +<a href="#sshdtcpserver">sshd under tcpserver</a><br> +<a href="#statd">statd</a>, <a href="#mountd">mountd</a><br> +<a href="#stunnel">stunnel</a><br> +<a href="#subversion">subversion</a><br> +<a href="#swat">swat</a><br> +<a href="#syslogd">syslogd</a><br> +<a href="#taiclockd">taiclockd</a><br> +<a href="#tmda-ofmipd">tmda-ofmipd</a><br> +<a href="#tomcat">tomcat</a><br> +<a href="#tor">tor</a><br> +<a href="#vsftpd">vsftpd</a><br> +<a href="#wvdial">wvdial</a><br> +<a href="#xdm">xdm</a><br> +<a href="#xfs">xfs</a><br> +<hr> + +<h3><a name="atftpd">An <tt>atftpd</tt> run script</a></h3> +(<i>Debian</i>) +<pre> + #!/bin/sh + exec in.tftpd --daemon --no-fork --tftpd-timeout 30 \ + --retry-timeout 5 --no-tsize --no-blksize --no-multicast \ + --maxthread 1000 --verbose=7 /var/atfpd 2>&1 +</pre> +<hr> +<h3><a name="apache">An <tt>apache</tt> run script</a></h3> +(<i>SunOS</i>, Apache 1.*, patched to run under supervise) +<pre> + #!/bin/sh + exec 2>&1 + exec env -i \ + /pack/apache/1.3.27-1/sbin/httpd -F 2>&1 +</pre> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec 1>&2 + exec apache-ssl -F +</pre> +<hr> +<h3><a name="apache2">An <tt>apache2</tt> run script</a></h3> +(<i>SunOS</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec env -i /command/pgrphack \ + /pack/apache/2.0.43-1/sbin/httpd -DFOREGROUND 2>&1 +</pre> +(<i>HP-UX/GNU</i>, <i>Linux</i>) +<pre> + #!/bin/sh + TZ=MET-1METDST + export TZ + exec /usr/local/apache2/bin/httpd -DNO_DETACH +</pre> +<hr> +<h3><a name="atd">An <tt>atd</aa> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec atd -d +</pre> +<hr> +<h3><a name="bind9">A <tt>bind9</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + MEM="`head -1 ./env/MEM`" + CHROOT="`head -1 ./env/CHROOT`" + exec softlimit -m "${MEM}" \ + named -u bind -t "${CHROOT}" -g 2>&1 +</pre> +(<i>HP-UX/GNU</i>, <i>Linux</i>) +<pre> + #!/bin/sh + exec named -f -t /var/spool/named/ -u named +</pre> +<hr> +<h3><a name="boa">A <tt>boa</tt> run script</a></h3> +(<i>SunOS</i>) +<pre> + #!/bin/sh + exec 2>&1 + ulimit -n 1024 + exec /pack/boa/current/boa -c /pack/boa/current -d 2>&1 +</pre> +<hr> +<h3><a name="cfengine">A <tt>cfengine</tt> run script</a></h3> +(<i>SunOS</i>) +<pre> + #!/bin/sh + /pack/cfengine/sbin/cfagent --file /pack/cfengine/etc/cfagent.conf \ + -L -v -q exec sleep 3600 +</pre> +<hr> +<h3><a name="cfsd">A <tt>cfsd</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + + set -e + + PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + DAEMON=cfsd + CONFIG_FILE=/etc/cfs.conf + + # source config file + test ! -r "$CONFIG_FILE" || . "$CONFIG_FILE" + + test -n "$CRYPT_ROOT" || exit 0 + test -n "$NULL_EXPORT" || exit 0 + test -n "$CFS_MOUNT" || exit 0 + test -n "$CFS_UMOUNT" || exit 0 + + sv start portmap || exit 1 + + exec env \ + NODAEMON=1 CFS_MOUNT="$CFS_MOUNT" CFS_UMOUNT="$CFS_UMOUNT" $DAEMON +</pre> +<hr> +<h3><a name="chrony">A <tt>chrony</tt> run script</a></h3> +(<i>LFS</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec chronyd -d -r -s +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="clamav">A <tt>clamd</tt> run script</a></h3> +(<i>RedHat 7</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec setuidgid clamav softlimit -a 40000000 clamd +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="clamsmtpd">A <tt>clamsmtpd</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec chpst -uclamav clamsmtpd -d 3 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="courier-imap">A <tt>courier-imap</tt> run script</a></h3> +(<i>SunOS</i>) +<pre> + #!/bin/sh + exec 2>&1 + PREFIX="/usr/lib/courier-imap" + exec envdir ./env \ + tcpserver -v -R 0 143 \ + $PREFIX/sbin/imaplogin \ + $PREFIX/libexec/authlib/authshadow \ + $PREFIX/libexec/authlib/authvchkpw \ + $PREFIX/bin/imapd Maildir +</pre> +See also <a href="http://jonaspasche.de/courier-imap-daemontools.txt"> +this page</a>. +<hr> +<h3><a name="cron">A <tt>cron</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec cron -f -l +</pre> +<hr> +<h3><a name="cups">A <tt>cups</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec cupsd -f +</pre> +<hr> +<h3><a name="dhclient">A <tt>dhclient</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec dhclient -e -d -cf ./config -lf ./leases -pf ./pid eth1 +</pre> +<hr> +<h3><a name="dhcpcd">A <tt>dhcpcd</tt> run script</a></h3> +(<i>Linux</i>, DHCP Client Daemon v.scriptconfig-0.1) +<pre> + #!/bin/sh + exec dhcpcd -a -d -D -H eth0 +</pre> +<hr> +<h3><a name="dhcpd">A <tt>dhcpd</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec dhcpd-2.2.x -f -d -cf ./config eth0 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<p> +(<i>Solaris 8</i>, uses additional dsvclockd service, would get fired off +automatically, but then it's not supervised) +<pre> + #!/bin/sh + exec 2>&1 + exec envdir ./env /usr/lib/inet/dsvclockd -f +</pre> +<pre> + #!/bin/sh + if svok /service/dsvclockd; then + sleep 2 # wait to make sure dsvclockd is initialized + exec 2>&1 + exec envdir ./env /usr/lib/inet/in.dhcpd -b manual -d # -v + fi + echo dsvclockd is not running - aborting + exec /usr/bin/sleep 5 +</pre> +The in.dhcpd service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="dictd">A <tt>dictd</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec dictd -d nodetach +</pre> +<hr> +<h3><a name="dropbear">A <tt>dropbear</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec dropbear -F -E -p 22 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<p> +(<i>Linux</i>, running under +<a href="http://smarden.org/ipsvd/tcpsvd.8.html">tcpsvd</a>) +<pre> + #!/bin/sh + exec 2>&1 + exec tcpsvd -v -i./peers 0 22 dropbear -i -E +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="exim">An <tt>exim</tt> run script</a></h3> +(<i>Linux</i>, <i>FreeBSD</i>) +<pre> + #!/bin/sh + exec /usr/local/sbin/exim -bdf -q30m +</pre> +<hr> +<h3><a name="expireproctitle"> +<tt>expireproctitle</tt> run script examples</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + echo -n . + exec sleep 300 +</pre> +<hr> +<h3><a name="fam">A <tt>fam</tt> run script</a></h3> +(<i>Slackware Linux 9.0</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec fam -L -f -v +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<p> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + sv start /service/portmap || exit 1 + exec famd -T 0 -f +</pre> +<hr> +<h3><a name="postfix">A postfix <tt>master</tt> run script</a></h3> +(<i>Debian etch</i>) +<pre> + #!/bin/sh + exec 1>&2 + + daemon_directory=/usr/lib/postfix \ + command_directory=/usr/sbin \ + config_directory=/etc/postfix \ + queue_directory=/var/spool/postfix \ + mail_owner=postfix \ + setgid_group=postdrop \ + /etc/postfix/postfix-script check || exit 1 + + exec /usr/lib/postfix/master +</pre> +<hr> +<h3><a name="fcron">A <tt>fcron</tt> run script</a></h3> +(<i>LFS</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec fcron -f -y +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="fetchmail">A <tt>fetchmail</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + INTERVAL=551 + exec 2>&1 + echo "*** Starting fetchmail service..." + exec env FETCHMAILHOME="./pid" \ + chpst -u fetchmail fetchmail -v \ + -f ./fetchmail.conf \ + --nodetach \ + --daemon ${INTERVAL} +</pre> +<hr> +<h3><a name="gdm">A <tt>gdm</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec gdm -nodaemon +</pre> +<hr> +<h3><a name="getty">A <tt>mingetty</tt> run script</a></h3> +(<i>Debian</i>) +<pre> + #!/bin/sh + exec mingetty tty5 +</pre> +The <a href="index.html">runit</a> package does not care about utmp records +for getties. You should choose a getty that handles its own utmp and wtmp +records. +Debian's <tt>mingetty</tt> creates its own utmp record. +<h3>An <tt>agetty</tt> run script</h3> +(<i>Slackware Linux 9.0</i>) +<pre> + #!/bin/sh + exec agetty 38400 tty1 linux +</pre> +<h3>A <tt>fgetty</tt> run script</h3> +(<i>Linux</i>) +<pre> + #!/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>) +<pre> + #!/bin/sh + exec 2>&1 + . /etc/sysconfig/mouse + exec gpm -D -m $MDEVICE -t $PROTOCOL +</pre> +<hr> +<h3><a name="hotwayd">A <tt>hotwayd</tt> run script</a></h3> +(<i>LFS</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec tcpsvd -l0 -u nobody 127.0.0.1 110 hotwayd +</pre> +<hr> +<h3><a name="identd">An <tt>oidentd</tt> run script</a></h3> +(<i>Linux</i>, oidentd version 2.0.6) +<pre> + #!/bin/sh + exec 2>&1 + exec oidentd -i -S -t 10 -u daemon -g daemon +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<p> +(<i>Debian</i>) +<pre> + #!/bin/sh + exec /usr/local/sbin/oidentd --nosyslog -i -u ident -g ident -l 15 -m \ + -C /etc/oidentd/oidentd.conf 2>&1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="inn">An <tt>innd</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + MEM="`head -1 ./env/MEM`" + exec softlimit -m "${MEM}" \ + setuidgid news \ + /usr/sw/bin/news/inndstart -f -r +</pre> +<hr> +<h3><a name="jabberd"><tt>jabberd</tt> run scripts</a></h3> +(<i>RedHat 7</i>) +<pre> + #!/bin/sh + exec 2>&1 + if [ -f /usr/local/jabber/jabber.pid ]; then + rm /usr/local/jabber/jabber.pid + fi + exec setuidgid jabberd \ + /usr/local/jabber/jabberd/jabberd -D -c /etc/jabber.xml +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<pre> + #!/bin/sh + exec 2>&1 + sleep 5 # so that jit starts after jabberd is up + exec setuidgid jabberd \ + /usr/local/jabber/jit/jabberd/jabberd -c /etc/jit.xml +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="junkbuster">A <tt>junkbuster</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + DAEMON=junkbuster + exec "$DAEMON" /etc/junkbuster/config +</pre> +<hr> +<h3><a name="kdm">A <tt>kdm</tt> run script</a></h3> +(<i>Debian sid</i>, <i>FreeBSD 5.3-REL</i>) +<pre> + #!/bin/sh + sv start /service/getty-* || exit 1 + exec kdm -nodaemon +</pre> +<hr> +<h3><a name="keepalived">A <tt>keepalived</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec keepalived -n +</pre> +<hr> +<h3><a name="klogd">A <tt>klogd</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec klogd -n +</pre> +<hr> +<h3><a name="leafnode">A <tt>leafnode</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec envuidgid news \ + tcpserver -v -x rules.cdb -c 10 -U 0 119 \ + leafnode +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="loglinuxkernel"> +A run script for <tt>logging Linux kernel messages with multilog</tt></a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh -e + exec < /proc/kmsg \ + setuidgid loguser \ + multilog t n64 ./main +</pre> +<hr> +<h3><a name="mdadm">A <tt>mdadm</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + DEBIANCONFIG=/etc/default/mdadm + MAIL_TO=root + test -f $DEBIANCONFIG && . $DEBIANCONFIG + exec mdadm --monitor --scan --mail $MAIL_TO +</pre> +<hr> +<h3><a name="minidentd">A <tt>minidentd</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec envuidgid nobody \ + tcpserver -vUR 0 113 \ + timeoutafter 60 \ + minidentd -v +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="mpd">A <tt>mpd</tt> run script</a></h3> +(<i>Debian sid</i>, <i>FreeBSD 5.3-REL</i>) +<pre> + #!/bin/sh + MPDCONF=/etc/mpd.conf + exec mpd --stdout --no-daemon $MPDCONF +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="nscd">A <tt>nscd</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + secure="" + for table in passwd group + do + if egrep '^'$table':.*nisplus' /etc/nsswitch.conf >/dev/null + then + nscd_nischeck $table || secure="$secure -S $table,yes" + fi + done + exec nscd -d -- $secure +</pre> +<hr> +<h3><a name="ntpd">A <tt>ntpd</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + MEM=`head -1 ./env/MEM` + exec softlimit -m "${MEM}" \ + ntpd -n +</pre> +(<i>OpenNTPD on OpenBSD/Linux</i>) +<pre> + #!/bin/sh + exec /usr/sbin/ntpd -s -d 2>&1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="nullidentd">A <tt>nullidentd</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec tcpsvd -u nobody -x nullidentd-cdb -t 60 0 113 nullidentd +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="polipo">A <tt>polipo</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec setuidgid polipo \ + polipo -c config forbiddenFile="`pwd`"/forbidden diskCacheRoot="`pwd`"/cache +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="pop3-ssl">A <tt>pop3-ssl</tt> run script</a></h3> +(<i>BSD</i>) +<pre> + #!/bin/sh + exec tcpserver -R -v -c 50 0 995 /usr/local/sbin/stunnel + -f -p /etc/ssl/stunnel.pem \ + -l /var/qmail/bin/qmail-popup -- /var/qmail/bin/qmail-popup + "`cat /var/qmail/control/me`" vchkpw /var/qmail/bin/qmail-pop3d Maildir 2>&1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="pop3vscan">A <tt>pop3vscan</tt> run script</a></h3> +(<i>RedHat 7</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec setuidgid pop3vscan pop3vscan -d +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="portmap">A <tt>portmap</tt> run script</a></h3> +(<i>LFS</i>, <i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec portmap -d +</pre> +<hr> +<h3><a name="postgresql">A <tt>postgresql</tt> run script</a></h3> +(<i>Debian</i>, <i>SunOS</i>) +<pre> + #!/bin/sh + exec setuidgid postgres /usr/lib/postgresql/bin/postmaster \ + -D /var/lib/postgres/data 2>&1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="powernowd">A <tt>powernowd</tt> run script</a></h3> +(<i>Debian</i>) +<pre> + #!/bin/sh + set -e # barf if modprobe fails + modprobe cpufreq-userspace + test ! -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor || + exec /usr/sbin/powernowd -d + + echo "required sysfs objects not found!" + echo "Read /usr/share/doc/powernowd/README.Debian for more information." + sv down "$(pwd)" +</pre> +<hr> +<h3><a name="ppp">A <tt>ppp</tt> run script</a></h3> +(<i>FreeBSD</i>) +<pre> + #!/bin/sh + exec 2>&1 + echo "ppp -ddial dsl " + exec ppp -unit0 -foreground dsl +</pre> +<h3>A <tt>pppd</tt> run script</h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec chpst -P pppd call isp nodetach +</pre> +<hr> +<h3><a name="privoxy">A <tt>privoxy</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec chpst -u privoxy:nogroup privoxy --no-daemon /etc/privoxy/config +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="proftpd">A <tt>proftpd</tt> run script</a></h3> +(<i>Linux</i>, ProFTPD Version 1.2.8rc1, +configure it to use 'ErrorLog "/dev/stdout"') +<pre> + #!/bin/sh + exec 2>&1 + exec proftpd -n -d 1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="pure-ftpd">A <tt>pure-ftpd</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec pure-ftpd -a 50 -E -l pam -u 100 +</pre> +<hr> +<h3><a name="radiusd">A <tt>radiusd</tt> run script</a></h3> +(<i>Slackware Linux 9.0</i>, cistron radius 1.6.1) +<pre> + #!/bin/sh + exec 2>&1 + exec radiusd -f -y -z -lstdout +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="rmrtg">A <tt>rmrtg</tt> run script</a></h3> +() +<pre> + #!/bin/sh + MRTGUID=`id -u mrtg` + MRTGGID=`id -g mrtg` + exec 2>&1 + exec tcpserver -l 0 -R -H -q \ + -u"${MRTGUID}" -g"${MRTGGID}" 0 5660 /home/mrtg/ext/rmrtg +</pre> +<hr> +<h3><a name="rsyncd">A <tt>rsyncd</tt> run script</a></h3> +(<i>SunOS</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec softlimit -d 100000000 tcpserver \ + -x /pack/rsync/rsync.service/tcp.rsync.cdb -v -c 100 -U -H -l 0 -R \ + 1.2.3.4 873 nice -2 /pack/rsync/bin/rsync --daemon --no-detach \ + --config /pack/rsync/etc/rsyncd.conf +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="samba">A <tt>smbd</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + PATH="/usr/local/samba/bin" + exec 2>&1 + exec smbd -F -S -d3 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<h3>A <tt>nmbd</tt> run script</h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + PATH="/usr/local/samba/bin" + exec 2>&1 + exec nmbd -F -S -d1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="shoutcast">A <tt>shoutcast</tt> run script</a></h3> +(<i>RedHat 7</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec setuidgid sc_serv \ + /usr/local/sc_serv/bin/sc_serv /etc/sc_serv.conf +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="spamd">A <tt>spamd</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec spamd -m 20 -a -H -s stderr 2>&1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="squid">A <tt>squid</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec squid -f ./config -sN +</pre> +<hr> +<h3><a name="sshd">A <tt>sshd</tt> run script</a></h3> +(<i>Debian</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec /usr/sbin/sshd -D -e +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="sshdtcpserver"> +A <tt>sshd (under tcpserver)</tt> run script</a></h3> +(<i>Linux</i>, sshd version OpenSSH_3.4p1) +<pre> + #!/bin/sh -e + exec 2>&1 + exec \ + tcpserver -1vpdl0 -Xxtcp.cdb 0 ssh \ + sshd -ief config +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="statd">A <tt>statd</tt> run script</a></h3> +(<i>Debian woody</i>) +<pre> + #!/bin/sh + exec 2>&1 + NEED_LOCKD=yes + if test -f /proc/ksyms; then + # We need to be conservative and run lockd, + # unless we can prove that it isn't required. + grep -q lockdctl /proc/ksyms || NEED_LOCKD=no + fi + if [ "$NEED_LOCKD" = yes ]; then + rpc.lockd + fi + exec rpc.statd -F -d +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<h3><a name="mountd">A <tt>mountd</tt> run script</a></h3> +(<i>Debian</i>) +<pre> + #!/bin/sh + sv start portmap statd || exit 1 + RPCNFSDCOUNT=8 # Number of servers to be started up by default + RPCMOUNTDOPTS= + + trap '/usr/bin/killall -2 nfsd' 0 + trap 'exit 2' 1 2 3 15 + + exportfs -r + rpc.nfsd -- $RPCNFSDCOUNT + rpcinfo -u localhost nfs 3 >/dev/null 2>&1 || + RPCMOUNTDOPTS="$RPCMOUNTDOPTS --no-nfs-version 3" + exec rpc.mountd -F $RPCMOUNTDOPTS +</pre> +<hr> +<h3><a name="stunnel">A <tt>stunnel</tt> run script</a></h3> +(<i>BSD</i>) +<pre> + #!/bin/sh + exec /usr/local/sbin/stunnel -f -d 1234 -r 25 -v3 -a /etc/ssl/mailcerts 2>&1 +</pre> +<hr> +<h3><a name="subversion">A <tt>svnserve</tt> run script</a></h3> +(<i>Debian</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec /usr/bin/svnserve -d --foreground +</pre> +<hr> +<h3><a name="swat">A <tt>swat</tt> run script</a></h3> +<pre> + #!/bin/sh + exec 2>&1 + exec tcpsvd -l0 127.0.0.1 901 swat +</pre> +<hr> +<h3><a name="syslogd">A <tt>syslogd</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec syslogd -n +</pre> +<hr> +<h3><a name="taiclockd">A <tt>taiclockd</tt> run script</a></h3> +<pre> + #!/bin/sh + exec 2>&1 + exec setuidgid taiclock /usr/local/clockspeed/bin/taiclockd +</pre> +<hr> +<h3><a name="tmda-ofmipd">A <tt>tmda-ofmipd</tt> run script</a></h3> +(<i>RedHat 7</i>) +<pre> + #!/bin/sh + exec /usr/local/tmda/bin/tmda-ofmipd -f -d -R pop3 -p my.host.name:8025 2>&1 +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="tomcat">A <tt>tomcat</tt> run script</a></h3> +(<i>SunOS</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec \ + setuidgid apache \ + /pack/tomcat/current/bin/catalina.sh run +</pre> +<hr> +<h3><a name="tor">A <tt>tor</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec chpst -P -u debian-tor:debian-tor tor +</pre> +<hr> +<h3><a name="vsftpd">A <tt>vsftpd</tt> run script</a></h3> +(<i>RedHat 7</i>) +<pre> + #!/bin/sh + exec 2>&1 + exec tcpserver -c30 -Xv -llocalhost \ + -x/etc/tcp.ftp.cdb -uvsftpd -gvsftpd 0 ftp \ + softlimit -d300000 /var/vsftpd/bin/vsftpd +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="wvdial">A <tt>wvdial</tt> run script</a></h3> +(<i>Slackware Linux 9.0</i>, the service should have a <tt>down</tt> +file, use <tt>svc -o /service/wvdial</tt> to bring up a ppp connection) +<pre> + #!/bin/sh + exec 2>&1 + exec wvdial ISP +</pre> +This service needs a +<a href="faq.html#createlog">log service</a> +to be set up. +<hr> +<h3><a name="xdm">A <tt>xdm</tt> run script</a></h3> +(<i>Linux</i>) +<pre> + #!/bin/sh + sv start /service/vc-* || exit 1 + exec xdm -nodaemon +</pre> +<hr> +<h3><a name="xfs">A <tt>xfs</tt> run script</a></h3> +(<i>Debian sarge</i>) +<pre> + #!/bin/sh + SOCKET_DIR=/tmp/.font-unix + mkdir -p $SOCKET_DIR + chown 0:0 $SOCKET_DIR + chmod 1777 $SOCKET_DIR + exec /usr/bin/X11/xfs -nodaemon +</pre> +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/runsv.8.html b/runit-2.1.2/doc/runsv.8.html new file mode 100644 index 0000000..d27deeb --- /dev/null +++ b/runit-2.1.2/doc/runsv.8.html @@ -0,0 +1,157 @@ + + + +<html> +<head> +<title>runsv(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +runsv - starts and monitors a service and optionally an appendant log +service +<h2><a name='sect1'>Synopsis</a></h2> +<b>runsv</b> <i>service</i> +<h2><a name='sect2'>Description</a></h2> +<i>service</i> must be a directory. <p> +<b>runsv</b> +switches to the directory <i>service</i> and starts ./run. If ./run exits and ./finish +exists, <b>runsv</b> starts ./finish. If ./finish doesn’t exist or ./finish exits, +<b>runsv</b> restarts ./run. <p> +If ./run or ./finish exit immediately, <b>runsv</b> waits a +second before starting ./finish or restarting ./run. <p> +Two arguments are given +to ./finish. The first one is ./run’s exit code, or -1 if ./run didn’t exit normally. +The second one is the least significant byte of the exit status as determined +by <i><b>waitpid</b>(2)</i>; for instance it is 0 if ./run exited normally, and the signal +number if ./run was terminated by a signal. If <b>runsv</b> cannot start ./run for +some reason, the exit code is 111 and the status is 0. <p> +If the file <i>service</i>/down +exists, <b>runsv</b> does not start ./run immediately. The control interface (see +below) can be used to start the service and to give other commands to <b>runsv</b>. +<p> +If the directory <i>service</i>/log exists, <b>runsv</b> creates a pipe, redirects <i>service</i>/run’s +and <i>service</i>/finish’s standard output to the pipe, switches to the directory +<i>service</i>/log and starts ./run (and ./finish) exactly as described above for +the <i>service</i> directory. The standard input of the log service is redirected +to read from the pipe. <p> +<b>runsv</b> maintains status information in a binary format +(compatible to the daemontools’ <b>supervise</b> program) in <i>service</i>/supervise/status +and <i>service</i>/log/supervise/status, and in a human-readable format in <i>service</i>/supervise/stat, +<i>service</i>/log/supervise/stat, <i>service</i>/supervise/pid, <i>service</i>/log/supervise/pid. + +<h2><a name='sect3'>Control</a></h2> +The named pipes <i>service</i>/supervise/control, and (optionally) <i>service</i>/log/supervise/control +are provided to give commands to <b>runsv</b>. You can use <i><b>sv</b>(8)</i> to control the +service or just write one of the following characters to the named pipe: + +<dl> + +<dt><b>u</b> </dt> +<dd>Up. If the service is not running, start it. If the service stops, restart +it. </dd> + +<dt><b>d</b> </dt> +<dd>Down. 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. </dd> + +<dt><b>o</b> </dt> +<dd>Once. If the service is not running, start it. Do not +restart it if it stops. </dd> + +<dt><b>p</b> </dt> +<dd>Pause. If the service is running, send it a STOP +signal. </dd> + +<dt><b>c</b> </dt> +<dd>Continue. If the service is running, send it a CONT signal. </dd> + +<dt><b>h</b> </dt> +<dd>Hangup. +If the service is running, send it a HUP signal. </dd> + +<dt><b>a</b> </dt> +<dd>Alarm. If the service +is running, send it a ALRM signal. </dd> + +<dt><b>i</b> </dt> +<dd>Interrupt. If the service is running, +send it a INT signal. </dd> + +<dt><b>q</b> </dt> +<dd>Quit. If the service is running, send it a QUIT signal. </dd> + +<dt><b>1</b> </dt> +<dd>User-defined 1. If the service is running, send it a USR1 signal. </dd> + +<dt><b>2</b> </dt> +<dd>User-defined 2. If the service is running, send it a USR2 signal. </dd> + +<dt><b>t</b> </dt> +<dd>Terminate. If the service +is running, send it a TERM signal. </dd> + +<dt><b>k</b> </dt> +<dd>Kill. If the service is running, send +it a KILL signal. </dd> + +<dt><b>x</b> </dt> +<dd>Exit. 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</b> exits. If the service is down and a log +service exists, <b>runsv</b> closes the standard input of the log service, and +waits for it to terminate. If the log service is down, <b>runsv</b> exits. This +command is ignored if it is given to <i>service</i>/log/supervise/control. </dd> +</dl> +<p> +Example: +to send a TERM signal to the socklog-unix service, either do # sv term +/service/socklog-unix<br> + or<br> + # printf t >/service/socklog-unix/supervise/control<br> + <p> +<i><b>printf</b>(1)</i> usually blocks if no <b>runsv</b> process is running in the service +directory. +<h2><a name='sect4'>Customize Control</a></h2> +For each control character <i>c</i> sent to the control +pipe, <b>runsv</b> first checks if <i>service</i>/control/<i>c</i> exists and is executable. +If so, it starts <i>service</i>/control/<i>c</i> and waits for it to terminate, before +interpreting the command. If the program exits with return code 0, <b>runsv</b> +refrains from sending the service the corresponding signal. The command +<i>o</i> is always considered as command <i>u</i>. On command <i>d</i> first <i>service</i>/control/<i>t</i> +is checked, and then <i>service</i>/control/<i>d</i>. On command <i>x</i> first <i>service</i>/control/<i>t</i> +is checked, and then <i>service</i>/control/<i>x</i>. The control of the optional log +service cannot be customized. +<h2><a name='sect5'>Signals</a></h2> +If <b>runsv</b> receives a TERM signal, it +acts as if the character x was written to the control pipe. +<h2><a name='sect6'>Exit Codes</a></h2> +<b>runsv</b> +exits 111 on an error on startup or if another <b>runsv</b> is running in <i>service</i>. +<p> +<b>runsv</b> exits 0 if it was told to exit. +<h2><a name='sect7'>See Also</a></h2> +<i>sv(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> + +<h2><a name='sect8'>Author</a></h2> +Gerrit Pape <pape@smarden.org> <p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Control</a></li> +<li><a name='toc4' href='#sect4'>Customize Control</a></li> +<li><a name='toc5' href='#sect5'>Signals</a></li> +<li><a name='toc6' href='#sect6'>Exit Codes</a></li> +<li><a name='toc7' href='#sect7'>See Also</a></li> +<li><a name='toc8' href='#sect8'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/runsvchdir.8.html b/runit-2.1.2/doc/runsvchdir.8.html new file mode 100644 index 0000000..54e66a5 --- /dev/null +++ b/runit-2.1.2/doc/runsvchdir.8.html @@ -0,0 +1,52 @@ + + + +<html> +<head> +<title>runsvchdir(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +runsvchdir - change services directory of <i>runsvdir(8)</i> +<h2><a name='sect1'>Synopsis</a></h2> +<b>runsvchdir</b> +<i>dir</i> +<h2><a name='sect2'>Description</a></h2> +<i>dir</i> is a services directory for the use with <i><b>runsvdir</b>(8)</i>. +If <i>dir</i> does not start with a slash, it is searched in /etc/runit/runsvdir/. +<i>dir</i> must not start with a dot. <p> +<b>runsvchdir</b> switches to the directory <i>/etc/runit/runsvdir/</i>, +copies <i>current</i> to <i>previous</i>, and replaces <i>current</i> with a symlink pointing +to <i>dir</i>. <p> +Normally <i>/service</i> is a symlink to <i>current</i>, and <i><b>runsvdir</b>(8)</i> is running +<i>/service/</i>. +<h2><a name='sect3'>Exit Codes</a></h2> +<b>runsvchdir</b> prints an error message and exits 111 on +error. <b>runsvchdir</b> exits 0 on success. +<h2><a name='sect4'>Files</a></h2> + /etc/runit/runsvdir/previous<br> + /etc/runit/runsvdir/current<br> + /etc/runit/runsvdir/current.new<br> + +<h2><a name='sect5'>See Also</a></h2> +<i>runsvdir(8)</i>, <i>runit(8)</i>, <i>runit-init(8)</i>, <i>sv(8)</i>, <i>runsv(8)</i> <p> +<i>http://smarden.org/runit/</i> + +<h2><a name='sect6'>Author</a></h2> +Gerrit Pape <pape@smarden.org> <p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Exit Codes</a></li> +<li><a name='toc4' href='#sect4'>Files</a></li> +<li><a name='toc5' href='#sect5'>See Also</a></li> +<li><a name='toc6' href='#sect6'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/runsvdir.8.html b/runit-2.1.2/doc/runsvdir.8.html new file mode 100644 index 0000000..f4053db --- /dev/null +++ b/runit-2.1.2/doc/runsvdir.8.html @@ -0,0 +1,73 @@ + + + +<html> +<head> +<title>runsvdir(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +runsvdir - starts and monitors a collection of <i>runsv(8)</i> processes +<h2><a name='sect1'>Synopsis</a></h2> +<b>runsvdir</b> +[-P] <i>dir</i> [ <i>log</i> ] +<h2><a name='sect2'>Description</a></h2> +<i>dir</i> must be a directory. <i>log</i> is a space holder +for a readproctitle log, and must be at least seven characters long or +absent. <p> +<b>runsvdir</b> starts a <i><b>runsv</b>(8)</i> process for each subdirectory, or symlink +to a directory, in the services directory <i>dir</i>, up to a limit of 1000 subdirectories, +and restarts a <i><b>runsv</b>(8)</i> process if it terminates. <b>runsvdir</b> skips subdirectory +names starting with dots. <i><b>runsv</b>(8)</i> must be in <b>runsvdir</b>’s PATH. <p> +At least every +five seconds <b>runsvdir</b> checks whether the time of last modification, the +inode, or the device, of the services directory <i>dir</i> has changed. If so, +it re-scans the service directory, and if it sees a new subdirectory, or +new symlink to a directory, in <i>dir</i>, it starts a new <i><b>runsv</b>(8)</i> process; if +<b>runsvdir</b> sees a subdirectory being removed that was previously there, it +sends the corresponding <i><b>runsv</b>(8)</i> process a TERM signal, stops monitoring +this process, and so does not restart the <i><b>runsv</b>(8)</i> process if it exits. +<p> +If the <i>log</i> argument is given to <b>runsvdir</b>, all output to standard error +is redirected to this <i>log</i>, which is similar to the daemontools’ <b>readproctitle</b> +log. To see the most recent error messages, use a process-listing tool such +as <i><b>ps</b>(1)</i>. <b>runsvdir</b> writes a dot to the readproctitle log every 15 minutes +so that old error messages expire. +<h2><a name='sect3'>Options</a></h2> + +<dl> + +<dt><b>-P</b> </dt> +<dd>use <i><b>setsid</b>(2)</i> to run each <i><b>runsv</b>(8)</i> +process in a new session and separate process group. </dd> +</dl> + +<h2><a name='sect4'>Signals</a></h2> +If <b>runsvdir</b> +receives a TERM signal, it exits with 0 immediately. <p> +If <b>runsvdir</b> receives +a HUP signal, it sends a TERM signal to each <i><b>runsv</b>(8)</i> process it is monitoring +and then exits with 111. +<h2><a name='sect5'>See Also</a></h2> +<i>sv(8)</i>, <i>runsv(8)</i>, <i>runsvchdir(8)</i>, <i>runit(8)</i>, +<i>runit-init(8)</i>, <i>chpst(8)</i>, <i>svlogd(8)</i>, <i>utmpset(8)</i>, <i>setsid(2)</i> <p> +<i>http://smarden.org/runit/</i> + +<h2><a name='sect6'>Author</a></h2> +Gerrit Pape <pape@smarden.org> <p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Options</a></li> +<li><a name='toc4' href='#sect4'>Signals</a></li> +<li><a name='toc5' href='#sect5'>See Also</a></li> +<li><a name='toc6' href='#sect6'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/sv.8.html b/runit-2.1.2/doc/sv.8.html new file mode 100644 index 0000000..504b30b --- /dev/null +++ b/runit-2.1.2/doc/sv.8.html @@ -0,0 +1,218 @@ + + + +<html> +<head> +<title>sv(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +sv - control and manage services monitored by <i><b>runsv</b>(8)</i> +<h2><a name='sect1'>Synopsis</a></h2> +<b>sv</b> [-v] +[-w <i>sec]</i> <i>command</i> <i>services</i> <p> +<b>/etc/init.d/</b><i>service</i> [-w <i>sec]</i> <i>command</i> +<h2><a name='sect2'>Description</a></h2> +The +<b>sv</b> program reports the current status and controls the state of services +monitored by the <i><b>runsv</b>(8)</i> supervisor. <p> +<i>services</i> consists of one or more arguments, +each argument naming a directory <i>service</i> used by <i><b>runsv</b>(8)</i>. If <i>service</i> doesn’t +start with a dot or slash and doesn’t end with a slash, it is searched in +the default services directory <i>/service/</i>, otherwise relative to the current +directory. <p> +<i>command</i> is one of up, down, status, once, pause, cont, hup, alarm, +interrupt, 1, 2, term, kill, or exit, or start, stop, restart, shutdown, +force-stop, force-reload, force-restart, force-shutdown. <p> +The <b>sv</b> program can +be sym-linked to <i>/etc/init.d/</i> to provide an LSB init script interface. The +<i>service</i> to be controlled then is specified by the base name of the ‘‘init +script’’. +<h2><a name='sect3'>Commands</a></h2> + +<dl> + +<dt><b>status</b> </dt> +<dd>Report the current status of the service, and the +appendant log service if available, to standard output. </dd> + +<dt><b>up</b> </dt> +<dd>If the service +is not running, start it. If the service stops, restart it. </dd> + +<dt><b>down</b> </dt> +<dd>If the service +is running, send it the TERM signal, and the CONT signal. If ./run exits, +start ./finish if it exists. After it stops, do not restart service. </dd> + +<dt><b>once</b> +</dt> +<dd>If the service is not running, start it. Do not restart it if it stops. </dd> + +<dt><b>pause +cont hup alarm interrupt quit 1 2 term kill</b> </dt> +<dd>If the service is running, +send it the STOP, CONT, HUP, ALRM, INT, QUIT, USR1, USR2, TERM, or KILL +signal respectively. </dd> + +<dt><b>exit</b> </dt> +<dd>If the service is running, send it the TERM signal, +and the CONT signal. Do not restart the service. If the service is down, +and no log service exists, <i><b>runsv</b>(8)</i> exits. If the service is down and a +log service exists, <i><b>runsv</b>(8)</i> closes the standard input of the log service +and waits for it to terminate. If the log service is down, <i><b>runsv</b>(8)</i> exits. +This command is ignored if it is given to an appendant log service. </dd> +</dl> +<p> +<b>sv</b> actually +looks only at the first character of these <i>command</i>s. +<h3><a name='sect4'>Commands compatible +to LSB init script actions</a></h3> + +<dl> + +<dt><b>status</b> </dt> +<dd>Same as <i>status</i>. </dd> + +<dt><b>start</b> </dt> +<dd>Same as <i>up</i>, but wait +up to 7 seconds for the command to take effect. Then report the status or +timeout. If the script <i>./check</i> exists in the service directory, <b>sv</b> runs this +script to check whether the service is up and available; it’s considered +to be available if <i>./check</i> exits with 0. </dd> + +<dt><b>stop</b> </dt> +<dd>Same as <i>down</i>, but wait up to +7 seconds for the service to become down. Then report the status or timeout. +</dd> + +<dt><b>reload</b> </dt> +<dd>Same as <i>hup</i>, and additionally report the status afterwards. </dd> + +<dt><b>restart</b> +</dt> +<dd>Send the commands <i>term</i>, <i>cont</i>, and <i>up</i> to the service, and wait up to 7 seconds +for the service to restart. Then report the status or timeout. If the script +<i>./check</i> exists in the service directory, <b>sv</b> runs this script to check whether +the service is up and available again; it’s considered to be available if +<i>./check</i> exits with 0. </dd> + +<dt><b>shutdown</b> </dt> +<dd>Same as <i>exit</i>, but wait up to 7 seconds for +the <i><b>runsv</b>(8)</i> process to terminate. Then report the status or timeout. </dd> + +<dt><b>force-stop</b> +</dt> +<dd>Same as <i>down</i>, but wait up to 7 seconds for the service to become down. Then +report the status, and on timeout send the service the <i>kill</i> command. </dd> + +<dt><b>force-reload</b> +</dt> +<dd>Send the service the <i>term</i> and <i>cont</i> commands, and wait up to 7 seconds for +the service to restart. Then report the status, and on timeout send the +service the <i>kill</i> command. </dd> + +<dt><b>force-restart</b> </dt> +<dd>Send the service the <i>term</i>, <i>cont</i> and +<i>up</i> commands, and wait up to 7 seconds for the service to restart. Then report +the status, and on timeout send the service the <i>kill</i> command. If the script +<i>./check</i> exists in the service directory, <b>sv</b> runs this script to check whether +the service is up and available again; it’s considered to be available if +<i>./check</i> exits with 0. </dd> + +<dt><b>force-shutdown</b> </dt> +<dd>Same as <i>exit</i>, but wait up to 7 seconds +for the <i><b>runsv</b>(8)</i> process to terminate. Then report the status, and on timeout +send the service the <i>kill</i> command. </dd> + +<dt><b>try-restart</b> </dt> +<dd>if the service is running, +send it the <i>term</i> and <i>cont</i> commands, and wait up to 7 seconds for the service +to restart. Then report the status or timeout. +<p> </dd> +</dl> + +<h3><a name='sect5'>Additional Commands</a></h3> + +<dl> + +<dt><b>check</b> +</dt> +<dd>Check for the service to be in the state that’s been requested. Wait up to +7 seconds for the service to reach the requested state, then report the +status or timeout. If the requested state of the service is <i>up</i>, and the +script <i>./check</i> exists in the service directory, <b>sv</b> runs this script to check +whether the service is up and running; it’s considered to be up if <i>./check</i> +exits with 0. </dd> +</dl> + +<h2><a name='sect6'>Options</a></h2> + +<dl> + +<dt><b>-v</b> </dt> +<dd>If the <i>command</i> is up, down, term, once, cont, or +exit, then wait up to 7 seconds for the command to take effect. Then report +the status or timeout. </dd> + +<dt><b>-w <i>sec</b> </i></dt> +<dd>Override the default timeout of 7 seconds with +<i>sec</i> seconds. This option implies <i>-v</i>. </dd> +</dl> + +<h2><a name='sect7'>Environment</a></h2> + +<dl> + +<dt><b>SVDIR</b> </dt> +<dd>The environment variable +$SVDIR overrides the default services directory <i>/service/</i>. </dd> + +<dt><b>SVWAIT</b> </dt> +<dd>The environment +variable $SVWAIT overrides the default 7 seconds to wait for a command +to take effect. It is overridden by the -w option. </dd> +</dl> + +<h2><a name='sect8'>Exit Codes</a></h2> +<b>sv</b> exits 0, if +the <i>command</i> was successfully sent to all <i>services</i>, and, if it was told +to wait, the <i>command</i> has taken effect to all services. <p> +For each <i>service</i> +that caused an error (e.g. the directory is not controlled by a <i><b>runsv</b>(8)</i> +process, or <b>sv</b> timed out while waiting), <b>sv</b> increases the exit code by +one and exits non zero. The maximum is 99. <b>sv</b> exits 100 on error. <p> +If <b>sv</b> is +called with a base name other than <b>sv</b>: it exits 1 on timeout or trouble +sending the command; if the <i>command</i> is <b>status</b>, it exits 3 if the service +is down, and 4 if the status is unknown; it exits 2 on wrong usage, and +151 on error. +<h2><a name='sect9'>See Also</a></h2> +<i>runsv(8)</i>, <i>chpst(8)</i>, <i>svlogd(8)</i>, <i>runsvdir(8)</i>, <i>runsvchdir(8)</i>, +<i>runit(8)</i>, <i>runit-init(8)</i> <p> +<i>http://smarden.org/runit/</i> +<h2><a name='sect10'>Author</a></h2> +Gerrit Pape <pape@smarden.org> +<p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Commands</a></li> +<ul> +<li><a name='toc4' href='#sect4'>Commands compatible to LSB init script actions</a></li> +<li><a name='toc5' href='#sect5'>Additional Commands</a></li> +</ul> +<li><a name='toc6' href='#sect6'>Options</a></li> +<li><a name='toc7' href='#sect7'>Environment</a></li> +<li><a name='toc8' href='#sect8'>Exit Codes</a></li> +<li><a name='toc9' href='#sect9'>See Also</a></li> +<li><a name='toc10' href='#sect10'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/svlogd.8.html b/runit-2.1.2/doc/svlogd.8.html new file mode 100644 index 0000000..9d300ae --- /dev/null +++ b/runit-2.1.2/doc/svlogd.8.html @@ -0,0 +1,264 @@ + + + +<html> +<head> +<title>svlogd(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +svlogd - runit’s service logging daemon +<h2><a name='sect1'>Synopsis</a></h2> +<b>svlogd</b> [-tttv] [-r <i>c]</i> [-R +<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> +<b>svlogd</b> continuously reads log data from its +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, 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 the daemontools’ <b>tai64n</b> program), 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 (or there is a new-line +within the last <i>len</i> of <i>size</i> bytes), or is older than a specified amount +of <i>time</i>, <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 the log directory, +it removes the oldest one. Note that this doesn’t decrease the number of +log files if there are already more than <i>num</i> log files, this must be done +manually, e.g. for keeping 10 log files: <p> + ls -1 \@* |sort |sed -ne ’10,$p’ |xargs +rm<br> + +<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.t</i> +is renamed to @<i>timestamp.s,</i> and @<i>timestamp.u</i> is deleted; 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 log directory <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, 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> + +<dt>n<i>num</i> </dt> +<dd>sets the 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. +If <i>num</i> is zero, <b>svlogd</b> doesn’t remove old log files. </dd> + +<dt>N<i>min</i> </dt> +<dd>sets the minimum +number of old log files <b>svlogd</b> should maintain to <i>min</i>. <i>min</i> must be less +than <i>num</i>. If <i>min</i> is set, and <b>svlogd</b> cannot write to <i>current</i> because the +filesystem is full, and it sees more than <i>min</i> old log files, it deletes +the oldest one. </dd> + +<dt>t<i>timeout</i> </dt> +<dd>sets the maximum age of the <i>current</i> log file when +<b>svlogd</b> should rotate the current log file to <i>timeout</i> seconds. If <i>current</i> +is <i>timeout</i> seconds old, and is not empty, <b>svlogd</b> forces log file rotation. +</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> + +<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 +error messages to the log directory. Attention: logging through udp is unreliable, +and should be used in private networks only. </dd> + +<dt>U<i>a.b.c.d[:port]</i> </dt> +<dd>is the same as +the <i>u</i> line above, but the log messages are no longer written to the log +directory, but transmitted through udp only. Error messages from <b>svlogd</b> +concerning sending udp packages still go to the log directory. </dd> + +<dt>p<i>prefix</i> </dt> +<dd>tells +<b>svlogd</b> to prefix each line to be written to the log directory, to standard +error, or through UDP, with <i>prefix</i>. </dd> +</dl> +<p> +If a line starts with a <i>-</i>, <i>+</i>, <i>e</i>, or <i>E</i>, +<b>svlogd</b> matches the first <i>len</i> characters of each log message against <i>pattern</i> +and acts accordingly: +<dl> + +<dt>-<i>pattern</i> </dt> +<dd>the log message is deselected. </dd> + +<dt>+<i>pattern</i> </dt> +<dd>the +log message is selected. </dd> + +<dt>e<i>pattern</i> </dt> +<dd>the log message is selected to be printed +to standard error. </dd> + +<dt>E<i>pattern</i> </dt> +<dd>the log message is deselected to be printed +to standard error. </dd> +</dl> +<p> +Initially each line is selected to be written to <i>log/current</i>. +Deselected log messages are discarded from <i>log</i>. Initially each line is deselected +to be written to standard err. Log messages selected for standard error +are written to standard error. +<h2><a name='sect7'>Pattern Matching</a></h2> +<b>svlogd</b> matches a log message +against the string <i>pattern</i> as follows: <p> +<i>pattern</i> is applied to the log message +one character by one, starting with the first. A character not a star (‘‘*’’) +and not a plus (‘‘+’’) matches itself. A plus matches the next character in +<i>pattern</i> in the log message one or more times. A star before the end of <i>pattern</i> +matches any string in the log message that does not include the next character +in <i>pattern</i>. A star at the end of <i>pattern</i> matches any string. <p> +Timestamps optionally +added by <b>svlogd</b> are not considered part of the log message. <p> +An <b>svlogd</b> pattern +is not a regular expression. For example consider a log message like this +<p> + 2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14<br> + <p> +The following pattern doesn’t match <p> + -*pid*<br> + <p> +because the first star matches up to the first p in tcpsvd, and then the +match fails because i is not s. To match this log message, you can use a +pattern like this instead <p> + -*: *: pid *<br> + +<h2><a name='sect8'>Options</a></h2> + +<dl> + +<dt><b>-t</b> </dt> +<dd>timestamp. Prefix each selected line with a precise timestamp +(see the daemontools’ <b>tai64n</b> program) when writing to <i>log</i> or to standard +error. </dd> + +<dt><b>-tt</b> </dt> +<dd>timestamp. Prefix each selected line with a human readable, sortable +UTC timestamp of the form YYYY-MM-DD_HH:MM:SS.xxxxx when writing to <i>log</i> or +to standard error. </dd> + +<dt><b>-ttt</b> </dt> +<dd>timestamp. Prefix each selected line with a human +readable, sortable UTC timestamp of the form YYYY-MM-DDTHH:MM:SS.xxxxx when +writing to <i>log</i> or to standard error. </dd> + +<dt><b>-r <i>c</b> </i></dt> +<dd>replace. <i>c</i> must be a single character. +Replace non-printable characters in log messages with <i>c</i>. Characters are replaced +before pattern matching is applied. </dd> + +<dt><b>-R <i>xyz</b> </i></dt> +<dd>replace charset. Additionally to +non-printable characters, replace all characters found in <i>xyz</i> with <i>c</i> (default +‘‘_’’). </dd> + +<dt><b>-l <i>len</b> </i></dt> +<dd>line length. Pattern matching applies to the first <i>len</i> characters +of a log message only. Default is 1000. </dd> + +<dt><b>-b <i>buflen</b> </i></dt> +<dd>buffer size. Set the size +of the buffer <b>svlogd</b> uses when reading from standard input and writing +to <i>logs</i> to <i>buflen</i>. Default is 1024. <i>buflen</i> must be greater than <i>len</i>. For <b>svlogd</b> +instances that process a lot of data in short time, the buffer size should +be increased to improve performance. </dd> + +<dt><b>-v</b> </dt> +<dd>verbose. Print verbose messages to +standard error. </dd> +</dl> + +<h2><a name='sect9'>Signals</a></h2> +If <b>svlogd</b> is sent a HUP signal, it closes and reopens +all <i>logs</i>, and updates their configuration according to <i>log/config</i>. If <b>svlogd</b> +has trouble opening a log directory, it prints a warning, and discards +this log directory. If <b>svlogd</b> is unable to open all log directories given +at the command line, it exits with an error. <p> +If <b>svlogd</b> is sent a TERM signal, +or if it sees end-of-file on standard input, it stops reading standard input, +processes the data in the buffer, waits for all <i>processor</i> subprocesses +to finish if any, and exits 0 as soon as possible. <p> +If <b>svlogd</b> is sent an +ALRM signal, it forces log file rotation for all <i>logs</i> with a non empty +<i>current</i> log file. +<h2><a name='sect10'>See Also</a></h2> +<i>sv(8)</i>, <i>runsv(8)</i>, <i>chpst(8)</i>, <i>runit(8)</i>, <i>runit-init(8)</i>, +<i>runsvdir(8)</i>, <i>runsvchdir(8)</i> <p> +<i>http://smarden.org/runit/</i> +<h2><a name='sect11'>Author</a></h2> +Gerrit Pape <pape@smarden.org> +<p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<ul> +<li><a name='toc3' href='#sect3'>Log Directory</a></li> +<li><a name='toc4' href='#sect4'>Log File Rotation</a></li> +<li><a name='toc5' href='#sect5'>Processor</a></li> +<li><a name='toc6' href='#sect6'>Config</a></li> +</ul> +<li><a name='toc7' href='#sect7'>Pattern Matching</a></li> +<li><a name='toc8' href='#sect8'>Options</a></li> +<li><a name='toc9' href='#sect9'>Signals</a></li> +<li><a name='toc10' href='#sect10'>See Also</a></li> +<li><a name='toc11' href='#sect11'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/doc/upgrade.html b/runit-2.1.2/doc/upgrade.html new file mode 100644 index 0000000..83d12e1 --- /dev/null +++ b/runit-2.1.2/doc/upgrade.html @@ -0,0 +1,105 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - upgrading from previous versions</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - upgrading from previous versions</h1> +<hr> +<h3>2.0.0 to 2.1.2</h3> +The <a href="chpst.8.html">chpst</a> program learned a new option -b to run +a program with a different name as the 0th argument. +<h3>1.9.0 to 2.0.0</h3> +No further action from you is required. +<h3>1.8.0 to 1.9.0</h3> +The default directory for services is now <tt>/service/</tt>, and no longer +<tt>/var/service/</tt>. +To be consistent with the new default location, create a symlink when +upgrading +<pre> + # ln -s /var/service / +</pre> +When installing runit on a system that should comply with the Filesystem +Hierarchy Standard (FHS), neither <tt>/service/</tt> nor +<tt>/var/service/</tt> should be chosen, but <tt>/etc/service/</tt>. +It is recommended to create a compatibility symlink <tt>/service</tt> +pointing to <tt>/etc/service</tt> in this case. +<h3>1.7.x to 1.8.0</h3> +The <a href="runit.8.html">runit</a> program, the process no 1, has been +fixed to reap dead processes that re-parented to process no 1 (zombies) +more thoroughly. +Instructions on how to run <tt>runit</tt> with upstart as init scheme have +been added, <a href="svlogd.8.html">svlogd</a> has been changed to use a +new source port for each log message sent through udp, and this release +includes a build fix for AIX. +<h3>1.6.0 to 1.7.x</h3> +With this version the <a href="runsv.8.html">runsv</a> program starts to +run the ./finish script with two arguments, the exit code and the exit +status of the just finished ./run script. +The timestamp <a href="svlogd.8.html">svlogd</a> optionally prepends to log +messages can be specified to be in iso 8601 alike format. +See the man pages for details. +<h3>1.5.x to 1.6.0</h3> +<a href="svlogd.8.html">svlogd</a> has been changed to prepend the optional +timestamp also to log messages sent to the network through UDP, just as it +does for log messages written to a log directory or standard error. +<h3>1.4.0 or 1.4.1 to 1.5.x</h3> +The <a href="svlogd.8.html">svlogd</a> program supports a new configuration +option p to optionally prefix each line written to logs, standard error, or +through UDP with a string, and no longer strips empty lines from the logs. +<h3>1.3.x to 1.4.0 or 1.4.1</h3> +With this version the <tt>runsvctrl</tt>, <tt>runsvstat</tt>, +<tt>svwaitdown</tt>, and <tt>svwaitup</tt> programs no longer are being +installed, the functionality of these programs has been incorporated into +the <a href="sv.8.html">sv</a> program. +The documentation now suggest to put service directories by default into +the <tt>/etc/sv/</tt> directory, and a list of frequently asked questions +with answers has been added. +The <a href="chpst.8.html">chpst</a> program understands a new option -d +to limit memory of the data segment per process. +<h3>1.2.x to 1.3.x</h3> +This release introduces a first test version of the <a href="sv.8.html">sv</a> +program, which can be used to control the state and query the status of +services monitored by <a href="runsv.8.html">runsv</a>. +Optionally it can be sym-linked into <tt>/etc/init.d/</tt> to provide an +interface to LSB init script actions for services controlled by runit. +See the <a href="sv.8.html">man page</a> for details. +Thanks to Lars Uffmann, instructions on how to run runit under launchd on +MacOSX 10.4 have been added. +<h3>1.1.0 to 1.2.x</h3> +With this version the <a href="runsv.8.html">runsv</a> program makes +controlling the service through commands normally sent by +<a href="runsvctrl.8.html">runsvctrl</a> configurable; +arbitrary actions through external programs can optionally be specified, and +signalling of the service disabled if desired. +See the <a href="runsv.8.html">man page</a> for details. +<p> +<a href="runsv.8.html">runsv</a> now reports the seconds since <tt>./run</tt> +has been started when running the <tt>./finish</tt> script, instead of the +seconds since <tt>./finish</tt> has been started. +It no longer reports immediately failing <tt>./run</tt> scripts as ``running'' +for up to one second, but as ``down, normally up, want up''. +<h3>1.0.x to 1.1.0</h3> +The <a href="svlogd.8.html">svlogd</a> program now interprets the ``e'' and +``E'' configuration options so that they can be combined to select or +deselect log messages to be written to standard error, similar to the ``+'' +and ``-'' options for the rotated log. +It also provides the new ``t'' and ``N'' configuration options, see the +<a href="svlogd.8.html">man page</a> for details. +The <a href="chpst.8.html">chpst</a> program supports adjusting the nice +level through the new -n command line option. +<p> +Starting with this version, <tt>/etc/runit/2</tt> by default runs the +<a href="runsvdir.8.html">runsvdir</a> program with the -P option. +To adapt edit <tt>/etc/runit/2</tt> and change the invocation of +<a href="runsvdir.8.html">runsvdir</a> accordingly, see +<a href="../etc/2"">here</a>. +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/usedietlibc.html b/runit-2.1.2/doc/usedietlibc.html new file mode 100644 index 0000000..70c5b2f --- /dev/null +++ b/runit-2.1.2/doc/usedietlibc.html @@ -0,0 +1,35 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - use dietlibc</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - use dietlibc</h1> +<hr> +To recompile the <i>runit</i> programs with the +<a href="http://www.fefe.de/dietlibc/">diet libc</a>, check that you have +the recent version of +<a href="http://www.fefe.de/dietlibc/">dietlibc</a> installed. +<p> +Change to the package directory of <i>runit</i> +<pre> + # cd /package/admin/runit/ +</pre> +Change the <tt>conf-cc</tt> and <tt>conf-ld</tt> to use <tt>diet</tt> +<pre> + # echo 'diet -Os gcc -O2 -Wall' >src/conf-cc + # echo 'diet -Os gcc -s -Os -pipe' >src/conf-ld +</pre> +Rebuild and install the <i>runit</i> programs +<pre> + # package/install +</pre> +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/useinit.html b/runit-2.1.2/doc/useinit.html new file mode 100644 index 0000000..a5c2853 --- /dev/null +++ b/runit-2.1.2/doc/useinit.html @@ -0,0 +1,102 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title>runit - use with traditional init</title> +</head> +<body> +<a href="http://smarden.org/pape/">G. Pape</a><br> +<a href="index.html">runit</a><br> +<hr> +<h1>runit - use with traditional init</h1> +<hr> +It's possible to use <i>runit</i>'s service supervision without replacing +the <i>init</i> scheme of the system. +Simply run the <i>stage 2</i> of <i>runit</i> as a service with your +current <i>init</i>. +<p> +Normally this is done by either adding an entry for +<tt>/sbin/runsvdir-start</tt> to <tt>/etc/inittab</tt>, or by adding +<tt>/sbin/runsvdir-start</tt> as command to </tt>/etc/rc.local</tt>, or by +adding <tt>/sbin/runsvdir-start</tt> to the system's <tt>StartupItems</tt>. +<p> +In any case, you first need to copy the <i>stage 2</i> script to +<tt>/sbin/runsvdir-start</tt>, and create the services directory +<tt>/service/</tt>: +<pre> + # install -m0750 /package/admin/runit/etc/2 /sbin/runsvdir-start + # mkdir -p /service +</pre> +<hr> +<a href="#sysv">How to use with sysvinit and inittab</a><br> +<a href="#upstart">How to use with sysvinit and upstart</a><br> +<a href="#bsd">How to use with *BSD init</a><br> +<a href="#macosx">How to use with MacOSX init</a> +<hr> +<a name="sysv"><h2>Using with sysvinit and inittab</h2></a> +If your system uses a sysvinit alike init scheme with a <tt>/etc/inittab</tt> +file, do: +<pre> + # cat >>/etc/inittab <<EOT + SV:123456:respawn:/sbin/runsvdir-start + EOT +</pre> +and tell <i>init</i> to re-read its configuration, e.g.: +<pre> + # init q +</pre> +<hr> +<a name="upstart"><h2>Using with sysvinit and upstart</h2></a> +If your system uses a sysvinit alike init scheme that utilizes upstart +instead of inittab, and which has start and stop scripts located in +<tt>/etc/init/</tt>, do: +<pre> + # cat >/etc/init/runsvdir.conf <<\EOT + # for runit - manage /usr/sbin/runsvdir-start + start on runlevel 2 + start on runlevel 3 + start on runlevel 4 + start on runlevel 5 + stop on shutdown + respawn + exec /usr/sbin/runsvdir-start + EOT +</pre> +and tell init to start the new service, e.g.: +<pre> + # start runsvdir +</pre> +<hr> +<a name="bsd"><h2>Using with *BSD init</h2></a> +If your system uses a BSD alike init scheme with a <tt>/etc/rc.local</tt> +script, do: +<pre> + # cat >>/etc/rc.local <<EOT + csh -cf '/sbin/runsvdir-start &' + EOT +</pre> +and reboot your system. +<hr> +<a name="macosx"><h2>Using with MacOSX init</h2></a> +On MacOSX 10.2 create an entry for <i>runit</i> in +<tt>/System/Library/StartupItems/</tt>: +<pre> + # cd /System/Library/StartupItems + # mkdir -p runit + # cp -p /package/admin/runit/etc/macosx/StartupItems/* runit/ +</pre> +and reboot your system. +<p> +On MacOSX 10.4 create an entry for <i>runit</i> in +<tt>/Library/LaunchDaemons/</tt>, and tell <i>launchd</i> to start the new +service: +<pre> + # cp /package/admin/runit/etc/macosx/org.smarden.runit.plist \ + /Library/LaunchDaemons/ + # launchctl load /Library/LaunchDaemons/org.smarden.runit.plist +</pre> +<hr> +<address><a href="mailto:pape@smarden.org"> +Gerrit Pape <pape@smarden.org> +</a></address> +</body> +</html> diff --git a/runit-2.1.2/doc/utmpset.8.html b/runit-2.1.2/doc/utmpset.8.html new file mode 100644 index 0000000..3b96cb6 --- /dev/null +++ b/runit-2.1.2/doc/utmpset.8.html @@ -0,0 +1,63 @@ + + + +<html> +<head> +<title>utmpset(8) manual page</title> +</head> +<body bgcolor='white'> +<a href='http://smarden.org/pape/'>G. Pape</a><br><a href='index.html'>runit</A><hr><p> + +<h2><a name='sect0'>Name</a></h2> +utmpset - logout a line from utmp and wtmp file +<h2><a name='sect1'>Synopsis</a></h2> +<b>utmpset</b> [ <b>-w</b> +] <i>line</i> +<h2><a name='sect2'>Description</a></h2> +The <b>utmpset</b> program modifies the user accounting database +<i><b>utmp</b>(5)</i> and optionally <i><b>wtmp</b>(5)</i> to indicate that the user on the terminal +<i>line</i> has logged out. <p> +Ordinary <i><b>init</b>(8)</i> processes handle utmp file records +for local login accounting. The <i><b>runit</b>(8)</i> program doesn’t include code to +update the utmp file, the <i><b>getty</b>(8)</i> processes are handled the same as all +other services. <p> +To enable local login accounting, add <b>utmpset</b> to the <i><b>getty</b>(8)</i> +<i>finish</i> scripts, e.g.: <p> + $ cat /service/getty-5/finish<br> + #!/bin/sh<br> + exec utmpset -w tty5<br> + $<br> + +<h2><a name='sect3'>Options</a></h2> + +<dl> + +<dt><b>-w</b> </dt> +<dd>wtmp. Additionally to the utmp file, write an empty record for +<i>line</i> to the wtmp file. </dd> +</dl> + +<h2><a name='sect4'>Exit Codes</a></h2> +<b>utmpset</b> returns 111 on error, 1 on wrong +usage, 0 in all other cases. +<h2><a name='sect5'>See Also</a></h2> +<i>sv(8)</i>, <i>runsv(8)</i>, <i>runit(8)</i>, <i>runit-init(8)</i> +<i>runsvdir(8)</i>, <i>runsvchdir(8)</i>, <i>chpst(8)</i>, <i>svlogd(8)</i>, <i>getty(8)</i> <p> +<i>http://smarden.org/runit/</i> + +<h2><a name='sect6'>Author</a></h2> +Gerrit Pape <pape@smarden.org> <p> + +<hr><p> +<a name='toc'><b>Table of Contents</b></a><p> +<ul> +<li><a name='toc0' href='#sect0'>Name</a></li> +<li><a name='toc1' href='#sect1'>Synopsis</a></li> +<li><a name='toc2' href='#sect2'>Description</a></li> +<li><a name='toc3' href='#sect3'>Options</a></li> +<li><a name='toc4' href='#sect4'>Exit Codes</a></li> +<li><a name='toc5' href='#sect5'>See Also</a></li> +<li><a name='toc6' href='#sect6'>Author</a></li> +</ul> +</body> +</html> diff --git a/runit-2.1.2/etc/2 b/runit-2.1.2/etc/2 new file mode 100755 index 0000000..3bb822d --- /dev/null +++ b/runit-2.1.2/etc/2 @@ -0,0 +1,6 @@ +#!/bin/sh + +PATH=/command:/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin + +exec env - PATH=$PATH \ +runsvdir -P /service 'log: ...........................................................................................................................................................................................................................................................................................................................................................................................................' diff --git a/runit-2.1.2/etc/debian/1 b/runit-2.1.2/etc/debian/1 new file mode 100755 index 0000000..4cd10cb --- /dev/null +++ b/runit-2.1.2/etc/debian/1 @@ -0,0 +1,10 @@ +#!/bin/sh +# system one time tasks + +PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin + +/etc/init.d/rcS +/etc/init.d/rmnologin + +touch /etc/runit/stopit +chmod 0 /etc/runit/stopit diff --git a/runit-2.1.2/etc/debian/2 b/runit-2.1.2/etc/debian/2 new file mode 120000 index 0000000..5fae01f --- /dev/null +++ b/runit-2.1.2/etc/debian/2 @@ -0,0 +1 @@ +../2 \ No newline at end of file diff --git a/runit-2.1.2/etc/debian/3 b/runit-2.1.2/etc/debian/3 new file mode 100755 index 0000000..10354d7 --- /dev/null +++ b/runit-2.1.2/etc/debian/3 @@ -0,0 +1,14 @@ +#!/bin/sh +exec 2>&1 + +PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin + +LAST=0 +test -x /etc/runit/reboot && LAST=6 + +echo 'Waiting for services to stop...' +sv -w196 force-stop /service/* +sv exit /service/* + +echo 'Shutdown...' +/etc/init.d/rc $LAST diff --git a/runit-2.1.2/etc/debian/ctrlaltdel b/runit-2.1.2/etc/debian/ctrlaltdel new file mode 100755 index 0000000..6684457 --- /dev/null +++ b/runit-2.1.2/etc/debian/ctrlaltdel @@ -0,0 +1,9 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +MSG="System is going down in 14 seconds..." + +# echo 'disabled.' ; exit +touch /etc/runit/stopit +chmod 100 /etc/runit/stopit && echo "$MSG" | wall +/bin/sleep 14 diff --git a/runit-2.1.2/etc/debian/getty-tty5/finish b/runit-2.1.2/etc/debian/getty-tty5/finish new file mode 100755 index 0000000..72d719b --- /dev/null +++ b/runit-2.1.2/etc/debian/getty-tty5/finish @@ -0,0 +1,2 @@ +#!/bin/sh +exec utmpset -w tty5 diff --git a/runit-2.1.2/etc/debian/getty-tty5/run b/runit-2.1.2/etc/debian/getty-tty5/run new file mode 100755 index 0000000..6767eae --- /dev/null +++ b/runit-2.1.2/etc/debian/getty-tty5/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec /sbin/getty 38400 tty5 linux diff --git a/runit-2.1.2/etc/freebsd/1 b/runit-2.1.2/etc/freebsd/1 new file mode 100755 index 0000000..2a4492d --- /dev/null +++ b/runit-2.1.2/etc/freebsd/1 @@ -0,0 +1,17 @@ +#!/bin/sh +# system one time tasks + +PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin +trap : 2 +trap : 3 + +sh /etc/rc autoboot +if test $? -ne 0; then + # /etc/rc crashed, start emergency shell. + echo '/etc/rc failed. Press <enter> for emergency shell...' + read input + sh -p + exec reboot +fi +touch /etc/runit/stopit +chmod 0 /etc/runit/stopit diff --git a/runit-2.1.2/etc/freebsd/2 b/runit-2.1.2/etc/freebsd/2 new file mode 120000 index 0000000..5fae01f --- /dev/null +++ b/runit-2.1.2/etc/freebsd/2 @@ -0,0 +1 @@ +../2 \ No newline at end of file diff --git a/runit-2.1.2/etc/freebsd/3 b/runit-2.1.2/etc/freebsd/3 new file mode 100755 index 0000000..f7f9327 --- /dev/null +++ b/runit-2.1.2/etc/freebsd/3 @@ -0,0 +1,15 @@ +#!/bin/sh +exec 2>&1 + +PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin + +echo 'Waiting for services to stop...' +sv -w196 force-stop /service/* +sv exit /service/* + +echo 'Shutdown...' +if test -x /etc/runit/reboot; then + exec reboot +else + exec halt +fi diff --git a/runit-2.1.2/etc/freebsd/ctrlaltdel b/runit-2.1.2/etc/freebsd/ctrlaltdel new file mode 100755 index 0000000..6684457 --- /dev/null +++ b/runit-2.1.2/etc/freebsd/ctrlaltdel @@ -0,0 +1,9 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +MSG="System is going down in 14 seconds..." + +# echo 'disabled.' ; exit +touch /etc/runit/stopit +chmod 100 /etc/runit/stopit && echo "$MSG" | wall +/bin/sleep 14 diff --git a/runit-2.1.2/etc/freebsd/getty-ttyv4/finish b/runit-2.1.2/etc/freebsd/getty-ttyv4/finish new file mode 100755 index 0000000..b53d0af --- /dev/null +++ b/runit-2.1.2/etc/freebsd/getty-ttyv4/finish @@ -0,0 +1,2 @@ +#!/bin/sh +exec utmpset -w ttyv4 diff --git a/runit-2.1.2/etc/freebsd/getty-ttyv4/run b/runit-2.1.2/etc/freebsd/getty-ttyv4/run new file mode 100755 index 0000000..2d5e3dc --- /dev/null +++ b/runit-2.1.2/etc/freebsd/getty-ttyv4/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/libexec/getty Pc ttyv4 diff --git a/runit-2.1.2/etc/macosx/2 b/runit-2.1.2/etc/macosx/2 new file mode 120000 index 0000000..5fae01f --- /dev/null +++ b/runit-2.1.2/etc/macosx/2 @@ -0,0 +1 @@ +../2 \ No newline at end of file diff --git a/runit-2.1.2/etc/macosx/StartupItems/StartupParameters.plist b/runit-2.1.2/etc/macosx/StartupItems/StartupParameters.plist new file mode 100644 index 0000000..14b5116 --- /dev/null +++ b/runit-2.1.2/etc/macosx/StartupItems/StartupParameters.plist @@ -0,0 +1,11 @@ +{ + Description = "runit service supervision"; + Provides = ("runit"); + Requires = ("Disks"); + OrderPreference = "None"; + Messages = + { + start = "Starting runit service supervision"; + stop = "Stopping runit service supervision"; + }; +} diff --git a/runit-2.1.2/etc/macosx/StartupItems/runit b/runit-2.1.2/etc/macosx/StartupItems/runit new file mode 100755 index 0000000..9f0eaf3 --- /dev/null +++ b/runit-2.1.2/etc/macosx/StartupItems/runit @@ -0,0 +1,22 @@ +#!/bin/sh + +## +# runit +## + +. /etc/rc.common + +StartService() { + ConsoleMessage "Starting runit service supervision" + /bin/csh -cf '/sbin/runsvdir-start &' +} +StopService() { + ConsoleMessage "Stopping runit service supervision" + sv -w196 force-stop /service/* + sv exit /service/* +} +RestartService() { + return 0 +} + +RunService "$1" diff --git a/runit-2.1.2/etc/macosx/org.smarden.runit.plist b/runit-2.1.2/etc/macosx/org.smarden.runit.plist new file mode 100644 index 0000000..1331f8a --- /dev/null +++ b/runit-2.1.2/etc/macosx/org.smarden.runit.plist @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>Label</key> + <string>org.smarden.runit</string> + <key>ServiceDescription</key> + <string>runsvdir - starts and monitors a collection of runsv(8) processes</string> + <key>QueueDirectories</key> + <array> + <string>/service</string> + </array> + <key>OnDemand</key> + <false/> + <key>ProgramArguments</key> + <array> + <string>/sbin/runsvdir-start</string> + </array> +</dict> +</plist> diff --git a/runit-2.1.2/etc/openbsd/1 b/runit-2.1.2/etc/openbsd/1 new file mode 100755 index 0000000..eaa3d39 --- /dev/null +++ b/runit-2.1.2/etc/openbsd/1 @@ -0,0 +1,17 @@ +#!/bin/sh +# system one time tasks + +PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin +trap : 2 +trap : 3 + +sh /etc/rc autoboot +if test $? -ne 0; then + # /etc/rc crashed, start emergency shell. + echo '/etc/rc failed. Press <enter> for emergency shell...' + read input + sh -l + exec reboot +fi +touch /etc/runit/stopit +chmod 0 /etc/runit/stopit diff --git a/runit-2.1.2/etc/openbsd/2 b/runit-2.1.2/etc/openbsd/2 new file mode 120000 index 0000000..5fae01f --- /dev/null +++ b/runit-2.1.2/etc/openbsd/2 @@ -0,0 +1 @@ +../2 \ No newline at end of file diff --git a/runit-2.1.2/etc/openbsd/3 b/runit-2.1.2/etc/openbsd/3 new file mode 100755 index 0000000..f7f9327 --- /dev/null +++ b/runit-2.1.2/etc/openbsd/3 @@ -0,0 +1,15 @@ +#!/bin/sh +exec 2>&1 + +PATH=/command:/sbin:/bin:/usr/sbin:/usr/bin + +echo 'Waiting for services to stop...' +sv -w196 force-stop /service/* +sv exit /service/* + +echo 'Shutdown...' +if test -x /etc/runit/reboot; then + exec reboot +else + exec halt +fi diff --git a/runit-2.1.2/etc/openbsd/ctrlaltdel b/runit-2.1.2/etc/openbsd/ctrlaltdel new file mode 100755 index 0000000..6684457 --- /dev/null +++ b/runit-2.1.2/etc/openbsd/ctrlaltdel @@ -0,0 +1,9 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +MSG="System is going down in 14 seconds..." + +# echo 'disabled.' ; exit +touch /etc/runit/stopit +chmod 100 /etc/runit/stopit && echo "$MSG" | wall +/bin/sleep 14 diff --git a/runit-2.1.2/etc/openbsd/getty-ttyC4/finish b/runit-2.1.2/etc/openbsd/getty-ttyC4/finish new file mode 100755 index 0000000..b3c7aa7 --- /dev/null +++ b/runit-2.1.2/etc/openbsd/getty-ttyC4/finish @@ -0,0 +1,2 @@ +#!/bin/sh +exec utmpset -w ttyC4 diff --git a/runit-2.1.2/etc/openbsd/getty-ttyC4/run b/runit-2.1.2/etc/openbsd/getty-ttyC4/run new file mode 100755 index 0000000..c1d9cb9 --- /dev/null +++ b/runit-2.1.2/etc/openbsd/getty-ttyC4/run @@ -0,0 +1,2 @@ +#!/bin/sh +exec /usr/libexec/getty Pc ttyC4 diff --git a/runit-2.1.2/man/chpst.8 b/runit-2.1.2/man/chpst.8 new file mode 100644 index 0000000..43c0b8d --- /dev/null +++ b/runit-2.1.2/man/chpst.8 @@ -0,0 +1,265 @@ +.TH chpst 8 +.SH NAME +chpst \- runs a program with a changed process state +.SH SYNOPSIS +.B chpst +[\-vP012] +[\-u +.IR user ] +[\-U +.IR user ] +[\-b +.IR argv0 ] +[-e +.IR dir ] +[\-/ +.IR root ] +[\-n +.IR inc ] +[-l|-L +.IR lock ] +[-m +.IR bytes ] +[-d +.IR bytes ] +[-o +.IR n ] +[-p +.IR n ] +[-f +.IR bytes ] +[-c +.IR bytes ] +.I prog +.SH DESCRIPTION +.I prog +consists of one or more arguments. +.P +.B chpst +changes the process state according to the given options, and runs +.IR prog . +.SH OPTIONS +.TP +.B \-u \fI[:]user[:group] +setuidgid. +Set uid and gid to the +.IR user 's +uid and gid, as found in +.IR /etc/passwd . +If +.I user +is followed by a colon and a +.IR group , +set the gid to +.IR group 's +gid, as found in +.IR /etc/group , +instead of +.IR user 's +gid. +If +.I group +consists of a colon-separated list of group names, +.B chpst +sets the group ids of all listed groups. +If +.I user +is prefixed with a colon, the +.I user +and all +.I group +arguments are interpreted as uid and gids respectivly, and not looked up in +the password or group file. +All initial supplementary groups are removed. +.TP +.B \-U \fI[:]user[:group] +envuidgid. +Set the environment variables $UID and $GID to the +.IR user 's +uid and gid, as found in +.IR /etc/passwd . +If +.I user +is followed by a colon and a +.IR group , +set $GID to the +.IR group 's +gid, as found in +.IR /etc/group , +instead of +.IR user 's +gid. +If +.I user +is prefixed with a colon, the +.I user +and +.I group +arguments are interpreted as uid and gid respectivly, and not looked up in +the password or group file. +.TP +.B \-b \fIargv0 +argv0. +Run +.I prog +with +.I argv0 +as the 0th argument. +.TP +.B \-e \fIdir +envdir. +Set various environment variables as specified by files in the directory +.IR dir : +If +.I dir +contains a file named +.I k +whose first line is +.IR v , +.B chpst +removes the environment variable +.I k +if it exists, and then adds the environment variable +.I k +with the value +.IR v . +The name +.I k +must not contain =. +Spaces and tabs at the end of +.I v +are removed, and nulls in +.I v +are changed to newlines. +If the file +.I k +is empty (0 bytes long), +.B chpst +removes the environment variable +.I k +if it exists, without adding a new variable. +.TP +.B \-/ \fIroot +chroot. +Change the root directory to +.I root +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 +.I lock +for writing, and obtain an exclusive lock on it. +.I lock +will be created if it does not exist. +If +.I lock +is locked by another process, wait until a new lock can be obtained. +.TP +.B \-L \fIlock +The same as \-l, but fail immediately if +.I lock +is locked by another process. +.TP +.B \-m \fIbytes +limit memory. +Limit the data segment, stack segment, locked physical pages, and total of +all segment per process to +.I bytes +bytes each. +.TP +.B \-d \fIbytes +limit data segment. +Limit the data segment per process to +.I bytes +bytes. +.TP +.B \-o \fIn +limit open files. +Limit the number of open file descriptors per process to +.IR n . +.TP +.B \-p \fIn +limit processes. +Limit the number of processes per uid to +.IR n . +.TP +.B \-f \fIbytes +limit output size. +Limit the output file size to +.I bytes +bytes. +.TP +.B \-c \fIbytes +limit core size. +Limit the core file size to +.I bytes +bytes. +.TP +.B \-v +verbose. +Print verbose messages to standard error. +This includes warnings about limits unsupported by the system. +.TP +.B \-P +pgrphack. +Run +.I prog +in a new process group. +.TP +.B \-0 +Close standard input before starting +.IR prog . +.TP +.B \-1 +Close standard output before starting +.IR prog . +.TP +.B \-2 +Close standard error before starting +.IR prog . +.SH EXIT CODES +.B chpst +exits 100 when called with wrong options. +It prints an error message and exits 111 if it has trouble changing the +process state. +Otherwise its exit code is the same as that of +.IR prog . +.SH EMULATION +If +.B chpst +is called as +.BR envdir , +.BR envuidgid , +.BR pgrphack , +.BR setlock , +.BR setuidgid , +or +.BR softlimit , +it emulates the functionality of these programs from the daemontools package +respectively. +.SH SEE ALSO +sv(8), +runsv(8), +setsid(2), +runit(8), +runit-init(8), +runsvdir(8), +runsvchdir(8) +.P + http://smarden.org/runit/ + http://cr.yp.to/daemontools.html +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/runit-init.8 b/runit-2.1.2/man/runit-init.8 new file mode 100644 index 0000000..4ea33c2 --- /dev/null +++ b/runit-2.1.2/man/runit-init.8 @@ -0,0 +1,63 @@ +.TH runit-init 8 +.SH NAME +init \- a UNIX process no 1 +.SH SYNOPSIS +.B init +[ 0 | 6 ] +.SH DESCRIPTION +.B runit-init +is the first process the kernel starts. +If +.B runit-init +is started as process no 1, it runs and replaces itself with +.BR runit (8). +.P +If +.B runit-init +is started while the system is up, it must be either called as +.B init 0 +or +.B init 6\fR: +.TP +.B init 0 +tells the Unix process no 1 to shutdown and halt the system. +To signal +.BR runit (8) +the system halt request, +.B runit-init +removes all permissions of the file +.I /etc/runit/reboot +(chmod 0), and sets the execute by owner permission of the file +.I /etc/runit/stopit +(chmod 100). +Then a CONT signal is sent to +.BR runit (8). +.TP +.B init 6 +tells the Unix process no 1 to shutdown and reboot the system. +To signal +.BR runit (8) +the system reboot request, +.B runit-init +sets the execute by owner permission of the files +.I /etc/runit/reboot +and +.I /etc/runit/stopit +(chmod 100). Then a CONT signal is sent to +.BR runit (8). +.SH EXIT CODES +.B runit-init +returns 111 on error, 0 in all other cases. +.SH SEE ALSO +runit(8), +runsvdir(8), +runsvchdir(8), +sv(8), +runsv(8), +chpst(8), +utmpset(8), +svlogd(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/runit.8 b/runit-2.1.2/man/runit.8 new file mode 100644 index 0000000..a53cf6e --- /dev/null +++ b/runit-2.1.2/man/runit.8 @@ -0,0 +1,88 @@ +.TH runit 8 +.SH NAME +runit \- a UNIX process no 1 +.SH SYNOPSIS +.B runit +.SH DESCRIPTION +.B runit +must be run as Unix process no 1. +It performs the system's booting, running, and shutdown in three stages: +.SH STAGE 1 +.B runit +runs +.I /etc/runit/1 +and waits for it to terminate. +The system's one time tasks are done here. +.I /etc/runit/1 +has full control of +.I /dev/console +to be able to start an emergency shell if the one time initialization tasks +fail. If +.I /etc/runit/1 +crashes, or exits 100, +.B runit +will skip stage 2 and enter stage 3. +.SH STAGE 2 +.B runit +runs +.IR /etc/runit/2 , +which should not return until system shutdown; if it crashes, or exits 111, +it will be restarted. +Normally +.I /etc/runit/2 +starts +.BR runsvdir (8). +.B runit +is able to handle the ctrl-alt-del keyboard request in stage 2, see below. +.SH STAGE 3 +If +.B runit +is told to shutdown the system, or stage 2 returns, it terminates stage 2 if +it is running, and runs +.IR /etc/runit/3 . +The systems tasks to shutdown and possibly halt or reboot the system are +done here. +If stage 3 returns, +.B runit +checks if the file +.I /etc/runit/reboot +exists and has the execute by owner permission set. +If so, the system is rebooted, it's halted otherwise. +.SH CTRL-ALT-DEL +If +.B runit +receives the ctrl-alt-del keyboard request and the file +.I /etc/runit/ctrlaltdel +exists and has the execute by owner permission set, +.B runit +runs +.IR /etc/runit/ctrlaltdel , +waits for it to terminate, and then sends itself a CONT signal. +.SH SIGNALS +.B runit +only accepts signals in stage 2. +.P +If +.B runit +receives a CONT signal and the file +.I /etc/runit/stopit +exists and has the execute by owner permission set, +.B runit +is told to shutdown the system. +.P +if +.B runit +receives an INT signal, a ctrl-alt-del keyboard request is triggered. +.SH SEE ALSO +runit-init(8), +runsvdir(8), +runsvchdir(8), +sv(8), +runsv(8), +chpst(8), +utmpset(8), +svlogd(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/runsv.8 b/runit-2.1.2/man/runsv.8 new file mode 100644 index 0000000..7c5abfc --- /dev/null +++ b/runit-2.1.2/man/runsv.8 @@ -0,0 +1,225 @@ +.TH runsv 8 +.SH NAME +runsv \- starts and monitors a service and optionally an appendant log +service +.SH SYNOPSIS +.B runsv +.I service +.SH DESCRIPTION +.I service +must be a directory. +.P +.B runsv +switches to the directory +.I service +and starts ./run. +If ./run exits and ./finish exists, +.B runsv +starts ./finish. +If ./finish doesn't exist or ./finish exits, +.B runsv +restarts ./run. +.P +If ./run or ./finish exit immediately, +.B runsv +waits a second before starting ./finish or restarting ./run. +.P +Two arguments are given to ./finish. +The first one is ./run's exit code, or -1 if ./run didn't exit normally. +The second one is the least significant byte of the exit status as +determined by +.BR waitpid (2); +for instance it is 0 if ./run exited normally, and the signal number +if ./run was terminated by a signal. +If +.B runsv +cannot start ./run for some reason, the exit code is 111 and the status is 0. +.P +If the file +.IR service /down +exists, +.B runsv +does not start ./run immediately. +The control interface (see below) can be used to start the service and to +give other commands to +.BR runsv . +.P +If the directory +.IR service /log +exists, +.B runsv +creates a pipe, redirects +.IR service /run's +and +.IR service /finish's +standard output to the pipe, switches to the directory +.IR service /log +and starts ./run (and ./finish) exactly as described above for the +.I service +directory. +The standard input of the log service is redirected to read from the pipe. +.P +.B runsv +maintains status information in a binary format (compatible to the +daemontools' +.B supervise +program) in +.IR service /supervise/status +and +.IR service /log/supervise/status, +and in a human-readable format in +.IR service /supervise/stat, +.IR service /log/supervise/stat, +.IR service /supervise/pid, +.IR service /log/supervise/pid. +.SH CONTROL +The named pipes +.IR service /supervise/control, +and (optionally) +.IR service /log/supervise/control +are provided to give commands to +.BR runsv . +You can use +.BR sv (8) +to control the service or just write one of the following characters to +the named pipe: +.TP +.B u +Up. +If the service is not running, start it. +If the service stops, restart it. +.TP +.B d +Down. +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 +.B o +Once. +If the service is not running, start it. +Do not restart it if it stops. +.TP +.B p +Pause. +If the service is running, send it a STOP signal. +.TP +.B c +Continue. +If the service is running, send it a CONT signal. +.TP +.B h +Hangup. +If the service is running, send it a HUP signal. +.TP +.B a +Alarm. +If the service is running, send it a ALRM signal. +.TP +.B i +Interrupt. +If the service is running, send it a INT signal. +.TP +.B q +Quit. +If the service is running, send it a QUIT signal. +.TP +.B 1 +User-defined 1. +If the service is running, send it a USR1 signal. +.TP +.B 2 +User-defined 2. +If the service is running, send it a USR2 signal. +.TP +.B t +Terminate. +If the service is running, send it a TERM signal. +.TP +.B k +Kill. +If the service is running, send it a KILL signal. +.TP +.B x +Exit. +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 +exits. +If the service is down and a log service exists, +.B runsv +closes the standard input of the log service, and waits for it to terminate. +If the log service is down, +.B runsv +exits. +This command is ignored if it is given to +.IR service /log/supervise/control. +.P +Example: to send a TERM signal to the socklog-unix service, either do + # sv term /service/socklog-unix + or + # printf t >/service/socklog-unix/supervise/control +.P +.BR printf (1) +usually blocks if no +.B runsv +process is running in the service directory. +.SH CUSTOMIZE CONTROL +For each control character +.I c +sent to the control pipe, +.B runsv +first checks if +.I service\fR/control/\fIc +exists and is executable. +If so, it starts +.I service\fR/control/\fIc +and waits for it to terminate, before interpreting the command. +If the program exits with return code 0, +.B runsv +refrains from sending the service the corresponding signal. +The command +.I o +is always considered as command +.IR u . +On command +.I d +first +.I service\fR/control/t +is checked, and then +.I service\fR/control/d. +On command +.I x +first +.I service\fR/control/t +is checked, and then +.I service\fR/control/x. +The control of the optional log service cannot be customized. +.SH SIGNALS +If +.B runsv +receives a TERM signal, it acts as if the character x was written to the +control pipe. +.SH EXIT CODES +.B runsv +exits 111 on an error on startup or if another +.B runsv +is running in +.IR service . +.P +.B runsv +exits 0 if it was told to exit. +.SH SEE ALSO +sv(8), +chpst(8), +svlogd(8), +runit(8), +runit-init(8), +runsvdir(8), +runsvchdir(8), +utmpset(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/runsvchdir.8 b/runit-2.1.2/man/runsvchdir.8 new file mode 100644 index 0000000..f7f94dc --- /dev/null +++ b/runit-2.1.2/man/runsvchdir.8 @@ -0,0 +1,55 @@ +.TH runsvchdir 8 +.SH NAME +runsvchdir \- change services directory of runsvdir(8) +.SH SYNOPSIS +.B runsvchdir +.I dir +.SH DESCRIPTION +.I dir +is a services directory for the use with +.BR runsvdir (8). +If +.I dir +does not start with a slash, it is searched in /etc/runit/runsvdir/. +.I dir +must not start with a dot. +.P +.B runsvchdir +switches to the directory +.IR /etc/runit/runsvdir/ , +copies +.I current +to +.IR previous , +and replaces +.I current +with a symlink pointing to +.IR dir . +.P +Normally +.I /service +is a symlink to +.IR current , +and +.BR runsvdir (8) +is running +.IR /service/ . +.SH EXIT CODES +.B runsvchdir +prints an error message and exits 111 on error. +.B runsvchdir +exits 0 on success. +.SH FILES + /etc/runit/runsvdir/previous + /etc/runit/runsvdir/current + /etc/runit/runsvdir/current.new +.SH SEE ALSO +runsvdir(8), +runit(8), +runit-init(8), +sv(8), +runsv(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/runsvdir.8 b/runit-2.1.2/man/runsvdir.8 new file mode 100644 index 0000000..adfa587 --- /dev/null +++ b/runit-2.1.2/man/runsvdir.8 @@ -0,0 +1,102 @@ +.TH runsvdir 8 +.SH NAME +runsvdir \- starts and monitors a collection of runsv(8) processes +.SH SYNOPSIS +.B runsvdir +[\-P] +.I dir +[ +.I log +] +.SH DESCRIPTION +.I dir +must be a directory. +.I log +is a space holder for a readproctitle log, and must be at least seven +characters long or absent. +.P +.B runsvdir +starts a +.BR runsv (8) +process for each subdirectory, or symlink to a directory, in the services +directory +.IR dir , +up to a limit of 1000 subdirectories, +and restarts a +.BR runsv (8) +process if it terminates. +.B runsvdir +skips subdirectory names starting with dots. +.BR runsv (8) +must be in +.BR runsvdir 's +PATH. +.P +At least every five seconds +.B runsvdir +checks whether the time of last modification, the inode, or the device, of +the services directory +.I dir +has changed. +If so, it re-scans the service directory, and if it sees a new subdirectory, +or new symlink to a directory, in +.IR dir , +it starts a new +.BR runsv (8) +process; +if +.B runsvdir +sees a subdirectory being removed that was previously there, it sends the +corresponding +.BR runsv (8) +process a TERM signal, stops monitoring this process, and so does not +restart the +.BR runsv (8) +process if it exits. +.P +If the +.I log +argument is given to +.BR runsvdir , +all output to standard error is redirected to this +.IR log , +which is similar to the daemontools' +.B readproctitle +log. +To see the most recent error messages, use a process-listing tool such as +.BR ps (1). +.B runsvdir +writes a dot to the readproctitle log every 15 minutes so that old error +messages expire. +.SH OPTIONS +.TP +.B \-P +use +.BR setsid (2) +to run each +.BR runsv (8) +process in a new session and separate process group. +.SH SIGNALS +If +.B runsvdir +receives a TERM signal, it exits with 0 immediately. +.P +If +.B runsvdir +receives a HUP signal, it sends a TERM signal to each +.BR runsv (8) +process it is monitoring and then exits with 111. +.SH SEE ALSO +sv(8), +runsv(8), +runsvchdir(8), +runit(8), +runit-init(8), +chpst(8), +svlogd(8), +utmpset(8), +setsid(2) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/sv.8 b/runit-2.1.2/man/sv.8 new file mode 100644 index 0000000..7ed9852 --- /dev/null +++ b/runit-2.1.2/man/sv.8 @@ -0,0 +1,285 @@ +.TH sv 8 +.SH NAME +sv \- control and manage services monitored by +.BR runsv (8) +.SH SYNOPSIS +.B sv +[\-v] [\-w +.I sec\fR] +.I command +.I services +.P +.BI /etc/init.d/ service +[\-w +.I sec\fR] +.I command +.SH DESCRIPTION +The +.B sv +program reports the current status and controls the state of services +monitored by the +.BR runsv (8) +supervisor. +.P +.I services +consists of one or more arguments, each argument naming a directory +.I service +used by +.BR runsv (8). +If +.I service +doesn't start with a dot or slash and doesn't end with a slash, it is +searched in the default services directory +.IR /service/ , +otherwise relative to the current directory. +.P +.I command +is one of up, down, status, once, pause, cont, hup, alarm, interrupt, 1, 2, +term, kill, or exit, or start, stop, restart, shutdown, force-stop, +force-reload, force-restart, force-shutdown. +.P +The +.B sv +program can be sym-linked to +.I /etc/init.d/ +to provide an LSB init script interface. +The +.I service +to be controlled then is specified by the base name of the ``init script''. +.SH COMMANDS +.TP +.B status +Report the current status of the service, and the appendant log service if +available, to standard output. +.TP +.B up +If the service is not running, start it. +If the service stops, restart it. +.TP +.B down +If the service is running, send it the TERM signal, and the CONT signal. +If ./run exits, start ./finish if it exists. +After it stops, do not restart service. +.TP +.B once +If the service is not running, start it. +Do not restart it if it stops. +.TP +.B pause cont hup alarm interrupt quit 1 2 term kill +If the service is running, send it the STOP, CONT, HUP, ALRM, INT, QUIT, +USR1, USR2, TERM, or KILL signal respectively. +.TP +.B exit +If the service is running, send it the TERM signal, and the CONT signal. +Do not restart the service. +If the service is down, and no log service exists, +.BR runsv (8) +exits. +If the service is down and a log service exists, +.BR runsv (8) +closes the standard input of the log service and waits for it to terminate. +If the log service is down, +.BR runsv (8) +exits. +This command is ignored if it is given to an appendant log service. +.P +.BR sv +actually looks only at the first character of these +.IR command s. +.SS Commands compatible to LSB init script actions +.TP +.B status +Same as +.IR status . +.TP +.B start +Same as +.IR up , +but wait up to 7 seconds for the command to take effect. +Then report the status or timeout. +If the script +.I ./check +exists in the service directory, +.B sv +runs this script to check whether the service is up and available; +it's considered to be available if +.I ./check +exits with 0. +.TP +.B stop +Same as +.IR down , +but wait up to 7 seconds for the service to become down. +Then report the status or timeout. +.TP +.B reload +Same as +.IR hup , +and additionally report the status afterwards. +.TP +.B restart +Send the commands +.IR term , +.IR cont , +and +.I up +to the service, and wait up to 7 seconds for the service to restart. +Then report the status or timeout. +If the script +.I ./check +exists in the service directory, +.B sv +runs this script to check whether the service is up and available again; +it's considered to be available if +.I ./check +exits with 0. +.TP +.B shutdown +Same as +.IR exit , +but wait up to 7 seconds for the +.BR runsv (8) +process to terminate. +Then report the status or timeout. +.TP +.B force-stop +Same as +.IR down , +but wait up to 7 seconds for the service to become down. +Then report the status, and on timeout send the service the +.I kill +command. +.TP +.B force-reload +Send the service the +.I term +and +.I cont +commands, and wait up to 7 seconds for the service to restart. +Then report the status, and on timeout send the service the +.I kill +command. +.TP +.B force-restart +Send the service the +.IR term , +.I cont +and +.I up +commands, and wait up to 7 seconds for the service to restart. +Then report the status, and on timeout send the service the +.I kill +command. +If the script +.I ./check +exists in the service directory, +.B sv +runs this script to check whether the service is up and available again; +it's considered to be available if +.I ./check +exits with 0. +.TP +.B force-shutdown +Same as +.IR exit , +but wait up to 7 seconds for the +.BR runsv (8) +process to terminate. +Then report the status, and on timeout send the service the +.I kill +command. +.TP +.B try-restart +if the service is running, send it the +.I term +and +.I cont +commands, and wait up to 7 seconds for the service to restart. +Then report the status or timeout. + +.SS Additional Commands +.TP +.B check +Check for the service to be in the state that's been requested. +Wait up to 7 seconds for the service to reach the requested state, then +report the status or timeout. +If the requested state of the service is +.IR up , +and the script +.I ./check +exists in the service directory, +.B sv +runs this script to check whether the service is up and running; it's +considered to be up if +.I ./check +exits with 0. +.SH OPTIONS +.TP +.B \-v +If the +.I command +is up, down, term, once, cont, or exit, then wait up to 7 seconds for the +command to take effect. +Then report the status or timeout. +.TP +.B \-w \fIsec +Override the default timeout of 7 seconds with +.I sec +seconds. +This option implies +.IR \-v . +.SH ENVIRONMENT +.TP +.B SVDIR +The environment variable $SVDIR overrides the default services directory +.IR /service/ . +.TP +.B SVWAIT +The environment variable $SVWAIT overrides the default 7 seconds to wait +for a command to take effect. +It is overridden by the \-w option. +.SH EXIT CODES +.B sv +exits 0, if the +.I command +was successfully sent to all +.IR services , +and, if it was told to wait, the +.I command +has taken effect to all services. +.P +For each +.I service +that caused an error (e.g. the directory is not controlled by a +.BR runsv (8) +process, or +.B sv +timed out while waiting), +.B sv +increases the exit code by one and exits non zero. +The maximum is 99. +.B sv +exits 100 on error. +.P +If +.B sv +is called with a base name other than +.BR sv : +it exits 1 on timeout or trouble sending the command; if the +.I command +is +.BR status , +it exits 3 if the service is down, and 4 if the status is unknown; +it exits 2 on wrong usage, and 151 on error. +.SH SEE ALSO +runsv(8), +chpst(8), +svlogd(8), +runsvdir(8), +runsvchdir(8), +runit(8), +runit-init(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/svlogd.8 b/runit-2.1.2/man/svlogd.8 new file mode 100644 index 0000000..01b2324 --- /dev/null +++ b/runit-2.1.2/man/svlogd.8 @@ -0,0 +1,464 @@ +.TH svlogd 8 +.SH NAME +svlogd \- runit's service logging daemon +.SH SYNOPSIS +.B svlogd +[\-tttv] [\-r +.I c\fR] [\-R +.I xyz\fR] [\-l +.I len\fR] [\-b +.I buflen\fR] +.I logs +.SH DESCRIPTION +.I logs +consists of one or more arguments, each specifying a directory. +.P +.B svlogd +continuously reads log data from its standard input, optionally filters log +messages, and writes the data to one or more automatically rotated +.IR logs . +.P +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, and through +udp. +.P +.B svlogd +runs until it sees end-of-file on standard input or is sent a TERM signal, +see below. +.SS LOG DIRECTORY +A log directory +.I log +contains some number of old log files, and the current log file +.IR current . +Old log files have a file name starting with +.I @ +followed by a precise timestamp (see the daemontools' +.B tai64n +program), indicating when +.I current +was rotated and renamed to this file. +.P +A log directory additionally contains the lock file +.IR lock , +maybe +.I state +and +.IR newstate , +and optionally the file +.IR config . +.B svlogd +creates necessary files if they don't exist. +.P +If +.B svlogd +has trouble opening a log directory, it prints a warning, and ignores this +log directory. +If +.B svlogd +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. +.SS LOG FILE ROTATION +.B svlogd +appends selected log messages to the +.I current +log file. +If +.I current +has +.I size +bytes or more (or there is a new-line within the last +.I len +of +.I size +bytes), or is older than a specified amount of +.IR time , +.I current +is rotated: +.P +.B svlogd +closes +.IR current , +changes permission of +.I current +to 0755, renames +.I current +to +.RI @ timestamp\fR.s, +and starts with a new empty +.IR current . +If +.B svlogd +sees +.I num +or more old log files in the log directory, it removes the oldest one. +Note that this doesn't decrease the number of log files if there are +already more than +.I num +log files, this must be done manually, e.g. for keeping 10 log files: +.P + ls \-1 \\@* |sort |sed \-ne '10,$p' |xargs rm +.SS PROCESSOR +If +.B svlogd +is told to process recent log files, it saves +.I current +to +.RI @ timestamp\fR.u, +feeds +.RI @ timestamp\fR.u +through ``sh \-c "\fIprocessor\fR"'' +and writes the output to +.RI @ timestamp\fR.t. +If the +.I processor +finishes successfully, +.RI @ timestamp\fR.t +is renamed to +.RI @ timestamp\fR.s, +and +.RI @ timestamp\fR.u +is deleted; otherwise +.RI @ timestamp\fR.t +is deleted and the +.I processor +is started again. +.B svlogd +also saves any output that the +.I processor +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 +A +.I processor +is run in the background. +If +.B svlogd +sees a previously started +.I processor +still running when trying to start a new one for the same +.IR log , +it blocks until the currently running +.I processor +has finished successfully. +Only the HUP signal works in that situation. +Note that this may block any program feeding its log data to +.BR svlogd. + +.SS CONFIG +On startup, and after receiving a HUP signal, +.B svlogd +checks for each log directory +.I log +if the configuration file +.I log/config +exists, and if so, reads the file line by line and adjusts configuration for +.I log +as follows: +.P +If the line is empty, or starts with a ``#'', it is ignored. +A line of the form +.TP +.RI s size +sets the maximum file size of +.I current +when +.B svlogd +should rotate the current log file to +.I size +bytes. +Default is 1000000. +If +.I size +is zero, +.B svlogd +doesn't rotate log files. +You should set +.I size +to at least (2 * +.IR len ). +.TP +.RI n num +sets the number of old log files +.B svlogd +should maintain to +.IR num . +If +.B svlogd +sees more that +.I num +old log files in +.I log +after log file rotation, it deletes the oldest one. +Default is 10. +If +.I num +is zero, +.B svlogd +doesn't remove old log files. +.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 +to feed each recent log file through +.I processor +(see above) on log file rotation. +By default log files are not processed. +.TP +.RI u a.b.c.d[:port] +tells +.B svlogd +to transmit the first +.I len +characters of selected log messages to the IP address +.IR a.b.c.d , +port number +.IR port . +If +.I port +isn't set, the default port for syslog is used (514). +.I len +can be set through the \-l option, see below. +If +.B svlogd +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. +.TP +.RI U a.b.c.d[:port] +is the same as the +.I u +line above, but the log messages are no longer written to the log directory, +but transmitted through udp only. +Error messages from +.B svlogd +concerning sending udp packages still go to the log directory. +.TP +.RI p prefix +tells +.B svlogd +to prefix each line to be written to the log directory, to standard error, +or through UDP, with +.IR prefix . +.P +If a line starts with a +.IR \- , +.IR + , +.IR e , +or +.IR E , +.B svlogd +matches the first +.I len +characters of each log message against +.I pattern +and acts accordingly: +.TP +.RI \- pattern +the log message is deselected. +.TP +.RI + pattern +the log message is selected. +.TP +.RI e pattern +the log message is selected to be printed to standard error. +.TP +.RI E pattern +the log message is deselected to be printed to standard error. +.P +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 +.I pattern +as follows: +.P +.I pattern +is applied to the log message one character by one, starting with the first. +A character not a star (``*'') and not a plus (``+'') matches itself. +A plus matches the next character in +.I pattern +in the log message one or more times. +A star before the end of +.I pattern +matches any string in the log message that does not include the next +character in +.IR pattern . +A star at the end of +.I pattern +matches any string. +.P +Timestamps optionally added by +.B svlogd +are not considered part of the log message. +.P +An +.B svlogd +pattern is not a regular expression. +For example consider a log message like this +.P + 2005-12-18_09:13:50.97618 tcpsvd: info: pid 1977 from 10.4.1.14 +.P +The following pattern doesn't match +.P + -*pid* +.P +because the first star matches up to the first p in tcpsvd, and then the +match fails because i is not s. +To match this log message, you can use a pattern like this instead +.P + -*: *: pid * +.SH OPTIONS +.TP +.B \-t +timestamp. +Prefix each selected line with a precise timestamp (see the daemontools' +.B tai64n +program) when writing to +.I log +or to standard error. +.TP +.B \-tt +timestamp. +Prefix each selected line with a human readable, sortable UTC timestamp of +the form YYYY-MM-DD_HH:MM:SS.xxxxx when writing to +.I log +or to standard error. +.TP +.B \-ttt +timestamp. +Prefix each selected line with a human readable, sortable UTC timestamp of +the form YYYY-MM-DDTHH:MM:SS.xxxxx when writing to +.I log +or to standard error. +.TP +.B \-r \fIc +replace. +.I c +must be a single character. +Replace non-printable characters in log messages with +.IR c . +Characters are replaced before pattern matching is applied. +.TP +.B \-R \fIxyz +replace charset. +Additionally to non-printable characters, replace all characters found in +.I xyz +with +.I c +(default ``_''). +.TP +.B \-l \fIlen +line length. +Pattern matching applies to the first +.I len +characters of a log message only. +Default is 1000. +.TP +.B \-b \fIbuflen +buffer size. +Set the size of the buffer +.B svlogd +uses when reading from standard input and writing to +.I logs +to +.IR buflen . +Default is 1024. +.I buflen +must be greater than +.IR len . +For +.B svlogd +instances that process a lot of data in short time, the buffer size should +be increased to improve performance. +.TP +.B \-v +verbose. +Print verbose messages to standard error. +.SH SIGNALS +If +.B svlogd +is sent a HUP signal, it closes and reopens all +.IR logs , +and updates their configuration according to +.IR log/config . +If +.B svlogd +has trouble opening a log directory, it prints a warning, and discards this +log directory. +If +.B svlogd +is unable to open all log directories given at the command line, it exits +with an error. +.P +If +.B svlogd +is sent a TERM signal, or if it sees end-of-file on standard input, it stops +reading standard input, processes the data in the buffer, waits for all +.I processor +subprocesses to finish if any, and exits 0 as soon as possible. +.P +If +.B svlogd +is sent an ALRM signal, it forces log file rotation for all +.I logs +with a non empty +.I current +log file. +.SH SEE ALSO +sv(8), +runsv(8), +chpst(8), +runit(8), +runit-init(8), +runsvdir(8), +runsvchdir(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/man/utmpset.8 b/runit-2.1.2/man/utmpset.8 new file mode 100644 index 0000000..4f9b4ef --- /dev/null +++ b/runit-2.1.2/man/utmpset.8 @@ -0,0 +1,63 @@ +.TH utmpset 8 +.SH NAME +utmpset \- logout a line from utmp and wtmp file +.SH SYNOPSIS +.B utmpset +[ +.B \-w +] +.I line +.SH DESCRIPTION +The +.B utmpset +program modifies the user accounting database +.BR utmp (5) +and optionally +.BR wtmp (5) +to indicate that the user on the terminal +.I line +has logged out. +.P +Ordinary +.BR init (8) +processes handle utmp file records for local login accounting. +The +.BR runit (8) +program doesn't include code to update the utmp file, the +.BR getty (8) +processes are handled the same as all other services. +.P +To enable local login accounting, add +.B utmpset +to the +.BR getty (8) +.I finish +scripts, e.g.: +.P + $ cat /service/getty-5/finish + #!/bin/sh + exec utmpset \-w tty5 + $ +.SH OPTIONS +.TP +.B \-w +wtmp. Additionally to the utmp file, write an empty record for +.I line +to the wtmp file. +.SH EXIT CODES +.B utmpset +returns 111 on error, 1 on wrong usage, 0 in all other cases. +.SH SEE ALSO +sv(8), +runsv(8), +runit(8), +runit-init(8) +runsvdir(8), +runsvchdir(8), +chpst(8), +svlogd(8), +getty(8) +.P +http://smarden.org/runit/ +.SH AUTHOR +Gerrit Pape <pape@smarden.org> diff --git a/runit-2.1.2/package/CHANGES b/runit-2.1.2/package/CHANGES new file mode 100644 index 0000000..da4ea27 --- /dev/null +++ b/runit-2.1.2/package/CHANGES @@ -0,0 +1,688 @@ +2.1.2 +Sun, 10 Aug 2014 18:01:54 +0000 + * doc/index.html: reorder, cleanup links to distributions; add Linux + from Scratch, Finnix, VServer. + * sv.c: properly format status command's output on failure cases. + * sv.c: support optional LSB init script actions reload and + try-restart. + * man/sv.8: "sv exit" does not send a TERM signal to the log service + (thx Jonathan Nieder). + * fmt_ptime.c: 64 bits time_t fix for svlogd (tnx Jérémie + Courrèges-Anglas). + * sv.c: fix typo that may lead to wrong output from sv when reporting + status of multiple service directories. + * doc/index.html: add deepOfix Mail Server to list of distributions + that include runit (thx Debayan Banerjee). + * doc/useinit.html: update description on how to use with upstart + (thx Gabriel de Perthuis). + * doc/index.html: add Dragora GNU/Linux to list of distributions that + use runit as default init scheme (thx Matias A. Fonzo). + * doc/index.html: add ArchLinux to list of distributions that include + runit (thx Kevin Berry). + +2.1.1 +Sun, 04 Oct 2009 20:28:38 +0000 + * doc/upgrade.html: fix typo. + * sv.c: on 'down', send runsv the 'down' command properly if not yet + done (e.g. when taken up with 'once'). + +2.1.0 +Thu, 24 Sep 2009 22:49:33 +0000 + * pathexec_env.c, pathexec.h: add function pathexec_env_run(). + * chpst.c, man/chpst.8: new option -b argv0: run prog with different + 0th argument. + * sv.c: fix exit code of status command in lsb mode (thx Mathieu + Poumeyrol) + * chpst.c, svwaitdown.c, svwaitup.c: fix checks for return value of + open_* functions (thx David Reiss). + * runsv.c: exit with error if [log/]supervise/control exists, but is + not a fifo (thx Charlie Brady). + * man/sv.8: clarify which return values apply to the LSB init script + interface. + +2.0.0 +Sun, 15 Jun 2008 15:31:05 +0000 + +1.9.0 +Mon, 05 May 2008 22:00:13 +0000 + * doc/upgrade.html: typo. + * sv.c: service name is also relative to the current directory if it + ends with a slash. + * change default directory for services from /var/service/ to /service/. + * runsv.c: create temporary new status files for log/supervise/ actually + in log/supervise/. + * doc/benefits.html: minor additions. + +1.8.0 +Fri, 21 Sep 2007 00:33:56 +0000 + * man/svlogd.8: add hint on how to manually remove log files after the + number of log files svlogd should maintain has been reduced; add hint + about increasing the buffer size if lots of data is to be processed + in short time. + * chpst.c, uidgid.c: improve error reporting if getpwnam() or getgrnam() + fails; cleanup. + * svlogd.c: don't statically bind local udp socket, but request new + source port for each log message sent through udp. + * runit.c: fix typo in error messages (thx Matthew R. Dempsky); minor + rewording. + * doc/useinit.html: add instructions on how to use with upstart (thx + Lloyd Zusman). + * chpst.c: add explicit braces to avoid ambiguous 'else'. + * uw_tmp.h1: fallback to UTMP_FILE if _PATH_UTMP is not defined as seen + on AIX 5.2 ML1, AIX 5.3 ML5 (thx Daniel Clark). + * sv.c: fix race on check for down if pid is 0 and state is run or finish. + * runit.c: speed up collecting zombies. + * runit.c: force check for zombies after a 14 second timeout without + signals (CHLD, CONT, INT). + * doc/index.html: typo. + * doc/*.html: remove $Id$. + +1.7.2 +Tue, 21 Nov 2006 15:13:47 +0000 + * doc/index.html: add list of distributions that are known to include + or package runit; some reordering. + * doc/replaceinit.html: point to faq.html#create, faq.html#tell (thx + David Kaufman). + * doc/runscripts.html: point to faq.html#createlog. + * runit.c: fix arguments to wait_pid() after fork for reboot_system() + (thx Jan Kampe). + * man/runsv.8: suggest printf t instead of echo -n t. + * runsv.c: really don't act on commands in state finish; minor. + +1.7.1 +Sat, 04 Nov 2006 19:23:29 +0000 + * chpst.c, uidgid.c, uidgid.h: support numerical uid gid through + chpst -[u|U] :uid:gid... + * man/chpst.8: adapt; clarify that users and groups are looked up in + /etc/passwd and /etc/group only. + * sv.c: properly wait for a service to be restarted on 'restart'; + support checks through -v for pause, cont, kill. + * doc/runscripts.html: add contributed run scripts (thx Kevin, marlowe, + ed neville, xavier dutoit). + +1.7.0 +Sat, 07 Oct 2006 18:24:17 +0000 + * svlogd.c, fmt_ptime.*, man/svlogd.8: new option -ttt: prefix log + messages with sortable UTC timestamp YYYY-MM-DDTHH:MM:SS.xxxxx. + * runsv.c, runsv.8: give two arguments to ./finish: exit code and exit + status of ./run (mostly copied from pipe-tools' npt-supervise, thx + Laurent Bercot). + * runit.c: don't make console the controlling terminal for process 1, + but for stage 1 only; fork before initiating system halt or reboot, + the linux kernel calls do_exit(0) in kernel/sys.c (thx Jan Kampe). + +1.6.0 +Thu, 29 Jun 2006 07:52:35 +0000 + * svlogd.c: cleanup *.t files possibly leftover by processor when + interrupted by signal, also on startup (thx Andras Korn, + http://bugs.debian.org/369840); 1st rename .t to .s, then remove .u. + * man/svlogd.8: adapt. + * svlogd.c: prepend optional timestamp to log messages sent through UDP, + as done for messages written to dir and to stderr. + * uidgid.c: properly fixup user/group argument on getpwnam() error. + * doc/benefits.html: typo; wording. + +1.5.1 +Wed, 10 May 2006 20:55:35 +0000 + * runsv.c: delay restart of log service at least 1 sec, just as the main + service. + * runsvdir.c: don't double-copy filedescriptor. + * package/README, package/COPYING: 2006. + * man/runsvctrl.8, man/runsvstat.8, man/svwaitup.8, man/svwaitdown.8, + doc/runsvctrl.html, doc/runsvstat.html, doc/svwaitdown.html, + doc/svwaitup.html: remove; obsolete. + +1.5.0 +Sun, 16 Apr 2006 12:26:50 +0000 + * man/runsvdir.8: document that the services directory is re-scanned if + the time of last modification, the inode, or the device has changed. + * sv.c: don't report success on 'sv start' if the service is in state + finish (thx Matthew R. Dempsky). + * svlogd.c: new config line p: optionally prefix each line written to + logs, stderr, or through udp; no longer skip empty lines (just + containing '\n'), old behavior can be restored with '-' in config. + * man/svlogd.8: document new p config line; adapt. + +1.4.1 +Mon, 20 Mar 2006 18:54:41 +0000 + * doc/faq.html: typos; add usercontrol, userservices; minor. + * src/uidgid.h: use uid_t, git_t (fix setting of multiple groups with + dietlibc, thx Tino Keitel, http://bugs.debian.org/356016) + +runit 1.4.0 +Mon, 06 Mar 2006 12:45:08 +0000 + * doc/faq.html: new. + * doc/benefits.html: use sv program instead of runsvstat, runsvctrl; + minor. + * doc/replaceinit.html, doc/runlevels.html: put getty service directory + into /etc/sv/. + * doc/runscripts.html: use sv program instead of svwaitup. + * etc/*/3, etc/macosx/StartupItems/runit: use sv program instead of + svwaitdown. + * man/runsv.8: use sv program instead of runsvctrl. + * man/sv.8: minor. + * Makefile, package/commands: no longer build/install runsvctrl, + runsvstat, svwaitdown, svwaitup. + * man/runsvctrl.8, man/runsvstat.8, man/svwaitdown.8, man/svwaitup.8: + remove; obsolete. + * doc/index.html: add faq; remove runsvctrl, runsvstat, svwaitdown, + svwaitup. + * sv: fix usage output. + * chpst: new option -d, limit data segment per process; don't use nested + functions. + +runit 1.3.3 +Mon, 02 Jan 2006 20:35:34 +0000 + * chpst.c: adjust nice value and set limits before dropping permissions. + * sv.c: new additional command 'check'; with -v check for CONT through + ./check if service is up. + * man/sv.8: adapt. + +runit 1.3.2 +Sun, 18 Dec 2005 11:22:04 +0000 + * svlogd.c: don't print extra newlines to the log if additionally writing + to the network through udp (thx Andras Korn, + http://bugs.debian.org/339030). + * runsvdir.c: also process svdir changes if mtime of svdir has changed into + the past (thx Martin Dickopp). + * doc/index.html: update description; Please contact this list and not me + privately. + * doc/replaceinit.html, doc/runscripts.html: minor. + * man/chpst.8: -U doesn't support a list of groups. + * man/svlogd.8: update PATTERN MATCHING section, add example (based on + sugesstions from Joshua N Pritikin). + * man/*8: update SEE ALSO sections: runsvctrl, runsvstat, svwaitdown, + svwaitup will become obsolete; remove references to man pages for + programs from the daemontools package. + +runit 1.3.1 +Wed, 24 Aug 2005 20:14:17 +0000 + * doc/runscripts.html: typo; openssh needs absolute path (thx Kevin Berry); + exec into dhcpcd. + * uidgid.c, uidgid.h, chpst.c: support colon-separated list of groups. + * sv.c: utilize optional ./check script in service directory to check for + availablity of service. + * runsv.c: wait_pid() might be interupted. + * man/chpst.8, man/sv.8: adapt. + +runit 1.3.0 +Sun, 24 Jul 2005 16:50:55 +0000 + * man/runsv.8: typo; no longer document the e control character; clarify + custom control on d and x. + * doc/useinit.html: how to use runit with macosx 10.4 (thx Lars Uffmann). + * etc/macosx/org.smarden.runit.plist: new; launchd plist file for + runsvdir-start (thx Lars Uffmann). + * doc/runscripts.html: don't use absolute pathnames for programs in $PATH; + add contributed run scripts (thx Sascha Huedepohl); typos. + * runsvchdir.c, runsvstat.c: optimize output buffer handling. + * runsvctrl.c: write x control character to runsv on e. + * svlogd.c: write to log dir after possibly writing through udp (fixes + line break issue). + * runsv.c, runsv.check: optimize output buffer handling; porperly run + custom t, d, x, k, when stopping service; no longer support e control + character. + * sv.c: new sv program to control services, optionally can be linked to + /etc/init.d/ as lsb "init script" command line interface. + * Makefile, TARGETS: adapt. + * chpst.c: fix pointer types. + * man/sv.8: new. + * package/TODO: new. + +runit 1.2.3 +Mon, 18 Apr 2005 17:08:35 +0000 + * doc/runscripts.html: add contributed run scripts (thx Kevin Berry); + remove mysql run scripts. + * svlogd.dist, svwaitdown.dist, svwaitup.dist: fix program selftest's + false alarms (thx Ian Stokes-Rees). + +runit 1.2.2 +Sun, 03 Apr 2005 09:21:52 +0000 + * doc/index.html, doc/replaceinit.html: no longer refer to sysvinit's + shutdown program. + * man/svlogd.8: svlogd doesn't decrease the number of log files in a log + directory; with n0 don't remove any log files. + * svlogd.c: properly prefix log messages written to standard error with + optional timestamp. + * runsvctrl.c, svwaitdown.c, svwaitup.c: supervise not running -> runsv + not running. + * package/README: 2005. + +runit 1.2.1 +Sat, 15 Jan 2005 11:57:46 +0000 + * chpst.c: typo. + * svwaitdown.c: minimum timeout is 1 second; service directories no longer + must start with /. + * svwaitup.c: minimum uptime of services is 1 second; service directories + no longer must start with /; print number of seconds a service is up if + verbose. + * man/svwaitdown.8, man/svwaitup.8: adapt. + * doc/runscripts.html: add contributed run scripts (thx Stefan Karrmann, + Kevin Berry, Karl Chen). + * runsv.c: typos; bugfix: run optional control/x when receiving SIGTERM + (thx Vladimir Smelhaus); minor. + * man/runsvctrl.8: minor. + * package/COPYING: adapt, 2005. + +runit 1.2.0 +Fri, 17 Dec 2004 21:08:50 +0000 + * doc/upgrade.html: typo. + * runsv.c: support custom control commands through control/ directory, + optionally switch off sending signal; don't update timestamp in status + when running ./finish; only sleep for a second if ./run has been + restarted within a second, and after updating status to down, normally + up, want up. + * man/runsv.8: document custom control commands. + * runsv.check, runsv.dist: check custom control commands. + * doc/runscripts.html: add contributed run scripts (thx Stefan Karrmann, + Kevin Berry). + +runit 1.1.0 +Sat, 06 Nov 2004 17:21:11 +0000 + * svlogd.c: new config option t timeout (thx Enrico Scholz); config + options e and E select and deselect lines for stderr respectively (thx + Vladimir Smelhaus); 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: add 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 + Scholz); properly retry writing to current on error; minor. + * 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. + * package/check, package/compile, package/install, package/install-man, + package/upgrade: use set -e instead of #!/bin/sh -e. + * runsvdir.c: new option -P, run each runsv process in a new session and + process group (thx Charlie Brady). + * man/runsvdir.8: adapt; typo. + +runit 1.0.4 +Sun, 01 Aug 2004 18:29:36 +0000 + * doc/runlevels.html, doc/upgrade.html, doc/useinit.html, man/runsvdir.8, + man/runsvchdir.8: minor changes in wording, notations. + * runsvdir.c: check services dir again after one second until it's + unchanged (thx Eric Lammerts); sleep one second before scanning if + services dir mtime is now; loop while chdir to starting dir fails; + rename log, loglen to rplog, rploglen. + * etc/macosx/StartupItems/runit: use -x option to svwaitdown; timeout 14. + +runit 1.0.3 +Sat, 26 Jun 2004 14:50:41 +0000 + * chpst.c, man/chpst.8: new option -/ chroot. + * runit.c, man/runit.8: if stage 1 crashes or exits 100, stage 2 will be + skipped; if stage 2 crashes or exits 111, it will be restarted. + * package/check, package/compile, package/install-man, package/upgrade: + minor cleanup. + * doc/runscripts.html: add, adapt various run scripts (thx). + +runit 1.0.2 +Mon, 29 Mar 2004 17:52:50 +0000 + * man/svlogd.8: timestamps are not considered when matching patterns (thx + Andras KORN). + * runsv.c: on exit run the finish scripts when taking the service down + (thx X.). + * runsv.c, runsvctrl.c: handle sig_quit (thx Wayne Marshall). + * svlogd.c: don't crash on zero byte long config file (thx Alex Efros). + * man/*: minor cleanup. + * doc/index.html: add link to runit on linuxfromscratch doc (thx Richard + A Downing FBCS). + +runit 1.0.1 +Sun, 07 Mar 2004 10:40:40 +0000 + * doc/usedietlibc.html: minor. + * fmt_ptime.c: create timestamps in UTC, not localtime. + * chpst.c: -e dir: silently ignore directories, print warning if verbose. + * runsv.c: allow also log/supervise to be a dangling symlink; more + meaningful error message if opening lock or locking fails. + * check-diff, check-dist, check-local, package/check: new; run checks on + programs. + * package/install: run package/check. + * chpst.check, runit-init.check, runit.check, runsv.check, + runsvchdir.check, runsvctrl.check, runsvdir.check, runsvstat.check, + svlogd.check, svwaitdown.check, svwaitup.check, utmpset.check: new; + check program. + * chpst.dist, runit-init.dist, runit.dist, runsv.dist, runsvchdir.dist, + runsvctrl.dist, runsvdir.dist, runsvstat.dist, svlogd.dist, + svwaitdown.dist, svwaitup.dist, utmpset.dist: new; dist check program + output. + +runit 1.0.0 +Tue, 10 Feb 2004 13:37:28 +0000 + * doc/benefits.html, doc/dependencies.html, doc/index.html, + doc/replaceinit.html, doc/runlevels.html, doc/upgrade.html, + doc/useinit.html: cleanup; minor. + * man/utmpset.8: run utmpset in finish script, not run script. + * man/runsvdir.8: minor. + +runit 0.13.1 +Mon, 19 Jan 2004 18:32:58 +0000 + * doc/upgrade.html: typo. + * svlogd.c: bugfix: properly print new-line character to the log on end + of line (thx Pawel Chmielowski). + * trysocketlib.c: new; check for libraries needed for socket() on some + systems (fixes link failure on solaris, thx Uffe Jakobsen). + * Makefile: adapt. + * print-cc.sh, print-ld.sh: head -1 -> head -n1. + +runit 0.13.0 +Mon, 12 Jan 2004 14:39:38 +0000 + * doc/runscripts.html: use html named entities (thx Taj Khattra); add + more contributed run scripts (thx Marek Bartnikowski, Thomas Schwinge). + * svlogd.c: support sending log entries to remote host through udp, + configurable through u and U lines in log dir config file; minor. + * man/svlogd.8: adapt; document -tt option. + * package/compile, package/install-man, package/upgrade: exit 1 on + sub-shell failures. + * man/runsv.8: fix typos (thx Christian Hammers). + +runit 0.12.1 +Tue, 18 Nov 2003 15:42:44 +0000 + * doc/runscripts: add pppd run script (with chpst) next to the ppp one. + * man/chpst.8: typo. + * etc/debian/3: test -r -> test -x (thx Alejandro Mery). + * runsv.c: don't start new processes while collecting children. + +runit 0.12.0 +Wed, 29 Oct 2003 18:27:48 +0000 + * runsv.c: don't use EOVERFLOW as it is not standard (thx Christoph + Scheurer). + * reboot_system.h1, reboot_system.h2, tryreboot.c: new; test if reboot() + function takes one or two arguments (solaris). + * runit.c: fallthrough stage 3: re-get stderr; sync() before reboot(). + * uw_tmp.h1, uw_tmp.h2, tryuwtmp.c, tryuwtmpx.c: new; test for utmpx or + utmp support. + * utmpset.c: support systems with utmp or utmpx (solaris). + * Makefile: adapt. + * supports the solaris platform (thx Uffe Jakobsen). + * doc/benefits.html, doc/index.html, doc/replaceinit.html, + doc/runlevels.html, doc/useinit.html: default service directory is + /var/service; minor. + * etc/2, etc/debian/3, etc/freebsd/3, etc/macosx/StartupItems/runit, + etc/openbsd/3, man/runsv.8, man/runsvchdir.8, man/runsvdir.8: default + service directory is /var/service. + * doc/runscripts.html: add more contributed run scripts (thx Tomasz + Nidecki). + +runit 0.11.2 +Tue, 23 Sep 2003 10:15:32 +0200 + * doc/useinit.html, etc/macosx/StartupItems/runit: don't use /etc/runit/2 + when using runit service supervision with traditional init, use + /sbin/runsvdir-start instead. + * fmt_ptime.c: calculate UTC localtime correctly. + * runsv.c: support ./supervise as symbolic link, on dangling symlink create + link target. + +runit 0.11.1 +Thu, 4 Sep 2003 11:51:02 +0200 + * src/Makefile: add dependency to sysdeps to target fmt_ptime.o (thx Thomas + Schwinge). + * svlogd.c: barf if all log directories given at the command line fail. + * man/svlogd.8: adapt. + * doc/runscripts.html: adaptions (thx Erich Schubert, Lang Martin). + +runit 0.11.0 +Fri, 08 Aug 2003 12:37:14 +0200 + * uidgid.c, uidgid.h: new; get uid/gid by name. + * chpst: new; run program with a changed process state (includes envdir, + envuidgid, pgrphack, setlock, setuidgid, softlimit functionality). + * setuidgid.c: remove; obsolete (replaced by chpst). + +runit 0.10.0 +Sun, 22 Jun 2003 20:44:58 +0200 + * doc/index.html, doc/install.html, doc/replaceinit.html, doc/useinit.html: + how to install and configure runit on MacOSX. + * svlogd.c: typo; fix incorrect handling of processor's state file; minor + code cleanup; correctly calculate size for all types of timestamps. + * runit-init.c: exit 0 on wrong usage. + * package/versions: new. + +runit 0.9.5 +Tue, 17 Jun 2003 10:48:10 +0200 + * runit.c: use select() on systems that don't provide poll(). + * svlogd.c: reset match flag in lineflush() in all cases. + * Makefile: build setuidgid in default target. + * doc/useinit.html: add instruction to create /etc/runit/2 first. + * doc/install.html: minor. + +runit 0.9.4 +Wed, 04 Jun 2003 13:56:33 +0200 + * svlogd.c: default log file size is 1M; print verbose message only if + -v is set. + * man/svlogd.8: document -v option; minor. + * etc/freebsd/3, etc/openbsd/3: check if magic files in /etc/runit/ are + executable, not readable. + * etc/*/getty-tty*/run: remove utmpset from script. + * etc/*/getty-tty*/finish: new: run utmpset. + * doc/replaceinit.html: adapt. + * setuidgid.c: new: daemontools' setuidgid drop in replacement (not + installed by default). + * Makefile: build setuidgid. + * doc/index.html: update. + +runit 0.9.3 +Sun, 04 May 2003 11:30:58 +0200 + * Makefile: actually build runsvstat, runsvctrl before installing them, + fixes build failure (thx Lukas Beeler). + * runsvctrl.c, runsvstat.c: use _exit(). + +runit 0.9.2 +Sat, 03 May 2003 17:40:23 +0200 + * doc/runscripts.html: changes from Jesse Cablek. + * doc/dependencies.html, doc/useinit.html: new. + * doc/index.html: adapt; reorder programs; runsvstat, runsvctrl installed + by default. + * doc/install.html: remove dependency on daemontools; create /package. + * doc/replaceinit.html, man/runsv.8: typos. + * man/svwaitdown.8, man/svwaitup.8: refer to runit and supervise. + * svlogd.c: fix counter var namespace. + * package/commands: add runsvctrl, runsvstat. + +runit 0.9.1 +Wed, 30 Apr 2003 22:10:57 +0200 + * svlogd.c: reset match flag on deselection, fixes pattern matching. + +runit 0.9.0 +Fri, 25 Apr 2003 09:22:03 +0200 + * runsvdir.c: don't propagate sig_term to runsv processes when receiving + sig_term; send sig_term to all runsv processes and exit 111 when + receiving sig_hangup. + * runit.c: print warning for each state that exits non-zero; restart + stage 2 if it exits non-zero. + * svlogd.c: code cleanup. + * svwaitdown.c: send command 'd' (and 'x' if -x is set) to each service if + it's not in state 'want down'. + * svwaitup.c: minor code cleanup. + * man/runsvdir.8, man/svwaitdown.8: adapt. + * doc/runscripts.html: add contributed run scripts (thx!). + * doc/upgrade.html, doc/index.html: adapt. + +runit 0.8.4 +Sun, 20 Apr 2003 19:31:24 +0200 + * svlogd.c: new; runit's service logging daemon. + * fmt_ptime.h, fmt_ptime.c, pmatch.h, pmatch.c: new. + * man/svlogd.8, doc/svlogd.8.html: new. + * man/runsv.8, man/runsvstat.8, man/utmpset.8: minor cleanup. + +runit 0.8.1 +Wed, 12 Mar 2003 15:10:04 +0100 + * runsvdir.c, runsv.c: close-on-exec file descriptors of current dir and + lock files (thx Lukas Beeler). + * doc/runscripts.html: add contributed run scripts (thx Robin S. Socha, + Claus Alboege, Paul Jarc, clemens fischer, Jesse Cablek). + +runit 0.8.0 +Tue, 25 Feb 2003 16:17:34 +0100 + * doc/benefits.html: new. + * doc/index.html, doc/upgrade.html: adapt. + * etc/*/1, etc/*/3, etc/*/ctrlaltdel: set permissions on the magic files + instead of creating and removing them (can make them symbolic links + now); set PATH. + * runit.h: new; centralize runit's compiled in magic file names. + * runit.c: check permissions of magic files instead of sole existence; + conditionally call reboot(RB_AUTOBOOT), reboot(RB_POWER_OFF), + reboot(RB_HALT_SYSTEM) if possible; code cleanup. + * runit-init.c: set permissions on magic files instead of creating or + removing them; code cleanup. + * runsvdir.c: detect and tolerate system time warp; code cleanup. + * runsv.c, runsvchdir.c, runsvctrl.c, runsvstat.c, svwaitdown.c, + svwaitup.c, utmpset.c: code cleanup. + * man/runit.8, man/runit-init.8: adapt. + +runit 0.7.2 +Fri, 10 Jan 2003 21:34:13 +0100 + * runsv.c: close finish script file descriptor. + * runsv.c: close logpipe[] instead of sending sigterm to logservice when + told to exit, loggers should exit when they see EOF on stdin (thx Paul + Jarc). + * etc/*/1, etc/*/3: remove explicit 'exit'. + * error.h: include <errno.h> (upcoming glibc changes). + +runit 0.7.1 +Wed, 23 Oct 2002 11:40:24 +0200 + * man/runsv.8, doc/runlevels.html: typos. + * runsvctrl.c, runsvstat.c: exit 111 on error. + * runsvdir.c: continue reading directory when stat() on entry fails. + * doc/runsvstat.8.html,doc/runsvctrl.8.html: new. + * runsvstat, runsvctrl: new; optional svc, svstat replacements. + * doc/index.html: adapt; new example. + +runit 0.7.0 +Mon, 07 Oct 2002 11:26:27 +0200 + * runsvdir.c: check service directory's inode and device in addition + to mtime; sleep at least 1 second before restarting runsv processes. + * runsv.c: use status[19] for state information; control pipe supports e. + * runsvstat.c: new option -l: only show log service if -l is given; use + status[19] for state. + * runsvchdir: new; change directory runsvdir is running in (switch + runlevels). + * man/runsvchdir.8, doc/runsvchdir.8.html: new. + * svwaitdown.c: -k option: only kill service that still are up on timeout. + +runit 0.6.0 +Fri, 27 Sep 2002 16:34:57 +0200 + * man/runsv.8, man/runsvdir.8: new. + * doc: use runsvdir/runsv instead of svscanboot/supervise. + * svwaitdown.c, svwaitup.c, man/svwaitdown.8, man/svwaitup.8: services + must start with slash. + * svwaitdown: new option -x: wait for runsv to exit instead for the + service to be down; new option -k: SIGKILL still running services if + timeout is reached. + * stage 3: use new svwaitdown options. + +runit 0.5.3 +Mon, 23 Sep 2002 16:25:07 +0200 + * runsv, runsvdir: new; svscan/supervise replacement. + * etc/runit/2: use runsvdir instead of svscanboot. + * runsvstat.c: new; svstat for runsv. + * runsvctrl.c: new; svc for runsv. + * runsvdir.c, runsv.c: code cleanup. + * utmpset.c: setlock utmp and wtmp file. + +runit 0.5.0 +Wed, 28 Aug 2002 11:18:28 +0200 + * utmpset: avoids libutil; compiles with dietlibc; built by default. + * doc/usedietlibc.html: fix description. + * getty-*/run: add utmpset. + +runit 0.4.1 +Mon, 24 Jun 2002 15:53:11 +0200 + * utmpset.c: new option -w: additionally write wtmp record. + +runit 0.4.0 +Sun, 19 May 2002 12:28:29 +0200 + * src/: include public domain sources to build byte.a, unix.a, time.a: + runit builds without having daemontools' sources installed. + * utmpset.c: new utmpset program. + * doc/utmpset.html: new. + +runit 0.3.2 +Wed, 13 Feb 2002 10:56:17 +0100 + * runit.c: support ctrl-alt-del also on Linux/i386, dietlibc. + * runscripts.html: more samples. (thx Alessandro Bono) + +runit 0.3.1 +Sun, 3 Feb 2002 16:30:55 +0100 + * src: cleanup. + +runit 0.3.0 +Tue, 29 Jan 2002 19:38:33 +0100 + * doc: adapted. + * runit.8: changes documented. + * runscripts.html: more examples. + +runit 0.2.9 +Thu, 17 Jan 2002 19:00:44 +0100 + * reportedly runs on FreeBSD 4.3 (thx clemensF) + * svwaitdown: max timeout is 6000, really. (thx ska) + * runit.c: stage 1 gets no new session and full control of console; an + emergency shell or login program (if present) can be executed. + * openbsd, freebsd: support for 'single user' emergency shell in stage 1 + * runit.c: skip stage 2 if stage 1 crashes. + +runit 0.2.7 +Tue, 1 Jan 2002 16:20:14 +0100 + * tested on fresh freebsd 4.4 installation in vmware + * new etc/freebsd: stages and getty service + * doc: replaceinit: how to replace bsd init (freebsd) + * svwaitup: minor code cleanup + * doc: /service/getty-5/ as default getty service. + * doc: index: related links added. + * package: install-man added for installing manpages in /usr/local/man/ + +runit 0.2.6 +Sun, 30 Dec 2001 17:29:29 +0100 + * runs on openbsd 2.9 + * runit: console init and reinit + * runit: sig_pause() on end. + * new: etc/openbsd: stages and getty service + * doc: replaceinit: how to replace bsd init + +runit 0.2.3 +Thu, 27 Dec 2001 14:41:56 +0100 + * doc: runscripts.html integrated + +runit 0.2.2 +Sun, 23 Dec 2001 18:12:29 +0100 + * runit: checks for pid == 1 + * new: svwaitdown, svwaitup, svwaitdown.8, svwaitup.8 + * stage3: uses svwaitdown + * doc: runscripts.html added + +runit 0.2.0 +Mon, 26 Nov 2001 12:29:44 +0100 + * runit-halt, runit-reboot removed, integrated into runit-init + * tested with dietlibc + * doc: usedietlibs.html added. + * BSD license. + +runit 0.1.2 +Thu, 22 Nov 2001 18:29:05 +0100 + * collects all terminated children in all stages + * sends sigkill to whole process group if stage2 crashes and waits + 5 seconds before restarting + * ctraltdel not automatically shuts down, now respects /etc/runit/stopit + * /etc/runit/ctrlaltdel touches /etc/runit/stopit + * on shutdown request: send sigterm to stage 2, wait max 5 second, send + sigkill if still running, leave stage 2, enter stage 3 + +runit 0.1.1 +Tue, 20 Nov 2001 11:56:58 +0100 + * package moved to smarden.org + +runit 0.1.0 +Fri, 16 Nov 2001 14:01:27 +0100 + * documention + * debian package + +runit 0.0.4 +Sun, 11 Nov 2001 19:07:49 +0100 + * initial release diff --git a/runit-2.1.2/package/COPYING b/runit-2.1.2/package/COPYING new file mode 100644 index 0000000..d24d1d2 --- /dev/null +++ b/runit-2.1.2/package/COPYING @@ -0,0 +1,24 @@ +Copyright (c) 2001-2008, Gerrit Pape +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/runit-2.1.2/package/README b/runit-2.1.2/package/README new file mode 100644 index 0000000..430fac5 --- /dev/null +++ b/runit-2.1.2/package/README @@ -0,0 +1,3 @@ +Copyright 2001-2006 +G. Pape +http://smarden.org/runit/ diff --git a/runit-2.1.2/package/THANKS b/runit-2.1.2/package/THANKS new file mode 100644 index 0000000..b84e3fe --- /dev/null +++ b/runit-2.1.2/package/THANKS @@ -0,0 +1,2 @@ +Thanks to D. J. Bernstein for his daemontools package and for putting the +daemontools' library code into the public domain. diff --git a/runit-2.1.2/package/TODO b/runit-2.1.2/package/TODO new file mode 100644 index 0000000..6c2bd6c --- /dev/null +++ b/runit-2.1.2/package/TODO @@ -0,0 +1,8 @@ +rewrite doc/benefits.html +rewrite doc/index.html +add doc/uselsb.html +have sv replace runsvctrl, runsvstat, svwaitdown, svwaitup +rewrite doc/dependencies.html: weak/string deps +runsv: provide ./run's return code to ./finish, count startups of ./run and + provide number to ./run +chpst: -u user[:group0[:group1 ...]] diff --git a/runit-2.1.2/package/check b/runit-2.1.2/package/check new file mode 100755 index 0000000..7662e74 --- /dev/null +++ b/runit-2.1.2/package/check @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +umask 022 +test -d package || sh -cx '! : Wrong working directory.' +test -d compile || sh -cx '! : Wrong working directory.' + +echo 'Checking commands in ./command...' +sh -cxe 'cd compile; exec make check' diff --git a/runit-2.1.2/package/commands b/runit-2.1.2/package/commands new file mode 100644 index 0000000..043d245 --- /dev/null +++ b/runit-2.1.2/package/commands @@ -0,0 +1,9 @@ +chpst +runit +runit-init +runsv +runsvchdir +runsvdir +sv +svlogd +utmpset diff --git a/runit-2.1.2/package/compile b/runit-2.1.2/package/compile new file mode 100755 index 0000000..0ed142e --- /dev/null +++ b/runit-2.1.2/package/compile @@ -0,0 +1,27 @@ +#!/bin/sh +set -e + +umask 022 +test -d package || sh -cx '! : Wrong working directory.' +test -d src || sh -cx '! : Wrong working directory.' + +here=`env - PATH=$PATH pwd` + +mkdir -p compile command +test -r compile/home || echo $here >compile/home +test -h compile/src || ln -s $here/src compile/src + +echo 'Linking ./src/* into ./compile...' +for i in `ls src`; do + test -h compile/$i || ln -s src/$i compile/$i +done + +echo 'Compiling everything in ./compile...' +sh -cxe 'cd compile; exec make' + +echo 'Copying commands into ./command...' +for i in `cat package/commands`; do + rm -f command/$i'{new}' + cp -p compile/$i command/$i'{new}' + mv -f command/$i'{new}' command/$i +done diff --git a/runit-2.1.2/package/install b/runit-2.1.2/package/install new file mode 100755 index 0000000..4e3c468 --- /dev/null +++ b/runit-2.1.2/package/install @@ -0,0 +1,6 @@ +#!/bin/sh +set -e + +package/compile +package/check +package/upgrade diff --git a/runit-2.1.2/package/install-man b/runit-2.1.2/package/install-man new file mode 100755 index 0000000..cd49048 --- /dev/null +++ b/runit-2.1.2/package/install-man @@ -0,0 +1,26 @@ +#!/bin/sh +set -e + +umask 022 +test -d package || sh -cx '! : Wrong working directory.' +test -d man || sh -cx '! : Wrong working directory.' + +here=`env - PATH=$PATH pwd` +parent=`dirname $here` + +echo 'Compressing manpages...' +for i in man/*.[1-8]; do + gzip -c $i >${i}.gz +done + +echo 'Making manpage links in /usr/local/man...' +cd man +for i in 8; do + mkdir -p /usr/local/man/man$i + for j in *.$i; do + rm -f /usr/local/man/man$i/$j.gz'{new}' + ln -s $parent/runit/man/$j.gz /usr/local/man/man$i/$j.gz'{new}' + mv -f /usr/local/man/man$i/$j.gz'{new}' /usr/local/man/man$i/$j.gz + done +done +cd .. diff --git a/runit-2.1.2/package/sharing b/runit-2.1.2/package/sharing new file mode 100644 index 0000000..303d3de --- /dev/null +++ b/runit-2.1.2/package/sharing @@ -0,0 +1,3 @@ +command:syst +package:dist +src:dist diff --git a/runit-2.1.2/package/upgrade b/runit-2.1.2/package/upgrade new file mode 100755 index 0000000..fac8902 --- /dev/null +++ b/runit-2.1.2/package/upgrade @@ -0,0 +1,29 @@ +#!/bin/sh +set -e + +umask 022 +test -d package || sh -cx '! : Wrong working directory.' +test -d src || sh -cx '! : Wrong working directory.' + +here=`env - PATH=$PATH pwd` +parent=`dirname $here` + +echo 'Creating symlink runit -> runit-2.1.2...' +rm -f runit +ln -s runit-2.1.2 runit +mv -f runit .. + +echo 'Making command links in /command...' +mkdir -p /command +for i in `cat package/commands`; do + rm -f /command/$i'{new}' + ln -s $parent/runit/command/$i /command/$i'{new}' + mv -f /command/$i'{new}' /command/$i +done +echo 'Making compatibility links in /usr/local/bin...' +mkdir -p /usr/local/bin +for i in `cat package/commands`; do + rm -f /usr/local/bin/$i'{new}' + ln -s /command/$i /usr/local/bin/$i'{new}' + mv -f /usr/local/bin/$i'{new}' /usr/local/bin/$i +done diff --git a/runit-2.1.2/package/versions b/runit-2.1.2/package/versions new file mode 100644 index 0000000..f1364f2 --- /dev/null +++ b/runit-2.1.2/package/versions @@ -0,0 +1,54 @@ +0.4.0 +0.4.1 +0.5.0 +0.5.3 +0.6.0 +0.7.0 +0.7.1 +0.7.2 +0.8.0 +0.8.1 +0.8.4 +0.9.0 +0.9.1 +0.9.2 +0.9.3 +0.9.4 +0.9.5 +0.10.0 +0.11.0 +0.11.1 +0.11.2 +0.12.0 +0.12.1 +0.13.0 +0.13.1 +1.0.0 +1.0.1 +1.0.2 +1.0.3 +1.0.4 +1.0.5 +1.1.0 +1.2.0 +1.2.1 +1.2.2 +1.2.3 +1.3.0 +1.3.1 +1.3.2 +1.3.3 +1.4.0 +1.4.1 +1.5.0 +1.5.1 +1.6.0 +1.7.0 +1.7.1 +1.7.2 +1.8.0 +1.9.0 +2.0.0 +2.1.0 +2.1.1 +2.1.2 diff --git a/runit-2.1.2/src/Makefile b/runit-2.1.2/src/Makefile new file mode 100644 index 0000000..d9624de --- /dev/null +++ b/runit-2.1.2/src/Makefile @@ -0,0 +1,468 @@ +IT=chpst runit runit-init runsv runsvchdir runsvdir sv svlogd utmpset + +default: sysdeps $(IT) + +check: $(IT) + ./check-local $(IT) + +runit: load runit.o unix.a byte.a + ./load runit unix.a byte.a -static + +runit-init: load runit-init.o unix.a byte.a + ./load runit-init unix.a byte.a -static + +runsv: load runsv.o unix.a byte.a time.a + ./load runsv unix.a byte.a time.a + +runsvdir: load runsvdir.o unix.a byte.a time.a + ./load runsvdir unix.a byte.a time.a + +runsvstat: load runsvstat.o unix.a byte.a time.a + ./load runsvstat unix.a byte.a time.a + +runsvctrl: load runsvctrl.o unix.a byte.a + ./load runsvctrl unix.a byte.a + +sv: load sv.o unix.a byte.a time.a + ./load sv unix.a byte.a time.a + +svwaitup: load svwaitup.o unix.a byte.a time.a + ./load svwaitup unix.a byte.a time.a + +svwaitdown: load svwaitdown.o unix.a byte.a time.a + ./load svwaitdown unix.a byte.a time.a + +utmpset: load utmpset.o unix.a byte.a + ./load utmpset unix.a byte.a + +runsvchdir: load runsvchdir.o unix.a byte.a + ./load runsvchdir unix.a byte.a + +svlogd: load svlogd.o pmatch.o fmt_ptime.o unix.a byte.a time.a socket.lib + ./load svlogd pmatch.o fmt_ptime.o unix.a byte.a time.a \ + `cat socket.lib` + +chpst: load chpst.o uidgid.o unix.a byte.a + ./load chpst uidgid.o unix.a byte.a + +runit.o: compile sysdeps runit.c + ./compile runit.c + +runit-init.o: compile runit-init.c + ./compile runit-init.c + +runsv.o: compile sysdeps runsv.c + ./compile runsv.c + +runsvdir.o: compile sysdeps runsvdir.c + ./compile runsvdir.c + +runsvstat.o: compile sysdeps runsvstat.c + ./compile runsvstat.c + +runsvctrl.o: compile runsvctrl.c + ./compile runsvctrl.c + +sv.o: compile sysdeps sv.c + ./compile sv.c + +svwaitup.o: compile sysdeps svwaitup.c + ./compile svwaitup.c + +svwaitdown.o: compile sysdeps svwaitdown.c + ./compile svwaitdown.c + +utmpset.o: compile sysdeps utmpset.c + ./compile utmpset.c + +runsvchdir.o: compile runsvchdir.c + ./compile runsvchdir.c + +svlogd.o: compile sysdeps svlogd.c + ./compile svlogd.c + +chpst.o: compile sysdeps chpst.c + ./compile chpst.c + + +uidgid.o: compile uidgid.c uidgid.h + ./compile uidgid.c + +pmatch.o: compile pmatch.c + ./compile pmatch.c + +fmt_ptime.o: compile sysdeps fmt_ptime.c + ./compile fmt_ptime.c + +reboot_system.h: choose compile reboot_system.h1 reboot_system.h2 + ./choose c tryreboot reboot_system.h1 reboot_system.h2 > \ + reboot_system.h + +uw_tmp.h: compile uw_tmp.h1 uw_tmp.h2 + ( ./compile tryuwtmpx.c 2>/dev/null && cat uw_tmp.h2 >uw_tmp.h ) || \ + ( ./compile tryuwtmp.c 2>/dev/null && cat uw_tmp.h1 >uw_tmp.h ) + rm -f tryuwtmp.o tryuwtmpx.o + +socket.lib: compile load trysocketlib.c + ./compile trysocketlib.c + ( ./load trysocketlib >/dev/null 2>&1 || \ + ( ./load trysocketlib -lxnet >/dev/null 2>&1 && echo '-lxnet' ) || \ + ( ./load trysocketlib -lsocket -lnsl >/dev/null 2>&1 && \ + echo '-lsocket -lnsl' ) \ + ) >socket.lib + rm -f trysocketlib.o trysocketlib + +clean: + find . -name \*~ -exec rm -f {} \; + find . -name .??*~ -exec rm -f {} \; + find . -name \#?* -exec rm -f {} \; + rm -f `cat TARGETS` + +alloc.o: alloc.c alloc.h compile error.h + ./compile alloc.c + +alloc_re.o: alloc.h alloc_re.c byte.h compile + ./compile alloc_re.c + +buffer.o: buffer.c buffer.h compile + ./compile buffer.c + +buffer_0.o: buffer.h buffer_0.c compile + ./compile buffer_0.c + +buffer_1.o: buffer.h buffer_1.c compile + ./compile buffer_1.c + +buffer_2.o: buffer.h buffer_2.c compile + ./compile buffer_2.c + +buffer_get.o: buffer.h buffer_get.c byte.h compile error.h + ./compile buffer_get.c + +buffer_put.o: buffer.h buffer_put.c byte.h compile error.h str.h + ./compile buffer_put.c + +buffer_read.o: buffer.h buffer_read.c compile + ./compile buffer_read.c + +buffer_write.o: buffer.h buffer_write.c compile + ./compile buffer_write.c + +byte.a: byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_rchr.o \ +fmt_uint.o fmt_uint0.o fmt_ulong.o makelib scan_ulong.o str_chr.o \ +str_diff.o str_len.o str_start.o + ./makelib byte.a byte_chr.o byte_copy.o byte_cr.o byte_diff.o \ + byte_rchr.o fmt_uint.o fmt_uint0.o fmt_ulong.o scan_ulong.o str_chr.o \ + str_diff.o str_len.o str_start.o + +byte_chr.o: byte.h byte_chr.c compile + ./compile byte_chr.c + +byte_copy.o: byte.h byte_copy.c compile + ./compile byte_copy.c + +byte_cr.o: byte.h byte_cr.c compile + ./compile byte_cr.c + +byte_diff.o: byte.h byte_diff.c compile + ./compile byte_diff.c + +byte_rchr.o: byte.h byte_rchr.c compile + ./compile byte_rchr.c + +chkshsgr: chkshsgr.o load + ./load chkshsgr + +chkshsgr.o: chkshsgr.c compile + ./compile chkshsgr.c + +choose: choose.sh warn-auto.sh + rm -f choose + cat warn-auto.sh choose.sh \ + > choose + chmod 555 choose + +coe.o: coe.c coe.h compile + ./compile coe.c + +compile: conf-cc print-cc.sh systype warn-auto.sh + rm -f compile + sh print-cc.sh > compile + chmod 555 compile + +direntry.h: choose compile direntry.h1 direntry.h2 trydrent.c + ./choose c trydrent direntry.h1 direntry.h2 > direntry.h + +env.o: compile env.c env.h str.h + ./compile env.c + +error.o: compile error.c error.h + ./compile error.c + +error_str.o: compile error.h error_str.c + ./compile error_str.c + +fd_copy.o: compile fd.h fd_copy.c + ./compile fd_copy.c + +fd_move.o: compile fd.h fd_move.c + ./compile fd_move.c + +fifo.o: compile fifo.c fifo.h hasmkffo.h + ./compile fifo.c + +fmt_uint.o: compile fmt.h fmt_uint.c + ./compile fmt_uint.c + +fmt_uint0.o: compile fmt.h fmt_uint0.c + ./compile fmt_uint0.c + +fmt_ulong.o: compile fmt.h fmt_ulong.c + ./compile fmt_ulong.c + +hasflock.h: choose compile hasflock.h1 hasflock.h2 load tryflock.c + ./choose cl tryflock hasflock.h1 hasflock.h2 > hasflock.h + +hasmkffo.h: choose compile hasmkffo.h1 hasmkffo.h2 load trymkffo.c + ./choose cl trymkffo hasmkffo.h1 hasmkffo.h2 > hasmkffo.h + +hassgact.h: choose compile hassgact.h1 hassgact.h2 load trysgact.c + ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h + +hassgprm.h: choose compile hassgprm.h1 hassgprm.h2 load trysgprm.c + ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h + +hasshsgr.h: chkshsgr choose compile hasshsgr.h1 hasshsgr.h2 load \ +tryshsgr.c warn-shsgr + ./chkshsgr || ( cat warn-shsgr; exit 1 ) + ./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h + +haswaitp.h: choose compile haswaitp.h1 haswaitp.h2 load trywaitp.c + ./choose cl trywaitp haswaitp.h1 haswaitp.h2 > haswaitp.h + +iopause.h: choose compile iopause.h1 iopause.h2 load trypoll.c + ./choose clr trypoll iopause.h1 iopause.h2 > iopause.h + +iopause.o: compile iopause.c iopause.h select.h tai.h taia.h uint64.h + ./compile iopause.c + +load: conf-ld print-ld.sh systype warn-auto.sh + rm -f load + sh print-ld.sh > load + chmod 555 load + +lock_ex.o: compile hasflock.h lock.h lock_ex.c + ./compile lock_ex.c + +lock_exnb.o: compile hasflock.h lock.h lock_exnb.c + ./compile lock_exnb.c + +makelib: print-ar.sh systype warn-auto.sh + rm -f makelib + sh print-ar.sh > makelib + chmod 555 makelib + +ndelay_off.o: compile ndelay.h ndelay_off.c + ./compile ndelay_off.c + +ndelay_on.o: compile ndelay.h ndelay_on.c + ./compile ndelay_on.c + +open_append.o: compile open.h open_append.c + ./compile open_append.c + +open_read.o: compile open.h open_read.c + ./compile open_read.c + +open_trunc.o: compile open.h open_trunc.c + ./compile open_trunc.c + +open_write.o: compile open.h open_write.c + ./compile open_write.c + +openreadclose.o: compile error.h gen_alloc.h open.h openreadclose.c \ +openreadclose.h readclose.h stralloc.h + ./compile openreadclose.c + +pathexec_env.o: alloc.h byte.h compile env.h gen_alloc.h pathexec.h \ +pathexec_env.c str.h stralloc.h + ./compile pathexec_env.c + +pathexec_run.o: compile env.h error.h gen_alloc.h pathexec.h \ +pathexec_run.c str.h stralloc.h + ./compile pathexec_run.c + +prot.o: compile hasshsgr.h prot.c prot.h + ./compile prot.c + +readclose.o: compile error.h gen_alloc.h readclose.c readclose.h \ +stralloc.h + ./compile readclose.c + +scan_ulong.o: compile scan.h scan_ulong.c + ./compile scan_ulong.c + +seek_set.o: compile seek.h seek_set.c + ./compile seek_set.c + +select.h: choose compile select.h1 select.h2 trysysel.c + ./choose c trysysel select.h1 select.h2 > select.h + +sgetopt.o: buffer.h compile sgetopt.c sgetopt.h subgetopt.h + ./compile sgetopt.c + +sig.o: compile sig.c sig.h + ./compile sig.c + +sig_block.o: compile hassgprm.h sig.h sig_block.c + ./compile sig_block.c + +sig_catch.o: compile hassgact.h sig.h sig_catch.c + ./compile sig_catch.c + +sig_pause.o: compile hassgprm.h sig.h sig_pause.c + ./compile sig_pause.c + +str_chr.o: compile str.h str_chr.c + ./compile str_chr.c + +str_diff.o: compile str.h str_diff.c + ./compile str_diff.c + +str_len.o: compile str.h str_len.c + ./compile str_len.c + +str_start.o: compile str.h str_start.c + ./compile str_start.c + +stralloc_cat.o: byte.h compile gen_alloc.h stralloc.h stralloc_cat.c + ./compile stralloc_cat.c + +stralloc_catb.o: byte.h compile gen_alloc.h stralloc.h \ +stralloc_catb.c + ./compile stralloc_catb.c + +stralloc_cats.o: byte.h compile gen_alloc.h str.h stralloc.h \ +stralloc_cats.c + ./compile stralloc_cats.c + +stralloc_eady.o: alloc.h compile gen_alloc.h gen_allocdefs.h \ +stralloc.h stralloc_eady.c + ./compile stralloc_eady.c + +stralloc_opyb.o: byte.h compile gen_alloc.h stralloc.h \ +stralloc_opyb.c + ./compile stralloc_opyb.c + +stralloc_opys.o: byte.h compile gen_alloc.h str.h stralloc.h \ +stralloc_opys.c + ./compile stralloc_opys.c + +stralloc_pend.o: alloc.h compile gen_alloc.h gen_allocdefs.h \ +stralloc.h stralloc_pend.c + ./compile stralloc_pend.c + +strerr_die.o: buffer.h compile strerr.h strerr_die.c + ./compile strerr_die.c + +strerr_sys.o: compile error.h strerr.h strerr_sys.c + ./compile strerr_sys.c + +subgetopt.o: compile subgetopt.c subgetopt.h + ./compile subgetopt.c + +sysdeps: compile direntry.h hasflock.h hasmkffo.h hassgact.h \ +hassgprm.h hasshsgr.h haswaitp.h iopause.h load select.h systype \ +uint64.h reboot_system.h uw_tmp.h socket.lib + rm -f sysdeps + cat systype compile load socket.lib >>sysdeps + grep sysdep direntry.h >>sysdeps + grep sysdep haswaitp.h >>sysdeps + grep sysdep hassgact.h >>sysdeps + grep sysdep hassgprm.h >>sysdeps + grep sysdep select.h >>sysdeps + grep sysdep uint64.h >>sysdeps + grep sysdep iopause.h >>sysdeps + grep sysdep hasmkffo.h >>sysdeps + grep sysdep hasflock.h >>sysdeps + grep sysdep hasshsgr.h >>sysdeps + grep sysdep reboot_system.h >>sysdeps + grep sysdep uw_tmp.h >>sysdeps + cat sysdeps + +systype: find-systype.sh trycpp.c x86cpuid.c + sh find-systype.sh > systype + +tai_now.o: compile tai.h tai_now.c uint64.h + ./compile tai_now.c + +tai_pack.o: compile tai.h tai_pack.c uint64.h + ./compile tai_pack.c + +tai_sub.o: compile tai.h tai_sub.c uint64.h + ./compile tai_sub.c + +tai_unpack.o: compile tai.h tai_unpack.c uint64.h + ./compile tai_unpack.c + +taia_add.o: compile tai.h taia.h taia_add.c uint64.h + ./compile taia_add.c + +taia_approx.o: compile tai.h taia.h taia_approx.c uint64.h + ./compile taia_approx.c + +taia_frac.o: compile tai.h taia.h taia_frac.c uint64.h + ./compile taia_frac.c + +taia_less.o: compile tai.h taia.h taia_less.c uint64.h + ./compile taia_less.c + +taia_now.o: compile tai.h taia.h taia_now.c uint64.h + ./compile taia_now.c + +taia_pack.o: compile tai.h taia.h taia_pack.c uint64.h + ./compile taia_pack.c + +taia_sub.o: compile tai.h taia.h taia_sub.c uint64.h + ./compile taia_sub.c + +taia_uint.o: compile tai.h taia.h taia_uint.c uint64.h + ./compile taia_uint.c + +time.a: iopause.o makelib tai_now.o tai_pack.o tai_sub.o tai_unpack.o \ +taia_add.o taia_approx.o taia_frac.o taia_less.o taia_now.o \ +taia_pack.o taia_sub.o taia_uint.o + ./makelib time.a iopause.o tai_now.o tai_pack.o tai_sub.o \ + tai_unpack.o taia_add.o taia_approx.o taia_frac.o taia_less.o \ + taia_now.o taia_pack.o taia_sub.o taia_uint.o + +uint64.h: choose compile load tryulong64.c uint64.h1 uint64.h2 + ./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h + +unix.a: alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o buffer_2.o \ +buffer_get.o buffer_put.o buffer_read.o buffer_write.o coe.o env.o \ +error.o error_str.o fd_copy.o fd_move.o fifo.o lock_ex.o lock_exnb.o \ +makelib ndelay_off.o ndelay_on.o open_append.o open_read.o \ +open_trunc.o open_write.o openreadclose.o pathexec_env.o \ +pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \ +sig_block.o sig_catch.o sig_pause.o stralloc_cat.o stralloc_catb.o \ +stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \ +stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o \ +wait_pid.o + ./makelib unix.a alloc.o alloc_re.o buffer.o buffer_0.o buffer_1.o \ + buffer_2.o buffer_get.o buffer_put.o buffer_read.o buffer_write.o \ + coe.o env.o error.o error_str.o fd_copy.o fd_move.o fifo.o lock_ex.o \ + lock_exnb.o ndelay_off.o ndelay_on.o open_append.o open_read.o \ + open_trunc.o open_write.o openreadclose.o pathexec_env.o \ + pathexec_run.o prot.o readclose.o seek_set.o sgetopt.o sig.o \ + sig_block.o sig_catch.o sig_pause.o stralloc_cat.o stralloc_catb.o \ + stralloc_cats.o stralloc_eady.o stralloc_opyb.o stralloc_opys.o \ + stralloc_pend.o strerr_die.o strerr_sys.o subgetopt.o wait_nohang.o \ + wait_pid.o + +wait_nohang.o: compile haswaitp.h wait_nohang.c + ./compile wait_nohang.c + +wait_pid.o: compile error.h haswaitp.h wait_pid.c + ./compile wait_pid.c + diff --git a/runit-2.1.2/src/TARGETS b/runit-2.1.2/src/TARGETS new file mode 100644 index 0000000..46981ce --- /dev/null +++ b/runit-2.1.2/src/TARGETS @@ -0,0 +1,143 @@ +runit +runit.o +runit-init +runit-init.o +runsv +runsv.o +runsvdir +runsvdir.o +runsvstat +runsvstat.o +runsvctrl +runsvctrl.o +sv +sv.o +svwaitdown +svwaitdown.o +svwaitup +svwaitup.o +utmpset +utmpset.o +runsvchdir +runsvchdir.o +svlogd +svlogd.o +chpst +chpst.o +pmatch.o +fmt_ptime.o +uidgid.o +reboot_system.h +uw_tmp.h +socket.lib +trysocketlib +trysocketlib.o +check +alloc.o +alloc_re.o +buffer.o +buffer_0.o +buffer_1.o +buffer_2.o +buffer_get.o +buffer_put.o +buffer_read.o +buffer_write.o +byte.a +byte_chr.o +byte_copy.o +byte_cr.o +byte_diff.o +byte_rchr.o +chkshsgr +chkshsgr.o +choose +coe.o +compile +direntry.h +env.o +error.o +error_str.o +fd_copy.o +fd_move.o +fifo.o +fmt_uint.o +fmt_uint0.o +fmt_ulong.o +hasflock.h +hasmkffo.h +hassgact.h +hassgprm.h +hasshsgr.h +haswaitp.h +iopause.h +iopause.o +load +lock_ex.o +lock_exnb.o +makelib +ndelay_off.o +ndelay_on.o +open_append.o +open_read.o +open_trunc.o +open_write.o +openreadclose.o +pathexec_env.o +pathexec_run.o +prot.o +readclose.o +scan_ulong.o +seek_set.o +select.h +sgetopt.o +sig.o +sig_block.o +sig_catch.o +sig_pause.o +str_chr.o +str_diff.o +str_len.o +str_start.o +stralloc_cat.o +stralloc_catb.o +stralloc_cats.o +stralloc_eady.o +stralloc_opyb.o +stralloc_opys.o +stralloc_pend.o +strerr_die.o +strerr_sys.o +subgetopt.o +sysdeps +systype +tai_now.o +tai_pack.o +tai_sub.o +tai_unpack.o +taia_add.o +taia_approx.o +taia_frac.o +taia_less.o +taia_now.o +taia_pack.o +taia_sub.o +taia_uint.o +time.a +uint64.h +unix.a +wait_nohang.o +wait_pid.o +chpst.local +runit-init.local +runit.local +runsv.local +runsvchdir.local +runsvctrl.local +runsvdir.local +runsvstat.local +sv.local +svlogd.local +svwaitdown.local +svwaitup.local +utmpset.local diff --git a/runit-2.1.2/src/alloc.c b/runit-2.1.2/src/alloc.c new file mode 100644 index 0000000..c741aa4 --- /dev/null +++ b/runit-2.1.2/src/alloc.c @@ -0,0 +1,33 @@ +/* Public domain. */ + +#include <stdlib.h> +#include "alloc.h" +#include "error.h" + +#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ +#define SPACE 2048 /* must be multiple of ALIGNMENT */ + +typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; +static aligned realspace[SPACE / ALIGNMENT]; +#define space ((char *) realspace) +static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ + +/*@null@*//*@out@*/char *alloc(n) +unsigned int n; +{ + char *x; + n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ + if (n <= avail) { avail -= n; return space + avail; } + x = malloc(n); + if (!x) errno = error_nomem; + return x; +} + +void alloc_free(x) +char *x; +{ + if (x >= space) + if (x < space + SPACE) + return; /* XXX: assuming that pointers are flat */ + free(x); +} diff --git a/runit-2.1.2/src/alloc.h b/runit-2.1.2/src/alloc.h new file mode 100644 index 0000000..21122fc --- /dev/null +++ b/runit-2.1.2/src/alloc.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef ALLOC_H +#define ALLOC_H + +extern /*@null@*//*@out@*/char *alloc(); +extern void alloc_free(); +extern int alloc_re(); + +#endif diff --git a/runit-2.1.2/src/alloc_re.c b/runit-2.1.2/src/alloc_re.c new file mode 100644 index 0000000..1074609 --- /dev/null +++ b/runit-2.1.2/src/alloc_re.c @@ -0,0 +1,19 @@ +/* Public domain. */ + +#include "alloc.h" +#include "byte.h" + +int alloc_re(x,m,n) +char **x; +unsigned int m; +unsigned int n; +{ + char *y; + + y = alloc(n); + if (!y) return 0; + byte_copy(y,m,*x); + alloc_free(*x); + *x = y; + return 1; +} diff --git a/runit-2.1.2/src/buffer.c b/runit-2.1.2/src/buffer.c new file mode 100644 index 0000000..38e6d77 --- /dev/null +++ b/runit-2.1.2/src/buffer.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include "buffer.h" + +void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len) +{ + s->x = buf; + s->fd = fd; + s->op = op; + s->p = 0; + s->n = len; +} diff --git a/runit-2.1.2/src/buffer.h b/runit-2.1.2/src/buffer.h new file mode 100644 index 0000000..8f2e572 --- /dev/null +++ b/runit-2.1.2/src/buffer.h @@ -0,0 +1,61 @@ +/* Public domain. */ + +#ifndef BUFFER_H +#define BUFFER_H + +typedef struct buffer { + char *x; + unsigned int p; + unsigned int n; + int fd; + int (*op)(); +} buffer; + +#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } +#define BUFFER_INSIZE 8192 +#define BUFFER_OUTSIZE 8192 + +extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int); + +extern int buffer_flush(buffer *); +extern int buffer_put(buffer *,const char *,unsigned int); +extern int buffer_putalign(buffer *,const char *,unsigned int); +extern int buffer_putflush(buffer *,const char *,unsigned int); +extern int buffer_puts(buffer *,const char *); +extern int buffer_putsalign(buffer *,const char *); +extern int buffer_putsflush(buffer *,const char *); + +#define buffer_PUTC(s,c) \ + ( ((s)->n != (s)->p) \ + ? ( (s)->x[(s)->p++] = (c), 0 ) \ + : buffer_put((s),&(c),1) \ + ) + +extern int buffer_get(buffer *,char *,unsigned int); +extern int buffer_bget(buffer *,char *,unsigned int); +extern int buffer_feed(buffer *); + +extern char *buffer_peek(buffer *); +extern void buffer_seek(buffer *,unsigned int); + +#define buffer_PEEK(s) ( (s)->x + (s)->n ) +#define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) + +#define buffer_GETC(s,c) \ + ( ((s)->p > 0) \ + ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \ + : buffer_get((s),(c),1) \ + ) + +extern int buffer_copy(buffer *,buffer *); + +extern int buffer_unixread(int,char *,unsigned int); +extern int buffer_unixwrite(int,const char *,unsigned int); + +extern buffer *buffer_0; +extern buffer *buffer_0small; +extern buffer *buffer_1; +extern buffer *buffer_1small; +extern buffer *buffer_2; + +#endif diff --git a/runit-2.1.2/src/buffer_0.c b/runit-2.1.2/src/buffer_0.c new file mode 100644 index 0000000..47d3263 --- /dev/null +++ b/runit-2.1.2/src/buffer_0.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include "buffer.h" + +int buffer_0_read(fd,buf,len) int fd; char *buf; int len; +{ + if (buffer_flush(buffer_1) == -1) return -1; + return buffer_unixread(fd,buf,len); +} + +char buffer_0_space[BUFFER_INSIZE]; +static buffer it = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof buffer_0_space); +buffer *buffer_0 = ⁢ diff --git a/runit-2.1.2/src/buffer_1.c b/runit-2.1.2/src/buffer_1.c new file mode 100644 index 0000000..f4bac3d --- /dev/null +++ b/runit-2.1.2/src/buffer_1.c @@ -0,0 +1,7 @@ +/* Public domain. */ + +#include "buffer.h" + +char buffer_1_space[BUFFER_OUTSIZE]; +static buffer it = BUFFER_INIT(buffer_unixwrite,1,buffer_1_space,sizeof buffer_1_space); +buffer *buffer_1 = ⁢ diff --git a/runit-2.1.2/src/buffer_2.c b/runit-2.1.2/src/buffer_2.c new file mode 100644 index 0000000..f255a92 --- /dev/null +++ b/runit-2.1.2/src/buffer_2.c @@ -0,0 +1,7 @@ +/* Public domain. */ + +#include "buffer.h" + +char buffer_2_space[256]; +static buffer it = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof buffer_2_space); +buffer *buffer_2 = ⁢ diff --git a/runit-2.1.2/src/buffer_get.c b/runit-2.1.2/src/buffer_get.c new file mode 100644 index 0000000..3a6e1b6 --- /dev/null +++ b/runit-2.1.2/src/buffer_get.c @@ -0,0 +1,69 @@ +/* Public domain. */ + +#include "buffer.h" +#include "byte.h" +#include "error.h" + +static int oneread(int (*op)(),int fd,char *buf,unsigned int len) +{ + int r; + + for (;;) { + r = op(fd,buf,len); + if (r == -1) if (errno == error_intr) continue; + return r; + } +} + +static int getthis(buffer *s,char *buf,unsigned int len) +{ + if (len > s->p) len = s->p; + s->p -= len; + byte_copy(buf,len,s->x + s->n); + s->n += len; + return len; +} + +int buffer_feed(buffer *s) +{ + int r; + + if (s->p) return s->p; + r = oneread(s->op,s->fd,s->x,s->n); + if (r <= 0) return r; + s->p = r; + s->n -= r; + if (s->n > 0) byte_copyr(s->x + s->n,r,s->x); + return r; +} + +int buffer_bget(buffer *s,char *buf,unsigned int len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,s->n); + r = buffer_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +int buffer_get(buffer *s,char *buf,unsigned int len) +{ + int r; + + if (s->p > 0) return getthis(s,buf,len); + if (s->n <= len) return oneread(s->op,s->fd,buf,len); + r = buffer_feed(s); if (r <= 0) return r; + return getthis(s,buf,len); +} + +char *buffer_peek(buffer *s) +{ + return s->x + s->n; +} + +void buffer_seek(buffer *s,unsigned int len) +{ + s->n += len; + s->p -= len; +} diff --git a/runit-2.1.2/src/buffer_put.c b/runit-2.1.2/src/buffer_put.c new file mode 100644 index 0000000..23164b3 --- /dev/null +++ b/runit-2.1.2/src/buffer_put.c @@ -0,0 +1,90 @@ +/* Public domain. */ + +#include "buffer.h" +#include "str.h" +#include "byte.h" +#include "error.h" + +static int allwrite(int (*op)(),int fd,const char *buf,unsigned int len) +{ + int w; + + while (len) { + w = op(fd,buf,len); + if (w == -1) { + if (errno == error_intr) continue; + return -1; /* note that some data may have been written */ + } + if (w == 0) ; /* luser's fault */ + buf += w; + len -= w; + } + return 0; +} + +int buffer_flush(buffer *s) +{ + int p; + + p = s->p; + if (!p) return 0; + s->p = 0; + return allwrite(s->op,s->fd,s->x,p); +} + +int buffer_putalign(buffer *s,const char *buf,unsigned int len) +{ + unsigned int n; + + while (len > (n = s->n - s->p)) { + byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; + if (buffer_flush(s) == -1) return -1; + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_put(buffer *s,const char *buf,unsigned int len) +{ + unsigned int n; + + n = s->n; + if (len > n - s->p) { + if (buffer_flush(s) == -1) return -1; + /* now s->p == 0 */ + if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; + while (len > s->n) { + if (n > len) n = len; + if (allwrite(s->op,s->fd,buf,n) == -1) return -1; + buf += n; + len -= n; + } + } + /* now len <= s->n - s->p */ + byte_copy(s->x + s->p,len,buf); + s->p += len; + return 0; +} + +int buffer_putflush(buffer *s,const char *buf,unsigned int len) +{ + if (buffer_flush(s) == -1) return -1; + return allwrite(s->op,s->fd,buf,len); +} + +int buffer_putsalign(buffer *s,const char *buf) +{ + return buffer_putalign(s,buf,str_len(buf)); +} + +int buffer_puts(buffer *s,const char *buf) +{ + return buffer_put(s,buf,str_len(buf)); +} + +int buffer_putsflush(buffer *s,const char *buf) +{ + return buffer_putflush(s,buf,str_len(buf)); +} diff --git a/runit-2.1.2/src/buffer_read.c b/runit-2.1.2/src/buffer_read.c new file mode 100644 index 0000000..09db05f --- /dev/null +++ b/runit-2.1.2/src/buffer_read.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <unistd.h> +#include "buffer.h" + +int buffer_unixread(int fd,char *buf,unsigned int len) +{ + return read(fd,buf,len); +} diff --git a/runit-2.1.2/src/buffer_write.c b/runit-2.1.2/src/buffer_write.c new file mode 100644 index 0000000..4ba13ef --- /dev/null +++ b/runit-2.1.2/src/buffer_write.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <unistd.h> +#include "buffer.h" + +int buffer_unixwrite(int fd,const char *buf,unsigned int len) +{ + return write(fd,buf,len); +} diff --git a/runit-2.1.2/src/byte.h b/runit-2.1.2/src/byte.h new file mode 100644 index 0000000..09aab61 --- /dev/null +++ b/runit-2.1.2/src/byte.h @@ -0,0 +1,15 @@ +/* Public domain. */ + +#ifndef BYTE_H +#define BYTE_H + +extern unsigned int byte_chr(); +extern unsigned int byte_rchr(); +extern void byte_copy(); +extern void byte_copyr(); +extern int byte_diff(); +extern void byte_zero(); + +#define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) + +#endif diff --git a/runit-2.1.2/src/byte_chr.c b/runit-2.1.2/src/byte_chr.c new file mode 100644 index 0000000..fd56056 --- /dev/null +++ b/runit-2.1.2/src/byte_chr.c @@ -0,0 +1,22 @@ +/* Public domain. */ + +#include "byte.h" + +unsigned int byte_chr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + + ch = c; + t = s; + for (;;) { + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + if (!n) break; if (*t == ch) break; ++t; --n; + } + return t - s; +} diff --git a/runit-2.1.2/src/byte_copy.c b/runit-2.1.2/src/byte_copy.c new file mode 100644 index 0000000..74c9e4a --- /dev/null +++ b/runit-2.1.2/src/byte_copy.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include "byte.h" + +void byte_copy(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + for (;;) { + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + if (!n) return; *to++ = *from++; --n; + } +} diff --git a/runit-2.1.2/src/byte_cr.c b/runit-2.1.2/src/byte_cr.c new file mode 100644 index 0000000..52dc251 --- /dev/null +++ b/runit-2.1.2/src/byte_cr.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "byte.h" + +void byte_copyr(to,n,from) +register char *to; +register unsigned int n; +register char *from; +{ + to += n; + from += n; + for (;;) { + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + if (!n) return; *--to = *--from; --n; + } +} diff --git a/runit-2.1.2/src/byte_diff.c b/runit-2.1.2/src/byte_diff.c new file mode 100644 index 0000000..0c4d17b --- /dev/null +++ b/runit-2.1.2/src/byte_diff.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "byte.h" + +int byte_diff(s,n,t) +register char *s; +register unsigned int n; +register char *t; +{ + for (;;) { + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; + } + return ((int)(unsigned int)(unsigned char) *s) + - ((int)(unsigned int)(unsigned char) *t); +} diff --git a/runit-2.1.2/src/byte_rchr.c b/runit-2.1.2/src/byte_rchr.c new file mode 100644 index 0000000..7ea9948 --- /dev/null +++ b/runit-2.1.2/src/byte_rchr.c @@ -0,0 +1,25 @@ +/* Public domain. */ + +#include "byte.h" + +unsigned int byte_rchr(s,n,c) +char *s; +register unsigned int n; +int c; +{ + register char ch; + register char *t; + register char *u; + + ch = c; + t = s; + u = 0; + for (;;) { + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + if (!n) break; if (*t == ch) u = t; ++t; --n; + } + if (!u) u = t; + return u - s; +} diff --git a/runit-2.1.2/src/check-diff b/runit-2.1.2/src/check-diff new file mode 100755 index 0000000..d334238 --- /dev/null +++ b/runit-2.1.2/src/check-diff @@ -0,0 +1,5 @@ +#!/bin/sh +while read i; do + read j 0<&7 || exit 1 + test "$i" = "$j" || exit 1 +done 7<$1.dist <$1.local diff --git a/runit-2.1.2/src/check-dist b/runit-2.1.2/src/check-dist new file mode 100755 index 0000000..f0c5dd5 --- /dev/null +++ b/runit-2.1.2/src/check-dist @@ -0,0 +1,8 @@ +#!/bin/sh + +PATH=`pwd`:$PATH + +for i in `cat ../package/commands`; do + echo "Creating new $i.dist..." + env - PATH="$PATH" ctmp="`pwd`/check-tmp" $i.check 2>&1 |cat -v >$i.dist +done diff --git a/runit-2.1.2/src/check-local b/runit-2.1.2/src/check-local new file mode 100755 index 0000000..36b3ed4 --- /dev/null +++ b/runit-2.1.2/src/check-local @@ -0,0 +1,9 @@ +#!/bin/sh + +PATH=`pwd`:$PATH + +for i in ${1+"$@"}; do + echo "Checking $i..." + env - PATH="$PATH" ctmp="`pwd`/check-tmp" $i.check 2>&1 |cat -v >$i.local + ./check-diff $i || ( cat $i.local; echo "$i failed."; exit 1 ) || exit 1 +done diff --git a/runit-2.1.2/src/chkshsgr.c b/runit-2.1.2/src/chkshsgr.c new file mode 100644 index 0000000..38c352d --- /dev/null +++ b/runit-2.1.2/src/chkshsgr.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <unistd.h> + +int main() +{ + short x[4]; + + x[0] = x[1] = 0; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + _exit(0); +} diff --git a/runit-2.1.2/src/choose.sh b/runit-2.1.2/src/choose.sh new file mode 100644 index 0000000..feff2da --- /dev/null +++ b/runit-2.1.2/src/choose.sh @@ -0,0 +1,18 @@ + +result="$4" + +case "$1" in + *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;; +esac + +case "$1" in + *r*) ./$2 >/dev/null 2>&1 || result="$3" ;; +esac + +rm -f $2.o $2 + +exec cat "$result" diff --git a/runit-2.1.2/src/chpst.c b/runit-2.1.2/src/chpst.c new file mode 100644 index 0000000..f1b8ed9 --- /dev/null +++ b/runit-2.1.2/src/chpst.c @@ -0,0 +1,475 @@ +#include <sys/types.h> +#include <time.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <unistd.h> +#include "sgetopt.h" +#include "error.h" +#include "strerr.h" +#include "str.h" +#include "uidgid.h" +#include "prot.h" +#include "strerr.h" +#include "scan.h" +#include "fmt.h" +#include "lock.h" +#include "pathexec.h" +#include "stralloc.h" +#include "byte.h" +#include "open.h" +#include "openreadclose.h" +#include "direntry.h" + +#define USAGE_MAIN " [-vP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] prog" +#define FATAL "chpst: fatal: " +#define WARNING "chpst: warning: " + +const char *progname; +static stralloc sa; + +void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } +void fatal2(const char *m0, const char *m1) { + strerr_die5sys(111, FATAL, m0, ": ", m1, ": "); +} +void fatalx(const char *m0, const char *m1) { + strerr_die4x(111, FATAL, m0, ": ", m1); +} +void warn(const char *m) { strerr_warn2(WARNING, m, 0); } +void die_nomem() { strerr_die2x(111, FATAL, "out of memory."); } +void usage() { strerr_die4x(100, "usage: ", progname, USAGE_MAIN, "\n"); } + +char *set_user =0; +char *env_user =0; +const char *argv0 =0; +const char *env_dir =0; +unsigned int verbose =0; +unsigned int pgrp =0; +unsigned int nostdin =0; +unsigned int nostdout =0; +unsigned int nostderr =0; +long limitd =-2; +long limits =-2; +long limitl =-2; +long limita =-2; +long limito =-2; +long limitp =-2; +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; + +void suidgid(char *user, unsigned int ext) { + struct uidgid ugid; + + if (ext) { + if (! uidgids_get(&ugid, user)) { + if (*user == ':') fatalx("invalid uid/gids", user +1); + if (errno) fatal("unable to get password/group file entry"); + fatalx("unknown user/group", user); + } + } + else + if (! uidgid_get(&ugid, user)) { + if (errno) fatal("unable to get password file entry"); + fatalx("unknown account", user); + } + if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to setgroups"); + if (setgid(*ugid.gid) == -1) fatal("unable to setgid"); + if (prot_uid(ugid.uid) == -1) fatal("unable to setuid"); +} + +void euidgid(char *user, unsigned int ext) { + struct uidgid ugid; + char bufnum[FMT_ULONG]; + + if (ext) { + if (! uidgids_get(&ugid, user)) { + if (*user == ':') fatalx("invalid uid/gids", user +1); + if (errno) fatal("unable to get password/group file entry"); + fatalx("unknown user/group", user); + } + } + else + if (! uidgid_get(&ugid, user)) { + if (errno) fatal("unable to get password file entry"); + fatalx("unknown account", user); + } + bufnum[fmt_ulong(bufnum, *ugid.gid)] =0; + if (! pathexec_env("GID", bufnum)) die_nomem(); + bufnum[fmt_ulong(bufnum, ugid.uid)] =0; + if (! pathexec_env("UID", bufnum)) die_nomem(); +} + +void edir(const char *dirname) { + int wdir; + DIR *dir; + direntry *d; + int i; + + if ((wdir =open_read(".")) == -1) + fatal("unable to open current working directory"); + if (chdir(dirname)) fatal2("unable to switch to directory", dirname); + if (! (dir =opendir("."))) fatal2("unable to open directory", dirname); + for (;;) { + errno =0; + d =readdir(dir); + if (! d) { + if (errno) fatal2("unable to read directory", dirname); + break; + } + 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; + } + else + strerr_die6sys(111, FATAL, "unable to read ", dirname, "/", + 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; + 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(); + } + else + if (! pathexec_env(d->d_name, 0)) die_nomem(); + } + closedir(dir); + if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); + close(wdir); +} + +void slock_die(const char *m, const char *f, unsigned int x) { + if (! x) fatal2(m, f); + _exit(0); +} +void slock(const char *f, unsigned int d, unsigned int x) { + int fd; + + if ((fd =open_append(f)) == -1) slock_die("unable to open lock", f, x); + if (d) { + if (lock_ex(fd) == -1) slock_die("unable to lock", f, x); + return; + } + if (lock_exnb(fd) == -1) slock_die("unable to lock", f, x); +} + +void limit(int what, long l) { + struct rlimit r; + + if (getrlimit(what, &r) == -1) fatal("unable to getrlimit()"); + if ((l < 0) || (l > r.rlim_max)) + r.rlim_cur =r.rlim_max; + else + r.rlim_cur =l; + if (setrlimit(what, &r) == -1) fatal("unable to setrlimit()"); +} +void slimit() { + if (limitd >= -1) { +#ifdef RLIMIT_DATA + limit(RLIMIT_DATA, limitd); +#else + if (verbose) warn("system does not support RLIMIT_DATA"); +#endif + } + if (limits >= -1) { +#ifdef RLIMIT_STACK + limit(RLIMIT_STACK, limits); +#else + if (verbose) warn("system does not support RLIMIT_STACK"); +#endif + } + if (limitl >= -1) { +#ifdef RLIMIT_MEMLOCK + limit(RLIMIT_MEMLOCK, limitl); +#else + if (verbose) warn("system does not support RLIMIT_MEMLOCK"); +#endif + } + if (limita >= -1) { +#ifdef RLIMIT_VMEM + limit(RLIMIT_VMEM, limita); +#else +#ifdef RLIMIT_AS + limit(RLIMIT_AS, limita); +#else + if (verbose) + warn("system does neither support RLIMIT_VMEM nor RLIMIT_AS"); +#endif +#endif + } + if (limito >= -1) { +#ifdef RLIMIT_NOFILE + limit(RLIMIT_NOFILE, limito); +#else +#ifdef RLIMIT_OFILE + limit(RLIMIT_OFILE, limito); +#else + if (verbose) + warn("system does neither support RLIMIT_NOFILE nor RLIMIT_OFILE"); +#endif +#endif + } + if (limitp >= -1) { +#ifdef RLIMIT_NPROC + limit(RLIMIT_NPROC, limitp); +#else + if (verbose) warn("system does not support RLIMIT_NPROC"); +#endif + } + if (limitf >= -1) { +#ifdef RLIMIT_FSIZE + limit(RLIMIT_FSIZE, limitf); +#else + if (verbose) warn("system does not support RLIMIT_FSIZE"); +#endif + } + if (limitc >= -1) { +#ifdef RLIMIT_CORE + limit(RLIMIT_CORE, limitc); +#else + if (verbose) warn("system does not support RLIMIT_CORE"); +#endif + } + if (limitr >= -1) { +#ifdef RLIMIT_RSS + limit(RLIMIT_RSS, limitr); +#else + if (verbose) warn("system does not support RLIMIT_RSS"); +#endif + } + if (limitt >= -1) { +#ifdef RLIMIT_CPU + limit(RLIMIT_CPU, limitt); +#else + if (verbose) warn("system does not support RLIMIT_CPU"); +#endif + } +} + +/* argv[0] */ +void setuidgid(int, const char *const *); +void envuidgid(int, const char *const *); +void envdir(int, const char *const *); +void pgrphack(int, const char *const *); +void setlock(int, const char *const *); +void softlimit(int, const char *const *); + +int main(int argc, const char **argv) { + int opt; + int i; + unsigned long ul; + + progname =argv[0]; + for (i =str_len(progname); i; --i) + if (progname[i -1] == '/') { + progname +=i; + break; + } + if (progname[0] == 'd') ++progname; + + /* argv[0] */ + if (str_equal(progname, "setuidgid")) setuidgid(argc, argv); + if (str_equal(progname, "envuidgid")) envuidgid(argc, argv); + if (str_equal(progname, "envdir")) envdir(argc, argv); + if (str_equal(progname, "pgrphack")) pgrphack(argc, argv); + if (str_equal(progname, "setlock")) setlock(argc, argv); + if (str_equal(progname, "softlimit")) softlimit(argc, argv); + + while ((opt =getopt(argc, argv, "u:U:b:e:m:d: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; + case 'b': argv0 =(char*)optarg; break; + case 'e': env_dir =optarg; break; + case 'm': + if (optarg[scan_ulong(optarg, &ul)]) usage(); + limits =limitl =limita =limitd =ul; + break; + case 'd': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitd =ul; break; + case 'o': if (optarg[scan_ulong(optarg, &ul)]) usage(); limito =ul; break; + case 'p': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitp =ul; break; + case 'f': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitf =ul; break; + case 'c': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitc =ul; break; + case 'r': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitr =ul; break; + case 't': if (optarg[scan_ulong(optarg, &ul)]) usage(); limitt =ul; break; + case '/': root =optarg; break; + case 'n': + switch (*optarg) { + case '-': + if (optarg[scan_ulong(++optarg, &ul)]) usage(); nicelvl =ul; + nicelvl *=-1; + break; + case '+': ++optarg; + default: + if (optarg[scan_ulong(optarg, &ul)]) usage(); nicelvl =ul; + 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; + case 'P': pgrp =1; break; + case '0': nostdin =1; break; + case '1': nostdout =1; break; + case '2': nostderr =1; break; + case 'V': strerr_warn1("$Id: f279d44141c981dd7535a12260efcf1ef7beed26 $", 0); + case '?': usage(); + } + argv +=optind; + if (! argv || ! *argv) usage(); + + if (pgrp) setsid(); + if (env_dir) edir(env_dir); + if (root) { + if (chdir(root) == -1) fatal2("unable to change directory", root); + if (chroot(".") == -1) fatal("unable to change root directory"); + } + if (nicelvl) { + errno =0; + if (nice(nicelvl) == -1) if (errno) fatal("unable to set nice level"); + } + if (env_user) euidgid(env_user, 1); + if (set_user) suidgid(set_user, 1); + if (lock) slock(lock, lockdelay, 0); + 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"); + slimit(); + + progname =*argv; + if (argv0) *argv =argv0; + pathexec_env_run(progname, argv); + fatal2("unable to run", *argv); + return(0); +} + +/* argv[0] */ +#define USAGE_SETUIDGID " account child" +#define USAGE_ENVUIDGID " account child" +#define USAGE_ENVDIR " dir child" +#define USAGE_PGRPHACK " child" +#define USAGE_SETLOCK " [ -nNxX ] file program [ arg ... ]" +#define USAGE_SOFTLIMIT " [-a allbytes] [-c corebytes] [-d databytes] [-f filebytes] [-l lockbytes] [-m membytes] [-o openfiles] [-p processes] [-r residentbytes] [-s stackbytes] [-t cpusecs] child" + +void setuidgid_usage() { + strerr_die4x(100, "usage: ", progname, USAGE_SETUIDGID, "\n"); +} +void setuidgid(int argc, const char *const *argv) { + const char *account; + + if (! (account =*++argv)) setuidgid_usage(); + if (! *++argv) setuidgid_usage(); + suidgid((char*)account, 0); + pathexec(argv); + fatal2("unable to run", *argv); +} + +void envuidgid_usage() { + strerr_die4x(100, "usage: ", progname, USAGE_ENVUIDGID, "\n"); +} +void envuidgid(int argc, const char *const *argv) { + const char *account; + + if (! (account =*++argv)) envuidgid_usage(); + if (! *++argv) envuidgid_usage(); + euidgid((char*)account, 0); + pathexec(argv); + fatal2("unable to run", *argv); +} + +void envdir_usage() { + strerr_die4x(100, "usage: ", progname, USAGE_ENVDIR, "\n"); +} +void envdir(int argc, const char *const *argv) { + const char *dir; + + if (! (dir =*++argv)) envdir_usage(); + if (! *++argv) envdir_usage(); + edir(dir); + pathexec(argv); + fatal2("unable to run", *argv); +} + +void pgrphack_usage() { + strerr_die4x(100, "usage: ", progname, USAGE_PGRPHACK, "\n"); +} +void pgrphack(int argc, const char *const *argv) { + if (! *++argv) pgrphack_usage(); + setsid(); + pathexec(argv); + fatal2("unable to run", *argv); +} + +void setlock_usage() { + strerr_die4x(100, "usage: ", progname, USAGE_SETLOCK, "\n"); +} +void setlock(int argc, const char *const *argv) { + int opt; + unsigned int delay =0; + unsigned int x =0; + const char *fn; + + while ((opt =getopt(argc, argv, "nNxX")) != opteof) + switch(opt) { + case 'n': delay =1; break; + case 'N': delay =0; break; + case 'x': x =1; break; + case 'X': x =0; break; + default: setlock_usage(); + } + argv +=optind; + if (! (fn =*argv)) setlock_usage(); + if (! *++argv) setlock_usage(); + + slock(fn, delay, x); + pathexec(argv); + if (! x) fatal2("unable to run", *argv); + _exit(0); +} + +void softlimit_usage() { + strerr_die4x(100, "usage: ", progname, USAGE_SOFTLIMIT, "\n"); +} +void getlarg(long *l) { + unsigned long ul; + + if (str_equal(optarg, "=")) { *l =-1; return; } + if (optarg[scan_ulong(optarg, &ul)]) usage(); + *l =ul; +} +void softlimit(int argc, const char *const *argv) { + int opt; + + while ((opt =getopt(argc,argv,"a:c:d:f:l:m:o:p:r:s:t:")) != opteof) + switch(opt) { + case '?': softlimit_usage(); + case 'a': getlarg(&limita); break; + case 'c': getlarg(&limitc); break; + case 'd': getlarg(&limitd); break; + case 'f': getlarg(&limitf); break; + case 'l': getlarg(&limitl); break; + case 'm': getlarg(&limitd); limits =limitl =limita =limitd; break; + case 'o': getlarg(&limito); break; + case 'p': getlarg(&limitp); break; + case 'r': getlarg(&limitr); break; + case 's': getlarg(&limits); break; + case 't': getlarg(&limitt); break; + } + argv +=optind; + if (!*argv) softlimit_usage(); + slimit(); + pathexec(argv); + fatal2("unable to run", *argv); +} diff --git a/runit-2.1.2/src/chpst.check b/runit-2.1.2/src/chpst.check new file mode 100755 index 0000000..384113e --- /dev/null +++ b/runit-2.1.2/src/chpst.check @@ -0,0 +1,36 @@ +#!/bin/sh +rm -rf "${ctmp}" + +chpst +echo $? +chpst -V +echo $? + +# -u +# -U + +mkdir "${ctmp}" +echo 1 >"${ctmp}"/test +chpst -e"${ctmp}" env |sed -ne '/^test=1$/p' +echo $? +rm -rf "${ctmp}" + +chpst -l"${ctmp}" true +echo $? +rm -f "${ctmp}" + +chpst -L"${ctmp}" true +echo $? +rm -f "${ctmp}" + +# -m +# -o +# -p +# -f +# -c + +chpst -P true +echo $? + +chpst -012 true +echo $? diff --git a/runit-2.1.2/src/chpst.dist b/runit-2.1.2/src/chpst.dist new file mode 100644 index 0000000..6779bfd --- /dev/null +++ b/runit-2.1.2/src/chpst.dist @@ -0,0 +1,13 @@ +usage: chpst [-vP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] prog + +100 +$Id: f279d44141c981dd7535a12260efcf1ef7beed26 $ +usage: chpst [-vP012] [-u user[:group]] [-U user[:group]] [-b argv0] [-e dir] [-/ root] [-n nice] [-l|-L lock] [-m n] [-d n] [-o n] [-p n] [-f n] [-c n] prog + +100 +test=1 +0 +0 +0 +0 +0 diff --git a/runit-2.1.2/src/coe.c b/runit-2.1.2/src/coe.c new file mode 100644 index 0000000..50b2397 --- /dev/null +++ b/runit-2.1.2/src/coe.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <fcntl.h> +#include "coe.h" + +int coe(int fd) +{ + return fcntl(fd,F_SETFD,1); +} diff --git a/runit-2.1.2/src/coe.h b/runit-2.1.2/src/coe.h new file mode 100644 index 0000000..b17db54 --- /dev/null +++ b/runit-2.1.2/src/coe.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef COE_H +#define COE_H + +extern int coe(int); + +#endif diff --git a/runit-2.1.2/src/conf-cc b/runit-2.1.2/src/conf-cc new file mode 100644 index 0000000..984024f --- /dev/null +++ b/runit-2.1.2/src/conf-cc @@ -0,0 +1,5 @@ +gcc -O2 -Wall + +gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings + +This will be used to compile .c files. diff --git a/runit-2.1.2/src/conf-ld b/runit-2.1.2/src/conf-ld new file mode 100644 index 0000000..59a0de7 --- /dev/null +++ b/runit-2.1.2/src/conf-ld @@ -0,0 +1,3 @@ +gcc -s + +This will be used to link .o files into an executable. diff --git a/runit-2.1.2/src/direntry.h1 b/runit-2.1.2/src/direntry.h1 new file mode 100644 index 0000000..6cb088d --- /dev/null +++ b/runit-2.1.2/src/direntry.h1 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef DIRENTRY_H +#define DIRENTRY_H + +/* sysdep: -dirent */ + +#include <sys/types.h> +#include <sys/dir.h> +#define direntry struct direct + +#endif diff --git a/runit-2.1.2/src/direntry.h2 b/runit-2.1.2/src/direntry.h2 new file mode 100644 index 0000000..bfd4d19 --- /dev/null +++ b/runit-2.1.2/src/direntry.h2 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef DIRENTRY_H +#define DIRENTRY_H + +/* sysdep: +dirent */ + +#include <sys/types.h> +#include <dirent.h> +#define direntry struct dirent + +#endif diff --git a/runit-2.1.2/src/env.c b/runit-2.1.2/src/env.c new file mode 100644 index 0000000..1b3ef62 --- /dev/null +++ b/runit-2.1.2/src/env.c @@ -0,0 +1,17 @@ +/* Public domain. */ + +#include "str.h" +#include "env.h" + +extern /*@null@*/char *env_get(const char *s) +{ + int i; + unsigned int len; + + if (!s) return 0; + len = str_len(s); + for (i = 0;environ[i];++i) + if (str_start(environ[i],s) && (environ[i][len] == '=')) + return environ[i] + len + 1; + return 0; +} diff --git a/runit-2.1.2/src/env.h b/runit-2.1.2/src/env.h new file mode 100644 index 0000000..834d331 --- /dev/null +++ b/runit-2.1.2/src/env.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef ENV_H +#define ENV_H + +extern char **environ; + +extern /*@null@*/char *env_get(const char *); + +#endif diff --git a/runit-2.1.2/src/error.c b/runit-2.1.2/src/error.c new file mode 100644 index 0000000..ea5f9c2 --- /dev/null +++ b/runit-2.1.2/src/error.c @@ -0,0 +1,132 @@ +/* Public domain. */ + +#include <errno.h> +#include "error.h" + +/* warning: as coverage improves here, should update error_{str,temp} */ + +int error_intr = +#ifdef EINTR +EINTR; +#else +-1; +#endif + +int error_nomem = +#ifdef ENOMEM +ENOMEM; +#else +-2; +#endif + +int error_noent = +#ifdef ENOENT +ENOENT; +#else +-3; +#endif + +int error_txtbsy = +#ifdef ETXTBSY +ETXTBSY; +#else +-4; +#endif + +int error_io = +#ifdef EIO +EIO; +#else +-5; +#endif + +int error_exist = +#ifdef EEXIST +EEXIST; +#else +-6; +#endif + +int error_timeout = +#ifdef ETIMEDOUT +ETIMEDOUT; +#else +-7; +#endif + +int error_inprogress = +#ifdef EINPROGRESS +EINPROGRESS; +#else +-8; +#endif + +int error_wouldblock = +#ifdef EWOULDBLOCK +EWOULDBLOCK; +#else +-9; +#endif + +int error_again = +#ifdef EAGAIN +EAGAIN; +#else +-10; +#endif + +int error_pipe = +#ifdef EPIPE +EPIPE; +#else +-11; +#endif + +int error_perm = +#ifdef EPERM +EPERM; +#else +-12; +#endif + +int error_acces = +#ifdef EACCES +EACCES; +#else +-13; +#endif + +int error_nodevice = +#ifdef ENXIO +ENXIO; +#else +-14; +#endif + +int error_proto = +#ifdef EPROTO +EPROTO; +#else +-15; +#endif + +int error_isdir = +#ifdef EISDIR +EISDIR; +#else +-16; +#endif + +int error_connrefused = +#ifdef ECONNREFUSED +ECONNREFUSED; +#else +-17; +#endif + +int error_notdir = +#ifdef ENOTDIR +ENOTDIR; +#else +-18; +#endif diff --git a/runit-2.1.2/src/error.h b/runit-2.1.2/src/error.h new file mode 100644 index 0000000..8ecb400 --- /dev/null +++ b/runit-2.1.2/src/error.h @@ -0,0 +1,33 @@ +/* Public domain. */ + +#ifndef ERROR_H +#define ERROR_H + +/* 20030124: include <errno.h> -upcoming glibc changes */ +#include <errno.h> + +/* extern int errno; */ + +extern int error_intr; +extern int error_nomem; +extern int error_noent; +extern int error_txtbsy; +extern int error_io; +extern int error_exist; +extern int error_timeout; +extern int error_inprogress; +extern int error_wouldblock; +extern int error_again; +extern int error_pipe; +extern int error_perm; +extern int error_acces; +extern int error_nodevice; +extern int error_proto; +extern int error_isdir; +extern int error_connrefused; +extern int error_notdir; + +extern const char *error_str(int); +extern int error_temp(int); + +#endif diff --git a/runit-2.1.2/src/error_str.c b/runit-2.1.2/src/error_str.c new file mode 100644 index 0000000..e002efe --- /dev/null +++ b/runit-2.1.2/src/error_str.c @@ -0,0 +1,267 @@ +/* Public domain. */ + +#include <errno.h> +#include "error.h" + +#define X(e,s) if (i == e) return s; + +const char *error_str(int i) +{ + X(0,"no error") + X(error_intr,"interrupted system call") + X(error_nomem,"out of memory") + X(error_noent,"file does not exist") + X(error_txtbsy,"text busy") + X(error_io,"input/output error") + X(error_exist,"file already exists") + X(error_timeout,"timed out") + X(error_inprogress,"operation in progress") + X(error_again,"temporary failure") + X(error_wouldblock,"input/output would block") + X(error_pipe,"broken pipe") + X(error_perm,"permission denied") + X(error_acces,"access denied") + X(error_nodevice,"device not configured") + X(error_proto,"protocol error") + X(error_isdir,"is a directory") + X(error_connrefused,"connection refused") + X(error_notdir,"not a directory") +#ifdef ESRCH + X(ESRCH,"no such process") +#endif +#ifdef E2BIG + X(E2BIG,"argument list too long") +#endif +#ifdef ENOEXEC + X(ENOEXEC,"exec format error") +#endif +#ifdef EBADF + X(EBADF,"file descriptor not open") +#endif +#ifdef ECHILD + X(ECHILD,"no child processes") +#endif +#ifdef EDEADLK + X(EDEADLK,"operation would cause deadlock") +#endif +#ifdef EFAULT + X(EFAULT,"bad address") +#endif +#ifdef ENOTBLK + X(ENOTBLK,"not a block device") +#endif +#ifdef EBUSY + X(EBUSY,"device busy") +#endif +#ifdef EXDEV + X(EXDEV,"cross-device link") +#endif +#ifdef ENODEV + X(ENODEV,"device does not support operation") +#endif +#ifdef EINVAL + X(EINVAL,"invalid argument") +#endif +#ifdef ENFILE + X(ENFILE,"system cannot open more files") +#endif +#ifdef EMFILE + X(EMFILE,"process cannot open more files") +#endif +#ifdef ENOTTY + X(ENOTTY,"not a tty") +#endif +#ifdef EFBIG + X(EFBIG,"file too big") +#endif +#ifdef ENOSPC + X(ENOSPC,"out of disk space") +#endif +#ifdef ESPIPE + X(ESPIPE,"unseekable descriptor") +#endif +#ifdef EROFS + X(EROFS,"read-only file system") +#endif +#ifdef EMLINK + X(EMLINK,"too many links") +#endif +#ifdef EDOM + X(EDOM,"input out of range") +#endif +#ifdef ERANGE + X(ERANGE,"output out of range") +#endif +#ifdef EALREADY + X(EALREADY,"operation already in progress") +#endif +#ifdef ENOTSOCK + X(ENOTSOCK,"not a socket") +#endif +#ifdef EDESTADDRREQ + X(EDESTADDRREQ,"destination address required") +#endif +#ifdef EMSGSIZE + X(EMSGSIZE,"message too long") +#endif +#ifdef EPROTOTYPE + X(EPROTOTYPE,"incorrect protocol type") +#endif +#ifdef ENOPROTOOPT + X(ENOPROTOOPT,"protocol not available") +#endif +#ifdef EPROTONOSUPPORT + X(EPROTONOSUPPORT,"protocol not supported") +#endif +#ifdef ESOCKTNOSUPPORT + X(ESOCKTNOSUPPORT,"socket type not supported") +#endif +#ifdef EOPNOTSUPP + X(EOPNOTSUPP,"operation not supported") +#endif +#ifdef EPFNOSUPPORT + X(EPFNOSUPPORT,"protocol family not supported") +#endif +#ifdef EAFNOSUPPORT + X(EAFNOSUPPORT,"address family not supported") +#endif +#ifdef EADDRINUSE + X(EADDRINUSE,"address already used") +#endif +#ifdef EADDRNOTAVAIL + X(EADDRNOTAVAIL,"address not available") +#endif +#ifdef ENETDOWN + X(ENETDOWN,"network down") +#endif +#ifdef ENETUNREACH + X(ENETUNREACH,"network unreachable") +#endif +#ifdef ENETRESET + X(ENETRESET,"network reset") +#endif +#ifdef ECONNABORTED + X(ECONNABORTED,"connection aborted") +#endif +#ifdef ECONNRESET + X(ECONNRESET,"connection reset") +#endif +#ifdef ENOBUFS + X(ENOBUFS,"out of buffer space") +#endif +#ifdef EISCONN + X(EISCONN,"already connected") +#endif +#ifdef ENOTCONN + X(ENOTCONN,"not connected") +#endif +#ifdef ESHUTDOWN + X(ESHUTDOWN,"socket shut down") +#endif +#ifdef ETOOMANYREFS + X(ETOOMANYREFS,"too many references") +#endif +#ifdef ELOOP + X(ELOOP,"symbolic link loop") +#endif +#ifdef ENAMETOOLONG + X(ENAMETOOLONG,"file name too long") +#endif +#ifdef EHOSTDOWN + X(EHOSTDOWN,"host down") +#endif +#ifdef EHOSTUNREACH + X(EHOSTUNREACH,"host unreachable") +#endif +#ifdef ENOTEMPTY + X(ENOTEMPTY,"directory not empty") +#endif +#ifdef EPROCLIM + X(EPROCLIM,"too many processes") +#endif +#ifdef EUSERS + X(EUSERS,"too many users") +#endif +#ifdef EDQUOT + X(EDQUOT,"disk quota exceeded") +#endif +#ifdef ESTALE + X(ESTALE,"stale NFS file handle") +#endif +#ifdef EREMOTE + X(EREMOTE,"too many levels of remote in path") +#endif +#ifdef EBADRPC + X(EBADRPC,"RPC structure is bad") +#endif +#ifdef ERPCMISMATCH + X(ERPCMISMATCH,"RPC version mismatch") +#endif +#ifdef EPROGUNAVAIL + X(EPROGUNAVAIL,"RPC program unavailable") +#endif +#ifdef EPROGMISMATCH + X(EPROGMISMATCH,"program version mismatch") +#endif +#ifdef EPROCUNAVAIL + X(EPROCUNAVAIL,"bad procedure for program") +#endif +#ifdef ENOLCK + X(ENOLCK,"no locks available") +#endif +#ifdef ENOSYS + X(ENOSYS,"system call not available") +#endif +#ifdef EFTYPE + X(EFTYPE,"bad file type") +#endif +#ifdef EAUTH + X(EAUTH,"authentication error") +#endif +#ifdef ENEEDAUTH + X(ENEEDAUTH,"not authenticated") +#endif +#ifdef ENOSTR + X(ENOSTR,"not a stream device") +#endif +#ifdef ETIME + X(ETIME,"timer expired") +#endif +#ifdef ENOSR + X(ENOSR,"out of stream resources") +#endif +#ifdef ENOMSG + X(ENOMSG,"no message of desired type") +#endif +#ifdef EBADMSG + X(EBADMSG,"bad message type") +#endif +#ifdef EIDRM + X(EIDRM,"identifier removed") +#endif +#ifdef ENONET + X(ENONET,"machine not on network") +#endif +#ifdef ERREMOTE + X(ERREMOTE,"object not local") +#endif +#ifdef ENOLINK + X(ENOLINK,"link severed") +#endif +#ifdef EADV + X(EADV,"advertise error") +#endif +#ifdef ESRMNT + X(ESRMNT,"srmount error") +#endif +#ifdef ECOMM + X(ECOMM,"communication error") +#endif +#ifdef EMULTIHOP + X(EMULTIHOP,"multihop attempted") +#endif +#ifdef EREMCHG + X(EREMCHG,"remote address changed") +#endif + return "unknown error"; +} diff --git a/runit-2.1.2/src/fd.h b/runit-2.1.2/src/fd.h new file mode 100644 index 0000000..1c7a035 --- /dev/null +++ b/runit-2.1.2/src/fd.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef FD_H +#define FD_H + +extern int fd_copy(int,int); +extern int fd_move(int,int); + +#endif diff --git a/runit-2.1.2/src/fd_copy.c b/runit-2.1.2/src/fd_copy.c new file mode 100644 index 0000000..80e9d15 --- /dev/null +++ b/runit-2.1.2/src/fd_copy.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include <unistd.h> +#include <fcntl.h> +#include "fd.h" + +int fd_copy(int to,int from) +{ + if (to == from) return 0; + if (fcntl(from,F_GETFL,0) == -1) return -1; + close(to); + if (fcntl(from,F_DUPFD,to) == -1) return -1; + return 0; +} diff --git a/runit-2.1.2/src/fd_move.c b/runit-2.1.2/src/fd_move.c new file mode 100644 index 0000000..49f723f --- /dev/null +++ b/runit-2.1.2/src/fd_move.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <unistd.h> +#include "fd.h" + +int fd_move(int to,int from) +{ + if (to == from) return 0; + if (fd_copy(to,from) == -1) return -1; + close(from); + return 0; +} diff --git a/runit-2.1.2/src/fifo.c b/runit-2.1.2/src/fifo.c new file mode 100644 index 0000000..c14f683 --- /dev/null +++ b/runit-2.1.2/src/fifo.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include "hasmkffo.h" +#include "fifo.h" + +#ifdef HASMKFIFO +int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); } +#else +int fifo_make(const char *fn,int mode) { return mknod(fn,S_IFIFO | mode,0); } +#endif diff --git a/runit-2.1.2/src/fifo.h b/runit-2.1.2/src/fifo.h new file mode 100644 index 0000000..ba75678 --- /dev/null +++ b/runit-2.1.2/src/fifo.h @@ -0,0 +1,8 @@ +/* Public domain. */ + +#ifndef FIFO_H +#define FIFO_H + +extern int fifo_make(const char *,int); + +#endif diff --git a/runit-2.1.2/src/find-systype.sh b/runit-2.1.2/src/find-systype.sh new file mode 100644 index 0000000..9f6e565 --- /dev/null +++ b/runit-2.1.2/src/find-systype.sh @@ -0,0 +1,143 @@ +# oper-:arch-:syst-:chip-:kern- +# oper = operating system type; e.g., sunos-4.1.4 +# arch = machine language; e.g., sparc +# syst = which binaries can run; e.g., sun4 +# chip = chip model; e.g., micro-2-80 +# kern = kernel version; e.g., sun4m +# dependence: arch --- chip +# \ \ +# oper --- syst --- kern +# so, for example, syst is interpreted in light of oper, but chip is not. +# anyway, no slashes, no extra colons, no uppercase letters. +# the point of the extra -'s is to ease parsing: can add hierarchies later. +# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, +# and i386-486 (486s do have more instructions, you know) as well as i386. +# the idea here is to include ALL useful available information. + +exec 2>/dev/null + +sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" +if [ x"$sys" != x ] +then + unamer="`uname -r | tr /: ..`" + unamem="`uname -m | tr /: ..`" + unamev="`uname -v | tr /: ..`" + + case "$sys" in + bsd.os|freebsd|netbsd|openbsd) + # in bsd 4.4, uname -v does not have useful info. + # in bsd 4.4, uname -m is arch, not chip. + oper="$sys-$unamer" + arch="$unamem" + syst="" + chip="`sysctl -n hw.model`" # hopefully + kern="" + ;; + linux) + # as in bsd 4.4, uname -v does not have useful info. + oper="$sys-$unamer" + syst="" + chip="$unamem" + kern="" + case "$chip" in + i386|i486|i586|i686) + arch="i386" + ;; + alpha) + arch="alpha" + ;; + esac + ;; + aix) + # naturally IBM has to get uname -r and uname -v backwards. dorks. + oper="$sys-$unamev-$unamer" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + sunos) + oper="$sys-$unamer-$unamev" + arch="`(uname -p || mach) | tr /: ..`" + syst="`arch | tr /: ..`" + chip="$unamem" # this is wrong; is there any way to get the real info? + kern="`arch -k | tr /: ..`" + ;; + unix_sv) + oper="$sys-$unamer-$unamev" + arch="`uname -m`" + syst="" + chip="$unamem" + kern="" + ;; + *) + oper="$sys-$unamer-$unamev" + arch="`arch | tr /: ..`" + syst="" + chip="$unamem" + kern="" + ;; + esac +else + gcc -c trycpp.c + gcc -o trycpp trycpp.o + case `./trycpp` in + nextstep) + oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" + arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" + syst="" + chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" + kern="" + ;; + *) + oper="unknown" + arch="" + syst="" + chip="" + kern="" + ;; + esac + rm -f trycpp.o trycpp +fi + +case "$chip" in +80486) + # let's try to be consistent here. (BSD/OS) + chip=i486 + ;; +i486DX) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx + ;; +i486.DX2) + # respect the hyphen hierarchy. (FreeBSD) + chip=i486-dx2 + ;; +Intel.586) + # no, you nitwits, there is no such chip. (NeXTStep) + chip=pentium + ;; +i586) + # no, you nitwits, there is no such chip. (Linux) + chip=pentium + ;; +i686) + # STOP SAYING THAT! (Linux) + chip=ppro +esac + +if gcc -c x86cpuid.c +then + if gcc -o x86cpuid x86cpuid.o + then + x86cpuid="`./x86cpuid | tr /: ..`" + case "$x86cpuid" in + ?*) + chip="$x86cpuid" + ;; + esac + fi +fi +rm -f x86cpuid x86cpuid.o + +echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' diff --git a/runit-2.1.2/src/fmt.h b/runit-2.1.2/src/fmt.h new file mode 100644 index 0000000..8847fa6 --- /dev/null +++ b/runit-2.1.2/src/fmt.h @@ -0,0 +1,27 @@ +/* Public domain. */ + +#ifndef FMT_H +#define FMT_H + +#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ +#define FMT_LEN ((char *) 0) /* convenient abbreviation */ + +extern unsigned int fmt_uint(char *,unsigned int); +extern unsigned int fmt_uint0(char *,unsigned int,unsigned int); +extern unsigned int fmt_xint(char *,unsigned int); +extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int); +extern unsigned int fmt_ushort(char *,unsigned short); +extern unsigned int fmt_xshort(char *,unsigned short); +extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short); +extern unsigned int fmt_ulong(char *,unsigned long); +extern unsigned int fmt_xlong(char *,unsigned long); +extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long); + +extern unsigned int fmt_plusminus(char *,int); +extern unsigned int fmt_minus(char *,int); +extern unsigned int fmt_0x(char *,int); + +extern unsigned int fmt_str(char *,const char *); +extern unsigned int fmt_strn(char *,const char *,unsigned int); + +#endif diff --git a/runit-2.1.2/src/fmt_ptime.c b/runit-2.1.2/src/fmt_ptime.c new file mode 100644 index 0000000..2ab5725 --- /dev/null +++ b/runit-2.1.2/src/fmt_ptime.c @@ -0,0 +1,42 @@ +#include <time.h> +#include "fmt_ptime.h" +#include "fmt.h" + +unsigned int fmt_ptime2(char *s, struct taia *ta, char sep) { + struct tm *t; + time_t u; + + if (ta->sec.x < 4611686018427387914ULL) return(0); /* impossible? */ + u =ta->sec.x -4611686018427387914ULL; + if (! (t =gmtime((time_t*)&u))) return(0); + fmt_ulong(s, 1900 +t->tm_year); + s[4] ='-'; fmt_uint0(&s[5], t->tm_mon +1, 2); + s[7] ='-'; fmt_uint0(&s[8], t->tm_mday, 2); + s[10] =sep; fmt_uint0(&s[11], t->tm_hour, 2); + s[13] =':'; fmt_uint0(&s[14], t->tm_min, 2); + s[16] =':'; fmt_uint0(&s[17], t->tm_sec, 2); + s[19] ='.'; fmt_uint0(&s[20], ta->nano, 9); + return(25); +} + +unsigned int fmt_ptime(char *s, struct taia *ta) { + return(fmt_ptime2(s, ta, '_')); +} + +unsigned int fmt_ptime_iso8601(char *s, struct taia *ta) { + return(fmt_ptime2(s, ta, 'T')); +} + +unsigned int fmt_taia(char *s, struct taia *t) { + static char hex[16] ="0123456789abcdef"; + static char pack[TAIA_PACK]; + int i; + + taia_pack(pack, t); + s[0] ='@'; + for (i =0; i < 12; ++i) { + s[i *2 +1] =hex[(pack[i] >>4) &15]; + s[i *2 +2] =hex[pack[i] &15]; + } + return(25); +} diff --git a/runit-2.1.2/src/fmt_ptime.h b/runit-2.1.2/src/fmt_ptime.h new file mode 100644 index 0000000..72ea008 --- /dev/null +++ b/runit-2.1.2/src/fmt_ptime.h @@ -0,0 +1,14 @@ +#ifndef FMT_PTIME_H +#define FMT_PTIME_H + +#define FMT_PTIME 30 + +#include <time.h> +#include <sys/time.h> +#include "taia.h" + +extern unsigned int fmt_ptime(char *, struct taia *); +extern unsigned int fmt_ptime_iso8601(char *, struct taia *); +extern unsigned int fmt_taia(char *, struct taia *); + +#endif diff --git a/runit-2.1.2/src/fmt_uint.c b/runit-2.1.2/src/fmt_uint.c new file mode 100644 index 0000000..b8ec0b7 --- /dev/null +++ b/runit-2.1.2/src/fmt_uint.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "fmt.h" + +unsigned int fmt_uint(register char *s,register unsigned int u) +{ + return fmt_ulong(s,u); +} diff --git a/runit-2.1.2/src/fmt_uint0.c b/runit-2.1.2/src/fmt_uint0.c new file mode 100644 index 0000000..728a5aa --- /dev/null +++ b/runit-2.1.2/src/fmt_uint0.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include "fmt.h" + +unsigned int fmt_uint0(char *s,unsigned int u,unsigned int n) +{ + unsigned int len; + len = fmt_uint(FMT_LEN,u); + while (len < n) { if (s) *s++ = '0'; ++len; } + if (s) fmt_uint(s,u); + return len; +} diff --git a/runit-2.1.2/src/fmt_ulong.c b/runit-2.1.2/src/fmt_ulong.c new file mode 100644 index 0000000..168572f --- /dev/null +++ b/runit-2.1.2/src/fmt_ulong.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include "fmt.h" + +unsigned int fmt_ulong(register char *s,register unsigned long u) +{ + register unsigned int len; register unsigned long q; + len = 1; q = u; + while (q > 9) { ++len; q /= 10; } + if (s) { + s += len; + do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ + } + return len; +} diff --git a/runit-2.1.2/src/gen_alloc.h b/runit-2.1.2/src/gen_alloc.h new file mode 100644 index 0000000..bd55e5b --- /dev/null +++ b/runit-2.1.2/src/gen_alloc.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +#define GEN_ALLOC_typedef(ta,type,field,len,a) \ + typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; + +#endif diff --git a/runit-2.1.2/src/gen_allocdefs.h b/runit-2.1.2/src/gen_allocdefs.h new file mode 100644 index 0000000..3afd92b --- /dev/null +++ b/runit-2.1.2/src/gen_allocdefs.h @@ -0,0 +1,36 @@ +/* Public domain. */ + +#ifndef GEN_ALLOC_DEFS_H +#define GEN_ALLOC_DEFS_H + +#define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ +int ta_ready(register ta *x,register unsigned int n) \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ +int ta_rplus(register ta *x,register unsigned int n) \ +{ register unsigned int i; \ + if (x->field) { \ + i = x->a; n += x->len; \ + if (n > i) { \ + x->a = base + n + (n >> 3); \ + if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ + x->a = i; return 0; } \ + return 1; } \ + x->len = 0; \ + return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } + +#define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ +int ta_append(register ta *x,register const type *i) \ +{ if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } + +#endif diff --git a/runit-2.1.2/src/hasflock.h1 b/runit-2.1.2/src/hasflock.h1 new file mode 100644 index 0000000..ac7dfc3 --- /dev/null +++ b/runit-2.1.2/src/hasflock.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -flock */ diff --git a/runit-2.1.2/src/hasflock.h2 b/runit-2.1.2/src/hasflock.h2 new file mode 100644 index 0000000..1878f64 --- /dev/null +++ b/runit-2.1.2/src/hasflock.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +flock */ +#define HASFLOCK 1 diff --git a/runit-2.1.2/src/hasmkffo.h1 b/runit-2.1.2/src/hasmkffo.h1 new file mode 100644 index 0000000..a562451 --- /dev/null +++ b/runit-2.1.2/src/hasmkffo.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -mkfifo */ diff --git a/runit-2.1.2/src/hasmkffo.h2 b/runit-2.1.2/src/hasmkffo.h2 new file mode 100644 index 0000000..8ac8943 --- /dev/null +++ b/runit-2.1.2/src/hasmkffo.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +mkfifo */ +#define HASMKFIFO 1 diff --git a/runit-2.1.2/src/hassgact.h1 b/runit-2.1.2/src/hassgact.h1 new file mode 100644 index 0000000..7639d24 --- /dev/null +++ b/runit-2.1.2/src/hassgact.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -sigaction */ diff --git a/runit-2.1.2/src/hassgact.h2 b/runit-2.1.2/src/hassgact.h2 new file mode 100644 index 0000000..60ff776 --- /dev/null +++ b/runit-2.1.2/src/hassgact.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +sigaction */ +#define HASSIGACTION 1 diff --git a/runit-2.1.2/src/hassgprm.h1 b/runit-2.1.2/src/hassgprm.h1 new file mode 100644 index 0000000..ef3eee9 --- /dev/null +++ b/runit-2.1.2/src/hassgprm.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -sigprocmask */ diff --git a/runit-2.1.2/src/hassgprm.h2 b/runit-2.1.2/src/hassgprm.h2 new file mode 100644 index 0000000..be9d0d7 --- /dev/null +++ b/runit-2.1.2/src/hassgprm.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +sigprocmask */ +#define HASSIGPROCMASK 1 diff --git a/runit-2.1.2/src/hasshsgr.h1 b/runit-2.1.2/src/hasshsgr.h1 new file mode 100644 index 0000000..3806277 --- /dev/null +++ b/runit-2.1.2/src/hasshsgr.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -shortsetgroups */ diff --git a/runit-2.1.2/src/hasshsgr.h2 b/runit-2.1.2/src/hasshsgr.h2 new file mode 100644 index 0000000..5624ed0 --- /dev/null +++ b/runit-2.1.2/src/hasshsgr.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +shortsetgroups */ +#define HASSHORTSETGROUPS 1 diff --git a/runit-2.1.2/src/haswaitp.h1 b/runit-2.1.2/src/haswaitp.h1 new file mode 100644 index 0000000..0d6f82c --- /dev/null +++ b/runit-2.1.2/src/haswaitp.h1 @@ -0,0 +1,3 @@ +/* Public domain. */ + +/* sysdep: -waitpid */ diff --git a/runit-2.1.2/src/haswaitp.h2 b/runit-2.1.2/src/haswaitp.h2 new file mode 100644 index 0000000..015413f --- /dev/null +++ b/runit-2.1.2/src/haswaitp.h2 @@ -0,0 +1,4 @@ +/* Public domain. */ + +/* sysdep: +waitpid */ +#define HASWAITPID 1 diff --git a/runit-2.1.2/src/iopause.c b/runit-2.1.2/src/iopause.c new file mode 100644 index 0000000..ea5a426 --- /dev/null +++ b/runit-2.1.2/src/iopause.c @@ -0,0 +1,78 @@ +/* Public domain. */ + +#include "taia.h" +#include "select.h" +#include "iopause.h" + +void iopause(iopause_fd *x,unsigned int len,struct taia *deadline,struct taia *stamp) +{ + struct taia t; + int millisecs; + double d; + int i; + + if (taia_less(deadline,stamp)) + millisecs = 0; + else { + t = *stamp; + taia_sub(&t,deadline,&t); + d = taia_approx(&t); + if (d > 1000.0) d = 1000.0; + millisecs = d * 1000.0 + 20.0; + } + + for (i = 0;i < len;++i) + x[i].revents = 0; + +#ifdef IOPAUSE_POLL + + poll(x,len,millisecs); + /* XXX: some kernels apparently need x[0] even if len is 0 */ + /* XXX: how to handle EAGAIN? are kernels really this dumb? */ + /* XXX: how to handle EINVAL? when exactly can this happen? */ + +#else +{ + + struct timeval tv; + fd_set rfds; + fd_set wfds; + int nfds; + int fd; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + nfds = 1; + for (i = 0;i < len;++i) { + fd = x[i].fd; + if (fd < 0) continue; + if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ + + if (fd >= nfds) nfds = fd + 1; + if (x[i].events & IOPAUSE_READ) FD_SET(fd,&rfds); + if (x[i].events & IOPAUSE_WRITE) FD_SET(fd,&wfds); + } + + tv.tv_sec = millisecs / 1000; + tv.tv_usec = 1000 * (millisecs % 1000); + + if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) <= 0) + return; + /* XXX: for EBADF, could seek out and destroy the bad descriptor */ + + for (i = 0;i < len;++i) { + fd = x[i].fd; + if (fd < 0) continue; + if (fd >= 8 * sizeof(fd_set)) continue; /*XXX*/ + + if (x[i].events & IOPAUSE_READ) + if (FD_ISSET(fd,&rfds)) x[i].revents |= IOPAUSE_READ; + if (x[i].events & IOPAUSE_WRITE) + if (FD_ISSET(fd,&wfds)) x[i].revents |= IOPAUSE_WRITE; + } + +} +#endif + +} diff --git a/runit-2.1.2/src/iopause.h1 b/runit-2.1.2/src/iopause.h1 new file mode 100644 index 0000000..5c53de7 --- /dev/null +++ b/runit-2.1.2/src/iopause.h1 @@ -0,0 +1,21 @@ +/* Public domain. */ + +#ifndef IOPAUSE_H +#define IOPAUSE_H + +/* sysdep: -poll */ + +typedef struct { + int fd; + short events; + short revents; +} iopause_fd; + +#define IOPAUSE_READ 1 +#define IOPAUSE_WRITE 4 + +#include "taia.h" + +extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *); + +#endif diff --git a/runit-2.1.2/src/iopause.h2 b/runit-2.1.2/src/iopause.h2 new file mode 100644 index 0000000..8e58452 --- /dev/null +++ b/runit-2.1.2/src/iopause.h2 @@ -0,0 +1,20 @@ +/* Public domain. */ + +#ifndef IOPAUSE_H +#define IOPAUSE_H + +/* sysdep: +poll */ +#define IOPAUSE_POLL + +#include <sys/types.h> +#include <poll.h> + +typedef struct pollfd iopause_fd; +#define IOPAUSE_READ POLLIN +#define IOPAUSE_WRITE POLLOUT + +#include "taia.h" + +extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *); + +#endif diff --git a/runit-2.1.2/src/lock.h b/runit-2.1.2/src/lock.h new file mode 100644 index 0000000..4a96cdc --- /dev/null +++ b/runit-2.1.2/src/lock.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef LOCK_H +#define LOCK_H + +extern int lock_ex(int); +extern int lock_un(int); +extern int lock_exnb(int); + +#endif diff --git a/runit-2.1.2/src/lock_ex.c b/runit-2.1.2/src/lock_ex.c new file mode 100644 index 0000000..b75a764 --- /dev/null +++ b/runit-2.1.2/src/lock_ex.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/file.h> +#include <fcntl.h> +#include "hasflock.h" +#include "lock.h" + +#ifdef HASFLOCK +int lock_ex(int fd) { return flock(fd,LOCK_EX); } +#else +int lock_ex(int fd) { return lockf(fd,1,0); } +#endif diff --git a/runit-2.1.2/src/lock_exnb.c b/runit-2.1.2/src/lock_exnb.c new file mode 100644 index 0000000..9ec2b9c --- /dev/null +++ b/runit-2.1.2/src/lock_exnb.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/file.h> +#include <fcntl.h> +#include "hasflock.h" +#include "lock.h" + +#ifdef HASFLOCK +int lock_exnb(int fd) { return flock(fd,LOCK_EX | LOCK_NB); } +#else +int lock_exnb(int fd) { return lockf(fd,2,0); } +#endif diff --git a/runit-2.1.2/src/ndelay.h b/runit-2.1.2/src/ndelay.h new file mode 100644 index 0000000..dbe91b2 --- /dev/null +++ b/runit-2.1.2/src/ndelay.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef NDELAY_H +#define NDELAY_H + +extern int ndelay_on(int); +extern int ndelay_off(int); + +#endif diff --git a/runit-2.1.2/src/ndelay_off.c b/runit-2.1.2/src/ndelay_off.c new file mode 100644 index 0000000..92d3244 --- /dev/null +++ b/runit-2.1.2/src/ndelay_off.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include "ndelay.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_off(int fd) +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); +} diff --git a/runit-2.1.2/src/ndelay_on.c b/runit-2.1.2/src/ndelay_on.c new file mode 100644 index 0000000..b96a6b2 --- /dev/null +++ b/runit-2.1.2/src/ndelay_on.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include "ndelay.h" + +#ifndef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + +int ndelay_on(int fd) +{ + return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); +} diff --git a/runit-2.1.2/src/open.h b/runit-2.1.2/src/open.h new file mode 100644 index 0000000..9939663 --- /dev/null +++ b/runit-2.1.2/src/open.h @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef OPEN_H +#define OPEN_H + +extern int open_read(const char *); +extern int open_excl(const char *); +extern int open_append(const char *); +extern int open_trunc(const char *); +extern int open_write(const char *); + +#endif diff --git a/runit-2.1.2/src/open_append.c b/runit-2.1.2/src/open_append.c new file mode 100644 index 0000000..d1b241b --- /dev/null +++ b/runit-2.1.2/src/open_append.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include "open.h" + +int open_append(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } diff --git a/runit-2.1.2/src/open_read.c b/runit-2.1.2/src/open_read.c new file mode 100644 index 0000000..99b3cd1 --- /dev/null +++ b/runit-2.1.2/src/open_read.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include "open.h" + +int open_read(const char *fn) +{ return open(fn,O_RDONLY | O_NDELAY); } diff --git a/runit-2.1.2/src/open_trunc.c b/runit-2.1.2/src/open_trunc.c new file mode 100644 index 0000000..6e0c4c2 --- /dev/null +++ b/runit-2.1.2/src/open_trunc.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include "open.h" + +int open_trunc(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } diff --git a/runit-2.1.2/src/open_write.c b/runit-2.1.2/src/open_write.c new file mode 100644 index 0000000..34cfa9b --- /dev/null +++ b/runit-2.1.2/src/open_write.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include "open.h" + +int open_write(const char *fn) +{ return open(fn,O_WRONLY | O_NDELAY); } diff --git a/runit-2.1.2/src/openreadclose.c b/runit-2.1.2/src/openreadclose.c new file mode 100644 index 0000000..635933b --- /dev/null +++ b/runit-2.1.2/src/openreadclose.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "error.h" +#include "open.h" +#include "readclose.h" +#include "openreadclose.h" + +int openreadclose(const char *fn,stralloc *sa,unsigned int bufsize) +{ + int fd; + fd = open_read(fn); + if (fd == -1) { + if (errno == error_noent) return 0; + return -1; + } + if (readclose(fd,sa,bufsize) == -1) return -1; + return 1; +} diff --git a/runit-2.1.2/src/openreadclose.h b/runit-2.1.2/src/openreadclose.h new file mode 100644 index 0000000..728899c --- /dev/null +++ b/runit-2.1.2/src/openreadclose.h @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef OPENREADCLOSE_H +#define OPENREADCLOSE_H + +#include "stralloc.h" + +extern int openreadclose(const char *,stralloc *,unsigned int); + +#endif diff --git a/runit-2.1.2/src/pathexec.h b/runit-2.1.2/src/pathexec.h new file mode 100644 index 0000000..d46ab17 --- /dev/null +++ b/runit-2.1.2/src/pathexec.h @@ -0,0 +1,11 @@ +/* Public domain. */ + +#ifndef PATHEXEC_H +#define PATHEXEC_H + +extern void pathexec_run(const char *,const char * const *,const char * const *); +extern int pathexec_env(const char *,const char *); +extern void pathexec_env_run(const char *, const char * const *); +extern void pathexec(const char * const *); + +#endif diff --git a/runit-2.1.2/src/pathexec_env.c b/runit-2.1.2/src/pathexec_env.c new file mode 100644 index 0000000..1305469 --- /dev/null +++ b/runit-2.1.2/src/pathexec_env.c @@ -0,0 +1,74 @@ +/* Public domain. */ + +#include "stralloc.h" +#include "alloc.h" +#include "str.h" +#include "byte.h" +#include "env.h" +#include "pathexec.h" + +static stralloc plus; +static stralloc tmp; + +int pathexec_env(const char *s,const char *t) +{ + if (!s) return 1; + if (!stralloc_copys(&tmp,s)) return 0; + if (t) { + if (!stralloc_cats(&tmp,"=")) return 0; + if (!stralloc_cats(&tmp,t)) return 0; + } + if (!stralloc_0(&tmp)) return 0; + return stralloc_cat(&plus,&tmp); +} + +void pathexec_env_run(const char *file, const char *const *argv) +{ + const char **e; + unsigned int elen; + unsigned int i; + unsigned int j; + unsigned int split; + unsigned int t; + + if (!stralloc_cats(&plus,"")) return; + + elen = 0; + for (i = 0;environ[i];++i) + ++elen; + for (i = 0;i < plus.len;++i) + if (!plus.s[i]) + ++elen; + + e = (const char **) alloc((elen + 1) * sizeof(char *)); + if (!e) return; + + elen = 0; + for (i = 0;environ[i];++i) + e[elen++] = environ[i]; + + j = 0; + for (i = 0;i < plus.len;++i) + if (!plus.s[i]) { + split = str_chr(plus.s + j,'='); + for (t = 0;t < elen;++t) + if (byte_equal(plus.s + j,split,e[t])) + if (e[t][split] == '=') { + --elen; + e[t] = e[elen]; + break; + } + if (plus.s[j + split]) + e[elen++] = plus.s + j; + j = i + 1; + } + e[elen] = 0; + + pathexec_run(file,argv,e); + alloc_free(e); +} + +void pathexec(const char *const *argv) +{ + return pathexec_env_run(*argv, argv); +} diff --git a/runit-2.1.2/src/pathexec_run.c b/runit-2.1.2/src/pathexec_run.c new file mode 100644 index 0000000..1770ac7 --- /dev/null +++ b/runit-2.1.2/src/pathexec_run.c @@ -0,0 +1,48 @@ +/* Public domain. */ + +#include "error.h" +#include "stralloc.h" +#include "str.h" +#include "env.h" +#include "pathexec.h" + +static stralloc tmp; + +void pathexec_run(const char *file,const char * const *argv,const char * const *envp) +{ + const char *path; + unsigned int split; + int savederrno; + + if (file[str_chr(file,'/')]) { + execve(file,argv,envp); + return; + } + + path = env_get("PATH"); + if (!path) path = "/bin:/usr/bin"; + + savederrno = 0; + for (;;) { + split = str_chr(path,':'); + if (!stralloc_copyb(&tmp,path,split)) return; + if (!split) + if (!stralloc_cats(&tmp,".")) return; + if (!stralloc_cats(&tmp,"/")) return; + if (!stralloc_cats(&tmp,file)) return; + if (!stralloc_0(&tmp)) return; + + execve(tmp.s,argv,envp); + if (errno != error_noent) { + savederrno = errno; + if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; + } + + if (!path[split]) { + if (savederrno) errno = savederrno; + return; + } + path += split; + path += 1; + } +} diff --git a/runit-2.1.2/src/pmatch.c b/runit-2.1.2/src/pmatch.c new file mode 100644 index 0000000..2fc9a53 --- /dev/null +++ b/runit-2.1.2/src/pmatch.c @@ -0,0 +1,40 @@ + +int pmatch(const char *p, const char *s, unsigned int len) { + for (;;) { + char c =*p++; + if (! c) return(! len); + switch(c) { + case '*': + if (! (c =*p)) return(1); + for (;;) { + if (! len) return(0); + if (*s == c) break; + ++s; --len; + } + continue; + case '+': + if ((c =*p++) != *s) return(0); + for (;;) { + if (! len) return(1); + if (*s != c) break; + ++s; --len; + } + continue; + /* + case '?': + if (*p == '?') { + if (*s != '?') return(0); + ++p; + } + ++s; --len; + continue; + */ + default: + if (! len) return(0); + if (*s != c) return(0); + ++s; --len; + continue; + } + } + return(0); +} diff --git a/runit-2.1.2/src/pmatch.h b/runit-2.1.2/src/pmatch.h new file mode 100644 index 0000000..8d4eb8b --- /dev/null +++ b/runit-2.1.2/src/pmatch.h @@ -0,0 +1,6 @@ +#ifndef PMATCH_H +#define PMATCH_H + +extern unsigned int pmatch(const char *, const char *, unsigned int); + +#endif diff --git a/runit-2.1.2/src/print-ar.sh b/runit-2.1.2/src/print-ar.sh new file mode 100644 index 0000000..99bc116 --- /dev/null +++ b/runit-2.1.2/src/print-ar.sh @@ -0,0 +1,14 @@ +cat warn-auto.sh +echo 'main="$1"; shift' +echo 'rm -f "$main"' +echo 'ar cr "$main" ${1+"$@"}' +case "`cat systype`" in + sunos-5.*) ;; + unix_sv*) ;; + irix64-*) ;; + irix-*) ;; + dgux-*) ;; + hp-ux-*) ;; + sco*) ;; + *) echo 'ranlib "$main"' ;; +esac diff --git a/runit-2.1.2/src/print-cc.sh b/runit-2.1.2/src/print-cc.sh new file mode 100644 index 0000000..31f4ed3 --- /dev/null +++ b/runit-2.1.2/src/print-cc.sh @@ -0,0 +1,5 @@ +cc="`head -n1 conf-cc`" +systype="`cat systype`" + +cat warn-auto.sh +echo exec "$cc" '-c ${1+"$@"}' diff --git a/runit-2.1.2/src/print-ld.sh b/runit-2.1.2/src/print-ld.sh new file mode 100644 index 0000000..59489a8 --- /dev/null +++ b/runit-2.1.2/src/print-ld.sh @@ -0,0 +1,6 @@ +ld="`head -n1 conf-ld`" +systype="`cat systype`" + +cat warn-auto.sh +echo 'main="$1"; shift' +echo exec "$ld" '-o "$main" "$main".o ${1+"$@"}' diff --git a/runit-2.1.2/src/prot.c b/runit-2.1.2/src/prot.c new file mode 100644 index 0000000..79a88c5 --- /dev/null +++ b/runit-2.1.2/src/prot.c @@ -0,0 +1,21 @@ +/* Public domain. */ + +#include "hasshsgr.h" +#include "prot.h" + +int prot_gid(int gid) +{ +#ifdef HASSHORTSETGROUPS + short x[2]; + x[0] = gid; x[1] = 73; /* catch errors */ + if (setgroups(1,x) == -1) return -1; +#else + if (setgroups(1,&gid) == -1) return -1; +#endif + return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ +} + +int prot_uid(int uid) +{ + return setuid(uid); +} diff --git a/runit-2.1.2/src/prot.h b/runit-2.1.2/src/prot.h new file mode 100644 index 0000000..2e5cb81 --- /dev/null +++ b/runit-2.1.2/src/prot.h @@ -0,0 +1,9 @@ +/* Public domain. */ + +#ifndef PROT_H +#define PROT_H + +extern int prot_gid(int); +extern int prot_uid(int); + +#endif diff --git a/runit-2.1.2/src/readclose.c b/runit-2.1.2/src/readclose.c new file mode 100644 index 0000000..9d83007 --- /dev/null +++ b/runit-2.1.2/src/readclose.c @@ -0,0 +1,23 @@ +/* Public domain. */ + +#include <unistd.h> +#include "error.h" +#include "readclose.h" + +int readclose_append(int fd,stralloc *sa,unsigned int bufsize) +{ + int r; + for (;;) { + if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } + r = read(fd,sa->s + sa->len,bufsize); + if (r == -1) if (errno == error_intr) continue; + if (r <= 0) { close(fd); return r; } + sa->len += r; + } +} + +int readclose(int fd,stralloc *sa,unsigned int bufsize) +{ + if (!stralloc_copys(sa,"")) { close(fd); return -1; } + return readclose_append(fd,sa,bufsize); +} diff --git a/runit-2.1.2/src/readclose.h b/runit-2.1.2/src/readclose.h new file mode 100644 index 0000000..bde9889 --- /dev/null +++ b/runit-2.1.2/src/readclose.h @@ -0,0 +1,11 @@ +/* Public domain. */ + +#ifndef READCLOSE_H +#define READCLOSE_H + +#include "stralloc.h" + +extern int readclose_append(int,stralloc *,unsigned int); +extern int readclose(int,stralloc *,unsigned int); + +#endif diff --git a/runit-2.1.2/src/reboot_system.h1 b/runit-2.1.2/src/reboot_system.h1 new file mode 100644 index 0000000..d4950c9 --- /dev/null +++ b/runit-2.1.2/src/reboot_system.h1 @@ -0,0 +1,8 @@ +#include <unistd.h> +#include <sys/reboot.h> + +/* sysdep: -std reboot */ + +int reboot_system(int what) { + return(reboot(what, (char *)0)); +} diff --git a/runit-2.1.2/src/reboot_system.h2 b/runit-2.1.2/src/reboot_system.h2 new file mode 100644 index 0000000..b30d1e9 --- /dev/null +++ b/runit-2.1.2/src/reboot_system.h2 @@ -0,0 +1,8 @@ +#include <unistd.h> +#include <sys/reboot.h> + +/* sysdep: +std reboot */ + +int reboot_system(int what) { + return(reboot(what)); +} diff --git a/runit-2.1.2/src/runit-init.c b/runit-2.1.2/src/runit-init.c new file mode 100644 index 0000000..00dc3c9 --- /dev/null +++ b/runit-2.1.2/src/runit-init.c @@ -0,0 +1,76 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include <unistd.h> +#include "runit.h" +#include "strerr.h" +#include "sig.h" +#include "open.h" +#include "error.h" + +#define USAGE " 0|6" +#define FATAL "init: fatal: " +/* #define WARNING "init: warning: " */ + +const char *progname; + +void usage(void) { strerr_die4x(0, "usage: ", progname, USAGE, "\n"); } + +void runit_halt () { + if (open_trunc(STOPIT) == -1) + strerr_die4sys(111, FATAL, "unable to create ", STOPIT, ": "); + if (chmod(STOPIT, 0100) == -1) + strerr_die4sys(111, FATAL, "unable to chmod ", STOPIT, ": "); + if (chmod(REBOOT, 0) == -1) + if (errno != error_noent) + strerr_die4sys(111, FATAL, "unable to chmod ", REBOOT, ": "); + kill(1, sig_cont); + _exit(0); +} + +void runit_reboot () { + if (open_trunc(STOPIT) == -1) + strerr_die4sys(111, FATAL, "unable to create ", STOPIT, ": "); + if (chmod(STOPIT, 0100) == -1) + strerr_die4sys(111, FATAL, "unable to chmod ", STOPIT, ": "); + if (open_trunc(REBOOT) == -1) + strerr_die4sys(111, FATAL, "unable to create ", REBOOT, ": "); + if (chmod(REBOOT, 0100) == -1) + strerr_die4sys(111, FATAL, "unable to chmod ", REBOOT, ": "); + kill(1, sig_cont); + _exit(0); +} + +int main (int argc, const char * const *argv, char * const *envp) { + const char *prog[2]; + + progname =*argv++; + + if (getpid() == 1) { + prog[1] =0; + prog[0] ="runit"; + + /* kernel is starting init, runit does the job. */ + execve(RUNIT, (char *const *)prog, envp); + + /* serious error */ + strerr_die4sys(111, FATAL, "unable to start ", prog[0], ": "); + } + + if (! *argv || ! **argv) usage(); + switch (**argv) { + case '0': + runit_halt(); + break; + case '6': + runit_reboot(); + break; + case '-': + if ((*argv)[1] == 'V') + strerr_warn1("$Id: f075d98bf7dd17c893021f9572cbb970cdad8dcf $\n", 0); + default: + usage(); + } + /* not reached */ + _exit(0); +} diff --git a/runit-2.1.2/src/runit-init.check b/runit-2.1.2/src/runit-init.check new file mode 100755 index 0000000..088e833 --- /dev/null +++ b/runit-2.1.2/src/runit-init.check @@ -0,0 +1,3 @@ +#!/bin/sh +runit-init +echo $? diff --git a/runit-2.1.2/src/runit-init.dist b/runit-2.1.2/src/runit-init.dist new file mode 100644 index 0000000..cca0307 --- /dev/null +++ b/runit-2.1.2/src/runit-init.dist @@ -0,0 +1,3 @@ +usage: runit-init 0|6 + +0 diff --git a/runit-2.1.2/src/runit.c b/runit-2.1.2/src/runit.c new file mode 100644 index 0000000..48620b3 --- /dev/null +++ b/runit-2.1.2/src/runit.c @@ -0,0 +1,346 @@ +#include <sys/types.h> +#include <sys/reboot.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include "runit.h" +#include "sig.h" +#include "strerr.h" +#include "error.h" +#include "iopause.h" +#include "coe.h" +#include "ndelay.h" +#include "wait.h" +#include "open.h" +#include "reboot_system.h" + +/* #define DEBUG */ + +#define INFO "- runit: " +#define WARNING "- runit: warning: " +#define FATAL "- runit: fatal: " + +const char * const stage[3] ={ + "/etc/runit/1", + "/etc/runit/2", + "/etc/runit/3" }; + +int selfpipe[2]; +int sigc =0; +int sigi =0; + +void sig_cont_handler (void) { + sigc++; + write(selfpipe[1], "", 1); +} +void sig_int_handler (void) { + sigi++; + write(selfpipe[1], "", 1); +} +void sig_child_handler (void) { write(selfpipe[1], "", 1); } + +int main (int argc, const char * const *argv, char * const *envp) { + const char * prog[2]; + int pid, pid2; + int wstat; + int st; + iopause_fd x; +#ifndef IOPAUSE_POLL + fd_set rfds; + struct timeval t; +#endif + char ch; + int ttyfd; + struct stat s; + + if (getpid() != 1) strerr_die2x(111, FATAL, "must be run as process no 1."); + setsid(); + + sig_block(sig_alarm); + sig_block(sig_child); + sig_catch(sig_child, sig_child_handler); + sig_block(sig_cont); + sig_catch(sig_cont, sig_cont_handler); + sig_block(sig_hangup); + sig_block(sig_int); + sig_catch(sig_int, sig_int_handler); + sig_block(sig_pipe); + sig_block(sig_term); + + /* console */ + if ((ttyfd =open_write("/dev/console")) != -1) { + dup2(ttyfd, 0); dup2(ttyfd, 1); dup2(ttyfd, 2); + if (ttyfd > 2) close(ttyfd); + } + + /* create selfpipe */ + while (pipe(selfpipe) == -1) { + strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys); + sleep(5); + } + coe(selfpipe[0]); + coe(selfpipe[1]); + ndelay_on(selfpipe[0]); + ndelay_on(selfpipe[1]); + +#ifdef RB_DISABLE_CAD + /* activate ctrlaltdel handling, glibc, dietlibc */ + if (RB_DISABLE_CAD == 0) reboot_system(0); +#endif + + strerr_warn3(INFO, "$Id: 25da3b86f7bed4038b8a039d2f8e8c9bbcf0822b $", + ": booting.", 0); + + /* runit */ + for (st =0; st < 3; st++) { + /* if (st == 2) logwtmp("~", "reboot", ""); */ + while ((pid =fork()) == -1) { + strerr_warn4(FATAL, "unable to fork for \"", stage[st], "\" pausing: ", + &strerr_sys); + sleep(5); + } + if (!pid) { + /* child */ + prog[0] =stage[st]; + prog[1] =0; + + /* stage 1 gets full control of console */ + if (st == 0) { + if ((ttyfd =open("/dev/console", O_RDWR)) != -1) { +#ifdef TIOCSCTTY + ioctl(ttyfd, TIOCSCTTY, (char *)0); +#endif + dup2(ttyfd, 0); + if (ttyfd > 2) close(ttyfd); + } + else + strerr_warn2(WARNING, "unable to open /dev/console: ", &strerr_sys); + } + else + setsid(); + + sig_unblock(sig_alarm); + sig_unblock(sig_child); + sig_uncatch(sig_child); + sig_unblock(sig_cont); + sig_ignore(sig_cont); + sig_unblock(sig_hangup); + sig_unblock(sig_int); + sig_uncatch(sig_int); + sig_unblock(sig_pipe); + sig_unblock(sig_term); + + strerr_warn3(INFO, "enter stage: ", stage[st], 0); + execve(*prog, (char *const *)prog, envp); + strerr_die4sys(0, FATAL, "unable to start child: ", stage[st], ": "); + } + + x.fd =selfpipe[0]; + x.events =IOPAUSE_READ; + for (;;) { + int child; + + sig_unblock(sig_child); + sig_unblock(sig_cont); + sig_unblock(sig_int); +#ifdef IOPAUSE_POLL + poll(&x, 1, 14000); +#else + t.tv_sec =14; t.tv_usec =0; + FD_ZERO(&rfds); + FD_SET(x.fd, &rfds); + select(x.fd +1, &rfds, (fd_set*)0, (fd_set*)0, &t); +#endif + sig_block(sig_cont); + sig_block(sig_child); + sig_block(sig_int); + + while (read(selfpipe[0], &ch, 1) == 1) {} + while ((child =wait_nohang(&wstat)) > 0) + if (child == pid) break; + if (child == -1) { + strerr_warn2(WARNING, "wait_nohang, pausing: ", &strerr_sys); + sleep(5); + } + + /* reget stderr */ + if ((ttyfd =open_write("/dev/console")) != -1) { + dup2(ttyfd, 2); + if (ttyfd > 2) close(ttyfd); + } + + if (child == pid) { + if (wait_exitcode(wstat) != 0) { + if (wait_crashed(wstat)) + strerr_warn3(WARNING, "child crashed: ", stage[st], 0); + else + strerr_warn3(WARNING, "child failed: ", stage[st], 0); + if (st == 0) + /* this is stage 1 */ + if (wait_crashed(wstat) || (wait_exitcode(wstat) == 100)) { + strerr_warn3(INFO, "leave stage: ", stage[st], 0); + strerr_warn2(WARNING, "skipping stage 2...", 0); + st++; + break; + } + if (st == 1) + /* this is stage 2 */ + if (wait_crashed(wstat) || (wait_exitcode(wstat) == 111)) { + strerr_warn2(WARNING, "killing all processes in stage 2...", 0); + kill(-pid, 9); + sleep(5); + strerr_warn2(WARNING, "restarting.", 0); + st--; + break; + } + } + strerr_warn3(INFO, "leave stage: ", stage[st], 0); + break; + } + if (child != 0) { + /* collect terminated children */ + write(selfpipe[1], "", 1); + continue; + } + + /* sig? */ + if (!sigc && !sigi) { +#ifdef DEBUG + strerr_warn2(WARNING, "poll: ", &strerr_sys); +#endif + continue; + } + if (st != 1) { + strerr_warn2(WARNING, "signals only work in stage 2.", 0); + sigc =sigi =0; + continue; + } + if (sigi && (stat(CTRLALTDEL, &s) != -1) && (s.st_mode & S_IXUSR)) { + strerr_warn2(INFO, "ctrl-alt-del request...", 0); + prog[0] =CTRLALTDEL; prog[1] =0; + while ((pid2 =fork()) == -1) { + strerr_warn4(FATAL, "unable to fork for \"", CTRLALTDEL, + "\" pausing: ", &strerr_sys); + sleep(5); + } + if (!pid2) { + /* child */ + strerr_warn3(INFO, "enter stage: ", prog[0], 0); + execve(*prog, (char *const *) prog, envp); + strerr_die4sys(0, FATAL, "unable to start child: ", prog[0], ": "); + } + if (wait_pid(&wstat, pid2) == -1) + strerr_warn2(FATAL, "wait_pid: ", &strerr_sys); + if (wait_crashed(wstat)) + strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0); + strerr_warn3(INFO, "leave stage: ", prog[0], 0); + sigi =0; + sigc++; + } + if (sigc && (stat(STOPIT, &s) != -1) && (s.st_mode & S_IXUSR)) { + int i; + /* unlink(STOPIT); */ + chmod(STOPIT, 0); + + /* kill stage 2 */ +#ifdef DEBUG + strerr_warn2(WARNING, "sending sigterm...", 0); +#endif + kill(pid, sig_term); + i =0; + while (i < 5) { + if ((child =wait_nohang(&wstat)) == pid) { +#ifdef DEBUG + strerr_warn2(WARNING, "stage 2 terminated.", 0); +#endif + pid =0; + break; + } + if (child) continue; + if (child == -1) + strerr_warn2(WARNING, "wait_nohang: ", &strerr_sys); +#ifdef DEBUG + strerr_warn2(WARNING, "waiting...", 0); +#endif + sleep(1); + i++; + } + if (pid) { + /* still there */ + strerr_warn2(WARNING, + "stage 2 not terminated, sending sigkill...", 0); + kill(pid, 9); + if (wait_pid(&wstat, pid) == -1) + strerr_warn2(WARNING, "wait_pid: ", &strerr_sys); + } + sigc =0; + strerr_warn3(INFO, "leave stage: ", stage[st], 0); + + /* enter stage 3 */ + break; + } + sigc =sigi =0; +#ifdef DEBUG + strerr_warn2(WARNING, "no request.", 0); +#endif + } + } + + /* reget stderr */ + if ((ttyfd =open_write("/dev/console")) != -1) { + dup2(ttyfd, 2); + if (ttyfd > 2) close(ttyfd); + } + +#ifdef RB_AUTOBOOT + /* fallthrough stage 3 */ + strerr_warn2(INFO, "sending KILL signal to all processes...", 0); + kill(-1, SIGKILL); + + pid =fork(); + switch (pid) { + case 0: + case -1: + if ((stat(REBOOT, &s) != -1) && (s.st_mode & S_IXUSR)) { + strerr_warn2(INFO, "system reboot.", 0); + sync(); + reboot_system(RB_AUTOBOOT); + } + else { +#ifdef RB_POWER_OFF + strerr_warn2(INFO, "power off...", 0); + sync(); + reboot_system(RB_POWER_OFF); + sleep(2); +#endif +#ifdef RB_HALT_SYSTEM + strerr_warn2(INFO, "system halt.", 0); + sync(); + reboot_system(RB_HALT_SYSTEM); +#else +#ifdef RB_HALT + strerr_warn2(INFO, "system halt.", 0); + sync(); + reboot_system(RB_HALT); +#else + strerr_warn2(INFO, "system reboot.", 0); + sync(); + reboot_system(RB_AUTOBOOT); +#endif +#endif + } + if (pid == 0) _exit(0); + break; + default: + sig_unblock(sig_child); + while (wait_pid(0, pid) == -1); + } +#endif + + for (;;) sig_pause(); + /* not reached */ + strerr_die2x(0, INFO, "exit."); + return(0); +} diff --git a/runit-2.1.2/src/runit.check b/runit-2.1.2/src/runit.check new file mode 100755 index 0000000..87f02d3 --- /dev/null +++ b/runit-2.1.2/src/runit.check @@ -0,0 +1,3 @@ +#!/bin/sh +runit +echo $? diff --git a/runit-2.1.2/src/runit.dist b/runit-2.1.2/src/runit.dist new file mode 100644 index 0000000..135c411 --- /dev/null +++ b/runit-2.1.2/src/runit.dist @@ -0,0 +1,2 @@ +- runit: fatal: must be run as process no 1. +111 diff --git a/runit-2.1.2/src/runit.h b/runit-2.1.2/src/runit.h new file mode 100644 index 0000000..ba98386 --- /dev/null +++ b/runit-2.1.2/src/runit.h @@ -0,0 +1,4 @@ +#define RUNIT "/sbin/runit" +#define STOPIT "/etc/runit/stopit" +#define REBOOT "/etc/runit/reboot" +#define CTRLALTDEL "/etc/runit/ctrlaltdel" diff --git a/runit-2.1.2/src/runsv.c b/runit-2.1.2/src/runsv.c new file mode 100644 index 0000000..0de2803 --- /dev/null +++ b/runit-2.1.2/src/runsv.c @@ -0,0 +1,607 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <signal.h> +#include "strerr.h" +#include "error.h" +#include "taia.h" +#include "sig.h" +#include "env.h" +#include "coe.h" +#include "ndelay.h" +#include "fifo.h" +#include "open.h" +#include "lock.h" +#include "iopause.h" +#include "wait.h" +#include "fd.h" +#include "buffer.h" +#include "fmt.h" +#include "byte.h" + +#define USAGE " dir" + +#define VERSION "$Id: ecf467746d7b97ff0fddb88b9d44cca201c74160 $" + +char *progname; +int selfpipe[2]; + +/* state */ +#define S_DOWN 0 +#define S_RUN 1 +#define S_FINISH 2 +/* ctrl */ +#define C_NOOP 0 +#define C_TERM 1 +#define C_PAUSE 2 +/* want */ +#define W_UP 0 +#define W_DOWN 1 +#define W_EXIT 2 + +struct svdir { + int pid; + int state; + int ctrl; + int want; + struct taia start; + int wstat; + int fdlock; + int fdcontrol; + int fdcontrolwrite; + int islog; +}; +struct svdir svd[2]; + +int sigterm =0; +int haslog =0; +int pidchanged =1; +int logpipe[2]; +char *dir; + +void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +void fatal(char *m) { + strerr_die5sys(111, "runsv ", dir, ": fatal: ", m, ": "); +} +void fatal2(char *m1, char *m2) { + strerr_die6sys(111, "runsv ", dir, ": fatal: ", m1, m2, ": "); +} +void fatalx(char *m1, char *m2) { + strerr_die5x(111, "runsv ", dir, ": fatal: ", m1, m2); +} +void warn(char *m) { + strerr_warn5("runsv ", dir, ": warning: ", m, ": ", &strerr_sys); +} +void warn2(char *m1, char *m2) { + strerr_warn6("runsv ", dir, ": warning: ", m1, m2, ": ", &strerr_sys); +} +void warnx(char *m1, char *m2, char *m3) { + strerr_warn6("runsv ", dir, ": warning: ", m1, m2, m3, 0); +} + +void stopservice(struct svdir *); + +void s_child() { write(selfpipe[1], "", 1); } +void s_term() { + sigterm =1; + write(selfpipe[1], "", 1); /* XXX */ +} + +void update_status(struct svdir *s) { + unsigned long l; + int fd; + char status[20]; + char bspace[64]; + buffer b; + char spid[FMT_ULONG]; + char *fstatus ="supervise/status"; + char *fstatusnew ="supervise/status.new"; + char *fstat ="supervise/stat"; + char *fstatnew ="supervise/stat.new"; + char *fpid ="supervise/pid"; + char *fpidnew ="supervise/pid.new"; + + if (s->islog) { + fstatus ="log/supervise/status"; + fstatusnew ="log/supervise/status.new"; + fstat ="log/supervise/stat"; + fstatnew ="log/supervise/stat.new"; + fpid ="log/supervise/pid"; + fpidnew ="log/supervise/pid.new"; + } + + /* pid */ + if (pidchanged) { + if ((fd =open_trunc(fpidnew)) == -1) { + warn2("unable to open ", fpidnew); + return; + } + buffer_init(&b, buffer_unixwrite, fd, bspace, sizeof bspace); + spid[fmt_ulong(spid, (unsigned long)s->pid)] =0; + if (s->pid) { + buffer_puts(&b, spid); + buffer_puts(&b, "\n"); + buffer_flush(&b); + } + close(fd); + if (rename(fpidnew, fpid) == -1) { + warn2("unable to rename pid.new to ", fpid); + return; + } + pidchanged =0; + } + + /* stat */ + if ((fd =open_trunc(fstatnew)) == -1) { + warn2("unable to open ", fstatnew); + return; + } + buffer_init(&b, buffer_unixwrite, fd, bspace, sizeof bspace); + switch (s->state) { + case S_DOWN: + buffer_puts(&b, "down"); + break; + case S_RUN: + buffer_puts(&b, "run"); + break; + case S_FINISH: + buffer_puts(&b, "finish"); + break; + } + if (s->ctrl & C_PAUSE) buffer_puts(&b, ", paused"); + if (s->ctrl & C_TERM) buffer_puts(&b, ", got TERM"); + if (s->state != S_DOWN) + switch(s->want) { + case W_DOWN: + buffer_puts(&b, ", want down"); + break; + case W_EXIT: + buffer_puts(&b, ", want exit"); + break; + } + buffer_puts(&b, "\n"); + buffer_flush(&b); + close(fd); + if (rename(fstatnew, fstat) == -1) + warn2("unable to rename stat.new to ", fstat); + + /* supervise compatibility */ + taia_pack(status, &s->start); + l =(unsigned long)s->pid; + status[12] =l; l >>=8; + status[13] =l; l >>=8; + status[14] =l; l >>=8; + status[15] =l; + if (s->ctrl & C_PAUSE) + status[16] =1; + else + status[16] =0; + if (s->want == W_UP) + status[17] ='u'; + else + status[17] ='d'; + if (s->ctrl & C_TERM) + status[18] =1; + else + status[18] =0; + status[19] =s->state; + if ((fd =open_trunc(fstatusnew)) == -1) { + warn2("unable to open ", fstatusnew); + return; + } + if ((l =write(fd, status, sizeof status)) == -1) { + warn2("unable to write ", fstatusnew); + close(fd); + unlink(fstatusnew); + return; + } + close(fd); + if (l < sizeof status) { + warnx("unable to write ", fstatusnew, ": partial write."); + return; + } + if (rename(fstatusnew, fstatus) == -1) + warn2("unable to rename status.new to ", fstatus); +} +unsigned int custom(struct svdir *s, char c) { + int pid; + int w; + char a[10]; + struct stat st; + char *prog[2]; + + if (s->islog) return(0); + byte_copy(a, 10, "control/?"); + a[8] =c; + if (stat(a, &st) == 0) { + if (st.st_mode & S_IXUSR) { + if ((pid =fork()) == -1) { + warn2("unable to fork for ", a); + return(0); + } + if (! pid) { + if (haslog && fd_copy(1, logpipe[1]) == -1) + warn2("unable to setup stdout for ", a); + prog[0] =a; + prog[1] =0; + execve(a, prog, environ); + fatal("unable to run control/?"); + } + while (wait_pid(&w, pid) == -1) { + if (errno == error_intr) continue; + warn2("unable to wait for child ", a); + return(0); + } + return(! wait_exitcode(w)); + } + } + else { + if (errno == error_noent) return(0); + warn2("unable to stat ", a); + } + return(0); +} +void stopservice(struct svdir *s) { + if (s->pid && ! custom(s, 't')) { + kill(s->pid, SIGTERM); + s->ctrl |=C_TERM; + update_status(s); + } + if (s->want == W_DOWN) { + kill(s->pid, SIGCONT); + custom(s, 'd'); return; + } + if (s->want == W_EXIT) { + kill(s->pid, SIGCONT); + custom(s, 'x'); + } +} + +void startservice(struct svdir *s) { + int p; + char *run[4]; + char code[FMT_ULONG]; + char stat[FMT_ULONG]; + + if (s->state == S_FINISH) { + run[0] ="./finish"; + code[fmt_ulong(code, wait_exitcode(s->wstat))] =0; + run[1] =wait_crashed(s->wstat) ? "-1" : code; + stat[fmt_ulong(stat, s->wstat & 0xff)] =0; + run[2] =stat; + run[3] =0; + } + else { + run[0] ="./run"; + custom(s, 'u'); + run[1] =0; + } + + if (s->pid != 0) stopservice(s); /* should never happen */ + while ((p =fork()) == -1) { + warn("unable to fork, sleeping"); + sleep(5); + } + if (p == 0) { + /* 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"); + } + else { + if (fd_copy(1, logpipe[1]) == -1) + fatal("unable to setup filedescriptor for ./run"); + close(logpipe[0]); + } + } + sig_uncatch(sig_child); + sig_unblock(sig_child); + sig_uncatch(sig_term); + sig_unblock(sig_term); + execve(*run, run, environ); + if (s->islog) + fatal2("unable to start log/", *run); + else + fatal2("unable to start ", *run); + } + if (s->state != S_FINISH) { + taia_now(&s->start); + s->state =S_RUN; + } + s->pid =p; + pidchanged =1; + s->ctrl =C_NOOP; + update_status(s); +} +int ctrl(struct svdir *s, char c) { + switch(c) { + case 'd': /* down */ + s->want =W_DOWN; + update_status(s); + if (s->state == S_RUN) stopservice(s); + break; + case 'u': /* up */ + s->want =W_UP; + update_status(s); + if (s->state == S_DOWN) startservice(s); + break; + case 'x': /* exit */ + if (s->islog) break; + s->want =W_EXIT; + update_status(s); + if (s->state == S_RUN) stopservice(s); + break; + case 't': /* sig term */ + if (s->state == S_RUN) stopservice(s); + break; + case 'k': /* sig kill */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGKILL); + s->state =S_DOWN; + break; + case 'p': /* sig pause */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGSTOP); + s->ctrl |=C_PAUSE; + update_status(s); + break; + case 'c': /* sig cont */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGCONT); + if (s->ctrl & C_PAUSE) s->ctrl &=~C_PAUSE; + update_status(s); + break; + case 'o': /* once */ + s->want =W_DOWN; + update_status(s); + if (s->state == S_DOWN) startservice(s); + break; + case 'a': /* sig alarm */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGALRM); + break; + case 'h': /* sig hup */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGHUP); + break; + case 'i': /* sig int */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGINT); + break; + case 'q': /* sig quit */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGQUIT); + break; + case '1': /* sig usr1 */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGUSR1); + break; + case '2': /* sig usr2 */ + if ((s->state == S_RUN) && ! custom(s, c)) kill(s->pid, SIGUSR2); + break; + } + return(1); +} + +int main(int argc, char **argv) { + struct stat s; + int fd; + int r; + char buf[256]; + + progname =argv[0]; + if (! argv[1] || argv[2]) usage(); + dir =argv[1]; + + if (pipe(selfpipe) == -1) fatal("unable to create selfpipe"); + coe(selfpipe[0]); + coe(selfpipe[1]); + ndelay_on(selfpipe[0]); + ndelay_on(selfpipe[1]); + + sig_block(sig_child); + sig_catch(sig_child, s_child); + sig_block(sig_term); + sig_catch(sig_term, s_term); + + if (chdir(dir) == -1) fatal("unable to change to directory"); + svd[0].pid =0; + svd[0].state =S_DOWN; + svd[0].ctrl =C_NOOP; + svd[0].want =W_UP; + svd[0].islog =0; + svd[1].pid =0; + taia_now(&svd[0].start); + if (stat("down", &s) != -1) svd[0].want =W_DOWN; + + if (stat("log", &s) == -1) { + if (errno != error_noent) + warn("unable to stat() ./log: "); + } + else { + if (! S_ISDIR(s.st_mode)) + warnx("./log", 0, ": not a directory."); + else { + haslog =1; + svd[1].state =S_DOWN; + svd[1].ctrl =C_NOOP; + svd[1].want =W_UP; + svd[1].islog =1; + taia_now(&svd[1].start); + if (stat("log/down", &s) != -1) + svd[1].want =W_DOWN; + if (pipe(logpipe) == -1) + fatal("unable to create log pipe"); + coe(logpipe[0]); + coe(logpipe[1]); + } + } + + if (mkdir("supervise", 0700) == -1) { + if ((r =readlink("supervise", buf, 256)) != -1) { + if (r == 256) + 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"); + } + } + if ((svd[0].fdlock =open_append("supervise/lock")) == -1) + fatal("unable to open supervise/lock"); + if (lock_exnb(svd[0].fdlock) == -1) fatal("unable to lock supervise/lock"); + coe(svd[0].fdlock); + 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); + } + else { + if ((errno != ENOENT) && (errno != EINVAL)) + fatal("unable to readlink ./log/supervise"); + } + } + if ((svd[1].fdlock =open_append("log/supervise/lock")) == -1) + fatal("unable to open log/supervise/lock"); + if (lock_ex(svd[1].fdlock) == -1) + fatal("unable to lock log/supervise/lock"); + coe(svd[1].fdlock); + } + + fifo_make("supervise/control", 0600); + if (stat("supervise/control", &s) == -1) + fatal("unable to stat supervise/control"); + if (!S_ISFIFO(s.st_mode)) + fatalx("supervise/control exists but is not a fifo", ""); + if ((svd[0].fdcontrol =open_read("supervise/control")) == -1) + fatal("unable to open supervise/control"); + coe(svd[0].fdcontrol); + if ((svd[0].fdcontrolwrite =open_write("supervise/control")) == -1) + fatal("unable to open supervise/control"); + coe(svd[0].fdcontrolwrite); + update_status(&svd[0]); + if (haslog) { + fifo_make("log/supervise/control", 0600); + if (stat("supervise/control", &s) == -1) + fatal("unable to stat log/supervise/control"); + if (!S_ISFIFO(s.st_mode)) + fatalx("log/supervise/control exists but is not a fifo", ""); + if ((svd[1].fdcontrol =open_read("log/supervise/control")) == -1) + fatal("unable to open log/supervise/control"); + coe(svd[1].fdcontrol); + if ((svd[1].fdcontrolwrite =open_write("log/supervise/control")) == -1) + fatal("unable to open log/supervise/control"); + coe(svd[1].fdcontrolwrite); + update_status(&svd[1]); + } + fifo_make("supervise/ok",0600); + if ((fd =open_read("supervise/ok")) == -1) + fatal("unable to read supervise/ok"); + coe(fd); + if (haslog) { + fifo_make("log/supervise/ok",0600); + if ((fd =open_read("log/supervise/ok")) == -1) + fatal("unable to read log/supervise/ok"); + coe(fd); + } + for (;;) { + iopause_fd x[3]; + struct taia deadline; + struct taia now; + char ch; + + if (haslog) + 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]); + + x[0].fd =selfpipe[0]; + x[0].events =IOPAUSE_READ; + x[1].fd =svd[0].fdcontrol; + x[1].events =IOPAUSE_READ; + if (haslog) { + x[2].fd =svd[1].fdcontrol; + x[2].events =IOPAUSE_READ; + } + taia_now(&now); + taia_uint(&deadline, 3600); + taia_add(&deadline, &now, &deadline); + + sig_unblock(sig_term); + sig_unblock(sig_child); + iopause(x, 2 +haslog, &deadline, &now); + sig_block(sig_term); + sig_block(sig_child); + + while (read(selfpipe[0], &ch, 1) == 1) + ; + for (;;) { + int child; + int wstat; + + child =wait_nohang(&wstat); + if (!child) break; + if ((child == -1) && (errno != error_intr)) break; + if (child == svd[0].pid) { + svd[0].pid =0; + pidchanged =1; + svd[0].wstat =wstat; + svd[0].ctrl &=~C_TERM; + if (svd[0].state != S_FINISH) + if ((fd =open_read("finish")) != -1) { + close(fd); + svd[0].state =S_FINISH; + update_status(&svd[0]); + continue; + } + svd[0].state =S_DOWN; + taia_uint(&deadline, 1); + taia_add(&deadline, &svd[0].start, &deadline); + taia_now(&svd[0].start); + update_status(&svd[0]); + if (taia_less(&svd[0].start, &deadline)) sleep(1); + } + if (haslog) { + if (child == svd[1].pid) { + svd[1].pid =0; + pidchanged =1; + svd[1].state =S_DOWN; + svd[1].ctrl &=~C_TERM; + taia_uint(&deadline, 1); + taia_add(&deadline, &svd[1].start, &deadline); + taia_now(&svd[1].start); + update_status(&svd[1]); + if (taia_less(&svd[1].start, &deadline)) sleep(1); + } + } + } + if (read(svd[0].fdcontrol, &ch, 1) == 1) ctrl(&svd[0], ch); + if (haslog) + if (read(svd[1].fdcontrol, &ch, 1) == 1) ctrl(&svd[1], ch); + + if (sigterm) { ctrl(&svd[0], 'x'); sigterm =0; } + + 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]"); + } + } + } + _exit(0); +} diff --git a/runit-2.1.2/src/runsv.check b/runit-2.1.2/src/runsv.check new file mode 100755 index 0000000..edfd0c9 --- /dev/null +++ b/runit-2.1.2/src/runsv.check @@ -0,0 +1,59 @@ +#!/bin/sh +rm -rf "${ctmp}" + +runsv +echo $? + +mkdir "${ctmp}" +echo '#!/bin/sh' >"${ctmp}"/run +echo 'echo starting' >>"${ctmp}"/run +echo 'exec sleep 14' >>"${ctmp}"/run +chmod 700 "${ctmp}"/run +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +cat "${ctmp}"/supervise/stat +mkdir -p "${ctmp}"/control +echo '#!/bin/sh' >"${ctmp}"/control/t +echo 'echo term' >>"${ctmp}"/control/t +echo 'exit 1' >>"${ctmp}"/control/t +chmod 700 "${ctmp}"/control/t +echo t >"${ctmp}"/supervise/control +sleep 2 +echo x >"${ctmp}"/supervise/control +wait +echo $? + +mkdir "${ctmp}"/log +echo '#!/bin/sh' >"${ctmp}"/log/run +echo 'exec cat >foo' >>"${ctmp}"/log/run +chmod 700 "${ctmp}"/log/run +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/log/supervise/stat || sleep 2 +mkdir -p "${ctmp}"/control +echo '#!/bin/sh' >"${ctmp}"/control/i +echo 'echo no interrupt' >>"${ctmp}"/control/i +echo 'exit 0' >>"${ctmp}"/control/i +chmod 700 "${ctmp}"/control/i +echo i >"${ctmp}"/supervise/control +sleep 1 +echo x >"${ctmp}"/supervise/control +wait +echo $? +cat "${ctmp}"/log/foo + +rm -rf "${ctmp}"/supervise +rm -rf "${ctmp}"/log/supervise +rm -f "${ctmp}"/log/foo +ln -s foo "${ctmp}"/supervise +ln -s bar "${ctmp}"/log/supervise +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +test -r "${ctmp}"/log/supervise/stat || sleep 2 +echo x >"${ctmp}"/foo/control +wait +echo $? +cat "${ctmp}"/log/foo +rm -rf "${ctmp}" diff --git a/runit-2.1.2/src/runsv.dist b/runit-2.1.2/src/runsv.dist new file mode 100644 index 0000000..d2b05b7 --- /dev/null +++ b/runit-2.1.2/src/runsv.dist @@ -0,0 +1,16 @@ +usage: runsv dir + +1 +starting +run +term +starting +term +0 +0 +starting +no interrupt +term +0 +starting +term diff --git a/runit-2.1.2/src/runsvchdir.c b/runit-2.1.2/src/runsvchdir.c new file mode 100644 index 0000000..fe7e987 --- /dev/null +++ b/runit-2.1.2/src/runsvchdir.c @@ -0,0 +1,76 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include "strerr.h" +#include "error.h" +#include "buffer.h" + +#define USAGE " dir" +#define SVDIR "/etc/runit/runsvdir" + +#define VERSION "$Id: 9bf17f77e33c6b961e060aacffa3c8abd38fc64a $" + +char *progname; +char *new; + +void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +void fatal(char *m1, char *m2) { + strerr_die5sys(111, progname, ": fatal: ", m1, m2, ": "); +} +void fatalx(char *m1, char *m2) { + strerr_die4x(111, progname, ": fatal: ", m1, m2); +} +void warn(char *m1, char *m2) { + strerr_warn5(progname, ": fatal: ", m1, m2, ": ", &strerr_sys); +} + +int main (int argc, char **argv) { + struct stat s; + int dev; + int ino; + + progname =*argv++; + if (! argv || ! *argv) usage(); + + new =*argv; + if (new[0] == '.') fatalx(new, ": must not start with a dot."); + if (chdir(SVDIR) == -1) fatal("unable to chdir: ", SVDIR); + + if (stat(new, &s) == -1) { + if (errno == error_noent) fatal(new, 0); + fatal("unable to stat: ", new); + } + if (! S_ISDIR(s.st_mode)) fatalx(new, "not a directory."); + ino =s.st_ino; + dev =s.st_dev; + if (stat("current", &s) == -1) fatal("unable to stat: ", "current"); + if ((s.st_ino == ino) && (s.st_dev == dev)) { + buffer_puts(buffer_1, "runsvchdir: "); + buffer_puts(buffer_1, new); + buffer_puts(buffer_1, ": current.\n"); + buffer_flush(buffer_1); + _exit(0); + } + + if (unlink("current.new") == -1) + if (errno != error_noent) fatal("unable to unlink: ", "current.new"); + if (symlink(new, "current.new") == -1) + fatal("unable to create: current.new -> ", new); + if (unlink("previous") == -1) + if (errno != error_noent) fatal("unable to unlink: ", "previous"); + if (rename("current", "previous") == -1) + fatal("unable to copy: current to ", "previous"); + if (rename("current.new", "current") == -1) { + warn("unable to move: current.new to ", "current"); + if (rename("previous", "current") == -1) + fatal("unable to move previous back to ", "current"); + _exit(111); + } + buffer_puts(buffer_1, "runsvchdir: "); + buffer_puts(buffer_1, new); + buffer_puts(buffer_1, ": now current.\n"); + buffer_flush(buffer_1); + _exit(0); +} diff --git a/runit-2.1.2/src/runsvchdir.check b/runit-2.1.2/src/runsvchdir.check new file mode 100755 index 0000000..a8de02b --- /dev/null +++ b/runit-2.1.2/src/runsvchdir.check @@ -0,0 +1,3 @@ +#!/bin/sh +runsvchdir +echo $? diff --git a/runit-2.1.2/src/runsvchdir.dist b/runit-2.1.2/src/runsvchdir.dist new file mode 100644 index 0000000..7664608 --- /dev/null +++ b/runit-2.1.2/src/runsvchdir.dist @@ -0,0 +1,3 @@ +usage: runsvchdir dir + +1 diff --git a/runit-2.1.2/src/runsvctrl.c b/runit-2.1.2/src/runsvctrl.c new file mode 100644 index 0000000..d8eb2c4 --- /dev/null +++ b/runit-2.1.2/src/runsvctrl.c @@ -0,0 +1,82 @@ +#include <unistd.h> +#include "strerr.h" +#include "error.h" +#include "open.h" + +#define USAGE " u|d|o|p|c|h|a|i|q|1|2|t|k|x|e service ..." + +#define VERSION "$Id: ccf8fc8ee3c340d8de97b5ddd9270b55e0f437cb $" + +#define FATAL "runsvctrl: fatal: " +#define WARNING "runsvctrl: warning: " + +char *progname; +unsigned int rc =0; + +void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +void fatal(char *m1) { strerr_die3sys(111, FATAL, m1, ": "); } +void warn(char *m1, char *m2) { + rc++; + strerr_warn5(WARNING, m1, ": ", m2, ": ", &strerr_sys); +} +void warnx(char *m1, char *m2) { + rc++; + strerr_warn4(WARNING, m1, ": ", m2, 0); +} + +int ctrl(char *name, char c) { + int fd; + + if ((fd =open_write("supervise/control")) == -1) { + if (errno == error_nodevice) + warnx(name, "runsv not running."); + else + warn(name, "unable to open supervise/control"); + return(-1); + } + if (write(fd, &c, 1) != 1) { + warn(name, "unable to write to supervise/control"); + return(-1); + } + return(1); +} + +int main(int argc, char **argv) { + char **dir; + int curdir; + char c; + + progname =*argv++; + + if (! argv || ! *argv) usage(); + + switch ((c =**argv)) { + case 'e': c ='x'; + case 'u': case 'd': case 'o': case 'x': case 'p': case 'c': case 'h': + case 'a': case 'i': case 't': case 'k': case 'q': case '1': case '2': + break; + default: + usage(); + } + dir =++argv; + if (! dir || ! *dir) usage(); + + if ((curdir =open_read(".")) == -1) { + rc =100; + fatal("unable to open current directory"); + } + for (; dir && *dir; dir++) { + if (chdir(*dir) == -1) { + warn(*dir, "unable to change directory"); + continue; + } + ctrl(*dir, c); + if (fchdir(curdir) == -1) { + rc =100; + fatal("unable to change directory"); + } + } + if (rc > 100) rc =100; + _exit(rc); +} diff --git a/runit-2.1.2/src/runsvctrl.check b/runit-2.1.2/src/runsvctrl.check new file mode 100755 index 0000000..7911074 --- /dev/null +++ b/runit-2.1.2/src/runsvctrl.check @@ -0,0 +1,23 @@ +#!/bin/sh +rm -rf "${ctmp}" + +runsvctrl +echo $? + +mkdir "${ctmp}" +echo '#!/bin/sh' >"${ctmp}"/run +echo 'echo starting' >>"${ctmp}"/run +echo 'exec sleep 14' >>"${ctmp}"/run +chmod 700 "${ctmp}"/run +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +runsvctrl down "${ctmp}" +echo $? +sleep 1 +cat "${ctmp}"/supervise/stat +runsvctrl exit "${ctmp}" +echo $? +wait +echo $? +rm -rf "${ctmp}" diff --git a/runit-2.1.2/src/runsvctrl.dist b/runit-2.1.2/src/runsvctrl.dist new file mode 100644 index 0000000..b07cf8a --- /dev/null +++ b/runit-2.1.2/src/runsvctrl.dist @@ -0,0 +1,8 @@ +usage: runsvctrl u|d|o|p|c|h|a|i|q|1|2|t|k|x|e service ... + +1 +starting +0 +down +0 +0 diff --git a/runit-2.1.2/src/runsvdir.c b/runit-2.1.2/src/runsvdir.c new file mode 100644 index 0000000..07c1d8e --- /dev/null +++ b/runit-2.1.2/src/runsvdir.c @@ -0,0 +1,286 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <signal.h> +#include "direntry.h" +#include "strerr.h" +#include "error.h" +#include "wait.h" +#include "env.h" +#include "open.h" +#include "pathexec.h" +#include "fd.h" +#include "str.h" +#include "coe.h" +#include "iopause.h" +#include "sig.h" +#include "ndelay.h" + +#define USAGE " [-P] dir" +#define VERSION "$Id: ecebd0a50510e91639c6a45dda8b0947aa8eb885 $" + +#define MAXSERVICES 1000 + +char *progname; +char *svdir; +unsigned long dev =0; +unsigned long ino =0; +struct { + unsigned long dev; + unsigned long ino; + int pid; + int isgone; +} sv[MAXSERVICES]; +int svnum =0; +int check =1; +char *rplog =0; +int rploglen; +int logpipe[2]; +iopause_fd io[1]; +struct taia stamplog; +int exitsoon =0; +int pgrp =0; + +void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } +void fatal(char *m1, char *m2) { + strerr_die6sys(100, "runsvdir ", svdir, ": fatal: ", m1, m2, ": "); +} +void warn(char *m1, char *m2) { + strerr_warn6("runsvdir ", svdir, ": warning: ", m1, m2, ": ", &strerr_sys); +} +void warn3x(char *m1, char *m2, char *m3) { + strerr_warn6("runsvdir ", svdir, ": warning: ", m1, m2, m3, 0); +} +void s_term() { exitsoon =1; } +void s_hangup() { exitsoon =2; } + +void runsv(int no, char *name) { + int pid; + + if ((pid =fork()) == -1) { + warn("unable to fork for ", name); + return; + } + if (pid == 0) { + /* child */ + const char *prog[3]; + + prog[0] ="runsv"; + prog[1] =name; + prog[2] =0; + sig_uncatch(sig_hangup); + sig_uncatch(sig_term); + if (pgrp) setsid(); + pathexec_run(*prog, prog, (const char* const*)environ); + fatal("unable to start runsv ", name); + } + sv[no].pid =pid; +} + +void runsvdir() { + DIR *dir; + direntry *d; + int i; + struct stat s; + + if (! (dir =opendir("."))) { + warn("unable to open directory ", svdir); + return; + } + for (i =0; i < svnum; i++) sv[i].isgone =1; + errno =0; + while ((d =readdir(dir))) { + if (d->d_name[0] == '.') continue; + if (stat(d->d_name, &s) == -1) { + warn("unable to stat ", d->d_name); + errno =0; + continue; + } + if (! S_ISDIR(s.st_mode)) continue; + for (i =0; i < svnum; i++) { + if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { + sv[i].isgone =0; + if (! sv[i].pid) runsv(i, d->d_name); + break; + } + } + if (i == svnum) { + /* new service */ + if (svnum >= MAXSERVICES) { + warn3x("unable to start runsv ", d->d_name, ": too many services."); + continue; + } + sv[i].ino =s.st_ino; + sv[i].dev =s.st_dev; + sv[i].pid =0; + sv[i].isgone =0; + svnum++; + runsv(i, d->d_name); + check =1; + } + } + if (errno) { + warn("unable to read directory ", svdir); + closedir(dir); + check =1; + return; + } + closedir(dir); + + /* SIGTERM removed runsv's */ + for (i =0; i < svnum; i++) { + if (! sv[i].isgone) continue; + if (sv[i].pid) kill(sv[i].pid, SIGTERM); + sv[i] =sv[--svnum]; + check =1; + } +} + +int setup_log() { + if ((rploglen =str_len(rplog)) < 7) { + warn3x("log must have at least seven characters.", 0, 0); + return(0); + } + if (pipe(logpipe) == -1) { + warn3x("unable to create pipe for log.", 0, 0); + return(-1); + } + coe(logpipe[1]); + coe(logpipe[0]); + ndelay_on(logpipe[0]); + ndelay_on(logpipe[1]); + if (fd_copy(2, logpipe[1]) == -1) { + warn3x("unable to set filedescriptor for log.", 0, 0); + return(-1); + } + io[0].fd =logpipe[0]; + io[0].events =IOPAUSE_READ; + taia_now(&stamplog); + return(1); +} + +int main(int argc, char **argv) { + struct stat s; + time_t mtime =0; + int wstat; + int curdir; + int pid; + struct taia deadline; + struct taia now; + struct taia stampcheck; + char ch; + int i; + + progname =*argv++; + if (! argv || ! *argv) usage(); + if (**argv == '-') { + switch (*(*argv +1)) { + case 'P': pgrp =1; + case '-': ++argv; + } + if (! argv || ! *argv) usage(); + } + + sig_catch(sig_term, s_term); + sig_catch(sig_hangup, s_hangup); + svdir =*argv++; + if (argv && *argv) { + rplog =*argv; + if (setup_log() != 1) { + rplog =0; + warn3x("log service disabled.", 0, 0); + } + } + if ((curdir =open_read(".")) == -1) + fatal("unable to open current directory", 0); + coe(curdir); + + taia_now(&stampcheck); + + for (;;) { + /* collect children */ + for (;;) { + if ((pid =wait_nohang(&wstat)) <= 0) break; + for (i =0; i < svnum; i++) { + if (pid == sv[i].pid) { + /* runsv has gone */ + sv[i].pid =0; + check =1; + break; + } + } + } + + taia_now(&now); + if (now.sec.x < (stampcheck.sec.x -3)) { + /* time warp */ + warn3x("time warp: resetting time stamp.", 0, 0); + taia_now(&stampcheck); + taia_now(&now); + if (rplog) taia_now(&stamplog); + } + if (taia_less(&now, &stampcheck) == 0) { + /* wait at least a second */ + taia_uint(&deadline, 1); + taia_add(&stampcheck, &now, &deadline); + + if (stat(svdir, &s) != -1) { + if (check || \ + s.st_mtime != mtime || s.st_ino != ino || s.st_dev != dev) { + /* svdir modified */ + if (chdir(svdir) != -1) { + mtime =s.st_mtime; + dev =s.st_dev; + ino =s.st_ino; + check =0; + if (now.sec.x <= (4611686018427387914ULL +(uint64)mtime)) + sleep(1); + runsvdir(); + while (fchdir(curdir) == -1) { + warn("unable to change directory, pausing", 0); + sleep(5); + } + } + else + warn("unable to change directory to ", svdir); + } + } + else + warn("unable to stat ", svdir); + } + + if (rplog) + if (taia_less(&now, &stamplog) == 0) { + write(logpipe[1], ".", 1); + taia_uint(&deadline, 900); + taia_add(&stamplog, &now, &deadline); + } + taia_uint(&deadline, check ? 1 : 5); + taia_add(&deadline, &now, &deadline); + + sig_block(sig_child); + if (rplog) + iopause(io, 1, &deadline, &now); + else + iopause(0, 0, &deadline, &now); + sig_unblock(sig_child); + + if (rplog && (io[0].revents | IOPAUSE_READ)) + while (read(logpipe[0], &ch, 1) > 0) + if (ch) { + for (i =6; i < rploglen; i++) + rplog[i -1] =rplog[i]; + rplog[rploglen -1] =ch; + } + + switch(exitsoon) { + case 1: + _exit(0); + case 2: + for (i =0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); + _exit(111); + } + } + /* not reached */ + _exit(0); +} diff --git a/runit-2.1.2/src/runsvdir.check b/runit-2.1.2/src/runsvdir.check new file mode 100755 index 0000000..a7927eb --- /dev/null +++ b/runit-2.1.2/src/runsvdir.check @@ -0,0 +1,3 @@ +#!/bin/sh +runsvdir +echo $? diff --git a/runit-2.1.2/src/runsvdir.dist b/runit-2.1.2/src/runsvdir.dist new file mode 100644 index 0000000..c553363 --- /dev/null +++ b/runit-2.1.2/src/runsvdir.dist @@ -0,0 +1,3 @@ +usage: runsvdir [-P] dir + +1 diff --git a/runit-2.1.2/src/runsvstat.c b/runit-2.1.2/src/runsvstat.c new file mode 100644 index 0000000..c0c0233 --- /dev/null +++ b/runit-2.1.2/src/runsvstat.c @@ -0,0 +1,167 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "strerr.h" +#include "error.h" +#include "sgetopt.h" +#include "open.h" +#include "buffer.h" +#include "tai.h" +#include "fmt.h" + +#define USAGE " [ -l ] service ..." + +#define VERSION "$Id: c17bbd3eda6f3c57027dfb47ff676bdd3fefff9f $" + +#define FATAL "runsvstat: fatal: " +#define WARNING "runsvstat: warning: " + +const char *progname; +unsigned int rc =0; +struct stat s; +int showlog =0; + +void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +void fatal(char *m1) { strerr_die3sys(111, FATAL, m1, ": "); } +void warn(char *m1, char *m2) { + rc++; + strerr_warn5(WARNING, m1, ": ", m2, ": ", &strerr_sys); +} +void warnx(char *m1, char *m2) { + rc++; + strerr_warn4(WARNING, m1, ": ", m2, 0); +} + +int show_status(char *name) { + char status[20]; + int pid; + int fd; + int normallyup =0; + char sulong[FMT_ULONG]; + struct tai when; + struct tai now; + + if (stat("down", &s) == -1) { + if (errno != error_noent) { + warn(name, "unable to stat down"); + return(-1); + } + normallyup = 1; + } + if ((fd =open_write("supervise/ok")) == -1) { + if (errno == error_nodevice) + warnx(name, "runsv not running."); + else + warn(name, "unable to open supervise/ok"); + return(-1); + } + close(fd); + if ((fd =open_read("supervise/status")) == -1) { + warn(name, "unable to open supervise/status"); + return(-1); + } + switch(read(fd, status, 20)) { + case 20: break; + case -1: + warn(name, "unable to read supervise/status"); + return(-1); + default: + warnx(name, "unable to read supervise/status: bad format."); + return(-1); + } + pid =(unsigned char) status[15]; + pid <<=8; pid +=(unsigned char)status[14]; + pid <<=8; pid +=(unsigned char)status[13]; + pid <<=8; pid +=(unsigned char)status[12]; + + tai_unpack(status,&when); + tai_now(&now); + if (tai_less(&now,&when)) when =now; + tai_sub(&when,&now,&when); + + buffer_puts(buffer_1, name); + buffer_puts(buffer_1, ": "); + if (pid) { + switch (status[19]) { + case 1: buffer_puts(buffer_1, "run "); break; + case 2: buffer_puts(buffer_1, "finish "); break; + } + buffer_puts(buffer_1, "(pid "); + buffer_put(buffer_1, sulong, fmt_ulong(sulong, pid)); + buffer_puts(buffer_1, ") "); + } + else + buffer_puts(buffer_1, "down "); + buffer_put(buffer_1, sulong, fmt_ulong(sulong, tai_approx(&when))); + buffer_puts(buffer_1, " seconds"); + if (pid && !normallyup) buffer_puts(buffer_1,", normally down"); + if (!pid && normallyup) buffer_puts(buffer_1,", normally up"); + if (pid && status[16]) buffer_puts(buffer_1,", paused"); + if (!pid && (status[17] == 'u')) buffer_puts(buffer_1,", want up"); + if (pid && (status[17] == 'd')) buffer_puts(buffer_1,", want down"); + if (pid && status[18]) buffer_puts(buffer_1, ", got TERM"); + /* buffer_putsflush(buffer_1, "\n"); */ + return(1); +} + +int main(int argc, char **argv) { + int opt; + int curdir; + char **dir; + + progname =*argv; + + while ((opt =getopt(argc, (const char * const *)argv, "lV")) != opteof) { + switch(opt) { + case 'l': + showlog =1; + break; + case 'V': + strerr_warn1(VERSION, 0); + case '?': + usage(); + } + } + argv +=optind; + + dir =argv; + if (! dir || ! *dir) usage(); + + if ((curdir =open_read(".")) == -1) { + rc =100; + fatal("unable to open current directory"); + } + for (; dir && *dir; dir++) { + if (chdir(*dir) == -1) { + warn(*dir, "unable to change directory"); + continue; + } + if (show_status(*dir) == 1) { + if (showlog) { + if (stat("log", &s) == -1) { + if (errno != error_noent) + warn("unable to stat()", "./log"); + } + else { + if (! S_ISDIR(s.st_mode)) + warnx("./log", "not a directory."); + else { + if (chdir("log") == -1) { + warn(*dir, "unable to change directory"); + continue; + } + show_status("\n log"); + } + } + } + buffer_puts(buffer_1, "\n"); buffer_flush(buffer_1); + } + if (fchdir(curdir) == -1) { + rc =100; + fatal("unable to change directory"); + } + } + if (rc > 100) rc =100; + _exit(rc); +} diff --git a/runit-2.1.2/src/runsvstat.check b/runit-2.1.2/src/runsvstat.check new file mode 100755 index 0000000..6ccde11 --- /dev/null +++ b/runit-2.1.2/src/runsvstat.check @@ -0,0 +1,26 @@ +#!/bin/sh +rm -rf "${ctmp}" + +runsvstat +echo $? +runsvstat -V +echo $? + +mkdir "${ctmp}" +echo '#!/bin/sh' >"${ctmp}"/run +echo 'echo starting' >>"${ctmp}"/run +echo 'exec sleep 14' >>"${ctmp}"/run +chmod 700 "${ctmp}"/run +chpst -2 runsvstat "${ctmp}" +echo $? +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +chpst -1 runsvstat "${ctmp}" +echo $? +runsvctrl exit "${ctmp}" +wait +echo $? +chpst -2 runsvstat "${ctmp}" +echo $? +rm -rf "${ctmp}" diff --git a/runit-2.1.2/src/runsvstat.dist b/runit-2.1.2/src/runsvstat.dist new file mode 100644 index 0000000..24b9ed4 --- /dev/null +++ b/runit-2.1.2/src/runsvstat.dist @@ -0,0 +1,12 @@ +usage: runsvstat [ -l ] service ... + +1 +$Id$ +usage: runsvstat [ -l ] service ... + +1 +1 +starting +0 +0 +1 diff --git a/runit-2.1.2/src/scan.h b/runit-2.1.2/src/scan.h new file mode 100644 index 0000000..3db49d3 --- /dev/null +++ b/runit-2.1.2/src/scan.h @@ -0,0 +1,30 @@ +/* Public domain. */ + +#ifndef SCAN_H +#define SCAN_H + +extern unsigned int scan_uint(const char *,unsigned int *); +extern unsigned int scan_xint(const char *,unsigned int *); +extern unsigned int scan_nbbint(const char *,unsigned int,unsigned int,unsigned int,unsigned int *); +extern unsigned int scan_ushort(const char *,unsigned short *); +extern unsigned int scan_xshort(const char *,unsigned short *); +extern unsigned int scan_nbbshort(const char *,unsigned int,unsigned int,unsigned int,unsigned short *); +extern unsigned int scan_ulong(const char *,unsigned long *); +extern unsigned int scan_xlong(const char *,unsigned long *); +extern unsigned int scan_nbblong(const char *,unsigned int,unsigned int,unsigned int,unsigned long *); + +extern unsigned int scan_plusminus(const char *,int *); +extern unsigned int scan_0x(const char *,unsigned int *); + +extern unsigned int scan_whitenskip(const char *,unsigned int); +extern unsigned int scan_nonwhitenskip(const char *,unsigned int); +extern unsigned int scan_charsetnskip(const char *,const char *,unsigned int); +extern unsigned int scan_noncharsetnskip(const char *,const char *,unsigned int); + +extern unsigned int scan_strncmp(const char *,const char *,unsigned int); +extern unsigned int scan_memcmp(const char *,const char *,unsigned int); + +extern unsigned int scan_long(const char *,long *); +extern unsigned int scan_8long(const char *,unsigned long *); + +#endif diff --git a/runit-2.1.2/src/scan_ulong.c b/runit-2.1.2/src/scan_ulong.c new file mode 100644 index 0000000..af19701 --- /dev/null +++ b/runit-2.1.2/src/scan_ulong.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include "scan.h" + +unsigned int scan_ulong(register const char *s,register unsigned long *u) +{ + register unsigned int pos = 0; + register unsigned long result = 0; + register unsigned long c; + while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { + result = result * 10 + c; + ++pos; + } + *u = result; + return pos; +} diff --git a/runit-2.1.2/src/seek.h b/runit-2.1.2/src/seek.h new file mode 100644 index 0000000..8011701 --- /dev/null +++ b/runit-2.1.2/src/seek.h @@ -0,0 +1,17 @@ +/* Public domain. */ + +#ifndef SEEK_H +#define SEEK_H + +typedef unsigned long seek_pos; + +extern seek_pos seek_cur(int); + +extern int seek_set(int,seek_pos); +extern int seek_end(int); + +extern int seek_trunc(int,seek_pos); + +#define seek_begin(fd) (seek_set((fd),(seek_pos) 0)) + +#endif diff --git a/runit-2.1.2/src/seek_set.c b/runit-2.1.2/src/seek_set.c new file mode 100644 index 0000000..19b8265 --- /dev/null +++ b/runit-2.1.2/src/seek_set.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <sys/types.h> +#include "seek.h" + +#define SET 0 /* sigh */ + +int seek_set(int fd,seek_pos pos) +{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; } diff --git a/runit-2.1.2/src/select.h1 b/runit-2.1.2/src/select.h1 new file mode 100644 index 0000000..68e971f --- /dev/null +++ b/runit-2.1.2/src/select.h1 @@ -0,0 +1,12 @@ +/* Public domain. */ + +#ifndef SELECT_H +#define SELECT_H + +/* sysdep: -sysselect */ + +#include <sys/types.h> +#include <sys/time.h> +extern int select(); + +#endif diff --git a/runit-2.1.2/src/select.h2 b/runit-2.1.2/src/select.h2 new file mode 100644 index 0000000..4bd4fcf --- /dev/null +++ b/runit-2.1.2/src/select.h2 @@ -0,0 +1,13 @@ +/* Public domain. */ + +#ifndef SELECT_H +#define SELECT_H + +/* sysdep: +sysselect */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/select.h> +extern int select(); + +#endif diff --git a/runit-2.1.2/src/sgetopt.c b/runit-2.1.2/src/sgetopt.c new file mode 100644 index 0000000..8bb608f --- /dev/null +++ b/runit-2.1.2/src/sgetopt.c @@ -0,0 +1,53 @@ +/* Public domain. */ + +/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer +D. J. Bernstein, djb@pobox.com. +Depends on subgetopt.h, buffer.h. +No system requirements. +19991219: Switched to buffer.h. +19970208: Cleanups. +931201: Baseline. +No known patent problems. + +Documentation in sgetopt.3. +*/ + +#include "buffer.h" +#define SGETOPTNOSHORT +#include "sgetopt.h" +#define SUBGETOPTNOSHORT +#include "subgetopt.h" + +#define getopt sgetoptmine +#define optind subgetoptind +#define opterr sgetopterr +#define optproblem subgetoptproblem +#define optprogname sgetoptprogname + +int opterr = 1; +const char *optprogname = 0; + +int getopt(int argc,const char *const *argv,const char *opts) +{ + int c; + const char *s; + + if (!optprogname) { + optprogname = *argv; + if (!optprogname) optprogname = ""; + for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; + } + c = subgetopt(argc,argv,opts); + if (opterr) + if (c == '?') { + char chp[2]; chp[0] = optproblem; chp[1] = '\n'; + buffer_puts(buffer_2,optprogname); + if (argv[optind] && (optind < argc)) + buffer_puts(buffer_2,": illegal option -- "); + else + buffer_puts(buffer_2,": option requires an argument -- "); + buffer_put(buffer_2,chp,2); + buffer_flush(buffer_2); + } + return c; +} diff --git a/runit-2.1.2/src/sgetopt.h b/runit-2.1.2/src/sgetopt.h new file mode 100644 index 0000000..bf8bce6 --- /dev/null +++ b/runit-2.1.2/src/sgetopt.h @@ -0,0 +1,23 @@ +/* Public domain. */ + +#ifndef SGETOPT_H +#define SGETOPT_H + +#ifndef SGETOPTNOSHORT +#define getopt sgetoptmine +#define optarg subgetoptarg +#define optind subgetoptind +#define optpos subgetoptpos +#define opterr sgetopterr +#define optproblem subgetoptproblem +#define optprogname sgetoptprogname +#define opteof subgetoptdone +#endif + +#include "subgetopt.h" + +extern int sgetoptmine(int,const char *const *,const char *); +extern int sgetopterr; +extern const char *sgetoptprogname; + +#endif diff --git a/runit-2.1.2/src/sig.c b/runit-2.1.2/src/sig.c new file mode 100644 index 0000000..423d18e --- /dev/null +++ b/runit-2.1.2/src/sig.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include <signal.h> +#include "sig.h" + +int sig_alarm = SIGALRM; +int sig_child = SIGCHLD; +int sig_cont = SIGCONT; +int sig_hangup = SIGHUP; +int sig_int = SIGINT; +int sig_pipe = SIGPIPE; +int sig_term = SIGTERM; + +void (*sig_defaulthandler)() = SIG_DFL; +void (*sig_ignorehandler)() = SIG_IGN; diff --git a/runit-2.1.2/src/sig.h b/runit-2.1.2/src/sig.h new file mode 100644 index 0000000..2a3c780 --- /dev/null +++ b/runit-2.1.2/src/sig.h @@ -0,0 +1,28 @@ +/* Public domain. */ + +#ifndef SIG_H +#define SIG_H + +extern int sig_alarm; +extern int sig_child; +extern int sig_cont; +extern int sig_hangup; +extern int sig_int; +extern int sig_pipe; +extern int sig_term; + +extern void (*sig_defaulthandler)(); +extern void (*sig_ignorehandler)(); + +extern void sig_catch(int,void (*)()); +#define sig_ignore(s) (sig_catch((s),sig_ignorehandler)) +#define sig_uncatch(s) (sig_catch((s),sig_defaulthandler)) + +extern void sig_block(int); +extern void sig_unblock(int); +extern void sig_blocknone(void); +extern void sig_pause(void); + +extern void sig_dfl(int); + +#endif diff --git a/runit-2.1.2/src/sig_block.c b/runit-2.1.2/src/sig_block.c new file mode 100644 index 0000000..a46c860 --- /dev/null +++ b/runit-2.1.2/src/sig_block.c @@ -0,0 +1,40 @@ +/* Public domain. */ + +#include <signal.h> +#include "sig.h" +#include "hassgprm.h" + +void sig_block(int sig) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); +#else + sigblock(1 << (sig - 1)); +#endif +} + +void sig_unblock(int sig) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigaddset(&ss,sig); + sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); +#else + sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); +#endif +} + +void sig_blocknone(void) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +#else + sigsetmask(0); +#endif +} diff --git a/runit-2.1.2/src/sig_catch.c b/runit-2.1.2/src/sig_catch.c new file mode 100644 index 0000000..7b5bd89 --- /dev/null +++ b/runit-2.1.2/src/sig_catch.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include <signal.h> +#include "sig.h" +#include "hassgact.h" + +void sig_catch(int sig,void (*f)()) +{ +#ifdef HASSIGACTION + struct sigaction sa; + sa.sa_handler = f; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(sig,&sa,(struct sigaction *) 0); +#else + signal(sig,f); /* won't work under System V, even nowadays---dorks */ +#endif +} diff --git a/runit-2.1.2/src/sig_pause.c b/runit-2.1.2/src/sig_pause.c new file mode 100644 index 0000000..3d1a793 --- /dev/null +++ b/runit-2.1.2/src/sig_pause.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include <signal.h> +#include "sig.h" +#include "hassgprm.h" + +void sig_pause(void) +{ +#ifdef HASSIGPROCMASK + sigset_t ss; + sigemptyset(&ss); + sigsuspend(&ss); +#else + sigpause(0); +#endif +} diff --git a/runit-2.1.2/src/str.h b/runit-2.1.2/src/str.h new file mode 100644 index 0000000..f65b8f6 --- /dev/null +++ b/runit-2.1.2/src/str.h @@ -0,0 +1,16 @@ +/* Public domain. */ + +#ifndef STR_H +#define STR_H + +extern unsigned int str_copy(char *,const char *); +extern int str_diff(const char *,const char *); +extern int str_diffn(const char *,const char *,unsigned int); +extern unsigned int str_len(const char *); +extern unsigned int str_chr(const char *,int); +extern unsigned int str_rchr(const char *,int); +extern int str_start(const char *,const char *); + +#define str_equal(s,t) (!str_diff((s),(t))) + +#endif diff --git a/runit-2.1.2/src/str_chr.c b/runit-2.1.2/src/str_chr.c new file mode 100644 index 0000000..9b467eb --- /dev/null +++ b/runit-2.1.2/src/str_chr.c @@ -0,0 +1,19 @@ +/* Public domain. */ + +#include "str.h" + +unsigned int str_chr(register const char *s,int c) +{ + register char ch; + register const char *t; + + ch = c; + t = s; + for (;;) { + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + if (!*t) break; if (*t == ch) break; ++t; + } + return t - s; +} diff --git a/runit-2.1.2/src/str_diff.c b/runit-2.1.2/src/str_diff.c new file mode 100644 index 0000000..47dff22 --- /dev/null +++ b/runit-2.1.2/src/str_diff.c @@ -0,0 +1,17 @@ +/* Public domain. */ + +#include "str.h" + +int str_diff(register const char *s,register const char *t) +{ + register char x; + + for (;;) { + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + x = *s; if (x != *t) break; if (!x) break; ++s; ++t; + } + return ((int)(unsigned int)(unsigned char) x) + - ((int)(unsigned int)(unsigned char) *t); +} diff --git a/runit-2.1.2/src/str_len.c b/runit-2.1.2/src/str_len.c new file mode 100644 index 0000000..dedd005 --- /dev/null +++ b/runit-2.1.2/src/str_len.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +#include "str.h" + +unsigned int str_len(const char *s) +{ + register const char *t; + + t = s; + for (;;) { + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + if (!*t) return t - s; ++t; + } +} diff --git a/runit-2.1.2/src/str_start.c b/runit-2.1.2/src/str_start.c new file mode 100644 index 0000000..017efc7 --- /dev/null +++ b/runit-2.1.2/src/str_start.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include "str.h" + +int str_start(register const char *s,register const char *t) +{ + register char x; + + for (;;) { + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + x = *t++; if (!x) return 1; if (x != *s++) return 0; + } +} diff --git a/runit-2.1.2/src/stralloc.h b/runit-2.1.2/src/stralloc.h new file mode 100644 index 0000000..51d61bd --- /dev/null +++ b/runit-2.1.2/src/stralloc.h @@ -0,0 +1,31 @@ +/* Public domain. */ + +#ifndef STRALLOC_H +#define STRALLOC_H + +#include "gen_alloc.h" + +GEN_ALLOC_typedef(stralloc,char,s,len,a) + +extern int stralloc_ready(stralloc *,unsigned int); +extern int stralloc_readyplus(stralloc *,unsigned int); +extern int stralloc_copy(stralloc *,const stralloc *); +extern int stralloc_cat(stralloc *,const stralloc *); +extern int stralloc_copys(stralloc *,const char *); +extern int stralloc_cats(stralloc *,const char *); +extern int stralloc_copyb(stralloc *,const char *,unsigned int); +extern int stralloc_catb(stralloc *,const char *,unsigned int); +extern int stralloc_append(stralloc *,const char *); /* beware: this takes a pointer to 1 char */ +extern int stralloc_starts(stralloc *,const char *); + +#define stralloc_0(sa) stralloc_append(sa,"") + +extern int stralloc_catulong0(stralloc *,unsigned long,unsigned int); +extern int stralloc_catlong0(stralloc *,long,unsigned int); + +#define stralloc_catlong(sa,l) (stralloc_catlong0((sa),(l),0)) +#define stralloc_catuint0(sa,i,n) (stralloc_catulong0((sa),(i),(n))) +#define stralloc_catint0(sa,i,n) (stralloc_catlong0((sa),(i),(n))) +#define stralloc_catint(sa,i) (stralloc_catlong0((sa),(i),0)) + +#endif diff --git a/runit-2.1.2/src/stralloc_cat.c b/runit-2.1.2/src/stralloc_cat.c new file mode 100644 index 0000000..2c6ad58 --- /dev/null +++ b/runit-2.1.2/src/stralloc_cat.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include "byte.h" +#include "stralloc.h" + +int stralloc_cat(stralloc *sato,const stralloc *safrom) +{ + return stralloc_catb(sato,safrom->s,safrom->len); +} diff --git a/runit-2.1.2/src/stralloc_catb.c b/runit-2.1.2/src/stralloc_catb.c new file mode 100644 index 0000000..8ee0af4 --- /dev/null +++ b/runit-2.1.2/src/stralloc_catb.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include "stralloc.h" +#include "byte.h" + +int stralloc_catb(stralloc *sa,const char *s,unsigned int n) +{ + if (!sa->s) return stralloc_copyb(sa,s,n); + if (!stralloc_readyplus(sa,n + 1)) return 0; + byte_copy(sa->s + sa->len,n,s); + sa->len += n; + sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ + return 1; +} diff --git a/runit-2.1.2/src/stralloc_cats.c b/runit-2.1.2/src/stralloc_cats.c new file mode 100644 index 0000000..ea1e290 --- /dev/null +++ b/runit-2.1.2/src/stralloc_cats.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_cats(stralloc *sa,const char *s) +{ + return stralloc_catb(sa,s,str_len(s)); +} diff --git a/runit-2.1.2/src/stralloc_eady.c b/runit-2.1.2/src/stralloc_eady.c new file mode 100644 index 0000000..81dbb85 --- /dev/null +++ b/runit-2.1.2/src/stralloc_eady.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) +GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) diff --git a/runit-2.1.2/src/stralloc_opyb.c b/runit-2.1.2/src/stralloc_opyb.c new file mode 100644 index 0000000..bbcff48 --- /dev/null +++ b/runit-2.1.2/src/stralloc_opyb.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +#include "stralloc.h" +#include "byte.h" + +int stralloc_copyb(stralloc *sa,const char *s,unsigned int n) +{ + if (!stralloc_ready(sa,n + 1)) return 0; + byte_copy(sa->s,n,s); + sa->len = n; + sa->s[n] = 'Z'; /* ``offensive programming'' */ + return 1; +} diff --git a/runit-2.1.2/src/stralloc_opys.c b/runit-2.1.2/src/stralloc_opys.c new file mode 100644 index 0000000..075b6f8 --- /dev/null +++ b/runit-2.1.2/src/stralloc_opys.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include "byte.h" +#include "str.h" +#include "stralloc.h" + +int stralloc_copys(stralloc *sa,const char *s) +{ + return stralloc_copyb(sa,s,str_len(s)); +} diff --git a/runit-2.1.2/src/stralloc_pend.c b/runit-2.1.2/src/stralloc_pend.c new file mode 100644 index 0000000..70cb55c --- /dev/null +++ b/runit-2.1.2/src/stralloc_pend.c @@ -0,0 +1,7 @@ +/* Public domain. */ + +#include "alloc.h" +#include "stralloc.h" +#include "gen_allocdefs.h" + +GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) diff --git a/runit-2.1.2/src/strerr.h b/runit-2.1.2/src/strerr.h new file mode 100644 index 0000000..21d812d --- /dev/null +++ b/runit-2.1.2/src/strerr.h @@ -0,0 +1,80 @@ +/* Public domain. */ + +#ifndef STRERR_H +#define STRERR_H + +struct strerr { + struct strerr *who; + const char *x; + const char *y; + const char *z; +} ; + +extern struct strerr strerr_sys; +extern void strerr_sysinit(void); + +extern const char *strerr(const struct strerr *); +extern void strerr_warn(const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); +extern void strerr_die(int,const char *,const char *,const char *,const char *,const char *,const char *,const struct strerr *); + +#define STRERR(r,se,a) \ +{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } + +#define STRERR_SYS(r,se,a) \ +{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } +#define STRERR_SYS3(r,se,a,b,c) \ +{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } + +#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se)) +#define strerr_warn5(x1,x2,x3,x4,x5,se) \ +strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se)) +#define strerr_warn4(x1,x2,x3,x4,se) \ +strerr_warn((x1),(x2),(x3),(x4),0,0,(se)) +#define strerr_warn3(x1,x2,x3,se) \ +strerr_warn((x1),(x2),(x3),0,0,0,(se)) +#define strerr_warn2(x1,x2,se) \ +strerr_warn((x1),(x2),0,0,0,0,(se)) +#define strerr_warn1(x1,se) \ +strerr_warn((x1),0,0,0,0,0,(se)) + +#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se)) +#define strerr_die5(e,x1,x2,x3,x4,x5,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se)) +#define strerr_die4(e,x1,x2,x3,x4,se) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se)) +#define strerr_die3(e,x1,x2,x3,se) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,(se)) +#define strerr_die2(e,x1,x2,se) \ +strerr_die((e),(x1),(x2),0,0,0,0,(se)) +#define strerr_die1(e,x1,se) \ +strerr_die((e),(x1),0,0,0,0,0,(se)) + +#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) +#define strerr_die5sys(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys) +#define strerr_die4sys(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys) +#define strerr_die3sys(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys) +#define strerr_die2sys(e,x1,x2) \ +strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys) +#define strerr_die1sys(e,x1) \ +strerr_die((e),(x1),0,0,0,0,0,&strerr_sys) + +#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0) +#define strerr_die5x(e,x1,x2,x3,x4,x5) \ +strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0) +#define strerr_die4x(e,x1,x2,x3,x4) \ +strerr_die((e),(x1),(x2),(x3),(x4),0,0,0) +#define strerr_die3x(e,x1,x2,x3) \ +strerr_die((e),(x1),(x2),(x3),0,0,0,0) +#define strerr_die2x(e,x1,x2) \ +strerr_die((e),(x1),(x2),0,0,0,0,0) +#define strerr_die1x(e,x1) \ +strerr_die((e),(x1),0,0,0,0,0,0) + +#endif diff --git a/runit-2.1.2/src/strerr_die.c b/runit-2.1.2/src/strerr_die.c new file mode 100644 index 0000000..f226b80 --- /dev/null +++ b/runit-2.1.2/src/strerr_die.c @@ -0,0 +1,33 @@ +/* Public domain. */ + +#include <unistd.h> +#include "buffer.h" +#include "strerr.h" + +void strerr_warn(const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) +{ + strerr_sysinit(); + + if (x1) buffer_puts(buffer_2,x1); + if (x2) buffer_puts(buffer_2,x2); + if (x3) buffer_puts(buffer_2,x3); + if (x4) buffer_puts(buffer_2,x4); + if (x5) buffer_puts(buffer_2,x5); + if (x6) buffer_puts(buffer_2,x6); + + while(se) { + if (se->x) buffer_puts(buffer_2,se->x); + if (se->y) buffer_puts(buffer_2,se->y); + if (se->z) buffer_puts(buffer_2,se->z); + se = se->who; + } + + buffer_puts(buffer_2,"\n"); + buffer_flush(buffer_2); +} + +void strerr_die(int e,const char *x1,const char *x2,const char *x3,const char *x4,const char *x5,const char *x6,const struct strerr *se) +{ + strerr_warn(x1,x2,x3,x4,x5,x6,se); + _exit(e); +} diff --git a/runit-2.1.2/src/strerr_sys.c b/runit-2.1.2/src/strerr_sys.c new file mode 100644 index 0000000..84b302f --- /dev/null +++ b/runit-2.1.2/src/strerr_sys.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include "error.h" +#include "strerr.h" + +struct strerr strerr_sys; + +void strerr_sysinit(void) +{ + strerr_sys.who = 0; + strerr_sys.x = error_str(errno); + strerr_sys.y = ""; + strerr_sys.z = ""; +} diff --git a/runit-2.1.2/src/subgetopt.c b/runit-2.1.2/src/subgetopt.c new file mode 100644 index 0000000..85ace96 --- /dev/null +++ b/runit-2.1.2/src/subgetopt.c @@ -0,0 +1,67 @@ +/* Public domain. */ + +#define SUBGETOPTNOSHORT +#include "subgetopt.h" + +#define sgopt subgetopt +#define optind subgetoptind +#define optpos subgetoptpos +#define optarg subgetoptarg +#define optproblem subgetoptproblem +#define optdone subgetoptdone + +int optind = 1; +int optpos = 0; +const char *optarg = 0; +int optproblem = 0; +int optdone = SUBGETOPTDONE; + +int sgopt(int argc,const char *const *argv,const char *opts) +{ + int c; + const char *s; + + optarg = 0; + if (!argv || (optind >= argc) || !argv[optind]) return optdone; + if (optpos && !argv[optind][optpos]) { + ++optind; + optpos = 0; + if ((optind >= argc) || !argv[optind]) return optdone; + } + if (!optpos) { + if (argv[optind][0] != '-') return optdone; + ++optpos; + c = argv[optind][1]; + if ((c == '-') || (c == 0)) { + if (c) ++optind; + optpos = 0; + return optdone; + } + /* otherwise c is reassigned below */ + } + c = argv[optind][optpos]; + ++optpos; + s = opts; + while (*s) { + if (c == *s) { + if (s[1] == ':') { + optarg = argv[optind] + optpos; + ++optind; + optpos = 0; + if (!*optarg) { + optarg = argv[optind]; + if ((optind >= argc) || !optarg) { /* argument past end */ + optproblem = c; + return '?'; + } + ++optind; + } + } + return c; + } + ++s; + if (*s == ':') ++s; + } + optproblem = c; + return '?'; +} diff --git a/runit-2.1.2/src/subgetopt.h b/runit-2.1.2/src/subgetopt.h new file mode 100644 index 0000000..41ad26a --- /dev/null +++ b/runit-2.1.2/src/subgetopt.h @@ -0,0 +1,26 @@ +/* Public domain. */ + +#ifndef SUBGETOPT_H +#define SUBGETOPT_H + +#ifndef SUBGETOPTNOSHORT +#define sgopt subgetopt +#define sgoptarg subgetoptarg +#define sgoptind subgetoptind +#define sgoptpos subgetoptpos +#define sgoptproblem subgetoptproblem +#define sgoptprogname subgetoptprogname +#define sgoptdone subgetoptdone +#endif + +#define SUBGETOPTDONE -1 + +extern int subgetopt(int,const char *const *,const char *); +extern const char *subgetoptarg; +extern int subgetoptind; +extern int subgetoptpos; +extern int subgetoptproblem; +extern const char *subgetoptprogname; +extern int subgetoptdone; + +#endif diff --git a/runit-2.1.2/src/sv.c b/runit-2.1.2/src/sv.c new file mode 100644 index 0000000..0125795 --- /dev/null +++ b/runit-2.1.2/src/sv.c @@ -0,0 +1,394 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "str.h" +#include "strerr.h" +#include "error.h" +#include "sgetopt.h" +#include "open.h" +#include "env.h" +#include "buffer.h" +#include "fmt.h" +#include "scan.h" +#include "tai.h" +#include "taia.h" +#include "wait.h" + +#define USAGE " [-v] [-w sec] command service ..." +#define USAGELSB " [-w sec] command" + +#define VERSION "$Id: 900314260c6d52c986c5357673bea2f3bd3f4698 $" + +#define FATAL "fatal: " +#define FAIL "fail: " +#define WARN "warning: " +#define OK "ok: " +#define RUN "run: " +#define FINISH "finish: " +#define DOWN "down: " +#define TIMEOUT "timeout: " +#define KILL "kill: " + +char *progname; +char *action; +char *acts; +char *varservice ="/service/"; +char **service; +char **servicex; +unsigned int services; +unsigned int rc =0; +unsigned int lsb; +unsigned int verbose =0; +unsigned long wait =7; +unsigned int kll =0; +unsigned int islog =0; +struct taia tstart, tnow, tdiff; +struct tai tstatus; + +int (*act)(char*) =0; +int (*cbk)(char*) =0; + +int curdir, fd, r; +char svstatus[20]; +char sulong[FMT_ULONG]; + +void usage() { + if (!lsb) strerr_die4x(100, "usage: ", progname, USAGE, "\n"); + strerr_die4x(2, "usage: ", progname, USAGELSB, "\n"); +} +void done(unsigned int e) { if (curdir != -1) fchdir(curdir); _exit(e); } +void fatal(char *m1) { + strerr_warn3(FATAL, m1, ": ", &strerr_sys); + done(lsb ? 151 : 100); +} +void fatal2(char *m1, char *m2) { + strerr_warn4(FATAL, m1, m2, ": ", &strerr_sys); + done(lsb ? 151 : 100); +} +void out(char *p, char *m1) { + buffer_puts(buffer_1, p); + buffer_puts(buffer_1, *service); + if (islog) buffer_puts(buffer_1, "/log"); + buffer_puts(buffer_1, ": "); + buffer_puts(buffer_1, m1); + if (errno) { + buffer_puts(buffer_1, ": "); + buffer_puts(buffer_1, error_str(errno)); + } + buffer_puts(buffer_1, "\n"); + buffer_flush(buffer_1); +} +void fail(char *m1) { ++rc; out(FAIL, m1); } +void failx(char *m1) { errno =0; fail(m1); } +void warn(char *m1) { ++rc; out(WARN, m1); } +void warnx(char *m1) { errno =0; warn(m1); } +void ok(char *m1) { errno =0; out(OK, m1); } + +void outs(const char *s) { buffer_puts(buffer_1, s); } +void flush(const char *s) { outs(s); buffer_flush(buffer_1); } +void outs2(const char *s) { buffer_puts(buffer_2, s); } +void flush2(const char *s) { outs2(s); buffer_flush(buffer_2); } + +int svstatus_get() { + if ((fd =open_write("supervise/ok")) == -1) { + if (errno == error_nodevice) { + *acts == 'x' ? ok("runsv not running") : failx("runsv not running"); + return(0); + } + warn("unable to open supervise/ok"); + return(-1); + } + close(fd); + if ((fd =open_read("supervise/status")) == -1) { + warn("unable to open supervise/status"); + return(-1); + } + r =read(fd, svstatus, 20); + close(fd); + switch(r) { + case 20: break; + case -1: warn("unable to read supervise/status"); return(-1); + default: warnx("unable to read supervise/status: bad format"); return(-1); + } + return(1); +} +unsigned int svstatus_print(char *m) { + int pid; + int normallyup =0; + struct stat s; + + if (stat("down", &s) == -1) { + if (errno != error_noent) { + outs2(WARN); outs2("unable to stat "); outs2(*service); outs2("/down: "); + outs2(error_str(errno)); flush2("\n"); + return(0); + } + normallyup =1; + } + pid =(unsigned char) svstatus[15]; + pid <<=8; pid +=(unsigned char)svstatus[14]; + pid <<=8; pid +=(unsigned char)svstatus[13]; + pid <<=8; pid +=(unsigned char)svstatus[12]; + tai_unpack(svstatus, &tstatus); + switch (svstatus[19]) { + case 0: outs(DOWN); break; + case 1: outs(RUN); break; + case 2: outs(FINISH); break; + } + outs(m); outs(": "); + if (svstatus[19]) { + outs("(pid "); sulong[fmt_ulong(sulong, pid)] =0; + outs(sulong); outs(") "); + } + buffer_put(buffer_1, sulong, + fmt_ulong(sulong, tnow.sec.x < tstatus.x ? 0 : tnow.sec.x -tstatus.x)); + outs("s"); + if (pid && !normallyup) outs(", normally down"); + if (!pid && normallyup) outs(", normally up"); + if (pid && svstatus[16]) outs(", paused"); + if (!pid && (svstatus[17] == 'u')) outs(", want up"); + if (pid && (svstatus[17] == 'd')) outs(", want down"); + if (pid && svstatus[18]) outs(", got TERM"); + return(pid ? 1 : 2); +} +int status(char *unused) { + int rc; + + rc =svstatus_get(); + switch(rc) { case -1: if (lsb) done(4); case 0: return(0); } + rc =svstatus_print(*service); + islog =1; + if (chdir("log") == -1) { + if (errno != error_noent) { + outs("; "); + warn("unable to change directory"); + } + else outs("\n"); + } + else { + outs("; "); + if (svstatus_get()) { rc =svstatus_print("log"); outs("\n"); } + } + islog =0; + flush(""); + if (lsb) switch(rc) { case 1: done(0); case 2: done(3); case 0: done(4); } + return(rc); +} + +int checkscript() { + char *prog[2]; + struct stat s; + int pid, w; + + if (stat("check", &s) == -1) { + if (errno == error_noent) return(1); + outs2(WARN); outs2("unable to stat "); outs2(*service); outs2("/check: "); + outs2(error_str(errno)); flush2("\n"); + return(0); + } + /* if (!(s.st_mode & S_IXUSR)) return(1); */ + if ((pid =fork()) == -1) { + outs2(WARN); outs2("unable to fork for "); outs2(*service); + outs2("/check: "); outs2(error_str(errno)); flush2("\n"); + return(0); + } + if (!pid) { + prog[0] ="./check"; + prog[1] =0; + close(1); + execve("check", prog, environ); + outs2(WARN); outs2("unable to run "); outs2(*service); outs2("/check: "); + outs2(error_str(errno)); flush2("\n"); + _exit(0); + } + while (wait_pid(&w, pid) == -1) { + if (errno == error_intr) continue; + outs2(WARN); outs2("unable to wait for child "); outs2(*service); + outs2("/check: "); outs2(error_str(errno)); flush2("\n"); + return(0); + } + return(!wait_exitcode(w)); +} + +int check(char *a) { + unsigned int pid; + + if ((r =svstatus_get()) == -1) return(-1); + while (*a) { + if (r == 0) { if (*a == 'x') return(1); return(-1); } + pid =(unsigned char)svstatus[15]; + pid <<=8; pid +=(unsigned char)svstatus[14]; + pid <<=8; pid +=(unsigned char)svstatus[13]; + pid <<=8; pid +=(unsigned char)svstatus[12]; + switch (*a) { + case 'x': return(0); + case 'u': + if (!pid || svstatus[19] != 1) return(0); + if (!checkscript()) return(0); + break; + case 'd': if (pid || svstatus[19] != 0) return(0); break; + case 'C': if (pid) if (!checkscript()) return(0); break; + case 't': + case 'k': + if (!pid && svstatus[17] == 'd') break; + tai_unpack(svstatus, &tstatus); + if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18] || !checkscript()) + return(0); + break; + case 'o': + tai_unpack(svstatus, &tstatus); + if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd')) + return(0); + break; + case 'p': if (pid && !svstatus[16]) return(0); break; + case 'c': if (pid && svstatus[16]) return(0); break; + } + ++a; + } + outs(OK); svstatus_print(*service); flush("\n"); + return(1); +} +int control(char *a) { + if (svstatus_get() <= 0) return(-1); + if (svstatus[17] == *a) + if (*a != 'd' || svstatus[18] == 1) return(0); /* once w/o term */ + if ((fd =open_write("supervise/control")) == -1) { + if (errno != error_nodevice) + warn("unable to open supervise/control"); + else + *a == 'x' ? ok("runsv not running") : failx("runsv not running"); + return(-1); + } + r =write(fd, a, str_len(a)); + close(fd); + if (r != str_len(a)) { + warn("unable to write to supervise/control"); + return(-1); + } + return(1); +} + +int main(int argc, char **argv) { + unsigned int i, done; + char *x; + + progname =*argv; + for (i =str_len(*argv); i; --i) if ((*argv)[i -1] == '/') break; + *argv +=i; + optprogname =progname =*argv; + service =argv; + services =1; + lsb =(str_diff(progname, "sv")); + if ((x =env_get("SVDIR"))) varservice =x; + if ((x =env_get("SVWAIT"))) scan_ulong(x, &wait); + while ((i =getopt(argc, (const char* const*)argv, "w:vV")) != opteof) { + switch(i) { + case 'w': scan_ulong(optarg, &wait); + case 'v': verbose =1; break; + case 'V': strerr_warn1(VERSION, 0); + case '?': usage(); + } + } + argv +=optind; argc -=optind; + if (!(action =*argv++)) usage(); --argc; + if (!lsb) { service =argv; services =argc; } + if (!*service) usage(); + + taia_now(&tnow); tstart =tnow; + if ((curdir =open_read(".")) == -1) + fatal("unable to open current directory"); + + act =&control; acts ="s"; + if (verbose) cbk =✓ + switch (*action) { + case 'x': case 'e': + acts ="x"; break; + case 'X': case 'E': + acts ="x"; kll =1; cbk =✓ break; + case 'D': + acts ="d"; kll =1; cbk =✓ break; + case 'T': + acts ="tc"; kll =1; cbk =✓ break; + case 't': + if (!str_diff(action, "try-restart")) { acts ="tc"; cbk =✓ break; } + case 'c': + if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =✓ break; } + case 'u': case 'd': case 'o': case 'p': case 'h': + case 'a': case 'i': case 'k': case 'q': case '1': case '2': + action[1] =0; acts =action; break; + case 's': + if (!str_diff(action, "shutdown")) { acts ="x"; cbk =✓ break; } + if (!str_diff(action, "start")) { acts ="u"; cbk =✓ break; } + if (!str_diff(action, "stop")) { acts ="d"; cbk =✓ break; } + if (lsb && str_diff(action, "status")) usage(); + act =&status; cbk =0; break; + case 'r': + if (!str_diff(action, "restart")) { acts ="tcu"; cbk =✓ break; } + if (!str_diff(action, "reload")) { acts ="h"; cbk =✓ break; } + usage(); + case 'f': + if (!str_diff(action, "force-reload")) + { acts ="tc"; kll =1; cbk =✓ break; } + if (!str_diff(action, "force-restart")) + { acts ="tcu"; kll =1; cbk =✓ break; } + if (!str_diff(action, "force-shutdown")) + { acts ="x"; kll =1; cbk =✓ break; } + if (!str_diff(action, "force-stop")) + { acts ="d"; kll =1; cbk =✓ break; } + default: + usage(); + } + + servicex =service; + for (i =0; i < services; ++i) { + if ((**service != '/') && (**service != '.') && **service && + ((*service)[str_len(*service) -1] != '/')) { + if ((chdir(varservice) == -1) || (chdir(*service) == -1)) { + fail("unable to change to service directory"); + *service =0; + } + } + else + if (chdir(*service) == -1) { + fail("unable to change to service directory"); + *service =0; + } + if (*service) if (act && (act(acts) == -1)) *service =0; + if (fchdir(curdir) == -1) fatal("unable to change to original directory"); + service++; + } + + if (*cbk) + for (;;) { + taia_sub(&tdiff, &tnow, &tstart); + service =servicex; done =1; + for (i =0; i < services; ++i, ++service) { + if (!*service) continue; + if ((**service != '/') && (**service != '.')) { + if ((chdir(varservice) == -1) || (chdir(*service) == -1)) { + fail("unable to change to service directory"); + *service =0; + } + } + else + if (chdir(*service) == -1) { + fail("unable to change to service directory"); + *service =0; + } + if (*service) { if (cbk(acts) != 0) *service =0; else done =0; } + if (*service && taia_approx(&tdiff) > wait) { + kll ? outs(KILL) : outs(TIMEOUT); + if (svstatus_get() > 0) { svstatus_print(*service); ++rc; } + flush("\n"); + if (kll) control("k"); + *service =0; + } + if (fchdir(curdir) == -1) + fatal("unable to change to original directory"); + } + if (done) break; + usleep(420000); + taia_now(&tnow); + } + return(rc > 99 ? 99 : rc); +} diff --git a/runit-2.1.2/src/sv.check b/runit-2.1.2/src/sv.check new file mode 100755 index 0000000..d3c277c --- /dev/null +++ b/runit-2.1.2/src/sv.check @@ -0,0 +1,27 @@ +#!/bin/sh +rm -rf "${ctmp}" +trap 'rm -rf "${ctmp}"' EXIT + +sv +echo $? +sv -V +echo $? + +mkdir "${ctmp}" +cat >"${ctmp}"/run <<-\EOT + #!/bin/sh + echo starting + exec sleep 14 + EOT +chmod 700 "${ctmp}"/run +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +sv down "${ctmp}" +echo $? +sleep 1 +cat "${ctmp}"/supervise/stat +sv exit "${ctmp}" +echo $? +wait +echo $? diff --git a/runit-2.1.2/src/sv.dist b/runit-2.1.2/src/sv.dist new file mode 100644 index 0000000..5b6c3ee --- /dev/null +++ b/runit-2.1.2/src/sv.dist @@ -0,0 +1,12 @@ +usage: sv [-v] [-w sec] command service ... + +100 +$Id: 900314260c6d52c986c5357673bea2f3bd3f4698 $ +usage: sv [-v] [-w sec] command service ... + +100 +starting +0 +down +0 +0 diff --git a/runit-2.1.2/src/svlogd.c b/runit-2.1.2/src/svlogd.c new file mode 100644 index 0000000..90a3321 --- /dev/null +++ b/runit-2.1.2/src/svlogd.c @@ -0,0 +1,848 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <time.h> +#include <sys/time.h> +#include <dirent.h> +#include <unistd.h> +#include <stdio.h> +#include "pmatch.h" +#include "fmt_ptime.h" +#include "alloc.h" +#include "stralloc.h" +#include "strerr.h" +#include "buffer.h" +#include "sig.h" +#include "env.h" +#include "fd.h" +#include "wait.h" +#include "error.h" +#include "sgetopt.h" +#include "open.h" +#include "openreadclose.h" +#include "coe.h" +#include "lock.h" +#include "str.h" +#include "byte.h" +#include "scan.h" +#include "direntry.h" +#include "taia.h" +#include "fmt.h" +#include "ndelay.h" +#include "iopause.h" + +#define USAGE " [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ..." +#define VERSION "$Id: 5e55a90e0a1b35ec47fed3021453c50675ea1117 $" + +#define FATAL "svlogd: fatal: " +#define WARNING "svlogd: warning: " +#define PAUSE "svlogd: pausing: " +#define INFO "svlogd: info: " + +const char *progname; + +unsigned int verbose =0; +unsigned int timestamp =0; +unsigned long linemax =1000; +unsigned long buflen =1024; +unsigned long linelen; + +const char *replace =""; +char repl =0; + +const char **fndir; +int fdwdir; +struct stat st; +stralloc sa; +int wstat; +struct taia now; +struct taia trotate; + +char *databuf; +buffer data; +char *line; +char stamp[FMT_PTIME]; +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; + char *btmp; + buffer b; + stralloc inst; + 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]; + char *name; + int fdcur; + int fdlock; + char match; + char matcherr; + struct sockaddr_in udpaddr; + unsigned int udponly; + stralloc prefix; +} *dir; +unsigned int dirn =0; + +void usage() { strerr_die4x(111, "usage: ", progname, USAGE, "\n"); } +void die_nomem() { strerr_die2x(111, FATAL, "out of memory."); } +void fatal(char *m0) { strerr_die3sys(111, FATAL, m0, ": "); } +void fatalx(char *m0) { strerr_die2x(111, FATAL, m0); } +void fatal2(char *m0, char *m1) { + strerr_die5sys(111, FATAL, m0, ": ", m1, ": "); +} +void warn(char *m0) { strerr_warn3(WARNING, m0, ": ", &strerr_sys); } +void warn2(char *m0, char *m1) { + strerr_warn5(WARNING, m0, ": ", m1, ": ", &strerr_sys); +} +void warnx(char *m0, char *m1) { strerr_warn4(WARNING, m0, ": ", m1, 0); } +void pause_nomem() { strerr_warn2(PAUSE, "out of memory.", 0); sleep(3); } +void pause1(char *m0) { strerr_warn3(PAUSE, m0, ": ", &strerr_sys); sleep(3); } +void pause2(char *m0, char *m1) { + strerr_warn5(PAUSE, m0, ": ", m1, ": ", &strerr_sys); + sleep(3); +} + +unsigned int processorstart(struct logdir *ld) { + int pid; + + if (! ld->processor.len) return(0); + if (ld->ppid) { + warnx("processor already running", ld->name); + return(0); + } + while ((pid =fork()) == -1) + pause2("unable to fork for processor", ld->name); + if (! pid) { + char *prog[4]; + int fd; + + /* child */ + sig_uncatch(sig_term); + sig_uncatch(sig_alarm); + sig_uncatch(sig_hangup); + sig_unblock(sig_term); + 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) + fatal2("unable to move filedescriptor for processor", ld->name); + ld->fnsave[26] ='t'; + if ((fd =open_trunc(ld->fnsave)) == -1) + fatal2("unable to open output for processor", ld->name); + if (fd_move(1, fd) == -1) + 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); + } + else + fatal2("unable to open state for processor", ld->name); + } + if (fd_move(4, fd) == -1) + fatal2("unable to move filedescriptor for processor", ld->name); + if ((fd =open_trunc("newstate")) == -1) + fatal2("unable to open newstate for processor", ld->name); + if (fd_move(5, fd) == -1) + fatal2("unable to move filedescriptor for processor", ld->name); + + prog[0] = "sh"; + prog[1] = "-c"; + prog[2] = ld->processor.s; + prog[3] = 0; + execve("/bin/sh", prog, environ); + fatal2("unable to run processor", ld->name); + } + ld->ppid =pid; + return(1); +} +unsigned int processorstop(struct logdir *ld) { + char f[28]; + + if (ld->ppid) { + sig_unblock(sig_hangup); + while (wait_pid(&wstat, ld->ppid) == -1) + pause2("error waiting for processor", ld->name); + 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 failed, restart", ld->name); + ld->fnsave[26] ='t'; + unlink(ld->fnsave); + ld->fnsave[26] ='u'; + processorstart(ld); + while (fchdir(fdwdir) == -1) + pause1("unable to change to initial working directory"); + return(ld->processor.len ? 0 : 1); + } + ld->fnsave[26] ='t'; + byte_copy(f, 26, ld->fnsave); + f[26] ='s'; f[27] =0; + while (rename(ld->fnsave, f) == -1) + pause2("unable to rename processed", ld->name); + while (chmod(f, 0744) == -1) + pause2("unable to set mode of processed", ld->name); + ld->fnsave[26] ='u'; + if (unlink(ld->fnsave) == -1) + strerr_warn5(WARNING, "unable to unlink: ", ld->name, "/", ld->fnsave, 0); + 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); +} + +void rmoldest(struct logdir *ld) { + DIR *d; + direntry *f; + char oldest[FMT_PTIME]; + int n =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)) { + if (f->d_name[26] == 't') { + if (unlink(f->d_name) == -1) + warn2("unable to unlink processor leftover", f->d_name); + } + else { + ++n; + if (str_diff(f->d_name, oldest) < 0) byte_copy(oldest, 27, f->d_name); + } + errno =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); + } +} + +unsigned int rotate(struct logdir *ld) { + char tmp[FMT_ULONG +1]; + + if (ld->fddir == -1) { ld->tmax =0; return(0); } + if (ld->ppid) while(! processorstop(ld)); + + while (fchdir(ld->fddir) == -1) + pause2("unable to change directory, want rotate", ld->name); + + /* create new filename */ + ld->fnsave[25] ='.'; + if (ld->processor.len) + ld->fnsave[26] ='u'; + else + ld->fnsave[26] ='s'; + ld->fnsave[27] =0; + do { + taia_now(&now); + fmt_taia(ld->fnsave, &now); + errno =0; + } while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent)); + + 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; + } + + 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); + } + 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); + rmoldest(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) { + 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') + 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); + close(ld->fddir); + ld->fddir =-1; + if (ld->fdcur == -1) return; /* impossible */ + 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); + ld->fdcur =-1; + if (ld->fdlock == -1) return; /* impossible */ + close(ld->fdlock); + ld->fdlock =-1; + while (! stralloc_copys(&ld->processor, "")) pause_nomem(); +} + +/* taken from libdjbdns */ +unsigned int ip4_scan(const char *s,char ip[4]) +{ + unsigned int i; + unsigned int len; + unsigned long u; + + len = 0; + i = scan_ulong(s,&u); if (!i) return 0; ip[0] = u; s += i; len += i; + if (*s != '.') return 0; ++s; ++len; + i = scan_ulong(s,&u); if (!i) return 0; ip[1] = u; s += i; len += i; + if (*s != '.') return 0; ++s; ++len; + i = scan_ulong(s,&u); if (!i) return 0; ip[2] = u; s += i; len += i; + if (*s != '.') return 0; ++s; ++len; + i = scan_ulong(s,&u); if (!i) return 0; ip[3] = u; s += i; len += i; + return len; +} + +unsigned int logdir_open(struct logdir *ld, const char *fn) { + int i; + + if ((ld->fddir =open_read(fn)) == -1) { + warn2("unable to open log directory", (char*)fn); + return(0); + } + coe(ld->fddir); + if (fchdir(ld->fddir) == -1) { + logdir_close(ld); + warn2("unable to change directory", (char*)fn); + return(0); + } + ld->fdlock =open_append("lock"); + if ((ld->fdlock == -1) || (lock_exnb(ld->fdlock) == -1)) { + logdir_close(ld); + warn2("unable to lock directory", (char*)fn); + while (fchdir(fdwdir) == -1) + pause1("unable to change to initial working directory"); + return(0); + } + coe(ld->fdlock); + + ld->size =0; + ld->sizemax =1000000; + ld->nmax =ld->nmin =10; + ld->tmax =0; + ld->name =(char*)fn; + ld->ppid =0; + ld->match ='+'; + ld->udpaddr.sin_port =0; + ld->udponly =0; + while (! stralloc_copys(&ld->prefix, "")) pause_nomem(); + while (! stralloc_copys(&ld->inst, "")) pause_nomem(); + while (! stralloc_copys(&ld->processor, "")) pause_nomem(); + + /* read config */ + if ((i =openreadclose("config", &sa, 128)) == -1) + warn2("unable to read config", ld->name); + if (i != 0) { + int len, c; + unsigned long port; + + if (verbose) strerr_warn4(INFO, "read: ", ld->name, "/config", 0); + for (i =0; i +1 < sa.len; ++i) { + len =byte_chr(&sa.s[i], sa.len -i, '\n'); + sa.s[len +i] =0; + switch(sa.s[i]) { + case '\n': + case '#': + 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; + case 's': + 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); + 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 '!': + if (len > 1) { + while (! stralloc_copys(&ld->processor, &sa.s[i +1])) pause_nomem(); + while (! stralloc_0(&ld->processor)) pause_nomem(); + } + break; + case 'U': + 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); + break; + case 'p': + if (len > 1) { + while (! stralloc_copys(&ld->prefix, &sa.s[i +1])) pause_nomem(); + while (! stralloc_0(&ld->prefix)) pause_nomem(); + } + break; + } + i +=len; + } + } + + /* open current */ + if ((i =stat("current", &st)) != -1) { + 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; + } while ((stat(ld->fnsave, &st) != -1) || (errno != error_noent)); + while (rename("current", ld->fnsave) == -1) + pause2("unable to rename current", ld->name); + rmoldest(ld); + i =-1; + } + else + ld->size =st.st_size; + } + else + if (errno != error_noent) { + logdir_close(ld); + warn2("unable to stat current", ld->name); + while (fchdir(fdwdir) == -1) + pause1("unable to change to initial working directory"); + return(0); + } + while ((ld->fdcur =open_append("current")) == -1) + pause2("unable to open current", ld->name); + coe(ld->fdcur); + while (fchmod(ld->fdcur, 0644) == -1) + pause2("unable to set mode of current", ld->name); + buffer_init(&ld->b, buffer_pwrite, ld -dir, ld->btmp, buflen); + + if (verbose) { + if (i == 0) strerr_warn4(INFO, "append: ", ld->name, "/current", 0); + else strerr_warn4(INFO, "new: ", ld->name, "/current", 0); + } + + while (fchdir(fdwdir) == -1) + pause1("unable to change to initial working directory"); + return(1); +} + +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; + } + if (! ok) fatalx("no functional log directories."); +} + +int buffer_pread(int fd, char *s, unsigned int len) { + int i; + + for (i =0; i < dirn; ++i) buffer_flush(&dir[i].b); + if (rotateasap) { + for (i =0; i < dirn; ++i) rotate(dir +i); + rotateasap =0; + } + if (exitasap) { + if (linecomplete) return(0); + len =1; + } + if (reopenasap) { + 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); + iopause(&in, 1, &trotate, &now); + sig_block(sig_term); + sig_block(sig_child); + sig_block(sig_alarm); + sig_block(sig_hangup); + 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); +} +void sig_term_handler(void) { + 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) { + dir[l].ppid =0; + processorstop(&dir[l]); + break; + } +} +void sig_alarm_handler(void) { + if (verbose) strerr_warn2(INFO, "sigalarm received.", 0); + rotateasap =1; +} +void sig_hangup_handler(void) { + if (verbose) strerr_warn2(INFO, "sighangup received.", 0); + reopenasap =1; +} + +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]; + break; + case 'e': + case 'E': + 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); + } +} +int main(int argc, const char **argv) { + int i; + int opt; + + progname =*argv; + + while ((opt =getopt(argc, argv, "R:r:l:b:tvV")) != opteof) { + switch(opt) { + case 'R': + replace =optarg; + if (! repl) repl ='_'; + break; + case 'r': + repl =*optarg; + if (! repl || *(optarg +1)) usage(); + break; + case 'l': + scan_ulong(optarg, &linemax); + if (linemax == 0) linemax =1000; + break; + case 'b': + scan_ulong(optarg, &buflen); + if (buflen == 0) buflen =1024; + break; + case 't': + if (++timestamp > 3) timestamp =3; + break; + case 'v': + ++verbose; + break; + case 'V': strerr_warn1(VERSION, 0); + case '?': usage(); + } + } + argv +=optind; + + dirn =argc -optind; + if (dirn <= 0) usage(); + if (buflen <= linemax) usage(); + if ((fdwdir =open_read(".")) == -1) + fatal("unable to open current working directory"); + coe(fdwdir); + dir =(struct logdir*)alloc(dirn *sizeof(struct logdir)); + if (! dir) die_nomem(); + for (i =0; i < dirn; ++i) { + dir[i].fddir =-1; dir[i].fdcur =-1; + dir[i].btmp =(char*)alloc(buflen *sizeof(char)); + if (! dir[i].btmp) die_nomem(); + dir[i].ppid =0; + } + databuf =(char*)alloc(buflen *sizeof(char)); + if (! databuf) die_nomem(); + buffer_init(&data, buffer_pread, 0, databuf, buflen); + 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); + sig_block(sig_alarm); + sig_block(sig_hangup); + sig_catch(sig_term, sig_term_handler); + sig_catch(sig_child, sig_child_handler); + sig_catch(sig_alarm, sig_alarm_handler); + sig_catch(sig_hangup, sig_hangup_handler); + + logdirs_reopen(); + + for(;;) { + char ch; + + linelen =0; + for (linelen =0; linelen < linemax; ++linelen) { + if (buffer_GETC(&data, &ch) <= 0) { + exitasap =1; + break; + } + if (! linelen && timestamp) { + taia_now(&now); + switch (timestamp) { + case 1: fmt_taia(stamp, &now); break; + case 2: fmt_ptime(stamp, &now); break; + case 3: fmt_ptime_iso8601(stamp, &now); break; + } + stamp[25] =' '; stamp[26] =0; + } + 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; + } + } + line[linelen] =ch; + } + if (exitasap && ! data.p) break; /* data buffer is empty */ + for (i =0; i < dirn; ++i) + if (dir[i].fddir != -1) { + if (dir[i].inst.len) logmatch(&dir[i]); + if (dir[i].matcherr == 'e') { + if (timestamp) buffer_puts(buffer_2, stamp); + if (dir[i].prefix.len) buffer_puts(buffer_2, dir[i].prefix.s); + 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].udpaddr.sin_port != 0) { + fdudp =socket(AF_INET, SOCK_DGRAM, 0); + if (fdudp) + if (ndelay_on(fdudp) == -1) { + close(fdudp); + fdudp =-1; + } + if (fdudp == -1) { + buffer_puts(&dir[i].b, "warning: no udp socket available: "); + if (timestamp) buffer_puts(&dir[i].b, stamp); + if (dir[i].prefix.len) buffer_puts(&dir[i].b, dir[i].prefix.s); + buffer_put(&dir[i].b, line, linelen); + buffer_put(&dir[i].b, "\n", 1); + buffer_flush(&dir[i].b); + } + else { + while (! stralloc_copys(&sa, "")) pause_nomem(); + if (timestamp) + while (! stralloc_cats(&sa, stamp)) pause_nomem(); + if (dir[i].prefix.len) + while (! stralloc_cats(&sa, dir[i].prefix.s)) pause_nomem(); + while (! stralloc_catb(&sa, line, linelen)) pause_nomem(); + if (linelen == linemax) + while (! stralloc_cats(&sa, "...")) pause_nomem(); + while (! stralloc_append(&sa, "\n")) pause_nomem(); + if (sendto(fdudp, sa.s, sa.len, 0, + (struct sockaddr *)&dir[i].udpaddr, + sizeof(dir[i].udpaddr)) != sa.len) { + buffer_puts(&dir[i].b, "warning: failure sending through udp: "); + buffer_put(&dir[i].b, sa.s, sa.len); + buffer_flush(&dir[i].b); + } + close(fdudp); + } + } + if (! dir[i].udponly) { + if (timestamp) buffer_puts(&dir[i].b, stamp); + if (dir[i].prefix.len) buffer_puts(&dir[i].b, dir[i].prefix.s); + buffer_put(&dir[i].b, line, linelen); + } + } + 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) { + if (dir[i].match != '+') continue; + if (! dir[i].udponly) { + ch ='\n'; + buffer_PUTC(&dir[i].b, ch); + buffer_flush(&dir[i].b); + } + } + } + + for (i =0; i < dirn; ++i) { + if (dir[i].ppid) while (! processorstop(&dir[i])); + logdir_close(&dir[i]); + } + _exit(0); +} diff --git a/runit-2.1.2/src/svlogd.check b/runit-2.1.2/src/svlogd.check new file mode 100755 index 0000000..7d926ef --- /dev/null +++ b/runit-2.1.2/src/svlogd.check @@ -0,0 +1,27 @@ +#!/bin/sh +rm -rf "${ctmp}" + +svlogd +echo $? +svlogd -V +echo $? + +mkdir "${ctmp}" +echo foo |svlogd "${ctmp}" +echo $? +cat "${ctmp}"/current + +( echo bar; echo baz ) |svlogd "${ctmp}" +echo $? +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}" diff --git a/runit-2.1.2/src/svlogd.dist b/runit-2.1.2/src/svlogd.dist new file mode 100644 index 0000000..b3329e6 --- /dev/null +++ b/runit-2.1.2/src/svlogd.dist @@ -0,0 +1,21 @@ +usage: svlogd [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ... + +111 +$Id: 5e55a90e0a1b35ec47fed3021453c50675ea1117 $ +usage: svlogd [-ttv] [-r c] [-R abc] [-l len] [-b buflen] dir ... + +111 +0 +foo +0 +foo +bar +baz +0 +foo +bar +baz +:oo +:ar +:az +0 diff --git a/runit-2.1.2/src/svwaitdown.c b/runit-2.1.2/src/svwaitdown.c new file mode 100644 index 0000000..21a2c2c --- /dev/null +++ b/runit-2.1.2/src/svwaitdown.c @@ -0,0 +1,177 @@ +#include <unistd.h> +#include "strerr.h" +#include "error.h" +#include "sgetopt.h" +#include "scan.h" +#include "open.h" +#include "tai.h" +#include "buffer.h" + +#define FATAL "svwaitdown: fatal: " +#define WARN "svwaitdown: warning: " +#define INFO "svwaitdown: " +#define USAGE " [-v] [-t 1..6000] service ..." + +#define VERSION "$Id: 6cd3efc2e15e5e3d2fa60cd0c028e60958676ec7 $" + +const char *progname; +const char * const *dir; +unsigned int rc =0; + +void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } +void warn(const char *s1, const char *s2, struct strerr *e) { + dir++; rc++; + strerr_warn3(WARN, s1, s2, e); +} +void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +int main(int argc, const char * const *argv) { + int opt; + unsigned long sec =600; + int verbose =0; + int doexit =0; + int dokill =0; + int wdir; + int fd; + char status[20]; + int r; + unsigned long pid; + struct tai start; + struct tai now; + + progname =*argv; + + while ((opt =getopt(argc, argv, "t:xkvV")) != opteof) { + switch(opt) { + case 't': + scan_ulong(optarg, &sec); + if ((sec < 1) || (sec > 6000)) usage(); + break; + case 'x': + doexit =1; + break; + case 'k': + dokill =1; + break; + case 'v': + verbose =1; + break; + case 'V': + strerr_warn1(VERSION, 0); + case '?': + usage(); + } + } + argv +=optind; + if (! argv || ! *argv) usage(); + + if ((wdir =open_read(".")) == -1) + fatal("unable to open current working directory"); + + for (dir =argv; *dir; ++dir) { + if (dir != argv) + if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); + if (chdir(*dir) == -1) continue; /* bummer */ + if ((fd =open_write("supervise/control")) == -1) continue; /* bummer */ + if (write(fd, "dx", 1 +doexit) != (1 +doexit)) { + close(fd); continue; /* bummer */ + } + close(fd); + } + dir =argv; + + tai_now(&start); + while (*dir) { + if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); + if (chdir(*dir) == -1) { + warn(*dir, ": unable to change directory: ", &strerr_sys); + continue; + } + if ((fd =open_write("supervise/ok")) == -1) { + if (errno == error_nodevice) { + if (verbose) strerr_warn3(INFO, *dir, ": runsv not running.", 0); + dir++; + } + else + warn(*dir, ": unable to open supervise/ok: ", &strerr_sys); + continue; + } + close(fd); + + if ((fd =open_read("supervise/status")) == -1) { + warn(*dir, "unable to open supervise/status: ", &strerr_sys); + continue; + } + r =buffer_unixread(fd, status, 20); + close(fd); + if ((r < 18) || (r == 19)) { /* supervise compatibility */ + if (r == -1) + warn(*dir, "unable to read supervise/status: ", &strerr_sys); + else + warn(*dir, ": unable to read supervise/status: bad format.", 0); + continue; + } + pid =(unsigned char)status[15]; + pid <<=8; pid +=(unsigned char)status[14]; + pid <<=8; pid +=(unsigned char)status[13]; + pid <<=8; pid +=(unsigned char)status[12]; + + if (! doexit && ! pid) { + /* ok, service is down */ + if (verbose) strerr_warn3(INFO, *dir, ": down.", 0); + dir++; + continue; + } + + if (status[17] != 'd') { /* catch previous failures */ + if ((fd =open_write("supervise/control")) == -1) { + warn(*dir, ": unable to open supervise/control: ", &strerr_sys); + continue; + } + if (write(fd, "dx", 1 +doexit) != (1 +doexit)) { + warn(*dir, ": unable to write to supervise/control: ", &strerr_sys); + close(fd); + continue; + } + close(fd); + } + + tai_now(&now); + tai_sub(&now, &now, &start); + if (tai_approx(&now) >= sec) { + /* timeout */ + if (verbose) strerr_warn2(INFO, "timeout.", 0); + if (dokill) { + if (chdir(*dir) == -1) { + warn(*dir, ": unable to change directory: ", &strerr_sys); + continue; + } + if ((fd =open_write("supervise/control")) == -1) { + if (errno == error_nodevice) { + if (verbose) + strerr_warn3(INFO, *dir, ": runsv not running.", 0); + dir++; + } + else + warn(*argv, ": unable to open supervise/control: ", &strerr_sys); + continue; + } + if (write(fd, "k", 1) != 1) + warn(*argv, ": unable to write to supervise/control: ", &strerr_sys); + else + strerr_warn3(INFO, *dir, ": killed.", 0); + close(fd); + dir++; + if (! *dir) _exit(111); + continue; + } + _exit(111); + } + sleep(1); + } + if (fchdir(wdir) == -1) + strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys); + close(wdir); + if (rc > 100) rc =100; + _exit(rc); +} diff --git a/runit-2.1.2/src/svwaitdown.check b/runit-2.1.2/src/svwaitdown.check new file mode 100755 index 0000000..5cf6c21 --- /dev/null +++ b/runit-2.1.2/src/svwaitdown.check @@ -0,0 +1,24 @@ +#!/bin/sh +rm -rf "${ctmp}" + +svwaitdown +echo $? +svwaitdown -V +echo $? + +mkdir "${ctmp}" +echo '#!/bin/sh' >"${ctmp}"/run +echo 'echo starting' >>"${ctmp}"/run +echo 'exec sleep 14' >>"${ctmp}"/run +chmod 700 "${ctmp}"/run +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +svwaitdown "${ctmp}" +echo $? +svwaitdown -x "${ctmp}" +echo $? +cat "${ctmp}"/supervise/stat +wait +echo $? +rm -rf "${ctmp}" diff --git a/runit-2.1.2/src/svwaitdown.dist b/runit-2.1.2/src/svwaitdown.dist new file mode 100644 index 0000000..2d83839 --- /dev/null +++ b/runit-2.1.2/src/svwaitdown.dist @@ -0,0 +1,12 @@ +usage: svwaitdown [-v] [-t 1..6000] service ... + +1 +$Id$ +usage: svwaitdown [-v] [-t 1..6000] service ... + +1 +starting +0 +0 +down +0 diff --git a/runit-2.1.2/src/svwaitup.c b/runit-2.1.2/src/svwaitup.c new file mode 100644 index 0000000..e682bbe --- /dev/null +++ b/runit-2.1.2/src/svwaitup.c @@ -0,0 +1,126 @@ +#include <unistd.h> +#include "strerr.h" +#include "error.h" +#include "sgetopt.h" +#include "scan.h" +#include "open.h" +#include "tai.h" +#include "buffer.h" +#include "fmt.h" + +#define FATAL "svwaitup: fatal: " +#define WARN "svwaitup: warning: " +#define INFO "svwaitup: " +#define USAGE " [-v] [-s 1..600] service ..." + +const char *progname; +unsigned long sec =2; +unsigned int rc =0; +const char * const *dir; + +void fatal(const char *m) { strerr_die3sys(111, FATAL, m, ": "); } +void warn(const char *s1, const char *s2, struct strerr *e) { + dir++; rc++; + strerr_warn3(WARN, s1, s2, e); +} +void usage() { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +int main(int argc, const char * const *argv) { + int opt; + int verbose =0; + char status[18]; + int fd; + int is; + int r; + int wdir; + unsigned long pid; + struct tai when; + struct tai now; + char sulong[FMT_ULONG]; + + progname =*argv; + + while ((opt =getopt(argc, argv, "s:vV")) != opteof) { + switch(opt) { + case 's': + scan_ulong(optarg, &sec); + if ((sec < 1) || (sec > 600)) usage(); + break; + case 'v': + verbose =1; + break; + case 'V': + strerr_warn1("$Id: e2d6c574c5e56f9931323fbc0e539c7f9b829b73 $", 0); + case '?': + usage(); + } + } + argv +=optind; + if (! argv || ! *argv) usage(); + + if ((wdir =open_read(".")) == -1) + fatal("unable to open current working directory"); + + dir =argv; + while (*dir) { + if (dir != argv) + if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); + if (chdir(*dir) == -1) { + warn(*dir, ": unable to change directory: ", &strerr_sys); + continue; + } + if ((fd =open_write("supervise/ok")) == -1) { + if (errno == error_nodevice) + warn(*dir, ": runsv not running.", 0); + else + warn(*dir, ": unable to open supervise/ok: ", &strerr_sys); + continue; + } + close(fd); + + if ((fd =open_read("supervise/status")) == -1) { + warn(*dir, "unable to open supervise/status: ", &strerr_sys); + continue; + } + r =buffer_unixread(fd, status, sizeof status); + close(fd); + if (r < sizeof status) { + if (r == -1) + warn(*dir, "unable to read supervise/status: ", &strerr_sys); + else + warn(*dir, ": unable to read supervise/status: bad format.", 0); + continue; + } + + pid =(unsigned char)status[15]; + pid <<=8; pid +=(unsigned char)status[14]; + pid <<=8; pid +=(unsigned char)status[13]; + pid <<=8; pid +=(unsigned char)status[12]; + if (! pid) { + warn(*dir, ": is down.", 0); + continue; + } + + tai_unpack(status, &when); + tai_now(&now); + if (tai_less(&now, &when)) when =now; + tai_sub(&when, &now, &when); + is =tai_approx(&when); + + if (is >= sec) { + /* ok */ + if (verbose) { + sulong[fmt_ulong(sulong, is)] =0; + strerr_warn5(INFO, *dir, ": is up (", sulong, " seconds)", 0); + } + dir++; + continue; + } + sleep(sec -is); + } + if (fchdir(wdir) == -1) + strerr_warn2(WARN, "unable to switch to starting directory: ", &strerr_sys); + close(wdir); + if (rc > 100) rc =100; + _exit(rc); +} diff --git a/runit-2.1.2/src/svwaitup.check b/runit-2.1.2/src/svwaitup.check new file mode 100755 index 0000000..a1be802 --- /dev/null +++ b/runit-2.1.2/src/svwaitup.check @@ -0,0 +1,28 @@ +#!/bin/sh +rm -rf "${ctmp}" + +svwaitup +echo $? +svwaitup -V +echo $? + +mkdir "${ctmp}" +echo '#!/bin/sh' >"${ctmp}"/run +echo 'echo starting' >>"${ctmp}"/run +echo 'exec sleep 14' >>"${ctmp}"/run +chmod 700 "${ctmp}"/run +runsv "${ctmp}" & +sleep 1 +test -r "${ctmp}"/supervise/stat || sleep 2 +svwaitup "${ctmp}" +echo $? +cat "${ctmp}"/supervise/stat +svwaitup -s2 "${ctmp}" +echo $? +cat "${ctmp}"/supervise/stat +runsvctrl exit "${ctmp}" +wait +echo $? +chpst -2 svwaitup -s2 "${ctmp}" +echo $? +rm -rf "${ctmp}" diff --git a/runit-2.1.2/src/svwaitup.dist b/runit-2.1.2/src/svwaitup.dist new file mode 100644 index 0000000..692990f --- /dev/null +++ b/runit-2.1.2/src/svwaitup.dist @@ -0,0 +1,14 @@ +usage: svwaitup [-v] [-s 1..600] service ... + +1 +$Id$ +usage: svwaitup [-v] [-s 1..600] service ... + +1 +starting +0 +run +0 +run +0 +1 diff --git a/runit-2.1.2/src/tai.h b/runit-2.1.2/src/tai.h new file mode 100644 index 0000000..1839f76 --- /dev/null +++ b/runit-2.1.2/src/tai.h @@ -0,0 +1,28 @@ +/* Public domain. */ + +#ifndef TAI_H +#define TAI_H + +#include "uint64.h" + +struct tai { + uint64 x; +} ; + +#define tai_unix(t,u) ((void) ((t)->x = 4611686018427387914ULL + (uint64) (u))) + +extern void tai_now(struct tai *); + +#define tai_approx(t) ((double) ((t)->x)) + +extern void tai_add(struct tai *,const struct tai *,const struct tai *); +extern void tai_sub(struct tai *,const struct tai *,const struct tai *); +#define tai_less(t,u) ((t)->x < (u)->x) + +#define TAI_PACK 8 +extern void tai_pack(char *,const struct tai *); +extern void tai_unpack(const char *,struct tai *); + +extern void tai_uint(struct tai *,unsigned int); + +#endif diff --git a/runit-2.1.2/src/tai_now.c b/runit-2.1.2/src/tai_now.c new file mode 100644 index 0000000..217ba75 --- /dev/null +++ b/runit-2.1.2/src/tai_now.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <time.h> +#include "tai.h" + +void tai_now(struct tai *t) +{ + tai_unix(t,time((time_t *) 0)); +} diff --git a/runit-2.1.2/src/tai_pack.c b/runit-2.1.2/src/tai_pack.c new file mode 100644 index 0000000..641fa5b --- /dev/null +++ b/runit-2.1.2/src/tai_pack.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "tai.h" + +void tai_pack(char *s,const struct tai *t) +{ + uint64 x; + + x = t->x; + s[7] = x & 255; x >>= 8; + s[6] = x & 255; x >>= 8; + s[5] = x & 255; x >>= 8; + s[4] = x & 255; x >>= 8; + s[3] = x & 255; x >>= 8; + s[2] = x & 255; x >>= 8; + s[1] = x & 255; x >>= 8; + s[0] = x; +} diff --git a/runit-2.1.2/src/tai_sub.c b/runit-2.1.2/src/tai_sub.c new file mode 100644 index 0000000..e891600 --- /dev/null +++ b/runit-2.1.2/src/tai_sub.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "tai.h" + +void tai_sub(struct tai *t,const struct tai *u,const struct tai *v) +{ + t->x = u->x - v->x; +} diff --git a/runit-2.1.2/src/tai_unpack.c b/runit-2.1.2/src/tai_unpack.c new file mode 100644 index 0000000..4541ff5 --- /dev/null +++ b/runit-2.1.2/src/tai_unpack.c @@ -0,0 +1,18 @@ +/* Public domain. */ + +#include "tai.h" + +void tai_unpack(const char *s,struct tai *t) +{ + uint64 x; + + x = (unsigned char) s[0]; + x <<= 8; x += (unsigned char) s[1]; + x <<= 8; x += (unsigned char) s[2]; + x <<= 8; x += (unsigned char) s[3]; + x <<= 8; x += (unsigned char) s[4]; + x <<= 8; x += (unsigned char) s[5]; + x <<= 8; x += (unsigned char) s[6]; + x <<= 8; x += (unsigned char) s[7]; + t->x = x; +} diff --git a/runit-2.1.2/src/taia.h b/runit-2.1.2/src/taia.h new file mode 100644 index 0000000..3882d1d --- /dev/null +++ b/runit-2.1.2/src/taia.h @@ -0,0 +1,36 @@ +/* Public domain. */ + +#ifndef TAIA_H +#define TAIA_H + +#include "tai.h" + +struct taia { + struct tai sec; + unsigned long nano; /* 0...999999999 */ + unsigned long atto; /* 0...999999999 */ +} ; + +extern void taia_tai(const struct taia *,struct tai *); + +extern void taia_now(struct taia *); + +extern double taia_approx(const struct taia *); +extern double taia_frac(const struct taia *); + +extern void taia_add(struct taia *,const struct taia *,const struct taia *); +extern void taia_addsec(struct taia *,const struct taia *,int); +extern void taia_sub(struct taia *,const struct taia *,const struct taia *); +extern void taia_half(struct taia *,const struct taia *); +extern int taia_less(const struct taia *,const struct taia *); + +#define TAIA_PACK 16 +extern void taia_pack(char *,const struct taia *); +extern void taia_unpack(const char *,struct taia *); + +#define TAIA_FMTFRAC 19 +extern unsigned int taia_fmtfrac(char *,const struct taia *); + +extern void taia_uint(struct taia *,unsigned int); + +#endif diff --git a/runit-2.1.2/src/taia_add.c b/runit-2.1.2/src/taia_add.c new file mode 100644 index 0000000..0ac8e6b --- /dev/null +++ b/runit-2.1.2/src/taia_add.c @@ -0,0 +1,20 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +void taia_add(struct taia *t,const struct taia *u,const struct taia *v) +{ + t->sec.x = u->sec.x + v->sec.x; + t->nano = u->nano + v->nano; + t->atto = u->atto + v->atto; + if (t->atto > 999999999UL) { + t->atto -= 1000000000UL; + ++t->nano; + } + if (t->nano > 999999999UL) { + t->nano -= 1000000000UL; + ++t->sec.x; + } +} diff --git a/runit-2.1.2/src/taia_approx.c b/runit-2.1.2/src/taia_approx.c new file mode 100644 index 0000000..c6f5f27 --- /dev/null +++ b/runit-2.1.2/src/taia_approx.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "taia.h" + +double taia_approx(const struct taia *t) +{ + return tai_approx(&t->sec) + taia_frac(t); +} diff --git a/runit-2.1.2/src/taia_frac.c b/runit-2.1.2/src/taia_frac.c new file mode 100644 index 0000000..f709f3e --- /dev/null +++ b/runit-2.1.2/src/taia_frac.c @@ -0,0 +1,8 @@ +/* Public domain. */ + +#include "taia.h" + +double taia_frac(const struct taia *t) +{ + return (t->atto * 0.000000001 + t->nano) * 0.000000001; +} diff --git a/runit-2.1.2/src/taia_less.c b/runit-2.1.2/src/taia_less.c new file mode 100644 index 0000000..18a9378 --- /dev/null +++ b/runit-2.1.2/src/taia_less.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +int taia_less(const struct taia *t,const struct taia *u) +{ + if (t->sec.x < u->sec.x) return 1; + if (t->sec.x > u->sec.x) return 0; + if (t->nano < u->nano) return 1; + if (t->nano > u->nano) return 0; + return t->atto < u->atto; +} diff --git a/runit-2.1.2/src/taia_now.c b/runit-2.1.2/src/taia_now.c new file mode 100644 index 0000000..3a951a9 --- /dev/null +++ b/runit-2.1.2/src/taia_now.c @@ -0,0 +1,15 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <time.h> +#include <sys/time.h> +#include "taia.h" + +void taia_now(struct taia *t) +{ + struct timeval now; + gettimeofday(&now,(struct timezone *) 0); + tai_unix(&t->sec,now.tv_sec); + t->nano = 1000 * now.tv_usec + 500; + t->atto = 0; +} diff --git a/runit-2.1.2/src/taia_pack.c b/runit-2.1.2/src/taia_pack.c new file mode 100644 index 0000000..9047da1 --- /dev/null +++ b/runit-2.1.2/src/taia_pack.c @@ -0,0 +1,22 @@ +/* Public domain. */ + +#include "taia.h" + +void taia_pack(char *s,const struct taia *t) +{ + unsigned long x; + + tai_pack(s,&t->sec); + s += 8; + + x = t->atto; + s[7] = x & 255; x >>= 8; + s[6] = x & 255; x >>= 8; + s[5] = x & 255; x >>= 8; + s[4] = x; + x = t->nano; + s[3] = x & 255; x >>= 8; + s[2] = x & 255; x >>= 8; + s[1] = x & 255; x >>= 8; + s[0] = x; +} diff --git a/runit-2.1.2/src/taia_sub.c b/runit-2.1.2/src/taia_sub.c new file mode 100644 index 0000000..d902e50 --- /dev/null +++ b/runit-2.1.2/src/taia_sub.c @@ -0,0 +1,23 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +void taia_sub(struct taia *t,const struct taia *u,const struct taia *v) +{ + unsigned long unano = u->nano; + unsigned long uatto = u->atto; + + t->sec.x = u->sec.x - v->sec.x; + t->nano = unano - v->nano; + t->atto = uatto - v->atto; + if (t->atto > uatto) { + t->atto += 1000000000UL; + --t->nano; + } + if (t->nano > unano) { + t->nano += 1000000000UL; + --t->sec.x; + } +} diff --git a/runit-2.1.2/src/taia_uint.c b/runit-2.1.2/src/taia_uint.c new file mode 100644 index 0000000..8b7f2d4 --- /dev/null +++ b/runit-2.1.2/src/taia_uint.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include "taia.h" + +/* XXX: breaks tai encapsulation */ + +void taia_uint(struct taia *t,unsigned int s) +{ + t->sec.x = s; + t->nano = 0; + t->atto = 0; +} diff --git a/runit-2.1.2/src/trycpp.c b/runit-2.1.2/src/trycpp.c new file mode 100644 index 0000000..e4503d4 --- /dev/null +++ b/runit-2.1.2/src/trycpp.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +int main() +{ +#ifdef NeXT + printf("nextstep\n"); exit(0); +#endif + printf("unknown\n"); exit(0); +} diff --git a/runit-2.1.2/src/trydrent.c b/runit-2.1.2/src/trydrent.c new file mode 100644 index 0000000..3333ac0 --- /dev/null +++ b/runit-2.1.2/src/trydrent.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <dirent.h> + +void foo() +{ + DIR *dir; + struct dirent *d; +} diff --git a/runit-2.1.2/src/tryflock.c b/runit-2.1.2/src/tryflock.c new file mode 100644 index 0000000..a82ffc2 --- /dev/null +++ b/runit-2.1.2/src/tryflock.c @@ -0,0 +1,10 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/file.h> +#include <fcntl.h> + +main() +{ + flock(0,LOCK_EX | LOCK_UN | LOCK_NB); +} diff --git a/runit-2.1.2/src/trymkffo.c b/runit-2.1.2/src/trymkffo.c new file mode 100644 index 0000000..9356342 --- /dev/null +++ b/runit-2.1.2/src/trymkffo.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/stat.h> + +void main() +{ + mkfifo("temp-trymkffo",0); +} diff --git a/runit-2.1.2/src/trypoll.c b/runit-2.1.2/src/trypoll.c new file mode 100644 index 0000000..6506617 --- /dev/null +++ b/runit-2.1.2/src/trypoll.c @@ -0,0 +1,20 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <fcntl.h> +#include <poll.h> + +int main() +{ + struct pollfd x; + + x.fd = open("trypoll.c",O_RDONLY); + if (x.fd == -1) _exit(111); + x.events = POLLIN; + if (poll(&x,1,10) == -1) _exit(1); + if (x.revents != POLLIN) _exit(1); + + /* XXX: try to detect and avoid poll() imitation libraries */ + + _exit(0); +} diff --git a/runit-2.1.2/src/tryreboot.c b/runit-2.1.2/src/tryreboot.c new file mode 100644 index 0000000..aefc703 --- /dev/null +++ b/runit-2.1.2/src/tryreboot.c @@ -0,0 +1,6 @@ +#include <unistd.h> +#include <sys/reboot.h> + +int main(void) { + return(reboot(0)); +} diff --git a/runit-2.1.2/src/trysgact.c b/runit-2.1.2/src/trysgact.c new file mode 100644 index 0000000..e264ef2 --- /dev/null +++ b/runit-2.1.2/src/trysgact.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <signal.h> + +main() +{ + struct sigaction sa; + sa.sa_handler = 0; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(0,&sa,(struct sigaction *) 0); +} diff --git a/runit-2.1.2/src/trysgprm.c b/runit-2.1.2/src/trysgprm.c new file mode 100644 index 0000000..a46c82c --- /dev/null +++ b/runit-2.1.2/src/trysgprm.c @@ -0,0 +1,12 @@ +/* Public domain. */ + +#include <signal.h> + +main() +{ + sigset_t ss; + + sigemptyset(&ss); + sigaddset(&ss,SIGCHLD); + sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); +} diff --git a/runit-2.1.2/src/tryshsgr.c b/runit-2.1.2/src/tryshsgr.c new file mode 100644 index 0000000..c5ed6d6 --- /dev/null +++ b/runit-2.1.2/src/tryshsgr.c @@ -0,0 +1,16 @@ +/* Public domain. */ + +int main() +{ + short x[4]; + + x[0] = x[1] = 1; + if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); + + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 1) _exit(1); + x[1] = 2; + if (getgroups(1,x) == -1) _exit(1); + if (x[1] != 2) _exit(1); + _exit(0); +} diff --git a/runit-2.1.2/src/trysocketlib.c b/runit-2.1.2/src/trysocketlib.c new file mode 100644 index 0000000..0fe5d06 --- /dev/null +++ b/runit-2.1.2/src/trysocketlib.c @@ -0,0 +1,12 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <unistd.h> + +int main(void) { + int s; + + s =socket(AF_INET, SOCK_STREAM, 0); + return(close(s)); +} diff --git a/runit-2.1.2/src/trysysel.c b/runit-2.1.2/src/trysysel.c new file mode 100644 index 0000000..5be862d --- /dev/null +++ b/runit-2.1.2/src/trysysel.c @@ -0,0 +1,11 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <time.h> +#include <sys/time.h> +#include <sys/select.h> /* SVR4 silliness */ + +void foo() +{ + ; +} diff --git a/runit-2.1.2/src/tryulong64.c b/runit-2.1.2/src/tryulong64.c new file mode 100644 index 0000000..003548a --- /dev/null +++ b/runit-2.1.2/src/tryulong64.c @@ -0,0 +1,13 @@ +/* Public domain. */ + +int main() +{ + unsigned long u; + u = 1; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; + if (!u) _exit(1); + _exit(0); +} diff --git a/runit-2.1.2/src/tryuwtmp.c b/runit-2.1.2/src/tryuwtmp.c new file mode 100644 index 0000000..2192a1e --- /dev/null +++ b/runit-2.1.2/src/tryuwtmp.c @@ -0,0 +1,9 @@ +#include <sys/types.h> +#include <utmp.h> + +struct utmp ut; + +int main(void) { + char *s =ut.ut_name; + return(0); +} diff --git a/runit-2.1.2/src/tryuwtmpx.c b/runit-2.1.2/src/tryuwtmpx.c new file mode 100644 index 0000000..d711c01 --- /dev/null +++ b/runit-2.1.2/src/tryuwtmpx.c @@ -0,0 +1,9 @@ +#include <sys/types.h> +#include <utmpx.h> + +struct futmpx ut; + +int main(void) { + char *s =ut.ut_name; + return(0); +} diff --git a/runit-2.1.2/src/trywaitp.c b/runit-2.1.2/src/trywaitp.c new file mode 100644 index 0000000..319b81f --- /dev/null +++ b/runit-2.1.2/src/trywaitp.c @@ -0,0 +1,9 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/wait.h> + +main() +{ + waitpid(0,0,0); +} diff --git a/runit-2.1.2/src/uidgid.c b/runit-2.1.2/src/uidgid.c new file mode 100644 index 0000000..befa754 --- /dev/null +++ b/runit-2.1.2/src/uidgid.c @@ -0,0 +1,74 @@ +#include <sys/types.h> +#include <pwd.h> +#include <grp.h> +#include "uidgid.h" +#include "str.h" +#include "scan.h" + +/* user */ +unsigned int uidgid_get(struct uidgid *u, char *ug) { + struct passwd *pwd =0; + + if (! (pwd =getpwnam(ug))) return(0); + u->gid[0] =pwd->pw_gid; u->gids =1; + u->uid =pwd->pw_uid; + return(1); +} + +/* uid:gid[:gid[:gid]...] */ +unsigned int uidgids_set(struct uidgid *u, char *ug) { + unsigned long id; + int i; + + if (*(ug +=scan_ulong(ug, &id)) != ':') return(0); + u->uid =(uid_t)id; + ++ug; + for (i =0; i < 60; ++i, ++ug) { + ug +=scan_ulong(ug, &id); + u->gid[i] =(gid_t)id; + if (*ug != ':') { ++i; break; } + } + u->gid[i] =0; + u->gids =i; + if (*ug) return(0); + return(1); +} + +/* [:]user[:group[:group]...] */ +unsigned int uidgids_get(struct uidgid *u, char *ug) { + char *g =0; + struct passwd *pwd =0; + struct group *gr =0; + int i, d =0; + + if (*ug == ':') return(uidgids_set(u, ug +1)); + if (ug[(d =str_chr(ug, ':'))] == ':') { + ug[d] =0; + g =ug +d +1; + } + if (! (pwd =getpwnam(ug))) { if (g) ug[d] =':'; return(0); } + u->uid =pwd->pw_uid; + if (! g) { + u->gid[0] =pwd->pw_gid; + u->gids =1; + return(1); + } + ug[d] =':'; + for (i =0; i < 60; ++i) { + if (g[(d =str_chr(g, ':'))] == ':') { + g[d] =0; + if (! (gr =getgrnam(g))) { g[d] =':'; return(0); } + g[d] =':'; + u->gid[i] =gr->gr_gid; + g +=d +1; + } + else { + if (! (gr =getgrnam(g))) return(0); + u->gid[i++] =gr->gr_gid; + break; + } + } + u->gid[i] =0; + u->gids =i; + return(1); +} diff --git a/runit-2.1.2/src/uidgid.h b/runit-2.1.2/src/uidgid.h new file mode 100644 index 0000000..13cacbc --- /dev/null +++ b/runit-2.1.2/src/uidgid.h @@ -0,0 +1,18 @@ +#ifndef UIDGID_H +#define UIDGID_H + +#include <sys/types.h> + +struct uidgid { + uid_t uid; + gid_t gid[61]; + int gids; +}; + +/* user */ +extern unsigned int uidgid_get(struct uidgid *, char *); + +/* [:]user[:group[:group]...] */ +extern unsigned int uidgids_get(struct uidgid *, char *); + +#endif diff --git a/runit-2.1.2/src/uint64.h1 b/runit-2.1.2/src/uint64.h1 new file mode 100644 index 0000000..486a380 --- /dev/null +++ b/runit-2.1.2/src/uint64.h1 @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef UINT64_H +#define UINT64_H + +/* sysdep: -ulong64 */ + +typedef unsigned long long uint64; + +#endif diff --git a/runit-2.1.2/src/uint64.h2 b/runit-2.1.2/src/uint64.h2 new file mode 100644 index 0000000..8869e43 --- /dev/null +++ b/runit-2.1.2/src/uint64.h2 @@ -0,0 +1,10 @@ +/* Public domain. */ + +#ifndef UINT64_H +#define UINT64_H + +/* sysdep: +ulong64 */ + +typedef unsigned long uint64; + +#endif diff --git a/runit-2.1.2/src/utmpset.c b/runit-2.1.2/src/utmpset.c new file mode 100644 index 0000000..eea41a5 --- /dev/null +++ b/runit-2.1.2/src/utmpset.c @@ -0,0 +1,112 @@ +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> +#include "uw_tmp.h" +#include "strerr.h" +#include "sgetopt.h" +#include "seek.h" +#include "str.h" +#include "open.h" +#include "byte.h" +#include "lock.h" + +#define USAGE " [-w] line" +#define FATAL "utmpset: fatal: " +#define WARNING "utmpset: warning: " + +const char *progname; + +void usage(void) { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } + +int utmp_logout(const char *line) { + int fd; + uw_tmp ut; + int ok =-1; + + if ((fd =open(UW_TMP_UFILE, O_RDWR, 0)) < 0) + strerr_die4sys(111, FATAL, "unable to open ", UW_TMP_UFILE, ": "); + if (lock_ex(fd) == -1) + strerr_die4sys(111, FATAL, "unable to lock: ", UW_TMP_UFILE, ": "); + + while (read(fd, &ut, sizeof(uw_tmp)) == sizeof(uw_tmp)) { + if (!ut.ut_name[0] || (str_diff(ut.ut_line, line) != 0)) continue; + memset(ut.ut_name, 0, sizeof ut.ut_name); + memset(ut.ut_host, 0, sizeof ut.ut_host); + if (time(&ut.ut_time) == -1) break; +#ifdef DEAD_PROCESS + ut.ut_type =DEAD_PROCESS; +#endif + if (lseek(fd, -(off_t)sizeof(uw_tmp), SEEK_CUR) == -1) break; + if (write(fd, &ut, sizeof(uw_tmp)) != sizeof(uw_tmp)) break; + ok =1; + break; + } + close(fd); + return(ok); +} +int wtmp_logout(const char *line) { + int fd; + int len; + struct stat st; + uw_tmp ut; + + if ((fd = open_append(UW_TMP_WFILE)) == -1) + strerr_die4sys(111, FATAL, "unable to open ", UW_TMP_WFILE, ": "); + if (lock_ex(fd) == -1) + strerr_die4sys(111, FATAL, "unable to lock ", UW_TMP_WFILE, ": "); + + if (fstat(fd, &st) == -1) { + close(fd); + return(-1); + } + memset(&ut, 0, sizeof(uw_tmp)); + if ((len =str_len(line)) > sizeof ut.ut_line) len =sizeof ut.ut_line -2; + byte_copy(ut.ut_line, len, line); + if (time(&ut.ut_time) == -1) { + close(fd); + return(-1); + } +#ifdef DEAD_PROCESS + ut.ut_type =DEAD_PROCESS; +#endif + if (write(fd, &ut, sizeof(uw_tmp)) != sizeof(uw_tmp)) { + ftruncate(fd, st.st_size); + close(fd); + return(-1); + } + close(fd); + return(1); +} + +int main (int argc, const char * const *argv, const char * const *envp) { + int opt; + int wtmp =0; + + progname =*argv; + + while ((opt =getopt(argc, argv, "wV")) != opteof) { + switch(opt) { + case 'w': + wtmp =1; + break; + case 'V': + strerr_warn1("$Id: cb399098f794012a7f5e6a3a7090b2d53b86c08c $", 0); + case '?': + usage(); + } + } + argv +=optind; + + if (! argv || ! *argv) usage(); + if (utmp_logout(*argv) == -1) + strerr_die4x(111, WARNING, "unable to logout line ", *argv, + " in utmp: no such entry"); + if (wtmp) + if (wtmp_logout(*argv) == -1) + strerr_die4sys(111, WARNING, + "unable to logout line ", *argv, " in wtmp: "); + _exit(0); +} diff --git a/runit-2.1.2/src/utmpset.check b/runit-2.1.2/src/utmpset.check new file mode 100755 index 0000000..51cf1a4 --- /dev/null +++ b/runit-2.1.2/src/utmpset.check @@ -0,0 +1,5 @@ +#!/bin/sh +utmpset +echo $? +utmpset -V +echo $? diff --git a/runit-2.1.2/src/utmpset.dist b/runit-2.1.2/src/utmpset.dist new file mode 100644 index 0000000..d5c0370 --- /dev/null +++ b/runit-2.1.2/src/utmpset.dist @@ -0,0 +1,7 @@ +usage: utmpset [-w] line + +1 +$Id: cb399098f794012a7f5e6a3a7090b2d53b86c08c $ +usage: utmpset [-w] line + +1 diff --git a/runit-2.1.2/src/uw_tmp.h1 b/runit-2.1.2/src/uw_tmp.h1 new file mode 100644 index 0000000..2d5e994 --- /dev/null +++ b/runit-2.1.2/src/uw_tmp.h1 @@ -0,0 +1,19 @@ +#include <sys/types.h> +#include <utmp.h> + +/* sysdep: -utmpx */ + +#ifdef _PATH_UTMP +#define UW_TMP_UFILE _PATH_UTMP +#define UW_TMP_WFILE _PATH_WTMP +#else +/* AIX only has UTMP_FILE */ +#ifdef UTMP_FILE +#define UW_TMP_UFILE UTMP_FILE +#define UW_TMP_WFILE WTMP_FILE +#else +#error neither _PATH_UTMP nor UTMP_FILE defined. +#endif +#endif + +typedef struct utmp uw_tmp; diff --git a/runit-2.1.2/src/uw_tmp.h2 b/runit-2.1.2/src/uw_tmp.h2 new file mode 100644 index 0000000..ae9542e --- /dev/null +++ b/runit-2.1.2/src/uw_tmp.h2 @@ -0,0 +1,13 @@ +#include <sys/types.h> +#include <utmpx.h> + +/* sysdep: +utmpx */ + +#define UW_TMP_UFILE _UTMPX_FILE +#define UW_TMP_WFILE _WTMPX_FILE + +#ifndef ut_time +#define ut_time ut_tv.tv_sec +#endif + +typedef struct futmpx uw_tmp; diff --git a/runit-2.1.2/src/wait.h b/runit-2.1.2/src/wait.h new file mode 100644 index 0000000..d294e9d --- /dev/null +++ b/runit-2.1.2/src/wait.h @@ -0,0 +1,16 @@ +/* Public domain. */ + +#ifndef WAIT_H +#define WAIT_H + +extern int wait_pid(); +extern int wait_nohang(); +extern int wait_stop(); +extern int wait_stopnohang(); + +#define wait_crashed(w) ((w) & 127) +#define wait_exitcode(w) ((w) >> 8) +#define wait_stopsig(w) ((w) >> 8) +#define wait_stopped(w) (((w) & 127) == 127) + +#endif diff --git a/runit-2.1.2/src/wait_nohang.c b/runit-2.1.2/src/wait_nohang.c new file mode 100644 index 0000000..5c9c53d --- /dev/null +++ b/runit-2.1.2/src/wait_nohang.c @@ -0,0 +1,14 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/wait.h> +#include "haswaitp.h" + +int wait_nohang(wstat) int *wstat; +{ +#ifdef HASWAITPID + return waitpid(-1,wstat,WNOHANG); +#else + return wait3(wstat,WNOHANG,(struct rusage *) 0); +#endif +} diff --git a/runit-2.1.2/src/wait_pid.c b/runit-2.1.2/src/wait_pid.c new file mode 100644 index 0000000..c2869b8 --- /dev/null +++ b/runit-2.1.2/src/wait_pid.c @@ -0,0 +1,41 @@ +/* Public domain. */ + +#include <sys/types.h> +#include <sys/wait.h> +#include "error.h" +#include "haswaitp.h" + +#ifdef HASWAITPID + +int wait_pid(wstat,pid) int *wstat; int pid; +{ + int r; + + do + r = waitpid(pid,wstat,0); + while ((r == -1) && (errno == error_intr)); + return r; +} + +#else + +/* XXX untested */ +/* XXX breaks down with more than two children */ +static int oldpid = 0; +static int oldwstat; /* defined if(oldpid) */ + +int wait_pid(wstat,pid) int *wstat; int pid; +{ + int r; + + if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } + + do { + r = wait(wstat); + if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } + } + while ((r == -1) && (errno == error_intr)); + return r; +} + +#endif diff --git a/runit-2.1.2/src/warn-auto.sh b/runit-2.1.2/src/warn-auto.sh new file mode 100644 index 0000000..36d2313 --- /dev/null +++ b/runit-2.1.2/src/warn-auto.sh @@ -0,0 +1,2 @@ +#!/bin/sh +# WARNING: This file was auto-generated. Do not edit! diff --git a/runit-2.1.2/src/warn-shsgr b/runit-2.1.2/src/warn-shsgr new file mode 100644 index 0000000..37c351e --- /dev/null +++ b/runit-2.1.2/src/warn-shsgr @@ -0,0 +1,3 @@ +Oops. Your getgroups() returned 0, and setgroups() failed; this means +that I can't reliably do my shsgr test. Please either ``make'' as root +or ``make'' while you're in one or more supplementary groups. diff --git a/runit-2.1.2/src/x86cpuid.c b/runit-2.1.2/src/x86cpuid.c new file mode 100644 index 0000000..f81c593 --- /dev/null +++ b/runit-2.1.2/src/x86cpuid.c @@ -0,0 +1,40 @@ +/* Public domain. */ + +#include <signal.h> + +void nope() +{ + exit(1); +} + +int main() +{ + unsigned long x[4]; + unsigned long y[4]; + int i; + int j; + char c; + + signal(SIGILL,nope); + + x[0] = 0; + x[1] = 0; + x[2] = 0; + x[3] = 0; + + asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) ); + if (!x[0]) return 0; + asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) ); + + for (i = 1;i < 4;++i) + for (j = 0;j < 4;++j) { + c = x[i] >> (8 * j); + if (c < 32) c = 32; + if (c > 126) c = 126; + putchar(c); + } + + printf("-%08x-%08x\n",y[0],y[3]); + + return 0; +} |