2688 lines
95 KiB
Bash
2688 lines
95 KiB
Bash
#!/bin/sh
|
|
# This is a shell archive (produced by shar 3.49)
|
|
# To extract the files from this archive, save it to a file, remove
|
|
# everything above the "!/bin/sh" line above, and type "sh file_name".
|
|
#
|
|
# made 04/17/1994 02:21 UTC by ian@comton.airs.com
|
|
# Source directory /disk4/ian
|
|
#
|
|
# existing files will NOT be overwritten unless -c is specified
|
|
#
|
|
# This shar contains:
|
|
# length mode name
|
|
# ------ ---------- ------------------------------------------
|
|
# 2602 -r--r--r-- uupoll/Makefile
|
|
# 3636 -r--r--r-- uupoll/README
|
|
# 4718 -r--r--r-- uupoll/autopoll.8c
|
|
# 44031 -r--r--r-- uupoll/autopoll.c
|
|
# 3884 -r--r--r-- uupoll/conf.h
|
|
# 4787 -r--r--r-- uupoll/uupoll.8c
|
|
# 27587 -r--r--r-- uupoll/uupoll.c
|
|
#
|
|
# ============= uupoll/Makefile ==============
|
|
if test ! -d 'uupoll'; then
|
|
echo 'x - creating directory uupoll'
|
|
mkdir 'uupoll'
|
|
fi
|
|
if test -f 'uupoll/Makefile' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/Makefile (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/Makefile (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/Makefile' &&
|
|
# This is the Makefile for uupoll and autopoll
|
|
# borrowed and hacked from Taylor UUCP 1.04
|
|
X
|
|
# Prefix directory for installation directories.
|
|
prefix = /usr/local
|
|
X
|
|
# The user name/group that should own the resulting executables.
|
|
# Both should run suid.
|
|
owner = uucp.daemon
|
|
X
|
|
# Which mode should the resulting executables have.
|
|
emode = 4111
|
|
X
|
|
# Where to install autopoll. This definition requires $(prefix)/lib to exist.
|
|
lbindir = $(prefix)/lib/uucp
|
|
X
|
|
# Where are the sources from uucp-Taylor uucp.h, uuconf.h, policy.h.
|
|
# the following assumes that our sources are in uucp-1.05/contrib/uupoll
|
|
# and the required .h files are in main directory for uucp-1.05
|
|
uucpsrcs = ../../
|
|
X
|
|
# Where to install uupoll
|
|
bbindir = $(prefix)/bin
|
|
X
|
|
# Where to install man pages. Section 8 for daemons.
|
|
man8dir = $(prefix)/man/man8
|
|
man8ext = .8c
|
|
X
|
|
# Define programs and flags
|
|
CC = gcc
|
|
CFLAGS = -O2
|
|
LDFLAGS = -s
|
|
LIBS =
|
|
X
|
|
INSTALL = /usr/bin/install -c
|
|
INSTALL_PROGRAM = $(INSTALL)
|
|
INSTALL_DATA = $(INSTALL) -m 644
|
|
X
|
|
#
|
|
# Nothing else to configure
|
|
#
|
|
X
|
|
SHELL = /bin/sh
|
|
X
|
|
VERSION = 1.00
|
|
X
|
|
MORECFLAGS = -I. -I$(uucpsrcs) -Wall
|
|
X
|
|
PROGRAMS = uupoll autopoll
|
|
X
|
|
UUPOLLOBJS = uupoll.o
|
|
AUTOOBJS = autopoll.o
|
|
X
|
|
ALLOBJS = uupoll.o autopoll.o
|
|
X
|
|
all: $(PROGRAMS)
|
|
X
|
|
install: $(PROGRAMS)
|
|
X if test -d $(lbindir); then true; else mkdir $(lbindir); fi
|
|
X if test -d $(bbindir); then true; else mkdir $(bbindir); fi
|
|
X -if test -f $(lbindir)/autopoll.old; then rm -f $(lbindir)/autopoll; else mv $(lbindir)/autopoll $(lbindir)/autopoll.old; fi
|
|
X -if test -f $(bbindir)/uupoll.old; then rm -f $(bbindir)/uupoll; else mv $(bbindir)/uupoll $(bbindir)/uupoll.old; fi
|
|
X $(INSTALL_PROGRAM) autopoll $(lbindir)/autopoll
|
|
X $(INSTALL_PROGRAM) uupoll $(bbindir)/uupoll
|
|
X chown $(owner) $(lbindir)/autopoll $(bbindir)/uupoll
|
|
X chmod $(emode) $(lbindir)/autopoll $(bbindir)/uupoll
|
|
X $(INSTALL_DATA) uupoll.8c $(man8dir)/uupoll$(man8ext)
|
|
X $(INSTALL_DATA) autopoll.8c $(man8dir)/autopoll$(man8ext)
|
|
X
|
|
uninstall:
|
|
X rm -f $(lbindir)/autopoll $(bbindir)/uupoll
|
|
X rm -f $(man8dir)/autopoll$(man8ext) $(man8dir)/uupoll$(man8ext)
|
|
X -cp $(lbindir)/autopoll.old $(lbindir)/autopoll
|
|
X -cp $(bbindir)/uupoll.old $(bbindir)/uupoll
|
|
X -chown $(owner) $(lbindir)/autopoll $(bbindir)/uupoll
|
|
X -chmod $(emode) $(lbindir)/autopoll $(bbindir)/uupoll
|
|
X
|
|
uupoll: $(UUPOLLOBJS)
|
|
X $(CC) $(LDFLAGS) -o uupoll $(UUPOLLOBJS) $(LIBS)
|
|
X
|
|
autopoll: $(AUTOOBJS)
|
|
X $(CC) $(LDFLAGS) -o autopoll $(AUTOOBJS) $(LIBS)
|
|
X
|
|
.c.o:
|
|
X $(CC) -c $(CFLAGS) $(MORECFLAGS) $<
|
|
X
|
|
X
|
|
clean:
|
|
X rm -f $(ALLOBJS) $(PROGRAMS)
|
|
X
|
|
mostlyclean: clean
|
|
X
|
|
TAGS:
|
|
X etags *.h *.c
|
|
X
|
|
# Header file dependencies. These are maintained by hand.
|
|
X
|
|
$(ALLOBJS): conf.h
|
|
X
|
|
.NOEXPORT:
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/Makefile ||
|
|
echo 'restore of uupoll/Makefile failed'
|
|
Wc_c="`wc -c < 'uupoll/Makefile'`"
|
|
test 2602 -eq "$Wc_c" ||
|
|
echo 'uupoll/Makefile: original size 2602, current size' "$Wc_c"
|
|
fi
|
|
# ============= uupoll/README ==============
|
|
if test -f 'uupoll/README' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/README (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/README (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/README' &&
|
|
X
|
|
The package consists of the following files:
|
|
X
|
|
X - autopoll.c
|
|
X - autopoll.8c
|
|
X - conf.h
|
|
X - Makefile
|
|
X - README
|
|
X - uupoll.c
|
|
X - uupoll.8c
|
|
X
|
|
CAVEAT:
|
|
uupoll as well as autopoll are created, tested and run on
|
|
a NeXT running NeXTstep 2.1+ only! Autopoll will take the same arguments
|
|
as uucico and may well work with them the same way uucico works but it
|
|
has only been tested to call uucico with the options:
|
|
X
|
|
X -s<site> -S<site> -f -r1 -C -D (as well as the long form of these options)
|
|
X
|
|
so far. All options given to autopoll will be passed verbatim to uucico.
|
|
X
|
|
DESCRIPTION:
|
|
The program uupoll was created to be a full replacement for the vendor
|
|
supplied one on a NeXT computer. That uupoll checked any site name against
|
|
the "hardwired" L.sys and did end with a "Bus error" if the site could not
|
|
be found. There was no source available to modify so it had to be created
|
|
from scratch.
|
|
The program autopoll has no equivalent an the NeXT. The intentions behind
|
|
it was to automate the task of rescheduling any failed call. It may be
|
|
started by an entry in the crontab tables in just the same way uucico is
|
|
started (it will start uucico):
|
|
X
|
|
05 5 * * * uucp /usr/local/lib/uucp/autopoll -r1 >>/tmp/poll.log 2>&1
|
|
X
|
|
Any messages go to stderr or a file (if compiled with that option); in case
|
|
the file could not be opened it will use stdout to tell you just that and quit.
|
|
To catch any output one may place the string
|
|
X
|
|
X >>/tmp/poll.log 2>&1
|
|
X
|
|
into the command line as well. Uupoll as well as autopoll will place only
|
|
a start message into the logfiles in case they are invoked manually from
|
|
the shell.
|
|
If the call fails autopoll will reschedule uucico for a later time by means
|
|
of an AT job.
|
|
The messages given by uupoll and autopoll carry an indicator to inform about
|
|
the nature of an error; they are:
|
|
X
|
|
- (I) informal message; such as ".. started" ".. ended".
|
|
- (W) there might be an error but the program decided to go ahead.
|
|
X The exit code will be at least 4.
|
|
- (E) a severe error was encountered that either aborts the whole run or
|
|
X only the task for one site will be aborted.
|
|
X The exit code will be at least 8.
|
|
- (C) a catastrophic error has been found such as unable to fork. The run
|
|
X is aborted.
|
|
X The exit code will be at least 16.
|
|
The final message will show the exit code the programm has terminated with.
|
|
X
|
|
For more information see the man pages or look into the source.
|
|
X
|
|
INSTALLATION:
|
|
all files should be placed in one folder. Then examine and change the files
|
|
Makefile and conf.h to meet your needs. To compile uupoll some files of
|
|
uucp must be available (see Makefile: uucpsrcs)
|
|
If not already there change to the directory which contain the files and type:
|
|
X
|
|
make
|
|
X
|
|
this should compile UUPOLL and AUTOPOLL. There should only be a warning
|
|
that rcsid is defined but not used.
|
|
Before actually installing you should test the programs to be working as
|
|
desired.
|
|
Then check the Makefile for the final placement of the modules and the man
|
|
pages. Make sure the ownership and setuid is what you need on your machine
|
|
to run the program(s).
|
|
Then su to root and type:
|
|
X
|
|
make install
|
|
X
|
|
which should install the above programs and the man pages in the appropriate
|
|
directories.
|
|
Some word on the coding: have mercy! This is my second project in 'C'; any
|
|
suggestions that may improve the style/coding are welcome however.
|
|
X
|
|
In case of any problems that can't be solved feel free to contact the
|
|
author at:
|
|
X
|
|
Klaus Dahlenburg Timezone : GMT + 2
|
|
P.O.Box 1267 email : kdburg@incoahe.hanse.de
|
|
D-21249 Tostedt Fax : +49 4287 676
|
|
X Germany Voice : +49 4287 681
|
|
X
|
|
Have fun!
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/README ||
|
|
echo 'restore of uupoll/README failed'
|
|
Wc_c="`wc -c < 'uupoll/README'`"
|
|
test 3636 -eq "$Wc_c" ||
|
|
echo 'uupoll/README: original size 3636, current size' "$Wc_c"
|
|
fi
|
|
# ============= uupoll/autopoll.8c ==============
|
|
if test -f 'uupoll/autopoll.8c' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/autopoll.8c (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/autopoll.8c (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/autopoll.8c' &&
|
|
.\"
|
|
.\" @(#)autopoll.8c 1.4 (incoahe) 5/09/1993
|
|
.\"
|
|
.TH AUTOPOLL 8C "May 09, 1993"
|
|
.UC 6
|
|
.SH NAME
|
|
autopoll \- automatic \s-1UUCP\s+1 file transfer supervisor
|
|
.SH SYNOPSIS
|
|
.B autopoll
|
|
[
|
|
.BI options
|
|
]
|
|
.SH DESCRIPTION
|
|
file transfer requests placed by
|
|
.IR uucp (1)
|
|
or
|
|
.IR uux (1)
|
|
are handled by
|
|
.IR uucico (8C).
|
|
.IR uucico
|
|
will be invoked immediately by the above programs unless the \-r
|
|
option is given which queues the request for later processing. This
|
|
is typically done by entries in the
|
|
.IR crontab
|
|
table(s) which will invoke
|
|
.IR uucico.
|
|
.IR uucico
|
|
can also be invoked by
|
|
.IR uupoll (8C).
|
|
All methods have in common that there is no automatic retry by
|
|
.IR uucico
|
|
itself in case the call failed for some reason.
|
|
Either manual
|
|
intervention or some sort of scripts must be used to overcome this
|
|
limitation.
|
|
.PP
|
|
.IR Autopoll
|
|
can be used to automate up to a certain degree the task of rescheduling
|
|
a call. None of the standard programs already mentioned need to be
|
|
modified to get this working. Also not recommended (see BUGS section)
|
|
.IR uucico
|
|
may be an alias to
|
|
.IR autopoll
|
|
as all arguments passed to
|
|
.IR autopoll
|
|
will be copied verbatim to
|
|
.IR uucico.
|
|
In case this is done by link or other means the original
|
|
.I uucio
|
|
must still be available in a directory outside of the normal search path
|
|
otherwise
|
|
.I autopoll
|
|
can't do what it's intended to do and will form a loop.
|
|
.PP
|
|
When
|
|
.IR autopoll
|
|
is called thre will be a check on the \-s, \-S and \-f option to
|
|
see whether this
|
|
is a specific call or not. Also the \-S and the \-f option must be checked
|
|
to determine the type of call: honor any imposed wait for a site or not.
|
|
Any call to ourself or to an unknown site will be refused. The known sites
|
|
will be obtained by a call to
|
|
.IR uuname(1).
|
|
All other options will not be checked in any way. Next to this
|
|
.IR uucico
|
|
is called and the exit code is checked for a `1' which indicates that the call
|
|
failed for some reason whatsoever. A `0' exit code will be interpreted as
|
|
a success and
|
|
.IR autopoll
|
|
ends immediate. If the call seems to be unsuccessful a new call is scheduled
|
|
for any site whose .Status files have a retry period greater than 0. The
|
|
retry will be scheduled by means of placing an
|
|
.IR at
|
|
job at the time of the failing call plus any wait time given. For those
|
|
sites that have been called with either the \-f or \-S option the retry
|
|
time will be the time of the failing call plus 120 seconds.
|
|
.PP
|
|
In case the time calculated from the values found in a \.Status file is
|
|
lower than the current time, the current time plus 60 seconds will be taken
|
|
as the retry time.
|
|
.PP
|
|
A site will
|
|
.IR not
|
|
be automatically called again if one of the following
|
|
conditions is met:
|
|
.PP
|
|
\-
|
|
.IR uucico
|
|
is terminated by a signal
|
|
.PP
|
|
\- either fork() or exec() failed
|
|
.PP
|
|
\- the
|
|
.IR at
|
|
command failed for any reasons.
|
|
.PP
|
|
\- if no wait should be honored and the retry time is found to be zero.
|
|
(this may indicate a `Wrong time to call' condition.
|
|
.PP
|
|
There are other circumstances that may lead to not reschedule a call or
|
|
not to call
|
|
.IR uucico
|
|
at all, all of which should be accompanied by (a) self explanatory message(s).
|
|
.SH BUGS
|
|
\- invalid options will make
|
|
.IR uucico
|
|
fail. The exit code for this type is the same as for any other failure; this
|
|
can reschedule the call over and over again or never.
|
|
.PP
|
|
\-
|
|
.IR autopoll
|
|
may not work as expected when called with options other than \-r1, \-s,
|
|
\-S or \-f.
|
|
.PP
|
|
\- a rescheduled call may fail with `wrong time to call' the second time
|
|
but will be rescheduled again. The times to call won't be checked by
|
|
.IR autopoll
|
|
and the .Status file may not indicate this in case the \-c option is given.
|
|
.PP
|
|
\- in case the ..._DIR points to an invalid file a `Bus error' my pop up
|
|
during the `exec' call.
|
|
.PP
|
|
\- the `chat-timeout' value may have to be increased when using
|
|
.IR autopoll.
|
|
An indication to do that is that the call fails short after `CONNECT'
|
|
has been received with `Time out in chat script'.
|
|
.PP
|
|
\- the site names given will be checked aginst the output of
|
|
.I uuname
|
|
without any alias expansion done.
|
|
.PP
|
|
\- the text strings whithin the \.Status files will not be used to detect
|
|
a failing call.
|
|
.SH FILES
|
|
.nf
|
|
/usr/local/lib/uucp UUCP internal utilities
|
|
/usr/lib/uucp
|
|
/usr/local/bin UUCP internal utilities
|
|
/usr/bin
|
|
/usr/spool/uucp/.Status/ Status files for each site
|
|
/usr/spool/uucp/ UUCP spool area. one of its sub-
|
|
X directories will hold the null jobs.
|
|
/tmp/poll.log This file is present only if autopoll
|
|
X has been compiled to place the messages
|
|
X into a file. Otherwise all messages will
|
|
X go to stderr. The directory as well as
|
|
X the name may be different.
|
|
.fi
|
|
.SH SEE ALSO
|
|
uucp(1C), uux(1C), uucico(8C), uupoll(8C), uuname(1C), sort(1), uniq(1),
|
|
at(1)
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/autopoll.8c ||
|
|
echo 'restore of uupoll/autopoll.8c failed'
|
|
Wc_c="`wc -c < 'uupoll/autopoll.8c'`"
|
|
test 4718 -eq "$Wc_c" ||
|
|
echo 'uupoll/autopoll.8c: original size 4718, current size' "$Wc_c"
|
|
fi
|
|
# ============= uupoll/autopoll.c ==============
|
|
if test -f 'uupoll/autopoll.c' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/autopoll.c (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/autopoll.c (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/autopoll.c' &&
|
|
/* ---------------------------------------------------------------------------*
|
|
X
|
|
X Name: autopoll
|
|
X
|
|
X Author: Klaus Dahlenburg <kdburg@incoahe.hanse.de>
|
|
X
|
|
X Status: Public domain
|
|
X
|
|
X Copyright: none; claiming it to be your work will adversly affect
|
|
X your image to be a good programmer.
|
|
X
|
|
X Function: Autopoll may be called just as uucico is called. The difference
|
|
X is that autopoll will call uucico and if the return code is
|
|
X not zero a check is made on the status files to see which site's
|
|
X call failed. Those sites will be called again at that time found
|
|
X in the status file plus any imposed wait. The next call will be
|
|
X scheduled via an at job which in turn is handled by cron.
|
|
X Atrun depends on the scheduling granularity of cron so the
|
|
X actual times may be later than planned.
|
|
X Autopoll will check the options -f and -s (-S) as well as the name
|
|
X of the site passed. All other options will be passed unchecked.
|
|
X The -f and -S options will indicate to autopoll that any wait
|
|
X to call a site should be ignored; if the call fails the next
|
|
X call to those sites will be at the current time plus 120 secs.
|
|
X When the time found plus any wait evaluates to a time that
|
|
X passed already the next call will be the current time plus 60
|
|
X secs. The name of the site if given must be a valid one and not
|
|
X the host itself otherwise it will be ignored.
|
|
X
|
|
X Call: autopoll [ options ]
|
|
X
|
|
X all option that apply to uucico may be given and
|
|
X will be passed verbatim. See man uucico(8).
|
|
X
|
|
X Environment: NeXT 2.1+, Taylor UUCP-1.04+
|
|
X
|
|
X I/O: stdin: unused.
|
|
X stdout: used only when ALOG_DIR is defined and the file
|
|
X can't be opened. It will be a single message to tell
|
|
X just that and the run is aborted.
|
|
X stderr: all messages go here.
|
|
X If ALOG_DIR is defined (see conf.h) all messages will
|
|
X be appended to a file autopoll.msglog in that
|
|
X directory; the file will be created automatically if
|
|
X necessary; a redirection is then no longer possible.
|
|
X Needs access to .Status files (see Comments later on).
|
|
X
|
|
X Called Programs: sort, uniq, uucico, uuname, at
|
|
X
|
|
X Compile: no special options are needed. Compiled with gcc 2.3.3 -O2.
|
|
X Compile with the supplied cc might produce erroneous code
|
|
X for the check options switch case 's' code: the break inside
|
|
X the first if (..) {... break} is ignored.
|
|
X
|
|
X Comments: - should run setuid UUCP or whatever userid is necessary to
|
|
X access (RDONLY) the .Status files and to run the programs
|
|
X named under "Called Programs" above.
|
|
X - No alias expansion is done on the given names for the
|
|
X check against uuname's output..
|
|
X - Invalid arguments will yield in an exit code > 0 as do
|
|
X "normal" failures. It may therefore happen that a site
|
|
X is called at the intervals with the same invalid arguments.
|
|
X - "Wrong time to call" is not handled properly and may
|
|
X call the site at the intervals until the time ban is lifted.
|
|
X - human action is necessary as we can't distinguish between
|
|
X "normal" failures and "errors" such as wrong password,
|
|
X number to dial etc. The logs should be checked periodically.
|
|
X - if CICO_DIR points to a non existent program the run may
|
|
X end with signal 10: Bus Error.
|
|
X - is has been observed that uucico will time out with "Dial
|
|
X failed" when called via autopoll; setting chat-timeout to
|
|
X value of 40 cured that problem.
|
|
X - no rescheduling is done in case uucico fails and this
|
|
X is not reported in the .Status file, one should check
|
|
X the uucico log; this is to the fact that autopoll will
|
|
X not scan the uucico log.
|
|
*/
|
|
X
|
|
X
|
|
#if !defined(lint)
|
|
static char rcsid[] = "$Id: autopoll.c,v 2.8 1994/04/14 17:22:54 kdburg Rel $";
|
|
#endif /* not lint */
|
|
X
|
|
/* $Log: autopoll.c,v $
|
|
X * Revision 2.8 1994/04/14 17:22:54 kdburg
|
|
X * corrected misspelled AT_OPTION
|
|
X *
|
|
X * Revision 2.7 1994/04/11 20:15:48 kdburg
|
|
X * major rework done; honor now some of the new option taht came with
|
|
X * uucp-1.05
|
|
X *
|
|
X * Revision 2.6 1994/03/26 17:40:30 kdburg
|
|
X * added support for UNAME_DIR; cleanup of some code; adjusted code after
|
|
X * obtaining sitenames via popen()
|
|
X *
|
|
X * Revision 2.5 1993/07/07 16:49:02 kdburg
|
|
X * when used interactivly only the start msg is put into the msg-log
|
|
X * so far defined (UULOG)
|
|
X *
|
|
X * Revision 2.4 1993/06/26 16:17:51 kdburg
|
|
X * the -S option wasn't propagated to the command passed to the at pgm
|
|
X *
|
|
X * Revision 2.3 1993/05/25 12:05:01 kdburg
|
|
X * added error check on gettimeofday; added comment in the note section;
|
|
X * minor changes not affection code
|
|
X *
|
|
X * Revision 2.2 1993/05/17 20:47:05 kdburg
|
|
X * execution of at cmd also ok always said failed...
|
|
X *
|
|
X * Revision 2.1 1993/05/16 21:49:13 kdburg
|
|
X * changed exit() to _exit() in case the exec fails within child
|
|
X *
|
|
X * Revision 2.0 1993/05/16 14:12:05 kdburg
|
|
X * initial revision
|
|
X * */
|
|
X
|
|
#define CAT 16
|
|
#define SEVERE 8
|
|
#define WARNING 4
|
|
#define OK 0
|
|
/* Boolean types */
|
|
typedef int bool;
|
|
#undef TRUE
|
|
#undef FALSE
|
|
#define TRUE (1)
|
|
#define FALSE (0)
|
|
X
|
|
#include "conf.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <pwd.h>
|
|
#include <unistd.h>
|
|
#include <sys/file.h>
|
|
#include <sys/time.h>
|
|
#include <sys/param.h>
|
|
#include <sys/wait.h>
|
|
X
|
|
#ifdef ALOG_FILE
|
|
X static char Msg_Log[] = ALOG_FILE; /* name of msglog filename */
|
|
#endif
|
|
X
|
|
#ifdef UNAME_DIR
|
|
X static char subcmd[] = " | sort | uniq"; /* pipe that follows uuname */
|
|
#else /* ! UNAME_DIR */
|
|
X static char Sort[] = "uuname | sort | uniq"; /* default to obtain site names */
|
|
#endif /*UNAME_DIR */
|
|
X
|
|
#ifdef AT_OPTION
|
|
X static char at_opt[] = AT_OPTION;
|
|
#else
|
|
X static char at_opt[] = "-mc";
|
|
#endif /* AT_OPTION */
|
|
X
|
|
static char at_cmd[] = "at";
|
|
static char cGrade[] = DEF_GRADE; /* grade as defined in conf.h */
|
|
static char dGrade[] = "A"; /* use this if DEF_GRADE is invalid */
|
|
static char Auto_Dir[] = AUTO_DIR; /* we live here */
|
|
static char Cico_Dir[] = CICO_DIR; /* here lives cico */
|
|
X
|
|
struct Sites {
|
|
X char name[MAXHOSTNAMELEN+1]; /* name of site as supplied by uuname */
|
|
X char grade[1]; /* as passed or defaulted */
|
|
X bool flag; /* TRUE: call this site only */
|
|
X bool force; /* TRUE: -S or -f option given */
|
|
X int stat_code;
|
|
X int stat_retries;
|
|
X long stat_lastcall;
|
|
X long stat_delay;
|
|
X char *stat_errtext;
|
|
};
|
|
X struct Common_Stor {
|
|
X int maxtab; /* high-water-mark for site tab */
|
|
X int Single_Site_Tab; /* entry into site tab for a site */
|
|
X /* passed via -s or -S option */
|
|
X bool force_any; /* TRUE: -f option without site */
|
|
X bool one_site; /* TRUE: call for a specific site */
|
|
X bool nodetach; /* TRUE: -D or --nodetach found */
|
|
X bool ifwork; /* TRUE: -C or --ifwork found */
|
|
X char *Grade; /* use this as grade for calls */
|
|
X char *Poll_Pgm; /* our name without path */
|
|
X char *called_as; /* but called by this name */
|
|
X int our_pid; /* our process-id */
|
|
X char *Uucico; /* cico's name without path */
|
|
X char This_Site[MAXHOSTNAMELEN+1]; /* our site name */
|
|
X char Single_Site[MAXHOSTNAMELEN+1]; /* name of site found as arg */
|
|
X union wait *W_Stat;
|
|
X char *Usort; /* will hold uuname + subcmd */
|
|
X struct passwd *pwd;
|
|
X struct timeval tp;
|
|
X struct timezone tzp;
|
|
X struct Sites Sitetab[SITE_MAX];
|
|
X char mon[3];
|
|
X int day, hh, mm, ss;
|
|
X char oname[24];
|
|
X char jname[20];
|
|
X char tstr[20];
|
|
X char ctag[2];
|
|
X char workf[300];
|
|
X char call_args[300];
|
|
X };
|
|
X
|
|
/* copied from taylor uucp "uudefs.h"
|
|
X *
|
|
X **/
|
|
X
|
|
/* The tstatus_type enumeration holds the kinds of status information
|
|
X we put in the status file. The order of entries here corresponds
|
|
X to the order of entries in the azStatus array. */
|
|
enum tstatus_type
|
|
{
|
|
X /* Conversation complete. */
|
|
X STATUS_COMPLETE,
|
|
X /* Port unavailable. */
|
|
X STATUS_PORT_FAILED,
|
|
X /* Dial failed. */
|
|
X STATUS_DIAL_FAILED,
|
|
X /* Login failed. */
|
|
X STATUS_LOGIN_FAILED,
|
|
X /* Handshake failed. */
|
|
X STATUS_HANDSHAKE_FAILED,
|
|
X /* Failed after logging in. */
|
|
X STATUS_FAILED,
|
|
X /* Talking to remote system. */
|
|
X STATUS_TALKING,
|
|
X /* Wrong time to call. */
|
|
X STATUS_WRONG_TIME,
|
|
X /* Number of status values. */
|
|
X STATUS_VALUES
|
|
};
|
|
X
|
|
/* ----end-- copied from taylor uucp "uudefs.h" */
|
|
X
|
|
X
|
|
/* define the prototypes
|
|
X * */
|
|
X
|
|
int set_mlog(FILE **seclog, struct Common_Stor *);
|
|
int get_sites(struct Common_Stor *);
|
|
int Call_Cico(int argc, char *argv[], struct Common_Stor *);
|
|
int get_args(int argc, char *argv[], struct Common_Stor *);
|
|
int Housekeeping(int argc, char *argv[], struct Common_Stor *);
|
|
int Chk_Status(int argc, char *argv[],
|
|
X struct timeval tcc,
|
|
X struct timezone tzcc,
|
|
X struct Common_Stor *);
|
|
int Check_Site(struct Common_Stor *);
|
|
int start_at(char *name, struct Common_Stor *);
|
|
void *storage(unsigned count, char *errloc, int *Rc, struct Common_Stor *);
|
|
X
|
|
extern int gethostname(char *name, int namelen);
|
|
extern int system(char *cmd);
|
|
extern int fork();
|
|
extern int unlink(char *path);
|
|
extern void *malloc(size_t byteSize);
|
|
extern int execve(char *name, char *argv[], char *envp[]);
|
|
extern int execlp(char *name, char *arg0, ...);
|
|
extern int chmod(char *path, int mode);
|
|
extern int getuid();
|
|
extern int getpid();
|
|
extern int isatty(int);
|
|
extern char *ttyname(int);
|
|
extern void free(void *ptr);
|
|
#ifdef __STRICT_ANSI__
|
|
extern FILE *popen(char *command, char *type);
|
|
extern int pclose(FILE *stream);
|
|
extern void _exit(int status);
|
|
#endif /* __STRICT_ANSI__ */
|
|
#ifdef __STRICT_BSD__
|
|
extern int fprintf(FILE *stream, const char *format, ...);
|
|
extern int fclose(FILE *stream);
|
|
extern char *strerror(int errnum);
|
|
extern int fflush(FILE *stream);
|
|
extern void exit(int status);
|
|
extern int fscanf(FILE *stream, const char *format, ...);
|
|
extern int sscanf(char *s, const char *format, ...);
|
|
#endif /* __STRICT_BSD__ */
|
|
X
|
|
/* --------------------------------------------------------------------------*/
|
|
/* Main */
|
|
/* --------------------------------------------------------------------------*/
|
|
X
|
|
int main(int argc, char *argv[])
|
|
{
|
|
X
|
|
X struct Common_Stor *sCom_Sto;
|
|
X int Maxrc = OK; /* Max err-code encountered so far */
|
|
X int k = 0;
|
|
X
|
|
X if ( NULL == (sCom_Sto = malloc(sizeof(struct Common_Stor))) ) {
|
|
X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n",
|
|
X AUTO_DIR,"Common_Stor",errno,strerror(errno));
|
|
X exit (CAT);
|
|
X }
|
|
X
|
|
X Maxrc = Housekeeping(argc, argv, sCom_Sto);
|
|
X
|
|
/* If any errors popped up so far they are of such a nature that it is very
|
|
X * questionable to continue; so we better bail out in this case.
|
|
X */
|
|
X if (Maxrc <= WARNING) {
|
|
X if ((sCom_Sto->W_Stat = (union wait *)storage (sizeof(union wait),
|
|
X "W_Stat",&Maxrc,sCom_Sto)) != NULL) {
|
|
X k = Call_Cico(argc, argv, sCom_Sto);
|
|
X Maxrc = Maxrc >= k ? Maxrc:k;
|
|
X free(sCom_Sto->W_Stat);
|
|
X sCom_Sto->W_Stat = NULL;
|
|
X }
|
|
X }
|
|
X k = gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp);
|
|
X fprintf(stderr,"%s: (I) ended with rc = %i on %s\n",
|
|
X sCom_Sto->called_as,
|
|
X Maxrc,k!=0 ? "time unavailable":ctime(&sCom_Sto->tp.tv_sec));
|
|
X fclose(stderr);
|
|
X free(sCom_Sto);
|
|
X sCom_Sto = NULL;
|
|
X exit (Maxrc);
|
|
}
|
|
X
|
|
/* --------------------------------------------------------------------------*/
|
|
/* Functions */
|
|
/* --------------------------------------------------------------------------*/
|
|
X
|
|
/* --------------------------------------------------------------------
|
|
X * housekeeping
|
|
X */
|
|
X
|
|
int Housekeeping(argc, argv, sCom_Sto)
|
|
X int argc;
|
|
X char *argv[];
|
|
X struct Common_Stor *sCom_Sto; {
|
|
X
|
|
X FILE *seclog = NULL;
|
|
X int Rc = OK;
|
|
X int Rci = OK; /* intermediate rc as returnd by functions */
|
|
X
|
|
X sCom_Sto->our_pid = getpid();
|
|
X
|
|
/*
|
|
X * get our name sans path
|
|
X * */
|
|
X
|
|
X sCom_Sto->called_as = argv[0] + strlen(*argv);
|
|
X for(;sCom_Sto->called_as >= argv[0] && *--sCom_Sto->called_as != '/';)
|
|
X ;
|
|
X sCom_Sto->called_as++;
|
|
X
|
|
/* if defined set up the name of the message log file otherwise
|
|
X * stderr will be used. Setup the cmd string to obtain all known sitenames
|
|
X * which will be sorted in ascending order with duplicates removed
|
|
X * */
|
|
X
|
|
X Rc = set_mlog(&seclog, sCom_Sto);
|
|
X if (Rc > WARNING)
|
|
X return (Rc);
|
|
X
|
|
/* put out the started message including the time and the userid.
|
|
X * */
|
|
X
|
|
X sCom_Sto->pwd = getpwuid(getuid());
|
|
X
|
|
X if ((gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp)) != 0) { /* unacceptable error */
|
|
X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X }
|
|
X
|
|
X if (seclog != NULL) {
|
|
X fprintf(seclog,"\n%s: (I) started by `%s' (%s) on %s",
|
|
X sCom_Sto->called_as,
|
|
X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name,
|
|
X ttyname(0),
|
|
X ctime(&sCom_Sto->tp.tv_sec));
|
|
X fclose(seclog);
|
|
X }
|
|
X fprintf(stderr,"\n%s: (I) started by `%s' on %s",
|
|
X sCom_Sto->called_as,
|
|
X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name,
|
|
X ctime(&sCom_Sto->tp.tv_sec));
|
|
X
|
|
/* set up the default grade
|
|
X * */
|
|
X
|
|
X sCom_Sto->Grade = dGrade; /* set default for now */
|
|
X if (strlen(cGrade) != 1) {
|
|
X fprintf(stderr,"%s: (W) grade %s invalid; default `%s' used\n",
|
|
X sCom_Sto->called_as,cGrade,sCom_Sto->Grade);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X else
|
|
X sCom_Sto->Grade = cGrade; /* Ok, take the one from conf.h */
|
|
X
|
|
/* get the program to actually call the site. This is normally UUCICO.
|
|
X * */
|
|
X
|
|
X sCom_Sto->Uucico = Cico_Dir + strlen(Cico_Dir);
|
|
X for(;sCom_Sto->Uucico >= Cico_Dir && *--sCom_Sto->Uucico != '/';)
|
|
X ;
|
|
X sCom_Sto->Uucico++;
|
|
X
|
|
/* get the path to ourself.
|
|
X * */
|
|
X
|
|
X sCom_Sto->Poll_Pgm = Auto_Dir + strlen(Auto_Dir);
|
|
X for(;sCom_Sto->Poll_Pgm >= Auto_Dir && *--(sCom_Sto->Poll_Pgm) != '/';)
|
|
X ;
|
|
X sCom_Sto->Poll_Pgm++;
|
|
X
|
|
/* obtain our sitename
|
|
X * */
|
|
X
|
|
X if ((gethostname(sCom_Sto->This_Site,MAXHOSTNAMELEN+1)) != 0) {
|
|
X fprintf(stderr,"%s: (W) hostname could not be obtained\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = (Rc >= WARNING) ? Rc:WARNING;
|
|
X }
|
|
X
|
|
/* obtain all known sitenames
|
|
X * */
|
|
X
|
|
X Rci = get_sites(sCom_Sto);
|
|
X Rc = Rci > Rc ? Rci:Rc;
|
|
X
|
|
/* check the arguments that we are called with
|
|
X * */
|
|
X
|
|
X Rci = get_args(argc, argv, sCom_Sto);
|
|
X Rc = Rci > Rc ? Rci:Rc;
|
|
X
|
|
X return (Rc);
|
|
}
|
|
X
|
|
/* --------------------------------------------------------------------
|
|
X * check all relevant arguments that have been passed to us. Those args
|
|
X * that may be needed for a recall will be copied to a workfield.
|
|
X * */
|
|
X
|
|
int get_args(int argc, char *argv[], struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int j = 0;
|
|
X int Rc = OK;
|
|
X int Rci = OK;
|
|
X
|
|
X strcpy(sCom_Sto->Single_Site,"");
|
|
X sCom_Sto->force_any = FALSE;
|
|
X sCom_Sto->one_site = FALSE;
|
|
X sCom_Sto->nodetach = FALSE;
|
|
X
|
|
X strcpy(sCom_Sto->call_args,AUTO_DIR); /* specify complete path to us */
|
|
X strcat(sCom_Sto->call_args," "); /* and separate by one space */
|
|
X for (j=1;j<argc;j++) {
|
|
X if (strcmp(argv[j],"--nodetach") == 0 ||
|
|
X strcmp(argv[j],"-D") == 0) {
|
|
X sCom_Sto->nodetach = TRUE;
|
|
X strcat(sCom_Sto->call_args,"-D ");
|
|
X continue;
|
|
X }
|
|
X if (strcmp(argv[j],"--force") == 0 ||
|
|
X strcmp(argv[j],"-f") == 0) {
|
|
X strcat(sCom_Sto->call_args,"-f ");
|
|
X sCom_Sto->force_any = TRUE;
|
|
X continue;
|
|
X }
|
|
X if (strcmp(argv[j],"--ifwork") == 0 ||
|
|
X strcmp(argv[j],"-C") == 0) {
|
|
X sCom_Sto->ifwork = TRUE;
|
|
X continue;
|
|
X }
|
|
X if ( strncmp(argv[j],"-s",2) == 0 ||
|
|
X strncmp(argv[j],"-S",2) == 0 ||
|
|
X strcmp(argv[j],"--system") == 0) {
|
|
X if (strncmp(argv[j],"-S",2) == 0)
|
|
X sCom_Sto->force_any = TRUE;
|
|
X
|
|
X if (strlen(argv[j]) == 2 || strcmp(argv[j],"--system") == 0) {
|
|
X j++;
|
|
X if (j>=argc) {
|
|
X fprintf(stderr,"%s: (E) System to call is missing\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X break;
|
|
X }
|
|
X else {
|
|
X strcpy(sCom_Sto->Single_Site,argv[j]);
|
|
X Rci = Check_Site(sCom_Sto);
|
|
X if (! Rci) {
|
|
X sCom_Sto->one_site = TRUE; /* specific call */
|
|
X strcat(sCom_Sto->call_args,argv[j-1]);
|
|
X strcat(sCom_Sto->call_args," ");
|
|
X strcat(sCom_Sto->call_args,argv[j]);
|
|
X strcat(sCom_Sto->call_args," ");
|
|
X }
|
|
X }
|
|
X Rc = Rci <= Rc ? Rc:Rci;
|
|
X }
|
|
X else {
|
|
X strcpy(sCom_Sto->Single_Site,argv[j]+2);
|
|
X Rci = Check_Site(sCom_Sto);
|
|
X if (! Rci) {
|
|
X sCom_Sto->one_site = TRUE; /* specific call */
|
|
X strcat(sCom_Sto->call_args,argv[j]);
|
|
X strcat(sCom_Sto->call_args," ");
|
|
X }
|
|
X Rc = Rci <= Rc ? Rc:Rci;
|
|
X }
|
|
X continue;
|
|
X }
|
|
X strcat(sCom_Sto->call_args,argv[j]);
|
|
X strcat(sCom_Sto->call_args," ");
|
|
X } /* end copy all arguments */
|
|
X
|
|
X if (sCom_Sto->ifwork) {
|
|
X if (sCom_Sto->one_site) {
|
|
X strcat(sCom_Sto->call_args,"-C ");
|
|
X }
|
|
X else {
|
|
X fprintf(stderr,"%s: (W) no site given, '-C' option is ignored\n",
|
|
X sCom_Sto->called_as);
|
|
X sCom_Sto->ifwork = FALSE;
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X }
|
|
X
|
|
X if (! sCom_Sto->nodetach) {
|
|
X strcat(sCom_Sto->call_args,"-D ");
|
|
X }
|
|
X
|
|
X return (Rc);
|
|
}
|
|
X
|
|
/* --------------------------------------------------------------------
|
|
X * call uucico or whatever programm is necessary to get connected
|
|
X */
|
|
X
|
|
/* Start uucico and wait for completion. In case the return code is '0'
|
|
X * we're finished; otherwise we'll have to check the status files for any
|
|
X * non successful calls (retry time > 0).
|
|
X * Any such site will be called again at the current time plus any wait
|
|
X * Note:
|
|
X * If the '-D' or '--nodetach' option is missing, uucico will
|
|
X * detach immediate. The return-code is 0 in this case and therefore
|
|
X * we can't check whether the call is successful or not. No recall
|
|
X * is scheduled for such an invocation. If we however get control
|
|
X * to schedule a recall we silently add the '-D' option. To add
|
|
X * the '-D' option in any case may be undesirable for a specific
|
|
X * type of run.
|
|
X */
|
|
X
|
|
int Call_Cico(int argc, char *argv[], struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int W_Ret = 0;
|
|
X int pid = 0;
|
|
X int Rc = OK;
|
|
X struct timeval tcc;
|
|
X struct timezone tzcc;
|
|
X
|
|
X if ((gettimeofday(&tcc, &tzcc)) != 0) { /* unacceptable error */
|
|
X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X Rc = Rc >= CAT ? Rc:CAT;
|
|
X }
|
|
X
|
|
X if (Rc > WARNING) {
|
|
X return (Rc);
|
|
X }
|
|
X
|
|
X fflush(stderr);
|
|
X switch(pid = fork()) {
|
|
X case -1:
|
|
X fprintf(stderr,"%s: (C) could not fork(). Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X return (CAT);
|
|
X case 0:
|
|
X if ((argv[0] = (char *)storage(strlen(sCom_Sto->Uucico)+1,"argv[0]",
|
|
X &Rc,sCom_Sto)) == NULL) {
|
|
X _exit (CAT);
|
|
X }
|
|
X strcpy(argv[0],sCom_Sto->Uucico); /* change name to be uucico */
|
|
X execve(Cico_Dir, argv, NULL);
|
|
X fprintf(stderr,"%s: (C) could not start %s. Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Uucico,errno,strerror(errno));
|
|
X _exit (CAT); /* child: bail out */
|
|
X default:
|
|
X fprintf(stderr,"%s: (I) starting %s [%d]\n\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Uucico,pid);
|
|
X fflush(stderr); /* maybe we come behind uucico's output */
|
|
X /* if any; it's a race condition */
|
|
X W_Ret = wait(sCom_Sto->W_Stat);
|
|
X if (sCom_Sto->W_Stat->w_termsig == 0) {
|
|
X if (sCom_Sto->W_Stat->w_retcode == 0) {
|
|
X fprintf(stderr,"%s: (I) %s [%d] ended normally\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Uucico,pid);
|
|
X return (OK);
|
|
X }
|
|
X if (sCom_Sto->W_Stat->w_retcode != CAT) {
|
|
X fprintf(stderr,"%s: (I) %s's log may contain further information !\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Uucico);
|
|
X fprintf(stderr,"\n%s: (W) %s [%d] ended with rc = %i\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Uucico,pid,
|
|
X sCom_Sto->W_Stat->w_retcode);
|
|
X return (Chk_Status(argc, argv,
|
|
X tcc, tzcc, sCom_Sto));
|
|
X }
|
|
X else
|
|
X return (CAT); /* we where unable to exec */
|
|
X }
|
|
X else {
|
|
X fprintf(stderr,"\n%s: (E) %s [%d] terminated by signal %i\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Uucico,
|
|
X pid,
|
|
X sCom_Sto->W_Stat->w_termsig);
|
|
X return (SEVERE);
|
|
X }
|
|
X } /* switch (pid = fork()) */
|
|
X return (OK); /* Never reached: silence the compiler */
|
|
}
|
|
X
|
|
X
|
|
/* --------------------------------------------------------------------
|
|
X * check the status after the call has completed and the return code
|
|
X * is > zero. The status is checked for all sites found via uuname or
|
|
X * for one site only (option -s, -S or --system given on call)
|
|
X */
|
|
X
|
|
int Chk_Status(int argc, char *argv[],
|
|
X struct timeval tcc,
|
|
X struct timezone tzcc,
|
|
X struct Common_Stor *sCom_Sto) {
|
|
X
|
|
/*
|
|
X * For all sites found in Site_Tab their status files will be checked.
|
|
X * The table scan will be bypassed for a call to a specific site.
|
|
X * If the call failed the wait period is > 0. We will schedule an at-job
|
|
X * to be run at the time found + the delta. In case we find an old entry
|
|
X * where the time + delta is lower than the current time we'll advance
|
|
X * the current time by 60 secs. and use that value instead.
|
|
X * In case we are invoked to call a specific site and either the -f option or
|
|
X * the site was given as -S... indicating to disregard any wait, we'll
|
|
X * use the time found in the status file increased by 120 secs.
|
|
*/
|
|
X
|
|
X FILE *infile;
|
|
X long secs, retries = 0;
|
|
X long add = 0;
|
|
X int errind = 0;
|
|
X int i = 0;
|
|
X int ecnt = 0;
|
|
X int recall_cnt = 0;
|
|
X char curr_site[MAXHOSTNAMELEN+11] = ""; /* keyword + sitename */
|
|
X bool schedule = TRUE; /* FALSE: no more rescheduling: unspec. + force */
|
|
X int Rc = WARNING; /* uucico got rc = 1 otherwise we were not here */
|
|
X int Rs = 0; /* uucico' reason code from .Status file */
|
|
X
|
|
/*
|
|
X * Note
|
|
X * We have to increase the sum of time and wait by at least one minute.
|
|
X * That is because this time denotes the earliest point *after* which
|
|
X * we may call again.
|
|
X * When a site is called at the wrong time the follwing actions are
|
|
X * taken: wait = 0 && ! force --> no further action (indicator: see log)
|
|
X * wait = 0 && force --> (W) message generated; no further action
|
|
X * wait > 0 && ! force --> normal scheduling at time + wait
|
|
X * wait > 0 && force --> normal scheduling at time+120 secs
|
|
X * We can't depend on the string "Wrong time to call" because the .Status
|
|
X * file may not be updated due to the -c switch. This may lead to a
|
|
X * situation where the site will be called over and over again while it's
|
|
X * still the wrong time. (No we don't want to go fishing for a message in
|
|
X * the uucp LOG!)
|
|
X * In case the -s, -S or --system option was given we will only
|
|
X * check that site and schedule a recall for it so far the
|
|
X * conditions are met.
|
|
X * In case the -C or --ifwork switch is given without naming a site a
|
|
X * the option is dropped and only an unspecific call is scheduled.
|
|
X * */
|
|
X
|
|
X if (sCom_Sto->one_site) {
|
|
X i = sCom_Sto->Single_Site_Tab;
|
|
X if (strncmp(sCom_Sto->Sitetab[i].name,
|
|
X sCom_Sto->Single_Site,
|
|
X sizeof(sCom_Sto->Single_Site)) != 0) {
|
|
X fprintf(stderr,"%s: (C) internal index-error (%d): %s found: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X i,
|
|
X sCom_Sto->Single_Site,
|
|
X sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= CAT ? Rc:CAT;
|
|
X return (Rc); /* break unconditionally */
|
|
X }
|
|
X }
|
|
X
|
|
X for (i = sCom_Sto->Single_Site_Tab; i <= sCom_Sto->maxtab; i++) {
|
|
X sprintf(sCom_Sto->workf,"%s%s",STATUS_DIR,sCom_Sto->Sitetab[i].name);
|
|
X if ((infile=fopen(sCom_Sto->workf,"r")) == NULL) {
|
|
X ecnt++;
|
|
X fprintf(stderr,"%s: (W) no access to status file for: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X if (sCom_Sto->one_site) {
|
|
X break;
|
|
X }
|
|
X else {
|
|
X continue;
|
|
X }
|
|
X }
|
|
X
|
|
X fscanf(infile,"%d %d %ld %ld",&errind,&retries,&secs,&add);
|
|
X fclose(infile);
|
|
X
|
|
X /*
|
|
X * in case the .Status file is not updated and we have a call to
|
|
X * a specific site we try to give some clues of what went wrong
|
|
X * (we won't succeed in any case!)
|
|
X */
|
|
X
|
|
X if (sCom_Sto->Sitetab[i].stat_lastcall == secs && sCom_Sto->one_site) {
|
|
X
|
|
X if (errind == 0 && retries == 0 && add == 0)
|
|
X break;
|
|
X
|
|
X if (errind > 0) {
|
|
X if (tcc.tv_sec <= (secs+add) && ! sCom_Sto->Sitetab[i].force) {
|
|
X fprintf(stderr,"%s: (W) retry time not reached for site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X else {
|
|
X fprintf(stderr,"%s: (E) maybe port/site unavailable site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X }
|
|
X else {
|
|
X if (sCom_Sto->one_site) {
|
|
X fprintf(stderr,"%s: (E) unknown error for call to site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X }
|
|
X fprintf(stderr,"%s: (W) no recall scheduled for site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X break; /* bail out completely */
|
|
X }
|
|
X
|
|
X if (sCom_Sto->Sitetab[i].stat_lastcall == secs) {
|
|
X if (sCom_Sto->one_site)
|
|
X break;
|
|
X else
|
|
X continue;
|
|
X }
|
|
X
|
|
X Rs = OK; /* if Rs is > WARNING we won't schedule a recall */
|
|
X switch(errind) {
|
|
X case STATUS_COMPLETE:
|
|
X if (add != 0 || retries != 0) {
|
|
X fprintf(stderr,"%s: (E) unknown error for call to site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rs = Rs >= SEVERE ? Rs:SEVERE;
|
|
X }
|
|
X break;
|
|
X case STATUS_PORT_FAILED:
|
|
X fprintf(stderr,"%s: (E) port was unavailable site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X break;
|
|
X case STATUS_DIAL_FAILED:
|
|
X fprintf(stderr,"%s: (E) dail failed for site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X break;
|
|
X case STATUS_LOGIN_FAILED:
|
|
X fprintf(stderr,"%s: (E) login for site: %s failed\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rs = Rs >= SEVERE ? Rs:SEVERE;
|
|
X break;
|
|
X case STATUS_HANDSHAKE_FAILED:
|
|
X fprintf(stderr,"%s: (E) handshake failed site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X break;
|
|
X case STATUS_FAILED:
|
|
X fprintf(stderr,"%s: (E) invalid status after login site: %s \n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X break;
|
|
X case STATUS_TALKING:
|
|
X break;
|
|
X case STATUS_WRONG_TIME:
|
|
X fprintf(stderr,"%s: (W) it's the wrong time to call site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rs = Rs >= SEVERE ? Rs:SEVERE;
|
|
X break;
|
|
X default:
|
|
X fprintf(stderr,"%s: (E) unknown error for call to site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rs = Rs >= SEVERE ? Rs:SEVERE;
|
|
X break;
|
|
X }
|
|
X Rc = Rs > Rc ? Rs:Rc;
|
|
X if (Rs > WARNING) { /* schedule a recall ? */
|
|
X fprintf(stderr,"%s: (W) no recall scheduled for site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X if (sCom_Sto->one_site)
|
|
X break;
|
|
X else
|
|
X continue;
|
|
X }
|
|
X
|
|
X if (add == 0) {
|
|
X fprintf(stderr,"%s: (W) no delay found for site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X
|
|
X
|
|
X if (! schedule) {
|
|
X recall_cnt += 1;
|
|
X continue; /* scheduling already done: unspec. + force */
|
|
X }
|
|
X if ((gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp)) != 0) {
|
|
X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X fclose(infile);
|
|
X Rc = Rc >= CAT ? Rc:CAT;
|
|
X break; /* break unconditionally */
|
|
X }
|
|
X
|
|
X if (sCom_Sto->force_any || sCom_Sto->Sitetab[i].force) {
|
|
X add = secs + 120; /* shorten the wait */
|
|
X }
|
|
X else { /* ! force */
|
|
X
|
|
/*
|
|
X * check for an already scheduled recall. For we don't keep
|
|
X * a file of already scheduled recalls the only way to recognize
|
|
X * this, is to check the current time against that of the .Stats file.
|
|
X * In case the current time is >= the .Stats-time + n-secs fuzz value
|
|
X * we assume (99.99% correctness) that we have already scheduled a recall
|
|
X * for this site. If this assumption is incorrect a call will be
|
|
X * scheduled on the next unspecific failing call. This check can't
|
|
X * be done for forced call because the .Stats will be updated.
|
|
X */
|
|
X if (sCom_Sto->tp.tv_sec >= secs+2) {
|
|
X fprintf(stderr,"%s: (W) Retry time not reached for site: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X if (sCom_Sto->one_site)
|
|
X break;
|
|
X else
|
|
X continue;
|
|
X }
|
|
X add += secs + 60; /* if not force then take the full wait */
|
|
X } /* force */
|
|
X
|
|
X if (sCom_Sto->tp.tv_sec >= add) {
|
|
X add = sCom_Sto->tp.tv_sec + 60; /* time < current time */
|
|
X }
|
|
X
|
|
X sscanf(ctime(&add),"%*s %s %d %d:%d:%d",sCom_Sto->mon,
|
|
X &sCom_Sto->day,
|
|
X &sCom_Sto->hh,
|
|
X &sCom_Sto->mm,
|
|
X &sCom_Sto->ss);
|
|
X
|
|
X sprintf(sCom_Sto->oname,"/tmp/at.%d.%02d%02d%02d",sCom_Sto->our_pid,
|
|
X sCom_Sto->hh,
|
|
X sCom_Sto->mm,
|
|
X sCom_Sto->ss);
|
|
X if (! sCom_Sto->one_site) {
|
|
X strcpy(curr_site,"-s");
|
|
X strcat(curr_site,sCom_Sto->Sitetab[i].name);
|
|
X }
|
|
X
|
|
X /*
|
|
X * If 'onesite' is FALSE and 'force' is TRUE
|
|
X * we will reschedule one unspecific call an let UUCICO decide
|
|
X * which site should be called (is there any work?)
|
|
X */
|
|
X
|
|
X if ( ! sCom_Sto->one_site && sCom_Sto->force_any) {
|
|
X recall_cnt += 1;
|
|
X schedule = FALSE;
|
|
X continue;
|
|
X }
|
|
X strcat(sCom_Sto->call_args,curr_site);
|
|
X Rs = start_at(sCom_Sto->Sitetab[i].name, sCom_Sto);
|
|
X Rc = Rs >= Rc ? Rs:Rc;
|
|
X unlink(sCom_Sto->oname);
|
|
X if (Rc > SEVERE || sCom_Sto->one_site)
|
|
X break;
|
|
X } /* for (i = Single_Site_Tab; ...) */
|
|
X
|
|
X if (ecnt > sCom_Sto->maxtab) {
|
|
X fprintf(stderr,"%s: (E) no access to status files; no scheduling done\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X else {
|
|
X if (! schedule) {
|
|
X if (recall_cnt == 1) {
|
|
X strcat(sCom_Sto->call_args,curr_site);
|
|
X }
|
|
X Rs = start_at("any site", sCom_Sto);
|
|
X Rc = Rs >= Rc ? Rs:Rc;
|
|
X unlink(sCom_Sto->oname);
|
|
X }
|
|
X }
|
|
X return (Rc);
|
|
}
|
|
X
|
|
X /*
|
|
X *
|
|
X */
|
|
X
|
|
int start_at(char *site, struct Common_Stor *sCom_Sto) {
|
|
X
|
|
FILE *outfile;
|
|
int W_Ret = 0;
|
|
int Rc = OK;
|
|
int pid = 0;
|
|
X
|
|
/*
|
|
X * if we can't open the workfile to be passed to AT we'll abandon
|
|
X * this site and set the rc accordingly
|
|
X * */
|
|
X
|
|
X if ((outfile=fopen(sCom_Sto->oname,"w")) == NULL) {
|
|
X fprintf(stderr,"%s: (E) could not open workfile %s. No scheduling for: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->oname,
|
|
X site);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X fclose(outfile);
|
|
X unlink(sCom_Sto->oname);
|
|
X return (Rc); /* bail out here */
|
|
X }
|
|
X sprintf(sCom_Sto->jname,"at.%d.%02d%02d%02d",sCom_Sto->our_pid,
|
|
X sCom_Sto->hh,
|
|
X sCom_Sto->mm,
|
|
X sCom_Sto->ss);
|
|
X fprintf(outfile,"%s \n",sCom_Sto->call_args);
|
|
X sprintf(sCom_Sto->tstr,"%02d%02d",sCom_Sto->hh,
|
|
X sCom_Sto->mm);
|
|
X sprintf(sCom_Sto->ctag,"%d",sCom_Sto->day);
|
|
X fclose(outfile);
|
|
X if ((chmod(sCom_Sto->oname,00644)) != 0) {
|
|
X fprintf(stderr,"%s: (W) chmod to %s failed. Reason_code: %i (%s)\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->oname,
|
|
X errno,
|
|
X strerror(errno));
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X
|
|
X switch (pid = fork()) {
|
|
X case -1:
|
|
X fprintf(stderr,"%s: (C) could not fork(). Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X case 0:
|
|
X if (*at_opt == '\0')
|
|
X execlp(at_cmd, at_cmd, sCom_Sto->tstr,
|
|
X sCom_Sto->mon, sCom_Sto->ctag,
|
|
X sCom_Sto->oname, 0);
|
|
X else
|
|
X execlp(at_cmd, at_cmd, at_opt, sCom_Sto->tstr,
|
|
X sCom_Sto->mon, sCom_Sto->ctag,
|
|
X sCom_Sto->oname, 0);
|
|
X
|
|
X fprintf(stderr,"%s: (C) could not start AT-cmd. Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,
|
|
X errno,strerror(errno));
|
|
X _exit (CAT); /* child: bail out */
|
|
X default:
|
|
X fprintf(stderr,"%s: (I) at [%d] started. Job name: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X pid,
|
|
X sCom_Sto->jname);
|
|
X W_Ret = wait(sCom_Sto->W_Stat);
|
|
X if (sCom_Sto->W_Stat->w_termsig == 0) {
|
|
X if (sCom_Sto->W_Stat->w_retcode != 0) {
|
|
X if (sCom_Sto->W_Stat->w_retcode != CAT) {
|
|
X fprintf(stderr,"%s: (E) at-cmd failed for some reason\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X else {
|
|
X Rc = Rc >= CAT ? Rc:CAT;
|
|
X }
|
|
X
|
|
X fprintf(stderr,"%s: (I) at [%d] ended with rc = %i\n",
|
|
X sCom_Sto->called_as,
|
|
X pid,
|
|
X sCom_Sto->W_Stat->w_retcode);
|
|
X /* bail out in case wait returned > SEVERE */
|
|
X if (Rc > SEVERE) {
|
|
X return (Rc);
|
|
X }
|
|
X }
|
|
X else {
|
|
X fprintf(stderr,"%s: (I) at-cmd [%d] ended normally\n",
|
|
X sCom_Sto->called_as,
|
|
X pid);
|
|
X }
|
|
X }
|
|
X else {
|
|
X fprintf(stderr,"%s: (E) at [%d] terminated by signal %i\n",
|
|
X sCom_Sto->called_as,
|
|
X pid,
|
|
X sCom_Sto->W_Stat->w_termsig);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X } /* switch (pid = fork()) */
|
|
X return (Rc);
|
|
}
|
|
/* -----------------------------------------------------------------
|
|
X * check the site passed via -s or -S option to be a valid one and
|
|
X * not to be our hostname.
|
|
X * */
|
|
X
|
|
int Check_Site(struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int i,j = 0;
|
|
X sCom_Sto->Single_Site_Tab = 0;
|
|
X if (strcmp(sCom_Sto->Single_Site,sCom_Sto->This_Site) == 0) {
|
|
X fprintf(stderr,"%s: (E) won't call *ourself* %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Single_Site);
|
|
X return(SEVERE);
|
|
X }
|
|
X for(i=0;i<=sCom_Sto->maxtab;i++) {
|
|
X if ((j=strcmp(sCom_Sto->Sitetab[i].name,sCom_Sto->Single_Site)) >= 0) {
|
|
X break;
|
|
X }
|
|
X }
|
|
X if (j != 0) {
|
|
X fprintf(stderr,"%s: (E) unknown site: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Single_Site);
|
|
X return(SEVERE);
|
|
X }
|
|
X sCom_Sto->Single_Site_Tab = i;
|
|
X sCom_Sto->Sitetab[i].flag = TRUE;
|
|
X if (sCom_Sto->force_any) {
|
|
X sCom_Sto->Sitetab[i].force = TRUE;
|
|
X sCom_Sto->force_any = FALSE;
|
|
X }
|
|
X return(OK);
|
|
}
|
|
X
|
|
X /* ------------------------------------------------------------------
|
|
X * storage - get some memory
|
|
X */
|
|
X
|
|
void *storage(unsigned count,
|
|
X char *location,
|
|
X int *Rc,
|
|
X struct Common_Stor *sCom_Sto)
|
|
{
|
|
X void *p;
|
|
X
|
|
X if( NULL == (p= malloc(count)) ) {
|
|
X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n",
|
|
X sCom_Sto->called_as,location,errno,strerror(errno));
|
|
X *Rc = *Rc >= CAT ? *Rc:CAT;
|
|
X }
|
|
X return p;
|
|
}
|
|
X
|
|
/* ------------------------------------------------------------------
|
|
X * if defined open the message log file otherwise all mesages will go
|
|
X * to stderr. If UNAME_DIR is defined construct the command to be
|
|
X * passed to popen(); if undefined the deafult will be used
|
|
X * */
|
|
X
|
|
int set_mlog(FILE **seclog, struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int Rc = 0;
|
|
X
|
|
#ifdef ALOG_FILE
|
|
X if (!isatty(0)) {
|
|
X if ((freopen(Msg_Log,"a",stderr)) == NULL) {
|
|
X fprintf(stdout,"%s: (C) Could not open msglog: %s\n",
|
|
X sCom_Sto->called_as,Msg_Log);
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X }
|
|
X }
|
|
X else {
|
|
X if ((*seclog = fopen(Msg_Log,"a")) == NULL) {
|
|
X fprintf(stderr,"%s: (C) Could not open msglog: %s\n",
|
|
X sCom_Sto->called_as,Msg_Log);
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X }
|
|
X }
|
|
#endif /* ALOG_FILE */
|
|
X
|
|
/* set up the pipe together with the complete path to uuname */
|
|
X
|
|
#ifdef UNAME_DIR
|
|
X if ((sCom_Sto->Usort = (char *)storage (sizeof(UNAME_DIR)+sizeof(subcmd),
|
|
X "Sort",&Rc, sCom_Sto)) != NULL) {
|
|
X strncpy(sCom_Sto->Usort,UNAME_DIR,strlen(UNAME_DIR)); /* paste in the path */
|
|
X strcat(sCom_Sto->Usort,subcmd); /* chain the pipe to it */
|
|
X }
|
|
#else /* ! UNAME_DIR */
|
|
X sCom_Sto->Usort = &Sort; /* set pointer to uuname + sort */
|
|
#endif /* UNAME_DIR */
|
|
X
|
|
X return (Rc);
|
|
}
|
|
X
|
|
/* ------------------------------------------------------------------
|
|
X * obtain all active sitenames
|
|
X * */
|
|
X
|
|
int get_sites(struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int i = 0;
|
|
X int n;
|
|
X int Rc = 0;
|
|
X FILE *infile, *statsfile;
|
|
X
|
|
X if ((infile=popen(sCom_Sto->Usort,"r")) != NULL) {
|
|
X while(fgets(sCom_Sto->Sitetab[i].name,MAXHOSTNAMELEN+1,infile)) {
|
|
X if (i > SITE_MAX) { /* let'm run so that we can give */
|
|
X i++; /* the user some guidance */
|
|
X continue; /* we'll tell the user later on */
|
|
X }
|
|
X n = strlen(sCom_Sto->Sitetab[i].name)-1; /* offset: next to last char */
|
|
X sCom_Sto->Sitetab[i].name[n] = '\0'; /* strip trailing newline */
|
|
X sCom_Sto->Sitetab[i].flag = FALSE; /* TRUE: poll this site only*/
|
|
X sCom_Sto->Sitetab[i].force = FALSE; /* TRUE: force call */
|
|
X strcpy(sCom_Sto->Sitetab[i].grade,sCom_Sto->Grade);
|
|
X sprintf(sCom_Sto->workf,"%s%s",STATUS_DIR,sCom_Sto->Sitetab[i].name);
|
|
X if ((statsfile=fopen(sCom_Sto->workf,"r")) == NULL) {
|
|
X fprintf(stderr,"%s: (W) no access to status file for: %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->Sitetab[i].name);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X else {
|
|
X fscanf(statsfile,"%d %d %ld %ld %s",
|
|
X &sCom_Sto->Sitetab[i].stat_code,
|
|
X &sCom_Sto->Sitetab[i].stat_retries,
|
|
X &sCom_Sto->Sitetab[i].stat_lastcall,
|
|
X &sCom_Sto->Sitetab[i].stat_delay,
|
|
X sCom_Sto->workf);
|
|
X
|
|
X fclose(statsfile);
|
|
X if ((sCom_Sto->Sitetab[i].stat_errtext =
|
|
X (char *)storage (sizeof(sCom_Sto->workf),
|
|
X "stat_errtext",&Rc, sCom_Sto)) == NULL) {
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X else
|
|
X strcpy(sCom_Sto->Sitetab[i].stat_errtext,sCom_Sto->workf);
|
|
X }
|
|
X sCom_Sto->maxtab = i++; /* set high-water-mark */
|
|
X }
|
|
X if (ferror(infile) != 0) {
|
|
X fprintf(stderr,"%s: (E) fgets() for sitenames failed reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X pclose(infile);
|
|
X
|
|
X /*
|
|
X * check for an empty table (strange but possible)
|
|
X */
|
|
X
|
|
X if (sCom_Sto->maxtab == 0) {
|
|
X fprintf(stderr,"%s: (E) could not obtain sitenames.\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X else {
|
|
X
|
|
X /* in case the internal table overflows we'll now give notice and tell
|
|
X * the user by which amount the table has to be increased to hold all
|
|
X * site-names
|
|
X */
|
|
X
|
|
X if (i > SITE_MAX) {
|
|
X fprintf(stderr,"%s: (E) number of sites > internal tab\n",
|
|
X sCom_Sto->called_as);
|
|
X fprintf(stderr,"%s: (E) increase SITE_MAX to >= %d and recompile\n",
|
|
X sCom_Sto->called_as,i);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X } /* sCom_Sto->maxtab == 0 */
|
|
X
|
|
X }
|
|
X else /* infile == NULL */
|
|
X {
|
|
X fprintf(stderr,"%s: (E) could not sort sitenames. Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X
|
|
X } /* if ((infile=popen(sCom_Sto->Usort,"r")) ... */
|
|
X
|
|
X return (Rc);
|
|
}
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/autopoll.c ||
|
|
echo 'restore of uupoll/autopoll.c failed'
|
|
Wc_c="`wc -c < 'uupoll/autopoll.c'`"
|
|
test 44031 -eq "$Wc_c" ||
|
|
echo 'uupoll/autopoll.c: original size 44031, current size' "$Wc_c"
|
|
fi
|
|
# ============= uupoll/conf.h ==============
|
|
if test -f 'uupoll/conf.h' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/conf.h (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/conf.h (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/conf.h' &&
|
|
#ifndef CONF
|
|
X #define CONF
|
|
X
|
|
/* $Id: conf.h,v 1.9 1994/04/14 17:24:58 kdburg Rel $ */
|
|
/* $Log: conf.h,v $
|
|
X * Revision 1.9 1994/04/14 17:24:58 kdburg
|
|
X * added comment to the AT_OPTION
|
|
X *
|
|
X * Revision 1.8 1994/03/26 17:41:06 kdburg
|
|
X * the location of uuname can now be specified. This was added due to
|
|
X * the fact that cron (NeXT 3.2 and +) now obeys the path that was active
|
|
X * during boot (either /.path or set within /etc/rc) so autopoll/uupoll
|
|
X * always got the wrong uuname when called direct fron cron. This is
|
|
X * not true when called via a script that does a 'su - user -c ...'
|
|
X *
|
|
X * Revision 1.7 1993/06/26 16:21:47 kdburg
|
|
X * default location for logfiles changed
|
|
X *
|
|
X * Revision 1.6 1993/05/14 22:32:05 kdburg
|
|
X * change to HAVE_SPOOLDIR_TAYLOR
|
|
X *
|
|
X * Revision 1.5 1993/05/09 13:16:53 kdburg
|
|
X * make have-autopoll the default
|
|
X *
|
|
X * Revision 1.4 1993/05/08 23:17:34 kdburg
|
|
X * cleanup and to reflect changes made to autopoll/uupoll
|
|
X *
|
|
X * Revision 1.3 1993/04/29 10:46:34 kdburg
|
|
X * added def for STATUS_DIR
|
|
X *
|
|
X * Revision 1.2 1993/04/27 15:31:47 kdburg
|
|
X * rearranged the defs; changed LOG_DIR to ALOG_DIR in case uupoll
|
|
X * will have one too; we need then eventually 2 different dirs.
|
|
X *
|
|
X * Revision 1.1 1993/04/26 21:20:12 kdburg
|
|
X * Initial revision
|
|
X * */
|
|
X
|
|
/* --------- combined config file for uupoll and autopoll */
|
|
/* --------- change the following defines to meet your needs */
|
|
X
|
|
/* define the default grade to be inserted into the pollfile name */
|
|
#define DEF_GRADE "A"
|
|
X
|
|
/* Define the complete path to the uuname program.
|
|
X * If undefined we'll use just the name 'uuname' to call it
|
|
X * */
|
|
#define UNAME_DIR "/usr/local/bin/uuname"
|
|
X
|
|
/* define the path to the directory which does contain uucico */
|
|
#define CICO_DIR "/usr/local/lib/uucp/uucico"
|
|
X
|
|
/* define the path to the directory which holds all the uucp files.
|
|
X * We'll place the poll file in one of it's subdirectories
|
|
X * */
|
|
#define SPOOL_DIR "/usr/spool/uucp"
|
|
X
|
|
/* at least one of the follwing must be defined To use the second or
|
|
X * third set of definitions, change the ``#if 1'' to ``#if 0''
|
|
X * and change the appropriate ``#if 0'' to ``#if 1''.
|
|
X * */
|
|
#if 0
|
|
#define HAVE_SPOOLDIR_BSD
|
|
#endif
|
|
#if 0
|
|
#define HAVE_SPOOLDIR_HDB
|
|
#endif
|
|
#if 1
|
|
#define HAVE_SPOOLDIR_TAYLOR
|
|
#endif
|
|
X
|
|
/* define the maximum number of sites in your config or L.sys */
|
|
#define SITE_MAX 100
|
|
X
|
|
/* define the path to the directory which is to contain the
|
|
X * message log created by uupoll and the file name itself.
|
|
X * change the ``#if 1'' to ``#if 0'' to have the messages on stderr
|
|
X * */
|
|
#if 1
|
|
#define ULOG_FILE "/Logfiles/poll.log"
|
|
#endif
|
|
X
|
|
/* change if to 0 if you don't have autopoll installed. */
|
|
#if 1
|
|
#define AUTO_POLL
|
|
#endif
|
|
X
|
|
/* The following defs are irrelevant if you don't have autopoll */
|
|
X
|
|
/* define the options to be given to the at cmd (-s -c -m). The default
|
|
X * is shown (use csh and send mail after execution) if AT_OPTION is
|
|
X * undefined
|
|
X * */
|
|
#define AT_OPTION "-mc"
|
|
X
|
|
/* Define the complete path to the autopoll program.
|
|
X * This will assure that we get the one we want
|
|
X * The path must be the same as given in Makefile (lbindir)
|
|
X * */
|
|
#define AUTO_DIR "/usr/local/lib/uucp/autopoll"
|
|
X
|
|
/* define the path to the directory which is to contain the
|
|
X * message log created by autopoll and the file name itself.
|
|
X * change the ``#if 1'' to ``#if 0'' to have the messages on stderr
|
|
X * */
|
|
#if 1
|
|
#define ALOG_FILE "/Logfiles/poll.log"
|
|
#endif
|
|
X
|
|
/* define the full path to the directory which holds the status files
|
|
X * The name should be given *except* the sitename. A trailing `/' if any
|
|
X * must be given.
|
|
X * Example: /usr/spool/uucp/.Status/sys.sitename
|
|
X * then specify STATUS_DIR as
|
|
X * "/usr/spool/uucp/.Status/sys."
|
|
X * */
|
|
#define STATUS_DIR "/usr/spool/uucp/.Status/"
|
|
#endif
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/conf.h ||
|
|
echo 'restore of uupoll/conf.h failed'
|
|
Wc_c="`wc -c < 'uupoll/conf.h'`"
|
|
test 3884 -eq "$Wc_c" ||
|
|
echo 'uupoll/conf.h: original size 3884, current size' "$Wc_c"
|
|
fi
|
|
# ============= uupoll/uupoll.8c ==============
|
|
if test -f 'uupoll/uupoll.8c' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/uupoll.8c (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/uupoll.8c (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/uupoll.8c' &&
|
|
.\" Copyright (c) 1986 Regents of the University of California.
|
|
.\" All rights reserved. The Berkeley software License Agreement
|
|
.\" specifies the terms and conditions for redistribution.
|
|
.\"
|
|
.\" @(#)uupoll.8c 6.1 (Berkeley) 4/24/86
|
|
.\" @(#)uupoll.8c 1.11 (incoahe) 5/09/1993
|
|
.\"
|
|
.TH UUPOLL 8C "Mai 09, 1993"
|
|
.UC 6
|
|
.SH NAME
|
|
uupoll \- poll a remote \s-1UUCP\s+1 site
|
|
.SH SYNOPSIS
|
|
.B uupoll
|
|
[
|
|
.BI \-g grade
|
|
] [
|
|
.B \-n
|
|
] [
|
|
.B \-x
|
|
]
|
|
.I system ... ...
|
|
.SH SUMMARY
|
|
This version of
|
|
.IR uupoll
|
|
can be used to fully replace the vendor supplied
|
|
.IR uupoll
|
|
that comes with the NeXTStep OS. The original version (up to 3.1) had a
|
|
X bug in that
|
|
X an unknown site given as argument would yield in a `Bus error' condition.
|
|
Using any other type of UUCP like Taylor-UUCP with the option of having
|
|
a different file structure as well as a different L.sys will therefore
|
|
make it necessary to do maintenance to the (unused) L.sys as well to keep
|
|
.IR uupoll
|
|
going. This one has been programmed from scratch due to the fact that no
|
|
source code was available. Some enhancements have been incorporated into
|
|
this version:
|
|
.PP
|
|
\- the default grade may now be compiled different from `A'.
|
|
.PP
|
|
\- the options may now be given in any order and the \-g option may be given
|
|
more than once. Any option will be used immediately when encountered and
|
|
will stay in effect unless reset; this does not apply to the \-x and \-n
|
|
option which can't be reset. The processing of options is guaranteed to be
|
|
from left to right so that some grouping may be achieved (see below).
|
|
.PP
|
|
\-
|
|
.IR uupoll
|
|
may be used to call any program instead of
|
|
.IR uucico
|
|
namely
|
|
.IR autopoll
|
|
to ease the task of rescheduling a failed call.
|
|
.SH DESCRIPTION
|
|
.I Uupoll
|
|
is used to force a poll of a remote system. It queues a null job for the
|
|
remote system, unless the \-x option has been given, and then invokes
|
|
either
|
|
.IR uucico (8C)
|
|
or
|
|
.IR autopoll (8C)
|
|
or any other program depending on how
|
|
.IR uupoll
|
|
is customized. If used in conjunction with
|
|
.IR autopoll
|
|
the latter will then invoke
|
|
.IR uucico.
|
|
.SH OPTIONS
|
|
The following options are available:
|
|
.TP 8
|
|
.BI \-g grade
|
|
Only send jobs of grade
|
|
.I grade
|
|
or higher on this call. The
|
|
.I grade
|
|
stays in effect until it is changed by a different \-g option.
|
|
.TP 8
|
|
.B \-n
|
|
Queue the null job, but do not invoke the program that actually calls
|
|
the named site(s).
|
|
The \-n option once given will apply to all sites following to the
|
|
.IR right
|
|
of it.
|
|
.TP 8
|
|
.B \-x
|
|
Do not place a null job for all following sites. This option must be given
|
|
before the \-n option. The \-n option will nullify this. Any grade in effect
|
|
will not be honored because
|
|
.I uucico (Taylor)
|
|
does not carry the \-g option at the moment.
|
|
.PP
|
|
.I Uupoll
|
|
is usually run by
|
|
.IR cron (5)
|
|
or by a user who wants to hurry a job along. A typical entry in
|
|
.I crontab
|
|
could be:
|
|
.PP
|
|
.nf
|
|
X 0 0,8,16 * * * uucp /usr/bin/uupoll ihnp4
|
|
X 0 4,12,20 * * * uucp /usr/bin/uupoll ucbvax
|
|
.fi
|
|
This will poll
|
|
.B ihnp4
|
|
at midnight, 0800, and 1600, and
|
|
.B ucbvax
|
|
at 0400, noon, and 2000.
|
|
.PP
|
|
If the local machine is already running
|
|
.I uucico
|
|
every
|
|
hour and has a limited number of outgoing modems, a better approach
|
|
might be:
|
|
.PP
|
|
.nf
|
|
X 0 0,8,16 * * * uucp /usr/bin/uupoll -n ihnp4
|
|
X 0 4,12,20 * * * uucp /usr/bin/uupoll -n ucbvax
|
|
X 5 * * * * uucp /usr/lib/uucp/uucico -r1 -D -C
|
|
.fi
|
|
This will queue null jobs for the remote sites at the top of the hour; they
|
|
will be processed by
|
|
.I uucico
|
|
when it runs five minutes later (the -C option apply to Taylor
|
|
uucp-1.05 only, the -D option applies to Talor uucp-1.04 and up)
|
|
.SH EXTENDED options
|
|
An example of the options and how they interact is given below. The working
|
|
order while processing the options is left to right:
|
|
.nf
|
|
X uupoll -gC site1 -gB site2 -x site3 -n -gA site4 site5
|
|
.fi
|
|
.PP
|
|
this poll will:
|
|
.PP
|
|
- call immediate site1 with grade C or higher and will place a null job
|
|
.PP
|
|
- call immediate site2 with grade B or higher and will place a null job
|
|
.PP
|
|
- call immediate site3 with grade B or higher without placing a null job
|
|
.PP
|
|
- just placing a null job for site4 and site5 with grade A or higher. These
|
|
sites will be called at the next regular schedule.
|
|
.SH BUGS
|
|
When more than one site is given on the command line and no \-n option is
|
|
given there will be an immediate invocation of
|
|
.IR uucico
|
|
or
|
|
.IR autopoll
|
|
for
|
|
.IR all
|
|
sites given. That may lead to a `No port available' condition.
|
|
.SH FILES
|
|
.ta \w'/usr/spool/uucp/ 'u
|
|
.nf
|
|
/etc/uucp/ UUCP internal files/utilities
|
|
/usr/spool/uucp/ Spool directory
|
|
/tmp/poll.log This file is present only if uupoll has been
|
|
X compiled to place the messages into a file.
|
|
X Otherwise all messages will go to stderr.
|
|
X The directory as well as the name may be
|
|
X different. The name may be defined at compile time.
|
|
.fi
|
|
.SH SEE ALSO
|
|
uucp(1C), uux(1C), uucico(8C), autopoll(8C)
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/uupoll.8c ||
|
|
echo 'restore of uupoll/uupoll.8c failed'
|
|
Wc_c="`wc -c < 'uupoll/uupoll.8c'`"
|
|
test 4787 -eq "$Wc_c" ||
|
|
echo 'uupoll/uupoll.8c: original size 4787, current size' "$Wc_c"
|
|
fi
|
|
# ============= uupoll/uupoll.c ==============
|
|
if test -f 'uupoll/uupoll.c' -a X"$1" != X"-c"; then
|
|
echo 'x - skipping uupoll/uupoll.c (File already exists)'
|
|
else
|
|
echo 'x - extracting uupoll/uupoll.c (Text)'
|
|
sed 's/^X//' << 'SHAR_EOF' > 'uupoll/uupoll.c' &&
|
|
/* ---------------------------------------------------------------------------*
|
|
X
|
|
X Name: uupoll
|
|
X
|
|
X Author: Klaus Dahlenburg <kdburg@incoahe.hanse.de>
|
|
X
|
|
X Status: Public domain
|
|
X
|
|
X Copyright: none
|
|
X
|
|
X Funktion: The main intention behind this program was to get a full
|
|
X replacement of the uupoll supplied by NeXT when using an
|
|
X UUCP or a file structure that is different from that hardwired
|
|
X config in NeXT's uupoll. The lack of source made it impossible
|
|
X to modify the supplied uupoll.
|
|
X
|
|
X Call: uupoll [-n] [-x] [-g[A | 0-9,A-Z,a-z]] site ...
|
|
X
|
|
X -n just place a poll file but do not call uucico;
|
|
X This option can be given only once.
|
|
X -x meaningful only for sites not affected by the -n
|
|
X option. It prevents the creation of a poll file;
|
|
X the default is to place one. In case the poll fails
|
|
X there will be no attempt to poll those sites on
|
|
X the next general (unspecific) poll. If using
|
|
X autopoll the site will be called at the next + 1
|
|
X run of autopoll.
|
|
X -g any grade may be given to meet the criteria for
|
|
X a successful poll. The default being specified
|
|
X in conf.h (A).
|
|
X This option may be given individually for each
|
|
X site to call.
|
|
X site the name of the site to be called. As many sites
|
|
X as necessary may be specified separated by at least
|
|
X one blank.
|
|
X Note: any site will be called with the options currently in
|
|
X effect. The working order is left to right. Example:
|
|
X uupoll -gQ site1 site2 -gZ site3 -n site4
|
|
X site1 and site2 will be called immediate with grade Q
|
|
X site3 will be called immediate with grade Z. Site4 will
|
|
X have a poll file created with grade Z.
|
|
X
|
|
X Environment: NeXT 2.1
|
|
X
|
|
X Called Programs: sort, uniq, uucico (or autopoll), uuname
|
|
X
|
|
X Compile: no special options are needed
|
|
X
|
|
X Comments: - should run setuid UUCP or whatever userid is necessary to
|
|
X write to the spool directory with the proper ownership of
|
|
X the files and to run uucico.
|
|
X - No alias expansion is done on the given names.
|
|
*/
|
|
X
|
|
#if !defined(lint)
|
|
static char rcsid[] = "$Id: uupoll.c,v 2.7 1994/04/14 17:22:04 kdburg Rel $";
|
|
#endif /* not lint */
|
|
X
|
|
/* $Log: uupoll.c,v $
|
|
X * Revision 2.7 1994/04/14 17:22:04 kdburg
|
|
X * major rework done
|
|
X *
|
|
X * Revision 2.6 1994/03/26 17:38:41 kdburg
|
|
X * added support for UNAME_DIR; cleanup of some code; adjusted code after
|
|
X * obtaining sitenames via popen()
|
|
X *
|
|
X * Revision 2.5 1994/03/24 19:01:24 kdburg
|
|
X * some minor changes; some calls had their rc not checked
|
|
X *
|
|
X * Revision 2.4 1993/07/08 07:56:26 kdburg
|
|
X * befor invoking autopoll stdin is now closed to avoid blocking of
|
|
X * terminal
|
|
X *
|
|
X * Revision 2.3 1993/07/05 19:43:00 kdburg
|
|
X * when used interactivly only the start msg is put into the msg-log
|
|
X * so far defined (UULOG)
|
|
X *
|
|
X * Revision 2.2 1993/05/20 18:50:52 kdburg
|
|
X * no execute permission to the poll-pgm (uucico/autopoll) was not
|
|
X * reflected in the log; when to start message was not given when -x
|
|
X * option was present
|
|
X *
|
|
X * Revision 2.1 1993/05/16 21:48:15 kdburg
|
|
X * changed exit() to _exit() in case the exec fails within child
|
|
X *
|
|
X * Revision 2.0 1993/05/16 14:11:04 kdburg
|
|
X * initial revision
|
|
X * */
|
|
X
|
|
#define CAT 16
|
|
#define SEVERE 8
|
|
#define WARNING 4
|
|
#define OK 0
|
|
#define P_MODE 00647 /* file-mode for poll-file */
|
|
/* Boolean types */
|
|
typedef int bool;
|
|
#undef TRUE
|
|
#undef FALSE
|
|
#define TRUE (1)
|
|
#define FALSE (0)
|
|
X
|
|
#include "conf.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <sys/file.h>
|
|
#include <sys/param.h>
|
|
#include <pwd.h>
|
|
#include <sys/time.h>
|
|
X
|
|
#define X_OK 1 /* access: executable ? */
|
|
X
|
|
#ifdef ALOG_FILE
|
|
X static char Msg_Log[] = ALOG_FILE; /* name of msglog filename */
|
|
#endif
|
|
X
|
|
#ifdef UNAME_DIR
|
|
X static char subcmd[] = " | sort | uniq"; /* pipe that follows uuname */
|
|
#else /* ! UNAME_DIR */
|
|
X static char Sort[] = "uuname | sort | uniq"; /* default to obtain site names */
|
|
#endif /*UNAME_DIR */
|
|
X
|
|
static char cGrade[] = DEF_GRADE; /* grade as defined in conf.h */
|
|
static char dGrade[] = "A"; /* use this if DEF_GRADE is invalid */
|
|
#ifdef AUTO_POLL
|
|
X static char Auto_Dir[] = AUTO_DIR; /* autopoll lives here */
|
|
#else
|
|
X static char Cico_Dir[] = CICO_DIR; /* and here lives cico */
|
|
#endif /* AUTO_POLL */
|
|
X
|
|
struct Sites {
|
|
X char name[MAXHOSTNAMELEN+1]; /* name of site as supplied by uuname */
|
|
X char grade[1]; /* as passed or defaulted */
|
|
X bool flag; /* TRUE this site should be polled */
|
|
X int asap; /* 1 without -n; 2 with -x option */
|
|
};
|
|
X struct Common_Stor {
|
|
X int maxtab; /* high-water-mark for site tab */
|
|
X char *Grade; /* use this as grade for calls */
|
|
X char *Poll_Pgm; /* our name without path */
|
|
X char *called_as; /* but called by this name */
|
|
X int our_pid; /* our process-id */
|
|
X char *Uucico; /* cico's name without path */
|
|
X char This_Site[MAXHOSTNAMELEN+1]; /* our site name */
|
|
X char System[MAXHOSTNAMELEN+1]; /* intermediate to hold sitename */
|
|
X char *Usort; /* will hold uuname + subcmd */
|
|
X struct passwd *pwd;
|
|
X struct timeval tp;
|
|
X struct timezone tzp;
|
|
X struct Sites Sitetab[SITE_MAX];
|
|
X char workf[300];
|
|
X };
|
|
X
|
|
/* define the prototypes
|
|
X * */
|
|
X
|
|
int set_mlog(FILE **seclog, struct Common_Stor *);
|
|
int get_sites(struct Common_Stor *);
|
|
int Check_Args(int argc, char *argv[], struct Common_Stor *);
|
|
int Housekeeping(int argc, char *argv[], struct Common_Stor *);
|
|
int Call_Site(struct Common_Stor *);
|
|
void *storage(unsigned count, char *errloc, int *Rc, struct Common_Stor *);
|
|
X
|
|
extern int getpid();
|
|
extern void free(void *ptr);
|
|
extern int access(char *path, int mode);
|
|
extern int gethostname(char *name, int namelen);
|
|
extern int system(char *cmd);
|
|
extern int fork();
|
|
extern int execlp(char *name, char *arg0, ...);
|
|
extern void *malloc(size_t byteSize);
|
|
extern int getuid();
|
|
extern int isatty(int);
|
|
extern char *ttyname(int);
|
|
extern int open(char *path, int flags, int mode);
|
|
extern int close(int fd);
|
|
#ifdef __STRICT_ANSI__
|
|
extern FILE *popen(char *command, char *type);
|
|
extern int pclose(FILE *stream);
|
|
extern void _exit(int status);
|
|
#endif /* __STRICT_ANSI__ */
|
|
#ifdef __STRICT_BSD__
|
|
extern int fprintf(FILE *stream, const char *format, ...);
|
|
extern int fclose(FILE *stream);
|
|
extern char *strerror(int errnum);
|
|
extern int fflush(FILE *stream);
|
|
extern void exit(int status);
|
|
#endif /* __STRICT_BSD__ */
|
|
X
|
|
/* --------------------------------------------------------------------------*/
|
|
/* Main */
|
|
/* --------------------------------------------------------------------------*/
|
|
X
|
|
int main(int argc, char *argv[])
|
|
{
|
|
X
|
|
X struct Common_Stor *sCom_Sto;
|
|
X int Maxrc = OK; /* Max err-code encountered so far */
|
|
X int k = 0;
|
|
X
|
|
X if ( NULL == (sCom_Sto = malloc(sizeof(struct Common_Stor))) ) {
|
|
X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n",
|
|
X argv[0],"Common_Stor",errno,strerror(errno));
|
|
X exit (CAT);
|
|
X }
|
|
X
|
|
X Maxrc = Housekeeping(argc, argv, sCom_Sto);
|
|
X
|
|
/* If any errors popped up so far they are of such a nature that it is very
|
|
X * questionable to continue; so we better bail out in this case.
|
|
X */
|
|
X if (Maxrc <= WARNING) {
|
|
X k = Call_Site(sCom_Sto);
|
|
X Maxrc = Maxrc >= k ? Maxrc:k;
|
|
X }
|
|
X k = gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp);
|
|
X fprintf(stderr,"%s: (I) ended with rc = %i on %s\n",
|
|
X sCom_Sto->called_as,
|
|
X Maxrc,k!=0 ? "time unavailable":ctime(&sCom_Sto->tp.tv_sec));
|
|
X fclose(stderr);
|
|
X free(sCom_Sto);
|
|
X sCom_Sto = NULL;
|
|
X exit (Maxrc);
|
|
}
|
|
X
|
|
/* --------------------------------------------------------------------------*/
|
|
/* Functions */
|
|
/* --------------------------------------------------------------------------*/
|
|
X
|
|
/* --------------------------------------------------------------------
|
|
X * housekeeping
|
|
X */
|
|
X
|
|
int Housekeeping(argc, argv, sCom_Sto)
|
|
X int argc;
|
|
X char *argv[];
|
|
X struct Common_Stor *sCom_Sto; {
|
|
X
|
|
X FILE *seclog = NULL;
|
|
X int Rc = OK;
|
|
X int Rci = OK; /* intermediate rc as returnd by functions */
|
|
X
|
|
X sCom_Sto->our_pid = getpid();
|
|
X
|
|
/*
|
|
X * get our name sans path
|
|
X * */
|
|
X
|
|
X sCom_Sto->called_as = argv[0] + strlen(*argv);
|
|
X for(;sCom_Sto->called_as >= argv[0] && *--sCom_Sto->called_as != '/';)
|
|
X ;
|
|
X sCom_Sto->called_as++;
|
|
X
|
|
/* if defined set up the name of the message log file otherwise
|
|
X * stderr will be used. Setup the cmd string to obtain all known sitenames
|
|
X * which will be sorted in ascending order with duplicates removed
|
|
X * */
|
|
X
|
|
X Rc = set_mlog(&seclog, sCom_Sto);
|
|
X if (Rc > WARNING)
|
|
X return (Rc);
|
|
X
|
|
/* put out the started message including the time and the userid.
|
|
X * */
|
|
X
|
|
X sCom_Sto->pwd = getpwuid(getuid());
|
|
X
|
|
X if ((gettimeofday(&sCom_Sto->tp, &sCom_Sto->tzp)) != 0) { /* unacceptable error */
|
|
X fprintf(stderr,"%s: (C) gettimeofday() failed. Reason: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X }
|
|
X
|
|
X if (seclog != NULL) {
|
|
X fprintf(seclog,"\n%s: (I) started by `%s' (%s) on %s",
|
|
X sCom_Sto->called_as,
|
|
X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name,
|
|
X ttyname(0),
|
|
X ctime(&sCom_Sto->tp.tv_sec));
|
|
X fclose(seclog);
|
|
X }
|
|
X fprintf(stderr,"\n%s: (I) started by `%s' on %s",
|
|
X sCom_Sto->called_as,
|
|
X (sCom_Sto->pwd==NULL) ? "???":sCom_Sto->pwd->pw_name,
|
|
X ctime(&sCom_Sto->tp.tv_sec));
|
|
X
|
|
/* set up the default grade
|
|
X * */
|
|
X
|
|
X sCom_Sto->Grade = dGrade; /* set default for now */
|
|
X if (strlen(cGrade) != 1) {
|
|
X fprintf(stderr,"%s: (W) grade %s invalid; default `%s' used\n",
|
|
X sCom_Sto->called_as,cGrade,sCom_Sto->Grade);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X else
|
|
X sCom_Sto->Grade = cGrade; /* Ok, take the one from conf.h */
|
|
X
|
|
/* get the program to actually call the site. This is either UUCICO
|
|
X * or AUTOPOLL or something completely different.
|
|
X * */
|
|
X
|
|
#ifdef AUTO_POLL
|
|
X sCom_Sto->Uucico = Auto_Dir + strlen(Auto_Dir);
|
|
X for(;sCom_Sto->Uucico >= Auto_Dir && *--sCom_Sto->Uucico != '/';)
|
|
X ;
|
|
X sCom_Sto->Uucico++;
|
|
#else /* ! AUTO_POLL */
|
|
X sCom_Sto->Uucico = Cico_Dir + strlen(Cico_Dir);
|
|
X for(;sCom_Sto->Uucico >= Cico_Dir && *--sCom_Sto->Uucico != '/';)
|
|
X ;
|
|
X sCom_Sto->Uucico++;
|
|
#endif /* AUTO_POLL */
|
|
X
|
|
/* get the path to ourself.
|
|
X * */
|
|
X
|
|
X sCom_Sto->Poll_Pgm = argv[0] + strlen(argv[0]);
|
|
X for(;sCom_Sto->Poll_Pgm >= argv[0] && *--(sCom_Sto->Poll_Pgm) != '/';)
|
|
X ;
|
|
X sCom_Sto->Poll_Pgm++;
|
|
X
|
|
/* obtain our sitename
|
|
X * */
|
|
X
|
|
X if ((gethostname(sCom_Sto->This_Site,MAXHOSTNAMELEN+1)) != 0) {
|
|
X fprintf(stderr,"%s: (W) hostname could not be obtained\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = (Rc >= WARNING) ? Rc:WARNING;
|
|
X }
|
|
X
|
|
/* obtain all known sitenames
|
|
X * */
|
|
X
|
|
X Rci = get_sites(sCom_Sto);
|
|
X Rc = Rci > Rc ? Rci:Rc;
|
|
X
|
|
/* check the arguments that we are called with
|
|
X * */
|
|
X
|
|
X Rci = Check_Args(argc, argv, sCom_Sto);
|
|
X Rc = Rci > Rc ? Rci:Rc;
|
|
X
|
|
X return (Rc);
|
|
}
|
|
X
|
|
/* --------------------------------------------------------------------
|
|
X * check all relevant arguments that have been passed to us. Those args
|
|
X * that may be needed for a recall will be copied to a workfield.
|
|
X * */
|
|
X
|
|
int Check_Args(int argc, char *argv[], struct Common_Stor *sCom_Sto) {
|
|
X int i,s,k,n = 0;
|
|
X int Rc = OK;
|
|
X int One_Site = 0; /* TRUE: found at least one valid site to call */
|
|
X int poll_file = 1; /* FALSE: after -x option given */
|
|
X int def_flag = 0; /* TRUE: when option -n was encountered */
|
|
X
|
|
X /* --------------------------------------------------------------*/
|
|
X /* check the arguments passed to us */
|
|
X /* */
|
|
X /* These are: -n -> place a POLL file but do not start uucico */
|
|
X /* -x -> do not place a poll file (immed. poll only) */
|
|
X /* -g? -> specify a grade with the POLL file. The ? */
|
|
X /* may be: 0-9, A-Z, a-z */
|
|
X /* (validity not checked!) */
|
|
X /* site name of the site to call. There many be as */
|
|
X /* many as necessary separated by at least one */
|
|
X /* blank */
|
|
X /* Note: all options will stay in effect as long as they are'nt */
|
|
X /* changed by a new setting. The options -n and -x can't */
|
|
X /* be negated once given; that means place all sites */
|
|
X /* that should be immediately polled to the left of the */
|
|
X /* -n option; the same applies to the -x option which must */
|
|
X /* be left of the -n option to come into effect! */
|
|
X /* The working order is left to right! */
|
|
X /* --------------------------------------------------------------*/
|
|
X
|
|
X for (i = 1, s = 0; i < argc; i++) {
|
|
X k = strlen(argv[i]);
|
|
X switch (*argv[i]) {
|
|
X
|
|
X /* ----> handle the options */
|
|
X
|
|
X case '-':
|
|
X n = 1;
|
|
X switch (*(argv[i]+n)) {
|
|
X case 'n':
|
|
X if (k > 2) {
|
|
X fprintf(stderr,"%s: (E) invalid specification %s\n",
|
|
X sCom_Sto->called_as,argv[i]);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X break;
|
|
X }
|
|
X def_flag = 1;
|
|
X break;
|
|
X case 'x':
|
|
X if (k > 2) {
|
|
X fprintf(stderr,"%s: (E) invalid specification %s\n",
|
|
X sCom_Sto->called_as,argv[i]);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X break;
|
|
X }
|
|
X if (def_flag) {
|
|
X fprintf(stderr,"%s: (W) -x after -n has no effect\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X else {
|
|
X poll_file = 0;
|
|
X }
|
|
X break;
|
|
X case 'g':
|
|
X if (k > 3) {
|
|
X fprintf(stderr,"%s: (E) invalid specification %s\n",
|
|
X sCom_Sto->called_as,argv[i]);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X break;
|
|
X }
|
|
X if (*(argv[i]+n+1) == '\0') {
|
|
X fprintf(stderr,"%s: (E) missing grade\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X break;
|
|
X }
|
|
X if (isalnum(*(argv[i]+n+1)) == 0) {
|
|
X fprintf(stderr,"%s: (E) invalid grade %s\n",
|
|
X sCom_Sto->called_as,argv[i]);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X break;
|
|
X }
|
|
X strcpy(sCom_Sto->Grade,(argv[i]+n+1));
|
|
X break;
|
|
X default:
|
|
X fprintf(stderr,"%s: (W) missing/unknown option `-%s' ignored\n",
|
|
X sCom_Sto->called_as,argv[i]+n);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X break;
|
|
X } /* end of switch (*(argv[i]+n)) */
|
|
X break;
|
|
X
|
|
X /* ----> handle the sitenames */
|
|
X
|
|
X default:
|
|
X if (strcmp(argv[i],sCom_Sto->This_Site) == 0) {
|
|
X fprintf(stderr,"%s: (W) ignoring to call *ourself* %s\n",
|
|
X sCom_Sto->called_as,argv[i]);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X break;
|
|
X }
|
|
X strcpy(sCom_Sto->System,argv[i]);
|
|
X for(s=0;s<=sCom_Sto->maxtab;s++) {
|
|
X if ((n=strcmp(sCom_Sto->Sitetab[s].name,sCom_Sto->System)) >= 0) {
|
|
X break;
|
|
X }
|
|
X }
|
|
X if (n != 0) {
|
|
X fprintf(stderr,"%s: (W) unknown site (ignored): %s\n",
|
|
X sCom_Sto->called_as,sCom_Sto->System);
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X break;
|
|
X }
|
|
X
|
|
X /* ----> if there was no error we arrive here to save the data */
|
|
X
|
|
X strcpy(sCom_Sto->Sitetab[s].grade,sCom_Sto->Grade);
|
|
X One_Site = sCom_Sto->Sitetab[s].flag = 1; /* poll this site */
|
|
X if (def_flag)
|
|
X sCom_Sto->Sitetab[s].asap = 0; /* poll on next schedule */
|
|
X else {
|
|
X sCom_Sto->Sitetab[s].asap = 1; /* poll immediately */
|
|
X if (! poll_file)
|
|
X sCom_Sto->Sitetab[s].asap++; /* and do not place a poll file */
|
|
X }
|
|
X s++;
|
|
X break;
|
|
X } /* end of switch (*argv[i]) */
|
|
X } /* end of for(...) */
|
|
X
|
|
/* now let's check what we've gotten so far. If no valid data has been */
|
|
/* entered we will indicate that to prevent further processing */
|
|
X
|
|
X if (! One_Site) {
|
|
X fprintf(stderr,"%s: (E) found no site to call\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X
|
|
return (Rc);
|
|
}
|
|
X
|
|
int Call_Site(struct Common_Stor *sCom_Sto) {
|
|
X
|
|
/* For all sites that carry the -n flag we will place */
|
|
/* a poll file into the appropriate directory. For all others there will */
|
|
/* be an immediate call to uucico (or autopoll) */
|
|
/* Those sites that have been named on the command have the corresponding */
|
|
/* flag byte set to one. */
|
|
X
|
|
X int fdpoll; /* fildes for the poll file */
|
|
X int mode = P_MODE; /* mode for poll file */
|
|
X int i = 0;
|
|
X int Rc = OK;
|
|
X int pid = 0; /* process-id after fork() */
|
|
X
|
|
X for(i=0;(i<=sCom_Sto->maxtab);i++) {
|
|
X if (sCom_Sto->Sitetab[i].flag == 0) /* should we trigger this one ? */
|
|
X continue; /* nope */
|
|
X
|
|
/* processing done for delayed polls only */
|
|
X
|
|
X if (sCom_Sto->Sitetab[i].asap <= 1) { /* do not place a poll file */
|
|
X /* for sites that will be polled */
|
|
X /* immediate and carry the -x option */
|
|
#ifdef HAVE_SPOOLDIR_TAYLOR
|
|
X sprintf(sCom_Sto->workf,"%s/%s/C./C.%sPOLL",
|
|
X SPOOL_DIR,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X sCom_Sto->Sitetab[i].grade);
|
|
#endif
|
|
#ifdef HAVE_SPOOLDIR_HDB
|
|
X sprintf(sCom_Sto->workf,"%s/%s/C.%s%sPOLL",
|
|
X SPOOL_DIR,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X sCom_Sto->Sitetab[i].grade);
|
|
#endif
|
|
#ifdef HAVE_SPOOLDIR_BSD
|
|
X sprintf(sCom_Sto->workf,"%s/C./C.%s%sPOLL",
|
|
X SPOOL_DIR,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X sCom_Sto->Sitetab[i].grade);
|
|
#endif
|
|
X
|
|
X fflush(stderr);
|
|
X if ((fdpoll=open(sCom_Sto->workf,O_CREAT,mode)) <= 0) {
|
|
X fprintf(stderr,"%s: (E) couldn't place poll file for system: %s. Reason: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X strerror(errno));
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X else {
|
|
X if (close(fdpoll) != 0) {
|
|
X fprintf(stderr,"%s: (W) close failed for poll file; system: %s. Reason: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X strerror(errno));
|
|
X Rc = Rc >= WARNING ? Rc:WARNING;
|
|
X }
|
|
X }
|
|
X }
|
|
X
|
|
/* the following processing is done for immediate polls only
|
|
X * there is no wait for the completion of the called program that actually
|
|
X * calls the site
|
|
X * */
|
|
X
|
|
X fflush(stderr);
|
|
X if (Rc <= WARNING) {
|
|
X fprintf(stderr,"%s: (I) site %s will be called %s\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Sitetab[i].name,
|
|
X sCom_Sto->Sitetab[i].asap == 0 ?
|
|
X "upon next poll":"immediately");
|
|
X if (sCom_Sto->Sitetab[i].asap >= 1)
|
|
X {
|
|
#ifdef AUTO_DIR
|
|
X if ( access(Auto_Dir,X_OK) != 0) /* do we have xecute permission ? */
|
|
#else /* ! AUTO_DIR */
|
|
X if ( access(Cico_Dir,X_OK) != 0) /* do we have xecute permission ? */
|
|
#endif /* AUTO_DIR */
|
|
X {
|
|
X fprintf(stderr,"%s: (C) could not start %s. Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Uucico,
|
|
X errno,strerror(errno));
|
|
X return (Rc >= CAT ? Rc:CAT); /* abandon the run */
|
|
X }
|
|
X switch (pid = fork())
|
|
X {
|
|
X case -1:
|
|
X fprintf(stderr,"%s: (C) could not fork() Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,
|
|
X errno,strerror(errno));
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X case 0:
|
|
X if (isatty(0))
|
|
X close(0); /* don't block the terminal by autopoll */
|
|
#ifdef AUTO_DIR
|
|
X execlp(Auto_Dir,
|
|
#else /* ! AUTO_DIR */
|
|
X execlp(Cico_Dir,
|
|
#endif /*AUTO_DIR */
|
|
X sCom_Sto->Uucico,
|
|
X "-D", "-r1", "-s",
|
|
X sCom_Sto->Sitetab[i].name,0);
|
|
X fprintf(stderr,"%s: (C) could not start %s. Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Uucico,
|
|
X errno,strerror(errno));
|
|
X _exit (CAT); /* child: bail out */
|
|
X default:
|
|
X fflush(stderr);
|
|
X fprintf(stderr,"%s: (I) %s [%d] started; site: %s\n",
|
|
X sCom_Sto->called_as,
|
|
X sCom_Sto->Uucico,
|
|
X pid,
|
|
X sCom_Sto->Sitetab[i].name);
|
|
X } /* switch (pid = fork()) */
|
|
X } /* if (Sitetab ...) */
|
|
X } /* if (Rc ...) */
|
|
X } /* for(i=0;(i<= ...)) */
|
|
X return (Rc);
|
|
}
|
|
X
|
|
X /* ------------------------------------------------------------------
|
|
X * storage - get some memory
|
|
X */
|
|
X
|
|
void *storage(unsigned count,
|
|
X char *location,
|
|
X int *Rc,
|
|
X struct Common_Stor *sCom_Sto)
|
|
{
|
|
X void *p;
|
|
X
|
|
X if( NULL == (p= malloc(count)) ) {
|
|
X fprintf(stderr,"%s: (C) malloc failed (%s). Reason: %i (%s)\n",
|
|
X sCom_Sto->called_as,location,errno,strerror(errno));
|
|
X *Rc = *Rc >= CAT ? *Rc:CAT;
|
|
X }
|
|
X return p;
|
|
}
|
|
X
|
|
/* ------------------------------------------------------------------
|
|
X * if defined open the message log file otherwise all mesages will go
|
|
X * to stderr. If UNAME_DIR is defined construct the command to be
|
|
X * passed to popen(); if undefined the default will be used
|
|
X * */
|
|
X
|
|
int set_mlog(FILE **seclog, struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int Rc = 0;
|
|
X
|
|
#ifdef ALOG_FILE
|
|
X if (!isatty(0)) {
|
|
X if ((freopen(Msg_Log,"a",stderr)) == NULL) {
|
|
X fprintf(stdout,"%s: (C) Could not open msglog: %s\n",
|
|
X sCom_Sto->called_as,Msg_Log);
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X }
|
|
X }
|
|
X else {
|
|
X if ((*seclog = fopen(Msg_Log,"a")) == NULL) {
|
|
X fprintf(stderr,"%s: (C) Could not open msglog: %s\n",
|
|
X sCom_Sto->called_as,Msg_Log);
|
|
X return (Rc >= CAT ? Rc:CAT);
|
|
X }
|
|
X }
|
|
#endif /* ALOG_FILE */
|
|
X
|
|
/* set up the pipe together with the complete path to uuname */
|
|
X
|
|
#ifdef UNAME_DIR
|
|
X if ((sCom_Sto->Usort = (char *)storage (sizeof(UNAME_DIR)+sizeof(subcmd),
|
|
X "Sort",&Rc, sCom_Sto)) != NULL) {
|
|
X strncpy(sCom_Sto->Usort,UNAME_DIR,strlen(UNAME_DIR)); /* paste in the path */
|
|
X strcat(sCom_Sto->Usort,subcmd); /* chain the pipe to it */
|
|
X }
|
|
#else /* ! UNAME_DIR */
|
|
X sCom_Sto->Usort = &Sort; /* set pointer to uuname + sort */
|
|
#endif /* UNAME_DIR */
|
|
X
|
|
X return (Rc);
|
|
}
|
|
X
|
|
/* ------------------------------------------------------------------
|
|
X * obtain all active sitenames
|
|
X * */
|
|
X
|
|
int get_sites(struct Common_Stor *sCom_Sto) {
|
|
X
|
|
X int i = 0;
|
|
X int n;
|
|
X int Rc = 0;
|
|
X FILE *infile;
|
|
X
|
|
X if ((infile=popen(sCom_Sto->Usort,"r")) != NULL) {
|
|
X while(fgets(sCom_Sto->Sitetab[i].name,MAXHOSTNAMELEN+1,infile)) {
|
|
X if (i > SITE_MAX) { /* let'm run so that we can give */
|
|
X i++; /* the user some guidance */
|
|
X continue; /* we'll tell the user later on */
|
|
X }
|
|
X n = strlen(sCom_Sto->Sitetab[i].name)-1; /* offset: next to last char */
|
|
X sCom_Sto->Sitetab[i].name[n] = '\0'; /* strip trailing newline */
|
|
X sCom_Sto->Sitetab[i].flag = FALSE; /* TRUE: poll this site */
|
|
X sCom_Sto->Sitetab[i].asap = FALSE; /* TRUE: immediate poll */
|
|
X strcpy(sCom_Sto->Sitetab[i].grade,sCom_Sto->Grade);
|
|
X sprintf(sCom_Sto->workf,"%s%s",STATUS_DIR,sCom_Sto->Sitetab[i].name);
|
|
X sCom_Sto->maxtab = i++; /* set high-water-mark */
|
|
X }
|
|
X if (ferror(infile) != 0) {
|
|
X fprintf(stderr,"%s: (E) fgets() for sitenames failed reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X pclose(infile);
|
|
X
|
|
X /*
|
|
X * check for an empty table (strange but possible)
|
|
X */
|
|
X
|
|
X if (sCom_Sto->maxtab == 0) {
|
|
X fprintf(stderr,"%s: (E) could not obtain sitenames.\n",
|
|
X sCom_Sto->called_as);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X else {
|
|
X
|
|
X /* in case the internal table overflows we'll now give notice and tell
|
|
X * the user by which amount the table has to be increased to hold all
|
|
X * site-names
|
|
X */
|
|
X
|
|
X if (i > SITE_MAX) {
|
|
X fprintf(stderr,"%s: (E) number of sites > internal tab\n",
|
|
X sCom_Sto->called_as);
|
|
X fprintf(stderr,"%s: (E) increase SITE_MAX to >= %d and recompile\n",
|
|
X sCom_Sto->called_as,i);
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X }
|
|
X } /* sCom_Sto->maxtab == 0 */
|
|
X
|
|
X }
|
|
X else /* infile == NULL */
|
|
X {
|
|
X fprintf(stderr,"%s: (E) could not sort sitenames. Reason-code: %i (%s)\n",
|
|
X sCom_Sto->called_as,errno,strerror(errno));
|
|
X Rc = Rc >= SEVERE ? Rc:SEVERE;
|
|
X
|
|
X } /* if ((infile=popen(sCom_Sto->Usort,"r")) ... */
|
|
X
|
|
X return (Rc);
|
|
}
|
|
SHAR_EOF
|
|
chmod 0444 uupoll/uupoll.c ||
|
|
echo 'restore of uupoll/uupoll.c failed'
|
|
Wc_c="`wc -c < 'uupoll/uupoll.c'`"
|
|
test 27587 -eq "$Wc_c" ||
|
|
echo 'uupoll/uupoll.c: original size 27587, current size' "$Wc_c"
|
|
fi
|
|
exit 0
|