Update 'Kanzlei-Kiel'.

This commit is contained in:
2019-05-31 13:40:39 +02:00
parent 0d7da00786
commit d95848426f
1164 changed files with 41953 additions and 125 deletions

View File

@@ -0,0 +1,25 @@
Version 3.1 of qlogtools is now available at:
http://untroubled.org/qlogtools/
------------------------------------------------------------------------------
qlogtools
Log processing tools
Bruce Guenter <bruceg@em.ca>
Version 3.1
2001-06-12
This package is a set of tools that are useful in analyzing or producing
logs from qmail and other packages.
This package is Copyright(C) 2000 Bruce Guenter, and may be copied
according to the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 or a later
version. A copy of this license is included with this package. This
package comes with no warranty of any kind.
------------------------------------------------------------------------------
Changes in version 3.1
- Ignore directories named "supervise" in multipipe.
- Added "teepipe" program.
- Modified build with SPAC.
-------------------------------------------------------------------------------

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,55 @@
ANNOUNCEMENT
COPYING
FILES
Makefile
NEWS
README
TARGETS
TODO
VERSION
bool.h
choose.sh
conf-bin
conf-cc
conf-ld
conf-man
direntry.h1
direntry.h2
fork.h1
fork.h2
installer.c
installer.h
instcheck.c
insthier.c
instshow.c
multipipe.1
multipipe.c
multitail.1
multitail.c
qfilelog.1
qfilelog.c
qlogselect.1
qlogtools-3.1.spec
select.h1
select.h2
spipe.1
spipe.c
svcfns.c
svcfns.h
tai.h
tai2tai64n.1
tai2tai64n.c
tai64n2tai.1
tai64n2tai.c
tai64n_decode.c
tai64n_encode.c
tai_decode.c
tai_encode.c
teepipe.1
teepipe.c
trydirent.c
trysysel.c
trysystime.c
trytime.c
tryvfork.c
warn-auto.sh

View File

@@ -0,0 +1,141 @@
# Don't edit Makefile! Use conf-* for configuration.
#
# Generated by spac see http://untroubled.org/spac/
SHELL=/bin/sh
default: all
all: programs installer instcheck instshow
choose: warn-auto.sh choose.sh
cat warn-auto.sh choose.sh >choose
chmod 755 choose
compile: conf-cc
( echo '#!/bin/sh'; \
echo 'source=$$1; shift'; \
echo 'base=`echo "$$source" | sed -e s:\\\\.c$$::`'; \
echo exec `head -1 conf-cc` '-I. -o $${base}.o -c $$source $${1+"$$@"}'; \
) >compile
chmod 755 compile
conf_bin.c: conf-bin
head -1 conf-bin | \
sed -e 's/"/\\"/g' \
-e 's/^/const char conf_bin[] = "/' \
-e 's/$$/";/' >conf_bin.c
conf_man.c: conf-man
head -1 conf-man | \
sed -e 's/"/\\"/g' \
-e 's/^/const char conf_man[] = "/' \
-e 's/$$/";/' >conf_man.c
direntry.h: compile direntry.h1 direntry.h2 trydirent.c
( ./compile trydirent.c >/dev/null 2>&1 \
&& cat direntry.h2 || cat direntry.h1 ) > direntry.h
rm -f trydirent.o
fork.h: compile load fork.h1 fork.h2 tryvfork.c
( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null 2>&1 \
&& cat fork.h2 || cat fork.h1 ) > fork.h
rm -f tryvfork.o tryvfork
installer: load installer.o insthier.o
./load installer insthier.o
installer.o: compile installer.c installer.h
./compile installer.c
instcheck: load instcheck.o insthier.o
./load instcheck insthier.o
instcheck.o: compile instcheck.c installer.h
./compile instcheck.c
insthier.o: compile insthier.c installer.h conf_bin.c conf_man.c
./compile insthier.c
instshow: load instshow.o insthier.o
./load instshow insthier.o
instshow.o: compile instshow.c installer.h
./compile instshow.c
load: conf-ld
( echo '#!/bin/sh';\
echo 'main="$$1"; shift';\
echo exec `head -1 conf-ld` '-o "$$main" "$$main.o" $${1+"$$@"}';\
) >load
chmod 755 load
multipipe: load multipipe.o svcfns.o
./load multipipe svcfns.o
multipipe.o: compile multipipe.c select.h direntry.h bool.h svcfns.h
./compile multipipe.c
multitail: load multitail.o
./load multitail
multitail.o: compile multitail.c systime.h bool.h
./compile multitail.c
programs: spipe qfilelog multipipe tai2tai64n tai64n2tai teepipe multitail
qfilelog: load qfilelog.o
./load qfilelog
qfilelog.o: compile qfilelog.c
./compile qfilelog.c
select.h: choose compile trysysel.c select.h1 select.h2
./choose c trysysel select.h1 select.h2 > select.h
spipe: load spipe.o svcfns.o
./load spipe svcfns.o
spipe.o: compile spipe.c bool.h svcfns.h
./compile spipe.c
svcfns.o: compile svcfns.c fork.h bool.h svcfns.h
./compile svcfns.c
systime.h: compile trysystime.c trytime.c
( ( ./compile trysystime.c >/dev/null 2>&1 && \
echo '#include <sys/time.h>' ); \
( ./compile trytime.c >/dev/null 2>&1 && \
echo '#include <time.h>' ) ) >systime.h
rm -f trysystime.o trytime.o
tai2tai64n: load tai2tai64n.o tai_decode.o tai64n_encode.o
./load tai2tai64n tai_decode.o tai64n_encode.o
tai2tai64n.o: compile tai2tai64n.c tai.h bool.h
./compile tai2tai64n.c
tai64n2tai: load tai64n2tai.o tai64n_decode.o tai_encode.o
./load tai64n2tai tai64n_decode.o tai_encode.o
tai64n2tai.o: compile tai64n2tai.c tai.h bool.h
./compile tai64n2tai.c
tai64n_decode.o: compile tai64n_decode.c tai.h bool.h
./compile tai64n_decode.c
tai64n_encode.o: compile tai64n_encode.c tai.h bool.h
./compile tai64n_encode.c
tai_decode.o: compile tai_decode.c tai.h bool.h
./compile tai_decode.c
tai_encode.o: compile tai_encode.c tai.h bool.h
./compile tai_encode.c
teepipe: load teepipe.o
./load teepipe
teepipe.o: compile teepipe.c fork.h
./compile teepipe.c

View File

@@ -0,0 +1,25 @@
-------------------------------------------------------------------------------
Changes in version 3.1
- Ignore directories named "supervise" in multipipe.
- Added "teepipe" program.
- Modified build with SPAC.
-------------------------------------------------------------------------------
Changes in version 3.0
- Added a new program, "spipe", which supervises a pipeline of commands.
- Added a new program, "multipipe", which supervises a set of processes
similar to svscan, but pipes a copy of stdin to each process.
- Added a new program, "tai64n2tai", which converts tai64n timestamps to
old style tai timestamps, for use with qmail-analog.
- Added a new program, "tai2tai64n", which converts old style tai
timestamps to tai64n format, just for completeness.
- Added an option for "multitail" to seek to the end of the first file
before writing any output.
-------------------------------------------------------------------------------

View File

@@ -0,0 +1,13 @@
qlogtools
Log processing tools
Bruce Guenter <bruceg@em.ca>
Version 3.1
2001-06-12
This package is a set of tools that are useful in analyzing or producing
logs from qmail and other packages.
This package is Copyright(C) 2000 Bruce Guenter, and may be copied
according to the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 or a later
version. A copy of this license is included with this package. This
package comes with no warranty of any kind.

View File

@@ -0,0 +1,37 @@
all
choose
compile
conf_bin.c
conf_man.c
direntry.h
fork.h
installer
installer.o
instcheck
instcheck.o
insthier.o
instshow
instshow.o
load
multipipe
multipipe.o
multitail
multitail.o
programs
qfilelog
qfilelog.o
select.h
spipe
spipe.o
svcfns.o
systime.h
tai2tai64n
tai2tai64n.o
tai64n2tai
tai64n2tai.o
tai64n_decode.o
tai64n_encode.o
tai_decode.o
tai_encode.o
teepipe
teepipe.o

View File

@@ -0,0 +1 @@
qlogtools 3.1

View File

@@ -0,0 +1,8 @@
#ifndef QLOGTOOLS__BOOL__H__
#define QLOGTOOLS__BOOL__H__
typedef int bool;
#define false 0
#define true (0==0)
#endif

View File

@@ -0,0 +1,20 @@
#!/bin/sh
# WARNING: This file was auto-generated. Do not edit!
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"

View File

@@ -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"

View File

@@ -0,0 +1,4 @@
#!/bin/sh
source=$1; shift
base=`echo "$source" | sed -e s:\\\\.c$::`
exec gcc -W -Wall -O -g -I. -o ${base}.o -c $source ${1+"$@"}

View File

@@ -0,0 +1,3 @@
/usr/local/bin
Programs will be installed in this directory.

View File

@@ -0,0 +1,3 @@
gcc -W -Wall -O -g
This will be used to compile .c files.

View File

@@ -0,0 +1,3 @@
gcc -s
This will be used to link .o and .a files into an executable.

View File

@@ -0,0 +1,4 @@
/usr/local/man
Man pages will be installed in subdirectories of this directory. An
unformatted man page foo.1 will go into .../man1/foo.1.

View File

@@ -0,0 +1 @@
const char conf_bin[] = "/usr/local/bin";

View File

@@ -0,0 +1 @@
const char conf_man[] = "/usr/local/man";

View File

@@ -0,0 +1,8 @@
#ifndef DIRENTRY_H
#define DIRENTRY_H
#include <sys/types.h>
#include <dirent.h>
#define direntry struct dirent
#endif

View File

@@ -0,0 +1,8 @@
#ifndef DIRENTRY_H
#define DIRENTRY_H
#include <sys/types.h>
#include <sys/dir.h>
#define direntry struct direct
#endif

View File

@@ -0,0 +1,8 @@
#ifndef DIRENTRY_H
#define DIRENTRY_H
#include <sys/types.h>
#include <dirent.h>
#define direntry struct dirent
#endif

View File

@@ -0,0 +1,7 @@
#ifndef FORK_H
#define FORK_H
extern int fork();
extern int vfork();
#endif

View File

@@ -0,0 +1,7 @@
#ifndef FORK_H
#define FORK_H
extern int fork();
#define vfork fork
#endif

View File

@@ -0,0 +1,7 @@
#ifndef FORK_H
#define FORK_H
extern int fork();
extern int vfork();
#endif

Binary file not shown.

View File

@@ -0,0 +1,103 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "installer.h"
static int sourcedir;
static char buffer[4096];
static void diesys(const char* msg)
{
fprintf(stderr, "installer error: %s:\n %s\n", msg,
strerror(errno));
exit(1);
}
static void diefsys(const char* msg, const char* filename)
{
fprintf(stderr, "installer error: %s '%s':\n %s\n", msg, filename,
strerror(errno));
exit(1);
}
static void setmodes(const char* filename,
unsigned uid, unsigned gid, unsigned mode)
{
if (chown(filename, uid, gid) == -1)
diefsys("Could not set owner or group for", filename);
if (chmod(filename, mode) == -1)
diefsys("Could not set mode for", filename);
}
void c(int dir, const char* subdir, const char* filename,
unsigned uid, unsigned gid, unsigned mode)
{
int fdin;
int fdout;
size_t rd;
size_t wr;
size_t offset;
if (fchdir(sourcedir) == -1)
diesys("Could not change base directory");
if ((fdin = open(filename, O_RDONLY)) == -1)
diefsys("Could not open input file", filename);
if (fchdir(dir) == -1)
diesys("Could not change base directory");
if (subdir && chdir(subdir) == -1)
diefsys("Could not change directory to", subdir);
if ((fdout = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) == -1)
diefsys("Could not create output file", filename);
while ((rd = read(fdin, buffer, sizeof buffer)) != 0) {
if (rd == (unsigned)-1) diefsys("Error reading from input file", filename);
for (offset = 0; offset < rd; offset += wr) {
if ((wr = write(fdout, buffer+offset, rd-offset)) == (unsigned)-1)
diefsys("Error writing to output file", filename);
}
}
if (close(fdout) == -1) diefsys("Error closing output file", filename);
close(fdin);
setmodes(filename, uid, gid, mode);
}
void d(int dir, const char* subdir,
unsigned uid, unsigned gid, unsigned mode)
{
if (fchdir(dir) == -1)
diesys("Could not change base directory");
if (mkdir(subdir, 0700) == -1 && errno != EEXIST)
diefsys("Could not create directory", subdir);
setmodes(subdir, uid, gid, mode);
}
int opendir(const char* dir)
{
int fd;
if (chdir(dir) == -1)
diefsys("Could not change directory to", dir);
if ((fd = open(".", O_RDONLY)) == -1)
diefsys("Could not open directory", dir);
return fd;
}
int opensubdir(int dir, const char* subdir)
{
if (fchdir(dir) == -1)
diesys("Could not change base directory in opensubdir");
return opendir(subdir);
}
int main(void)
{
sourcedir = opendir(".");
umask(077);
insthier();
return 0;
}

View File

@@ -0,0 +1,13 @@
#ifndef SPAC__INSTALLER__H__
#define SPAC__INSTALLER__H__
int opendir(const char* dir);
int opensubdir(int dir, const char* subdir);
void d(int dir, const char* subdir,
unsigned uid, unsigned gid, unsigned mode);
void c(int dir, const char* subdir, const char* file,
unsigned uid, unsigned gid, unsigned mode);
extern void insthier(void);
#endif

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,90 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "installer.h"
static struct stat statbuf;
int bin;
int man;
static void diesys(const char* msg)
{
fprintf(stderr, "installer error: %s:\n %s\n", msg,
sys_errlist[errno]);
exit(1);
}
static void diefsys(const char* msg, const char* filename)
{
fprintf(stderr, "installer error: %s '%s':\n %s\n", msg, filename,
sys_errlist[errno]);
exit(1);
}
static void warn(const char* subdir, const char* filename, const char* msg)
{
printf("instcheck warning: File '%s%s%s' %s.\n",
subdir ? subdir : "", subdir ? "/" : "", filename, msg);
}
static void testmode(int dir, const char* subdir, const char* filename,
unsigned uid, unsigned gid, unsigned mode, unsigned type)
{
if (fchdir(dir) == -1)
diesys("Could not change base directory");
if (subdir && chdir(subdir) == -1)
return;
if (stat(filename, &statbuf) == -1) {
if (errno == ENOENT)
warn(subdir, filename, "is missing");
else
diefsys("Could not stat file", filename);
}
if ((statbuf.st_mode & S_IFMT) != type)
warn(subdir, filename, "is the wrong type of file");
if (uid != (unsigned)-1 && statbuf.st_uid != uid)
warn(subdir, filename, "has wrong owner");
if (gid != (unsigned)-1 && statbuf.st_gid != gid)
warn(subdir, filename, "has wrong group");
if ((statbuf.st_mode & 07777) != mode)
warn(subdir, filename, "has wrong permissions");
}
void c(int dir, const char* subdir, const char* filename,
unsigned uid, unsigned gid, unsigned mode)
{
testmode(dir, subdir, filename, uid, gid, mode, S_IFREG);
}
void d(int dir, const char* subdir,
unsigned uid, unsigned gid, unsigned mode)
{
testmode(dir, 0, subdir, uid, gid, mode, S_IFDIR);
}
int opendir(const char* dir)
{
int fd;
if (chdir(dir) == -1)
diefsys("Could not change directory to", dir);
if ((fd = open(".", O_RDONLY)) == -1)
diefsys("Could not open directory", dir);
return fd;
}
int opensubdir(int dir, const char* subdir)
{
if (fchdir(dir) == -1)
diesys("Could not change base directory in opensubdir");
return opendir(subdir);
}
int main(void)
{
insthier();
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,27 @@
#include "installer.h"
#include "conf_bin.c"
#include "conf_man.c"
void insthier(void) {
int bin = opendir(conf_bin);
int man = opendir(conf_man);
int man1;
c(bin, 0, "multipipe", -1, -1, 0755);
c(bin, 0, "multitail", -1, -1, 0755);
c(bin, 0, "qfilelog", -1, -1, 0755);
c(bin, 0, "spipe", -1, -1, 0755);
c(bin, 0, "tai2tai64n", -1, -1, 0755);
c(bin, 0, "tai64n2tai", -1, -1, 0755);
c(bin, 0, "teepipe", -1, -1, 0755);
d(man, "man1", -1, -1, 0755);
man1 = opensubdir(man, "man1");
c(man1, 0, "multipipe.1", -1, -1, 0644);
c(man1, 0, "multitail.1", -1, -1, 0644);
c(man1, 0, "qfilelog.1", -1, -1, 0644);
c(man1, 0, "spipe.1", -1, -1, 0644);
c(man1, 0, "tai2tai64n.1", -1, -1, 0644);
c(man1, 0, "tai64n2tai.1", -1, -1, 0644);
c(man1, 0, "teepipe.1", -1, -1, 0644);
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,98 @@
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "installer.h"
#define DENTRY_SLOTS 16
static const char* dentries[DENTRY_SLOTS] = {0};
static int last_dentry = 0;
static void showmode(char type, unsigned mode)
{
putchar(type);
putchar((mode & 0400) ? 'r' : '-');
putchar((mode & 0200) ? 'w' : '-');
putchar((mode & 0100) ?
(mode & 04000) ? 's' : 'x' :
(mode & 04000) ? 'S' : '-');
putchar((mode & 040) ? 'r' : '-');
putchar((mode & 020) ? 'w' : '-');
putchar((mode & 010) ?
(mode & 02000) ? 's' : 'x' :
(mode & 02000) ? 'S' : '-');
putchar((mode & 04) ? 'r' : '-');
putchar((mode & 02) ? 'w' : '-');
putchar((mode & 01) ?
(mode & 01000) ? 't' : 'x' :
(mode & 01000) ? 'T' : '-');
}
static void show(char type,
int dir, const char* subdir, const char* filename,
unsigned uid, unsigned gid, unsigned mode)
{
showmode(type, mode);
if (uid == (unsigned)-1) fputs(" N/A", stdout);
else printf(" %8d", uid);
if (gid == (unsigned)-1) fputs(" N/A", stdout);
else printf(" %8d", gid);
putchar(' ');
fputs(dentries[dir], stdout);
putchar('/');
if (subdir) {
fputs(subdir, stdout);
putchar('/');
}
puts(filename);
}
void c(int dir, const char* subdir, const char* filename,
unsigned uid, unsigned gid, unsigned mode)
{
show('-', dir, subdir, filename, uid, gid, mode);
}
void d(int dir, const char* subdir,
unsigned uid, unsigned gid, unsigned mode)
{
show('d', dir, 0, subdir, uid, gid, mode);
}
int opendir(const char* dir)
{
if (last_dentry >= DENTRY_SLOTS) {
fputs("instshow: error: Too many open directories!\n", stderr);
exit(1);
}
dentries[last_dentry] = strdup(dir);
return last_dentry++;
}
int opensubdir(int dir, const char* subdir)
{
char* str;
if (last_dentry >= DENTRY_SLOTS) {
fputs("instshow: error: Too many open directories!\n", stderr);
exit(1);
}
str = malloc(strlen(dentries[dir])+1+strlen(subdir)+1);
strcpy(str, dentries[dir]);
strcat(str, "/");
strcat(str, subdir);
dentries[last_dentry] = str;
return last_dentry++;
}
int main(void)
{
puts(" type/mode owner group path");
insthier();
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,3 @@
#!/bin/sh
main="$1"; shift
exec gcc -s -o "$main" "$main.o" ${1+"$@"}

Binary file not shown.

View File

@@ -0,0 +1,44 @@
.TH multipipe 1
.SH NAME
multipipe \- supervise an pipeline of commands
.SH SYNOPSIS
.B multipipe
.I [ directory ]
.SH DESCRIPTION
.B multipipe
starts one supervise process for each subdirectory of the current
directory.
.B multipipe
skips subdirectory names starting with dots.
Each supervised processes is piped a copy of standard input sent to
.BR multipipe .
.P
Every five seconds,
.B multipipe
checks for subdirectories again.
If it sees a new subdirectory, it starts a new supervise process.
If a subdirectory is removed, it closes the pipe to that supervise
process.
Directory named
.I supervise
or with names starting with a period are ignored.
.P
If
.B multipipe
is given a command-line argument, it switches to that directory when it
starts.
.P
If
.B multipipe
is sent either the
.IR INT ,
.IR QUIT ,
or the
.I TERM
signal, or it reaches end of file on standard input, it runs
.B svc -dx
on each command to shut it down, and waits for it to exit.
.SH RETURN VALUE
Exits 0 when all the commands are shut down.
.SH SEE ALSO
supervise, svscan

View File

@@ -0,0 +1,346 @@
/* multipipe -- pipe output to multiple programs
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "select.h"
#include "direntry.h"
#include "bool.h"
#include "svcfns.h"
void err(const char* msg)
{
write(2, "multipipe: Error: ", 18);
write(2, msg, strlen(msg));
write(2, "\n", 1);
}
void err2(const char* msg1, const char* msg2)
{
write(2, "multipipe: Error: ", 18);
write(2, msg1, strlen(msg1));
write(2, msg2, strlen(msg2));
write(2, "\n", 1);
}
void set_ndelay(int fd)
{
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#define BUFSIZE 8192
static char buffer[BUFSIZE];
static unsigned buf_start = 0;
static unsigned buf_end = 0;
static bool buf_eof = false;
#define buf_wrapped (buf_end < buf_start)
#define buf_left (buf_start-buf_end + (buf_wrapped ? -1 : BUFSIZE-1))
#define buf_len (buf_end-buf_start + (buf_wrapped ? BUFSIZE : 0))
struct reader
{
ino_t inode;
const char* name;
pid_t pid;
int fd;
unsigned buf_pos;
bool marked;
struct reader* next;
};
static struct reader* readers = 0;
void reset_buf_start(void)
{
struct reader* reader;
bool wrapped = (buf_end < buf_start);
buf_start = buf_end;
for(reader = readers; reader; reader = reader->next) {
unsigned bp = reader->buf_pos;
if(bp < buf_start && (!wrapped || bp >= buf_end))
buf_start = bp;
}
if(buf_start == buf_end) {
buf_end = buf_start = 0;
for(reader = readers; reader; reader = reader->next)
reader->buf_pos = 0;
}
}
void read_input(void)
{
unsigned readable = buf_wrapped ? buf_left : BUFSIZE-buf_end;
ssize_t rd;
if(readable >= buf_left)
readable = buf_left;
rd = read(FD_STDIN, buffer+buf_end, readable);
if(rd <= 0)
buf_eof = true;
else
buf_end = (buf_end + rd) % BUFSIZE;
}
void write_output(struct reader* reader)
{
unsigned writable = buf_wrapped ? BUFSIZE-buf_end : buf_len;
ssize_t wr = write(reader->fd, buffer+reader->buf_pos, writable);
if(wr > 0) {
reader->buf_pos = (reader->buf_pos + wr) % BUFSIZE;
reset_buf_start();
}
}
void add_reader(const char* name, ino_t inode)
{
struct reader* r = malloc(sizeof(struct reader));
r->name = strdup(name);
r->inode = inode;
r->pid = 0;
r->fd = -1;
r->buf_pos = buf_end;
r->next = readers;
readers = r;
}
bool del_reader(pid_t pid)
{
struct reader* curr = readers;
struct reader* prev = 0;
while(curr) {
struct reader* next = curr->next;
if(curr->pid == pid) {
if(prev)
prev->next = next;
else
readers = next;
free((char*)curr->name);
free(curr);
return true;
}
prev = curr;
curr = next;
}
return false;
}
void start_reader(struct reader* reader)
{
int fd[2];
if(pipe(fd)) {
err2("Could not create pipe to reader ", reader->name);
return;
}
reader->pid = start_supervise(reader->name, fd[0], FD_STDOUT);
close(fd[0]);
reader->fd = fd[1];
set_ndelay(reader->fd);
}
void stop_reader(struct reader* reader)
{
stop_supervise(reader->name, reader->pid);
}
void stop_readers(void)
{
struct reader* reader;
for(reader = readers; reader; reader = reader->next)
stop_reader(reader);
}
void reap_children(void)
{
pid_t pid;
int status;
while((pid = waitpid(0, &status, WNOHANG)) > 0) {
if(!del_reader(pid))
err("Caught exit of unknown process");
}
}
void scan_dirs(void)
{
direntry* entry;
DIR* dir = opendir(".");
struct reader* reader;
struct reader* prev;
if(!dir) {
err("Unable to read directory");
return;
}
/* Clear all the marked flags */
for(reader = readers; reader; reader = reader->next)
reader->marked = false;
/* For each directory entry, mark the corresponding reader.
* If a matching reader is not found, make one. */
while((entry = readdir(dir)) != 0) {
struct stat statbuf;
if(entry->d_name[0] == '.' || !strcmp(entry->d_name, "supervise"))
continue;
if(stat(entry->d_name, &statbuf))
continue;
if(!S_ISDIR(statbuf.st_mode))
continue;
for(reader = readers; reader; reader = reader->next)
if(reader->inode == statbuf.st_ino) {
reader->marked = true;
break;
}
if(!reader) {
add_reader(entry->d_name, statbuf.st_ino);
start_reader(readers);
readers->marked = true;
}
}
closedir(dir);
reap_children();
/* Clean up any reader that was removed from the directory */
prev = 0;
reader = readers;
while(reader) {
struct reader* next = reader->next;
if(!reader->marked) {
/* Don't stop it, since the directory is no longer there */
/* stop_reader(reader); */
if(prev)
prev->next = next;
else
readers = next;
close(reader->fd);
free((char*)reader->name);
free(reader);
}
prev = reader;
reader = next;
}
}
#define EVENT_INTR 0
#define EVENT_ALRM 1
static int selfpipe[2];
void read_event(void)
{
char buf[1];
if(read(selfpipe[0], buf, 1) != 1)
return;
switch(buf[0]) {
case EVENT_INTR:
buf_eof = true;
break;
case EVENT_ALRM:
scan_dirs();
alarm(5);
break;
default:
err("Unknown event sent to self?!?");
}
}
void write_event(int event)
{
char buf[1];
buf[0] = event;
if(write(selfpipe[1], buf, 1) != 1)
err("Could not send event to self");
}
void handle_signal(int sig)
{
int event;
switch(sig) {
case SIGALRM: event = EVENT_ALRM; break;
default: event = EVENT_INTR; break;
}
write_event(event);
}
void main_loop(void)
{
for(;;) {
struct reader* reader;
fd_set readfds;
fd_set writefds;
int fdmax = selfpipe[0];
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(selfpipe[0], &readfds);
if(buf_eof) {
if(buf_start == buf_end)
return;
}
else if(buf_left)
FD_SET(FD_STDIN, &readfds);
for(reader = readers; reader; reader = reader->next) {
if(reader->buf_pos != buf_end) {
int fd = reader->fd;
FD_SET(fd, &writefds);
if(fd > fdmax)
fdmax = fd;
}
}
if(select(fdmax+1, &readfds, &writefds, 0, 0) == -1)
continue;
/* If an event arrived, skip all other I/O */
if(FD_ISSET(selfpipe[0], &readfds)) {
read_event();
continue;
}
if(FD_ISSET(FD_STDIN, &readfds))
read_input();
for(reader = readers; reader; reader = reader->next)
if(FD_ISSET(reader->fd, &writefds))
write_output(reader);
}
}
int main(int argc, char** argv)
{
if(argc > 1 && chdir(argv[1]) != 0) {
err2("Couldn't chdir to ", argv[1]);
return 1;
}
if(pipe(selfpipe)) {
err("Couldn't create self pipe");
return 1;
}
scan_dirs();
signal(SIGALRM, handle_signal);
signal(SIGINT, handle_signal);
signal(SIGTERM, handle_signal);
signal(SIGQUIT, handle_signal);
alarm(5);
set_ndelay(FD_STDIN);
main_loop();
stop_readers();
return 0;
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,47 @@
.TH multitail 1
.SH NAME
multitail \- watch output sent to a file
.SH SYNOPSIS
.B multitail
[
.B \-E
] [
.B \-e
]
.I filename
.SH DESCRIPTION
.B multitail
opens the named file for reading, and outputs data appended to the
file as it grows.
If a new file is put in place of the original filename, the original
file is closed and the file is reopened.
.SH OPTIONS
.TP
.B \-E
Seek to the end of file before producing any output from the original
file.
This is the default.
.TP
.B \-e
Do not seek to the end of file before producing any output.
This will cause the entire file to be output.
.SH SEE ALSO
multilog, tail(1)
.SH NOTES
This program is useful for watching output written to the
.I current
log file produced by
.BR multitail .
.P
.B multitail
is very similar to GNU
.BR tail .
An equivalent command would be:
.EX
tail -n -0 --follow=name FILENAME
.EE
.SH RESTRICTIONS
.B multitail
can't count lines or bytes from the beginning or end of the file.
If you need these features, download and install GNU textutils.

View File

@@ -0,0 +1,140 @@
/* multitail -- Watch the output from a utility such as multilog
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "systime.h"
#include "bool.h"
#define BLKSZ 4096
const int FD_STDIN = 0;
const int FD_STDOUT = 1;
const int FD_STDERR = 2;
void print(const char* msg)
{
write(FD_STDERR, msg, strlen(msg));
}
void warn(const char* msg)
{
print("multitail: ");
print(msg);
print("!\n");
}
void die(const char* msg)
{
warn(msg);
exit(1);
}
void warn2(const char* msg1, const char* msg2)
{
print("multitail: ");
print(msg1);
print(msg2);
print("!\n");
}
void usage(const char* error)
{
if(error)
warn(error);
print("Usage: multitail [-Ee] filename\n"
" -E Seek to end of file before output (default)\n"
" -e Do not seek to end of file before output\n");
exit(1);
}
static const char* opt_filename;
static bool opt_seek_end = true;
void parse_args(int argc, char** argv)
{
int ch;
while((ch = getopt(argc, argv, "Ee")) != -1){
switch(ch) {
case 'E': opt_seek_end = true; break;
case 'e': opt_seek_end = false; break;
default: usage(0);
}
}
if(optind+1 != argc)
usage("Must include exactly one filename");
opt_filename = argv[optind];
}
void copy(int fd)
{
char buf[BLKSZ];
ssize_t rd;
while((rd = read(fd, buf, BLKSZ)) != 0) {
if(rd == -1)
die("Could not read from file");
while(rd) {
ssize_t wr = write(FD_STDOUT, buf, rd);
if(wr == -1)
die("Could not write to stdout");
rd -= wr;
}
}
}
void multitail(void)
{
int fd = 0;
ino_t inode = 0;
bool first = true;
for(;; sleep(1)) {
struct stat buf;
if(!fd) {
while((fd = open(opt_filename, O_RDONLY)) == -1) {
warn("Could not open file, sleeping for one minute");
sleep(60);
}
if(first && opt_seek_end) {
if(lseek(fd, 0, SEEK_END) == -1)
die("Could not seek to end of file");
first = false;
}
fstat(fd, &buf);
inode = buf.st_ino;
}
copy(fd);
if(stat(opt_filename, &buf) == -1)
warn("Could not stat file");
else if(buf.st_ino != inode) {
close(fd);
fd = 0;
}
}
}
int main(int argc, char* argv[])
{
parse_args(argc, argv);
multitail();
return 1;
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,25 @@
.TH qfilelog 1
.SH NAME
qfilelog \- log messages to a single file
.SH SYNOPSIS
.B qfilelog
.I filename
.SH DESCRIPTION
.B qfilelog
appends from standard input to a single named file.
If
.B qfilelog
is sent the
.I HUP
signal, it syncs, closes, and re-opens the output file.
.SH RETURN VALUE
Exits 0 when it successfully reaches end-of-file on standard input.
Otherwise it exits 1 after printing an error diagnostic to standard
error.
.SH SEE ALSO
cyclog(1),
splogger(8)
.SH NOTES
If any of the write operations fail,
.B qfilelog
prints a warning to standard error and pauses for 60 seconds.

View File

@@ -0,0 +1,129 @@
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#define PAUSE sleep(60)
void errmsg(const char* m)
{
write(2, m, strlen(m));
}
void warn_sys(const char* m)
{
errmsg("qfilelog: warning: ");
errmsg(m);
errmsg(": ");
errmsg(strerror(errno));
errmsg("\n");
}
void warn(const char* m)
{
errmsg("qfilelog: warning: ");
errmsg(m);
errmsg(".\n");
}
void fatal(const char* m)
{
errmsg("qfilelog: fatal error: ");
errmsg(m);
errmsg("\n");
exit(1);
}
#define BUFSIZE 4096
static int fd;
static char* filename;
static char buf[BUFSIZE];
ssize_t do_read(void)
{
ssize_t rd = read(0, buf, BUFSIZE);
if(rd == -1)
rd = 0;
return rd;
}
void do_write(ssize_t rd)
{
ssize_t offset = 0;
ssize_t wr;
while(offset < rd) {
wr = write(fd, buf+offset, rd-offset);
if(wr == -1) {
warn_sys("Can't write, pausing");
PAUSE;
}
else
offset += wr;
}
}
void do_close(void)
{
if(fd >= 0) {
while(fsync(fd) == -1) {
warn_sys("Error syncing the file, pausing");
PAUSE;
}
while(close(fd) == -1) {
warn_sys("Error closing the file, pausing");
PAUSE;
}
}
}
void do_open(void)
{
do {
fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0666);
if(fd == -1) {
warn_sys("Error opening the output file, pausing");
PAUSE;
}
} while(fd == -1);
}
void loop(void)
{
ssize_t rd;
for(;;) {
rd = do_read();
if(rd)
do_write(rd);
}
}
void catch_hup(int flag)
{
signal(SIGHUP, catch_hup);
do_close();
do_open();
}
void catch_int(int flag)
{
do_close();
exit(0);
}
int main(int argc, char* argv[])
{
if(argc < 2) {
fatal("usage: filelog filename\n");
return 1;
}
filename = argv[1];
signal(SIGHUP, catch_hup);
signal(SIGINT, catch_int);
signal(SIGTERM, catch_int);
fd = -1;
do_open();
loop();
return 0; /* Never reached! */
}

Binary file not shown.

View File

@@ -0,0 +1,46 @@
.TH qlogselect 1
.SH NAME
qlogselect \- selectively copy entries from a qmail log file
.SH SYNOPSIS
.B qlogselect
.I [from PATTERN]
.I [start TIME]
.I [end TIME]
.I [stripstatus]
.I [addstatus]
.SH DESCRIPTION
This program selectively copies entries from a qmail log file on
standard input to standard output.
All times must be expressed either as year-month-day,
or as the number of seconds since the Unix epoch (January 1, 1970).
.SH OPTIONS
.TP
.I from PATTERN
Only output messages that have a envelope sender address that matches
.IR PATTERN .
.TP
.I start TIME
Only output lines that are stamped with a time that is on or after the
named time.
.TP
.I end TIME
Only output lines that are stamped with a time that is before the
named time.
.TP
.I stripstatus
Strip all the status lines from the input.
.TP
.I addstatus
Recalculate and insert status lines.
.SH EXAMPLES
To show all the messages sent from the mailing list owner at
vger.rutgers.edu:
.EX
qlogselect from owner-.*-outgoing@vger.rutgers.edu
.EE
.SH SEE ALSO
accustamp(1),
qmail(7),
splogger(8)

View File

@@ -0,0 +1,42 @@
Name: qlogtools
Summary: Log processing tools
Version: 3.1
Release: 1
Copyright: GPL
Group: Utilities/System
Source: qlogtools-3.1.tar.gz
BuildRoot: %{_tmppath}/qlogtools
Packager: Bruce Guenter <bruceg@em.ca>
Requires: daemontools
%description
This package is a set of tools that are useful in analyzing or producing
logs from qmail and other packages.
%prep
%setup
%build
echo %{_bindir} >conf-bin
echo %{_mandir} >conf-man
echo gcc $CFLAGS >conf-cc
echo gcc -s >conf-ld
make
%install
rm -fr %{buildroot}
mkdir -p %{buildroot}{%{_bindir},%{_mandir}}
echo %{buildroot}%{_bindir} >conf-bin
echo %{buildroot}%{_mandir} >conf-man
rm conf_bin.c conf_man.c insthier.o installer instcheck
make installer instcheck
./installer
./instcheck
%clean
rm -rf %{buildroot}
%files
%defattr(-,root,root)
%{_bindir}*
%{_mandir}/man1/*

View File

@@ -0,0 +1,11 @@
#ifndef SELECT_H
#define SELECT_H
/* sysdep: +sysselect */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
extern int select();
#endif

View File

@@ -0,0 +1,10 @@
#ifndef SELECT_H
#define SELECT_H
/* sysdep: -sysselect */
#include <sys/types.h>
#include <sys/time.h>
extern int select();
#endif

View File

@@ -0,0 +1,11 @@
#ifndef SELECT_H
#define SELECT_H
/* sysdep: +sysselect */
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>
extern int select();
#endif

Binary file not shown.

View File

@@ -0,0 +1,33 @@
.TH spipe 1
.SH NAME
spipe \- supervise an pipeline of commands
.SH SYNOPSIS
.B spipe
.I dir1 dir2 ...
.SH DESCRIPTION
.B spipe
is designed for the purpose of allowing supervise to manage a complete
pipeline of commands.
.B spipe
executes supervise on all of the named directories, inserting a pipe
between each pair of supervised processes.
The supervise processes are started from last to first, to ensure that
each producer of output has a consumer to pipe its data to.
If
.B spipe
is sent either the
.IR INT ,
.IR QUIT ,
or the
.I TERM
signal, it runs
.B svc -dx
on each command to shut it down, and waits for it to exit.
The processes are shut down from first to last, to ensure that each
producer stops writing its output before shutting down the corresponding
consumer.
.SH RETURN VALUE
Exits 0 when all the commands are shut down.
If a fatal error is encountered, it exits.
.SH SEE ALSO
supervise, svscan

View File

@@ -0,0 +1,132 @@
/* spipe -- supervise a pipeline of programs
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "bool.h"
#include "svcfns.h"
static unsigned part_count;
static pid_t* part_pids;
static int selfpipe[2];
static const char** part_names;
void err(const char* msg)
{
fputs("spipe: Error: ", stderr);
fputs(msg, stderr);
fputc('\n', stderr);
}
void die(const char* msg)
{
err(msg);
exit(1);
}
bool is_pipe(const char* p)
{
return p[0] == '|' && p[1] == 0;
}
void usage(const char* msg)
{
if(msg)
err(msg);
fputs("usage: spipe dir1 dir2 ...\n", stderr);
exit(1);
}
void parse_args(int argc, char** argv)
{
--argc, ++argv;
if(argc <= 0)
usage("Too few command-line arguments");
part_count = argc;
part_names = (const char**)argv;
part_pids = calloc(part_count, sizeof(pid_t));
memset(part_pids, 0, sizeof(pid_t) * part_count);
if(pipe(selfpipe))
die("Could not create self pipe");
}
void stop_parts()
{
unsigned i;
for(i = 0; i < part_count; i++)
if(part_pids[i])
stop_supervise(part_names[i], part_pids[i]);
}
void start_parts()
{
int fdout = FD_STDOUT;
int fdout_next = -1;
unsigned i;
for(i = part_count; i > 0; i--) {
int fdin = FD_STDIN;
if(i > 1) {
int p[2];
if(pipe(p)) {
die("Could not create pipe");
stop_parts();
exit(1);
}
fdin = p[0];
fdout_next = p[1];
}
if(!start_supervise(part_names[i-1], fdin, fdout)) {
stop_parts();
exit(1);
}
close(fdout);
close(fdin);
fdout = fdout_next;
}
}
void handle_intr(int sig)
{
write(selfpipe[1], "", 1);
}
void mainloop()
{
char buf[1];
signal(SIGINT, handle_intr);
signal(SIGQUIT, handle_intr);
signal(SIGTERM, handle_intr);
read(selfpipe[0], buf, 1);
stop_parts();
exit(0);
}
int main(int argc, char** argv)
{
parse_args(argc, argv);
start_parts();
mainloop();
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,99 @@
/* spipe -- supervise a pipeline of programs
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "fork.h"
#include "bool.h"
#include "svcfns.h"
void exec_supervise(const char* dir, int fdin, int fdout)
{
if(fdin != FD_STDIN) {
close(FD_STDIN);
dup2(fdin, FD_STDIN);
close(fdin);
}
if(fdout != FD_STDOUT) {
close(FD_STDOUT);
dup2(fdout, FD_STDOUT);
close(fdout);
}
execlp("supervise", "supervise", dir, 0);
err("Could not exec supervise");
exit(1);
}
pid_t start_supervise(const char* dir, int fdin, int fdout)
{
pid_t pid = fork();
switch(pid) {
case -1:
err("fork() failed while trying to run supervise");
return 0;
case 0:
exec_supervise(dir, fdin, fdout);
default:
return pid;
}
}
bool stop_supervise(const char* dir, pid_t svcpid)
{
int status;
pid_t pid = fork();
if(pid == -1) {
err("fork failed while trying to run svc");
return false;
}
if(pid == 0) {
execlp("svc", "svc", "-dx", dir, 0);
err("exec of svc failed");
return false;
}
while(waitpid(pid, &status, WUNTRACED) != pid) {
if(errno != EINTR) {
err("Could not wait for svc to exit");
return false;
}
}
if(!WIFEXITED(status)) {
err("svc crashed");
return false;
}
if(WEXITSTATUS(status)) {
err("svc failed");
return false;
}
while(waitpid(svcpid, &status, WUNTRACED) != svcpid)
if(errno != EINTR) {
err("Could not wait for supervise to exit");
return false;
}
if(!WIFEXITED(status)) {
err("supervise crashed");
return false;
}
if(WEXITSTATUS(status)) {
err("supervise failed");
return false;
}
return true;
}

View File

@@ -0,0 +1,16 @@
#ifndef SVC_FNS__H__
#define SVC_FNS__H__
#define FD_STDIN 0
#define FD_STDOUT 1
#define FD_STDERR 2
#include <sys/types.h>
void exec_supervise(const char* dir, int fdin, int fdout);
pid_t start_supervise(const char* dir, int fdin, int fdout);
int stop_supervise(const char* dir, pid_t svcpid);
/* Required external functions */
extern void err(const char* msg);
#endif

Binary file not shown.

View File

@@ -0,0 +1,2 @@
#include <sys/time.h>
#include <time.h>

View File

@@ -0,0 +1,19 @@
#ifndef QLOGTOOLS__TAI__H__
#define QLOGTOOLS__TAI__H__
#include "bool.h"
struct tai
{
unsigned long seconds;
unsigned long nanoseconds;
};
typedef struct tai tai;
tai* tai64n_decode(const char* str, const char** endptr);
bool tai64n_encode(const tai* t, char* buf);
tai* tai_decode(const char* str, const char** endptr);
bool tai_encode(const tai* t, char* buf);
#endif

Binary file not shown.

View File

@@ -0,0 +1,17 @@
.TH tai2tai64n 1
.SH NAME
tai2tai64n \- convert TAI timestamps to TAI64N
.SH SYNOPSIS
.B tai2tai64n
.SH DESCRIPTION
.B tai2tai64n
reads lines from standard input.
If a line does not begin with a TAI label,
.B tai2tai64n
writes it out without change.
Otherwise,
.B tai2tai64n
converts the timestamp to TAI64N format, and writes out the
converted timestamp followed by the rest of the original line.
.SH SEE ALSO
multilog, qmail-analog, tai64n, tai64nlocal, tai64n2tai

View File

@@ -0,0 +1,38 @@
/* tai2tai64n -- Convert older TAI format timestamps to TAI64N
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "tai.h"
int main()
{
char buf[4096];
while(fgets(buf, 4096, stdin)) {
const char* ptr = 0;
tai* t = tai_decode(buf, &ptr);
if(ptr) {
char tmp[32];
tai64n_encode(t, tmp);
fputs(tmp, stdout);
fputs(ptr, stdout);
}
else
fputs(buf, stdout);
fflush(stdout);
}
return 0;
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,18 @@
.TH tai64n2tai 1
.SH NAME
tai64n2tai \- convert TAI64N timestamps to TAI
.SH SYNOPSIS
.B tai64n2tai
.SH DESCRIPTION
.B tai64n2tai
reads lines from standard input.
If a line does not begin with a TAI64N label,
.B tai64n2tai
writes it out without change.
Otherwise,
.B tai64n2tai
converts the timestamp to TAI format, and writes out the
converted timestamp followed by the rest of the original line.
The older TAI format is used by some older programs such as qmail-analog.
.SH SEE ALSO
multilog, qmail-analog, tai64n, tai64nlocal, tai2tai64n

View File

@@ -0,0 +1,38 @@
/* tai64n2tai -- Convert TAI64N timestamps to older TAI format
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "tai.h"
int main()
{
char buf[4096];
while(fgets(buf, 4096, stdin)) {
const char* ptr = 0;
tai* t = tai64n_decode(buf, &ptr);
if(ptr) {
/* tai is 20 bytes, tai64n is 25 */
tai_encode(t, buf);
fputs(buf, stdout);
fputs(ptr, stdout);
}
else
fputs(buf, stdout);
fflush(stdout);
}
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,44 @@
#include "tai.h"
static int hex2int(char c)
{
if(c >= '0' && c <= '9')
return c - '0';
if(c >= 'A' && c <= 'F')
return c - 'A' + 10;
if(c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1;
}
tai* tai64n_decode(const char* str, const char** endptr)
{
static struct tai t;
if(*str++ != '@')
return 0;
/* Check if the line is within range */
if(str[0] != '4' || str[1] != '0' || str[2] != '0' || str[3] != '0' ||
str[4] != '0' || str[5] != '0' || str[6] != '0' || str[7] != '0')
return 0;
t.seconds =
hex2int(str[8]) << 28 |
hex2int(str[9]) << 24 |
hex2int(str[10]) << 20 |
hex2int(str[11]) << 16 |
hex2int(str[12]) << 12 |
hex2int(str[13]) << 8 |
hex2int(str[14]) << 4 |
hex2int(str[15]);
t.nanoseconds =
hex2int(str[16]) << 28 |
hex2int(str[17]) << 24 |
hex2int(str[18]) << 20 |
hex2int(str[19]) << 16 |
hex2int(str[20]) << 12 |
hex2int(str[21]) << 8 |
hex2int(str[22]) << 4 |
hex2int(str[23]);
if(endptr)
*endptr = str + 24;
return &t;
}

Binary file not shown.

View File

@@ -0,0 +1,38 @@
#include "tai.h"
static char INT2HEX[16] = "0123456789abcdef";
#define int2hex(X) INT2HEX[(X)&0xf]
bool tai64n_encode(const tai* t, char* buf)
{
unsigned long n = t->nanoseconds;
unsigned long s = t->seconds;
char* ptr = buf + 1+8+8+8+1;
*--ptr = 0;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n); n >>= 4;
*--ptr = int2hex(n);
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s); s >>= 4;
*--ptr = int2hex(s);
*--ptr = '0';
*--ptr = '0';
*--ptr = '0';
*--ptr = '0';
*--ptr = '0';
*--ptr = '0';
*--ptr = '0';
*--ptr = '4';
*--ptr = '@';
return true;
}

Binary file not shown.

View File

@@ -0,0 +1,23 @@
#include "tai.h"
static bool isdigit(char ch)
{
return ch >= '0' && ch <= '9';
}
tai* tai_decode(const char* str, const char** endptr)
{
static tai t;
t.seconds = 0;
t.nanoseconds = 0;
while(isdigit(*str))
t.seconds = (t.seconds * 10) + (*str++ - '0');
if(*str == '.') {
++str;
while(isdigit(*str))
t.nanoseconds = (t.nanoseconds * 10) + (*str++ - '0');
}
if(endptr)
*endptr = str;
return &t;
}

Binary file not shown.

View File

@@ -0,0 +1,19 @@
#include "tai.h"
bool tai_encode(const tai* t, char* buf)
{
unsigned long s = t->seconds;
unsigned long n = t->nanoseconds;
int i;
for(i = 9; i >= 0; i--) {
buf[i] = '0' + s % 10;
s /= 10;
}
buf[10] = '.';
for(i = 19; i >= 11; i--) {
buf[i] = '0' + n % 10;
n /= 10;
}
buf[20] = 0;
return true;
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,21 @@
.TH teepipe 1
.SH NAME
teepipe \- copy stdin to a program and stdout
.SH SYNOPSIS
.B teepipe
.I program
[
.I args ...
]
.SH DESCRIPTION
.B teepipe
starts a pipeline to the program named on the command line, and copies
standard input to both the pipe and to standard output.
Standard output of the executed program is redirected to standard error.
If an error occurs while writing to either the pipeline or standard
output, the other is closed and
.B teepipe
exits.
.SH RETURN VALUE
Exits 0 if all data from standard input was successfully copied to both
the pipe and standard output.

View File

@@ -0,0 +1,93 @@
/* teepipe -- tee output to both stdout and a program
* Copyright (C) 2000 Bruce Guenter <bruceg@em.ca>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "fork.h"
void err(const char* msg)
{
write(2, "teepipe: Error: ", 16);
write(2, msg, strlen(msg));
write(2, "\n", 1);
exit(1);
}
void err2(const char* msg1, const char* msg2)
{
write(2, "teepipe: Error: ", 16);
write(2, msg1, strlen(msg1));
write(2, msg2, strlen(msg2));
write(2, "\n", 1);
exit(1);
}
#define BUFSIZE 4096
void main_loop(int fd)
{
for(;;) {
char buf[BUFSIZE];
ssize_t rd = read(0, buf, BUFSIZE);
if(rd == 0 || rd == -1)
break;
if(write(fd, buf, rd) != rd)
err("Error writing to program");
if(write(1, buf, rd) != rd)
err("Error writing to standard output");
}
}
void exec_child(char** argv, int fd[2])
{
if(close(fd[1]) || close(0) ||
dup2(fd[0], 0) || close(fd[0]))
err("Error setting up pipe as standard input");
if(close(1) || dup2(2, 1) != 1)
err("Error setting up standard output");
execvp(argv[0], argv);
err2("Error executing", argv[0]);
}
int main(int argc, char** argv)
{
int fd[2];
int status;
pid_t pid;
if(argc < 2)
err("usage: teepipe program [args ...]");
if(pipe(fd) == -1)
err("Could not create pipe");
pid = fork();
if(pid == -1)
err("Could not fork");
if(!pid)
exec_child(argv+1, fd);
signal(SIGPIPE, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
close(fd[0]);
main_loop(fd[1]);
if(close(fd[1]))
err("Error closing output pipe");
if(waitpid(pid, &status, 0) != pid)
err("Error waiting for program to exit");
return WIFEXITED(status) ? WEXITSTATUS(status) : 255;
}

Binary file not shown.

View File

@@ -0,0 +1,8 @@
#include <sys/types.h>
#include <dirent.h>
void foo()
{
DIR *dir;
struct dirent *d;
}

View File

@@ -0,0 +1,8 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h> /* SVR4 silliness */
void foo()
{
;
}

View File

@@ -0,0 +1 @@
#include <sys/time.h>

View File

@@ -0,0 +1 @@
#include <time.h>

View File

@@ -0,0 +1,4 @@
void main()
{
vfork();
}

View File

@@ -0,0 +1,2 @@
#!/bin/sh
# WARNING: This file was auto-generated. Do not edit!