Taylor UUCP 1.04

This commit is contained in:
conklin 1993-08-05 18:28:27 +00:00
parent 0c36f1e1e4
commit 5afcbe9074
300 changed files with 81211 additions and 0 deletions

339
gnu/libexec/uucp/COPYING Normal file
View File

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

3152
gnu/libexec/uucp/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
# This is the Makefile for Taylor UUCP
# $Id: Makefile,v 1.4 1993/08/05 17:56:17 jtc Exp $
SUBDIR= libunix libuucp libuuconf \
cu uuchk uucico uuconv uucp uulog uuname uupick uusched \
uustat uuto uux uuxqt
.include <bsd.subdir.mk>

View File

@ -0,0 +1,30 @@
.if exists(${.CURDIR}/../libunix/obj)
LIBUNIX= $(.CURDIR)/../libunix/obj/libunix.a
.else
LIBUNIX= $(.CURDIR)/../libunix/libunix.a
.endif
.if exists(${.CURDIR}/../libuuconf/obj)
LIBUUCONF= $(.CURDIR)/../libuuconf/obj/libuuconf.a
.else
LIBUUCONF= $(.CURDIR)/../libuuconf/libuuconf.a
.endif
.if exists(${.CURDIR}/../libuucp/obj)
LIBUUCP= $(.CURDIR)/../libuucp/obj/libuucp.a
.else
LIBUUCP= $(.CURDIR)/../libuucp/libuucp.a
.endif
VERSION= 1.04
owner= uucp
bindir= /usr/bin
sbindir= /usr/libexec/uucp
# The directory to look in for new style configuration files (when
# using HAVE_TAYLOR_CONFIG).
newconfigdir= /etc/uucp
# The directory to look in for BNU (when using HAVE_BNU_CONFIG) or
# V2 (when using HAVE_V2_CONFIG) style configuration files.
oldconfigdir= /etc/uucp

207
gnu/libexec/uucp/README Normal file
View File

@ -0,0 +1,207 @@
This is the README file for version 1.04 of the Taylor UUCP package.
It was written by Ian Lance Taylor. I can be reached at ian@airs.com,
or, equivalently, uunet!cygint!airs!ian, or c/o Cygnus Support, 4th
Floor, Building 200, 1 Kendall Square, Cambridge MA, 02139, USA.
There is a mailing list for discussion of the package. To join (or
get off) the list, send mail to taylor-uucp-request@gnu.ai.mit.edu.
Mail to this address is answered by a person, not a program. When
joining the list, make sure you include the address at which you want
to receive mail in the body of your message. To send a message to the
list, send it to taylor-uucp@gnu.ai.mit.edu.
This package is covered by the Gnu Public License. See the file
COPYING for details. If you would like to do something with this
package that you feel is reasonable but you feel is prohibited by the
license, contact me to see if we can work it out.
WHAT IT IS
This is the complete source code for a Unix UUCP package. It provides
everything you need to make a UUCP connection. It includes versions
of uucico, uusched, uuxqt, uux, uucp, uustat, uulog, uuname, uuto,
uupick, and cu, as well as uuchk (a program to check configuration
files), uuconv (a program to convert from one type of configuration
file to another) and tstuu (a test harness for the package).
The Free Software Foundation plans to make this their standard UUCP
package.
The package currently supports the 'f', 'g' (in all window and packet
sizes), 'G', 't' and 'e' protocols, as well a Zmodem protocol and two
new bidirectional protocols. If you have a Berkeley sockets library,
it can make TCP connections. If you have TLI libraries, it can make
TLI connections. It supports a new configuration file mechanism which
I like (but other people dislike).
The package has a few advantages over regular UUCP:
You get the source code.
It uses significantly less CPU time than many UUCP packages.
You can specify a chat script to run when a system calls in,
allowing adjustment of modem parameters on a per system basis.
You can specify failure strings for chat scripts, allowing the
chat script to fail immediately if the modem returns ``BUSY''.
If you are talking to another instance of the package, you can use
the new bidirectional protocol for rapid data transfer in both
directions at once. You can also restrict file transfers by size
based on the time of day and who placed the call.
On the other hand:
It only runs on Unix. The code is carefully divided into system
dependent and system independent portions, so it should be
possible to port it to other systems. It would not be trivial.
You don't get uuclean, uusend, uuq, uusnap, uumonitor, uutry,
uupoll, etc. If you have current copies of these programs, you
may be able to use them. Shell scripts versions of uuclean and
uutry are provided, with most, if not all, of the functionality of
the usual programs. I believe the supplied uustat program allows
you to do everything that uuq, uusnap and uumonitor do. uupoll
could be written as a shell script.
The package does not read modemcap or acucap files, although you
can use V2 configuration files with a BNU Dialers file or a dialer
file written in my new configuration file format.
The package cannot use SCO dialer programs directly, although it
can with a simple shell script interface.
If you start using this package, I suggest that you join the mailing
list (see above) to keep up to date on patches and new versions. I am
also open to suggestions for improvements and modifications.
CHANGES SINCE 1.03
For a complete list, see ChangeLog.
IMPORTANT: the default when talking to another version of 1.04 is to
use the new bidirectional 'i' protocol. If you are using a
half-duplex modem, such as a Telebit T2500, you will want to either
mark the port as half-duplex with the ``half-duplex'' command, or
force use of the 'g' protocol by using the ``protocol'' command in the
sys or port file or by adding ``,g'' after the port name in the
Systems or L.sys or Devices file.
As usual, many bugs were fixed.
Bidirectional transfers are supported with the new 'i' protocol;
it requires an eight-bit clear datapath.
New programs: uusched, cu, uuto and uupick.
The 'G' protocol and a new Zmodem protocol were added.
A number of uustat options were added to support uuclean, and a
sample uuclean shell script was added to the contrib directory.
The uustat output formats were changed slightly.
A protocol extension eliminates transfer of the command file for
simple commands, such as rmail or rnews, when talking to another
version of 1.04.
Some TLI support was added.
UUCP forwarding was added, along with the ``forward-to'',
``forward-from'' and ``forward'' commands.
If a file transfer fails in the middle, the retry will now start
from where it left off. The implementation is compatible with
SVR4.
The work queue is checked every 10 minutes during a conversation;
if there is new work and a bidirectional protocol is not in use,
the receiving uucico requests the sender to transfer control.
The amount of free disk space is checked periodically as a file is
received, and if it drops too low the call is aborted.
The UUCP configuration file reading routines were moved into a
standalone library, uuconf. All known bugs in V2 and HDB
configuration file reading were fixed.
The ``half-duplex'' command was added for the port and dialer
files.
The ``max-retries'', ``success-wait'', ``send-request'' and
``receive-request'' commands were added for the sys file. The
``call-request'' and ``called-request'' commands were eliminated
(they did not work correctly anyhow).
\d in chat scripts now calls sleep (2) rather than sleep (1), so
it will sleep longer (on some systems sleep(1) may delay much less
than one second).
SPOOLDIR_SVR4 was added for SVR4 style spool directories.
Defaults are now permitted in the port and dialer files.
The ALIAS field is supported in the HDB Permissions file.
DOCUMENTATION
The documentation is in the file uucp.texi, which is a Texinfo file.
Texinfo is a format used by the Free Software Foundation. You can
print the documentation using TeX in combination with the file
texinfo.tex. DVI, PostScript and info versions of the documentation
are available in a separate package, uucp-doc-1.04.tar.Z.
See the TODO file for things which should be done. Please feel free
to do them, although you may want to check with me first. Send me
suggestions for new things to do.
The compilation instructions are in uucp.texi. Here is a summary.
Edit Makefile.in to set installation directories.
Type ``sh configure''. You can pass a number of arguments in the
environment (using bash or sh, enter something like ``CC=gcc
configure''; using csh, enter something like ``setenv CC gcc; sh
configure''):
CC: C compiler to use; default is gcc if it exists, else cc
CFLAGS: Flags to pass to $CC when compiling; default -g
LDFLAGS: Flags to pass to $CC when only linking; default none
LIBS: Library arguments to pass to $CC; default none
INSTALL: Install program; default install -c or cp
INSTALLDATA: Install data; default install -c -m 0644 or cp
The configure script will compile a number of test programs to see
what is available on your system, so if your system is at all
unusual you will need to pass in $CC and $LIBS correctly.
The configure script will create conf.h from conf.h.in and
Makefile from Makefile.in. It will also create config.status,
which is a shell script which actually creates the files. Please
report any configuration problems, so that they can be fixed in
later versions.
Igor V. Semenyuk provided this (lightly edited) note about ISC
Unix 3.0. The configure script will default to passing -posix to
gcc. However, using -posix changes the environment to POSIX, and
on ISC 3.0, at least, the default for POSIX_NO_TRUNC is 1. This
means nothing for uucp, but can lead to a problem when uuxqt
executes rmail. IDA sendmail has dbm configuration files named
mailertable.{dir,pag}. Notice these names are 15 characters long.
When uuxqt compiled with -posix executes rmail, which in turn
executes sendmail, the later is run under POSIX environment too!
This leads to sendmail bombing out with 'error opening 'M'
database: name too long' (mailertable.dir). It's rather obscure
behaviour, and it took me a day to find out the cause. I don't
use -posix, instead I run gcc with -D_POSIX_SOURCE, and add
-lcposix to LIBS.
Examine conf.h and Makefile to make sure they're right.
Edit policy.h for your local system.
Type ``make''.
Use ``uuchk'' to check configuration files. You can use
``uuconv'' to convert between configuration file formats.
Type ``make install'' to install.

573
gnu/libexec/uucp/TODO Normal file
View File

@ -0,0 +1,573 @@
This is a list of things to do for the Taylor UUCP package. Please
feel free to work on any of them. You may want to check with me first
to make sure that nobody else is working on them as well.
Some of these are my thoughts, but most are suggestions from other
people; I have tried to give credit. They are in the order I received
them; the missing numbers have already been implemented.
Just because something is on the list doesn't mean that I necessarily
think it is a good idea. It does mean that I think it's worth
thinking about.
2.
John Cowan <cowan@snark.thyrsus.com> says:
>I think you should accept a broader range of time specifications.
>Consider using getdate() (from your handy Usenet news source code)
>with its high-powered yacc parser.
Of course, getdate() accepts a single date, but we want a range. A
better syntax would be certainly be nice.
9.
Gordon Burditt <gordon@sneaky.lonestar.org> warns about modifications
to the TZ environment variable, to fool uucico into dialing out at an
inappropriate time.
10.
Gordon Burditt <gordon@sneaky.lonestar.org> says:
>(4) Less important, because few people will have this problem, is a
>port-specific dialcodes file. Why? Well, one system I had was connected
>to 2 inside lines "dial 9 for outside line", and one outside line (which
>doesn't want the 9). A number of the systems called were "inside", so
>you didn't add the 9 on those lines dialing from inside, but you did add
>"390" to the 4-digit number if you dialed it via "outside". Also not
>unheard of are systems with 2 outside lines that are local to different
>area codes, or one local outside line and one WATS line (which MUST
>have an area code).
>Example:
> inside-line Dialcodes outside-line Dialcodes
> pbx "" pbx "390"
> local "9" local ""
> nyc "9-1212" nyc "1212"
12.
Ralf E. Stranzenbach <ralf@reswi.ruhr.de> says:
>It would be nice to also have the option of running a shell script each time
>uucico connects/disconnects a systen. I do not mean shell scripts for dial/in.
>I would like to do some accounting and batching when the connection
>establishes.
13.
les@chinet.chi.il.us (Leslie Mikesell) writes:
>>local-send /usr/spool/uucppublic !/usr/spool/uucpublic/private
>>
>>The directories are searched from left to right, and the last one to
>>match determines whether the file may be sent or not. This is
>>slightly more general than NOWRITE, since it permits a public
>>directory within a private directory within a public directory,
>>although probably nobody will ever want that.
>
>Interesting... The obvious enhancement is to generalize to shell-like
>wild cards for the READ/WRITE/COMMANDS entries.
14.
Should there be a way for chat scripts to specify the parity to
generate? I don't think there's much point to specifying what parity
to accept.
17.
The -b and -s switches to uux are not implemented by uuxqt.
18.
If we are supposed to call a system back, we should do it immediately
rather than merely queuing up an empty command file.
22.
Add an ftp port type which uses anonymous ftp rather than any of the
UUCP protocols to do file transfers. This would allow ftp work to be
done late at night, and allow neighbors of cooperative Internet sites
to use UUCP forwarding for anonymous FTP.
31.
David Nugent: add a -C option to uucico to only call the system if
there is work to do.
32.
It would be nice if uucico could sleep until a line was available.
This is complicated by the possibility of wanting to wait for any of
several different lines, and one would really want some sort of
semaphore function to do it right. If the available lines could be
sorted, then each could be assigned to a byte in a line lock file.
Looking for a line could be done by sleeping on a read lock on all
possible lines. Once it came through, write locks would be attempted.
If they all failed, somebody else snuck in, so you would sleep on a
read lock again. This isn't great because a process could be starved,
but it might be better than nothing.
This could be tied in to uucp and uux, such that they wouldn't
actually fire up uucico unless a line was known to be available; an
additional switch would be used to fire up uucico anyhow (or one could
switch the default behaviour and the switch).
So how do you sort the lines? You could just use the index in the
port (or Devices) file, but what if multiple ports used the same
physical device? Hmmm.
43.
David Nugent: it would be nice to be able to set debugging, log, and
statistics files on a site by site basis.
Brian Murrell: heck, set those files on a port by port basis as well.
74.
Yanek Martinson: allow each system to independently choose whether to
permit shell execution.
81.
Marty Shannon: log reason for dial failure (chat-fail string) in
.Status file.
83.
Switch between 'M' and 'S' correctly in the BNU log file output.
86.
Les Mikesell: allow a separate program to be specified to handle the
communications with a particular system.
105.
T. William Wells: close and open the Debug file after each file
transfer. Alternatively, cycle through a series of Debug file names
every 1000 lines or so.
106.
Marty Shannon: add a time command for ports, to specify when they may
be used.
115.
T. William Wells: new options for uustat:
-i display job ids only
Also, there should perhaps be a configuration option to request uustat
to only display jobs submitted by the user running uustat, except for
root and uucp.
117.
Marc Unangst: provide some way to change the debugging level of a
running uucico. T. William Wells suggests having it read a file to
change arbitrary configuration information, although obviously one has
to be careful of what gets changed while a connection is active.
120.
Jarmo Raiha: new chat-fail commands: one to not update the status file
and require a retry wait, and one to permit the string to occur a few
times before reporting an error.
124.
Peter da Silva: perhaps there should be a ``chat-end-program'' command
to let a program be run after the initial handshake has been completed
and the protocol has been selected and turned on. This would let
people run stty to change their terminal parameters.
128.
Richard Stallman: have an interactive program to set up a chat script.
It would let you type directly to the port, recording what you type as
send strings and recording what comes back from the other side as
expect strings.
129.
Use POSIX fcntl locks when possible instead of creating a lock file.
130.
Chip Salzenberg: BSD lets you override the timeout for a particular
expect string by using a trailing ~.
138.
T. William Wells: BNU apparently uses a file named A.whatever to hold
the line number reached in current C. file processing. This is a
hack, and won't work right with size control anyhow, but
fsysdep_did_work could, for example, clobber the first byte in the
line to a # or something to mark that it had been finished. Still a
hack, but a better one.
139.
Patrick Smith: incorporate patches to generate full debugging traces
with less debugging file overhead. The debugging file repeats too
much information at great length right now--not good.
141.
Franc,ois Pinard: batch up pauses and delays in chat scripts and do
them all at once in a single system call. This is particularly useful
for pauses on systems which don't support subsecond sleeps. For
everything else it's a fairly minor optimization.
142.
Franc,ois Pinard: give uustat an option to requeue jobs to another
system. This only makes a lot of sense for rmail executions, but it's
fairly easy to do for any type of command. I think uucico does all
the file checking needed to ensure that this doesn't break security,
but that should be double-checked.
144.
T. William Wells: add a -g option to uucico to permit specifying the
maximum grade to be transferred at that time. This could restrict the
timegrade command further, but should not be permitted to override it.
145.
T. William Wells: if uucico or uuxqt get started with bad arguments,
put an indication in the log file since stderr may be /dev/null.
146.
Richard Todd: it would be nice to sometimes be able to request the
other side to turn on debugging.
147.
Bart Schaefer: some more possible options for uucico:
-R reverse roles (hangup immediately). Not too exciting.
some method to restrict calling to particular systems.
148.
Jarmo Raiha: some method to control the work queue at the remote end.
This could get awfully general, though.
149.
The interaction of the time command and defaults can be confusing,
since any time command in the actual system entry, even a fairly
specific one, will wipe out the default entry. Not sure what can be
done about this.
150.
Jarmo Raiha: should there be some way to specify modem initialization
strings when uucico is hanging on a port with -l or -e? This would
presumably require a new type of chat script associated with a dialer.
151.
Petri Helenius: log complete CONNECT string reported by modem, so that
the baud rate is recorded in the log file.
152.
Marc Evans: let the protocol selection be based on the CONNECT string,
so that different protocols could be selected based on what type of
connection was made.
153.
Chris Lewis: provide a signal to get a core dump even on systems which
won't do core dumps if the uid is not the euid. One could catch a
signal, call setuid (getuid ()), and then raise the signal again.
Unfortunately the core dump has to wind up in a directory which is
world writable, so that the process is able to create the core file,
but is not world readable, since that would permit anybody to read the
core dump file and extract private information from it.
154.
Les Mikesell: write a new version of dial.o, with provisions for
running a chat script.
155.
Scott Blachowicz: perhaps there should be some way to telling uucico
to not log certain errors. This could get fairly complex, though.
156.
Franc,ois Pinard: have uustat -m report the time of the last
successful conversation when reporting a failure.
158.
Thomas Fischer: should there be a way to completely disable an entry
in the sys, port or dial file? Such as a ``disable'' command?
159.
Petri Helenius: when uuxqt -s is invoked, lock uuxqt for the system so
that only one uuxqt is invoked per system. If the -c option is used,
don't lock on a per system basis, and ignore any per system locks
(regardless of -s). If neither option is used, respect existing
system and command locks, and do any other type of file.
161.
Scott Blachowicz: provide some sort of include mechanism for the
configuration files.
162.
Chris Lewis: add uuxqtpolicy command, probably in config, supporting
the following values which determine when uuxqt should be run:
- never (let cron or something else worry about it)
- perinvocation (when uucico exits for good - current behaviour)
- persite (when uucico terminates a conversation - HDBish)
- periodic (per 5 or 10 incoming X. files - BSDish)
- perturnaround?
163.
Sort jobs in the send queue by size. Pretty easy.
164.
Ed Carp: preserve files if uuxqt execution fails.
165.
Marc Sheldon: use exit codes from <sysexits.h> in uux and uucp.
166.
Chip Salzenberg: allow chat failure strings to specify a retry time.
167.
Gregory Bond: allow a dialer sequence for a TCP port, so you can make
a TCP connection to a modem and then dial out.
168.
Jose A. Manas: allow a maximum connect time, after which we try to
hang up the connection. This requires a protocol extension, since
there's no way to force the other side to hang up. The best we can do
without an extension is refuse to send any new jobs ourselves. Of
course, we could just drop the connection.
169.
Franc,ois Pinard: when given uustat -k00FC, check each possible job ID
and use it if there is an unambiguous one.
170.
T. William Wells: if ! HAVE_SETREUID && ! HAVE_SAVED_SETUID, fork a
subprocesses to revoke setuid and read the file over a pipe.
171.
Provide some option to have the internal uuconf functions not start
with an underscore.
172.
T. William Wells: have some way to configure the parity for cu.
173.
Gert Doering: uuchk should display unknown system information.
175.
T. William Wells:
Cu will not let itself be interrupted before the connection is
established. If the chat script doesn't write something, cu does
something odd, I've forgotten exactly what. Cu takes an
inordinate amount of time after the line drops to exit. Somebody,
cu, I think, but maybe uucico, drops dtr twice sometimes. Again,
somebody will attempt to write after a hangup signal has been
received. Once a hangup has been received, I/O should not be
attempted. Among other things this will save the bacon of those
who have brain damaged serial drivers (FAS, sigh, is among them)
that don't handle output properly on a dropped line.
Me:
Note that sometimes you do want to write to a line after receiving a
hangup signal. For example, you might want to use ATZ to reset a
modem.
176.
Hans-Dieter Doll: provide some way (another escape sequence) to pass
the protocol to a chat-program. Or, allow the protocol as an argument
to the chat script command, which is more general, but maybe a bit too
fancy.
177.
Nickolay Saukh: use a default port for cu, you can just do ``cu
number''.
178.
Don Phillips: should there be some way to restrict of grade of
transfers even when the other system places the call?
179.
Nickolay Saukh: add something to chat scripts to specify the timeout
for an expect string, e.g. AT\c OK\W3 to wait for 3 seconds. Except
that perhaps the unit should not be seconds. Berkeley apparently uses
~number, not \W number, but I don't see any reason to prevent use of
the ~ character in an expect string.
180.
Nickolay Saukh: if we have received a partial file, request the remote
system to start sending from that point. We currently accept SVR4
style remote file positioning requests, but we do not generate them.
181.
Mark Powell: provide some way to restrict file transfer by size as
well as grade? One way would be to let uux select the grade based on
the file size.
182.
Mark Powell: permit using multiple timetables in a single time
statement.
183.
Optionally check for interrupts in fcopy_file, since it can take a
long time to copy a file named in a uucp request.
184.
Ian Moran: if an attempt is made to a copy a file to a directory which
denies write permission, perhaps the file should be saved somewhere.
It must be saved in a private location, though.
185.
A syntax error in a command received from the remote system should not
hold up the queue. Unfortunately, I don't know what can be done
except deny the command and report it. Reporting a garbled command
error should report the command correctly, rather than just the first
character.
186.
Franc,ois Pinard: have an option to control nostop vs. stop on the cu
command line.
187.
Fix the notion of %nostop to be SVID compatible.
188.
Frank Conrad: provide a means to set the strip mode for a port, to
make it easy to use it from cu.
189.
Marc Unangst: there should be a way to specify that a system should
only be called if there are jobs of a certain grade, but if the system
is called then jobs of any grade should be transferred. This
basically means splitting the ``timegrade'' command into two commands:
``place-call-timegrade'' and ``transfer-timegrade''. Or maybe another
optional argument to ``timegrade'':
timegrade grade time-string [retry] [transfer-any]
not to mention
time time-string [retry] [transfer-any]
Or maybe a separate command for a system or port like
transfer-any BOOL
190.
Chip Salzenberg: it would be really nice if uucico could automatically
figure out when it could use an E command, so that uux didn't have to
generate it and so that uucico could use with other versions of uux.
Unfortunately, it would require uucico to read the execution file to
see if it were suitable; this would be complex, but it would probably
be worth it since normally the execution file would wind up not being
sent. Of course, the current method works too; it's just harder to
combine with other versions of UUCP.
191.
Brian J. Murrell: should there be a way to cu a specific alternate?
192.
Andrew A. Chernov: Perhaps cu -pport system should be able to try
different alternates for the system, because there might be different
phone numbers to try.
193.
Brian J. Murrell: it would be nice to be able to ^C a cu chat script
if you know it's going to fail. Right now you have to use ^\.
194.
Steven S. Dick: have some way to force uucico off the phone at a
certain time. If that is done, it might be cool to have some way to
predict how long a file transfer will take, and not do it if it will
take too long. But, if doing file restart, you can just quit and then
pick it up later.
195.
Franc,ois Pinard: if the disk fills up, or some other error occurs,
while receiving a file, perhaps it would make sense to turn the
connection around immediately and see if the other side had anything
to do, and then try again later. This would require a protocol
extension. I don't know if it's worth it. The code should be checked
to see how well it handles a disk full situation.
196.
For real adjustability, provide some mechanism for picking the lead
characters to use for the shell scripts, between : and #!.
197.
Try alternate IP addresses if there are any.
198.
Lele Gaifax: mention the device in Stats, and provide some way to
associate the entry in Log with the entry in Stats.
199.
Michael Richardson: provide some way to turn on parity for the login
chat, since some systems apparently require it. Provide some way for
cu to control parity after connecting.
200.
Chip Salzenberg: add max-remote-debug to config.
201.
Gert Doering: change the timeout message in chat scripts to reflect
which chat script timed out (dialer or login).
202.
Bill Foote: have uuchk check whether a system is defined more than
once.
203.

4
gnu/libexec/uucp/VERSION Normal file
View File

@ -0,0 +1,4 @@
Version 1.04
a complete, unmodified version of this program is available from
prep.ai.mit.edu.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,444 @@
/* conf.h. Generated automatically by configure. */
/* Configuration header file for Taylor UUCP. -*- C -*- */
/* Set MAIL_PROGRAM to a program which takes a mail address as an
argument and accepts a mail message to send to that address on
stdin (e.g. "/bin/mail"). */
#define MAIL_PROGRAM "/usr/bin/mail"
/* Set ECHO_PROGRAM to a program which echoes its arguments; if echo
is a shell builtin you can just use "echo". */
#define ECHO_PROGRAM "echo"
/* The following macros indicate what header files you have. Set the
macro to 1 if you have the corresponding header file, or 0 if you
do not. */
#define HAVE_STDDEF_H 1 /* <stddef.h> */
#define HAVE_STRING_H 1 /* <string.h> */
#define HAVE_STRINGS_H 1 /* <strings.h> */
#define HAVE_UNISTD_H 1 /* <unistd.h> */
#define HAVE_STDLIB_H 1 /* <stdlib.h> */
#define HAVE_LIMITS_H 1 /* <limits.h> */
#define HAVE_TIME_H 1 /* <time.h> */
#define HAVE_SYS_WAIT_H 1 /* <sys/wait.h> */
#define HAVE_SYS_IOCTL_H 1 /* <sys/ioctl.h> */
#define HAVE_DIRENT_H 1 /* <dirent.h> */
#define HAVE_MEMORY_H 1 /* <memory.h> */
#define HAVE_SYS_PARAM_H 1 /* <sys/param.h> */
#define HAVE_UTIME_H 1 /* <utime.h> */
#define HAVE_FCNTL_H 1 /* <fcntl.h> */
#define HAVE_SYS_FILE_H 1 /* <sys/file.h> */
#define HAVE_SYS_TIMES_H 1 /* <sys/times.h> */
#define HAVE_LIBC_H 0 /* <libc.h> */
#define HAVE_SYSEXITS_H 1 /* <sysexits.h> */
#define HAVE_POLL_H 0 /* <poll.h> */
#define HAVE_TIUSER_H 0 /* <tiuser.h> */
#define HAVE_XTI_H 0 /* <xti.h> */
#define HAVE_SYS_TLI_H 0 /* <sys/tli.h> */
#define HAVE_STROPTS_H 0 /* <stropts.h> */
#define HAVE_FTW_H 0 /* <ftw.h> */
#define HAVE_GLOB_H 1 /* <glob.h> */
#define HAVE_SYS_SELECT_H 0 /* <sys/select.h> */
#define HAVE_SYS_TYPES_TCP_H 0 /* <sys/types.tcp.h> */
/* If major and minor are not defined in <sys/types.h>, but are in
<sys/mkdev.h>, set MAJOR_IN_MKDEV to 1. If they are in
<sys/sysmacros.h>, set MAJOR_IN_SYSMACROS to 1. */
#define MAJOR_IN_MKDEV 0
#define MAJOR_IN_SYSMACROS 0
/* If the macro offsetof is not defined in <stddef.h>, you may give it
a definition here. If you do not, the code will use a definition
(in uucp.h) that should be fairly portable. */
/* #define offsetof */
/* Set RETSIGTYPE to the return type of a signal handler. On newer
systems this will be void; some older systems use int. */
#define RETSIGTYPE void
/* Set HAVE_SYS_TIME_AND_TIME_H to 1 if <time.h> and <sys/time.h> can both
be included in a single source file; if you don't have either or both of
them, it doesn't matter what you set this to. */
#define HAVE_SYS_TIME_AND_TIME_H 1
/* Set HAVE_TERMIOS_AND_SYS_IOCTL_H to 1 if <termios.h> and <sys/ioctl.h>
can both be included in a single source file; if you don't have either
or both of them, it doesn't matter what you set this to. */
#define HAVE_TERMIOS_AND_SYS_IOCTL_H 1
/* If you are configuring by hand, you should set one of the terminal
driver options in policy.h. If you are autoconfiguring, the script
will check whether your system defines CBREAK, which is a terminal
setting; if your system supports CBREAK, and you don't set a terminal
driver in policy.h, the code will assume that you have a BSD style
terminal driver. */
#define HAVE_CBREAK 1
/* The package needs several standard types. If you are using the
configure script, it will look in standard places for these types,
and give default definitions for them here if it doesn't find them.
The default definitions should work on most systems, but you may
want to check them. If you are configuring by hand, you will have
to figure out whether the types are defined on your system, and
what they should be defined to.
Any type that is not defined on your system should get a macro
definition. The definition should be of the name of the type in
all capital letters. For example, #define PID_T int. If the type
is defined in a standard header file, the macro name should not be
defined. */
/* The type pid_t is used to hold a process ID number. It is normally
defined in <sys/types.h>. This is the type returned by the
functions fork or getpid. Usually int will work fine. */
#undef PID_T
/* The type uid_t is used to hold a user ID number. It is normally
defined in <sys/types.h>. This is the type returned by the getuid
function. Usually int will work fine. */
#undef UID_T
/* The type gid_t is used to hold a group ID number. It is sometimes
defined in <sys/types.h>. This is the type returned by the getgid
function. Usually int will work fine. */
#undef GID_T
/* The type off_t is used to hold an offset in a file. It is sometimes
defined in <sys/types.h>. This is the type of the second argument to
the lseek function. Usually long will work fine. */
#undef OFF_T
/* Set HAVE_SIG_ATOMIC_T_IN_SIGNAL_H if the type sig_atomic_t is defined
in <signal.h> as required by ANSI C. */
#define HAVE_SIG_ATOMIC_T_IN_SIGNAL_H 1
/* Set HAVE_SIG_ATOMIC_T_IN_TYPES_H if the type sig_atomic_t is defined
in <sys/types.h>. This is ignored if HAVE_SIG_ATOMIC_T_IN_SIGNAL_H is
set to 1. */
#define HAVE_SIG_ATOMIC_T_IN_TYPES_H 0
/* The type sig_atomic_t is used to hold a value which may be
referenced in a single atomic operation. If it is not defined in
either <signal.h> or <sys/types.h>, you may want to give it a
definition here. If you don't, the code will use char. If your
compiler does not support sig_atomic_t, there is no type which is
really correct; fortunately, for this package it does not really
matter very much. */
#undef SIG_ATOMIC_T
/* Set HAVE_SIZE_T_IN_STDDEF_H to 1 if the type size_t is defined in
<stddef.h> as required by ANSI C. */
#define HAVE_SIZE_T_IN_STDDEF_H 1
/* Set HAVE_SIZE_T_IN_TYPES_H to 1 if the type size_t is defined in
<sys/types.h>. This is ignored if HAVE_SIZE_T_IN_STDDEF_H is set
to 1. */
#define HAVE_SIZE_T_IN_TYPES_H 1
/* The type size_t is used to hold the size of an object. In
particular, an argument of this type is passed as the size argument
to the malloc and realloc functions. If size_t is not defined in
either <stddef.h> or <sys/types.h>, you may want to give it a
definition here. If you don't, the code will use unsigned. */
#undef SIZE_T
/* Set HAVE_TIME_T_IN_TIME_H to 1 if the type time_t is defined in
<time.h>, as required by the ANSI C standard. */
#define HAVE_TIME_T_IN_TIME_H 1
/* Set HAVE_TIME_T_IN_TYPES_H to 1 if the type time_t is defined in
<sys/types.h>. This is ignored if HAVE_TIME_T_IN_TIME_H is set to
1. */
#define HAVE_TIME_T_IN_TYPES_H 1
/* When Taylor UUCP is talking to another instance of itself, it will
tell the other side the size of a file before it is transferred.
If the package can determine how much disk space is available, it
will use this information to avoid filling up the disk. Define one
of the following macros to tell the code how to determine the
amount of available disk space. It is possible that none of these
are appropriate; it will do no harm to use none of them, but, of
course, nothing will then prevent the package from filling up the
disk. Note that this space check is only useful when talking to
another instance of Taylor UUCP.
STAT_STATVFS statvfs function
STAT_STATFS2_BSIZE two argument statfs function with f_bsize field
STAT_STATFS2_FSIZE two argument statfs function with f_fsize field
STAT_STATFS2_FS_DATA two argument statfs function with fd_req field
STAT_STATFS4 four argument statfs function
STAT_USTAT the ustat function with 512 byte blocks. */
#define STAT_STATVFS 0
#define STAT_STATFS2_BSIZE 0
#define STAT_STATFS2_FSIZE 1
#define STAT_STATFS2_FS_DATA 0
#define STAT_STATFS4 0
#define STAT_USTAT 0
/* Set HAVE_VOID to 1 if the compiler supports declaring functions with
a return type of void and casting values to void. */
#define HAVE_VOID 1
/* Set HAVE_UNSIGNED_CHAR to 1 if the compiler supports the type unsigned
char. */
#define HAVE_UNSIGNED_CHAR 1
/* Set HAVE_ERRNO_DECLARATION to 1 if errno is declared in <errno.h>. */
#define HAVE_ERRNO_DECLARATION 1
/* There are now a number of functions to check for. For each of
these, the macro HAVE_FUNC should be set to 1 if your system has
FUNC. For example, HAVE_VFPRINTF should be set to 1 if your system
has vfprintf, 0 otherwise. */
/* Taylor UUCP will take advantage of the following functions if they
are available, but knows how to deal with their absence. */
#define HAVE_VFPRINTF 1
#define HAVE_FTRUNCATE 1
#define HAVE_LTRUNC 0
#define HAVE_WAITPID 1
#define HAVE_WAIT4 1
#define HAVE_GLOB 1
#define HAVE_SETREUID 1
/* There are several functions which are replaced in the subdirectory
lib. If they are missing, the configure script will automatically
add them to lib/Makefile to force them to be recompiled. If you
are configuring by hand, you will have to do this yourself. The
string @LIBOBJS@ in lib/Makefile.in should be replaced by a list of
object files in lib/Makefile. The following comments tell you
which object file names to add (they are generally fairly obvious,
given that the file names have no more than six characters before
the period). */
/* For each of these functions, if it does not exist, the indicated
object file should be added to lib/Makefile. */
#define HAVE_BSEARCH 1 /* bsrch.o */
#define HAVE_GETLINE 0 /* getlin.o */
#define HAVE_MEMCHR 1 /* memchr.o */
#define HAVE_STRDUP 1 /* strdup.o */
#define HAVE_STRSTR 1 /* strstr.o */
#define HAVE_STRTOL 1 /* strtol.o */
/* If neither of these functions exists, you should add bzero.o to
lib/Makefile. */
#define HAVE_BZERO 1
#define HAVE_MEMSET 1
/* If neither of these functions exists, you should add memcmp.o to
lib/Makefile. */
#define HAVE_MEMCMP 1
#define HAVE_BCMP 1
/* If neither of these functions exists, you should add memcpy.o to
lib/Makefile. */
#define HAVE_MEMCPY 1
#define HAVE_BCOPY 1
/* If neither of these functions exists, you should add strcas.o to
lib/Makefile. */
#define HAVE_STRCASECMP 1
#define HAVE_STRICMP 0
/* If neither of these functions exists, you should add strncs.o to
lib/Makefile. */
#define HAVE_STRNCASECMP 1
#define HAVE_STRNICMP 0
/* If neither of these functions exists, you should add strchr.o to
lib/Makefile. */
#define HAVE_STRCHR 1
#define HAVE_INDEX 1
/* If neither of these functions exists, you should add strrch.o to
lib/Makefile. */
#define HAVE_STRRCHR 1
#define HAVE_RINDEX 1
/* There are also Unix specific functions which are replaced in the
subdirectory unix. If they are missing, the configure script will
automatically add them to unix/Makefile to force them to be
recompiled. If you are configuring by hand, you will have to do
this yourself. The string @UNIXOBJS@ in unix/Makefile.in should be
replaced by a list of object files in unix/Makefile. The following
comments tell you which object file names to add. */
/* For each of these functions, if it does not exist, the indicated
object file should be added to unix/Makefile. */
#define HAVE_OPENDIR 1 /* dirent.o */
#define HAVE_DUP2 1 /* dup2.o */
#define HAVE_FTW 0 /* ftw.o */
#define HAVE_REMOVE 1 /* remove.o */
#define HAVE_RENAME 1 /* rename.o */
#define HAVE_STRERROR 1 /* strerr.o */
/* The code needs to know how to create directories. If you have the
mkdir function, set HAVE_MKDIR to 1 and replace @UUDIR@ in
Makefile.in with '# ' (the configure script will set @UUDIR@
according to the variable UUDIR). Otherwise, set HAVE_MKDIR to 0,
remove @UUDIR@ from Makefile.in, set MKDIR_PROGRAM to the name of
the program which will create a directory named on the command line
(e.g., "/bin/mkdir"), and add mkdir.o to the @UNIXOBJS@ string in
unix/Makefile.in. */
#define HAVE_MKDIR 1
#define MKDIR_PROGRAM unused
/* The code also needs to know how to remove directories. If you have
the rmdir function, set HAVE_RMDIR to 1. Otherwise, set
RMDIR_PROGRAM to the name of the program which will remove a
directory named on the command line (e.g., "/bin/rmdir") and add
rmdir.o to the @UNIXOBJS@ string in unix/Makefile.in. */
#define HAVE_RMDIR 1
#define RMDIR_PROGRAM unused
/* The code needs to know to how to get the name of the current
directory. If getcwd is available it will be used, otherwise if
getwd is available it will be used. Otherwise, set PWD_PROGRAM to
the name of the program which will print the name of the current
working directory (e.g., "/bin/pwd") and add getcwd.o to the
@UNIXOBJS@ string in unix/Makefile.in. */
#define HAVE_GETCWD 1
#define HAVE_GETWD 1
#define PWD_PROGRAM unused
/* If you have either sigsetjmp or setret, it will be used instead of
setjmp. These functions will only be used if your system restarts
system calls after interrupts (see HAVE_RESTARTABLE_SYSCALLS,
below). */
#define HAVE_SIGSETJMP 0
#define HAVE_SETRET 0
/* The code needs to know what function to use to set a signal
handler. If will try to use each of the following functions in
turn. If none are available, it will use signal, which is assumed
to always exist. */
#define HAVE_SIGACTION 1
#define HAVE_SIGVEC 1
#define HAVE_SIGSET 0
/* If the code is going to use sigvec (HAVE_SIGACTION is 0 and
HAVE_SIGVEC is 1), then HAVE_SIGVEC_SV_FLAGS must be set to 1 if
the sigvec structure contains the sv_flags field, or 0 if the
sigvec structure contains the sv_onstack field. If the code is not
going to use sigvec, it doesn't matter what this is set to. */
#define HAVE_SIGVEC_SV_FLAGS 1
/* The code will try to use each of the following functions in turn
when blocking signals from delivery. If none are available, a
relatively unimportant race condition will exist. */
#define HAVE_SIGPROCMASK 1
#define HAVE_SIGBLOCK 1
#define HAVE_SIGHOLD 0
/* If you have either of the following functions, it will be used to
determine the number of file descriptors which may be open.
Otherwise, the code will use OPEN_MAX if defined, then NOFILE if
defined, then 20. */
#define HAVE_GETDTABLESIZE 1
#define HAVE_SYSCONF 0
/* The code will use one of the following functions when detaching
from a terminal. One of these must exist. */
#define HAVE_SETPGRP 1
#define HAVE_SETSID 1
/* If you do not specify the local node name in the main configuration
file, Taylor UUCP will try to use each of the following functions
in turn. If neither is available, you must specify the local node
name in the configuration file. */
#define HAVE_GETHOSTNAME 1
#define HAVE_UNAME 0
/* The code will try to use each of the following functions in turn to
determine the current time. If none are available, it will use
time, which is assumed to always exist. */
#define HAVE_GETTIMEOFDAY 1
#define HAVE_FTIME 0
/* If neither gettimeofday nor ftime is available, the code will use
times (if available) to measure a span of time. See also the
discussion of TIMES_TICK in policy.h. */
#define HAVE_TIMES 1
/* When a chat script requests a pause of less than a second with \p,
Taylor UUCP will try to use each of the following functions in
turn. If none are available, it will sleep for a full second.
Also, the (non-portable) tstuu program requires either select or
poll. */
#define HAVE_NAPMS 0
#define HAVE_NAP 0
#define HAVE_USLEEP 1
#define HAVE_POLL 0
#define HAVE_SELECT 1
/* If the getgrent function is available, it will be used to determine
all the groups a user belongs to when checking file access
permissions. */
#define HAVE_GETGRENT 1
/* If the socket function is available, TCP support code will be
compiled in. */
#define HAVE_SOCKET 1
/* If the t_open function is available, TLI support code will be
compiled in. This may require adding a library, such as -lnsl or
-lxti, to the Makefile variables LIBS. */
#define HAVE_T_OPEN 0
/* That's the end of the list of the functions. Now there are a few
last miscellaneous items. */
/* On some systems the following functions are declared in such a way
that the code cannot make a simple extern. On other systems, these
functions are not declared at all, and the extern is required. If
a declaration of the function, as shown, compiles on your system,
set the value to 1. Not all functions declared externally are
listed here, only the ones with which I have had trouble. */
/* extern long times (); */
#define TIMES_DECLARATION_OK 0
/* extern struct passwd *getpwnam (); */
#define GETPWNAM_DECLARATION_OK 1
/* extern struct passwd *getpwuid (); */
#define GETPWUID_DECLARATION_OK 0
/* extern struct group *getgrent (); */
#define GETGRENT_DECLARATION_OK 1
/* Set HAVE_BSD_PGRP to 1 if your getpgrp call takes 1 argument and
your setpgrp calls takes 2 arguments (on System V they generally
take no arguments). You can safely set this to 1 on System V,
provided the call will compile without any errors. */
#define HAVE_BSD_PGRP 0
/* Set HAVE_UNION_WAIT to 1 if union wait is defined in the header
file <sys/wait.h>. */
#define HAVE_UNION_WAIT 1
/* Set HAVE_LONG_FILE_NAMES to 1 if the system supports file names
longer than 14 characters. */
#define HAVE_LONG_FILE_NAMES 1
/* If slow system calls are restarted after interrupts, set
HAVE_RESTARTABLE_SYSCALLS to 1. This is ignored if HAVE_SIGACTION
is 1 or if HAVE_SIGVEC is 1 and HAVE_SIGVEC_SV_FLAGS is 1 and
SV_INTERRUPT is defined in <signal.h>. In both of these cases
system calls can be prevented from restarting. */
#define HAVE_RESTARTABLE_SYSCALLS 1
/* Some systems supposedly need the following macros to be defined.
These are handled by the configure script (it will turn #undef into
#define when appropriate, which is why the peculiar #ifndef #undef
construction is used). If you are configuring by hand, you may add
appropriate definitions here, or just add them to CFLAGS when
running make. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
#ifndef _POSIX_SOURCE
#undef _POSIX_SOURCE
#endif
#ifndef _MINIX
#undef _MINIX
#endif
#ifndef _POSIX_1_SOURCE
#undef _POSIX_1_SOURCE
#endif

View File

@ -0,0 +1,552 @@
/* conn.c
Connection routines for the Taylor UUCP package.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char conn_rcsid[] = "$Id: conn.c,v 1.1 1993/08/04 19:30:39 jtc Exp $";
#endif
#include <ctype.h>
#include "uudefs.h"
#include "uuconf.h"
#include "conn.h"
static boolean fcdo_dial P((struct sconnection *qconn, pointer puuconf,
struct uuconf_dialer *qdialer,
const char *zphone, boolean ftranslate));
/* Create a new connection. This relies on system dependent functions
to set the qcmds and psysdep fields. If qport is NULL, it opens a
standard input port. */
boolean
fconn_init (qport, qconn)
struct uuconf_port *qport;
struct sconnection *qconn;
{
qconn->qport = qport;
switch (qport == NULL ? UUCONF_PORTTYPE_STDIN : qport->uuconf_ttype)
{
case UUCONF_PORTTYPE_STDIN:
return fsysdep_stdin_init (qconn);
case UUCONF_PORTTYPE_MODEM:
return fsysdep_modem_init (qconn);
case UUCONF_PORTTYPE_DIRECT:
return fsysdep_direct_init (qconn);
#if HAVE_TCP
case UUCONF_PORTTYPE_TCP:
return fsysdep_tcp_init (qconn);
#endif
#if HAVE_TLI
case UUCONF_PORTTYPE_TLI:
return fsysdep_tli_init (qconn);
#endif
default:
ulog (LOG_ERROR, "Unknown port type");
return FALSE;
}
}
/* Connection dispatch routines. */
/* Free a connection. */
void
uconn_free (qconn)
struct sconnection *qconn;
{
(*qconn->qcmds->pufree) (qconn);
}
/* Lock a connection. */
boolean
fconn_lock (qconn, fin)
struct sconnection *qconn;
boolean fin;
{
boolean (*pflock) P((struct sconnection *, boolean));
pflock = qconn->qcmds->pflock;
if (pflock == NULL)
return TRUE;
return (*pflock) (qconn, fin);
}
/* Unlock a connection. */
boolean
fconn_unlock (qconn)
struct sconnection *qconn;
{
boolean (*pfunlock) P((struct sconnection *));
pfunlock = qconn->qcmds->pfunlock;
if (pfunlock == NULL)
return TRUE;
return (*pfunlock) (qconn);
}
/* Open a connection. */
boolean
fconn_open (qconn, ibaud, ihighbaud, fwait)
struct sconnection *qconn;
long ibaud;
long ihighbaud;
boolean fwait;
{
boolean fret;
#if DEBUG > 1
if (FDEBUGGING (DEBUG_PORT))
{
char abspeed[20];
if (ibaud == (long) 0)
strcpy (abspeed, "default speed");
else
sprintf (abspeed, "speed %ld", ibaud);
if (qconn->qport == NULL)
ulog (LOG_DEBUG, "fconn_open: Opening stdin port (%s)",
abspeed);
else if (qconn->qport->uuconf_zname == NULL)
ulog (LOG_DEBUG, "fconn_open: Opening unnamed port (%s)",
abspeed);
else
ulog (LOG_DEBUG, "fconn_open: Opening port %s (%s)",
qconn->qport->uuconf_zname, abspeed);
}
#endif
/* If the system provides a range of baud rates, we select the
highest baud rate supported by the port. */
if (ihighbaud != 0 && qconn->qport != NULL)
{
struct uuconf_port *qport;
qport = qconn->qport;
ibaud = ihighbaud;
if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM)
{
if (qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud != 0)
{
if (qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud < ibaud)
ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud;
}
else if (qport->uuconf_u.uuconf_smodem.uuconf_ibaud != 0)
ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ibaud;
}
else if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT)
{
if (qport->uuconf_u.uuconf_sdirect.uuconf_ibaud != 0)
ibaud = qport->uuconf_u.uuconf_sdirect.uuconf_ibaud;
}
}
/* This will normally be overridden by the port specific open
routine. */
if (qconn->qport == NULL)
ulog_device ("stdin");
else
ulog_device (qconn->qport->uuconf_zname);
fret = (*qconn->qcmds->pfopen) (qconn, ibaud, fwait);
if (! fret)
ulog_device ((const char *) NULL);
return fret;
}
/* Close a connection. */
boolean
fconn_close (qconn, puuconf, qdialer, fsuccess)
struct sconnection *qconn;
pointer puuconf;
struct uuconf_dialer *qdialer;
boolean fsuccess;
{
boolean fret;
DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_close: Closing connection");
/* Don't report hangup signals while we're closing. */
fLog_sighup = FALSE;
fret = (*qconn->qcmds->pfclose) (qconn, puuconf, qdialer, fsuccess);
/* Make sure any signal reporting has been done before we set
fLog_sighup back to TRUE. */
ulog (LOG_ERROR, (const char *) NULL);
fLog_sighup = TRUE;
ulog_device ((const char *) NULL);
return fret;
}
/* Reset the connection. */
boolean
fconn_reset (qconn)
struct sconnection *qconn;
{
DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_reset: Resetting connection");
return (*qconn->qcmds->pfreset) (qconn);
}
/* Dial out on the connection. */
boolean
fconn_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound)
struct sconnection *qconn;
pointer puuconf;
const struct uuconf_system *qsys;
const char *zphone;
struct uuconf_dialer *qdialer;
enum tdialerfound *ptdialerfound;
{
struct uuconf_dialer sdialer;
enum tdialerfound tfound;
boolean (*pfdial) P((struct sconnection *, pointer,
const struct uuconf_system *, const char *,
struct uuconf_dialer *, enum tdialerfound *));
if (qdialer == NULL)
qdialer = &sdialer;
if (ptdialerfound == NULL)
ptdialerfound = &tfound;
qdialer->uuconf_zname = NULL;
*ptdialerfound = DIALERFOUND_FALSE;
pfdial = qconn->qcmds->pfdial;
if (pfdial == NULL)
return TRUE;
return (*pfdial) (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound);
}
/* Read data from the connection. */
boolean
fconn_read (qconn, zbuf, pclen, cmin, ctimeout, freport)
struct sconnection *qconn;
char *zbuf;
size_t *pclen;
size_t cmin;
int ctimeout;
boolean freport;
{
boolean fret;
fret = (*qconn->qcmds->pfread) (qconn, zbuf, pclen, cmin, ctimeout,
freport);
#if DEBUG > 1
if (FDEBUGGING (DEBUG_INCOMING))
udebug_buffer ("fconn_read: Read", zbuf, *pclen);
else if (FDEBUGGING (DEBUG_PORT))
ulog (LOG_DEBUG, "fconn_read: Read %lu", (unsigned long) *pclen);
#endif
return fret;
}
/* Write data to the connection. */
boolean
fconn_write (qconn, zbuf, clen)
struct sconnection *qconn;
const char *zbuf;
size_t clen;
{
#if DEBUG > 1
if (FDEBUGGING (DEBUG_OUTGOING))
udebug_buffer ("fconn_write: Writing", zbuf, clen);
else if (FDEBUGGING (DEBUG_PORT))
ulog (LOG_DEBUG, "fconn_write: Writing %lu", (unsigned long) clen);
#endif
return (*qconn->qcmds->pfwrite) (qconn, zbuf, clen);
}
/* Read and write data. */
boolean
fconn_io (qconn, zwrite, pcwrite, zread, pcread)
struct sconnection *qconn;
const char *zwrite;
size_t *pcwrite;
char *zread;
size_t *pcread;
{
boolean fret;
#if DEBUG > 1
size_t cwrite = *pcwrite;
size_t cread = *pcread;
if (cread == 0 || cwrite == 0)
ulog (LOG_FATAL, "fconn_io: cread %lu; cwrite %lu",
(unsigned long) cread, (unsigned long) cwrite);
#endif
#if DEBUG > 1
if (FDEBUGGING (DEBUG_OUTGOING))
udebug_buffer ("fconn_io: Writing", zwrite, cwrite);
#endif
fret = (*qconn->qcmds->pfio) (qconn, zwrite, pcwrite, zread, pcread);
DEBUG_MESSAGE4 (DEBUG_PORT,
"fconn_io: Wrote %lu of %lu, read %lu of %lu",
(unsigned long) *pcwrite, (unsigned long) cwrite,
(unsigned long) *pcread, (unsigned long) cread);
#if DEBUG > 1
if (*pcread > 0 && FDEBUGGING (DEBUG_INCOMING))
udebug_buffer ("fconn_io: Read", zread, *pcread);
#endif
return fret;
}
/* Send a break character to a connection. Some port types may not
support break characters, in which case we just return TRUE. */
boolean
fconn_break (qconn)
struct sconnection *qconn;
{
boolean (*pfbreak) P((struct sconnection *));
pfbreak = *qconn->qcmds->pfbreak;
if (pfbreak == NULL)
return TRUE;
DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_break: Sending break character");
return (*pfbreak) (qconn);
}
/* Change the setting of a connection. Some port types may not
support this, in which case we just return TRUE. */
boolean
fconn_set (qconn, tparity, tstrip, txonxoff)
struct sconnection *qconn;
enum tparitysetting tparity;
enum tstripsetting tstrip;
enum txonxoffsetting txonxoff;
{
boolean (*pfset) P((struct sconnection *, enum tparitysetting,
enum tstripsetting, enum txonxoffsetting));
pfset = qconn->qcmds->pfset;
if (pfset == NULL)
return TRUE;
DEBUG_MESSAGE3 (DEBUG_PORT,
"fconn_set: Changing setting to %d, %d, %d",
(int) tparity, (int) tstrip, (int) txonxoff);
return (*pfset) (qconn, tparity, tstrip, txonxoff);
}
/* Require or ignore carrier on a connection. */
boolean
fconn_carrier (qconn, fcarrier)
struct sconnection *qconn;
boolean fcarrier;
{
boolean (*pfcarrier) P((struct sconnection *, boolean));
pfcarrier = qconn->qcmds->pfcarrier;
if (pfcarrier == NULL)
return TRUE;
return (*pfcarrier) (qconn, fcarrier);
}
/* Run a chat program on a connection. */
boolean
fconn_run_chat (qconn, pzprog)
struct sconnection *qconn;
char **pzprog;
{
return (*qconn->qcmds->pfchat) (qconn, pzprog);
}
/* Get the baud rate of a connection. */
long
iconn_baud (qconn)
struct sconnection *qconn;
{
long (*pibaud) P((struct sconnection *));
pibaud = qconn->qcmds->pibaud;
if (pibaud == NULL)
return 0;
return (*pibaud) (qconn);
}
/* Modem dialing routines. */
/*ARGSUSED*/
boolean
fmodem_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound)
struct sconnection *qconn;
pointer puuconf;
const struct uuconf_system *qsys;
const char *zphone;
struct uuconf_dialer *qdialer;
enum tdialerfound *ptdialerfound;
{
*ptdialerfound = DIALERFOUND_FALSE;
if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL)
{
char **pz;
boolean ffirst;
/* The pzdialer field is a sequence of dialer/token pairs. The
dialer portion names a dialer to use. The token portion is
what \D and \T in the chat script expand to. If there is no
token for the last dialer, the phone number for the system is
used. */
ffirst = TRUE;
pz = qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer;
while (*pz != NULL)
{
int iuuconf;
struct uuconf_dialer *q;
struct uuconf_dialer s;
const char *ztoken;
boolean ftranslate;
if (! ffirst)
q = &s;
else
q = qdialer;
iuuconf = uuconf_dialer_info (puuconf, *pz, q);
if (iuuconf == UUCONF_NOT_FOUND)
{
ulog (LOG_ERROR, "%s: Dialer not found", *pz);
return FALSE;
}
else if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
return FALSE;
}
++pz;
ztoken = *pz;
ftranslate = FALSE;
if (ztoken == NULL
|| strcmp (ztoken, "\\D") == 0)
ztoken = zphone;
else if (strcmp (ztoken, "\\T") == 0)
{
ztoken = zphone;
ftranslate = TRUE;
}
if (! fcdo_dial (qconn, puuconf, q, ztoken, ftranslate))
{
(void) uuconf_dialer_free (puuconf, q);
if (! ffirst)
(void) uuconf_dialer_free (puuconf, qdialer);
return FALSE;
}
if (ffirst)
{
*ptdialerfound = DIALERFOUND_FREE;
ffirst = FALSE;
}
else
(void) uuconf_dialer_free (puuconf, q);
if (*pz != NULL)
++pz;
}
return TRUE;
}
else if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer != NULL)
{
struct uuconf_dialer *q;
q = qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer;
*qdialer = *q;
*ptdialerfound = DIALERFOUND_TRUE;
return fcdo_dial (qconn, puuconf, q, zphone, FALSE);
}
else
{
ulog (LOG_ERROR, "No dialer information");
return FALSE;
}
}
/* Actually use a dialer. We set up the modem (which may include
opening the dialer device), run the chat script, and finish dealing
with the modem. */
static boolean
fcdo_dial (qconn, puuconf, qdial, zphone, ftranslate)
struct sconnection *qconn;
pointer puuconf;
struct uuconf_dialer *qdial;
const char *zphone;
boolean ftranslate;
{
const char *zname;
if (! fsysdep_modem_begin_dial (qconn, qdial))
return FALSE;
if (qconn->qport == NULL)
zname = NULL;
else
zname = qconn->qport->uuconf_zname;
if (! fchat (qconn, puuconf, &qdial->uuconf_schat,
(const struct uuconf_system *) NULL, qdial,
zphone, ftranslate, zname, iconn_baud (qconn)))
return FALSE;
return fsysdep_modem_end_dial (qconn, qdial);
}

View File

@ -0,0 +1,312 @@
/* conn.h
Header file for routines which manipulate connections.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#ifndef CONN_H
#define CONN_H
#if ANSI_C
/* These structures are used in prototypes but are not defined in this
header file. */
struct uuconf_system;
struct uuconf_dialer;
struct uuconf_chat;
#endif
/* This structure represents a connection. */
struct sconnection
{
/* Pointer to command table for this type of connection. */
const struct sconncmds *qcmds;
/* Pointer to system dependent information. */
pointer psysdep;
/* Pointer to system independent information. */
struct uuconf_port *qport;
};
/* Whether fconn_dial got a dialer. */
enum tdialerfound
{
/* Did not find a dialer. */
DIALERFOUND_FALSE,
/* Found a dialer which does not need to be freed. */
DIALERFOUND_TRUE,
/* Found a dialer which does need to be freed. */
DIALERFOUND_FREE
};
/* Parity settings to pass to fconn_set. */
enum tparitysetting
{
/* Do not change output parity generation. */
PARITYSETTING_DEFAULT,
/* No parity (all eight output bits used). */
PARITYSETTING_NONE,
/* Even parity. */
PARITYSETTING_EVEN,
/* Odd parity. */
PARITYSETTING_ODD,
/* Mark parity. */
PARITYSETTING_MARK,
/* Space parity. */
PARITYSETTING_SPACE
};
/* Type of strip control argument to fconn_set. */
enum tstripsetting
{
/* Do not change the stripping of input characters. */
STRIPSETTING_DEFAULT,
/* Do not strip input characters to seven bits. */
STRIPSETTING_EIGHTBITS,
/* Strip input characters to seven bits. */
STRIPSETTING_SEVENBITS
};
/* Type of XON/XOFF control argument to fconn_set. */
enum txonxoffsetting
{
/* Do not change XON/XOFF handshake setting. */
XONXOFF_DEFAULT,
/* Do not do XON/XOFF handshaking. */
XONXOFF_OFF,
/* Do XON/XOFF handshaking. */
XONXOFF_ON
};
/* A command table holds the functions which implement actions for
each different kind of connection. */
struct sconncmds
{
/* Free up a connection. */
void (*pufree) P((struct sconnection *qconn));
/* Lock the connection. The fin argument is TRUE if the connection
is to be used for an incoming call. May be NULL. */
boolean (*pflock) P((struct sconnection *qconn, boolean fin));
/* Unlock the connection. May be NULL. */
boolean (*pfunlock) P((struct sconnection *qconn));
/* Open the connection. */
boolean (*pfopen) P((struct sconnection *qconn, long ibaud,
boolean fwait));
/* Close the connection. */
boolean (*pfclose) P((struct sconnection *qconn,
pointer puuconf,
struct uuconf_dialer *qdialer,
boolean fsuccess));
/* Reset the connection so that another call may be accepted. */
boolean (*pfreset) P((struct sconnection *qconn));
/* Dial a number on a connection. This set *qdialer to the dialer
used, if any, and sets *ptdialerfound appropriately. The qsys
and zphone arguments are for the chat script. This field may be
NULL. */
boolean (*pfdial) P((struct sconnection *qconn, pointer puuconf,
const struct uuconf_system *qsys,
const char *zphone,
struct uuconf_dialer *qdialer,
enum tdialerfound *ptdialerfound));
/* Read data from a connection, with a timeout in seconds. When
called *pclen is the length of the buffer; on successful return
*pclen is the number of bytes read into the buffer. The cmin
argument is the minimum number of bytes to read before returning
ahead of a timeout. */
boolean (*pfread) P((struct sconnection *qconn, char *zbuf, size_t *pclen,
size_t cmin, int ctimeout, boolean freport));
/* Write data to the connection. */
boolean (*pfwrite) P((struct sconnection *qconn, const char *zbuf,
size_t clen));
/* Read and write data to the connection. This reads and writes
data until either all passed in data has been written or the read
buffer has been filled. When called *pcread is the size of the
read buffer and *pcwrite is the number of bytes to write; on
successful return *pcread is the number of bytes read and
*pcwrite is the number of bytes written. */
boolean (*pfio) P((struct sconnection *qconn, const char *zwrite,
size_t *pcwrite, char *zread, size_t *pcread));
/* Send a break character. This field may be NULL. */
boolean (*pfbreak) P((struct sconnection *qconn));
/* Change the connection setting. This field may be NULL. */
boolean (*pfset) P((struct sconnection *qconn,
enum tparitysetting tparity,
enum tstripsetting tstrip,
enum txonxoffsetting txonxoff));
/* Require or ignore carrer. This field may be NULL. */
boolean (*pfcarrier) P((struct sconnection *qconn,
boolean fcarrier));
/* Run a chat program on a connection. */
boolean (*pfchat) P((struct sconnection *qconn, char **pzprog));
/* Get the baud rate of a connection. This field may be NULL. */
long (*pibaud) P((struct sconnection *qconn));
};
/* Connection functions. */
/* Initialize a connection. This must be called before any of the
other connection functions are called. It initializes the fields
of qconn. It returns FALSE on error. */
extern boolean fconn_init P((struct uuconf_port *qport,
struct sconnection *qconn));
/* Free up connection data. */
extern void uconn_free P((struct sconnection *qconn));
/* Lock a connection. The fin argument is TRUE if the port is to be
used for an incoming call; certains type of Unix locking need this
information because they need to open the port. */
extern boolean fconn_lock P((struct sconnection *qconn, boolean fin));
/* Unlock a connection. */
extern boolean fconn_unlock P((struct sconnection *qconn));
/* Open a connection. If ibaud is 0, the natural baud rate of the
port is used. If ihighbaud is not 0, fconn_open chooses the
highest supported baud rate between ibaud and ihighbaud. If fwait
is TRUE, this should wait for an incoming call. */
extern boolean fconn_open P((struct sconnection *qconn, long ibaud,
long ihighbaud, boolean fwait));
/* Close a connection. The fsuccess argument is TRUE if the
conversation completed normally, FALSE if it is being aborted. */
extern boolean fconn_close P((struct sconnection *qconn,
pointer puuconf,
struct uuconf_dialer *qdialer,
boolean fsuccess));
/* Reset a connection such that another call may be accepted. */
extern boolean fconn_reset P((struct sconnection *q));
/* Dial out on a connection. The qsys and zphone arguments are for
the chat scripts; zphone is the phone number to dial. If qdialer
is not NULL, *qdialer will be set to the dialer information used if
any; *ptdialerfound will be set appropriately. */
extern boolean fconn_dial P((struct sconnection *q, pointer puuconf,
const struct uuconf_system *qsys,
const char *zphone,
struct uuconf_dialer *qdialer,
enum tdialerfound *ptdialerfound));
/* Read from a connection.
zbuf -- buffer to read bytes into
*pclen on call -- length of zbuf
*pclen on successful return -- number of bytes read
cmin -- minimum number of bytes to read before returning ahead of timeout
ctimeout -- timeout in seconds, 0 if none
freport -- whether to report errors. */
extern boolean fconn_read P((struct sconnection *qconn, char *zbuf,
size_t *pclen, size_t cmin,
int ctimeout, boolean freport));
/* Write to a connection. */
extern boolean fconn_write P((struct sconnection *qconn, const char *zbuf,
size_t cbytes));
/* Read and write to a connection. This reads and writes data until
either all passed-in data has been written or the read buffer is
full.
zwrite -- buffer to write bytes from
*pcwrite on call -- number of bytes to write
*pcwrite on successful return -- number of bytes written
zread -- buffer to read bytes into
*pcread on call -- size of read buffer
*pcread on successful return -- number of bytes read. */
extern boolean fconn_io P((struct sconnection *qconn, const char *zwrite,
size_t *pcwrite, char *zread, size_t *pcread));
/* Send a break character to a connection. */
extern boolean fconn_break P((struct sconnection *qconn));
/* Change the settings of a connection. This allows independent
control over the parity of output characters, whether to strip
input characters, and whether to do XON/XOFF handshaking. There is
no explicit control over parity checking of input characters. This
function returns FALSE on error. Attempts to set values not
supported by the hardware are silently ignored. */
extern boolean fconn_set P((struct sconnection *qconn,
enum tparitysetting tparity,
enum tstripsetting tstrip,
enum txonxoffsetting txonxoff));
/* Get the baud rate of a connection. */
extern long iconn_baud P((struct sconnection *qconn));
/* Do a chat script with a system. */
extern boolean fchat P((struct sconnection *qconn, pointer puuconf,
const struct uuconf_chat *qchat,
const struct uuconf_system *qsys,
const struct uuconf_dialer *qdialer,
const char *zphone, boolean ftranslate,
const char *zport, long ibaud));
/* Tell the connection to either require or ignore carrier as fcarrier
is TRUE or FALSE respectively. This is called with fcarrier TRUE
when \m is encountered in a chat script, and with fcarrier FALSE
when \M is encountered. */
extern boolean fconn_carrier P((struct sconnection *qconn,
boolean fcarrier));
/* Run a chat program on a connection. */
extern boolean fconn_run_chat P((struct sconnection *qconn,
char **pzprog));
/* Dialing out on a modem is partially system independent. This is
the modem dialing routine. */
extern boolean fmodem_dial P((struct sconnection *qconn, pointer puuconf,
const struct uuconf_system *qsys,
const char *zphone,
struct uuconf_dialer *qdialer,
enum tdialerfound *ptdialerfound));
/* Begin dialing out. This should open the dialer device if there is
one, toggle DTR if requested and possible, and tell the port to
ignore carrier. It should return FALSE on error. */
extern boolean fsysdep_modem_begin_dial P((struct sconnection *qconn,
struct uuconf_dialer *qdial));
/* Finish dialing out on a modem. This should close the dialer device
if there is one. If the dialer and the port both support carrier,
the connection should be told to pay attention to carrier. If it
is possible to wait for carrier to come on, and the dialer and the
port both the port support carrier, it should wait until carrier
comes on. */
extern boolean fsysdep_modem_end_dial P((struct sconnection *qconn,
struct uuconf_dialer *qdial));
/* System dependent initialization routines. */
extern boolean fsysdep_stdin_init P((struct sconnection *qconn));
extern boolean fsysdep_modem_init P((struct sconnection *qconn));
extern boolean fsysdep_direct_init P((struct sconnection *qconn));
#if HAVE_TCP
extern boolean fsysdep_tcp_init P((struct sconnection *qconn));
#endif
#if HAVE_TLI
extern boolean fsysdep_tli_init P((struct sconnection *qconn));
#endif
#endif /* ! defined (CONN_H) */

View File

@ -0,0 +1,202 @@
/* copy.c
Copy one file to another for the UUCP package.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char copy_rcsid[] = "$Id: copy.c,v 1.1 1993/08/04 19:30:44 jtc Exp $";
#endif
#include "uudefs.h"
#include "system.h"
#include "sysdep.h"
#include <stdio.h>
#include <errno.h>
/* Copy one file to another. */
#if USE_STDIO
boolean
fcopy_file (zfrom, zto, fpublic, fmkdirs)
const char *zfrom;
const char *zto;
boolean fpublic;
boolean fmkdirs;
{
FILE *efrom;
boolean fret;
efrom = fopen (zfrom, BINREAD);
if (efrom == NULL)
{
ulog (LOG_ERROR, "fopen (%s): %s", zfrom, strerror (errno));
return FALSE;
}
fret = fcopy_open_file (efrom, zto, fpublic, fmkdirs);
(void) fclose (efrom);
return fret;
}
boolean
fcopy_open_file (efrom, zto, fpublic, fmkdirs)
FILE *efrom;
const char *zto;
boolean fpublic;
boolean fmkdirs;
{
FILE *eto;
char ab[8192];
int c;
eto = esysdep_fopen (zto, fpublic, FALSE, fmkdirs);
if (eto == NULL)
return FALSE;
while ((c = fread (ab, sizeof (char), sizeof ab, efrom)) != 0)
{
if (fwrite (ab, sizeof (char), (size_t) c, eto) != c)
{
ulog (LOG_ERROR, "fwrite: %s", strerror (errno));
(void) fclose (eto);
(void) remove (zto);
return FALSE;
}
}
if (fclose (eto) != 0)
{
ulog (LOG_ERROR, "fclose: %s", strerror (errno));
(void) remove (zto);
return FALSE;
}
return TRUE;
}
#else /* ! USE_STDIO */
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
boolean
fcopy_file (zfrom, zto, fpublic, fmkdirs)
const char *zfrom;
const char *zto;
boolean fpublic;
boolean fmkdirs;
{
int ofrom;
boolean fret;
ofrom = open (zfrom, O_RDONLY | O_NOCTTY, 0);
if (ofrom < 0)
{
ulog (LOG_ERROR, "open (%s): %s", zfrom, strerror (errno));
return FALSE;
}
fret = fcopy_open_file (ofrom, zto, fpublic, fmkdirs);
(void) close (ofrom);
return fret;
}
boolean
fcopy_open_file (ofrom, zto, fpublic, fmkdirs)
int ofrom;
const char *zto;
boolean fpublic;
boolean fmkdirs;
{
int oto;
char ab[8192];
int c;
/* These file mode arguments are from the UNIX version of sysdep.h;
each system dependent header file will need their own
definitions. */
oto = creat (zto, fpublic ? IPUBLIC_FILE_MODE : IPRIVATE_FILE_MODE);
if (oto < 0)
{
if (errno == ENOENT && fmkdirs)
{
if (! fsysdep_make_dirs (zto, fpublic))
return FALSE;
oto = creat (zto,
fpublic ? IPUBLIC_FILE_MODE : IPRIVATE_FILE_MODE);
}
if (oto < 0)
{
ulog (LOG_ERROR, "open (%s): %s", zto, strerror (errno));
return FALSE;
}
}
while ((c = read (ofrom, ab, sizeof ab)) > 0)
{
if (write (oto, ab, (size_t) c) != c)
{
ulog (LOG_ERROR, "write: %s", strerror (errno));
(void) close (oto);
(void) remove (zto);
return FALSE;
}
}
if (close (oto) < 0)
{
ulog (LOG_ERROR, "close: %s", strerror (errno));
(void) remove (zto);
return FALSE;
}
if (c < 0)
{
ulog (LOG_ERROR, "read: %s", strerror (errno));
(void) remove (zto);
return FALSE;
}
return TRUE;
}
#endif /* ! USE_STDIO */

View File

@ -0,0 +1,80 @@
/* cu.h
Header file for cu.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
/* The user settable variables supported by cu. */
/* The escape character used to introduce a special command. The
escape character is the first character of this string. */
extern const char *zCuvar_escape;
/* Whether to delay for a second before printing the host name after
seeing an escape character. */
extern boolean fCuvar_delay;
/* The input characters which finish a line. The escape character is
only recognized following one of these characters. */
extern const char *zCuvar_eol;
/* Whether to transfer binary data (nonprintable characters other than
newline and tab) when sending a file. If this is FALSE, then
newline is changed to carriage return. */
extern boolean fCuvar_binary;
/* A prefix string to use before sending a binary character from a
file; this is only used if fCuvar_binary is TRUE. */
extern const char *zCuvar_binary_prefix;
/* Whether to check for echoes of characters sent when sending a file.
This is ignored if fCuvar_binary is TRUE. */
extern boolean fCuvar_echocheck;
/* A character to look for after each newline is sent when sending a
file. The character is the first character in this string, except
that a '\0' means that no echo check is done. */
extern const char *zCuvar_echonl;
/* The timeout to use when looking for an character. */
extern int cCuvar_timeout;
/* The character to use to kill a line if an echo check fails. The
first character in this string is sent. */
extern const char *zCuvar_kill;
/* The number of times to try resending a line if the echo check keeps
failing. */
extern int cCuvar_resend;
/* The string to send at the end of a file sent with ~>. */
extern const char *zCuvar_eofwrite;
/* The string to look for to finish a file received with ~<. For tip
this is a collection of single characters, but I don't want to do
that because it means that there are characters which cannot be
received. */
extern const char *zCuvar_eofread;
/* Whether to provide verbose information when sending or receiving a
file. */
extern boolean fCuvar_verbose;

View File

@ -0,0 +1,120 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
This file was modified slightly by Ian Lance Taylor, November 1992,
for Taylor UUCP. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* Ian Lance Taylor <ian@airs.com> added the following defines for
Taylor UUCP. This avoids reported conflicts with system getopt
definitions. */
#define getopt gnu_getopt
#define optarg gnu_optarg
#define optind gnu_optind
#define opterr gnu_opterr
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
enum _argtype
{
no_argument,
required_argument,
optional_argument
};
extern int getopt P((int argc, char *const *argv, const char *shortopts));
extern int getopt_long P((int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind));
extern int getopt_long_only P((int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind));
/* Internal only. Users should not call this directly. */
extern int _getopt_internal P((int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only));
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

View File

@ -0,0 +1,699 @@
/* log.c
Routines to add entries to the log files.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char log_rcsid[] = "$Id: log.c,v 1.1 1993/08/04 19:30:50 jtc Exp $";
#endif
#include <errno.h>
#if ANSI_C
#include <stdarg.h>
#endif
#if HAVE_TIME_H
#include <time.h>
#endif
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
/* Local functions. */
static const char *zldate_and_time P((void));
/* Log file name. */
static const char *zLogfile;
/* The function to call when a LOG_FATAL error occurs. */
static void (*pfLfatal) P((void));
/* Whether to go to a file. */
static boolean fLfile;
/* ID number. */
static int iLid;
/* The current user name. */
static char *zLuser;
/* The current system name. */
static char *zLsystem;
/* The current device name. */
char *zLdevice;
/* The open log file. */
static FILE *eLlog;
/* Whether we have tried to open the log file. We need this because
we don't want to keep trying to open the log file if we failed the
first time. It can't be static because under HAVE_HDB_LOGGING we
may have to write to various different log files. */
static boolean fLlog_tried;
#if DEBUG > 1
/* Debugging file name. */
static const char *zLdebugfile;
/* The open debugging file. */
static FILE *eLdebug;
/* Whether we've tried to open the debugging file. */
static boolean fLdebug_tried;
/* Whether we've written out any debugging information. */
static boolean fLdebugging;
#endif
/* Statistics file name. */
static const char *zLstatsfile;
/* The open statistics file. */
static FILE *eLstats;
/* Whether we've tried to open the statistics file. */
static boolean fLstats_tried;
/* The array of signals. The elements are only set to TRUE by the
default signal handler. They are only set to FALSE if we don't
care whether we got the signal or not. */
volatile sig_atomic_t afSignal[INDEXSIG_COUNT];
/* The array of signals to log. The elements are only set to TRUE by
the default signal handler. They are set to FALSE when the signal
is logged in ulog. This means that if a signal comes in at just
the right time we won't log it (or, rather, we'll log it once
instead of twice), but that is not a catatrophe. */
volatile sig_atomic_t afLog_signal[INDEXSIG_COUNT];
/* Flag that indicates SIGHUP is worth logging. */
boolean fLog_sighup = TRUE;
/* Signal names to use when logging signals. */
static const char * const azSignal_names[INDEXSIG_COUNT] = INDEXSIG_NAMES;
/* If not NULL, ulog calls this function before outputting anything.
This is used to support cu. */
void (*pfLstart) P((void));
/* If not NULL, ulog calls this function after outputting everything.
This is used to support cu. */
void (*pfLend) P((void));
/* Set the function to call on a LOG_FATAL error. */
void
ulog_fatal_fn (pfn)
void (*pfn) P((void));
{
pfLfatal = pfn;
}
/* Decide whether to send log message to the file or not. */
void
ulog_to_file (puuconf, ffile)
pointer puuconf;
boolean ffile;
{
int iuuconf;
iuuconf = uuconf_logfile (puuconf, &zLogfile);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
#if DEBUG > 1
iuuconf = uuconf_debugfile (puuconf, &zLdebugfile);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
#endif
iuuconf = uuconf_statsfile (puuconf, &zLstatsfile);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
fLfile = ffile;
}
/* Set the ID number. This will be called by the usysdep_initialize
if there is something sensible to set it to. */
void
ulog_id (i)
int i;
{
iLid = i;
}
/* Set the user we are making log entries for. The arguments will be
copied into memory. */
void
ulog_user (zuser)
const char *zuser;
{
ubuffree (zLuser);
zLuser = zbufcpy (zuser);
}
/* Set the system name we are making log entries for. The name is copied
into memory. */
void
ulog_system (zsystem)
const char *zsystem;
{
if (zsystem == NULL
|| zLsystem == NULL
|| strcmp (zsystem, zLsystem) != 0)
{
ubuffree (zLsystem);
zLsystem = zbufcpy (zsystem);
#if HAVE_HDB_LOGGING
/* Under HDB logging we now must write to a different log file. */
ulog_close ();
#endif /* HAVE_HDB_LOGGING */
}
}
/* Set the device name. This is copied into memory. */
void
ulog_device (zdevice)
const char *zdevice;
{
ubuffree (zLdevice);
zLdevice = zbufcpy (zdevice);
}
/* Make a log entry. We make a token concession to non ANSI_C systems,
but it clearly won't always work. */
#if ! ANSI_C
#undef HAVE_VFPRINTF
#endif
/*VARARGS2*/
#if HAVE_VFPRINTF
void
ulog (enum tlog ttype, const char *zmsg, ...)
#else
void
ulog (ttype, zmsg, a, b, c, d, f, g, h, i, j)
enum tlog ttype;
const char *zmsg;
#endif
{
#if HAVE_VFPRINTF
va_list parg;
#endif
FILE *e, *edebug;
boolean fstart, fend;
const char *zhdr, *zstr;
/* Log any received signal. We do it this way to avoid calling ulog
from the signal handler. A few routines call ulog to get this
message out with zmsg == NULL. */
{
static boolean fdoing_sigs;
if (! fdoing_sigs)
{
int isig;
fdoing_sigs = TRUE;
for (isig = 0; isig < INDEXSIG_COUNT; isig++)
{
if (afLog_signal[isig])
{
afLog_signal[isig] = FALSE;
/* Apparently SunOS sends SIGINT rather than SIGHUP
when hanging up, so we don't log either signal if
fLog_sighup is FALSE. */
if ((isig != INDEXSIG_SIGHUP && isig != INDEXSIG_SIGINT)
|| fLog_sighup)
ulog (LOG_ERROR, "Got %s signal", azSignal_names[isig]);
}
}
fdoing_sigs = FALSE;
}
}
if (zmsg == NULL)
return;
#if DEBUG > 1
/* If we've had a debugging file open in the past, then we want to
write all log file entries to the debugging file even if it's
currently closed. */
if (fLfile
&& eLdebug == NULL
&& ! fLdebug_tried
&& (fLdebugging || (int) ttype >= (int) LOG_DEBUG))
{
fLdebug_tried = TRUE;
eLdebug = esysdep_fopen (zLdebugfile, FALSE, TRUE, TRUE);
fLdebugging = TRUE;
}
#endif /* DEBUG > 1 */
if (! fLfile)
e = stderr;
#if DEBUG > 1
else if ((int) ttype >= (int) LOG_DEBUG)
{
e = eLdebug;
/* If we can't open the debugging file, don't output any
debugging messages. */
if (e == NULL)
return;
}
#endif /* DEBUG > 1 */
else
{
if (eLlog == NULL && ! fLlog_tried)
{
fLlog_tried = TRUE;
#if ! HAVE_HDB_LOGGING
eLlog = esysdep_fopen (zLogfile, TRUE, TRUE, TRUE);
#else /* HAVE_HDB_LOGGING */
{
const char *zsys;
char *zfile;
/* We want to write to .Log/program/system, e.g.
.Log/uucico/uunet. The system name may not be set. */
if (zLsystem == NULL)
zsys = "ANY";
else
zsys = zLsystem;
zfile = zbufalc (strlen (zLogfile)
+ strlen (abProgram)
+ strlen (zsys)
+ 1);
sprintf (zfile, zLogfile, abProgram, zsys);
eLlog = esysdep_fopen (zfile, TRUE, TRUE, TRUE);
ubuffree (zfile);
}
#endif /* HAVE_HDB_LOGGING */
if (eLlog == NULL)
{
/* We can't open the log file. We don't even have a
safe way to report this problem, since we may not be
able to write to stderr (it may, for example, be
attached to the incoming call). */
if (pfLfatal != NULL)
(*pfLfatal) ();
usysdep_exit (FALSE);
}
}
e = eLlog;
/* eLlog might be NULL here because we might try to open the log
file recursively via esysdep_fopen. */
if (e == NULL)
return;
}
if (pfLstart != NULL)
(*pfLstart) ();
edebug = NULL;
#if DEBUG > 1
if ((int) ttype < (int) LOG_DEBUG)
edebug = eLdebug;
#endif
fstart = TRUE;
fend = TRUE;
switch (ttype)
{
case LOG_NORMAL:
zhdr = "";
break;
case LOG_ERROR:
zhdr = "ERROR: ";
break;
case LOG_FATAL:
zhdr = "FATAL: ";
break;
#if DEBUG > 1
case LOG_DEBUG:
zhdr = "DEBUG: ";
break;
case LOG_DEBUG_START:
zhdr = "DEBUG: ";
fend = FALSE;
break;
case LOG_DEBUG_CONTINUE:
zhdr = NULL;
fstart = FALSE;
fend = FALSE;
break;
case LOG_DEBUG_END:
zhdr = NULL;
fstart = FALSE;
break;
#endif
default:
zhdr = "???: ";
break;
}
if (fstart)
{
if (! fLfile)
{
fprintf (e, "%s: ", abProgram);
if (edebug != NULL)
fprintf (edebug, "%s: ", abProgram);
}
else
{
#if HAVE_TAYLOR_LOGGING
fprintf (e, "%s ", abProgram);
if (edebug != NULL)
fprintf (edebug, "%s ", abProgram);
#else /* ! HAVE_TAYLOR_LOGGING */
fprintf (e, "%s ", zLuser == NULL ? "uucp" : zLuser);
if (edebug != NULL)
fprintf (edebug, "%s ", zLuser == NULL ? "uucp" : zLuser);
#endif /* HAVE_TAYLOR_LOGGING */
fprintf (e, "%s ", zLsystem == NULL ? "-" : zLsystem);
if (edebug != NULL)
fprintf (edebug, "%s ", zLsystem == NULL ? "-" : zLsystem);
#if HAVE_TAYLOR_LOGGING
fprintf (e, "%s ", zLuser == NULL ? "-" : zLuser);
if (edebug != NULL)
fprintf (edebug, "%s ", zLuser == NULL ? "-" : zLuser);
#endif /* HAVE_TAYLOR_LOGGING */
zstr = zldate_and_time ();
fprintf (e, "(%s", zstr);
if (edebug != NULL)
fprintf (edebug, "(%s", zstr);
if (iLid != 0)
{
#if ! HAVE_HDB_LOGGING
#if HAVE_TAYLOR_LOGGING
fprintf (e, " %d", iLid);
if (edebug != NULL)
fprintf (edebug, " %d", iLid);
#else /* ! HAVE_TAYLOR_LOGGING */
fprintf (e, "-%d", iLid);
if (edebug != NULL)
fprintf (edebug, "-%d", iLid);
#endif /* ! HAVE_TAYLOR_LOGGING */
#else /* HAVE_HDB_LOGGING */
/* I assume that the second number here is meant to be
some sort of file sequence number, and that it should
correspond to the sequence number in the statistics
file. I don't have any really convenient way to do
this, so I won't unless somebody thinks it's very
important. */
fprintf (e, ",%d,%d", iLid, 0);
if (edebug != NULL)
fprintf (edebug, ",%d,%d", iLid, 0);
#endif /* HAVE_HDB_LOGGING */
}
fprintf (e, ") ");
if (edebug != NULL)
fprintf (edebug, ") ");
fprintf (e, "%s", zhdr);
if (edebug != NULL)
fprintf (edebug, "%s", zhdr);
}
}
#if HAVE_VFPRINTF
va_start (parg, zmsg);
vfprintf (e, zmsg, parg);
va_end (parg);
if (edebug != NULL)
{
va_start (parg, zmsg);
vfprintf (edebug, zmsg, parg);
va_end (parg);
}
#else /* ! HAVE_VFPRINTF */
fprintf (e, zmsg, a, b, c, d, f, g, h, i, j);
if (edebug != NULL)
fprintf (edebug, zmsg, a, b, c, d, f, g, h, i, j);
#endif /* ! HAVE_VFPRINTF */
if (fend)
{
fprintf (e, "\n");
if (edebug != NULL)
fprintf (edebug, "\n");
}
(void) fflush (e);
if (edebug != NULL)
(void) fflush (edebug);
if (pfLend != NULL)
(*pfLend) ();
if (ttype == LOG_FATAL)
{
if (pfLfatal != NULL)
(*pfLfatal) ();
usysdep_exit (FALSE);
}
#if CLOSE_LOGFILES
ulog_close ();
#endif
}
/* Log a uuconf error. */
void
ulog_uuconf (ttype, puuconf, iuuconf)
enum tlog ttype;
pointer puuconf;
int iuuconf;
{
char ab[512];
(void) uuconf_error_string (puuconf, iuuconf, ab, sizeof ab);
ulog (ttype, "%s", ab);
}
/* Close the log file. There's nothing useful we can do with errors,
so we don't check for them. */
void
ulog_close ()
{
/* Make sure we logged any signal we received. */
ulog (LOG_ERROR, (const char *) NULL);
if (eLlog != NULL)
{
(void) fclose (eLlog);
eLlog = NULL;
fLlog_tried = FALSE;
}
#if DEBUG > 1
if (eLdebug != NULL)
{
(void) fclose (eLdebug);
eLdebug = NULL;
fLdebug_tried = FALSE;
}
#endif
}
/* Add an entry to the statistics file. We may eventually want to put
failed file transfers in here, but we currently do not. */
/*ARGSUSED*/
void
ustats (fsucceeded, zuser, zsystem, fsent, cbytes, csecs, cmicros, fmaster)
boolean fsucceeded;
const char *zuser;
const char *zsystem;
boolean fsent;
long cbytes;
long csecs;
long cmicros;
boolean fmaster;
{
long cbps;
/* The seconds and microseconds are now counted independently, so
they may be out of synch. */
if (cmicros < 0)
{
csecs -= ((- cmicros) / 1000000L) + 1;
cmicros = 1000000L - ((- cmicros) % 1000000L);
}
if (cmicros >= 1000000L)
{
csecs += cmicros / 10000000L;
cmicros = cmicros % 1000000L;
}
/* On a system which can determine microseconds we might very well
have both csecs == 0 and cmicros == 0. */
if (csecs == 0 && cmicros < 1000)
cbps = 0;
else
{
long cmillis;
/* This computation will not overflow provided csecs < 2147483
and cbytes and cbps both fit in a long. */
cmillis = csecs * 1000 + cmicros / 1000;
cbps = ((cbytes / cmillis) * 1000
+ ((cbytes % cmillis) * 1000) / cmillis);
}
if (eLstats == NULL)
{
if (fLstats_tried)
return;
fLstats_tried = TRUE;
eLstats = esysdep_fopen (zLstatsfile, TRUE, TRUE, TRUE);
if (eLstats == NULL)
return;
}
#if HAVE_TAYLOR_LOGGING
fprintf (eLstats,
"%s %s (%s) %s%s %ld bytes in %ld.%03ld seconds (%ld bytes/sec)\n",
zuser, zsystem, zldate_and_time (),
fsucceeded ? "" : "failed after ",
fsent ? "sent" : "received",
cbytes, csecs, cmicros / 1000, cbps);
#endif /* HAVE_TAYLOR_LOGGING */
#if HAVE_V2_LOGGING
fprintf (eLstats,
"%s %s (%s) (%ld) %s %s %ld bytes %ld seconds\n",
zuser, zsystem, zldate_and_time (),
(long) time ((time_t *) NULL),
fsent ? "sent" : "received",
fsucceeded ? "data" : "failed after",
cbytes, csecs + cmicros / 500000);
#endif /* HAVE_V2_LOGGING */
#if HAVE_HDB_LOGGING
{
static int iseq;
/* I don't know what the 'C' means. The sequence number should
probably correspond to the sequence number in the log file, but
that is currently always 0; using this fake sequence number
will still at least reveal which transfers are from different
calls. We don't report a failed data transfer with this
format. */
if (! fsucceeded)
return;
++iseq;
fprintf (eLstats,
"%s!%s %c (%s) (C,%d,%d) [%s] %s %ld / %ld.%03ld secs, %ld %s\n",
zsystem, zuser, fmaster ? 'M' : 'S', zldate_and_time (),
iLid, iseq, zLdevice == NULL ? "unknown" : zLdevice,
fsent ? "->" : "<-",
cbytes, csecs, cmicros / 1000, cbps,
"bytes/sec");
}
#endif /* HAVE_HDB_LOGGING */
(void) fflush (eLstats);
#if CLOSE_LOGFILES
ustats_close ();
#endif
}
/* Close the statistics file. */
void
ustats_close ()
{
if (eLstats != NULL)
{
if (fclose (eLstats) != 0)
ulog (LOG_ERROR, "fclose: %s", strerror (errno));
eLstats = NULL;
fLstats_tried = FALSE;
}
}
/* Return the date and time in a form used for a log entry. */
static const char *
zldate_and_time ()
{
long isecs, imicros;
struct tm s;
#if HAVE_TAYLOR_LOGGING
static char ab[sizeof "1991-12-31 12:00:00.00"];
#endif
#if HAVE_V2_LOGGING
static char ab[sizeof "12/31-12:00"];
#endif
#if HAVE_HDB_LOGGING
static char ab[sizeof "12/31-12:00:00"];
#endif
isecs = ixsysdep_time (&imicros);
usysdep_localtime (isecs, &s);
#if HAVE_TAYLOR_LOGGING
sprintf (ab, "%04d-%02d-%02d %02d:%02d:%02d.%02d",
s.tm_year + 1900, s.tm_mon + 1, s.tm_mday, s.tm_hour,
s.tm_min, s.tm_sec, (int) (imicros / 10000));
#endif
#if HAVE_V2_LOGGING
sprintf (ab, "%d/%d-%02d:%02d", s.tm_mon + 1, s.tm_mday,
s.tm_hour, s.tm_min);
#endif
#if HAVE_HDB_LOGGING
sprintf (ab, "%d/%d-%02d:%02d:%02d", s.tm_mon + 1, s.tm_mday,
s.tm_hour, s.tm_min, s.tm_sec);
#endif
return ab;
}

View File

@ -0,0 +1,521 @@
/* policy.h
Configuration file for policy decisions. To be edited on site.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
/* This header file contains macro definitions which must be set by
each site before compilation. The first few are system
characteristics that can not be easily discovered by the
configuration script. Most are configuration decisions that must
be made by the local administrator. */
/* System characteristics. */
/* This code tries to use several ANSI C features, including
prototypes, stdarg.h, the const qualifier and the types void
(including void * pointers) and unsigned char. By default it will
use these features if the compiler defines __STDC__. If your
compiler supports these features but does not define __STDC__, you
should set ANSI_C to 1. If your compiler does not support these
features but defines __STDC__ (no compiler should do this, in my
opinion), you should set ANSI_C to 0. In most cases (or if you're
not sure) just leave the line below commented out. */
/* #define ANSI_C 1 */
/* Set USE_STDIO to 1 if data files should be read using the stdio
routines (fopen, fread, etc.) rather than the UNIX unbuffered I/O
calls (open, read, etc.). Unless you know your stdio is really
rotten, you should leave this as 1. */
#define USE_STDIO 1
/* Exactly one of the following macros must be set to 1. Many modern
systems support more than one of these choices through some form of
compilation environment, in which case the setting will depend on
the compilation environment you use. If you have a reasonable
choice between options, I suspect that TERMIO or TERMIOS will be
more efficient than TTY, but I have not done any head to head
comparisons.
If you don't set any of these macros, the code below will guess.
It will doubtless be wrong on some systems.
HAVE_BSD_TTY -- Use the 4.2BSD tty routines
HAVE_SYSV_TERMIO -- Use the System V termio routines
HAVE_POSIX_TERMIOS -- Use the POSIX termios routines
*/
#define HAVE_BSD_TTY 0
#define HAVE_SYSV_TERMIO 0
#define HAVE_POSIX_TERMIOS 1
/* This code tries to guess which terminal driver to use if you did
not make a choice above. It is in this file to make it easy to
figure out what's happening if something goes wrong. */
#if HAVE_BSD_TTY + HAVE_SYSV_TERMIO + HAVE_POSIX_TERMIOS == 0
#if HAVE_CBREAK
#undef HAVE_BSD_TTY
#define HAVE_BSD_TTY 1
#else
#undef HAVE_SYSV_TERMIO
#define HAVE_SYSV_TERMIO 1
#endif
#endif
/* On some systems a write to a serial port will block even if the
file descriptor has been set to not block. File transfer can be
more efficient if the package knows that a write to the serial port
will not block; however, if the write does block unexpectedly then
data loss is possible at high speeds.
If writes to a serial port always block even when requested not to,
you should set HAVE_UNBLOCKED_WRITES to 0; otherwise you should set
it to 1. In general on System V releases without STREAMS-based
ttys (e.g., before SVR4) HAVE_UNBLOCKED_WRITES should be 0 and on
BSD or SVR4 it should be 1.
If HAVE_UNBLOCKED_WRITES is set to 1 when it should be 0 you may
see an unexpectedly large number of transmission errors, or, if you
have hardware handshaking, transfer times may be lower than
expected (but then, they always are). If HAVE_UNBLOCKED_WRITES is
set to 0 when it should be 1, file transfer will use more CPU time
than necessary. If you are unsure, setting HAVE_UNBLOCKED_WRITES
to 0 should always be safe. */
#define HAVE_UNBLOCKED_WRITES 1
/* When the code does do a blocking write, it wants to write the
largest amount of data which the kernel will accept as a single
unit. On BSD this is typically the value of OBUFSIZ in
<sys/tty.h>, usually 100. On System V before SVR4 this is
typically the size of a clist, CLSIZE in <sys/tty.h>, which is
usually 64. On SVR4, which uses STREAMS-based ttys, 2048 is
reasonable. Define SINGLE_WRITE to the correct value for your
system. If SINGLE_WRITE is too large, data loss may occur. If
SINGLE_WRITE is too small, file transfer will use more CPU time
than necessary. If you have no idea, 64 should work on most modern
systems. */
#define SINGLE_WRITE 100
/* Some tty drivers, such as those from SCO and AT&T's Unix PC, have a
bug in the implementation of ioctl() that causes CLOCAL to be
ineffective until the port is opened a second time. If
HAVE_CLOCAL_BUG is set to 1, code will be added to do this second
open on the port. Set this if you are getting messages that say
"Line disconnected" while in the dial chat script after only
writing the first few characters to the port. This bug causes the
resetting of CLOCAL to have no effect, so the "\m" (require
carrier) escape sequence won't function properly in dialer chat
scripts. */
#define HAVE_CLOCAL_BUG 0
/* On some systems, such as SCO Xenix, resetting DTR on a port
apparently prevents getty from working on the port, and thus
prevents anybody from dialing in. If HAVE_RESET_BUG is set to 1,
DTR will not be reset when a serial port is closed. */
#define HAVE_RESET_BUG 0
/* The Sony NEWS reportedly handles no parity by clearing both the odd
and even parity bits in the sgtty structure, unlike most BSD based
systems in which no parity is indicated by setting both the odd and
even parity bits. Setting HAVE_PARITY_BUG to 1 will handle this
correctly. */
#define HAVE_PARITY_BUG 0
#if HAVE_BSD_TTY
#ifdef sony
#undef HAVE_PARITY_BUG
#define HAVE_PARITY_BUG 1
#endif
#endif
/* On Ultrix 4.0, at least, setting CBREAK causes input characters to
be stripped, regardless of the setting of LPASS8 and LLITOUT. This
can be worked around by using the termio call to reset ISTRIP.
This probably does not apply to any other operating system.
Setting HAVE_STRIP_BUG to 1 will use this workaround. */
#define HAVE_STRIP_BUG 0
#if HAVE_BSD_TTY
#ifdef ultrix
#undef HAVE_STRIP_BUG
#define HAVE_STRIP_BUG 1
#endif
#endif
/* TIMES_TICK is the fraction of a second which times(2) returns (for
example, if times returns 100ths of a second TIMES_TICK should be
set to 100). On a true POSIX system (one which has the sysconf
function and also has _SC_CLK_TCK defined in <unistd.h>) TIMES_TICK
may simply be left as 0. On some systems the environment variable
HZ is what you want for TIMES_TICK, but on some other systems HZ
has the wrong value; check the man page. If you leave this set to
0, the code will try to guess; it will doubtless be wrong on some
non-POSIX systems. If TIMES_TICK is wrong the code may report
incorrect file transfer times in the statistics file, but on many
systems times(2) will actually not be used and this value will not
matter at all. */
#define TIMES_TICK 0
/* If your system does not support saved set user ID, set
HAVE_SAVED_SETUID to 0. However, this is ignored if your system
has the setreuid function. Most modern Unixes have one or the
other. If your system has the setreuid function, don't worry about
this define, or about the following discussion.
If you set HAVE_SAVED_SETUID to 0, you will not be able to use uucp
to transfer files that the uucp user can not read. Basically, you
will only be able to use uucp on world-readable files. If you set
HAVE_SAVED_SETUID to 1, but your system does not have saved set
user ID, uucp will fail with an error message whenever anybody
other than the uucp user uses it. */
#define HAVE_SAVED_SETUID 1
/* On some systems, such as the DG Aviion and, possibly, the RS/6000,
the setreuid function is broken. It should be possible to use
setreuid to swap the real and effective user ID's, but on some
systems it will not change the real user ID (I believe this is due
to a misreading of the POSIX standard). On such a system you must
set HAVE_BROKEN_SETREUID to 1; if you do not, you will get error
messages from setreuid. Systems on which setreuid exists but is
broken pretty much always have saved setuid. */
#define HAVE_BROKEN_SETREUID 0
/* On the 3B2, and possibly other systems, nap takes an argument in
hundredths of a second rather than milliseconds. I don't know of
any way to test for this. Set HAVE_HUNDREDTHS_NAP to 1 if this is
true on your system. This does not matter if your system does not
have the nap function. */
#define HAVE_HUNDREDTHS_NAP 0
/* Set PS_PROGRAM to the program to run to get a process status,
including the arguments to pass it. This is used by ``uustat -p''.
Set HAVE_PS_MULTIPLE to 1 if a comma separated list of process
numbers may be appended (e.g. ``ps -flp1,10,100''). Otherwise ps
will be invoked several times, with a single process number append
each time. The default definitions should work on most systems,
although some (such as the NeXT) will complain about the 'p'
option; for those, use the second set of definitions. The third
set of definitions are appropriate for System V. To use the second
or third set of definitions, change the ``#if 1'' to ``#if 0'' and
change the appropriate ``#if 0'' to ``#if 1''. */
#if 1
#define PS_PROGRAM "/bin/ps -lp"
#define HAVE_PS_MULTIPLE 0
#endif
#if 0
#define PS_PROGRAM "/bin/ps -l"
#define HAVE_PS_MULTIPLE 0
#endif
#if 0
#define PS_PROGRAM "/bin/ps -flp"
#define HAVE_PS_MULTIPLE 1
#endif
/* If you use other programs that also lock devices, such as cu or
uugetty, the other programs and UUCP must agree on whether a device
is locked. This is typically done by creating a lock file in a
specific directory; the lock files are generally named
LCK..something or LK.something. If the LOCKDIR macro is defined,
these lock files will be placed in the named directory; otherwise
they will be placed in the default spool directory. On some HDB
systems the lock files are placed in /etc/locks. On some they are
placed in /usr/spool/locks. On the NeXT they are placed in
/usr/spool/uucp/LCK. */
/* #define LOCKDIR "/usr/spool/uucp" */
/* #define LOCKDIR "/etc/locks" */
/* #define LOCKDIR "/usr/spool/locks" */
/* #define LOCKDIR "/usr/spool/uucp/LCK" */
#define LOCKDIR "/var/spool/lock"
/* You must also specify the format of the lock files by setting
exactly one of the following macros to 1. Check an existing lock
file to decide which of these choices is more appropriate.
The HDB style is to write the locking process ID in ASCII, passed
to ten characters, followed by a newline.
The V2 style is to write the locking process ID as four binary
bytes in the host byte order. Many BSD derived systems use this
type of lock file, including the NeXT.
SCO lock files are similar to HDB lock files, but always lock the
lowercase version of the tty (i.e., LCK..tty2a is created if you
are locking tty2A). They are appropriate if you are using Taylor
UUCP on an SCO Unix, SCO Xenix, or SCO Open Desktop system.
SVR4 lock files are also similar to HDB lock files, but they use a
different naming convention. The filenames are LK.xxx.yyy.zzz,
where xxx is the major device number of the device holding the
special device file, yyy is the major device number of the port
device itself, and zzz is the minor device number of the port
device.
Coherent use a completely different method of terminal locking.
See unix/cohtty for details. For locks other than for terminals,
HDB type lock files are used. */
#define HAVE_V2_LOCKFILES 0
#define HAVE_HDB_LOCKFILES 1
#define HAVE_SCO_LOCKFILES 0
#define HAVE_SVR4_LOCKFILES 0
#define HAVE_COHERENT_LOCKFILES 0
/* If your system supports Internet mail addresses (which look like
user@host.domain rather than system!user), HAVE_INTERNET_MAIL
should be set to 1. This is checked by uuxqt when sending error
(or success, if requested) notifications to the person who
submitted the job. */
#define HAVE_INTERNET_MAIL 1
/* Adminstrative decisions. */
/* Set USE_RCS_ID to 1 if you want the RCS ID strings compiled into
the executable. Leaving them out will decrease the executable
size. Leaving them in will make it easier to determine which
version you are running. */
#define USE_RCS_ID 1
/* DEBUG controls how much debugging information is compiled into the
code. If DEBUG is defined as 0, no sanity checks will be done and
no debugging messages will be compiled in. If DEBUG is defined as
1 sanity checks will be done but there will still be no debugging
messages. If DEBUG is 2 than debugging messages will be compiled
in. When initially testing, DEBUG should be 2, and you should
probably leave it at 2 unless a small reduction in the executable
file size will be very helpful. */
#define DEBUG 2
/* Set the default grade to use for a uucp command if the -g option is
not used. The grades, from highest to lowest, are 0 to 9, A to Z,
a to z. */
#define BDEFAULT_UUCP_GRADE ('N')
/* Set the default grade to use for a uux command if the -g option is
not used. */
#define BDEFAULT_UUX_GRADE ('N')
/* To compile in use of the new style of configuration files described
in the documentation, set HAVE_TAYLOR_CONFIG to 1. */
#define HAVE_TAYLOR_CONFIG 1
/* To compile in use of V2 style configuration files (L.sys, L-devices
and so on), set HAVE_V2_CONFIG to 1. To compile in use of HDB
style configuration files (Systems, Devices and so on) set
HAVE_HDB_CONFIG to 1. The files will be looked up in the
oldconfigdir directory as defined in the Makefile.
You may set any or all of HAVE_TAYLOR_CONFIG, HAVE_V2_CONFIG and
HAVE_HDB_CONFIG to 1 (you must set at least one of the macros).
When looking something up (a system, a port, etc.) the new style
configuration files will be read first, followed by the V2
configuration files, followed by the HDB configuration files. */
#define HAVE_V2_CONFIG 1
#define HAVE_HDB_CONFIG 1
/* Exactly one of the following macros must be set to 1. The exact
format of the spool directories is explained in unix/spool.c.
SPOOLDIR_V2 -- Use a Version 2 (original UUCP) style spool directory
SPOOLDIR_BSD42 -- Use a BSD 4.2 style spool directory
SPOOLDIR_BSD43 -- Use a BSD 4.3 style spool directory
SPOOLDIR_HDB -- Use a HDB (BNU) style spool directory
SPOOLDIR_ULTRIX -- Use an Ultrix style spool directory
SPOOLDIR_SVR4 -- Use a System V Release 4 spool directory
SPOOLDIR_TAYLOR -- Use a new style spool directory
If you are not worried about compatibility with a currently running
UUCP, use SPOOLDIR_TAYLOR. */
#define SPOOLDIR_V2 0
#define SPOOLDIR_BSD42 0
#define SPOOLDIR_BSD43 0
#define SPOOLDIR_HDB 0
#define SPOOLDIR_ULTRIX 0
#define SPOOLDIR_SVR4 0
#define SPOOLDIR_TAYLOR 1
/* You must select which type of logging you want by setting exactly
one of the following to 1. These control output to the log file
and to the statistics file.
If you define HAVE_TAYLOR_LOGGING, each line in the log file will
look something like this:
uucico uunet uucp (1991-12-10 09:04:34.45 16390) Receiving uunet/D./D.uunetSwJ72
and each line in the statistics file will look something like this:
uucp uunet (1991-12-10 09:04:40.20) received 2371 bytes in 5 seconds (474 bytes/sec)
If you define HAVE_V2_LOGGING, each line in the log file will look
something like this:
uucico uunet uucp (12/10-09:04 16390) Receiving uunet/D./D.uunetSwJ72
and each line in the statistics file will look something like this:
uucp uunet (12/10-09:04 16390) (692373862) received data 2371 bytes 5 seconds
If you define HAVE_HDB_LOGGING, each program will by default use a
separate log file. For uucico talking to uunet, for example, it
will be /usr/spool/uucp/.Log/uucico/uunet. Each line will look
something like this:
uucp uunet (12/10-09:04:22,16390,1) Receiving uunet/D./D.uunetSwJ72
and each line in the statistics file will look something like this:
uunet!uucp M (12/10-09:04:22) (C,16390,1) [ttyXX] <- 2371 / 5.000 secs, 474 bytes/sec
The main reason to prefer one format over another is that you may
have shell scripts which expect the files to have a particular
format. If you have none, choose whichever format you find more
appealing. */
#define HAVE_TAYLOR_LOGGING 1
#define HAVE_V2_LOGGING 0
#define HAVE_HDB_LOGGING 0
/* If you would like the log, debugging and statistics files to be
closed after each message, set CLOSE_LOGFILES to 1. This will
permit the log files to be easily moved. If a log file does not
exist when a new message is written out, it will be created.
Setting CLOSE_LOGFILES to 1 will obviously require slightly more
processing time. */
#define CLOSE_LOGFILES 0
/* The name of the default spool directory. If HAVE_TAYLOR_CONFIG is
set to 1, this may be overridden by the ``spool'' command in the
configuration file. */
#define SPOOLDIR "/var/spool/uucp"
/* The name of the default public directory. If HAVE_TAYLOR_CONFIG is
set to 1, this may be overridden by the ``pubdir'' command in the
configuration file. Also, a particular system may be given a
specific public directory by using the ``pubdir'' command in the
system file. */
#define PUBDIR "/var/spool/uucppublic"
/* The default command path. This is a space separated list of
directories. Remote command executions requested by uux are looked
up using this path. If you are using HAVE_TAYLOR_CONFIG, the
command path may be overridden for a particular system. For most
systems, you should just make sure that the programs rmail and
rnews can be found using this path. */
#define CMDPATH "/bin /usr/bin /usr/local/bin"
/* The default amount of free space to require for systems that do not
specify an amount with the ``free-space'' command. This is only
used when talking to another instance of Taylor UUCP; if accepting
a file would not leave at least this many bytes free on the disk,
it will be refused. */
#define DEFAULT_FREE_SPACE (50000)
/* While a file is being received, Taylor UUCP will periodically check
to see if there is enough free space remaining on the disk. If
there is not enough space available on the disk (as determined by
DEFAULT_FREE_SPACE, above, or the ``free-space'' command for the
system) the communication will be aborted. The disk will be
checked each time FREE_SPACE_DELTA bytes are received. Lower
values of FREE_SPACE_DELTA are less likely to fill up the disk, but
will also waste more time checking the amount of free space. To
avoid checking the disk while the file is being received, set
FREE_SPACE_DELTA to 0. */
#define FREE_SPACE_DELTA (10240)
/* It is possible for an execute job to request to be executed using
sh(1), rather than execve(2). This is such a security risk, it is
being disabled by default; to allow such jobs, set the following
macro to 1. */
#define ALLOW_SH_EXECUTION 0
/* If a command executed on behalf of a remote system takes a filename
as an argument, a security breach may be possible (note that on my
system neither of the default commands, rmail and rnews, take
filename arguments). If you set ALLOW_FILENAME_ARGUMENTS to 0, all
arguments to a command will be checked; if any argument
1) starts with ../
2) contains the string /../
3) begins with a / but does not name a file that may be sent or
received (according to the specified ``remote-send'' and
``remote-receive'')
the command will be rejected. By default, any argument is
permitted. */
#define ALLOW_FILENAME_ARGUMENTS 1
#if HAVE_TAYLOR_LOGGING
/* The default log file when using HAVE_TAYLOR_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``logfile''
command in the configuration file. */
#define LOGFILE "/var/spool/uucp/Log"
/* The default statistics file when using HAVE_TAYLOR_LOGGING. When
using HAVE_TAYLOR_CONFIG, this may be overridden by the
``statfile'' command in the configuration file. */
#define STATFILE "/var/spool/uucp/Stats"
/* The default debugging file when using HAVE_TAYLOR_LOGGING. When
using HAVE_TAYLOR_CONFIG, this may be overridden by the
``debugfile'' command in the configuration file. */
#define DEBUGFILE "/var/spool/uucp/Debug"
#endif /* HAVE_TAYLOR_LOGGING */
#if HAVE_V2_LOGGING
/* The default log file when using HAVE_V2_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``logfile''
command in the configuration file. */
#define LOGFILE "/var/spool/uucp/LOGFILE"
/* The default statistics file when using HAVE_V2_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``statfile''
command in the configuration file. */
#define STATFILE "/var/spool/uucp/SYSLOG"
/* The default debugging file when using HAVE_V2_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``debugfile''
command in the configuration file. */
#define DEBUGFILE "/var/spool/uucp/DEBUG"
#endif /* HAVE_V2_LOGGING */
#if HAVE_HDB_LOGGING
/* The default log file when using HAVE_HDB_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``logfile''
command in the configuration file. The first %s in the string will
be replaced by the program name (e.g. uucico); the second %s will
be replaced by the system name (if there is no appropriate system,
"ANY" will be used). No other '%' character may appear in the
string. */
#define LOGFILE "/var/spool/uucp/.Log/%s/%s"
/* The default statistics file when using HAVE_HDB_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``statfile''
command in the configuration file. */
#define STATFILE "/var/spool/uucp/.Admin/xferstats"
/* The default debugging file when using HAVE_HDB_LOGGING. When using
HAVE_TAYLOR_CONFIG, this may be overridden by the ``debugfile''
command in the configuration file. */
#define DEBUGFILE "/var/spool/uucp/.Admin/audit.local"
#endif /* HAVE_HDB_LOGGING */

View File

@ -0,0 +1,237 @@
/* prot.c
Protocol support routines to move commands and data around.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char prot_rcsid[] = "$Id: prot.c,v 1.1 1993/08/04 19:30:55 jtc Exp $";
#endif
#include <errno.h>
#include "uudefs.h"
#include "system.h"
#include "conn.h"
#include "prot.h"
/* Variables visible to the protocol-specific routines. */
/* Buffer to hold received data. */
char abPrecbuf[CRECBUFLEN];
/* Index of start of data in abPrecbuf. */
int iPrecstart;
/* Index of end of data (first byte not included in data) in abPrecbuf. */
int iPrecend;
/* We want to output and input at the same time, if supported on this
machine. If we have something to send, we send it all while
accepting a large amount of data. Once we have sent everything we
look at whatever we have received. If data comes in faster than we
can send it, we may run out of buffer space. */
boolean
fsend_data (qconn, zsend, csend, fdoread)
struct sconnection *qconn;
const char *zsend;
size_t csend;
boolean fdoread;
{
if (! fdoread)
return fconn_write (qconn, zsend, csend);
while (csend > 0)
{
size_t crec, csent;
if (iPrecend < iPrecstart)
crec = iPrecstart - iPrecend - 1;
else
{
crec = CRECBUFLEN - iPrecend;
if (iPrecstart == 0)
--crec;
}
csent = csend;
if (! fconn_io (qconn, zsend, &csent, abPrecbuf + iPrecend, &crec))
return FALSE;
csend -= csent;
zsend += csent;
iPrecend = (iPrecend + crec) % CRECBUFLEN;
}
return TRUE;
}
/* Read data from the other system when we have nothing to send. The
argument cneed is the amount of data the caller wants, and ctimeout
is the timeout in seconds. The function sets *pcrec to the amount
of data which was actually received, which may be less than cneed
if there isn't enough room in the receive buffer. If no data is
received before the timeout expires, *pcrec will be returned as 0.
If an error occurs, the function returns FALSE. If the freport
argument is FALSE, no error should be reported. */
boolean
freceive_data (qconn, cneed, pcrec, ctimeout, freport)
struct sconnection *qconn;
size_t cneed;
size_t *pcrec;
int ctimeout;
boolean freport;
{
/* Set *pcrec to the maximum amount of data we can read. fconn_read
expects *pcrec to be the buffer size, and sets it to the amount
actually received. */
if (iPrecend < iPrecstart)
*pcrec = iPrecstart - iPrecend - 1;
else
{
*pcrec = CRECBUFLEN - iPrecend;
if (iPrecstart == 0)
--(*pcrec);
}
#if DEBUG > 0
/* If we have no room in the buffer, we're in trouble. The
protocols must be written to ensure that this can't happen. */
if (*pcrec == 0)
ulog (LOG_FATAL, "freceive_data: No room in buffer");
#endif
/* If we don't have room for all the data the caller wants, we
simply have to expect less. We'll get the rest later. */
if (*pcrec < cneed)
cneed = *pcrec;
if (! fconn_read (qconn, abPrecbuf + iPrecend, pcrec, cneed, ctimeout,
freport))
return FALSE;
iPrecend = (iPrecend + *pcrec) % CRECBUFLEN;
return TRUE;
}
/* Read a single character. Get it out of the receive buffer if it's
there, otherwise ask freceive_data for at least one character.
This is used because as a protocol is shutting down freceive_data
may read ahead and eat characters that should be read outside the
protocol routines. We call freceive_data rather than fconn_read
with an argument of 1 so that we can get all the available data in
a single system call. The ctimeout argument is the timeout in
seconds; the freport argument is FALSE if no error should be
reported. This returns a character, or -1 on timeout or -2 on
error. */
int
breceive_char (qconn, ctimeout, freport)
struct sconnection *qconn;
int ctimeout;
boolean freport;
{
char b;
if (iPrecstart == iPrecend)
{
size_t crec;
if (! freceive_data (qconn, sizeof (char), &crec, ctimeout, freport))
return -2;
if (crec == 0)
return -1;
}
b = abPrecbuf[iPrecstart];
iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
return BUCHAR (b);
}
/* Send mail about a file transfer. We send to the given mailing
address if there is one, otherwise to the user. */
boolean
fmail_transfer (fsuccess, zuser, zmail, zwhy, zfromfile, zfromsys,
ztofile, ztosys, zsaved)
boolean fsuccess;
const char *zuser;
const char *zmail;
const char *zwhy;
const char *zfromfile;
const char *zfromsys;
const char *ztofile;
const char *ztosys;
const char *zsaved;
{
const char *zsendto;
const char *az[20];
int i;
if (zmail != NULL && *zmail != '\0')
zsendto = zmail;
else
zsendto = zuser;
i = 0;
az[i++] = "The file\n\t";
if (zfromsys != NULL)
{
az[i++] = zfromsys;
az[i++] = "!";
}
az[i++] = zfromfile;
if (fsuccess)
az[i++] = "\nwas successfully transferred to\n\t";
else
az[i++] = "\ncould not be transferred to\n\t";
if (ztosys != NULL)
{
az[i++] = ztosys;
az[i++] = "!";
}
az[i++] = ztofile;
az[i++] = "\nas requested by\n\t";
az[i++] = zuser;
if (! fsuccess)
{
az[i++] = "\nfor the following reason:\n\t";
az[i++] = zwhy;
az[i++] = "\n";
}
if (zsaved != NULL)
{
az[i++] = zsaved;
az[i++] = "\n";
}
return fsysdep_mail (zsendto,
fsuccess ? "UUCP succeeded" : "UUCP failed",
i, az);
}

View File

@ -0,0 +1,250 @@
/* prot.h
Protocol header file.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
/* We need the definition of uuconf_cmdtab to declare the protocol
parameter arrays. */
#ifndef UUCONF_H
#include "uuconf.h"
#endif
#if ANSI_C
/* These structures are used in prototypes but are not defined in this
header file. */
struct sdaemon;
struct sconnection;
struct stransfer;
#endif
/* The sprotocol structure holds information and functions for a specific
protocol (e.g. the 'g' protocol). */
struct sprotocol
{
/* The name of the protocol (e.g. 'g'). */
char bname;
/* Reliability requirements, an or of UUCONF_RELIABLE_xxx defines
from uuconf.h. */
int ireliable;
/* The maximum number of channels this protocol can support. */
int cchans;
/* Protocol parameter commands. */
struct uuconf_cmdtab *qcmds;
/* A routine to start the protocol. If *pzlog is set to be
non-NULL, it is an informative message to be logged; it should
then be passed to ubuffree. */
boolean (*pfstart) P((struct sdaemon *qdaemon, char **pzlog));
/* Shutdown the protocol. */
boolean (*pfshutdown) P((struct sdaemon *qdaemon));
/* Send a command to the other side. */
boolean (*pfsendcmd) P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
/* Get buffer to space to fill with data. This should set *pcdata
to the amount of data desired. */
char *(*pzgetspace) P((struct sdaemon *qdaemon, size_t *pcdata));
/* Send data to the other side. The argument z must be a return
value of pzgetspace. The ipos argument is the file position, and
is ignored by most protocols. */
boolean (*pfsenddata) P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
/* Wait for data to come in and call fgot_data with it until
fgot_data sets *pfexit. */
boolean (*pfwait) P((struct sdaemon *qdaemon));
/* Handle any file level actions that need to be taken. If a file
transfer is starting rather than ending, fstart is TRUE. If the
file is being sent rather than received, fsend is TRUE. If
fstart and fsend are both TRUE, cbytes holds the size of the
file. If *pfhandled is set to TRUE, then the protocol routine
has taken care of queueing up qtrans for the next action. */
boolean (*pffile) P((struct sdaemon *qdaemon, struct stransfer *qtrans,
boolean fstart, boolean fsend, long cbytes,
boolean *pfhandled));
};
/* Send data to the other system. If the fread argument is TRUE, this
will also receive data into the receive buffer abPrecbuf; fread is
passed as TRUE if the protocol expects data to be coming back, to
make sure the input buffer does not fill up. Returns FALSE on
error. */
extern boolean fsend_data P((struct sconnection *qconn,
const char *zsend, size_t csend,
boolean fdoread));
/* Receive data from the other system when there is no data to send.
The cneed argument is the amount of data desired and the ctimeout
argument is the timeout in seconds. This will set *pcrec to the
amount of data received. It will return FALSE on error. If a
timeout occurs, it will return TRUE with *pcrec set to zero. */
extern boolean freceive_data P((struct sconnection *qconn, size_t cneed,
size_t *pcrec, int ctimeout,
boolean freport));
/* Get one character from the remote system, going through the
procotol buffering. The ctimeout argument is the timeout in
seconds, and the freport argument is TRUE if errors should be
reported (when closing a connection it is pointless to report
errors). This returns a character or -1 on a timeout or -2 on an
error. */
extern int breceive_char P((struct sconnection *qconn,
int ctimeout, boolean freport));
/* Compute a 32 bit CRC of a data buffer, given an initial CRC. */
extern unsigned long icrc P((const char *z, size_t c, unsigned long ick));
/* The initial CRC value to use for a new buffer. */
#if ANSI_C
#define ICRCINIT (0xffffffffUL)
#else
#define ICRCINIT ((unsigned long) 0xffffffffL)
#endif
/* The size of the receive buffer. */
#define CRECBUFLEN (16384)
/* Buffer to hold received data. */
extern char abPrecbuf[CRECBUFLEN];
/* Index of start of data in abPrecbuf. */
extern int iPrecstart;
/* Index of end of data (first byte not included in data) in abPrecbuf. */
extern int iPrecend;
/* There are a couple of variables and functions that are shared by
the 'i' and 'j' protocols (the 'j' protocol is just a wrapper
around the 'i' protocol). These belong in a separate header file,
protij.h, but I don't want to create one for just a couple of
things. */
/* An escape sequence of characters for the 'j' protocol to avoid
(protocol parameter ``avoid''). */
extern const char *zJavoid_parameter;
/* Timeout to use when sending the 'i' protocol SYNC packet (protocol
parameter ``sync-timeout''). */
extern int cIsync_timeout;
/* Shared startup routine for the 'i' and 'j' protocols. */
extern boolean fijstart P((struct sdaemon *qdaemon, char **pzlog,
int imaxpacksize,
boolean (*pfsend) P((struct sconnection *qconn,
const char *zsend,
size_t csend,
boolean fdoread)),
boolean (*pfreceive) P((struct sconnection *qconn,
size_t cneed,
size_t *pcrec,
int ctimeout,
boolean freport))));
/* Prototypes for 'g' protocol functions. */
extern struct uuconf_cmdtab asGproto_params[];
extern boolean fgstart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean fbiggstart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean fgshutdown P((struct sdaemon *qdaemon));
extern boolean fgsendcmd P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
extern char *zggetspace P((struct sdaemon *qdaemon, size_t *pcdata));
extern boolean fgsenddata P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
extern boolean fgwait P((struct sdaemon *qdaemon));
/* Prototypes for 'f' protocol functions. */
extern struct uuconf_cmdtab asFproto_params[];
extern boolean ffstart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean ffshutdown P((struct sdaemon *qdaemon));
extern boolean ffsendcmd P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
extern char *zfgetspace P((struct sdaemon *qdaemon, size_t *pcdata));
extern boolean ffsenddata P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
extern boolean ffwait P((struct sdaemon *qdaemon));
extern boolean fffile P((struct sdaemon *qdaemon, struct stransfer *qtrans,
boolean fstart, boolean fsend, long cbytes,
boolean *pfhandled));
/* Prototypes for 't' protocol functions. */
extern struct uuconf_cmdtab asTproto_params[];
extern boolean ftstart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean ftshutdown P((struct sdaemon *qdaemon));
extern boolean ftsendcmd P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
extern char *ztgetspace P((struct sdaemon *qdaemon, size_t *pcdata));
extern boolean ftsenddata P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
extern boolean ftwait P((struct sdaemon *qdaemon));
extern boolean ftfile P((struct sdaemon *qdaemon, struct stransfer *qtrans,
boolean fstart, boolean fsend, long cbytes,
boolean *pfhandled));
/* Prototypes for 'e' protocol functions. */
extern struct uuconf_cmdtab asEproto_params[];
extern boolean festart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean feshutdown P((struct sdaemon *qdaemon));
extern boolean fesendcmd P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
extern char *zegetspace P((struct sdaemon *qdaemon, size_t *pcdata));
extern boolean fesenddata P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
extern boolean fewait P((struct sdaemon *qdaemon));
extern boolean fefile P((struct sdaemon *qdaemon, struct stransfer *qtrans,
boolean fstart, boolean fsend, long cbytes,
boolean *pfhandled));
/* Prototypes for 'i' protocol functions. */
extern struct uuconf_cmdtab asIproto_params[];
extern boolean fistart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean fishutdown P((struct sdaemon *qdaemon));
extern boolean fisendcmd P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
extern char *zigetspace P((struct sdaemon *qdaemon, size_t *pcdata));
extern boolean fisenddata P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
extern boolean fiwait P((struct sdaemon *qdaemon));
/* Prototypes for 'j' protocol functions. The 'j' protocol mostly
uses the 'i' protocol functions, but it has a couple of functions
of its own. */
extern boolean fjstart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean fjshutdown P((struct sdaemon *qdaemon));
/* Prototypes for 'a' protocol functions (these use 'z' as the second
character because 'a' is a modified Zmodem protocol). */
extern struct uuconf_cmdtab asZproto_params[];
extern boolean fzstart P((struct sdaemon *qdaemon, char **pzlog));
extern boolean fzshutdown P((struct sdaemon *qdaemon));
extern boolean fzsendcmd P((struct sdaemon *qdaemon, const char *z,
int ilocal, int iremote));
extern char *zzgetspace P((struct sdaemon *qdaemon, size_t *pcdata));
extern boolean fzsenddata P((struct sdaemon *qdaemon, char *z, size_t c,
int ilocal, int iremote, long ipos));
extern boolean fzwait P((struct sdaemon *qdaemon));
extern boolean fzfile P((struct sdaemon *qdaemon, struct stransfer *qtrans,
boolean fstart, boolean fsend, long cbytes,
boolean *pfhandled));

View File

@ -0,0 +1,530 @@
/* sysh.unx -*- C -*-
The header file for the UNIX system dependent routines.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#ifndef SYSH_UNX_H
#define SYSH_UNX_H
#if ANSI_C
/* These structures are used in prototypes but are not defined in this
header file. */
struct uuconf_system;
struct sconnection;
#endif
/* Make sure the defines do not conflict. These are in this file
because they are Unix dependent. */
#if HAVE_V2_LOCKFILES + HAVE_HDB_LOCKFILES + HAVE_SCO_LOCKFILES + HAVE_SVR4_LOCKFILES + HAVE_COHERENT_LOCKFILES != 1
#error LOCKFILES define not set or duplicated
#endif
/* SCO and SVR4 lockfiles are basically just like HDB lockfiles. */
#if HAVE_SCO_LOCKFILES || HAVE_SVR4_LOCKFILES
#undef HAVE_HDB_LOCKFILES
#define HAVE_HDB_LOCKFILES 1
#endif
#if HAVE_BSD_TTY + HAVE_SYSV_TERMIO + HAVE_POSIX_TERMIOS != 1
#error Terminal driver define not set or duplicated
#endif
#if SPOOLDIR_V2 + SPOOLDIR_BSD42 + SPOOLDIR_BSD43 + SPOOLDIR_HDB + SPOOLDIR_ULTRIX + SPOOLDIR_SVR4 + SPOOLDIR_TAYLOR != 1
#error Spool directory define not set or duplicated
#endif
/* If setreuid is broken, don't use it. */
#if HAVE_BROKEN_SETREUID
#undef HAVE_SETREUID
#define HAVE_SETREUID 0
#endif
/* Get some standard types from the configuration header file. */
#ifdef PID_T
typedef PID_T pid_t;
#endif
#ifdef UID_T
typedef UID_T uid_t;
#endif
#ifdef GID_T
typedef GID_T gid_t;
#endif
#ifdef OFF_T
typedef OFF_T off_t;
#endif
/* On Unix, binary files are the same as text files. */
#define BINREAD "r"
#define BINWRITE "w"
/* If we have sigaction, we can force system calls to not be
restarted. */
#if HAVE_SIGACTION
#undef HAVE_RESTARTABLE_SYSCALLS
#define HAVE_RESTARTABLE_SYSCALLS 0
#endif
/* If we have sigvec, and we have HAVE_SIGVEC_SV_FLAGS, and
SV_INTERRUPT is defined, we can force system calls to not be
restarted (signal.h is included by uucp.h before this point, so
SV_INTERRUPT will be defined by now if it it ever is). */
#if HAVE_SIGVEC && HAVE_SIGVEC_SV_FLAGS
#ifdef SV_INTERRUPT
#undef HAVE_RESTARTABLE_SYSCALLS
#define HAVE_RESTARTABLE_SYSCALLS 0
#endif
#endif
/* If we were cross-configured, we will have a value of -1 for
HAVE_RESTARTABLE_SYSCALLS. In this case, we try to guess what the
correct value should be. Yuck. If we have sigvec, but neither of
the above cases applied (which we know because they would have
changed HAVE_RESTARTABLE_SYSCALLS) then we are probably on 4.2BSD
and system calls are automatically restarted. Otherwise, assume
that they are not. */
#if HAVE_RESTARTABLE_SYSCALLS == -1
#undef HAVE_RESTARTABLE_SYSCALLS
#if HAVE_SIGVEC
#define HAVE_RESTARTABLE_SYSCALLS 1
#else
#define HAVE_RESTARTABLE_SYSCALLS 0
#endif
#endif /* HAVE_RESTARTABLE_SYSCALLS == -1 */
/* We don't handle sigset in combination with restartable system
calls, so we check for it although this combination will never
happen. */
#if ! HAVE_SIGACTION && ! HAVE_SIGVEC && HAVE_SIGSET
#if HAVE_RESTARTABLE_SYSCALLS
#undef HAVE_SIGSET
#define HAVE_SIGSET 0
#endif
#endif
/* If we don't have restartable system calls, we can ignore
fsysdep_catch, usysdep_start_catch and usysdep_end_catch.
Otherwise fsysdep_catch has to do a setjmp. */
#if ! HAVE_RESTARTABLE_SYSCALLS
#define fsysdep_catch() (TRUE)
#define usysdep_start_catch()
#define usysdep_end_catch()
#define CATCH_PROTECT
#else /* HAVE_RESTARTABLE_SYSCALLS */
#if HAVE_SETRET && ! HAVE_SIGSETJMP
#include <setret.h>
#define setjmp setret
#define longjmp longret
#define jmp_buf ret_buf
#else /* ! HAVE_SETRET || HAVE_SIGSETJMP */
#include <setjmp.h>
#if HAVE_SIGSETJMP
#undef setjmp
#undef longjmp
#undef jmp_buf
#define setjmp(s) sigsetjmp ((s), TRUE)
#define longjmp siglongjmp
#define jmp_buf sigjmp_buf
#endif /* HAVE_SIGSETJMP */
#endif /* ! HAVE_SETRET || HAVE_SIGSETJMP */
extern volatile sig_atomic_t fSjmp;
extern volatile jmp_buf sSjmp_buf;
#define fsysdep_catch() (setjmp (sSjmp_buf) == 0)
#define usysdep_start_catch() (fSjmp = TRUE)
#define usysdep_end_catch() (fSjmp = FALSE)
#define CATCH_PROTECT volatile
#endif /* HAVE_RESTARTABLE_SYSCALLS */
/* Get definitions for the terminal driver. */
#if HAVE_BSD_TTY
#include <sgtty.h>
struct sbsd_terminal
{
struct sgttyb stty;
struct tchars stchars;
struct ltchars sltchars;
};
typedef struct sbsd_terminal sterminal;
#define fgetterminfo(o, q) \
(ioctl ((o), TIOCGETP, &(q)->stty) == 0 \
&& ioctl ((o), TIOCGETC, &(q)->stchars) == 0 \
&& ioctl ((o), TIOCGLTC, &(q)->sltchars) == 0)
#define fsetterminfo(o, q) \
(ioctl ((o), TIOCSETN, &(q)->stty) == 0 \
&& ioctl ((o), TIOCSETC, &(q)->stchars) == 0 \
&& ioctl ((o), TIOCSLTC, &(q)->sltchars) == 0)
#define fsetterminfodrain(o, q) \
(ioctl ((o), TIOCSETP, &(q)->stty) == 0 \
&& ioctl ((o), TIOCSETC, &(q)->stchars) == 0 \
&& ioctl ((o), TIOCSLTC, &(q)->sltchars) == 0)
#endif /* HAVE_BSD_TTY */
#if HAVE_SYSV_TERMIO
#include <termio.h>
typedef struct termio sterminal;
#define fgetterminfo(o, q) (ioctl ((o), TCGETA, (q)) == 0)
#define fsetterminfo(o, q) (ioctl ((o), TCSETA, (q)) == 0)
#define fsetterminfodrain(o, q) (ioctl ((o), TCSETAW, (q)) == 0)
#endif /* HAVE_SYSV_TERMIO */
#if HAVE_POSIX_TERMIOS
#include <termios.h>
typedef struct termios sterminal;
#define fgetterminfo(o, q) (tcgetattr ((o), (q)) == 0)
#define fsetterminfo(o, q) (tcsetattr ((o), TCSANOW, (q)) == 0)
#define fsetterminfodrain(o, q) (tcsetattr ((o), TCSADRAIN, (q)) == 0)
/* On some systems it is not possible to include both <sys/ioctl.h>
and <termios.h> in the same source files; I don't really know why.
On such systems, we pretend that we don't have <sys/ioctl.h>. */
#if ! HAVE_TERMIOS_AND_SYS_IOCTL_H
#undef HAVE_SYS_IOCTL_H
#define HAVE_SYS_IOCTL_H 0
#endif
#endif /* HAVE_POSIX_TERMIOS */
/* The root directory (this is needed by the system independent stuff
as the default for local-send). */
#define ZROOTDIR "/"
/* The name of the execution directory within the spool directory
(this is need by the system independent uuxqt.c). */
#define XQTDIR ".Xqtdir"
/* The name of the directory in which we preserve file transfers that
failed. */
#define PRESERVEDIR ".Preserve"
/* The length of the sequence number used in a file name. */
#define CSEQLEN (4)
/* Get some standard definitions. Avoid including the files more than
once--some might have been included by uucp.h. */
#if USE_STDIO && HAVE_UNISTD_H
#include <unistd.h>
#endif
#if ! USE_TYPES_H
#include <sys/types.h>
#endif
#include <sys/stat.h>
/* Get definitions for the file permission bits. */
#ifndef S_IRWXU
#define S_IRWXU 0700
#endif
#ifndef S_IRUSR
#define S_IRUSR 0400
#endif
#ifndef S_IWUSR
#define S_IWUSR 0200
#endif
#ifndef S_IXUSR
#define S_IXUSR 0100
#endif
#ifndef S_IRWXG
#define S_IRWXG 0070
#endif
#ifndef S_IRGRP
#define S_IRGRP 0040
#endif
#ifndef S_IWGRP
#define S_IWGRP 0020
#endif
#ifndef S_IXGRP
#define S_IXGRP 0010
#endif
#ifndef S_IRWXO
#define S_IRWXO 0007
#endif
#ifndef S_IROTH
#define S_IROTH 0004
#endif
#ifndef S_IWOTH
#define S_IWOTH 0002
#endif
#ifndef S_IXOTH
#define S_IXOTH 0001
#endif
#ifndef S_ISDIR
#ifdef S_IFDIR
#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR)
#else /* ! defined (S_IFDIR) */
#define S_ISDIR(i) (((i) & 0170000) == 040000)
#endif /* ! defined (S_IFDIR) */
#endif /* ! defined (S_ISDIR) */
/* We need the access macros. */
#ifndef R_OK
#define R_OK 4
#define W_OK 2
#define X_OK 1
#define F_OK 0
#endif /* ! defined (R_OK) */
/* We create files with these modes (should this be configurable?). */
#define IPRIVATE_FILE_MODE (S_IRUSR | S_IWUSR)
#define IPUBLIC_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/* We create directories with this mode (should this be configurable?). */
#define IDIRECTORY_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
#define IPUBLIC_DIRECTORY_MODE (S_IRWXU | S_IRWXG | S_IRWXO)
#if ! HAVE_OPENDIR
/* Define some structures to use if we don't have opendir, etc. These
will only work if we have the old Unix filesystem, with a 2 byte
inode and a 14 byte filename. */
#include <sys/dir.h>
struct dirent
{
char d_name[DIRSIZ + 1];
};
typedef struct
{
int o;
struct dirent s;
} DIR;
extern DIR *opendir P((const char *zdir));
extern struct dirent *readdir P((DIR *));
extern int closedir P((DIR *));
#endif /* ! HAVE_OPENDIR */
#if ! HAVE_FTW_H
/* If there is no <ftw.h>, define the ftw constants. */
#define FTW_F (0)
#define FTW_D (1)
#define FTW_DNR (2)
#define FTW_NS (3)
#endif /* ! HAVE_FTW_H */
/* This structure holds the system dependent information we keep for a
connection. This is used by the TCP and TLI code. */
struct ssysdep_conn
{
/* File descriptor. */
int o;
/* Device name. */
char *zdevice;
/* File status flags. */
int iflags;
/* File status flags for descriptor 1 (-1 if not standard input). */
int istdout_flags;
/* Hold the real descriptor when using a dialer device. */
int ohold;
/* TRUE if this is a terminal and the remaining fields are valid. */
boolean fterminal;
/* TRUE if this is a TLI descriptor. */
boolean ftli;
/* Baud rate. */
long ibaud;
/* Original terminal settings. */
sterminal sorig;
/* Current terminal settings. */
sterminal snew;
#if HAVE_COHERENT_LOCKFILES
/* On Coherent we need to hold on to the real port name which will
be used to enable the port. Ick. */
char *zenable;
#endif
};
/* These functions do I/O and chat scripts to a port. They are called
by the TCP and TLI routines. */
extern boolean fsysdep_conn_read P((struct sconnection *qconn,
char *zbuf, size_t *pclen,
size_t cmin, int ctimeout,
boolean freport));
extern boolean fsysdep_conn_write P((struct sconnection *qconn,
const char *zbuf, size_t clen));
extern boolean fsysdep_conn_io P((struct sconnection *qconn,
const char *zwrite, size_t *pcwrite,
char *zread, size_t *pcread));
extern boolean fsysdep_conn_chat P((struct sconnection *qconn,
char **pzprog));
/* Set a signal handler. */
extern void usset_signal P((int isig, RETSIGTYPE (*pfn) P((int)),
boolean fforce, boolean *pfignored));
/* Default signal handler. This sets the appropriate element of the
afSignal array. If system calls are automatically restarted, it
may do a longjmp to an fsysdep_catch. */
extern RETSIGTYPE ussignal P((int isig));
/* Try to fork, repeating several times. */
extern pid_t ixsfork P((void));
/* Spawn a job. Returns the process ID of the spawned job or -1 on
error. The following macros may be passed in aidescs. */
/* Set descriptor to /dev/null. */
#define SPAWN_NULL (-1)
/* Set element of aidescs to a pipe for caller to read from. */
#define SPAWN_READ_PIPE (-2)
/* Set element of aidescs to a pipe for caller to write to. */
#define SPAWN_WRITE_PIPE (-3)
extern pid_t ixsspawn P((const char **pazargs, int *aidescs,
boolean fkeepuid, boolean fkeepenv,
const char *zchdir, boolean fnosigs,
boolean fshell, const char *zpath,
const char *zuu_machine,
const char *zuu_user));
/* Do a form of popen using ixsspawn. */
extern FILE *espopen P((const char **pazargs, boolean frd,
pid_t *pipid));
/* Wait for a particular process to finish, returning the exit status.
The process ID should be pid_t, but we can't put that in a
prototype. */
extern int ixswait P((unsigned long ipid, const char *zreport));
/* Find a spool file in the spool directory. For a local file, the
bgrade argument is the grade of the file. This is needed for
SPOOLDIR_SVR4. */
extern char *zsfind_file P((const char *zsimple, const char *zsystem,
int bgrade));
/* Return the grade given a sequence number. */
extern char bsgrade P((pointer pseq));
/* Lock a string. */
extern boolean fsdo_lock P((const char *, boolean fspooldir,
boolean *pferr));
/* Unlock a string. */
extern boolean fsdo_unlock P((const char *, boolean fspooldir));
/* Check access for a particular user name, or NULL to check access
for any user. */
extern boolean fsuser_access P((const struct stat *, int imode,
const char *zuser));
/* Stick two directories and a file name together. */
extern char *zsappend3 P((const char *zdir1, const char *zdir2,
const char *zfile));
/* Stick three directories and a file name together. */
extern char *zsappend4 P((const char *zdir1, const char *zdir2,
const char *zdir3, const char *zfile));
/* Get a temporary file name. */
extern char *zstemp_file P((const struct uuconf_system *qsys));
/* Get a command file name. */
extern char *zscmd_file P((const struct uuconf_system *qsys, int bgrade));
/* Get a jobid from a system, a file name, and a grade. */
extern char *zsfile_to_jobid P((const struct uuconf_system *qsys,
const char *zfile,
int bgrade));
/* Get a file name from a jobid. This also returns the associated system
in *pzsystem and the grade in *pbgrade. */
extern char *zsjobid_to_file P((const char *zid, char **pzsystem,
char *pbgrade));
/* See whether there is a spool directory for a system when using
SPOOLDIR_ULTRIX. */
extern boolean fsultrix_has_spool P((const char *zsystem));
#if HAVE_COHERENT_LOCKFILES
/* Lock a coherent tty. */
extern boolean lockttyexist P((const char *z));
extern boolean fscoherent_disable_tty P((const char *zdevice,
char **pzenable));
#endif
/* Some replacements for standard Unix functions. */
#if ! HAVE_DUP2
extern int dup2 P((int oold, int onew));
#endif
#if ! HAVE_FTW
extern int ftw P((const char *zdir,
int (*pfn) P((const char *zfile,
const struct stat *qstat,
int iflag)),
int cdescriptors));
#endif
#if ! HAVE_GETCWD && ! HAVE_GETWD
extern char *getcwd P((char *zbuf, size_t cbuf));
#endif
#if ! HAVE_MKDIR
extern int mkdir P((const char *zdir, int imode));
#endif
#if ! HAVE_RENAME
extern int rename P((const char *zold, const char *znew));
#endif
#if ! HAVE_RMDIR
extern int rmdir P((const char *zdir));
#endif
/* The working directory from which the program was run (this is set
by usysdep_initialize if called with INIT_GETCWD). */
extern char *zScwd;
/* The spool directory name. */
extern const char *zSspooldir;
/* The lock directory name. */
extern const char *zSlockdir;
/* The local UUCP name (needed for some spool directory stuff). */
extern const char *zSlocalname;
#endif /* ! defined (SYSH_UNX_H) */

View File

@ -0,0 +1,950 @@
/* system.h
Header file for system dependent stuff in the Taylor UUCP package.
This file is not itself system dependent.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#ifndef SYSTEM_H
#define SYSTEM_H
#if ANSI_C
/* These structures are used in prototypes but are not defined in this
header file. */
struct tm;
struct uuconf_system;
struct uuconf_port;
struct sconnection;
struct sstatus;
struct scmd;
#endif
/* Any function which returns an error should also report an error
message, unless otherwise indicated.
Any function that returns a char *, rather than a const char *, is
returning a pointer to a buffer allocated by zbufalc which must be
freed using ubuffree, unless otherwise indicated. */
/* The maximum length of a remote system name. */
extern size_t cSysdep_max_name_len;
/* Initialize. If something goes wrong, this routine should just
exit. The flag argument is 0, or a combination of any of the
following flags. */
/* This program needs to know the current working directory. This is
used because on Unix it can be expensive to determine the current
working directory (some versions of getcwd fork a process), but in
most cases we don't need to know it. However, we are going to
chdir to the spool directory (unless INIT_CHDIR is set), so we have
to get the cwd now if we are ever going to get it. Both uucp and
uux use the function fsysdep_needs_cwd to determine whether they
will need the current working directory, and pass the argument to
usysdep_initialize appropriately. There's probably a cleaner way
to handle this, but this will suffice for now. */
#define INIT_GETCWD (01)
/* This program should not chdir to the spool directory. This may
only make sense on Unix. It is set by cu. */
#define INIT_NOCHDIR (02)
/* This program needs special access to the spool directories. That
means, on Unix, this program is normally installed setuid. */
#define INIT_SUID (04)
extern void usysdep_initialize P((pointer puuconf, int iflags));
/* Exit the program. The fsuccess argument indicates whether to
return an indication of success or failure to the outer
environment. This routine should not return. */
extern void usysdep_exit P((boolean fsuccess));
/* Called when a non-standard configuration file is being used, to
avoid handing out privileged access. If it returns FALSE, default
configuration file will be used. This is called before the
usysdep_initialize function is called. */
extern boolean fsysdep_other_config P((const char *));
/* Detach from the controlling terminal. This probably only makes
sense on Unix. It is called by uucico to try to get the modem port
as a controlling terminal. It is also called by uucico before it
starts up uuxqt, so that uuxqt will be a complete daemon. */
extern void usysdep_detach P((void));
/* Get the local node name if it is not specified in the configuration
files. Returns NULL on error; otherwise the return value should
point to a static buffer. */
extern const char *zsysdep_localname P((void));
/* Get the login name. This is used when uucico is started up with no
arguments in slave mode, which causes it to assume that somebody
has logged in. It also used by uucp and uux for recording the user
name. This may not return NULL. The return value should point to
a static buffer. */
extern const char *zsysdep_login_name P((void));
/* Set a signal handler for a signal. If the signal occurs, the
appropriate element of afSignal should be set to the signal number
(see the declaration of afSignal in uucp.h). This routine might be
able to just use signal, but Unix requires more complex handling.
This is called before usysdep_initialize. */
extern void usysdep_signal P((int isig));
/* Catch a signal. This is actually defined as a macro in the system
dependent header file, and the prototype here just indicates how it
should be called. It is called before a routine which must exit if
a signal occurs, and is expected to set do a setjmp (which is why
it must be a macro). It is actually only called in one place in
the system independent code, before the call to read stdin in uux.
This is needed to handle 4.2 BSD restartable system calls, which
require a longjmp. On systems which don't need to do
setjmp/longjmp around system calls, this can be redefined in
sysdep.h to TRUE. It should return TRUE if the routine should
proceed, or FALSE if a signal occurred. After having this return
TRUE, usysdep_start_catch should be used to start catching the
signal; this basically tells the signal handler that it's OK to do
the longjmp, if fsysdep_catch did not already do so. */
#ifndef fsysdep_catch
extern boolean fsysdep_catch P((void));
#endif
/* Start catching a signal. This is called after fsysdep_catch to
tell the signal handler to go ahead and do the longjmp. This may
be implemented as a macro in sysdep.h. */
#ifndef usysdep_start_catch
extern void usysdep_start_catch P((void));
#endif
/* Stop catching a signal. This is called when it is no longer
necessary for fsysdep_catch to handle signals. This may be
implemented as a macro in sysdep.h. */
#ifndef usysdep_end_catch
extern void usysdep_end_catch P((void));
#endif
/* Link two files. On Unix this should attempt the link. If it
succeeds it should return TRUE with *pfworked set to TRUE. If the
link fails because it must go across a device, it should return
TRUE with *pfworked set to FALSE. If the link fails for some other
reason, it should log an error message and return FALSE. On a
system which does not support links to files, this should just
return TRUE with *pfworked set to FALSE. */
extern boolean fsysdep_link P((const char *zfrom, const char *zto,
boolean *pfworked));
/* Get the port name. This is used when uucico is started up in slave
mode to figure out which port was used to call in so that it can
determine any appropriate protocol parameters. This may return
NULL if the port cannot be determined, which will just mean that no
protocol parameters are applied. The name returned should be the
sort of name that would appear in the port file. This should set
*pftcp_port to TRUE if it can determine that the port is a TCP
connection rather than a normal serial port. The return value (if
not NULL) should point to a static buffer. */
extern const char *zsysdep_port_name P((boolean *pftcp_port));
/* Expand a file name on the local system. On Unix, if the zfile
argument begins with ~user/ it goes in that users home directory,
and if it begins with ~/ it goes in the public directory (the
public directory is passed to this routine, since each system may
have its own public directory). Similar conventions may be
desirable on other systems. This should always return an absolute
path name, probably in the public directory. It should return NULL
on error; otherwise the return value should be allocated using
zbufcpy or zbufalc. */
extern char *zsysdep_local_file P((const char *zname,
const char *zpubdir));
/* Return whether a file name is in a directory, and check for read or
write access. This should check whether zfile is within zdir (or
is zdir itself). If it is not, it should return FALSE. If zfile
is in zdir, then fcheck indicates whether further checking should
be done. If fcheck is FALSE, no further checking is done.
Otherwise, if freadable is TRUE the user zuser should have search
access to all directories from zdir down to zfile and should have
read access on zfile itself (if zfile does not exist, or is not a
regular file, this function may return FALSE but does not have to).
If freadable is FALSE, the user zuser should have search access to
all directories from zdir down to zfile and should have write
access on zfile (which may be a directory, or may not actually
exist, which is acceptable). The zuser argument may be NULL, in
which case the check should be made for any user, not just zuser.
There is no way for this function to return error. */
extern boolean fsysdep_in_directory P((const char *zfile,
const char *zdir,
boolean fcheck,
boolean freadable,
const char *zuser));
/* Return TRUE if a file exists, FALSE otherwise. There is no way to
return error. */
extern boolean fsysdep_file_exists P((const char *zfile));
/* Start up a program. The code expects fsysdep_run to return after
doing a fork, but at least for now everything will work fine if it
does not (on a system which does not support forking). The three
string arguments may be catenated together to form the program to
execute; I did it this way to make it easy to call execl(2), and
because I never needed more than two arguments. The program will
always be "uucico" or "uuxqt". The return value will be passed
directly to usysdep_exit, and should be TRUE on success, FALSE on
error. */
extern boolean fsysdep_run P((const char *zprogram, const char *zarg1,
const char *zarg2));
/* Send a mail message. This function will be passed an array of
strings. All necessary newlines are already included; the strings
should simply be concatenated together to form the mail message.
It should return FALSE on error, although the return value is often
ignored. */
extern boolean fsysdep_mail P((const char *zto, const char *zsubject,
int cstrs, const char **paz));
/* Get the time in seconds since some epoch. The actual epoch is
unimportant, so long as the time values are consistent across
program executions and the value is never negative. If the
pimicros argument is not NULL, it should be set to the number of
microseconds (if this is not available, *pimicros should be set to
zero). */
extern long ixsysdep_time P((long *pimicros));
/* Get the time in seconds and microseconds (millionths of a second)
since some epoch. The actual epoch is not important, and it may
change in between program invocations; this is provided because on
Unix the times function may be used. If microseconds can not be
determined, *pimicros can just be set to zero. */
extern long ixsysdep_process_time P((long *pimicros));
/* Parse the value returned by ixsysdep_time into a struct tm. I
assume that this structure is defined in <time.h>. This is
basically just localtime, except that the ANSI function takes a
time_t which may not be what is returned by ixsysdep_time. */
extern void usysdep_localtime P((long itime, struct tm *q));
/* Sleep for a number of seconds. */
extern void usysdep_sleep P((int cseconds));
/* Pause for half a second, or 1 second if subsecond sleeps are not
possible. */
extern void usysdep_pause P((void));
/* Lock a remote system. This should return FALSE if the system is
already locked (no error should be reported). */
extern boolean fsysdep_lock_system P((const struct uuconf_system *qsys));
/* Unlock a remote system. This should return FALSE on error
(although the return value is generally ignored). */
extern boolean fsysdep_unlock_system P((const struct uuconf_system *qsys));
/* Get the conversation sequence number for a remote system, and
increment it for next time. This should return -1 on error. */
extern long ixsysdep_get_sequence P((const struct uuconf_system *qsys));
/* Get the status of a remote system. This should return FALSE on
error. Otherwise it should set *qret to the status. If no status
information is available, this should set *qret to sensible values
and return TRUE. If pfnone is not NULL, then it should be set to
TRUE if no status information was available or FALSE otherwise. */
extern boolean fsysdep_get_status P((const struct uuconf_system *qsys,
struct sstatus *qret,
boolean *pfnone));
/* Set the status of a remote system. This should return FALSE on
error. The system will be locked before this call is made. */
extern boolean fsysdep_set_status P((const struct uuconf_system *qsys,
const struct sstatus *qset));
/* See whether a remote system is permitted to log in. This is just
to support the remote.unknown shell script for HDB. The zscript
argument is the script name, as return by uuconf_remote_unknown.
The zsystem argument is the name given by the remote system. If
the system is not permitted to log in, this function should log an
error and return FALSE. */
extern boolean fsysdep_unknown_caller P((const char *zscript,
const char *zsystem));
/* Check whether there is work for a remote system. It should return
TRUE if there is work, FALSE otherwise; there is no way to indicate
an error. */
extern boolean fsysdep_has_work P((const struct uuconf_system *qsys));
/* Initialize the work scan. This will be called before
fsysdep_get_work. The bgrade argument is the minimum grade of
execution files that should be considered (e.g. a bgrade of 'd'
will allow all grades from 'A' to 'Z' and 'a' to 'd'). This
function should return FALSE on error. */
extern boolean fsysdep_get_work_init P((const struct uuconf_system *qsys,
int bgrade));
/* Get the next command to be executed for a remote system. The
bgrade argument will be the same as for fsysdep_get_work_init;
probably only one of these functions will use it, namely the
function for which it is more convenient. This should return FALSE
on error. The structure pointed to by qcmd should be filled in.
The strings may point into a static buffer; they will be copied out
if necessary. If there is no more work, this should set qcmd->bcmd
to 'H' and return TRUE. This should set qcmd->pseq to something
which can be passed to fsysdep_did_work to remove the job from the
queue when it has been completed. This may set qcmd->bcmd to 'P'
to represent a poll file; the main code will just pass the pseq
element of such a structure to fsysdep_did_work if the system is
called. */
extern boolean fsysdep_get_work P((const struct uuconf_system *qsys,
int bgrade, struct scmd *qcmd));
/* Remove a job from the work queue. This must also remove the
temporary file used for a send command, if there is one. It should
return FALSE on error. */
extern boolean fsysdep_did_work P((pointer pseq));
/* Save the temporary file for a send command. This function should
return a string that will be put into a mail message. On success
this string should say something like ``The file has been saved as
...''. On failure it could say something like ``The file could not
be saved because ...''. If there is no temporary file, or for some
reason it's not appropriate to include a message, this function
should just return NULL. This function is used when a file send
fails for some reason, to make sure that we don't completely lost
the file. */
extern const char *zsysdep_save_temp_file P((pointer pseq));
/* Cleanup anything left over by fsysdep_get_work_init and
fsysdep_get_work. This may be called even though
fsysdep_get_work_init has not been. */
extern void usysdep_get_work_free P((const struct uuconf_system *qsys));
/* Add a base name to a file if it is a directory. If zfile names a
directory, then return a string naming a file within the directory
with the base file name of zname. This should return NULL on
error. */
extern char *zsysdep_add_base P((const char *zfile,
const char *zname));
/* Get a file name from the spool directory. This should return NULL
on error. The pseq argument is TRUE if the file was found from
searching the work directory; this is, unfortunately, needed to
support SVR4 spool directories. */
extern char *zsysdep_spool_file_name P((const struct uuconf_system *qsys,
const char *zfile,
pointer pseq));
/* Make necessary directories. This should create all non-existent
directories for a file. If the fpublic argument is TRUE, anybody
should be permitted to create and remove files in the directory;
otherwise anybody can list the directory, but only the UUCP system
can create and remove files. It should return FALSE on error. */
extern boolean fsysdep_make_dirs P((const char *zfile, boolean fpublic));
/* Create a stdio file, setting appropriate protection. If the
fpublic argument is TRUE, the file is made publically accessible;
otherwise it is treated as a private data file. If the fappend
argument is TRUE, the file is opened in append mode; otherwise any
previously existing file of the same name is removed. If the
fmkdirs argument is TRUE, then any necessary directories should
also be created. On a system in which file protections are
unimportant and the necessary directories exist, this may be
implemented as
fopen (zfile, fappend ? "a" : "w");
*/
extern FILE *esysdep_fopen P((const char *zfile, boolean fpublic,
boolean fappend, boolean fmkdirs));
/* Open a file, using the access permission of the user who invoked
the program. The frd argument is TRUE if the file should be opened
for reading, and the fbinary argument is TRUE if the file should be
opened as a binary file (this is ignored on Unix, since there all
files are binary files). This returns an openfile_t, not a FILE *.
This is supposed to be able to open a file even if it can not be
read by the uucp user. This is not possible on some older Unix
systems. */
extern openfile_t esysdep_user_fopen P((const char *zfile,
boolean frd, boolean fbinary));
/* Open a file to send to another system; the qsys argument is the
system the file is being sent to. If fcheck is TRUE, it should
make sure that the file is readable by zuser (if zuser is NULL the
file must be readable by anybody). This is to eliminate a window
between fsysdep_in_directory and esysdep_open_send. If an error
occurs, it should return EFILECLOSED. */
extern openfile_t esysdep_open_send P((const struct uuconf_system *qsys,
const char *zname,
boolean fcheck,
const char *zuser));
/* Return a temporary file name to receive into. This file will be
opened by esysdep_open_receive. The qsys argument is the system
the file is coming from, the zto argument is the name the file will
have after it has been fully received, and the ztemp argument, if
it is not NULL, is from the command sent by the remote system. The
return value must be freed using ubuffree. The function should
return NULL on error. */
extern char *zsysdep_receive_temp P((const struct uuconf_system *qsys,
const char *zfile,
const char *ztemp));
/* Open a file to receive from another system. The zreceive argument
is the return value of zsysdep_receive_temp with the same qsys,
zfile and ztemp arguments. If the function can determine that this
file has already been partially received, it should set *pcrestart
to the number of bytes that have been received. If the file has
not been partially received, *pcrestart should be set to -1. The
function should return EFILECLOSED on error. After the file is
written, fsysdep_move_file will be called to move the file to its
final destination, and to set the correct file mode. */
extern openfile_t esysdep_open_receive P((const struct uuconf_system *qsys,
const char *zto,
const char *ztemp,
const char *zreceive,
long *pcrestart));
/* Move a file. This is used to move a received file to its final
location. The zto argument is the file to create. The zorig
argument is the name of the file to move. If fmkdirs is TRUE, then
any necessary directories are created; fpublic indicates whether
they should be publically writeable or not. If fcheck is TRUE,
this should make sure the directory is writeable by the user zuser
(if zuser is NULL, then it must be writeable by any user); this is
to avoid a window of vulnerability between fsysdep_in_directory and
fsysdep_move_file. This function should return FALSE on error; the
zorig file should be removed even if an error occurs. */
extern boolean fsysdep_move_file P((const char *zorig, const char *zto,
boolean fmkdirs, boolean fpublic,
boolean fcheck, const char *zuser));
/* Change the mode of a file. The imode argument is a Unix mode.
This should return FALSE on error. */
extern boolean fsysdep_change_mode P((const char *zfile,
unsigned int imode));
/* Truncate a file which we are receiving into. This may be done by
closing the original file, removing it and reopening it. This
should return FALSE on error. */
extern openfile_t esysdep_truncate P((openfile_t e, const char *zname));
/* It is possible for the acknowledgement of a received file to be
lost. The sending system will then now know that the file was
correctly received, and will send it again. This can be a problem
particularly with protocols which support channels, since they may
send several small files in a single window, all of which may be
received correctly although the sending system never sees the
acknowledgement. If these files involve an execution, the
execution will happen twice, which will be bad.
This function is called when a file is completely received. It is
supposed to try and remember the reception, in case the connection
is lost. It is passed the system, the file name to receive to, and
the temporary file name from the sending system. It should return
FALSE on error. */
extern boolean fsysdep_remember_reception P((const struct uuconf_system *qsys,
const char *zto,
const char *ztemp));
/* This function is called to see if a file has already been received
successfully. It gets the same arguments as
fsysdep_remember_reception. It should return TRUE if the file was
already received, FALSE otherwise. There is no way to report
error. */
extern boolean fsysdep_already_received P((const struct uuconf_system *qsys,
const char *zto,
const char *ztemp));
/* This function is called when it is no longer necessary to remember
that a file has been received. This will be called when the
protocol knows that the receive message has been acknowledged. It
gets the same arguments as fsysdep_remember_reception. it should
return FALSE on error. */
extern boolean fsysdep_forget_reception P((const struct uuconf_system *qsys,
const char *zto,
const char *ztemp));
/* Start expanding a wildcarded file name. This should return FALSE
on error; otherwise subsequent calls to zsysdep_wildcard should
return file names. */
extern boolean fsysdep_wildcard_start P((const char *zfile));
/* Get the next wildcard name. This should return NULL when there are
no more names to return. The return value should be freed using
ubuffree. The argument should be the same as that to
fsysdep_wildcard_start. There is no way to return error. */
extern char *zsysdep_wildcard P((const char *zfile));
/* Finish getting wildcard names. This may be called before or after
zsysdep_wildcard has returned NULL. It should return FALSE on
error. */
extern boolean fsysdep_wildcard_end P((void));
/* Prepare to execute a bunch of file transfer requests. This should
make an entry in the spool directory so that the next time uucico
is started up it will transfer these files. The bgrade argument
specifies the grade of the commands. The commands themselves are
in the pascmds array, which has ccmds entries. The function should
return NULL on error, or the jobid on success. The jobid is a
string that may be printed or passed to fsysdep_kill_job and
related functions, but is otherwise uninterpreted. */
extern char *zsysdep_spool_commands P((const struct uuconf_system *qsys,
int bgrade, int ccmds,
const struct scmd *pascmds));
/* Get a file name to use for a data file to be copied to another
system. The ztname, zdname and zxname arguments will all either be
NULL or point to an array of CFILE_NAME_LEN characters in length.
The ztname array should be set to a temporary file name that could
be passed to zsysdep_spool_file_name to retrieve the return value
of this function; this will be appropriate for the temporary name
in a send request. The zdname array should be set to a data file
name that is appropriate for the spool directory of the other
system; this will be appropriate for the name of the destination
file in a send request of a data file for an execution of some
sort. The zxname array should be set to an execute file name that
is appropriate for the other system. The zlocalname argument is
the name of the local system as seen by the remote system, the
bgrade argument is the grade, and fxqt is TRUE if this file is
going to become an execution file. This should return NULL on
error. */
#define CFILE_NAME_LEN (15)
extern char *zsysdep_data_file_name P((const struct uuconf_system *qsys,
const char *zlocalname,
int bgrade, boolean fxqt,
char *ztname, char *zdname,
char *zxname));
/* Get a name for a local execute file. This is used by uux for a
local command with remote files. Returns NULL on error. */
extern char *zsysdep_xqt_file_name P((void));
/* Beginning getting execute files. To get a list of execute files,
first fsysdep_get_xqt_init is called, then zsysdep_get_xqt is
called several times until it returns NULL, then finally
usysdep_get_xqt_free is called. */
extern boolean fsysdep_get_xqt_init P((void));
/* Get the next execute file. This should return NULL when finished
(with *pferr set to FALSE). On an error this should return NULL
with *pferr set to TRUE. This should set *pzsystem to the name of
the system for which the execute file was created. Both the return
value and *pzsystem should be freed using ubuffree. */
extern char *zsysdep_get_xqt P((char **pzsystem,
boolean *pferr));
/* Clean up after getting execute files. */
extern void usysdep_get_xqt_free P((void));
/* Get the absolute pathname of a command to execute. This is given
the legal list of commands (which may be the special case "ALL")
and the path. It must return an absolute pathname to the command.
If it gets an error it should set *pferr to TRUE and return NULL;
if the command is not found it should set *pferr to FALSE and
return NULL. */
extern char *zsysdep_find_command P((const char *zcmd, char **pzcmds,
char **pzpath, boolean *pferr));
/* Expand file names for uuxqt. This exists because uuxqt on Unix has
to expand file names which begin with a ~. It does not want to
expand any other type of file name, and it turns a double ~ into a
single one without expanding. If this returns NULL, the file does
not need to be changed; otherwise it returns a zbufalc'ed string.
There is no way to report error. */
extern char *zsysdep_xqt_local_file P((const struct uuconf_system *qsys,
const char *zfile));
#if ! ALLOW_FILENAME_ARGUMENTS
/* Check an argument to an execution command to make sure that it
doesn't refer to a file name that may not be accessed. This should
check the argument to see if it is a filename. If it is, it should
either reject it out of hand or it should call fin_directory_list
on the file with both qsys->zremote_receive and qsys->zremote_send.
If the file is rejected, it should log an error and return FALSE.
Otherwise it should return TRUE. */
extern boolean fsysdep_xqt_check_file P((const struct uuconf_system *qsys,
const char *zfile));
#endif /* ! ALLOW_FILENAME_ARGUMENTS */
/* Run an execute file. The arguments are:
qsys -- system for which execute file was created
zuser -- user who requested execution
pazargs -- list of arguments to command (element 0 is command)
zfullcmd -- command and arguments stuck together in one string
zinput -- file name for standard input (may be NULL)
zoutput -- file name for standard output (may be NULL)
fshell -- if TRUE, use /bin/sh to execute file
ilock -- return value of ixsysdep_lock_uuxqt
pzerror -- set to name of standard error file
pftemp -- set to TRUE if error is temporary, FALSE otherwise
If fshell is TRUE, the command should be executed with /bin/sh
(obviously, this can only really be done on Unix systems). If an
error occurs this should return FALSE and set *pftemp
appropriately. *pzerror should be freed using ubuffree. */
extern boolean fsysdep_execute P((const struct uuconf_system *qsys,
const char *zuser,
const char **pazargs,
const char *zfullcmd,
const char *zinput,
const char *zoutput,
boolean fshell,
int ilock,
char **pzerror,
boolean *pftemp));
/* Lock for uuxqt execution. If the cmaxuuxqts argument is not zero,
this should make sure that no more than cmaxuuxqts uuxqt processes
are running at once. Also, only one uuxqt may execute a particular
command (specified by the -c option) at a time. If zcmd is not
NULL, it is a command that must be locked. This should return a
nonnegative number which will be passed to other routines,
including fsysdep_unlock_uuxqt, or -1 on error. */
extern int ixsysdep_lock_uuxqt P((const char *zcmd,
int cmaxuuxqts));
/* Unlock a uuxqt process. This is passed the return value of
ixsysdep_lock_uuxqt, as well as the arguments passed to
ixsysdep_lock_uuxqt. It may return FALSE on error, but at present
the return value is ignored. */
extern boolean fsysdep_unlock_uuxqt P((int iseq, const char *zcmd,
int cmaxuuxqts));
/* See whether a particular uuxqt command is locked. This should
return TRUE if the command is locked (because ixsysdep_lock_uuxqt
was called with it as an argument), FALSE otherwise. There is no
way to return error. */
extern boolean fsysdep_uuxqt_locked P((const char *zcmd));
/* Lock an execute file in order to execute it. This should return
FALSE if the execute file is already locked. There is no way to
return error. */
extern boolean fsysdep_lock_uuxqt_file P((const char *zfile));
/* Unlock an execute file. This should return FALSE on error. */
extern boolean fsysdep_unlock_uuxqt_file P((const char *zfile));
/* Lock the execution directory. The ilock argument is the return
value of ixsysdep_lock_uuxqt. This should return FALSE if the
directory is already locked. There is no way to return error. */
extern boolean fsysdep_lock_uuxqt_dir P((int ilock));
/* Remove all files in the execution directory, and unlock it. This
should return FALSE on error. */
extern boolean fsysdep_unlock_uuxqt_dir P((int ilock));
/* Move files into or out of the execution directory. The code will
already have checked that all the files exist. The elements in the
pzfrom array will be complete filenames, and the elements in the
pzto array will be either NULL (in which case the file should not
be moved) or simple base names. If fto is TRUE, the files in
pzfrom should be moved to pzto; otherwise, the files in pzto should
be moved to pzfrom (this is used if a temporary failure occurs, in
which case the execution will be retried later). If pzinput and
*pzinput are not NULL, then it is the name of the standard input
file; if it is the same as any element of pzfrom, then *pzinput
should be set to the zbufcpy of the corresponding pzto value, if
any. */
extern boolean fsysdep_move_uuxqt_files P((int cfiles,
const char *const *pzfrom,
const char *const *pzto,
boolean fto, int ilock,
char **pzinput));
/* Expand a file name on the local system, defaulting to the current
directory. This is just like zsysdep_local_file, except that
relative files are placed in the working directory the program
started in rather than in the public directory. This should return
NULL on error. */
extern char *zsysdep_local_file_cwd P((const char *zname,
const char *zpubdir));
/* Add the working directory to a file name. The named file is
actually on a remote system. If the file already has a directory,
it should not be changed. This should return NULL on error. */
extern char *zsysdep_add_cwd P((const char *zfile));
/* See whether a file name will need the current working directory
when zsysdep_local_file_cwd or zsysdep_add_cwd is called on it.
This will be called before usysdep_initialize. It should just
check whether the argument is an absolute path. See the comment
above usysdep_initialize in this file for an explanation of why
things are done this way. */
extern boolean fsysdep_needs_cwd P((const char *zfile));
/* Get the base name of a file. The file will be a local file name,
and this function should return the base file name, ideally in a
form which will make sense on most systems; it will be used if the
destination of a uucp is a directory. */
extern char *zsysdep_base_name P((const char *zfile));
/* Return a filename within a directory. */
extern char *zsysdep_in_dir P((const char *zdir, const char *zfile));
/* Get the mode of a file. This should return a Unix style file mode.
It should return 0 on error. */
extern unsigned int ixsysdep_file_mode P((const char *zfile));
/* See whether the user has access to a file. This is called by uucp
and uux to prevent copying of a file which uucp can read but the
user cannot. If access is denied, this should log an error message
and return FALSE. */
extern boolean fsysdep_access P((const char *zfile));
/* See whether the daemon has access to a file. This is called by
uucp and uux when a file is queued up for transfer without being
copied into the spool directory. It is merely an early error
check, as the daemon would of course discover the error itself when
it tried the transfer. If access would be denied, this should log
an error message and return FALSE. */
extern boolean fsysdep_daemon_access P((const char *zfile));
/* Translate a destination from system!user to a place in the public
directory where uupick will get the file. On Unix this produces
system!~/receive/user/localname, and that's probably what it has to
produce on any other system as well. Returns NULL on a usage
error, or otherwise returns string allocated by zbufcpy. */
extern char *zsysdep_uuto P((const char *zdest,
const char *zlocalname));
/* Return TRUE if a pathname exists and is a directory. */
extern boolean fsysdep_directory P((const char *zpath));
/* Walk a directory tree. The zdir argument is the directory to walk.
The pufn argument is a function to call on each regular file in the
tree. The first argument to pufn should be the full filename; the
second argument to pufn should be the filename relative to zdir;
the third argument to pufn should be the pinfo argument to
usysdep_walk_tree. The usysdep_walk_tree function should return
FALSE on error. */
extern boolean usysdep_walk_tree P((const char *zdir,
void (*pufn) P((const char *zfull,
const char *zrelative,
pointer pinfo)),
pointer pinfo));
/* Return the jobid of a work file, given the sequence value. On
error this should log an error and return NULL. The jobid is a
string which may be printed out and read in and passed to
fsysdep_kill_job, etc., but is not otherwise interpreted. */
extern char *zsysdep_jobid P((const struct uuconf_system *qsys,
pointer pseq));
/* See whether the current user is permitted to kill jobs submitted by
another user. This should return TRUE if permission is granted,
FALSE otherwise. */
extern boolean fsysdep_privileged P((void));
/* Kill a job, given the jobid. This should remove all associated
files and in general eliminate the job completely. On error it
should log an error message and return FALSE. */
extern boolean fsysdep_kill_job P((pointer puuconf,
const char *zjobid));
/* Rejuvenate a job, given the jobid. If possible, this should update
the time associated with the job such that it will not be
eliminated by uustat -K or similar programs that check the creation
time. This should affect the return value of ixsysdep_work_time.
On error it should log an error message and return FALSE. */
extern boolean fsysdep_rejuvenate_job P((pointer puuconf,
const char *zjobid));
/* Get the time a job was queued, given the sequence number. There is
no way to indicate error. The return value must use the same epoch
as ixsysdep_time. */
extern long ixsysdep_work_time P((const struct uuconf_system *qsys,
pointer pseq));
/* Get the time a file was created. This is called by uustat on
execution files. There is no way to indicate error. The return
value must use the same epoch as ixsysdep_time. */
extern long ixsysdep_file_time P((const char *zfile));
/* Get the size in bytes of a file. If this file does not exist, this
should not give an error message, but should return -1. If some
other error occurs, this should return -2. */
extern long csysdep_size P((const char *zfile));
/* Return the amount of free space on the containing the given file
name (the file may or may not exist). If the amount of free space
cannot be determined, the function should return -1. */
extern long csysdep_bytes_free P((const char *zfile));
/* Start getting status information for all systems with available
status information. There may be status information for unknown
systems, which is why this series of functions is used. The phold
argument is used to pass information around, to possibly avoid the
use of static variables. On error this should log an error and
return FALSE. */
extern boolean fsysdep_all_status_init P((pointer *phold));
/* Get status information for the next system. This should return the
system name and fill in the qstat argument. The phold argument
will be that set by fsysdep_all_status_init. On error this should
log an error, set *pferr to TRUE, and return NULL. */
extern char *zsysdep_all_status P((pointer phold, boolean *pferr,
struct sstatus *qstat));
/* Free up anything allocated by fsysdep_all_status_init and
zsysdep_all_status. The phold argument is that set by
fsysdep_all_status_init. */
extern void usysdep_all_status_free P((pointer phold));
/* Display the process status of all processes holding lock files.
This is uustat -p. The return value is passed to usysdep_exit. */
extern boolean fsysdep_lock_status P((void));
/* Return TRUE if the user has legitimate access to the port. This is
used by cu to control whether the user can open a port directly,
rather than merely being able to dial out on it. Opening a port
directly allows the modem to be reprogrammed. */
extern boolean fsysdep_port_access P((struct uuconf_port *qport));
/* Return whether the given port could be named by the given line. On
Unix, the line argument would be something like "ttyd0", and this
function should return TRUE if the named port is "/dev/ttyd0". */
extern boolean fsysdep_port_is_line P((struct uuconf_port *qport,
const char *zline));
/* Set the terminal into raw mode. In this mode no input characters
should be treated specially, and characters should be made
available as they are typed. The original terminal mode should be
saved, so that it can be restored by fsysdep_terminal_restore. If
flocalecho is TRUE, then local echoing should still be done;
otherwise echoing should be disabled. This function returns FALSE
on error. */
extern boolean fsysdep_terminal_raw P((boolean flocalecho));
/* Restore the terminal back to the original setting, before
fsysdep_terminal_raw was called. Returns FALSE on error. */
extern boolean fsysdep_terminal_restore P((void));
/* Read a line from the terminal. The fsysdep_terminal_raw function
will have been called. This should print the zprompt argument
(unless it is NULL) and return the line, allocated by zbufcpy, or
NULL on error. */
extern char *zsysdep_terminal_line P((const char *zprompt));
/* Write a line to the terminal, ending with a newline. This is
basically just puts (zline, stdout), except that the terminal will
be in raw mode, so on ASCII Unix systems the line needs to end with
\r\n. */
extern boolean fsysdep_terminal_puts P((const char *zline));
/* If faccept is TRUE, permit the user to generate signals from the
terminal. If faccept is FALSE, turn signals off again. After
fsysdep_terminal_raw is called, signals should be off. Return
FALSE on error. */
extern boolean fsysdep_terminal_signals P((boolean faccept));
/* The cu program expects the system dependent code to handle the
details of copying data from the communications port to the
terminal. This should be set up by fsysdep_cu_init, and done while
fsysdep_cu is called. It is permissible to do it on a continual
basis (on Unix a subprocess handles it) so long as the copying can
be stopped by the fsysdep_cu_copy function.
The fsysdep_cu_init function does any system dependent
initialization needed for this. */
extern boolean fsysdep_cu_init P((struct sconnection *qconn));
/* Copy all data from the communications port to the terminal, and all
data from the terminal to the communications port. Keep this up
until the escape character *zCuvar_escape is seen. Set *pbcmd to
the character following the escape character; after the escape
character, zlocalname should be printed, possibly after a delay.
If two escape characters are entered in sequence, this function
should send a single escape character to the port, and not return.
Returns FALSE on error. */
extern boolean fsysdep_cu P((struct sconnection *qconn,
char *pbcmd,
const char *zlocalname));
/* If fcopy is TRUE, start copying data from the communications port
to the terminal. If fcopy is FALSE, stop copying data. This
function may be called several times during a cu session. It
should return FALSE on error. */
extern boolean fsysdep_cu_copy P((boolean fcopy));
/* Stop copying data from the communications port to the terminal, and
generally clean up after fsysdep_cu_init and fsysdep_cu. Returns
FALSE on error. */
extern boolean fsysdep_cu_finish P((void));
/* Run a shell command. If zcmd is NULL, or *zcmd == '\0', just
start up a shell. The second argument is one of the following
values. This should return FALSE on error. */
enum tshell_cmd
{
/* Attach stdin and stdout to the terminal. */
SHELL_NORMAL,
/* Attach stdout to the communications port, stdin to the terminal. */
SHELL_STDOUT_TO_PORT,
/* Attach stdin to the communications port, stdout to the terminal. */
SHELL_STDIN_FROM_PORT,
/* Attach both stdin and stdout to the communications port. */
SHELL_STDIO_ON_PORT
};
extern boolean fsysdep_shell P((struct sconnection *qconn,
const char *zcmd,
enum tshell_cmd tcmd));
/* Change directory. If zdir is NULL, or *zdir == '\0', change to the
user's home directory. Return FALSE on error. */
extern boolean fsysdep_chdir P((const char *zdir));
/* Suspend the current process. This is only expected to work on Unix
versions that support SIGTSTP. In general, people can just shell
out. */
extern boolean fsysdep_suspend P((void));
/* Start getting files for uupick. The zsystem argument may be NULL
to get files from all systems, or it may specify a particular
system. The zpubdir argument is the public directory to use. This
returns FALSE on error. */
extern boolean fsysdep_uupick_init P((const char *zsystem,
const char *zpubdir));
/* Get the next file for uupick. This returns the basic file name.
It sets *pzfull to the full name, and *pzfrom to the name of the
system which sent this file over; both should be freed using
ubuffree. *pzfull should be passed to ubuffree after it is no
longer needed. The zsystem and zpubdir arguments should be the
same as the arguments to fsysdep_uupick_init. This returns NULL
when all files been returned. */
extern char *zsysdep_uupick P((const char *zsystem, const char *zpubdir,
char **pzfrom, char **pzfull));
/* Clean up after getting files for uupick. */
extern boolean fsysdep_uupick_free P((const char *zsystem,
const char *zpubdir));
/* Translate a local file name for uupick. On Unix this is just like
zsysdep_local_file_cwd except that a file beginning with ~/ is
placed in the user's home directory rather than in the public
directory. */
extern char *zsysdep_uupick_local_file P((const char *zfile));
/* Remove a directory and all the files in it. */
extern boolean fsysdep_rmdir P((const char *zdir));
#endif /* ! defined (SYSTEM_H) */

View File

@ -0,0 +1,470 @@
/* tcp.c
Code to handle TCP connections.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char tcp_rcsid[] = "$Id: tcp.c,v 1.1 1993/08/04 19:31:06 jtc Exp $";
#endif
#if HAVE_TCP
#include "uudefs.h"
#include "uuconf.h"
#include "sysdep.h"
#include "conn.h"
#include "system.h"
#include <errno.h>
#if HAVE_SYS_TYPES_TCP_H
#include <sys/types.tcp.h>
#endif
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
/* This code handles TCP connections. It assumes a Berkeley socket
interface. */
/* The normal "uucp" port number. */
#define IUUCP_PORT (540)
/* Local functions. */
static void utcp_free P((struct sconnection *qconn));
static boolean ftcp_open P((struct sconnection *qconn, long ibaud,
boolean fwait));
static boolean ftcp_close P((struct sconnection *qconn,
pointer puuconf,
struct uuconf_dialer *qdialer,
boolean fsuccess));
static boolean ftcp_reset P((struct sconnection *qconn));
static boolean ftcp_dial P((struct sconnection *qconn, pointer puuconf,
const struct uuconf_system *qsys,
const char *zphone,
struct uuconf_dialer *qdialer,
enum tdialerfound *ptdialer));
static int itcp_port_number P((const char *zport));
/* The command table for a TCP connection. */
static const struct sconncmds stcpcmds =
{
utcp_free,
NULL, /* pflock */
NULL, /* pfunlock */
ftcp_open,
ftcp_close,
ftcp_reset,
ftcp_dial,
fsysdep_conn_read,
fsysdep_conn_write,
fsysdep_conn_io,
NULL, /* pfbreak */
NULL, /* pfset */
NULL, /* pfcarrier */
fsysdep_conn_chat,
NULL /* pibaud */
};
/* Initialize a TCP connection. */
boolean
fsysdep_tcp_init (qconn)
struct sconnection *qconn;
{
struct ssysdep_conn *q;
q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
q->o = -1;
q->zdevice = NULL;
q->iflags = -1;
q->istdout_flags = -1;
q->fterminal = FALSE;
q->ftli = FALSE;
q->ibaud = 0;
qconn->psysdep = (pointer) q;
qconn->qcmds = &stcpcmds;
return TRUE;
}
/* Free a TCP connection. */
static void
utcp_free (qconn)
struct sconnection *qconn;
{
xfree (qconn->psysdep);
}
/* Open a TCP connection. If the fwait argument is TRUE, we are
running as a server. Otherwise we are just trying to reach another
system. */
static boolean
ftcp_open (qconn, ibaud, fwait)
struct sconnection *qconn;
long ibaud;
boolean fwait;
{
struct ssysdep_conn *qsysdep;
struct sockaddr_in s;
const char *zport;
uid_t iuid, ieuid;
ulog_device ("TCP");
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
qsysdep->o = socket (AF_INET, SOCK_STREAM, 0);
if (qsysdep->o < 0)
{
ulog (LOG_ERROR, "socket: %s", strerror (errno));
return FALSE;
}
if (fcntl (qsysdep->o, F_SETFD,
fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0)
{
ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
(void) close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0);
if (qsysdep->iflags < 0)
{
ulog (LOG_ERROR, "fcntl: %s", strerror (errno));
(void) close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
/* If we aren't waiting for a connection, we're done. */
if (! fwait)
return TRUE;
/* Run as a server and wait for a new connection. The code in
uucico.c has already detached us from our controlling terminal.
From this point on if the server gets an error we exit; we only
return if we have received a connection. It would be more robust
to respawn the server if it fails; someday. */
bzero ((pointer) &s, sizeof s);
s.sin_family = AF_INET;
zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport;
s.sin_port = itcp_port_number (zport);
s.sin_addr.s_addr = htonl (INADDR_ANY);
/* Swap to our real user ID when doing the bind call. This will
permit the server to use privileged TCP ports when invoked by
root. We only swap if our effective user ID is not root, so that
the program can also be made suid root in order to get privileged
ports when invoked by anybody. */
iuid = getuid ();
ieuid = geteuid ();
if (ieuid != 0)
{
#if HAVE_SETREUID
/* Swap the effective user id and the real user id. We can then
swap them back again when we want to return to the uucp
user's permissions. */
if (setreuid (ieuid, iuid) < 0)
{
ulog (LOG_ERROR, "setreuid (%ld, %ld): %s",
(long) ieuid, (long) iuid, strerror (errno));
(void) close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
#else /* ! HAVE_SETREUID */
#if HAVE_SAVED_SETUID
/* Set the effective user id to the real user id. Since the
effective user id is the saved setuid we will able to set
back to it later. If the real user id is root we will not be
able to switch back and forth, but that doesn't matter since
we only want to switch once. */
if (setuid (iuid) < 0)
{
ulog (LOG_ERROR, "setuid (%ld): %s", (long) iuid,
strerror (errno));
(void) close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
#else /* ! HAVE_SAVED_SETUID */
/* There's no way to switch between real permissions and
effective permissions. Just try the bind with the uucp
permissions. */
#endif /* ! HAVE_SAVED_SETUID */
#endif /* ! HAVE_SETREUID */
}
if (bind (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0)
ulog (LOG_FATAL, "bind: %s", strerror (errno));
/* Now swap back to the uucp user ID. */
if (ieuid != 0)
{
#if HAVE_SETREUID
if (setreuid (iuid, ieuid) < 0)
{
ulog (LOG_ERROR, "setreuid (%ld, %ld): %s",
(long) iuid, (long) ieuid, strerror (errno));
(void) close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
#else /* ! HAVE_SETREUID */
#if HAVE_SAVED_SETUID
/* Set ourselves back to our original effective user id. */
if (setuid ((uid_t) ieuid) < 0)
{
ulog (LOG_ERROR, "setuid (%ld): %s", (long) ieuid,
strerror (errno));
(void) close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
#else /* ! HAVE_SAVED_SETUID */
/* We didn't switch, no need to switch back. */
#endif /* ! HAVE_SAVED_SETUID */
#endif /* ! HAVE_SETREUID */
}
if (listen (qsysdep->o, 5) < 0)
ulog (LOG_FATAL, "listen: %s", strerror (errno));
while (! FGOT_SIGNAL ())
{
size_t clen;
int onew;
pid_t ipid;
DEBUG_MESSAGE0 (DEBUG_PORT,
"ftcp_open: Waiting for connections");
clen = sizeof s;
onew = accept (qsysdep->o, (struct sockaddr *) &s, &clen);
if (onew < 0)
ulog (LOG_FATAL, "accept: %s", strerror (errno));
DEBUG_MESSAGE0 (DEBUG_PORT,
"ftcp_open: Got connection; forking");
ipid = ixsfork ();
if (ipid < 0)
ulog (LOG_FATAL, "fork: %s", strerror (errno));
if (ipid == 0)
{
(void) close (qsysdep->o);
qsysdep->o = onew;
/* Now we fork and let our parent die, so that we become
a child of init. This lets the main server code wait
for its child and then continue without accumulating
zombie children. */
ipid = ixsfork ();
if (ipid < 0)
{
ulog (LOG_ERROR, "fork: %s", strerror (errno));
_exit (EXIT_FAILURE);
}
if (ipid != 0)
_exit (EXIT_SUCCESS);
ulog_id (getpid ());
return TRUE;
}
(void) close (onew);
/* Now wait for the child. */
(void) ixswait ((unsigned long) ipid, (const char *) NULL);
}
/* We got a signal. */
usysdep_exit (FALSE);
/* Avoid compiler warnings. */
return FALSE;
}
/* Close the port. */
/*ARGSUSED*/
static boolean
ftcp_close (qconn, puuconf, qdialer, fsuccess)
struct sconnection *qconn;
pointer puuconf;
struct uuconf_dialer *qdialer;
boolean fsuccess;
{
struct ssysdep_conn *qsysdep;
boolean fret;
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
fret = TRUE;
if (qsysdep->o >= 0 && close (qsysdep->o) < 0)
{
ulog (LOG_ERROR, "close: %s", strerror (errno));
fret = FALSE;
}
qsysdep->o = -1;
return fret;
}
/* Reset the port. This will be called by a child which was forked
off in ftcp_open, above. We don't want uucico to continue looping
and giving login prompts, so we pretend that we received a SIGINT
signal. This should probably be handled more cleanly. The signal
will not be recorded in the log file because we don't set
afLog_signal[INDEXSIG_SIGINT]. */
/*ARGSUSED*/
static boolean
ftcp_reset (qconn)
struct sconnection *qconn;
{
afSignal[INDEXSIG_SIGINT] = TRUE;
return TRUE;
}
/* Dial out on a TCP port, so to speak: connect to a remote computer. */
/*ARGSUSED*/
static boolean
ftcp_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
struct sconnection *qconn;
pointer puuconf;
const struct uuconf_system *qsys;
const char *zphone;
struct uuconf_dialer *qdialer;
enum tdialerfound *ptdialer;
{
struct ssysdep_conn *qsysdep;
const char *zhost;
struct hostent *q;
struct sockaddr_in s;
const char *zport;
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
*ptdialer = DIALERFOUND_FALSE;
zhost = zphone;
if (zhost == NULL)
{
if (qsys == NULL)
{
ulog (LOG_ERROR, "No address for TCP connection");
return FALSE;
}
zhost = qsys->uuconf_zname;
}
errno = 0;
q = gethostbyname ((char *) zhost);
if (q == NULL)
{
if (errno == 0)
ulog (LOG_ERROR, "%s: unknown host name", zhost);
else
ulog (LOG_ERROR, "gethostbyname (%s): %s", zhost, strerror (errno));
return FALSE;
}
s.sin_family = q->h_addrtype;
zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport;
s.sin_port = itcp_port_number (zport);
memcpy (&s.sin_addr.s_addr, q->h_addr, (size_t) q->h_length);
if (connect (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0)
{
ulog (LOG_ERROR, "connect: %s", strerror (errno));
return FALSE;
}
return TRUE;
}
/* Get the port number given a name. The argument will almost always
be "uucp" so we cache that value. The return value is always in
network byte order. This returns -1 on error. */
static int
itcp_port_number (zname)
const char *zname;
{
boolean fuucp;
static int iuucp;
int i;
char *zend;
struct servent *q;
fuucp = strcmp (zname, "uucp") == 0;
if (fuucp && iuucp != 0)
return iuucp;
/* Try it as a number first. */
i = strtol ((char *) zname, &zend, 10);
if (i != 0 && *zend == '\0')
return htons (i);
q = getservbyname ((char *) zname, (char *) "tcp");
if (q == NULL)
{
/* We know that the "uucp" service should be 540, even if isn't
in /etc/services. */
if (fuucp)
{
iuucp = htons (IUUCP_PORT);
return iuucp;
}
ulog (LOG_ERROR, "getservbyname (%s): %s", zname, strerror (errno));
return -1;
}
if (fuucp)
iuucp = q->s_port;
return q->s_port;
}
#endif /* HAVE_TCP */

View File

@ -0,0 +1,644 @@
/* tli.c
Code to handle TLI connections.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char tli_rcsid[] = "$Id: tli.c,v 1.1 1993/08/04 19:31:09 jtc Exp $";
#endif
#if HAVE_TLI
#include "sysdep.h"
#include "uudefs.h"
#include "uuconf.h"
#include "conn.h"
#include "system.h"
#include <errno.h>
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if HAVE_TIUSER_H
#include <tiuser.h>
#else
#if HAVE_XTI_H
#include <xti.h>
#else
#if HAVE_SYS_TLI_H
#include <sys/tli.h>
#endif
#endif
#endif
#if HAVE_STROPTS_H
#include <stropts.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
/* The arguments to t_alloca have two different names. I want the
SVID ones, not the XPG3 ones. */
#ifndef T_BIND
#define T_BIND T_BIND_STR
#endif
#ifndef T_CALL
#define T_CALL T_CALL_STR
#endif
/* Hopefully these externs will not cause any trouble. This is how
they are shown in the SVID. */
extern int t_errno;
extern char *t_errlist[];
extern int t_nerr;
#ifndef t_alloc
extern pointer t_alloc ();
#endif
/* This code handles TLI connections. It's Unix specific. It's
largely based on code from Unix Network Programming, by W. Richard
Stevens. */
/* Local functions. */
static const char *ztlierror P((void));
static void utli_free P((struct sconnection *qconn));
static boolean ftli_push P((struct sconnection *qconn));
static boolean ftli_open P((struct sconnection *qconn, long ibaud,
boolean fwait));
static boolean ftli_close P((struct sconnection *qconn,
pointer puuconf,
struct uuconf_dialer *qdialer,
boolean fsuccess));
static boolean ftli_reset P((struct sconnection *qconn));
static boolean ftli_dial P((struct sconnection *qconn, pointer puuconf,
const struct uuconf_system *qsys,
const char *zphone,
struct uuconf_dialer *qdialer,
enum tdialerfound *ptdialer));
/* The command table for a TLI connection. */
static const struct sconncmds stlicmds =
{
utli_free,
NULL, /* pflock */
NULL, /* pfunlock */
ftli_open,
ftli_close,
ftli_reset,
ftli_dial,
fsysdep_conn_read,
fsysdep_conn_write,
fsysdep_conn_io,
NULL, /* pfbreak */
NULL, /* pfset */
NULL, /* pfcarrier */
fsysdep_conn_chat,
NULL /* pibaud */
};
/* Get a TLI error string. */
static const char *
ztlierror ()
{
if (t_errno == TSYSERR)
return strerror (errno);
if (t_errno < 0 || t_errno >= t_nerr)
return "Unknown TLI error";
return t_errlist[t_errno];
}
/* Initialize a TLI connection. */
boolean
fsysdep_tli_init (qconn)
struct sconnection *qconn;
{
struct ssysdep_conn *q;
q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
q->o = -1;
q->zdevice = NULL;
q->iflags = -1;
q->istdout_flags = -1;
q->fterminal = FALSE;
q->ftli = TRUE;
q->ibaud = 0;
qconn->psysdep = (pointer) q;
qconn->qcmds = &stlicmds;
return TRUE;
}
/* Free a TLI connection. */
static void
utli_free (qconn)
struct sconnection *qconn;
{
xfree (qconn->psysdep);
}
/* Push all desired modules onto a TLI stream. If the user requests a
STREAMS connection without giving a list of modules, we just push
tirdwr. If the I_PUSH ioctl is not defined on this system, we just
ignore any list of modules. */
static boolean
ftli_push (qconn)
struct sconnection *qconn;
{
#ifdef I_PUSH
struct ssysdep_conn *qsysdep;
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
if (qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush != NULL)
{
char **pz;
for (pz = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush;
*pz != NULL;
pz++)
{
if (ioctl (qsysdep->o, I_PUSH, *pz) < 0)
{
ulog (LOG_ERROR, "ioctl (I_PUSH, %s): %s", *pz,
strerror (errno));
return FALSE;
}
}
}
else if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream)
{
if (ioctl (qsysdep->o, I_PUSH, "tirdwr") < 0)
{
ulog (LOG_ERROR, "ioctl (I_PUSH, tirdwr): %s",
strerror (errno));
return FALSE;
}
}
/* If we have just put the connection into stream mode, we must turn
off the TLI flag to avoid using TLI calls on it. */
if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream)
qsysdep->ftli = FALSE;
#endif /* defined (I_PUSH) */
return TRUE;
}
/* Open a TLI connection. If the fwait argument is TRUE, we are
running as a server. Otherwise we are just trying to reach another
system. */
static boolean
ftli_open (qconn, ibaud, fwait)
struct sconnection *qconn;
long ibaud;
boolean fwait;
{
struct ssysdep_conn *qsysdep;
const char *zdevice;
char *zfreedev;
const char *zservaddr;
char *zfreeaddr;
struct t_bind *qtbind;
struct t_call *qtcall;
/* Unlike most other device types, we don't bother to call
ulog_device here, because fconn_open calls it with the name of
the port anyhow. */
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
zdevice = qconn->qport->uuconf_u.uuconf_stli.uuconf_zdevice;
if (zdevice == NULL)
zdevice = qconn->qport->uuconf_zname;
zfreedev = NULL;
if (*zdevice != '/')
{
zfreedev = zbufalc (sizeof "/dev/" + strlen (zdevice));
sprintf (zfreedev, "/dev/%s", zdevice);
zdevice = zfreedev;
}
qsysdep->o = t_open (zdevice, O_RDWR, (struct t_info *) NULL);
if (qsysdep->o < 0)
{
ulog (LOG_ERROR, "t_open (%s): %s", zdevice, ztlierror ());
ubuffree (zfreedev);
return FALSE;
}
if (fcntl (qsysdep->o, F_SETFD,
fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0)
{
ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
ubuffree (zfreedev);
(void) t_close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0);
if (qsysdep->iflags < 0)
{
ulog (LOG_ERROR, "fcntl: %s", strerror (errno));
ubuffree (zfreedev);
(void) t_close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
/* If we aren't waiting for a connection, we can bind to any local
address, and then we're finished. */
if (! fwait)
{
ubuffree (zfreedev);
if (t_bind (qsysdep->o, (struct t_bind *) NULL,
(struct t_bind *) NULL) < 0)
{
ulog (LOG_ERROR, "t_bind: %s", ztlierror ());
(void) t_close (qsysdep->o);
qsysdep->o = -1;
return FALSE;
}
return TRUE;
}
/* Run as a server and wait for a new connection. The code in
uucico.c has already detached us from our controlling terminal.
From this point on if the server gets an error we exit; we only
return if we have received a connection. It would be more robust
to respawn the server if it fails; someday. */
qtbind = (struct t_bind *) t_alloc (qsysdep->o, T_BIND, T_ALL);
if (qtbind == NULL)
ulog (LOG_FATAL, "t_alloc (T_BIND): %s", ztlierror ());
zservaddr = qconn->qport->uuconf_u.uuconf_stli.uuconf_zservaddr;
if (zservaddr == NULL)
ulog (LOG_FATAL, "Can't run as TLI server; no server address");
zfreeaddr = zbufcpy (zservaddr);
qtbind->addr.len = cescape (zfreeaddr);
if (qtbind->addr.len > qtbind->addr.maxlen)
ulog (LOG_FATAL, "%s: TLI server address too long (max %d)",
zservaddr, qtbind->addr.maxlen);
memcpy (qtbind->addr.buf, zfreeaddr, qtbind->addr.len);
ubuffree (zfreeaddr);
qtbind->qlen = 5;
if (t_bind (qsysdep->o, qtbind, (struct t_bind *) NULL) < 0)
ulog (LOG_FATAL, "t_bind (%s): %s", zservaddr, ztlierror ());
(void) t_free ((pointer) qtbind, T_BIND);
qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ALL);
if (qtcall == NULL)
ulog (LOG_FATAL, "t_alloc (T_CALL): %s", ztlierror ());
while (! FGOT_SIGNAL ())
{
int onew;
pid_t ipid;
DEBUG_MESSAGE0 (DEBUG_PORT,
"ftli_open: Waiting for connections");
if (t_listen (qsysdep->o, qtcall) < 0)
ulog (LOG_FATAL, "t_listen: %s", ztlierror ());
onew = t_open (zdevice, O_RDWR, (struct t_info *) NULL);
if (onew < 0)
ulog (LOG_FATAL, "t_open (%s): %s", zdevice, ztlierror ());
if (fcntl (onew, F_SETFD,
fcntl (onew, F_GETFD, 0) | FD_CLOEXEC) < 0)
ulog (LOG_FATAL, "fcntl (FD_CLOEXEC): %s", strerror (errno));
if (t_bind (onew, (struct t_bind *) NULL, (struct t_bind *) NULL) < 0)
ulog (LOG_FATAL, "t_bind: %s", ztlierror ());
if (t_accept (qsysdep->o, onew, qtcall) < 0)
{
/* We may have received a disconnect. */
if (t_errno != TLOOK)
ulog (LOG_FATAL, "t_accept: %s", ztlierror ());
if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0)
ulog (LOG_FATAL, "t_rcvdis: %s", ztlierror ());
(void) t_close (onew);
continue;
}
DEBUG_MESSAGE0 (DEBUG_PORT,
"ftli_open: Got connection; forking");
ipid = ixsfork ();
if (ipid < 0)
ulog (LOG_FATAL, "fork: %s", strerror (errno));
if (ipid == 0)
{
ulog_close ();
(void) t_close (qsysdep->o);
qsysdep->o = onew;
/* Push any desired modules. */
if (! ftli_push (qconn))
_exit (EXIT_FAILURE);
/* Now we fork and let our parent die, so that we become
a child of init. This lets the main server code wait
for its child and then continue without accumulating
zombie children. */
ipid = ixsfork ();
if (ipid < 0)
{
ulog (LOG_ERROR, "fork: %s", strerror (errno));
_exit (EXIT_FAILURE);
}
if (ipid != 0)
_exit (EXIT_SUCCESS);
ulog_id (getpid ());
return TRUE;
}
(void) t_close (onew);
/* Now wait for the child. */
(void) ixswait ((unsigned long) ipid, (const char *) NULL);
}
/* We got a signal. */
usysdep_exit (FALSE);
/* Avoid compiler warnings. */
return FALSE;
}
/* Close the port. */
/*ARGSUSED*/
static boolean
ftli_close (qconn, puuconf, qdialer, fsuccess)
struct sconnection *qconn;
pointer puuconf;
struct uuconf_dialer *qdialer;
boolean fsuccess;
{
struct ssysdep_conn *qsysdep;
boolean fret;
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
fret = TRUE;
if (qsysdep->o >= 0)
{
if (qsysdep->ftli)
{
if (t_close (qsysdep->o) < 0)
{
ulog (LOG_ERROR, "t_close: %s", ztlierror ());
fret = FALSE;
}
}
else
{
if (close (qsysdep->o) < 0)
{
ulog (LOG_ERROR, "close: %s", strerror (errno));
fret = FALSE;
}
}
qsysdep->o = -1;
}
return fret;
}
/* Reset the port. This will be called by a child which was forked
off in ftli_open, above. We don't want uucico to continue looping
and giving login prompts, so we pretend that we received a SIGINT
signal. This should probably be handled more cleanly. The signal
will not be recorded in the log file because we don't set
afLog_signal[INDEXSIG_SIGINT]. */
/*ARGSUSED*/
static boolean
ftli_reset (qconn)
struct sconnection *qconn;
{
afSignal[INDEXSIG_SIGINT] = TRUE;
return TRUE;
}
/* Dial out on a TLI port, so to speak: connect to a remote computer. */
/*ARGSUSED*/
static boolean
ftli_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound)
struct sconnection *qconn;
pointer puuconf;
const struct uuconf_system *qsys;
const char *zphone;
struct uuconf_dialer *qdialer;
enum tdialerfound *ptdialerfound;
{
struct ssysdep_conn *qsysdep;
char **pzdialer;
const char *zaddr;
struct t_call *qtcall;
char *zescape;
qsysdep = (struct ssysdep_conn *) qconn->psysdep;
*ptdialerfound = DIALERFOUND_FALSE;
pzdialer = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzdialer;
if (*pzdialer == NULL)
pzdialer = NULL;
/* If the first dialer is "TLI" or "TLIS", we use the first token
(pzdialer[1]) as the address to connect to. */
zaddr = zphone;
if (pzdialer != NULL
&& (strcmp (pzdialer[0], "TLI") == 0
|| strcmp (pzdialer[0], "TLIS") == 0))
{
if (pzdialer[1] == NULL)
++pzdialer;
else
{
if (strcmp (pzdialer[1], "\\D") != 0
&& strcmp (pzdialer[1], "\\T") != 0)
zaddr = pzdialer[1];
pzdialer += 2;
}
}
if (zaddr == NULL)
{
ulog (LOG_ERROR, "No address for TLI connection");
return FALSE;
}
qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ADDR);
if (qtcall == NULL)
{
ulog (LOG_ERROR, "t_alloc (T_CALL): %s", ztlierror ());
return FALSE;
}
zescape = zbufcpy (zaddr);
qtcall->addr.len = cescape (zescape);
if (qtcall->addr.len > qtcall->addr.maxlen)
{
ulog (LOG_ERROR, "%s: TLI address too long (max %d)", zaddr,
qtcall->addr.maxlen);
ubuffree (zescape);
return FALSE;
}
memcpy (qtcall->addr.buf, zescape, qtcall->addr.len);
ubuffree (zescape);
if (t_connect (qsysdep->o, qtcall, (struct t_call *) NULL) < 0)
{
if (t_errno != TLOOK)
ulog (LOG_ERROR, "t_connect: %s", ztlierror ());
else
{
if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0)
ulog (LOG_ERROR, "t_rcvdis: %s", ztlierror ());
else
ulog (LOG_ERROR, "Connection refused");
}
return FALSE;
}
/* We've connected to the remote. Push any desired modules. */
if (! ftli_push (qconn))
return FALSE;
/* Handle the rest of the dialer sequence. This is similar to
fmodem_dial, and they should, perhaps, be combined somehow. */
if (pzdialer != NULL)
{
boolean ffirst;
ffirst = TRUE;
while (*pzdialer != NULL)
{
int iuuconf;
struct uuconf_dialer *q;
struct uuconf_dialer s;
const char *ztoken;
boolean ftranslate;
if (! ffirst)
q = &s;
else
q = qdialer;
iuuconf = uuconf_dialer_info (puuconf, *pzdialer, q);
if (iuuconf == UUCONF_NOT_FOUND)
{
ulog (LOG_ERROR, "%s: Dialer not found", *pzdialer);
return FALSE;
}
else if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
return FALSE;
}
++pzdialer;
ztoken = *pzdialer;
ftranslate = FALSE;
if (ztoken == NULL
|| strcmp (ztoken, "\\D") == 0)
ztoken = zphone;
else if (strcmp (ztoken, "\\T") == 0)
{
ztoken = zphone;
ftranslate = TRUE;
}
if (! fchat (qconn, puuconf, &q->uuconf_schat,
(const struct uuconf_system *) NULL, q,
zphone, ftranslate, qconn->qport->uuconf_zname,
(long) 0))
{
(void) uuconf_dialer_free (puuconf, q);
if (! ffirst)
(void) uuconf_dialer_free (puuconf, qdialer);
return FALSE;
}
if (ffirst)
{
*ptdialerfound = DIALERFOUND_FREE;
ffirst = FALSE;
}
else
(void) uuconf_dialer_free (puuconf, q);
if (*pzdialer != NULL)
++pzdialer;
}
}
return TRUE;
}
#endif /* HAVE_TLI */

View File

@ -0,0 +1,268 @@
/* trans.h
Header file for file and command transfer routines.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
/* The maximum possible number of channels. */
#define IMAX_CHAN (16)
/* The ifeatures field of the sdaemon structure is an or of the
following values. These values are sent during the uucico
handshake, and MUST NOT CHANGE. */
/* File size negotiation. */
#define FEATURE_SIZES (01)
/* File transfer restart. */
#define FEATURE_RESTART (02)
/* The E (execute) command. */
#define FEATURE_EXEC (04)
/* Version 1.03: requires decimal size in S and R command. Needless
to say, this should not be used by any new programs. */
#define FEATURE_V103 (010)
/* SVR4 UUCP: expects dummy string between notify field and size field
in send command. There is probably some meaning to this string,
but I don't know what it is. If I ever find out, this flag will
still be used to indicate it. */
#define FEATURE_SVR4 (020)
/* This structure is used to hold information concerning the
communication link established with the remote system. */
struct sdaemon
{
/* Global uuconf pointer. */
pointer puuconf;
/* Remote system information. */
const struct uuconf_system *qsys;
/* Local name being used. */
const char *zlocalname;
/* Connection structure. */
struct sconnection *qconn;
/* Protocol being used. */
const struct sprotocol *qproto;
/* The largest file size permitted for a local request. */
long clocal_size;
/* The largest file size permitted for a remote request. */
long cremote_size;
/* The largest file size that may ever be transferred. */
long cmax_ever;
/* The remote system ulimit. */
long cmax_receive;
/* Features supported by the remote side. */
int ifeatures;
/* TRUE if we should request the remote side to hang up. */
boolean frequest_hangup;
/* TRUE if the remote side requested a hangup. */
boolean fhangup_requested;
/* TRUE if we are hanging up. */
boolean fhangup;
/* TRUE if the local system is currently the master. */
boolean fmaster;
/* TRUE if the local system placed the call. */
boolean fcaller;
/* UUCONF_RELIABLE_* flags for the connection. */
int ireliable;
/* If fcaller is FALSE, the lowest grade which may be transferred
during this call. */
char bgrade;
};
/* This structure is used to hold a file or command transfer which is
in progress. */
struct stransfer
{
/* Next file transfer in queue. */
struct stransfer *qnext;
/* Previous file transfer in queue. */
struct stransfer *qprev;
/* Points to the queue this structure is on. */
struct stransfer **pqqueue;
/* The function to call to send some data. */
boolean (*psendfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon));
/* The function to call when data is received. */
boolean (*precfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon,
const char *zdata, size_t cdata));
/* Type specific information. */
pointer pinfo;
/* TRUE if we are sending the file e (this is used to avoid a call
to psendfn). */
boolean fsendfile;
/* TRUE if we are receiving the file e (this is used to avoid a call
to precfn). */
boolean frecfile;
/* The file to read or write. */
openfile_t e;
/* The position we are at in the file. */
long ipos;
/* TRUE if we are waiting for a command string. */
boolean fcmd;
/* The command string we have so far. */
char *zcmd;
/* The length of the command string we have so far. */
size_t ccmd;
/* Local destination number. */
int ilocal;
/* Remote destination number. */
int iremote;
/* The command. */
struct scmd s;
/* A message to log when work starts. */
char *zlog;
/* The process time; imicros can be negative. */
long isecs;
long imicros;
/* Number of bytes sent or received. */
long cbytes;
};
/* Reasons that a file transfer might fail. */
enum tfailure
{
/* No failure. */
FAILURE_NONE,
/* No permission for operation. */
FAILURE_PERM,
/* Can't open necessary file. */
FAILURE_OPEN,
/* Not enough space to receive file. */
FAILURE_SIZE,
/* File was received in a previous conversation. */
FAILURE_RECEIVED
};
/* The main loop which talks to the remote system, passing transfer
requests and file back and forth. */
extern boolean floop P((struct sdaemon *qdaemon));
/* Allocate a new transfer structure. */
extern struct stransfer *qtransalc P((struct scmd *qcmd));
/* Free a transfer structure. */
extern void utransfree P((struct stransfer *qtrans));
/* Queue up local requests. If pfany is not NULL, this sets *pfany to
TRUE if there are, in fact, any local requests which can be done at
this point. */
extern boolean fqueue P((struct sdaemon *qdaemon, boolean *pfany));
/* Clear away any queued requests. This may be called more than once
at the end of a call. */
extern void uclear_queue P((struct sdaemon *qdaemon));
/* Queue a new transfer request made by the local system. */
extern boolean fqueue_local P((struct sdaemon *qdaemon,
struct stransfer *qtrans));
/* Queue a new transfer request made by the remote system. */
extern boolean fqueue_remote P((struct sdaemon *qdaemon,
struct stransfer *qtrans));
/* Queue a transfer request which wants to send something. */
extern boolean fqueue_send P((struct sdaemon *qdaemon,
struct stransfer *qtrans));
/* Queue a transfer request which wants to receiving something. */
extern boolean fqueue_receive P((struct sdaemon *qdaemon,
struct stransfer *qtrans));
/* Prepare to send a file by local or remote request. */
extern boolean flocal_send_file_init P((struct sdaemon *qdaemon,
struct scmd *qcmd));
extern boolean fremote_send_file_init P((struct sdaemon *qdaemon,
struct scmd *qcmd,
int iremote));
/* Prepare to receive a file by local or remote request. */
extern boolean flocal_rec_file_init P((struct sdaemon *qdaemon,
struct scmd *qcmd));
extern boolean fremote_rec_file_init P((struct sdaemon *qdaemon,
struct scmd *qcmd,
int iremote));
/* Prepare to request work by local or remote request. */
extern boolean flocal_xcmd_init P((struct sdaemon *qdaemon,
struct scmd *qcmd));
extern boolean fremote_xcmd_init P((struct sdaemon *qdaemon,
struct scmd *qcmd,
int iremote));
/* We have lost the connection; record any in progress file transfers
in the statistics file and discard any temporary files. */
extern void ufailed P((struct sdaemon *qdaemon));
/* Check that there is enough disk space for a file receive. Return
FALSE if there is not. */
extern boolean frec_check_free P((struct stransfer *qtrans,
long cfree_space));
/* Discard the temporary file being used to receive a file, if
appropriate. */
extern boolean frec_discard_temp P((struct sdaemon *qdaemon,
struct stransfer *qtrans));
/* Handle data received by a protocol. This is called by the protocol
specific routines as data comes in. The data is passed as two
buffers because that is convenient for packet based protocols, but
normally csecond will be 0. The ilocal argument is the local
channel number, and the iremote argument is the remote channel
number. Either may be -1, if the protocol does not have channels.
The ipos argument is the position in the file, if the protocol
knows it; for most protocols, this will be -1. The fallacked
argument should be set to TRUE if the remote has acknowledged all
outstanding data; see uwindow_acked, below, for details. This will
set *pfexit to TRUE if there is something for the main loop to do.
A file is complete is when a zero length buffer is passed (cfirst
== 0). A command is complete when data containing a null byte is
passed. This will return FALSE on error. If the protocol pfwait
entry point should exit and let the top level loop continue,
*pfexit will be set to TRUE (if pfexit is not NULL). This will not
set *pfexit to FALSE, so the caller must do that. */
extern boolean fgot_data P((struct sdaemon *qdaemon,
const char *zfirst, size_t cfirst,
const char *zsecond, size_t csecond,
int ilocal, int iremote,
long ipos, boolean fallacked,
boolean *pfexit));
/* This routine is called when an ack is sent for a file receive. */
extern void usent_receive_ack P((struct sdaemon *qdaemon,
struct stransfer *qtrans));
/* A protocol may call this routine to indicate the packets have been
acknowledged by the remote system. If the fallacked argument is
TRUE, then all outstanding packets have been acknowledged; for
convenience, this may also be indicated by passing fallacked as
TRUE to fgot_data, above. Otherwise this routine should be called
each time a complete window is acked by the remote system. The
transfer code uses this information to keep track of when an
acknowledgement of a file receive has been seen by the other side,
so that file receives may be handled cleanly if the connection is
lost. */
extern void uwindow_acked P((struct sdaemon *qdaemon,
boolean fallacked));

View File

@ -0,0 +1,144 @@
/* util.c
A couple of UUCP utility functions.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char util_rcsid[] = "$Id: util.c,v 1.1 1993/08/04 19:31:13 jtc Exp $";
#endif
#include <ctype.h>
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
/* Get information for an unknown system. This will leave the name
allocated on the heap. We could fix this by breaking the
abstraction and adding the name to qsys->palloc. It makes sure the
name is not too long, but takes no other useful action. */
boolean
funknown_system (puuconf, zsystem, qsys)
pointer puuconf;
const char *zsystem;
struct uuconf_system *qsys;
{
char *z;
int iuuconf;
if (strlen (zsystem) <= cSysdep_max_name_len)
z = zbufcpy (zsystem);
else
{
char **pznames, **pz;
boolean ffound;
z = zbufalc (cSysdep_max_name_len + 1);
memcpy (z, zsystem, cSysdep_max_name_len);
z[cSysdep_max_name_len] = '\0';
iuuconf = uuconf_system_names (puuconf, &pznames, TRUE);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
ffound = FALSE;
for (pz = pznames; *pz != NULL; pz++)
{
if (strcmp (*pz, z) == 0)
ffound = TRUE;
xfree ((pointer) *pz);
}
xfree ((pointer) pznames);
if (ffound)
{
ubuffree (z);
return FALSE;
}
}
iuuconf = uuconf_system_unknown (puuconf, qsys);
if (iuuconf == UUCONF_NOT_FOUND)
{
ubuffree (z);
return FALSE;
}
else if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
for (; qsys != NULL; qsys = qsys->uuconf_qalternate)
qsys->uuconf_zname = z;
return TRUE;
}
/* See whether a file is in a directory list, and make sure the user
has appropriate access. */
boolean
fin_directory_list (zfile, pzdirs, zpubdir, fcheck, freadable, zuser)
const char *zfile;
char **pzdirs;
const char *zpubdir;
boolean fcheck;
boolean freadable;
const char *zuser;
{
boolean fmatch;
char **pz;
fmatch = FALSE;
for (pz = pzdirs; *pz != NULL; pz++)
{
char *zuse;
if (pz[0][0] == '!')
{
zuse = zsysdep_local_file (*pz + 1, zpubdir);
if (zuse == NULL)
return FALSE;
if (fsysdep_in_directory (zfile, zuse, FALSE,
FALSE, (const char *) NULL))
fmatch = FALSE;
}
else
{
zuse = zsysdep_local_file (*pz, zpubdir);
if (zuse == NULL)
return FALSE;
if (fsysdep_in_directory (zfile, zuse, fcheck,
freadable, zuser))
fmatch = TRUE;
}
ubuffree (zuse);
}
return fmatch;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
/* uucp.h
Header file for the UUCP package.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
/* Get the system configuration parameters. */
#include "conf.h"
#include "policy.h"
/* Get a definition for ANSI_C if we weren't given one. */
#ifndef ANSI_C
#ifdef __STDC__
#define ANSI_C 1
#else /* ! defined (__STDC__) */
#define ANSI_C 0
#endif /* ! defined (__STDC__) */
#endif /* ! defined (ANSI_C) */
/* Pass this definition into uuconf.h. */
#define UUCONF_ANSI_C ANSI_C
/* We always include some standard header files. We need <signal.h>
to define sig_atomic_t. */
#if HAVE_STDDEF_H
#include <stddef.h>
#endif
#include <stdio.h>
#include <signal.h>
/* On some systems we need <sys/types.h> to get sig_atomic_t or
size_t or time_t. */
#if ! HAVE_SIG_ATOMIC_T_IN_SIGNAL_H && HAVE_SIG_ATOMIC_T_IN_TYPES_H
#define USE_TYPES_H 1
#else
#if ! HAVE_SIZE_T_IN_STDDEF_H && HAVE_SIZE_T_IN_TYPES_H
#define USE_TYPES_H 1
#else
#if ! HAVE_TIME_T_IN_TIME_H && HAVE_TIME_T_IN_TYPES_H
#define USE_TYPES_H 1
#endif
#endif
#endif
#ifndef USE_TYPES_H
#define USE_TYPES_H 0
#endif
#if USE_TYPES_H
#include <sys/types.h>
#endif
/* Make sure we have sig_atomic_t. */
#if ! HAVE_SIG_ATOMIC_T_IN_SIGNAL_H && ! HAVE_SIG_ATOMIC_T_IN_TYPES_H
#ifndef SIG_ATOMIC_T
/* There is no portable definition for sig_atomic_t. */
#define SIG_ATOMIC_T char
#endif /* ! defined (SIG_ATOMIC_T) */
typedef SIG_ATOMIC_T sig_atomic_t;
#endif /* ! HAVE_SIG_ATOMIC_T_IN_SIGNAL_H && ! HAVE_SIG_ATOMIC_T_IN_TYPES_H */
/* Make sure we have size_t. We use int as the default because the
main use of this type is to provide an argument to malloc and
realloc. On a system which does not define size_t, int is
certainly the correct type to use. */
#if ! HAVE_SIZE_T_IN_STDDEF_H && ! HAVE_SIZE_T_IN_TYPES_H
#ifndef SIZE_T
#define SIZE_T unsigned
#endif /* ! defined (SIZE_T) */
typedef SIZE_T size_t;
#endif /* ! HAVE_SIZE_T_IN_STDDEF_H && ! HAVE_SIZE_T_IN_TYPES_H */
/* Make sure we have time_t. We use long as the default. We don't
bother to let conf.h override this, since on a system which doesn't
define time_t long must be correct. */
#if ! HAVE_TIME_T_IN_TIME_H && ! HAVE_TIME_T_IN_TYPES_H
typedef long time_t;
#endif
/* Set up some definitions for both ANSI C and Classic C.
P() -- for function prototypes (e.g. extern int foo P((int)) ).
pointer -- for a generic pointer (i.e. void *).
constpointer -- for a generic pointer to constant data.
BUCHAR -- to convert a character to unsigned. */
#if ANSI_C
#if ! HAVE_VOID || ! HAVE_UNSIGNED_CHAR
#error ANSI C compiler without void or unsigned char
#endif
#define P(x) x
typedef void *pointer;
typedef const void *constpointer;
#define BUCHAR(b) ((unsigned char) (b))
#else /* ! ANSI_C */
/* Handle uses of const, volatile and void in Classic C. */
#define const
#define volatile
#if ! HAVE_VOID
#define void int
#endif
#define P(x) ()
typedef char *pointer;
typedef const char *constpointer;
#if HAVE_UNSIGNED_CHAR
#define BUCHAR(b) ((unsigned char) (b))
#else /* ! HAVE_UNSIGNED_CHAR */
/* This should work on most systems, but not necessarily all. */
#define BUCHAR(b) ((b) & 0xff)
#endif /* ! HAVE_UNSIGNED_CHAR */
#endif /* ! ANSI_C */
/* Make sure we have a definition for offsetof. */
#ifndef offsetof
#define offsetof(type, field) \
((size_t) ((char *) &(((type *) 0)->field) - (char *) (type *) 0))
#endif
/* Only use inline with gcc. */
#ifndef __GNUC__
#define __inline__
#endif
/* Get the string functions, which are used throughout the code. */
#if HAVE_MEMORY_H
#include <memory.h>
#else
/* We really need a definition for memchr, and this should not
conflict with anything in <string.h>. I hope. */
extern pointer memchr ();
#endif
#if HAVE_STRING_H
#include <string.h>
#else /* ! HAVE_STRING_H */
#if HAVE_STRINGS_H
#include <strings.h>
#else /* ! HAVE_STRINGS_H */
extern char *strcpy (), *strncpy (), *strchr (), *strrchr (), *strtok ();
extern char *strcat (), *strerror (), *strstr ();
extern size_t strlen (), strspn (), strcspn ();
#if ! HAVE_MEMORY_H
extern pointer memcpy (), memchr ();
#endif /* ! HAVE_MEMORY_H */
#endif /* ! HAVE_STRINGS_H */
#endif /* ! HAVE_STRING_H */
/* Get what we need from <stdlib.h>. */
#if HAVE_STDLIB_H
#include <stdlib.h>
#else /* ! HAVE_STDLIB_H */
extern pointer malloc (), realloc (), bsearch ();
extern long strtol ();
extern char *getenv ();
#endif /* ! HAVE_STDLIB_H */
/* NeXT uses <libc.h> to declare a bunch of functions. */
#if HAVE_LIBC_H
#include <libc.h>
#endif
/* Make sure we have the EXIT_ macros. */
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS (0)
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE (1)
#endif
/* If we need to declare errno, do so. I don't want to always do
this, because some system might theoretically have a different
declaration for errno. On a POSIX system this is sure to work. */
#if ! HAVE_ERRNO_DECLARATION
extern int errno;
#endif
/* If the system has the socket call, guess that we can compile the
TCP code. */
#define HAVE_TCP HAVE_SOCKET
/* If the system has the t_open call, guess that we can compile the
TLI code. */
#define HAVE_TLI HAVE_T_OPEN
/* The boolean type holds boolean values. */
typedef int boolean;
#undef TRUE
#undef FALSE
#define TRUE (1)
#define FALSE (0)
/* The openfile_t type holds an open file. This depends on whether we
are using stdio or not. */
#if USE_STDIO
typedef FILE *openfile_t;
#define EFILECLOSED ((FILE *) NULL)
#define ffileisopen(e) ((e) != NULL)
#define ffileeof(e) feof (e)
#define cfileread(e, z, c) fread ((z), 1, (c), (e))
#define ffilereaderror(e, c) ferror (e)
#define cfilewrite(e, z, c) fwrite ((z), 1, (c), (e))
#ifdef SEEK_SET
#define ffileseek(e, i) (fseek ((e), (long) (i), SEEK_SET) == 0)
#define ffilerewind(e) (fseek ((e), (long) 0, SEEK_SET) == 0)
#else
#define ffileseek(e, i) (fseek ((e), (long) (i), 0) == 0)
#define ffilerewind(e) (fseek ((e), (long) 0, 0) == 0)
#endif
#define ffileclose(e) (fclose (e) == 0)
#else /* ! USE_STDIO */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
typedef int openfile_t;
#define EFILECLOSED (-1)
#define ffileisopen(e) ((e) >= 0)
#define ffileeof(e) (FALSE)
#define cfileread(e, z, c) read ((e), (z), (c))
#define ffilereaderror(e, c) ((c) < 0)
#define cfilewrite(e, z, c) write ((e), (z), (c))
#ifdef SEEK_SET
#define ffileseek(e, i) (lseek ((e), (long) i, SEEK_SET) >= 0)
#define ffilerewind(e) (lseek ((e), (long) 0, SEEK_SET) >= 0)
#else
#define ffileseek(e, i) (lseek ((e), (long) i, 0) >= 0)
#define ffilerewind(e) (lseek ((e), (long) 0, 0) >= 0)
#endif
#define ffileclose(e) (close (e) >= 0)
#endif /* ! USE_STDIO */
/* A prototype for main to avoid warnings from gcc 2.0
-Wmissing-prototype option. */
extern int main P((int argc, char **argv));
/* Some standard routines which we only define if they are not present
on the system we are compiling on. */
#if ! HAVE_GETLINE
/* Read a line from a file. */
extern int getline P((char **pz, size_t *pc, FILE *e));
#endif
#if ! HAVE_REMOVE
/* Erase a file. */
#undef remove
extern int remove P((const char *zfile));
#endif
#if ! HAVE_STRDUP
/* Copy a string into memory. */
extern char *strdup P((const char *z));
#endif
#if ! HAVE_STRSTR
/* Look for one string within another. */
extern char *strstr P((const char *zouter, const char *zinner));
#endif
#if ! HAVE_STRCASECMP
#if HAVE_STRICMP
#define strcasecmp stricmp
#else /* ! HAVE_STRICMP */
/* Rename strcasecmp to avoid ANSI C name space. */
#define strcasecmp xstrcasecmp
extern int strcasecmp P((const char *z1, const char *z2));
#endif /* ! HAVE_STRICMP */
#endif /* ! HAVE_STRCASECMP */
#if ! HAVE_STRNCASECMP
#if HAVE_STRNICMP
#define strncasecmp strnicmp
#else /* ! HAVE_STRNICMP */
/* Rename strncasecmp to avoid ANSI C name space. */
#define strncasecmp xstrncasecmp
extern int strncasecmp P((const char *z1, const char *z2, size_t clen));
#endif /* ! HAVE_STRNICMP */
#endif /* ! HAVE_STRNCASECMP */
#if ! HAVE_STRERROR
/* Get a string corresponding to an error message. */
#undef strerror
extern char *strerror P((int ierr));
#endif
/* Get the appropriate definitions for memcmp, memcpy, memchr and
bzero. */
#if ! HAVE_MEMCMP
#if HAVE_BCMP
#define memcmp(p1, p2, c) bcmp ((p1), (p2), (c))
#else /* ! HAVE_BCMP */
extern int memcmp P((constpointer p1, constpointer p2, size_t c));
#endif /* ! HAVE_BCMP */
#endif /* ! HAVE_MEMCMP */
#if ! HAVE_MEMCPY
#if HAVE_BCOPY
#define memcpy(pto, pfrom, c) bcopy ((pfrom), (pto), (c))
#else /* ! HAVE_BCOPY */
extern pointer memcpy P((pointer pto, constpointer pfrom, size_t c));
#endif /* ! HAVE_BCOPY */
#endif /* ! HAVE_MEMCPY */
#if ! HAVE_MEMCHR
extern pointer memchr P((constpointer p, int b, size_t c));
#endif
#if ! HAVE_BZERO
#if HAVE_MEMSET
#define bzero(p, c) memset ((p), 0, (c))
#else /* ! HAVE_MEMSET */
extern void bzero P((pointer p, int c));
#endif /* ! HAVE_MEMSET */
#endif /* ! HAVE_BZERO */
/* Look up a character in a string. */
#if ! HAVE_STRCHR
#if HAVE_INDEX
#define strchr index
extern char *index ();
#else /* ! HAVE_INDEX */
extern char *strchr P((const char *z, int b));
#endif /* ! HAVE_INDEX */
#endif /* ! HAVE_STRCHR */
#if ! HAVE_STRRCHR
#if HAVE_RINDEX
#define strrchr rindex
extern char *rindex ();
#else /* ! HAVE_RINDEX */
extern char *strrchr P((const char *z, int b));
#endif /* ! HAVE_RINDEX */
#endif /* ! HAVE_STRRCHR */
/* Turn a string into a long integer. */
#if ! HAVE_STRTOL
extern long strtol P((const char *, char **, int));
#endif
/* Lookup a key in a sorted array. */
#if ! HAVE_BSEARCH
extern pointer bsearch P((constpointer pkey, constpointer parray,
size_t celes, size_t cbytes,
int (*pficmp) P((constpointer, constpointer))));
#endif

View File

@ -0,0 +1,445 @@
/* uudefs.h
Miscellaneous definitions for the UUCP package.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#if ANSI_C
/* These structures are used in prototypes but are not defined in this
header file. */
struct uuconf_system;
struct uuconf_timespan;
#endif
/* The tlog enumeration holds the different types of logging. */
enum tlog
{
/* Normal log entry. */
LOG_NORMAL,
/* Error log entry. */
LOG_ERROR,
/* Fatal log entry. */
LOG_FATAL
#if DEBUG > 1
,
/* Debugging log entry. */
LOG_DEBUG,
/* Start debugging log entry. */
LOG_DEBUG_START,
/* Continue debugging log entry. */
LOG_DEBUG_CONTINUE,
/* End debugging log entry. */
LOG_DEBUG_END
#endif
};
/* The tstatus_type enumeration holds the kinds of status information
we put in the status file. The order of entries here corresponds
to the order of entries in the azStatus array. */
enum tstatus_type
{
/* Conversation complete. */
STATUS_COMPLETE,
/* Port unavailable. */
STATUS_PORT_FAILED,
/* Dial failed. */
STATUS_DIAL_FAILED,
/* Login failed. */
STATUS_LOGIN_FAILED,
/* Handshake failed. */
STATUS_HANDSHAKE_FAILED,
/* Failed after logging in. */
STATUS_FAILED,
/* Talking to remote system. */
STATUS_TALKING,
/* Wrong time to call. */
STATUS_WRONG_TIME,
/* Number of status values. */
STATUS_VALUES
};
/* An array to convert status entries to strings. If more status entries
are added, this array must be extended. */
extern const char *azStatus[];
/* The sstatus structure holds the contents of a system status file. */
struct sstatus
{
/* Current status of conversation. */
enum tstatus_type ttype;
/* Number of failed retries. */
int cretries;
/* Time of last call in seconds since epoch (determined by
ixsysdep_time). */
long ilast;
/* Number of seconds until a retry is permitted. */
int cwait;
};
/* How long we have to wait for the next call, given the number of retries
we have already made. This should probably be configurable. */
#define CRETRY_WAIT(c) ((c) * 10 * 60)
/* The scmd structure holds a complete UUCP command. */
struct scmd
{
/* Command ('S' for send, 'R' for receive, 'X' for execute, 'E' for
simple execution, 'H' for hangup, 'Y' for hangup confirm, 'N' for
hangup deny). */
char bcmd;
/* At least one compiler needs an explicit padding byte here. */
char bdummy;
/* Sequence handle for fsysdep_did_work. */
pointer pseq;
/* File name to transfer from. */
const char *zfrom;
/* File name to transfer to. */
const char *zto;
/* User who requested transfer. */
const char *zuser;
/* Options. */
const char *zoptions;
/* Temporary file name ('S' and 'E'). */
const char *ztemp;
/* Mode to give newly created file ('S' and 'E'). */
unsigned int imode;
/* User to notify on remote system (optional; 'S' and 'E'). */
const char *znotify;
/* File size (-1 if not supplied) ('S', 'E' and 'R'). */
long cbytes;
/* Command to execute ('E'). */
const char *zcmd;
/* Position to restart from ('R'). */
long ipos;
};
#if DEBUG > 1
/* We allow independent control over several different types of
debugging output, using a bit string with individual bits dedicated
to particular debugging types. */
/* The bit string is stored in iDebug. */
extern int iDebug;
/* Debug abnormal events. */
#define DEBUG_ABNORMAL (01)
/* Debug chat scripts. */
#define DEBUG_CHAT (02)
/* Debug initial handshake. */
#define DEBUG_HANDSHAKE (04)
/* Debug UUCP protocol. */
#define DEBUG_UUCP_PROTO (010)
/* Debug protocols. */
#define DEBUG_PROTO (020)
/* Debug port actions. */
#define DEBUG_PORT (040)
/* Debug configuration files. */
#define DEBUG_CONFIG (0100)
/* Debug spool directory actions. */
#define DEBUG_SPOOLDIR (0200)
/* Debug executions. */
#define DEBUG_EXECUTE (0400)
/* Debug incoming data. */
#define DEBUG_INCOMING (01000)
/* Debug outgoing data. */
#define DEBUG_OUTGOING (02000)
/* Maximum possible value for iDebug. */
#define DEBUG_MAX (03777)
/* Intializer for array of debug names. The index of the name in the
array is the corresponding bit position in iDebug. We only check
for prefixes, so these names only need to be long enough to
distinguish each name from every other. The last entry must be
NULL. The string "all" is also recognized to turn on all
debugging. */
#define DEBUG_NAMES \
{ "a", "ch", "h", "u", "pr", "po", "co", "s", "e", "i", "o", NULL }
/* The prefix to use to turn off all debugging. */
#define DEBUG_NONE "n"
/* Check whether a particular type of debugging is being done. */
#define FDEBUGGING(i) ((iDebug & (i)) != 0)
/* These macros are used to output debugging information. I use
several different macros depending on the number of arguments
because no macro can take a variable number of arguments and I
don't want to use double parentheses. */
#define DEBUG_MESSAGE0(i, z) \
do { if (FDEBUGGING (i)) ulog (LOG_DEBUG, (z)); } while (0)
#define DEBUG_MESSAGE1(i, z, a1) \
do { if (FDEBUGGING (i)) ulog (LOG_DEBUG, (z), (a1)); } while (0)
#define DEBUG_MESSAGE2(i, z, a1, a2) \
do { if (FDEBUGGING (i)) ulog (LOG_DEBUG, (z), (a1), (a2)); } while (0)
#define DEBUG_MESSAGE3(i, z, a1, a2, a3) \
do \
{ \
if (FDEBUGGING (i)) \
ulog (LOG_DEBUG, (z), (a1), (a2), (a3)); \
} \
while (0)
#define DEBUG_MESSAGE4(i, z, a1, a2, a3, a4) \
do \
{ \
if (FDEBUGGING (i)) \
ulog (LOG_DEBUG, (z), (a1), (a2), (a3), (a4)); \
} \
while (0)
#else /* DEBUG <= 1 */
/* If debugging information is not being compiled, provide versions of
the debugging macros which just disappear. */
#define DEBUG_MESSAGE0(i, z)
#define DEBUG_MESSAGE1(i, z, a1)
#define DEBUG_MESSAGE2(i, z, a1, a2)
#define DEBUG_MESSAGE3(i, z, a1, a2, a3)
#define DEBUG_MESSAGE4(i, z, a1, a2, a3, a4)
#endif /* DEBUG <= 1 */
/* Functions. */
/* Given an unknown system name, return information for an unknown
system. If unknown systems are not permitted, this returns FALSE.
Otherwise, it translates the name as necessary for the spool
directory, and fills in *qsys. */
extern boolean funknown_system P((pointer puuconf, const char *zsystem,
struct uuconf_system *qsys));
/* See whether a file belongs in the spool directory. */
extern boolean fspool_file P((const char *zfile));
/* See if the current time matches a time span. If not, return FALSE.
Otherwise, return TRUE and set *pival and *pcretry to the values
from the matching element of the span. */
extern boolean ftimespan_match P((const struct uuconf_timespan *qspan,
long *pival, int *pcretry));
/* Determine the maximum size that may ever be transferred, given a
timesize span. If there are any time gaps larger than 1 hour not
described by the timesize span, this returns -1. Otherwise it
returns the largest size that may be transferred at some time. */
extern long cmax_size_ever P((const struct uuconf_timespan *qtimesize));
/* Send mail about a file transfer. */
extern boolean fmail_transfer P((boolean fok, const char *zuser,
const char *zmail, const char *zwhy,
const char *zfrom, const char *zfromsys,
const char *zto, const char *ztosys,
const char *zsaved));
/* See whether a file is in one of a list of directories. The zpubdir
argument is used to pass the directory names to zsysdep_local_file.
If fcheck is FALSE, this does not check accessibility. Otherwise,
if freadable is TRUE, the user zuser must have read access to the
file and all appropriate directories; if freadable is FALSE zuser
must have write access to the appropriate directories. The zuser
argument may be NULL, in which case all users must have the
appropriate access (this is used for a remote request). */
extern boolean fin_directory_list P((const char *zfile,
char **pzdirs,
const char *zpubdir,
boolean fcheck,
boolean freadable,
const char *zuser));
/* Parse a command string. */
extern boolean fparse_cmd P((char *zcmd, struct scmd *qcmd));
/* Make a log entry. */
#ifdef __GNUC__
#define GNUC_VERSION __GNUC__
#else
#define GNUC_VERSION 0
#endif
#if ANSI_C && HAVE_VFPRINTF
extern void ulog P((enum tlog ttype, const char *zfmt, ...))
#if GNUC_VERSION > 1
__attribute__ ((format (printf, 2, 3)))
#endif
;
#else
extern void ulog ();
#endif
#undef GNUC_VERSION
/* Report an error returned by one of the uuconf routines. */
extern void ulog_uuconf P((enum tlog ttype, pointer puuconf,
int iuuconf));
/* Set the function to call if a fatal error occurs. */
extern void ulog_fatal_fn P((void (*pfn) P((void))));
/* If ffile is TRUE, send log entries to the log file rather than to
stderr. */
extern void ulog_to_file P((pointer puuconf, boolean ffile));
/* Set the ID number used by the logging functions. */
extern void ulog_id P((int iid));
/* Set the system name used by the logging functions. */
extern void ulog_system P((const char *zsystem));
/* Set the system and user name used by the logging functions. */
extern void ulog_user P((const char *zuser));
/* Set the device name used by the logging functions. */
extern void ulog_device P((const char *zdevice));
/* Close the log file. */
extern void ulog_close P((void));
/* Make an entry in the statistics file. */
extern void ustats P((boolean fsucceeded, const char *zuser,
const char *zsystem, boolean fsent,
long cbytes, long csecs, long cmicros,
boolean fmaster));
/* Close the statistics file. */
extern void ustats_close P((void));
#if DEBUG > 1
/* A debugging routine to output a buffer. This outputs zhdr, the
buffer length clen, and the contents of the buffer in quotation
marks. */
extern void udebug_buffer P((const char *zhdr, const char *zbuf,
size_t clen));
/* A debugging routine to make a readable version of a character.
This takes a buffer at least 5 bytes long, and returns the length
of the string it put into it (not counting the null byte). */
extern size_t cdebug_char P((char *z, int ichar));
/* Parse a debugging option string. This can either be a number or a
comma separated list of debugging names. This returns a value for
iDebug. */
extern int idebug_parse P((const char *));
#endif /* DEBUG <= 1 */
/* Copy one file to another. */
extern boolean fcopy_file P((const char *zfrom, const char *zto,
boolean fpublic, boolean fmkdirs));
/* Copy an open file to another. */
extern boolean fcopy_open_file P((openfile_t efrom, const char *zto,
boolean fpublic, boolean fmkdirs));
/* Translate escape sequences in a buffer, leaving the result in the
same buffer and returning the length. */
extern size_t cescape P((char *zbuf));
/* Get a buffer to hold a string of a given size. The buffer should
be freed with ubuffree. */
extern char *zbufalc P((size_t csize));
/* Call zbufalc to allocate a buffer and copy a string into it. */
extern char *zbufcpy P((const char *z));
/* Free up a buffer returned by zbufalc or zbufcpy. */
extern void ubuffree P((char *z));
/* Allocate memory without fail. */
extern pointer xmalloc P((size_t));
/* Realloc memory without fail. */
extern pointer xrealloc P((pointer, size_t));
/* Free memory (accepts NULL pointers, which some libraries erroneously
do not). */
extern void xfree P((pointer));
/* Global variables. */
/* The name of the program being run. This is statically initialized,
although it should perhaps be set from argv[0]. */
extern char abProgram[];
/* When a signal occurs, the signal handlers sets the appropriate
element of the arrays afSignal and afLog_signal to TRUE. The
afSignal array is used to check whether a signal occurred. The
afLog_signal array tells ulog to log the signal; ulog will clear
the element after logging it, which means that if a signal comes in
at just the right moment it will not be logged. It will always be
recorded in afSignal, though. At the moment we handle 5 signals:
SIGHUP, SIGINT, SIGQUIT, SIGTERM and SIGPIPE (the Unix code also
handles SIGALRM). If we want to handle more, the afSignal array
must be extended; I see little point to handling any of the other
ANSI C or POSIX signals, as they are either unlikely to occur
(SIGABRT, SIGUSR1) or nearly impossible to handle cleanly (SIGILL,
SIGSEGV). SIGHUP is only logged if fLog_sighup is TRUE. */
#define INDEXSIG_SIGHUP (0)
#define INDEXSIG_SIGINT (1)
#define INDEXSIG_SIGQUIT (2)
#define INDEXSIG_SIGTERM (3)
#define INDEXSIG_SIGPIPE (4)
#define INDEXSIG_COUNT (5)
extern volatile sig_atomic_t afSignal[INDEXSIG_COUNT];
extern volatile sig_atomic_t afLog_signal[INDEXSIG_COUNT];
extern boolean fLog_sighup;
/* The names of the signals to use in error messages, as an
initializer for an array. */
#define INDEXSIG_NAMES \
{ "hangup", "interrupt", "quit", "termination", "SIGPIPE" }
/* Check to see whether we've received a signal. It would be nice if
we could use a single variable for this, but we sometimes want to
clear our knowledge of a signal and that would cause race
conditions (clearing a single element of the array is not a race
assuming that we don't care about a particular signal, even if it
occurs after we've examined the array). */
#define FGOT_SIGNAL() \
(afSignal[INDEXSIG_SIGHUP] || afSignal[INDEXSIG_SIGINT] \
|| afSignal[INDEXSIG_SIGQUIT] || afSignal[INDEXSIG_SIGTERM] \
|| afSignal[INDEXSIG_SIGPIPE])
/* If we get a SIGINT in uucico, we continue the current communication
session but don't start any new ones. This macros checks for any
signal other than SIGINT, which means we should get out
immediately. */
#define FGOT_QUIT_SIGNAL() \
(afSignal[INDEXSIG_SIGHUP] || afSignal[INDEXSIG_SIGQUIT] \
|| afSignal[INDEXSIG_SIGTERM] || afSignal[INDEXSIG_SIGPIPE])
/* File being sent. */
extern openfile_t eSendfile;
/* File being received. */
extern openfile_t eRecfile;
/* Device name to log. This is set by fconn_open. It may be NULL. */
extern char *zLdevice;
/* If not NULL, ulog calls this function before outputting anything.
This is used to support cu. */
extern void (*pfLstart) P((void));
/* If not NULL, ulog calls this function after outputting everything.
This is used to support cu. */
extern void (*pfLend) P((void));

View File

@ -0,0 +1,108 @@
#!xchat
# @(#) dial.hayes V1.1 Tue Sep 1 13:59:58 1992 (Bob Denny)
#
# xchat script for dialing a vanilla Hayes modem
#
# Usage:
# xchat dial.hayes telno
#
# where telno is the telephone number, subject to pause and wait
# character modification.
#
# Uncomment the first two lines after "start:" to get debugging
# in file "Dial.Log"
#
# Flush input, zero counter, set telephone number if supplied,
# else fail if no telephone number given.
#
start:
### dbgfile Dial.Log
### dbgset 15
zero
flush
ifnstr notelno 0
telno 0
goto initmodem
#
# Missing telephone number.
#
notelno:
logerr No telephone number given
failed
#
# Reset the modem to nonvolatile profile.
# Allow 3 sec. for response, as some modems are slow to reset.
#
initmodem:
count
ifgtr cantinit 4
send ATZ\r
timeout initmodem 3000
expect setupmodem OK
#
# No response from modem
#
cantinit:
logerr Can't wake modem
failed
#
# Send the stuff needed to initialize the modem to the modes
# needed for the particular modem flavor. The string below
# is provided as a vanilla example. Allow 2 sec. for the
# modem to respond to this command.
#
setupmodem:
sleep 1000
send ATM0S7=90S11=120\r
timeout setupfail 2000
expect setupfail ERROR
expect dialnumber OK
#
# Modem barfed or died on setup command.
#
setupfail:
logerr Error in modem setup string
failed
#
# Dial the supplied number. Handle the various errors that
# can come back from the modem by logging the error.
#
dialnumber:
sleep 1000
send ATDT
dial
send \r
flush
timeout timeout 90000
expect connected CONNECT
expect busy BUSY
expect nocarrier NO CARRIER
expect noanswer NO ANSWER
expect nodialtone NO DIALTONE
#
# Success!
#
connected:
success
#
# Handle modem dial failures
#
timeout:
logerr Modem or carrier timeout.
failed
busy:
logerr BUSY
failed
nocarrier:
logerr NO CARRIER
failed
noanswer:
logerr NO ANSWER
failed
nodialtone:
logerr NO DIALTONE
failed
#
# end
#

View File

@ -0,0 +1,57 @@
#!xchat
# @(#) Hangup.Hayes V1.1 Tue Sep 1 14:04:25 1992 (Bob Denny)
#
# xchat script for hanging up a Hayes-type modem. When used with Taylor
# UUCP, this script should be run as the dialer-complete and dialer-abort
# script with xchat.
#
# Usage:
# xchat Hangup.Hayes [ x ]
#
# where 'x' is any string. If it is present, this script will log the
# modem reset as an ABORT reset, otherwise it will not log anything.
#
# Uncomment the lines starting with '###' to get debugging log.
#
start:
### dbgfile Hangup.Log
### dbgset 15
zero
sleep 2000 # Wait for trailing garbage
flush # Toss it out
ifnstr wakemodem 0 # No abort indicator
log Hangup on abort
#
# Get modem's attention via Hayes 'escape' protocol.
#
wakemodem:
sleep 4000
send +++
sleep 4000
send \r
timeout reset 2000
expect reset OK
#
# We're (probably) in command mode. Use ATZ (reset) to hang up
# as some modems don't behave well with ATH0 command.
#
reset:
send ATZ\r
timeout silent 5000
expect done OK
#
# Finished, modem is back in initial state.
#
done:
success
#
# No response to escape protocol. Log the error and force DTR low
# in an attempt to get control of the modem. Then send ATZ just to
# make sure.
#
silent:
logerr Hangup: no response from modem
hangup # Force DTR low as last gasp
send ATZ\r
sleep 5000
failed

View File

@ -0,0 +1,137 @@
#!xchat
# @(#) login.LAT V1.2 Tue Sep 1 13:25:28 1992
#
# xchat script for logging into a VMS system through a LAT
# terminal server port. If no VMS password parameter supplied,
# skips password phase of VMS login. If LAT-password supplied,
# will log into LAT server using that password. NOTE: does not
# handle the situation where a LAT password is needed but no
# VMS password is needed.
#
# Usage:
# xchat login.LAT sysname username [ password [ LAT-password ] ]
#
# History:
# rbd Fri Aug 14 13:37:06 1992
# Changes for Lantronix ETS-16. It says "type help at the Local>
# prompt..." then it gives the prompt for real! Prompt may need
# to be something other than "Local>". We match the real Local>
# prompt by matching the leading newline!
#
# rbd Tue Sep 1 13:04:32 1992
# Remove absolute path name from log file. Now defaults per config.
#
start:
dbgfile Login.Log
dbgset 15
sleep 2000 # Wait 2 seconds
flush # Flush typeahead
ifnstr svrstart 3 # Skip server password if not given
#
# Starting point if server password supplied. Handle situation
# where the server line may have been left waiting for username
# or at local> prompt.
#
getsvrpwp:
zero
l0:
count # Get server's password prompt
ifgtr deadmux 5 # die if 5 cr's don't do it
send \r
timeout l0 1000 # Wait and try again
expect dosvrpw ssword>
expect svrlogin ername>
expect connect \nLocal>
#
# Send server's password. Fail if don't get Username
# or Local> prompt.
#
dosvrpw:
zero
l2:
sendstr 3
send \r
timeout badsvrpw 5000 # Die if invalid
expect svrlogin ername>
expect connect \nLocal>
#
# Starting point if NO server password supplied. Handle situation
# where the server line may have been left at local> prompt.
#
svrstart:
zero
l1:
count # Get username> or local> prompt
ifgtr deadmux 5 # Die if 5 cr's don't do it
send \r
timeout l1 1000 # Wait and try again
expect svrlogin ername>
expect connect \nLocal>
#
# Server asked for a username. Just give 'uucp'.
#
svrlogin:
send uucp\r
timeout deadmux 2000
expect connect \nLocal>
#
# At this point, we have the Local> prompt. Send the connect
# command for the specified LAT host service name, and wait for
# VMS "Username:" prompt. Die after 10 seconds.
#
connect:
send c\s
sendstr 0
send \r
timeout nologin 10000
expect gotlogin ername:
#
# Got VMS "Username:" prompt. Send the username. If a password
# was given, wait for the "Password:" prompt. Die after 10 seconds.
# if no password was given, we're done!
#
gotlogin:
sendstr 1
send \r
ifnstr done 2
timeout nopasswd 10000
expect gotpasswd ssword:
#
# Got VMS "Password:" prompt. Send the password and we're done!
#
gotpasswd:
sendstr 2
send \r
#
# Success!
#
done:
success
#
# ERROR HANDLERS
#
#
# LAT server appears dead. Fail.
#
deadmux:
logerr No response from LAT server
failed
#
# The server password was bad. Fail.
#
badsvrpw:
logerr Invalid LAT server password
failed
#
# VMS system appears to be dead. Fail.
#
nologin:
logerr No VMS Username: prompt
failed
#
# Failed to get "Password:" prompt. Fail.
#
nopasswd:
logerr No VMS Password: prompt. Invalid password?
failed

View File

@ -0,0 +1,133 @@
#!xchat
# @(#) Login.PortSelUnix V1.0 Tue Sep 1 14:57:05 1992 (Bob Denny)
#
# NOTE: Untested with xchat V1.1. Taken from DECUS UUCP.
#
# From: "Kent C. Brodie" <moocow!brodie@CSD4.MILW.WISC.EDU>
# uucp: {uunet!marque,csd4.milw.wisc.edu}!moocow!brodie
# special script for "uwmcsd4", have to go through a port selector (and then
# log in via standard Unix procedures).
#
# Also included is the ability to wait in the port selector queue.
# Be forwarned that the debug log can get pretty big depending on
# how many times you "wait" in the queue.
# (C) 1989 Kent C. Brodie - Medical College of Wisconsin
# P0 is systemname , P1 is username, P2 is password.
zero
# send a CR to get the selector's attention. Sleep a little bit
# due to large login text of selector. It sends "Which System?"
# when it's ready.
getprtslct:
count
ifgtr noprtslct 6
break
send \r
sleep 2000
flush
expect prtslctok ystem?
timeout getprtslct 15000
noprtslct:
logerr Sent cr, no "Which System?" from port selector
failed
# Send the system name. We either get "OK" (connected), or we
# get "No ports available, would you like to wait?" (wait in queue)
prtslctok:
zero
sendstr 0
send \r
expect connected OK
expect prtslctwait wait?
timeout noconnect 10000
# Usually we get "nn Your place in queue" messages. JUST in case we
# get a free port right away, check for 'Are you ready?' as well.
prtslctwait:
zero
send Y\r
expect prtslctque queue
expect prtslctrdy ready?
timeout prtwaitbad 70000
prtwaitbad:
logerr Sent "Y" to wait in queue, did not get valid response.
failed
# Here's where we wait in the queue. The port selector sends us a status
# message about once a minute. We either get "nn Your place in queue"
# or we get "System Available. Are you Ready?".
# If something goes wrong, we time out waiting for either response.
# The reason we don't sleep for 40-50 seconds is because as SOON as the
# port is ready, it informs us. If we wait too long, it drops us.
# This setup is laid out for a maximum of 20 "tries" which is ABOUT
# 20 minutes. Note: This constant retrying can make log files
# kind of big....
prtslctque:
count
ifgtr prtslcttry 20
expect prtslctque queue
expect prtslctrdy ready?
timeout noportwait 70000
prtslcttry:
logerr Too many (20) wait/retries -- queue too busy.
failed
prtslctrdy:
send Y\r
expect connected OK
timeout noconnect 20000
noportwait:
logerr Timed out awaiting place in port queue
failed
noconnect:
logerr Sent system name, no "OK" from selector
failed
# standard Unix login stuff. Send cr, expect "ogin:", if no, send a break
# (which tells Unix to try the next bit rate) and try again.
connected:
send \r
zero
goto waitlogin
sendbreak:
count
ifgtr nolgi 6
flush
break
waitlogin:
expect gotlogin ogin:
timeout sendbreak 5000
nolgi:
logerr No login: prompt
failed
gotlogin:
sendstr 1
send \r
expect gotword word:
timeout nopwd 10000
nopwd:
logerr No password: prompt
failed
gotword:
sendstr 2
send \r
success

View File

@ -0,0 +1,96 @@
#!xchat
# @(#) Login.VMS V1.1 Tue Sep 1 13:24:54 1992 (Bob Denny)
#
#
# xchat script for logging into a VMS system. If no VMS password
# parameter supplied, skips password phase of VMS login. If syspass
# parameter given, will go through steps needed to log into a VMS
# system where a "system password" was set on the port.
#
# Cannot handle situation where system password is required but
# no password needed.
#
#
# Usage:
# xchat Login.VMS username [ password [ syspass ] ]
#
# Uncomment the lines starting with "###" to get debug logging.
#
start:
### dbgfile Login.Log
### dbgset 15
sleep 2000 # Wait 2 seconds
zero
flush # Flush typeahead
ifnstr login 2 # Skip sys passwd if not given
#
# Need system password. Send <CR> to get bell.
# Try 5 times at 2 sec. intervals. Skip to do
# username if we see "Username:".
#
syspass:
count
ifgtr nobell 5 # Fail after 5 tries
send \r
timeout syspass 2000 # Wait 2 sec. and try again
expect gotbell \007
expect gotlogin Username:
#
# Got the bell. Send the system password. Repeat 5 times
# at 2 sec. intervals. Fail if we don't get Username:
#
gotbell:
zero
sleep 2000
l1:
count
ifgtr nologin 5 # Fail after 5 tries
sendstr 2
send \r
timeout l1 2000 # Wait 2 sec. and try again
expect gotlogin Username:
#
# Start here if no system password supplied.
# Send <CR> until we get Username: Try 5 times at 2 sec. intervals.
#
login:
count
ifgtr nologin 5 # Fail after 5 tries
send \r
timeout login 2000 # Wait 2 sec. and try again
expect gotlogin Username:
#
# Got VMS "Username:" prompt. Send the username. If a password
# was given, wait for the "Password:" prompt. Die after 10 seconds.
# if no password was given, we're done!
#
gotlogin:
sendstr 0
send \r
ifnstr done 1
timeout nopasswd 10000
expect gotpasswd Password:
#
# Got VMS "Password:" prompt. Send the password and we're done!
#
gotpasswd:
sendstr 1
send \r
#
# Success!
#
done:
success
#
# ERROR HANDLERS
#
nobell:
logerr No VMS system password prompt (bell)
failed
nologin:
logerr No VMS Username: prompt
failed
nopasswd:
logerr No VMS Password: prompt.
failed

View File

@ -0,0 +1,30 @@
#
# Makefile for uurate 1.0
#
# Where uurate is installed
BIN=/usr/local/bin
# Flags to use when compiling uurate
CFLAGS=-I..
CC=cc
SHELL=/bin/sh
PROGS=uurate
#-----------
all: $(PROGS)
install: $(PROGS)
@for i in $(PROGS) ; do \
echo "Install $$i into $(BIN)..." ; \
cp $$i $(BIN) ; \
echo "Set ownership and protection..." ; \
/bin/chmod 0555 $(BIN)/$$i ; \
/bin/chown bin $(BIN)/$$i ; \
/bin/chgrp bin $(BIN)/$$i ; \
done
clean:
rm -f $(PROGS) core

View File

@ -0,0 +1,31 @@
#
# Makefile for xchat 1.1
#
# Bob Denny - Tue Sep 1 15:58:22 1992
#
CC=cc
SHELL=/bin/sh
BIN=/usr/local/lib/uucp
PROGS=xchat
#-----------
all: $(PROGS)
install: $(PROGS)
@for i in $(PROGS) ; do \
echo "Install $$i into $(BIN)..." ; \
cp $$i $(BIN) ; \
echo "Set ownership and protection..." ; \
/bin/chmod 0555 $(BIN)/$$i ; \
/bin/chown bin $(BIN)/$$i ; \
/bin/chgrp bin $(BIN)/$$i ; \
done
clean:
rm -f $(PROGS) core

View File

@ -0,0 +1,46 @@
This is the README file for the Taylor UUCP contrib directory.
This directory contains contributed shell scripts and programs that
you may find useful.
xchat.c, xchat.man, README-XCHAT, xc-conf.h-dist, Makefile.xchat:
A program by Bob Denny that may be invoked by the ``chat-program''
command for any of the various types of chat scripts. It is
driven by scripts which are written in its own little language.
It is a powerful program that can add a lot of flexibility to your
chat scripts.
Dial.Hayes, Hangup.Hayes, Login.LAT, Login.PortSel, Login.VMS:
Sample scripts for xchat.
uurate.c, uurate.man, README-UURATE, Makefile.uurt:
A nifty little program by Bob Denny which analyzes the Log and
Stats file and prints various sorts of reports.
uutraf:
Another program to produce neat reports from your log files, this
one a perl script by Johan Vromans.
savelog.sh, savelog.man:
A handy shell script to rename a log file and cycle old versions
through a set of names, throwing away the oldest one. It will
also optionally compress the old log files. I believe that this
is originally from smail. It was written by Ronald S. Karr and
Landon Curt Noll, and was given to me by Bob Denny.
uureroute:
A perl script reroute all mail queued up for one host to another.
Written by Bill Campbell and contributed by Francois Pinard.
stats.sh:
A gawk script by Zacharias Beckman which reads the Stats file and
prints the last 80 lines as a nicely formatted table.
uuq.sh:
A uuq workalike shell script by Zacharias Beckman.
tstout.c:
A program to remove a user from utmp and wtmp, essentially logging
them out. I put this together from BSD code. I need it to use
tstuu with the system UUCP on Ultrix 4.0, for reasons that escape
me. Most people will have little use for this.

View File

@ -0,0 +1,20 @@
uurate V1.2 - Gather and display Taylor UUCP traffic statistics
Bob Denny (denny@alisa.com) - Thu Sep 3 19:47:41 1992
See the man page for documentation.
Installation:
------------
(1) Copy Makefile.uurt to Makefile.
(2) Edit Makefile: set BIN where you want uurate to be installed, and
set CFLAGS to point to the directory containing the UUCP sources
(this is .. by default).
(3) Type ``make'' to compile the program.
(4) Type ``make install'' to install the program.
(5) Install the man page if you want. I didn't put that into the Makefile.

View File

@ -0,0 +1,42 @@
This is xchat V1.1 (Tue Sep 1 15:50:56 1992)
Introduction:
------------
Xchat is a general-purpose dialing and login program designed for use
with Taylor UUCP as a "chat-program", taking the place (or augmenting)
the built-in chat scripting facility. It provides the ability to
closely control timeouts, multiple simultaneous expect strings with
separate actions, extended terminal control, modem command character
pacing, and more.
When used in conjunction with Taylor UUCP's configuration features,
xchat can provide you the ability to manage the most intricate login,
dial and hangup needs. The scripts are written in a shell-like (well,
sort-of) style with labels, commands, and parameters, easing the task
of writing procedures for complex terminal communications situations.
Installation:
------------
(1) Copy xc-conf.h-dist to xc-conf.h, then edit xc-conf.h to reflect
your condifuration. A description of the settings is in that file.
(2) Copy Makefile.xchat to Makefile and edit it to set BIN to where
you want xchat installed.
(2) Do a 'make' to build xchat.
(3) Do a 'make install' to install it.
(4) Format and print xchat.8, and install it if you want.
(5) Print out copies of the scripts in the ./scripts subdirectory.
(6) Read xchat.8 and the scripts together.
Author:
------
Robert B. Denny (denny@alisa.com)

View File

@ -0,0 +1,130 @@
.\" @(#)man/man8/savelog.an 1.2 24 Oct 1990 05:18:46
.de pP
.if n .sp 1
.if t .sp .4
..
.de tP
.pP
.ta \\n(pDu
.ti -\\n(pDu
..
.TH SAVELOG X_MAN8_EXT_X "31 January 1988" "Local"
.SH NAME
savelog \- cycle and truncate log files
.SH SYNOPSIS
.na
.B X_UTIL_BIN_DIR_X/savelog
[
.B \-m
.I mode
] [
.B \-u
.I user
] [
.B \-g
.I group
] [
.B \-c
.I cycle
] [
.B \-t
] [
.B \-l
]
.I logfile
.br
.ad
.SH DESCRIPTION
The
.I savelog
command renames and optionally compresses a log file and cycles it
through a set of names based on the original log file, removing the
last name in the cycle.
.SH OPTIONS
The
.I savelog
command accepts the following options:
.TP
\fB\-m\fP \fImode\fP
Change the permissions mode for renamed log files to
.IR mode .
By default the mode is unchanged.
.TP
\fB\-u\fP \fIuser\fP
Change the owner for renamed log files to
.IR user .
By default the owner is unchanged.
.TP
\fB\-g\fP \fIgroup\fP
Change the group for renamed log files to
.IR group .
By default the group is unchanged.
.TP
\fB\-c\fP \fIcycle\fP
Save
.I cycle
versions of the logfile, where
.I cycle
is a decimal number. The default value is 7.
.TP
.B \-l
Do not compress log files. By default, a compression program is used,
if one is available.
.TP
.B \-t
Ensure that a new logfile exists when the savelog operation is
complete. Use of
.BR \-m ,
.BR \-u
or
.BR \-g
imply this, ensuring that the logfile will have the designated mode.
.SH "OPERATION"
The given logfile is cycled through files named:
.RS
OLD/\fIfile\fP.\fInumber\fP
.RE
where
.I file
is the basename for the logfile and where
.I number
ranges from 0 to one less then the
.I cycle
count specified for the command.
The
.I OLD
dirctory is created, as necessary, and is under the same directory as
the logfile itself.
.PP
This cycle operation is accomplished by renaming the file numbered
.IR cycle -2
to a file numbered
.IR cycle -1
and so on until the file numbered 0 is renamed to the file numbered 1.
If compression is being used, the first cycle file is compressed after
being renamed to cycle 1. After the cycle files are moved through the
various names, the filefile itself is moved to the cycle 0 file.
This cycle normally occurs once every time
.I savelog
is executed.
If the log file does not exist, savelog ignores it and does
not cycle the OLD files.
.PP
If compression is being used, then compressed log files will have an
additional suffix appropriate for the compression program that is
used.
.SH "SEE ALSO"
.IR smail (X_MAN5_EXT_X)
and
.IR smail (X_MAN8_EXT_X).
.SH COPYRIGHT
Copyright(C)1987, 1988 Ronald S. Karr and Landon Curt Noll
.br
See a file COPYING,
distributed with the source code,
or type
.I "smail \-bc"
for distribution rights and restrictions
associated with this software.

View File

@ -0,0 +1,247 @@
#! /bin/sh
# @(#)util/savelog.sh 1.4 26 Oct 1991 22:49:39
#
# savelog - save a log file
#
# Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
#
# See the file COPYING, distributed with smail, for restriction
# and warranty information.
#
# usage: savelog [-m mode] [-u user] [-g group] [-t] [-c cycle] [-l] file...
#
# -m mode - chmod log files to mode
# -u user - chown log files to user
# -g group - chgrp log files to group
# -c cycle - save cycle versions of the logfile (default: 7)
# -t - touch file
# -l - don't compress any log files (default: compress)
# file - log file names
#
# The savelog command saves and optionally compresses old copies of files
# into an 'dir'/OLD sub-directory. The 'dir' directory is determined from
# the directory of each 'file'.
#
# Older version of 'file' are named:
#
# OLD/'file'.<number><compress_suffix>
#
# where <number> is the version number, 0 being the newest. By default,
# version numbers > 0 are compressed (unless -l prevents it). The
# version number 0 is never compressed on the off chance that a process
# still has 'file' opened for I/O.
#
# If the 'file' does not exist or if it is zero length, no further processing
# is performed. However if -t was also given, it will be created.
#
# For files that do exist and have lengths greater than zero, the following
# actions are performed.
#
# 1) Version numered files are cycled. That is version 6 is moved to
# version 7, version is moved to becomes version 6, ... and finally
# version 0 is moved to version 1. Both compressed names and
# uncompressed names are cycled, regardless of -t. Missing version
# files are ignored.
#
# 2) The new OLD/file.1 is compressed and is changed subject to
# the -m, -u and -g flags. This step is skipped if the -t flag
# was given.
#
# 3) The main file is moved to OLD/file.0.
#
# 4) If the -m, -u, -g or -t flags are given, then file is created
# (as an empty file) subject to the given flags.
#
# 5) The new OLD/file.0 is chanegd subject to the -m, -u and -g flags.
#
# Note: If the OLD sub-directory does not exist, it will be created
# with mode 0755.
#
# Note: If no -m, -u or -g flag is given, then the primary log file is
# not created.
#
# Note: Since the version numbers start with 0, version number <cycle>
# is never formed. The <cycle> count must be at least 2.
#
# Bugs: If a process is still writing to the file.0 and savelog
# moved it to file.1 and compresses it, data could be lost.
# Smail does not have this problem in general because it
# restats files often.
# common location
PATH="X_UTIL_PATH_X:X_SECURE_PATH_X"; export PATH
COMPRESS="X_COMPRESS_X"
COMP_FLAG="X_COMP_FLAG_X"
DOT_Z="X_DOT_Z_X"
CHOWN="X_CHOWN_X"
GETOPT="X_UTIL_BIN_DIR_X/getopt"
# parse args
exitcode=0 # no problems to far
prog=$0
mode=
user=
group=
touch=
count=7
set -- `$GETOPT m:u:g:c:lt $*`
if [ $# -eq 0 -o $? -ne 0 ]; then
echo "usage: $prog [-m mode][-u user][-g group][-t][-c cycle][-l] file ..." 1>&2
exit 1
fi
for i in $*; do
case $i in
-m) mode=$2; shift 2;;
-u) user=$2; shift 2;;
-g) group=$2; shift 2;;
-c) count=$2; shift 2;;
-t) touch=1; shift;;
-l) COMPRESS=""; shift;;
--) shift; break;;
esac
done
if [ "$count" -lt 2 ]; then
echo "$prog: count must be at least 2" 1>&2
exit 2
fi
# cycle thru filenames
while [ $# -gt 0 ]; do
# get the filename
filename=$1
shift
# catch bogus files
if [ -b "$filename" -o -c "$filename" -o -d "$filename" ]; then
echo "$prog: $filename is not a regular file" 1>&2
exitcode=3
continue
fi
# if not a file or empty, do nothing major
if [ ! -s $filename ]; then
# if -t was given and it does not exist, create it
if [ ! -z "$touch" -a ! -f $filename ]; then
touch $filename
if [ "$?" -ne 0 ]; then
echo "$prog: could not touch $filename" 1>&2
exitcode=4
continue
fi
if [ ! -z "$user" ]; then
$CHOWN $user $filename
fi
if [ ! -z "$group" ]; then
chgrp $group $filename
fi
if [ ! -z "$mode" ]; then
chmod $mode $filename
fi
fi
continue
fi
# be sure that the savedir exists and is writable
savedir=`expr "$filename" : '\(.*\)/'`
if [ -z "$savedir" ]; then
savedir=./OLD
else
savedir=$savedir/OLD
fi
if [ ! -s $savedir ]; then
mkdir $savedir
if [ "$?" -ne 0 ]; then
echo "$prog: could not mkdir $savedir" 1>&2
exitcode=5
continue
fi
chmod 0755 $savedir
fi
if [ ! -d $savedir ]; then
echo "$prog: $savedir is not a directory" 1>&2
exitcode=6
continue
fi
if [ ! -w $savedir ]; then
echo "$prog: directory $savedir is not writable" 1>&2
exitcode=7
continue
fi
# deterine our uncompressed file names
newname=`expr "$filename" : '.*/\(.*\)'`
if [ -z "$newname" ]; then
newname=$savedir/$filename
else
newname=$savedir/$newname
fi
# cycle the old compressed log files
cycle=`expr $count - 1`
rm -f $newname.$cycle $newname.$cycle$DOT_Z
while [ "$cycle" -gt 1 ]; do
# --cycle
oldcycle=$cycle
cycle=`expr $cycle - 1`
# cycle log
if [ -f $newname.$cycle$DOT_Z ]; then
mv -f $newname.$cycle$DOT_Z $newname.$oldcycle$DOT_Z
fi
if [ -f $newname.$cycle ]; then
# file was not compressed for some reason move it anyway
mv -f $newname.$cycle $newname.$oldcycle
fi
done
# compress the old uncompressed log if needed
if [ -f $newname.0 ]; then
if [ -z "$COMPRESS" ]; then
newfile=$newname.1
mv $newname.0 $newfile
else
newfile=$newname.1$DOT_Z
$COMPRESS $COMP_FLAG < $newname.0 > $newfile
rm -f $newname.0
fi
if [ ! -z "$user" ]; then
$CHOWN $user $newfile
fi
if [ ! -z "$group" ]; then
chgrp $group $newfile
fi
if [ ! -z "$mode" ]; then
chmod $mode $newfile
fi
fi
# move the file into the file.0 holding place
mv -f $filename $newname.0
# replace file if needed
if [ ! -z "$touch" -o ! -z "$user" -o \
! -z "$group" -o ! -z "$mode" ]; then
touch $filename
fi
if [ ! -z "$user" ]; then
$CHOWN $user $filename
fi
if [ ! -z "$group" ]; then
chgrp $group $filename
fi
if [ ! -z "$mode" ]; then
chmod $mode $filename
fi
# fix the permissions on the holding place file.0 file
if [ ! -z "$user" ]; then
$CHOWN $user $newname.0
fi
if [ ! -z "$group" ]; then
chgrp $group $newname.0
fi
if [ ! -z "$mode" ]; then
chmod $mode $newname.0
fi
done
exit $exitcode

View File

@ -0,0 +1,27 @@
#!/bin/sh
#
# uuspeed - a script to parse a Taylor UUCP Stats file into pretty results.
# Zacharias J. Beckman.
grep bytes /usr/spool/uucp/Stats | grep -v 'bytes 0.00 secs' | grep -v 'failed after' | tail -80 | \
gawk '
BEGIN {
printf(" UUCP transmission history:\n");
format=" %8d bytes %8s(%8s) in %7.2f sec = %5.0f baud, %4.1fK / min\n";
average=0.01;
samples=0;
}
{
if ($6 > 100) {
printf (format, $6, $5, $2, $9, $6/$9*10, ($6/$9*60)/1000);
average += ($6/$9*10);
samples += 1;
}
}
END {
printf (" average speed %d baud\n", average/samples);
}
'

View File

@ -0,0 +1,158 @@
/* tstout.c
Put together by Ian Lance Taylor <ian@airs.com>
This program is used to logout a program run by the tstuu program.
I needed this because on Ultrix 4.0 I can't get the uucp program
to run without invoking it via /bin/login and having it start up
as a shell. If I don't do it this way, it gets a SIGSEGV trap
for some reason. Most systems probably don't need to do things
this way. It will only work on BSD systems anyhow, I suspect.
The code for this comes from "UNIX Network Programming" by W.
Richard Stevens, Prentice-Hall 1990. Most of it is from 4.3BSD, as
noted in the comments.
This program must run suid to root.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <utmp.h>
static int logout P((const char *zdev));
static void logwtmp P((const char *zdev, const char *zname,
const char *zhost));
int
main (argc, argv)
int argc;
char **argv;
{
char *z;
if (argc != 2
|| strncmp (argv[1], "/dev/", sizeof "/dev/" - 1) != 0)
{
fprintf (stderr, "Usage: tstout device\n");
exit (EXIT_FAILURE);
}
z = argv[1] + 5;
if (logout (z))
logwtmp (z, "", "");
chmod (argv[1], 0666);
chown (argv[1], 0, 0);
*z = 'p';
chmod (argv[1], 0666);
chown (argv[1], 0, 0);
exit (EXIT_SUCCESS);
}
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)logout.c 5.2 (Berkeley) 2/17/89";
#endif /* LIBC_SCCS and not lint */
#define UTMPFILE "/etc/utmp"
/* 0 on failure, 1 on success */
static int
logout(line)
register const char *line;
{
register FILE *fp;
struct utmp ut;
int rval;
time_t time();
if (!(fp = fopen(UTMPFILE, "r+")))
return(0);
rval = 0;
while (fread((char *)&ut, sizeof(struct utmp), 1, fp) == 1) {
if (!ut.ut_name[0] ||
strncmp(ut.ut_line, line, sizeof(ut.ut_line)))
continue;
bzero(ut.ut_name, sizeof(ut.ut_name));
bzero(ut.ut_host, sizeof(ut.ut_host));
(void)time((time_t *)&ut.ut_time);
(void)fseek(fp, (long)-sizeof(struct utmp), L_INCR);
(void)fwrite((char *)&ut, sizeof(struct utmp), 1, fp);
(void)fseek(fp, (long)0, L_INCR);
rval = 1;
}
(void)fclose(fp);
return(rval);
}
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)logwtmp.c 5.2 (Berkeley) 9/20/88";
#endif /* LIBC_SCCS and not lint */
#define WTMPFILE "/usr/adm/wtmp"
static void
logwtmp(line, name, host)
const char *line, *name, *host;
{
struct utmp ut;
struct stat buf;
int fd;
time_t time();
char *strncpy();
if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
return;
if (!fstat(fd, &buf)) {
(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
(void)time((time_t *)&ut.ut_time);
if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
sizeof(struct utmp))
(void)ftruncate(fd, buf.st_size);
}
(void)close(fd);
}

View File

@ -0,0 +1,23 @@
# This is a sample uuclean shell script
# Copyright (C) 1992 Ian Lance Taylor
# Do whatever you like with this script.
#
# Set some variables
bindir=/usr/local/bin
spooldir=/usr/spool/uucp
#
# Warn about all mail over two days old
$(bindir)/uustat -c rmail -o 48 -N -Q -W"Unable to deliver; will try up to one week"
# Return all mail over a week old
$(bindir)/uustat -c rmail -o 168 -K -M -N -Q -W"Could not be delivered for over one week"
# Throw away other requests over a week old
$(bindir)/uustat -o 168 -K -M -N -Q -W"Over one week old"
# Throw away any executions over three days old
$(bindir)/uustat -o 72 -M -N -Q -W"Unable to execute for three days"
#
# Now delete any old spool files
find $(spooldir) -ctime +8 -name '[CDX].*' -print -exec rm -f \{\} \;
# Delete any old temporary files
find $(spooldir) -atime +1 -ctime +1 -name 'TM.*' -print -exec rm -f \{\} \;
# Delete any old preserved files
find $(spooldir)/.Preserve -atime +14 -ctime +14 -print -exec rm -f \{\} \;

125
gnu/libexec/uucp/contrib/uuq.sh Executable file
View File

@ -0,0 +1,125 @@
#!/bin/sh
#
# uuq - a script to examine and display the Taylor spool directory contents.
# note - uses the uuname script or similar functionality.
# Zacharias Beckman
SPOOLDIR="/usr/spool/uucp"
SYSTEMS=`uuname`
TMPFILE="/tmp/uuq.tmp"
FORSYSTEM=""
DELETE=""
LONG=0
SINGLE=0
while [ "$1" != "" ]
do
case $1 in
-l) LONG=1
shift
;;
-s) shift
SYSTEMS=$argv[1]
SINGLE=1
shift
;;
-d) shift
DELETE=$argv[1]
shift
;;
-h) echo "uuq: usage uuq [options]"
echo " -l long listing (may take a while)"
echo " -s n run uuq only for system n"
echo " -d n delete item n from the queue (required -s)"
exit 1
;;
*) echo "uuq: invalid option"
exit 1
;;
esac
done
if [ "${DELETE}" != "" ] && [ ${SINGLE} != 1 ] ; then
echo "uuq: you must specify a system to delete the job from:"
echo " uuq -s wizard -d D.0004"
exit 1
fi
cd ${SPOOLDIR}
# if we are deleting a job, then do that first and exit without showing
# any other queue information
if [ "${DELETE}" != "" ] ; then
if [ -d ${SYSTEMS}/D. ] ; then
cd ${SYSTEMS}/C.
PACKET=${DELETE}
if [ -f ${PACKET} ] ; then
EXFILE=../D.X/`awk '{if (NR == 2) print $2}' ${PACKET}`
DFILE=../D./`awk '{if (NR == 1) print $2}' ${PACKET}`
echo "deleting job ${PACKET}"
rm ${PACKET}
rm ${EXFILE}
rm ${DFILE}
else
echo "uuq: job ${PACKET} not found"
exit 1
fi
else
echo "uuq: system ${SYSTEMS} not found"
fi
exit 1
fi
# use the 'uuname' script to obtain a list of systems for the 'sys' file,
# then step through each directory looking for appropriate information.
if [ ${LONG} -gt 0 ] ; then
echo "system"
echo -n "job# act size command"
fi
for DESTSYSTEM in ${SYSTEMS} ; do
# if there is an existing directory for the named system, cd into it and
# "do the right thing."
if [ -d ${DESTSYSTEM} ] ; then
cd ${DESTSYSTEM}/C.
PACKET=`ls`
if [ "${PACKET}" != "" ] ; then
# if a long listing has been required, extra information is printed
echo ""
echo "${DESTSYSTEM}:"
# now each packet must be examined and appropriate information is
# printed for this system
if [ ${LONG} -gt 0 ] ; then
for PACKET in * ; do
EXFILE=../D.X/`awk '{if (NR == 2) print $2}' ${PACKET}`
DFILE=../D./`awk '{if (NR == 1) print $2}' ${PACKET}`
echo -n "${PACKET} " > ${TMPFILE}
gawk '{if (NR == 2) printf(" %s ", $1);}' ${PACKET} >> ${TMPFILE}
ls -l ${DFILE}|awk '{printf("%-10d ", $4)}' >> ${TMPFILE}
if [ -f ${EXFILE} ] ; then
gawk '/U / {printf("(%s)", $2);}\
/C / {print substr($0,2,length($0));}' ${EXFILE} >> ${TMPFILE}
else
echo "---" >> ${TMPFILE}
fi
cat ${TMPFILE}
done
cat ${SPOOLDIR}/.Status/${DESTSYSTEM}
else
ls
fi
fi
fi
cd ${SPOOLDIR}
done

View File

@ -0,0 +1,657 @@
/*
* @(#)uurate.c 1.2 - Thu Sep 3 18:32:46 1992
*
* This program digests log and stats files in the "Taylor" format
* and outputs various statistical data to standard out.
*
* Author:
* Bob Denny (denny@alisa.com)
* Fri Feb 7 13:38:36 1992
*
* Original author:
* Mark Pizzolato mark@infopiz.UUCP
*
* Edits:
* Bob Denny - Fri Feb 7 15:04:54 1992
* Heavy rework for Taylor UUCP. This was the (very old) uurate from
* DECUS UUCP, which had a single logfile for activity and stats.
* Personally, I would have done things differently, with tables
* and case statements, but in the interest of time, I preserved
* Mark Pizzolato's techniques and style.
*
* Bob Denny - Sun Aug 30 14:18:50 1992
* Changes to report format suggested by Francois Pinard and others.
* Add summary report, format from uutraf.pl (perl script), again
* thanks to Francois. Integrate and checkout with 1.03 of Taylor UUCP.
*/
char version[] = "@(#) Taylor UUCP Log File Summary Filter, Version 1.2";
#include <ctype.h> /* Character Classification */
#include <string.h>
#include <math.h>
#include "uucp.h"
#define _DEBUG_ 0
/*
* Direction of Calling and Data Transmission
*/
#define IN 0 /* Inbound */
#define OUT 1 /* Outbound */
/*
* Data structures used to collect information
*/
struct File_Stats
{
int files; /* Files Transferred */
unsigned long bytes; /* Data Size Transferred*/
double time; /* Transmission Time */
};
struct Phone_Call
{
int calls; /* Call Count */
int succs; /* Successful calls */
double connect_time; /* Connect Time Spent */
struct File_Stats flow[2]; /* Rcvd & Sent Data */
};
struct Execution_Command
{
struct Execution_Command *next;
char Commandname[64];
int count;
};
struct Host_entry
{
struct Host_entry *next;
char Hostname[32];
struct Execution_Command *cmds; /* Local Activities */
struct Phone_Call call[2]; /* In & Out Activities */
};
/*
* Stuff for getopt()
*/
extern int optind; /* GETOPT : Option Index */
extern char *optarg; /* GETOPT : Option Value */
extern void *calloc();
static void fmtime();
static void fmbytes();
/*
* Default files to read. Taken from Taylor compile-time configuration.
* Must look like an argvec, hence the dummy argv[0].
*/
static char *(def_logs[3]) = { "", LOGFILE, STATFILE };
/*
* Misc. strings for reports
*/
static char *(file_hdr[2]) = { "\nReceived file statistics:\n",
"\nSent file statistics\n" };
/*
* BEGIN EXECUTION
*/
main(argc, argv)
int argc;
char *argv[];
{
char c;
char *p, *s;
struct Host_entry *hosts = NULL;
struct Host_entry *cur = NULL;
struct Host_entry *e;
struct Execution_Command *cmd;
struct Execution_Command *ec;
char Hostname[64];
FILE *Log = NULL;
char logline[1024];
char *logmsg;
int sent;
int called;
int show_files = 0; /* I prefer boolean, but... */
int show_calls = 0;
int show_commands = 0;
int show_efficiency = 0;
int show_summary = 0;
int have_files = 0;
int have_calls = 0;
int have_commands = 0;
int use_stdin = 0;
Hostname[0] = '\0';
/*
* I wish the compiler had the #error directive!
*/
#if !HAVE_TAYLOR_LOGGING
fprintf(stderr, "uurate cannot be used with your configuration of\n");
fprintf(stderr, "Taylor UUCP. To use uurate you must be using the\n");
fprintf(stderr, "TAYLOR_LOGGING configuration.\n");
exit(1);
#endif
/*
* Process the command line arguments
*/
while((c = getopt(argc, argv, "h:cfexai")) != EOF)
{
switch(c)
{
case 'h':
strcpy(Hostname, optarg);
break;
case 'c':
show_calls = 1;
break;
case 'f':
show_files = 1;
break;
case 'x':
show_commands = 1;
break;
case 'e':
show_efficiency = 1;
break;
case 'a':
show_calls = show_files = show_commands = show_efficiency = 1;
break;
case 'i':
use_stdin = 1;
break;
default :
goto usage;
}
}
/*
* If no report switches given, show summary report.
*/
if (show_calls == 0 && show_files == 0
&& show_efficiency == 0 && show_commands == 0)
show_summary = 1;
/*
* Adjust argv and argc to account for the args processed above.
*/
argc -= (optind - 1);
argv += (optind - 1);
/*
* If further args present, Assume rest are logfiles for us to process,
* otherwise, take input from Log and Stat files provided in the
* compilation environment of Taylor UUCP. If -i was given, Log already
* points to stdin and no file args are accepted.
*/
if(argc == 1) /* No file arguments */
{
if (use_stdin) /* If -i, read from stdin */
{
argc = 2;
Log = stdin;
}
else /* Read from current logs */
{
argc = 3; /* Bash argvec to default log/stat files */
argv = &def_logs[0];
}
}
else if (use_stdin) /* File args with -i is an error */
{
fprintf(stderr, "uurate (error): file args given with '-i'\n");
goto usage;
}
#if _DEBUG_
printf("\n");
#endif
/*
* MAIN LOGFILE PROCESSING LOOP
*/
while (argc > 1)
{
if (!use_stdin && (Log = fopen(argv[1], "r")) == NULL)
{
perror(argv[1]);
return;
}
#if _DEBUG_
printf("Reading %s...\n", (use_stdin ? "stdin" : argv[1]));
#endif
/*
* Read each line of the logfile and collect information
*/
while (fgets(logline, sizeof(logline), Log))
{
/*
* The host name of the other end of the connection is
* always the second field of the log line, whether we
* are reading a Log file or a Stats file. Set 'p' to
* point to the second field, null-terminated. Skip
* the line if something is funny.
*/
if (NULL == (p = strchr(logline, ' ')))
continue;
++p;
if (NULL != (s = strchr(p, ' ')))
*s = '\0';
for (s = p; *s; ++s)
if (isupper(*s))
*s = tolower(*s);
/*
* Skip this line if we got -h <host> and
* this line does not contain that host name.
*/
if (Hostname[0] != '\0')
if (0 != strcmp(p, Hostname))
continue;
/*
* We are within a call block now. If this line is a file
* transfer record, determine the direction. If not then
* skip the line if it is not interesting.
*/
if ((s = strchr(++s, ')')) == NULL)
continue;
logmsg = s + 2; /* Message is 2 characters after ')' */
if (0 == strncmp(logmsg, "sent", 4))
sent = OUT;
else
if (0 == strncmp(logmsg, "received", 8))
sent = IN;
else
if ((0 != strncmp(logmsg, "Call complete", 13)) &&
(0 != strncmp(logmsg, "Calling system", 14)) &&
(0 != strncmp(logmsg, "Incoming call", 13)) &&
(0 != strncmp(logmsg, "Executing", 9)))
continue;
/*
* Find the Host_entry for this host, or create a new
* one and link it on to the list.
*/
if ((cur == NULL) || (0 != strcmp(p, cur->Hostname)))
{
for (cur = hosts; cur != NULL ; cur = cur->next)
if (0 == strcmp(cur->Hostname, p))
break;
if (cur == NULL)
{
cur = (struct Host_entry *)calloc(1, sizeof(*hosts));
strcpy(cur->Hostname, p);
if (hosts == NULL)
hosts = cur;
else
{
for (e = hosts; e->next != NULL; e = e->next);
e->next = cur;
}
}
}
/*
* OK, if this is a uuxqt record, find the Execution_Command
* structure for the command being executed, or create a new
* one. Then count an execution of this command.
*/
if (0 == strncmp(logmsg, "Executing", 9))
{
if (NULL == (p = strchr(logmsg, '(')))
continue;
if ((s = strpbrk(++p, " )")) == NULL)
continue;
*s = '\0';
for (cmd = cur->cmds; cmd != NULL; cmd = cmd->next)
if (0 == strcmp(cmd->Commandname, p))
break;
if (cmd == NULL)
{
cmd = (struct Execution_Command *)calloc(1, sizeof(*cmd));
strcpy(cmd->Commandname, p);
if (cur->cmds == NULL)
cur->cmds = cmd;
else
{
for (ec = cur->cmds; ec->next != NULL; ec = ec->next);
ec->next = cmd;
}
}
++cmd->count;
have_commands = 1;
continue;
}
/*
* Count start of outgoing call.
*/
if (0 == strncmp(logmsg, "Calling system", 14))
{
called = OUT;
cur->call[called].calls += 1;
have_calls = 1;
continue;
}
/*
* Count start of incoming call.
*/
if (0 == strncmp(logmsg, "Incoming call", 13))
{
called = IN;
cur->call[called].calls += 1;
have_calls = 1;
continue;
}
/*
* Handle end of call. Pick up the connect time.
*/
if (0 == strncmp(logmsg, "Call complete", 13))
{
cur->call[called].succs += 1;
if (NULL == (s = strchr(logmsg, '(')))
continue;
cur->call[called].connect_time += atof(s+1);
continue;
}
/*
* If we reached here, this must have been a file transfer
* record. Count it in the field corresponding to the
* direction of the transfer. Count bytes transferred and
* the time to transfer as well.
*/
have_files = 1;
cur->call[called].flow[sent].files += 1;
if (NULL == (s = strchr(logmsg, ' ')))
continue;
cur->call[called].flow[sent].bytes += atol(++s);
if (NULL == (s = strchr(s, ' ')))
continue;
if (NULL == (s = strpbrk(s, "0123456789")))
continue;
cur->call[called].flow[sent].time += atof(s);
}
argc -= 1;
argv += 1;
if(Log != stdin)
fclose(Log);
}
/*
* ***********
* * REPORTS *
* ***********
*/
/*
* Truncate the Hostnames to 8 characters at most.
*/
for (cur = hosts; cur != NULL; cur = cur->next)
cur->Hostname[8] = '\0';
#if _DEBUG_
printf("\n");
#endif
/*
* Summary report
*
* I know, this code could be tightened (rbd)...
*/
if(show_summary)
{
char t1[32], t2[32], t3[32], t4[32], t5[32];
long ib, ob, b, rf, sf;
long t_ib=0, t_ob=0, t_b=0, t_rf=0, t_sf=0;
double it, ot, ir, or;
double t_it=0.0, t_ot=0.0;
int nhosts = 0;
printf("\n\
Remote ------- Bytes -------- --- Time ---- -- Avg CPS -- -- Files --\n");
printf("\
Host Rcvd Sent Total Rcvd Sent Rcvd Sent Rcvd Sent\n");
printf("\
-------- ------- ------- ------- ------ ------ ------ ------ ----- -----\n");
for (cur = hosts; cur != NULL; cur = cur->next)
{
ib = (cur->call[IN].flow[IN].bytes +
cur->call[OUT].flow[IN].bytes);
fmbytes(ib, t1);
t_ib += ib;
ob = (cur->call[IN].flow[OUT].bytes +
cur->call[OUT].flow[OUT].bytes);
fmbytes(ob, t2);
t_ob += ob;
b = ib + ob;
fmbytes(b, t3);
t_b += b;
it = cur->call[IN].flow[IN].time +
cur->call[OUT].flow[IN].time;
fmtime(it, t4);
t_it += it;
ot = cur->call[IN].flow[OUT].time +
cur->call[OUT].flow[OUT].time;
fmtime(ot, t5);
t_ot += ot;
rf = cur->call[IN].flow[IN].files +
cur->call[OUT].flow[IN].files;
t_rf += rf;
sf = cur->call[IN].flow[OUT].files +
cur->call[OUT].flow[OUT].files;
t_sf += sf;
ir = (it == 0.0) ? 0.0 : (ib / it);
or = (ot == 0.0) ? 0.0 : (ob / ot);
printf("%-8s %7s %7s %7s %6s %6s %6.1f %6.1f %5d %5d\n",
cur->Hostname,
t1, t2, t3, t4, t5,
ir, or, rf, sf);
}
if(nhosts > 1)
{
fmbytes(t_ib, t1);
fmbytes(t_ob, t2);
fmbytes(t_b, t3);
fmtime(t_it, t4);
fmtime(t_ot, t5);
ir = (t_it == 0.0) ? 0.0 : (t_ib / t_it);
or = (t_ot == 0.0) ? 0.0 : (t_ob / t_ot);
printf("\
-------- ------- ------- ------- ------ ------ ------ ------ ----- -----\n");
printf("\
Totals %7s %7s %7s %6s %6s %6.1f %6.1f %5d %5d\n",
t1, t2, t3, t4, t5,
ir, or, t_rf, t_sf);
}
}
/*
* Call statistics report
*/
if(show_calls && have_calls)
{
char t1[32], t2[32];
printf("\nCall statistics:\n");
printf("\
sysname callto failto totime callfm failfm fmtime\n");
printf("\
-------- ------ ------ -------- ------ ------ --------\n");
for (cur = hosts; cur != NULL; cur = cur->next)
{
fmtime(cur->call[OUT].connect_time, t1);
fmtime(cur->call[IN].connect_time, t2),
printf(" %-8s %6d %6d %8s %6d %6d %8s\n",
cur->Hostname,
cur->call[OUT].calls,
cur->call[OUT].calls - cur->call[OUT].succs,
t1,
cur->call[IN].calls,
cur->call[IN].calls - cur->call[IN].succs,
t2);
}
}
/*
* File statistics report
*/
if(show_files && have_files)
{
char t1[32], t2[32];
for (sent = IN; sent <= OUT; ++sent)
{
printf(file_hdr[sent]);
printf(" sysname files bytes xfr time byte/s\n");
printf(" -------- ------ -------- -------- ------\n");
for (cur = hosts; cur != NULL; cur = cur->next)
{
double rate;
double time;
time = cur->call[IN].flow[sent].time +
cur->call[OUT].flow[sent].time;
if (time == 0.0)
continue;
rate = (cur->call[IN].flow[sent].bytes +
cur->call[OUT].flow[sent].bytes) / time;
fmbytes((cur->call[IN].flow[sent].bytes +
cur->call[OUT].flow[sent].bytes), t1);
fmtime((cur->call[IN].flow[sent].time +
cur->call[OUT].flow[sent].time), t2);
printf(" %-8s %6d %8s %8s %6.1f\n",
cur->Hostname,
cur->call[IN].flow[sent].files +
cur->call[OUT].flow[sent].files,
t1, t2, rate);
}
}
}
/*
* Efficiency report
*/
if (show_efficiency && have_files)
{
char t1[32], t2[32], t3[32];
double total, flow;
printf("\nEfficiency:\n");
printf(" sysname conntime flowtime ovhdtime eff. %%\n");
printf(" -------- -------- -------- -------- ------\n");
for (cur = hosts; cur != NULL; cur = cur->next)
{
total = cur->call[IN].connect_time + cur->call[OUT].connect_time;
flow = cur->call[IN].flow[IN].time + cur->call[IN].flow[OUT].time +
cur->call[OUT].flow[IN].time + cur->call[OUT].flow[OUT].time;
fmtime(total, t1);
fmtime(flow, t2);
fmtime((total-flow), t3);
printf(" %-8s %8s %8s %8s %5.1f%%\n",
cur->Hostname, t1, t2, t3, ((flow / total) * 100.0));
}
}
/*
* Command execution report
*/
if (show_commands & have_commands)
{
printf("\nCommand executions:\n");
printf(" sysname rmail rnews other\n");
printf(" -------- ------ ------ ------\n");
for (cur = hosts; cur != NULL; cur = cur->next)
{
int rmail, rnews, other;
if (cur->cmds == NULL)
continue;
rmail = rnews = other = 0;
for (cmd = cur->cmds; cmd != NULL; cmd = cmd->next)
{
if (strcmp(cmd->Commandname, "rmail") == 0)
rmail += cmd->count;
else if (strcmp(cmd->Commandname, "rnews") == 0)
rnews += cmd->count;
else
other += cmd->count;
}
printf(" %-8s %6d %6d %6d\n", cur->Hostname,
rmail, rnews, other);
}
}
return;
usage:
fprintf(stderr,
"Usage uurate [-cfexai] [-h hostname] [logfile ... logfile]\n");
fprintf(stderr,"where:\t-c\tReport call statistics\n");
fprintf(stderr, "\t-f\tReport file transfer statistics\n");
fprintf(stderr, "\t-e\tReport efficiency statistics\n");
fprintf(stderr, "\t-x\tReport command execution statistics\n");
fprintf(stderr, "\t-a\tAll of the above reports\n");
fprintf(stderr, "\t-h host\tReport activities involving ONLY host\n");
fprintf(stderr, "\t-i\tRead log info from standard input\n");
fprintf(stderr,
"If no report options given, a compact summary report is given.\n");
fprintf(stderr,
"If neither -i nor logfiles given, defaults to reading from\n");
fprintf(stderr, "%s and %s\n\n", LOGFILE, STATFILE);
}
/*
* fmtime() - Format time in hours & minutes;
*/
static void fmtime(dsec, buf)
double dsec;
char *buf;
{
long hrs, min, lsec;
lsec = dsec;
hrs = lsec / 3600L;
min = (lsec - (hrs * 3600L)) / 60L;
sprintf(buf, "%02ld:%02ld", hrs, min);
}
/*
* fmbytes - Format size in bytes
*/
static void fmbytes(n, buf)
unsigned long n;
char *buf;
{
char t;
double s = n;
if(s >= 10239897.6) /* More than 9999.9K ? */
{
s = (double)n / 1048576.0; /* Yes, display in Megabytes */
t = 'M';
}
else
{
s = (double)n / 1024.0; /* Display in Kilobytes */
t = 'K';
}
sprintf(buf, "%.1f%c", s, t);
}

View File

@ -0,0 +1,217 @@
.TH uurate 1
.SH NAME
uurate \- Report Taylor UUCP statistics
.SH SYNOPSIS
.BR uurate " [ " "\-cfexai" " ] [ " "\-h "
.I host
.RI " ] [ " "logfile..." " ] "
.PP
or simply,
.PP
.B uurate
.PP
for a traffic summary report.
.SH DESCRIPTION
The
.I uurate
command provides tabular summary reports on the operation of the
Taylor UUCP system. Data is taken from the currently active log
files, standard input, or from a list of log files given on the
command line. Output is in the form of tabular reports summarizing
call, file transfer, and command execution
.RI "(" "uuxqt" ")"
activity.
.PP
The log files given to
.I uurate
must be in the ``Taylor'' format. Also, note that call and file
transfer activities are logged in separate files, nominally called
.I Log
and
.I Stats,
respectively. For reports to be meaningful, the
.I Log
and
.I Stats
files should be given to
.I uurate
together, and cover the same time period.
.PP
If neither the
.B \-i
option nor any
.I logfile
options are given,
.I uurate
defaults to taking its input from the current Taylor
.I Log
and
.I Stats
files, as defined at compilation time.
This is the normal mode of operation.
.PP
The reporting options described below can be used to select
the set of reports desired. If no options are given, the
.B call
and
.B file
reports are displayed. If there is no relevant data for a particular
report or host, that report or host will be supressed.
.SH OPTIONS
The following options may be given to
.I uurate:
.TP 5
.B \-c
Report on call statistics. Requires data from a
.I Log
file.
.TP 5
.B \-f
Report on file transfer statistics. Requires data from a
.I Stats
file.
.TP 5
.B \-e
Report on efficiency (total connect time versus time spent transferring
files). Requires data from both a
.I Log
and a
.I Stats
file, and they must span the same time period.
.TP 5
.B \-x
Report on remote execution requests (e.g.,
.IR rmail ")."
Requires data from a
.I Log
file.
.TP 5
.B \-a
All reports. Identical to
.B \-cfex.
.TP 5
.BI "\-h " "host"
Restrict report output to
.I host.
.SH "DESCRIPTION OF REPORTS"
There are four reports available: the call, file transfer, efficiency,
and remote execution reports. Each may be selected by a command line
option. All reports may be selected via the option
.B \-a.
If no report selection options are given,
.I uurate
displays a compact traffic summary report (see below).
.SS "Summary report"
If no report options are given,
.I uurate
displays a traffic summary report. This is particularly useful in daily
.I cron
jobs which report on errors and the like. Traffic statistics for each
active system is reported on a single line. If more than one system was
active, a 'totals' line is included at the end of the report.
.SS "Call report"
The call report gives statistics on inbound and outbound calls for
each active host system. The fields are described below:
.br
.nf
.in +.5i
.ta 1.0i
.BR "sysname " "UUCP node name of neighbor host system"
.BR "callto " "Outbound calls attempted to that system"
.BR "failto " "Failed outbound calls to that system"
.BR "totime " "Connect time (sec.) on outbound calls"
.BR "callfm " "Inbound calls attempted by that system"
.BR "failfm " "Failed inbound calls from that system"
.BR "fmtime " "Connect time (sec.) on inbound calls"
.in -.5
.SS "File transfer reports"
The file transfer reports give statistics on inbound and
outbound file transfers (regardless of which end initiated the transfer)
for each active host system. There are two reports, one for files
sent to the remote system and one for files received from the remote
system. The fields in each report are described below:
.br
.nf
.in +.5i
.ta 1.0i
.BR "sysname " "UUCP node name of neighbor host system"
.BR "files " "Number of files transferred"
.BR "bytes " "Total size (bytes) of files transferred"
.BR "seconds " "Total time (sec.) to transfer files"
.BR "byte/sec " "Average transfer rate (bytes/sec)"
.in -.5
.SS "Efficiency report"
The efficiency report describes the utilization of the links
to each active remote system, giving the ratio of total connect time
to the time spent actually transferring files.
The fields are described below:
.br
.nf
.in +.5i
.ta 1.0i
.BR "sysname " "UUCP node name of neighbor host system"
.BR "conntime " "Total connect time for that system"
.BR "flowtime " "Total file transfer time for that system"
.BR "ovhdtime " "Connect time not used to transfer files"
.BR "effcy (%) " "Ratio of connect time to transfer time"
.in -.5
.SS "Remote execution report"
The remote execution report describes remotely
requested command executions from each active host system.
Executions of
.I rmail
and
.I rnews
are the most common, and are detailed separately. The fields
are described below:
.br
.nf
.in +.5i
.ta 1.0i
.BR "sysname " "UUCP node name of neighbor host system"
.BR "rmail " "Number of rmail requests from that system"
.BR "rnews " "Number of rnews requests from that system"
.BR "other " "Number of other requests from that system"
.in -.5i
.SS FILES
The file names below may be changed at compilation time or by the
configuration file, so these are only approximations.
.br
.nf
.in +.5in
.ta 2.0i
.IR "/usr/spool/uucp/Log " "Taylor format call/execution log"
.IR "/usr/spool/uucp/Stats " "Taylor format file transfer log"
.SS "SEE ALSO"
.IR uucico "(8)"
.SS BUGS
Does not understand older (V2, BNU) logging formats. Anyone care to
volunteer to add this? I don't use the stuff myself.
.PP
The entries that Taylor UUCP makes in the log file for incoming calls
don't have a host name. This confuses
.I uurate
into thinking that the calls came in for system "-". This may require
a change to Taylor logging.
.PP
Should check the configuration file to locate the currently active
.I Log
and
.I Stats
files when using them for default inputs. Instead, it uses the
compile-time settings only.
.PP
Should report packet protocol error statistics by host and
protocol type.
.SS AUTHOR
Robert B. Denny (denny@alisa.com)
.br
Loosely based on the DECUS UUCP program
.I uurate
by Mark Pizzolato.

View File

@ -0,0 +1,91 @@
#!/usr/local/bin/perl
eval ' exec /usr/local/bin/perl $0 "$@" '
if $running_under_some_shell;
# From a script by <Bill.Campbell@celestial.com>
# Newsgroups: comp.sources.misc
# Subject: v28i073: uureroute - Reroute HDB queued mail, Part01/01
# Date: 26 Feb 92 02:28:37 GMT
#
# This is a Honey DanBer specific routine written in perl to reroute all
# mail queued up for a specific host. It needs to be run as "root" since
# uucp will not allow itself to remove others requests.
#
# Revision *** 92/21/09: Francois Pinard <pinard@iro.umontreal.ca>
# 1. adapted for Taylor UUCP
#
# Revision 1.3 91/10/08 09:01:21 src
# 1. Rewritten in perl
# 2. Add -v option for debugging.
#
# Revision 1.2 91/10/07 23:57:42 root
# 1. Fix mail program path.
# 2. Truncate directory name to 7 characters
($progname = $0) =~ s!.*/!!; # save this very early
$USAGE = "
# Reroute uucp mail
#
# Usage: $progname [-v] host [host...]
#
# Options Argument Description
# -v Verbose (doesn't execute /bin/sh)
#
";
$UUSTAT = "/usr/local/bin/uustat";
$SHELL = "/bin/sh";
$SMAIL = "/bin/smail";
sub usage
{
die join ("\n", @_) . "\n$USAGE\n";
}
do "getopts.pl";
&usage ("Invalid Option") unless do Getopts ("vV");
$verbose = ($opt_v ? '-v' : ());
$suffix = ($verbose ? '' : $$);
&usage ("No system specified") if $#ARGV < 0;
if (!$verbose)
{
open (SHELL, "| $SHELL");
select SHELL;
}
while ($system = shift)
{
$sysprefix = substr ($system, 0, 7);
$directory = "/usr/spool/uucp/$sysprefix";
open (UUSTAT, "$UUSTAT -s $system -c rmail |");
print "set -ex\n";
while (<UUSTAT>)
{
($jobid, ) = split;
($cfile) = substr ($jobid, length ($jobid) - 5);
$cfilename = "$directory/C./C.$cfile";
open (CFILE, $cfilename) || die "Cannot open $cfilename\n";
$_ = <CFILE>;
close CFILE;
if (/^E D\.(....) [^ ]+ [^ ]+ -CR D\.\1 0666 [^ ]+ 0 rmail (.*)/)
{
$datafile = "$directory/D./D.$1";
$address = $2;
}
else
{
print STDERR;
die "Cannot parse previous line from $cfilename\n";
}
print "$SMAIL -R $system!$address < $datafile && $UUSTAT -k $jobid\n";
}
close UUSTAT;
}
close SHELL unless $verbose;
exit 0;

View File

@ -0,0 +1,321 @@
/* uusnap.c
(c) 1992 Heiko W.Rupp hwr@pilhuhn.ka.sub.org
uusnap is a tool to display the activities of the connected
systems.
Put a file uusnap.systems in NEWCONFIGDIR (see Makefile), in which
the systems, you want to monitor are listed, one on a single line.
The sequence of the files there determine the sequence of the
listing.
At the moment it only works with taylor config and taylor dirs
compile it form the Makefile or:
cc -c -g -pipe -O -I. -I. -DNEWCONFIGLIB=\"/usr/local/lib/uucp\" uusnap.c
cc -o uusnap uusnap.o
For this, uusnap.[ch] must be in the same directory as uucp.h and so.
uusnap must have read access to SPOOLDIR/.Status in order to work.
*/
#define MAXSYS 30 /* maximum number of systems */
#define WAIT_NORMAL 10 /* wait period if noone is talking */
#define WAIT_TALKING 2 /* refresh display every second if */
/* someone is talking with us */
#include "uucp.h"
#if USE_RCS_ID
char uusnap_rcsid[] = "$Id: uusnap.c,v 1.1 1993/08/04 19:31:43 jtc Exp $";
#endif
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/dir.h>
extern char *ctime(time_t*);
struct sysInfo {
char sysname[10]; /* name of the system to watch */
char *statfile; /* name of its status file */
char *spooldir; /* root of its spooldir */
int in; /* number of unprocessed in-files */
int out; /* number of files to send them */
time_t last; /* last poll time */
time_t next; /* time of next poll */
time_t lastidir; /* time of last in-spooldir access */
time_t lastodir; /* time of last outgoing spd acc */
time_t laststat; /* time of last status file access */
int status; /* status of the system */
int num_retries; /* number of retries */
};
struct sysInfo Systems[MAXSYS];
/* I have extend the system status. If time for the specified system
is Never, I say so. To get this to work, one also should extend
uucico.c. It is not important to do this. With the normal uucico,
one only gets no status.
*/
const char *azStatus[] = /* Status codes as defined by uucico */
{ /* listing them here instead of */
"Conversation complete", /* including the appropriate file */
"Port unavailable", /* reduces the size of the executable */
"Dial failed",
"Login failed",
"Handshake failed",
"Call failed",
"Talking",
"Wrong time to call",
"Time to call = Never !"
};
main()
{
int i;
i=get_systems();
display_info(i);
exit(0);
}
int
get_systems()
{
char filename[1024];
char fn[1024];
char line[80];
FILE *fp;
int i=0;
int j;
struct stat stbuf;
struct sysInfo sys;
strcpy(filename,NEWCONFIGLIB);
strcat(filename,"/uusnap.systems");
if ((fp=fopen(filename,"r"))!=NULL) {
while (fgets(line,80,fp)!=NULL) {
*(rindex(line,'\n'))='\0';
strcpy(sys.sysname,line); /* get the name of the system */
strcpy(fn,SPOOLDIR); /* get the name of the statusfile */
strcat(fn,"/.Status/");
strcat(fn,line);
sys.statfile=malloc(strlen(fn)+1);
strcpy(sys.statfile,fn);
strcpy(fn,SPOOLDIR); /* get the name of the spooldir */
strcat(fn,"/");
strcat(fn,line);
sys.spooldir=malloc(strlen(fn)+1);
strcpy(sys.spooldir,fn);
sys.laststat=0;
sys.lastidir=sys.lastodir=0;
Systems[i]=sys; /* get_stat_for_system needs it */
get_stat_for_system(i); /* now get the system status */
get_inq_num(i,TRUE); /* number of unprocessed files */
get_outq_num(i,TRUE); /* number of files to send */
i++;
}
fclose(fp);
}
else {
fprintf(stderr,"Can't open %s \n",filename);
exit(1);
}
return i;
}
display_info(int numSys)
{
char *filename;
int sysnum;
FILE *fp;
char contentline[80];
char isTalking=FALSE;
struct stat stbuf;
struct sysInfo sys;
time_t time;
filename = (char*)malloc(1024);
if (filename == NULL) {
fprintf(stderr, "Can't malloc 1024 bytes");
exit(1);
}
while(TRUE) {
display_headline();
for (sysnum=0;sysnum<numSys;sysnum++) {
sys = Systems[sysnum];
stat(sys.statfile,&stbuf);
if ((time=stbuf.st_atime) > sys.laststat) {
get_stat_for_system(sysnum);
}
if(display_status_line(sysnum)==1)
isTalking=TRUE;
}
if (isTalking) {
sleep(WAIT_TALKING);
isTalking = FALSE;
}
else
sleep(WAIT_NORMAL); /* wait a bit */
}
return 0;
}
int
display_status_line(int sn)
{
char *time_s;
int sys_stat,num_retries,wait;
int i;
time_t last_time;
time_t next_time;
struct sysInfo sys;
sys = Systems[sn];
printf("%10s ",sys.sysname);
get_inq_num(sn);
if (sys.in==0)
printf(" ");
else
printf("%3d ",sys.in);
get_outq_num(sn);
if (sys.out==0)
printf(" ");
else
printf("%3d ",sys.out);
time_s = ctime(&sys.last);
time_s = time_s + 11;
*(time_s+8)='\0';
printf("%8s ",time_s); /* time of last poll */
time_s = ctime(&sys.next);
time_s = time_s + 11;
*(time_s+8)='\0';
if (sys.last == sys.next)
printf(" ");
else
printf("%8s ",time_s); /* time of next poll */
if (sys.num_retries==0)
printf(" ");
else
printf("%2d ",sys.num_retries);
if (sys_stat==6) /* system is talking */
printf("\E[7m"); /* reverse video on */
printf("%s",azStatus[sys.status]);
if (sys.status==6) {
printf("\E[m\n"); /* reverse video off */
return 1;
}
else {
printf("\n");
return 0;
}
}
display_headline()
{
printf("\E[;H\E[2J"); /* clear screen */
printf("\E[7muusnap (press CTRL-C to escape)\E[m \n\n");
printf(" System #in #out last next #ret Status\n");
return 0;
}
get_inq_num(int num,char firstTime)
{
int i=0;
char filename[1024];
struct stat stbuf;
DIR *dirp;
strcpy(filename,Systems[num].spooldir);
strcat(filename,"/X./.");
stat(filename,&stbuf);
if ((stbuf.st_mtime > Systems[num].lastidir) || (firstTime)) {
if ((dirp=opendir(filename))!=NULL) {
while(readdir(dirp))
i++;
closedir(dirp);
stat(filename,&stbuf);
Systems[num].lastidir=stbuf.st_mtime;
}
else {
fprintf(stderr,"Can't open %s \n",filename);
exit(1);
}
if (i>=2)
i-=2; /* correct . and .. */
Systems[num].in=i;
}
return 0;
}
get_outq_num(int sys,char firstTime)
{
int i=0;
char filename[1024];
struct stat stbuf;
DIR *dirp;
strcpy(filename,Systems[sys].spooldir);
strcat(filename,"/C./.");
stat(filename,&stbuf);
if ((stbuf.st_mtime > Systems[sys].lastodir) || (firstTime)) {
if ((dirp=opendir(filename))!=NULL) {
while(readdir(dirp))
i++;
closedir(dirp);
stat(filename,&stbuf);
Systems[sys].lastodir=stbuf.st_mtime;
}
else {
fprintf(stderr,"Can't open %s \n",filename);
exit(1);
}
if (i>=2)
i-=2; /* correct . and .. */
Systems[sys].out=i;
}
return 0;
}
get_stat_for_system(int i)
{
char fn[80];
struct sysInfo sys;
struct stat stbuf;
FILE *fp;
time_t wait;
sys = Systems[i];
stat(sys.statfile,&stbuf);
if (stbuf.st_atime > sys.laststat) {
if ((fp=fopen(sys.statfile,"r"))!=NULL) {
fgets(fn,80,fp);
fclose(fp);
sscanf(fn,"%d %d %ld %d",
&sys.status,
&sys.num_retries,
&sys.last,
&wait);
sys.next=sys.last+wait;
}
else {
sys.status=0;
sys.num_retries=0;
sys.last=0;
sys.next=0;
}
stat(sys.statfile,&stbuf);
sys.laststat=stbuf.st_atime;
}
Systems[i] = sys;
return 0;
}

View File

@ -0,0 +1,203 @@
#!/usr/local/bin/perl
# uutraf.pl -- UUCP Traffic Analyzer
# SCCS Status : @(#)@ uutraf 1.7
# Author : Johan Vromans
# Created On : ***
# Last Modified By: Johan Vromans
# Last Modified On: Wed Feb 26 08:52:56 1992
# Update Count : 4
# Status : OK
# Requires: : Perl V4 or later
# Reads UUCP syslog, and generates a report from it.
#
# Created by Johan Vromans <jv@mh.nl>
# Loosely based on an idea by Greg Hackney (hack@texbell.swbt.com)
# Usage: uutraf [-taylor|-hdb|-bnu|-bsd] [syslog]
# Logfile formats:
#
# BSD:
#
# jv mhres (2/23-5:18) (698818735) received 135 b 2 secs
# root mhres (2/23-5:19) (698818742) sent 2365 b 3 secs, Pk: 38, Rxmt: 0
#
# HDB:
#
# uunet!uucp M (12/10-09:04:22) (C,16390,1) [ttyXX] <- 2371 / 5.000 secs, \
# 474 bytes/sec
#
# Taylor:
#
# jv mhres (1992-02-24 20:49:04.06) sent 16234 bytes in 148.780 seconds \
# (109 bytes/sec)
# jv mhres (1992-02-24 21:04:05.76) received 449 bytes in 6.550 seconds \
# (68 bytes/sec)
$uucp_type = "gnu";
%hosts = (); # hosts seen
%bytes_in = (); # of bytes received from host
%bytes_out = (); # of bytes sent to host
%secs_in = (); # of seconds connect for recving
%secs_out = (); # of seconds connect for sending
%files_in = (); # of input requests
%files_out = (); # of output requests
# read info, break the lines and tally
if ( $ARGV[0] =~ /^-/ ) {
($uucp_type = substr (shift (@ARGV), 1)) =~ tr/A-Z/a-z/;
}
if ( $uucp_type eq "taylor" || $uucp_type eq "gnu" ) {
@ARGV = ("/usr/spool/uucp/Stats") unless $#ARGV >= 0;
$pat = "^[^ ]+ ([^ ]+) \\(([-0-9:\\/ .]+)\\) " .
"(sent|received) (\\d+) bytes in (\\d+)\\.(\\d+) seconds";
$uucp_type = 0;
$recv = "received";
}
elsif ( $uucp_type eq "hdb" || $uucp_type eq "bnu" ) {
@ARGV = ("/usr/spool/uucp/.Admin/xferstats") unless $#ARGV >= 0;
$pat = "^([^!]+)![^(]+\\(([-0-9:\\/]+)\\).+([<>])-? " .
"(\\d+) \\/ (\\d+)\\.(\\d+) secs";
$uucp_type = 1;
$recv = "<";
}
elsif ( $uucp_type eq "bsd" || $uucp_type eq "v7" ) {
@ARGV = ("/usr/spool/uucp/SYSLOG") unless $#ARGV >= 0;
$pat = "^[^ ]+ ([^ ]+) \\(([-0-9:\\/]+)\\) \\([^)]+\\) " .
"(sent|received) (\\d+) b (\\d+) secs";
$uucp_type = 2;
$recv = "received";
}
else {
die ("Unknown UUCP type: $uucp_type\n");
}
$garbage = 0;
while ( <> ) {
unless ( /$pat/o ) {
print STDERR "Possible garbage: $_";
if ( $garbage++ > 10 ) {
die ("Too much garbage; wrong UUCP type?\n");
}
next;
}
# gather timestamps
$last_date = $2;
$first_date = $last_date unless defined $first_date;
# initialize new hosts
unless ( defined $hosts{$1} ) {
$hosts{$1} = $files_in{$1} = $files_out{$1} =
$bytes_in{$1} = $bytes_out{$1} =
$secs_in{$1} = $secs_out{$1} = 0;
}
# Taylor and HDB have milliseconds, BSD has not.
$secs = ($uucp_type == 2) ? ($5 + ($5 == 0 ? 0.5 : 0)) : ($5 + $6/1000);
# tally
if ( $3 eq $recv ) { # recv
$bytes_in{$1} += $4;
$files_in{$1}++;
$secs_in{$1} += $secs;
}
else { # xmit
$bytes_out{$1} += $4;
$files_out{$1}++;
$secs_out{$1} += $secs;
}
$garbage = 0;
}
@hosts = keys (%hosts);
die ("No info found, stopped\n") if $#hosts < 0;
################ report section ################
$thishost = &gethostname();
$thishost = (defined $thishost) ? "on node $thishost" : "report";
if ( $uucp_type eq 0 ) { # Taylor UUCP
substr ($first_date, 16) = "";
substr ($last_date, 16) = "";
}
format std_head =
@|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"UUCP traffic $thishost from $first_date to $last_date"
Remote -----------K-Bytes----------- ----Hours---- --Avg CPS-- --Files--
Host Recv Sent Total Recv Sent Recv Sent Recv Sent
.
format std_out =
@<<<<<<< @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>>> @>>>>> @>>>> @>>>> @>>> @>>>
$Zhost, $Zi_bytes, $Zo_bytes, $Zt_bytes, $Zi_hrs, $Zo_hrs, $Zi_acps, $Zo_acps, $Zi_count, $Zo_count
.
$^ = "std_head";
$~ = "std_out";
&print_dashes ();
reset "T"; # reset totals
foreach $host (@hosts) {
&print_line ($host, $bytes_in{$host}, $bytes_out{$host},
$secs_in{$host}, $secs_out{$host},
$files_in{$host}, $files_out{$host});
}
&print_dashes ();
&print_line ("Total", $Ti_bytes, $To_bytes,
$Ti_secs, $To_secs, $Ti_count, $To_count);
################ that's it ################
sub print_line {
reset "Z"; # reset print fields
local ($Zhost,
$Zi_bytes, $Zo_bytes,
$Zi_secs, $Zo_secs,
$Zi_count, $Zo_count) = @_;
$Ti_bytes += $Zi_bytes;
$To_bytes += $Zo_bytes;
$Zt_bytes = $Zi_bytes + $Zo_bytes;
$Tt_bytes += $Zt_bytes;
$Zi_acps = ($Zi_secs > 0) ? sprintf ("%.0f", $Zi_bytes/$Zi_secs) : "0";
$Zo_acps = ($Zo_secs > 0) ? sprintf ("%.0f", $Zo_bytes/$Zo_secs) : "0";
$Zi_bytes = sprintf ("%.1f", $Zi_bytes/1000);
$Zo_bytes = sprintf ("%.1f", $Zo_bytes/1000);
$Zt_bytes = sprintf ("%.1f", $Zt_bytes/1000);
$Zi_hrs = sprintf ("%.1f", $Zi_secs/3600);
$Zo_hrs = sprintf ("%.1f", $Zo_secs/3600);
$Ti_secs += $Zi_secs;
$To_secs += $Zo_secs;
$Ti_count += $Zi_count;
$To_count += $Zo_count;
write;
}
sub print_dashes {
$Zhost = $Zi_bytes = $Zo_bytes = $Zt_bytes =
$Zi_hrs = $Zo_hrs = $Zi_acps = $Zo_acps = $Zi_count = $Zo_count =
"------------";
write;
# easy, isn't it?
}
################ missing ################
sub gethostname {
$ENV{"SHELL"} = "/bin/sh";
$try = `uuname -l 2>/dev/null`;
chop $try;
return $+ if $try =~ /^[-.\w]+$/;
return undef;
}

View File

@ -0,0 +1,43 @@
#!/bin/sh
#
# This script was hacked together by Marc Evans (marc@Synergytics.Com)
# I claim no copyright to it and don't really care what people do
# with it, hence, it is public domain. I take no responsibility for
# for happens if you use this script, providing no warentee. This
# section of the comments may be removed if you so desire.
#
# Usage:
# uutry [-x#] systemname
# where '-x#' has the value [0-9], higher values providing more detail
#
# The following variables should be gropped from the configuration
# files rather then being hard coded here.
#
Spool=/usr/spool/uucp
Lib=/usr/lib/uucp
Status=$Spool/.Status
Debug=$Spool/Debug
Uucico=$lib/uucico
#
# Default option values
#
x="-x5"
s=""
for i in $* ; do
case $i in
-x*) x="$i" ;;
*) s="$i" ;;
esac
done
if [ $s != "" ]; then
rm -f $Status/$s
$Uucico -r1 $x -s$s &
>$Debug
tail -f $Debug
else
echo "Usage: uutry systemname"
exit 1
fi

View File

@ -0,0 +1,38 @@
/*
* *************
* * XC-CONF.H *
* *************
*
* Configuration file for xchat 1.1. Edit this file prior to make-ing
* xchat.
*
* History:
* Bob Denny - Tue Sep 1 11:42:54 1992
*/
/*
* Edit this to reflect the relative location of xchat sources to
* the main Taylor UUCP source directory. As distributed, xchat
* is in the ./contrib sub-directory under the main Taylor UUCP
* directory. Therefore, Taylor's conf.h is in our parent directory.
*/
#include "../conf.h"
/*
* The following definition establishes the default path to the
* scripts used by xchat. You may lleave this blank (""), but
* the command line given to xchat (e.g., in the 'sys' file entry)
* must specify a full (absolute) path name to the script to be
* executed. Normally, this is the same place you put your config
* and system files for UUCP.
*/
#define SCRIPT_DIR "/usr/local/conf/uucp/" /* MUST HAVE TRAILING "/" */
/*
* The following definition establishes the default path to the
* log files that are produced by the 'dbgfile' statement. Normally
* this is the same location you configured Taylor UUCP to put its
* log files.
*/
#define LOG_DIR "/usr/spool/uucp/" /* MUST HAVE TRAILING "/" */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,614 @@
.TH xchat 8
.SH NAME
xchat - Extended chat processor
.SH SYNOPSIS
.BI "xchat " "scriptfile"
.RI " [ " parameter... " ] "
.PP
where
.I scriptfile
is the name of a file containing an
.I xchat
script. If
.I scriptfile
begins with ``/'', then it is assumed to be a full path name for the
script file. If not, a configuration-dependent default directory path
(usually
.B "/usr/local/conf/uucp/"
) is prepended to the script file name. Normally, the default path
is the same as that for the Taylor UUCP configuration files.
.SH DESCRIPTION
.I Xchat
is a general-purpose dialing and login program designed for use
with Taylor UUCP as a ``chat-program'', taking the place (or
augmenting) the built-in chat scripting facility. It provides the
ability to closely control timeouts, multiple simultaneous ``expect''
strings with separate actions, extended terminal control, modem
command character pacing, and more.
.PP
When used in conjunction with Taylor UUCP's
configuration features,
.I xchat
can provide you the ability to manage the most intricate login,
dial and hangup needs. The scripts are written in a shell-like (well,
sort-of) style with labels, commands, and parameters, easing the task
of writing procedures for complex terminal communications situations.
.PP
Because
.I xchat
assumes that it is connected to the terminal device via stdin/stdout,
you can easily debug scripts by invoking it from the shell and
responding to the script from the keyboard. A debug logging facility
is included, with the debug output going to a separate user-specified
file. This makes it easy to debug connection problems without wading
through large
.I uucico
log and debug files.
.PP
Formally, a script describes a state machine;
.I xchat
interprets the script and does what the state machine
tells it to. This section will be much easier to understand
if you obtain listings of the script files supplied with
.I xchat.
.SH "SCRIPT FILE FORMAT"
Script files are ordinary text files containing comments, labels,
and statements. Blank lines are ignored.
Comments are denoted by leading ``#''
characters. Some statements (those which do not end with an
``extended string'' argument; see below) can also have trailing
comments.
.PP
.I Labels
begin in column one and are ended by colons (:). A label
specifies a state name. All lines between a pair of labels are
the statements for a single state.
.PP
Processing always begins at the head of the script (no leading
state name is necessary).
.PP
.I Statements
are divided into two categories, ``action'' and ``expect''.
When a state is entered, all of its actions are performed in the
order in which they appear in the file.
.PP
A
.I transition
to another state may occur for any of three reasons:
.IP (1) 5
One of the actions may cause a transition to
another state, in which case the rest of the
current state's actions are skipped.
Processing resumes with the first action
statement of the new state.
.IP (2) 5
If none of the actions cause a state
transition, and there are no expects in the
state, processing ``falls through'' to the next
state in the file.
.IP (3) 5
If none of the actions cause a state
transition, but there are expects in the
state, the state machine pauses until one of
the expects is ``satisfied''. It then transitions
to the state named in the expect
statement.
.PP
Finally, there are two action statements which, when executed,
cause the script to exit.
.SH "SCRIPT FILE STATEMENTS"
This section describes all of the statements that may appear in script
files, except for a few special action statements. Those are described
in a later section, ``Overriding Defaults''.
.PP
Some statements accept one or two arguments, referred to in the
following descriptions as
.IR int ", " ns ", " str ", or "
.IR xstr ", to"
indicate whether the argument is an integer, a new state name, a
string, or an ``extended string'' (described in a later section).
.PP
For all statements that accept two arguments, the first is the
name of a new state, and the second specifies a condition or
reason for changing to the new state.
.SS "Termination And Informational Statements"
These statements are used to place entries into the Taylor UUCP
.I Log
file, and to cause
.I xchat
to exit with successful or failure status. It is also possible to open a
separate
.I debug
log file and control the level of tracing and error reporting that will go
into that log file. This is very useful in debugging
.I xchat
scripts.
.br
.ta 1.0i 1.5i 2.0i
.TP 2.0i
.B failed
Exit script with ``failed'' status. This causes
.I xchat
to exit with status 0.
.TP 2.0i
.B success
Exit script with ``success'' status. This causes
.I xchat
to exit with status 1.
.TP 2.0i
.BI "log " xstr
Send informational message
.I xstr
to standard error. When used with Taylor UUCP, this is the
.I Log
file for the
.I uucico
program.
.TP 2.0i
.BI "logerr " xstr
Send message
.I xstr
to standard error, with ``ERROR:'' indicator. When used
with Taylor UUCP, this is the
.I Log
file for the
.I uucico
program.
.TP 2.0i
.BI "dbgfile " xstr
Open script debugging file
.I xstr.
If
.I xstr
begins with ``/'', it is assumed to be an absolute path name for the
debugging file. If not, then a configuration-dependent default directory
path (usually
.B "/usr/spool/uucp"
) is prepended to
.I xstr.
Normally the default path is that of the directory where Taylor UUCP
puts its log files.
The debugging file is used to capture a detailed log of the data sent
and received, errors encountered, and a trace of script execution.
The various types of logging are controlled by the
.I "debug mask,"
described next.
.B Note:
A new log file is created each time
.I xchat
runs. Use the
.B log
and
.B loge
commands to log
continuous information onto standard out, which is connected
to the Taylor UUCP
.I Log
file when
.I xchat
is run by the Taylor
.I uucico.
.TP 2.0i
.BI "dbgset " int
Set the bits specified in
.I int
in the debugging mask. The value in
.I int
is ``or''ed into the mask. Set bit 0 (value \= 1) for error messages,
bit 1 (value \= 2) for dial, login and init errors, bit 2 (value \= 4)
for dial, login and init trace with character I/O, and bit 3 (value \= 8)
for script processing internals. Normally, you will just turn it all on
with a value of 15.
.TP 2.0i
.BI "dbgclr " int
Clear the bits specified in
.I int
from the debugging mask.
.TP 2.0i
.BI "debug " xstr
Write
.I
xstr
into the debug log. The entry will be enclosed in angle brackets.
.TP 2.0i
.BI "debuge " xstr
Write
.I xstr
into the debug log with ``ERROR: '' prepended. The entry will be enclosed
in angle brackets.
.SS "Sending Data"
These statements are used to transmit data to standard out (the tty or TCP
port when used with Taylor UUCP).
.I
No implied carriage returns are sent.
You must include a \\r if you want a carriage return in the string
sent by the
.B send
command. If you want a return sent after
.B dial
or
.B sendstr,
you must send it with a separate
.B send
command.
.TP 2.0i
.B dial
Send the string previously set by the
.B telno
command to the serial port.
.B W
and
.B P
characters in the phone number are
converted as described under
.B
Dial Strings,
below. This statement also sets a default
timeout value, as described under the
.B timeout
statement.
.TP 2.0i
.BI "send " xstr
Send the string
.I xstr
to the serial port.
.TP 2.0i
.BI "sendstr " int
The argument of this statement is a digit from 0
through 7. Send the corresponding string
parameter as passed to
.I xchat
following the script file name. The parameter is interpreted
as an extended string.
.SS "Special Terminal Control Statements"
These statements are used to cause the terminal port to perform some special action, or to change the mode of the port.
.I
The modes of the port are restored to their original settings
.I
by xchat before it exits.
.TP 2.0i
.B flush
Flush the terminal port's input buffer.
.TP 2.0i
.B break
Send a break signal.
.TP 2.0i
.B hangup
Momentarily drop Data Terminal Ready (DTR) on the
serial port, causing the modem to hang up. (Not
usually needed, since
.I uucico
does this at the end of each call.)
.TP 2.0i
.B 7bit
Change the port to strip incoming characters to 7 bits.
.I
This is the default mode.
This mode
is implied when the port has parity enabled, since parity characters
are 7-bits wide.
.TP 2.0i
.B 8bit
Change the port to allow incoming 8-bit characters to be passed
to the script processor. This mode has no effect if parity is
enabled, since parity characters are 7-bits wide.
.TP 2.0i
.B nopar
Change the port to 8-bits, no parity.
.I
This is the default mode.
.TP 2.0i
.B evenpar
Change the port to 7-bits, even parity.
.I
Incoming characters with parity errors are discarded.
.TP 2.0i
.B oddpar
Change the port to 7-bits, odd parity.
.I
Incoming characters with parity errors are discarded.
.SS "Counting, Branching, Timing and Testing Statements"
These statements are used to control the flow of the
.I xchat
script itself, including branching, delays, and counter manipulation.
.TP 2.0i
.BI "sleep " int
Delay for
.I int
milliseconds.
.TP 2.0i
.B zero
Clear the counter.
.TP 2.0i
.B count
Add one to the counter.
.TP 2.0i
.BI "ifgtr " "ns int"
Go to state
.I ns
if counter greater than
.I int.
.TP 2.0i
.BI "goto " ns
Go to state
.I ns
unconditionally.
.TP 2.0i
.BI "ifstr " "ns int"
Go to state
.I ns
if string parameter
.I int
is nonempty.
.TP 2.0i
.BI "ifnstr " "ns int"
Go to state
.I ns
if string parameter
.I int
is empty.
.TP 2.0i
.BI "ifblind " ns
Change to state
.I ns
if the port is ``blind'' without carrier (CD) asserted.
.I
This is not yet implemented, the test always fails.
.TP 2.0i
.BI "ifblgtr " "ns int"
Change to state
.I ns
if the port is ``blind'' without carrier (CD) asserted, and counter
is greater then
.I int.
.I
This is not yet implemented, the test always fails.
.SS "Expect Statements"
Expect statements are usually the last statements that appear in a
given state, though in fact they can appear anywhere within the
state. Even if they appear at the beginning, the script processor
always does all of the action statements first. As a practical
matter, the order of these statements is not significant; they are
all interpreted ``in parallel''.
.TP 2.0i
.BI "expect " "ns xstr"
Change to state
.I ns
if the string specified by
.I xstr
is received from standard input (usually the serial port).
Case is significant, but high-order bits are not
checked.
.TP 2.0i
.BI "ifcarr " ns
Change to state
.I ns
if Carrier Detect (CD) is true.
.I
Not currently implemented. Always changes state.
.TP 2.0i
.BI "ifhang " ns
Change to state
.I ns
if a data set hangup occurs (SIGHUP signal received).
.TP 2.0i
.BI "timeout " "ns int"
Change to state
.I ns
if the time (in milliseconds)
given by
.I int
has elapsed without satisfying any
expects. If the time specified is 0, a default
timeout value (calculated from the length and
other characteristics of the most recent dial
string) is used.
.SH "SCRIPT PROCESSING DETAILS"
.SS "Extended Strings"
In the statements that accept string arguments, the strings are
interpreted as
.I
extended strings.
Extended strings begin with
the first nonblank character and continue, including all imbedded
and trailing blanks and other whitespace, until (but not
including) the end of the line in the script file. (There is no
provision for line continuation.) No trailing spaces should be
present between the last ``desired'' character of the string and the
end of the line, as they will be included in the stored string and
sent or expected, just as they appear in the script file. And,
obviously, no trailing comments are permitted! They will just be
stored as part of the string.
.PP
Within an extended string, the following ``escape sequences'' will
be converted as indicated before being sent or expected:
.br
.nf
.in +0.5i
\fB\\d\fR EOT character (control-D)
\fB\\N\fR null character
\fB\\n\fR line feed
\fB\\r\fR carriage return
\fB\\s\fR space
\fB\\t\fR tab
\fB\\\-\fR hyphen
\fB\\\\\fR backslash
\fB\\ooo\fR character with value ooo (in octal)
.in -0.5i
.fi
.PP
Since extended strings in scripts can include embedded spaces,
tabs, etc., these escape sequences are only required in strings
appearing in systems entries, though they may be used in script
files to improve readability.
.PP
The octal-character specification (\\ooo) may have from one to
three octal digits; it is terminated either after the third digit
or when a non-octal character is encountered. But if you want to
specify one of these followed by something that happens to be a
valid octal character (for example, a control-A followed by a 7)
make sure to include all three digits after the \\ . So \\0017
would become a control-A followed by the Ascii character ``7'', but
\\17 or \\017 would become a control-Y (decimal value 25). \\1S
would convert to a control-A followed by an ``S''.
.PP
Extended strings are stored without a trailing carriage return
unless one is explicitly present in the string (via \\r).
.SS "String Parameters"
The
.B sendstr
statement sends (after conversion from extended string
format) one of the parameters given on the
.I xchat
command line following the script file name.
The parameter is selected by the integer
argument of the statement.
.PP
This allows ``generic'' script files to serve
for many different systems; the string parameters
provide the phone number, username, password, etc. Character
substitutions described under ``extended strings'' above are
performed on these strings.
.PP
The ifstr and ifnstr statements allow further generality in script
files, by testing whether a particular parameter is present in the
systems entry. For example, a single script can be
used both for those systems that require a password and
those that do not. The password is specified as the last argument
in the
.xchat
command; the script can test for this
parameter's existence and skip the password sequence if
the parameter is empty.
.SS "``Wait'' And ``Pause'' Characters In Dial Strings"
An additional conversion is performed on dial strings. Dial strings
are interpreted as extended strings. Then the characters
.B W
and
.B P
within a dial string are interpreted as ``wait for dial
tone'' and ``pause'', and may be converted to other characters. By
default,
.B W
is left alone, and
.B P
is converted to a comma (,);
these are appropriate for Hayes-type modems. The script may
specify other substitutions (see below).
.PP
.B NOTE:
The Taylor UUCP documentation states that the ``wait'' and ``pause''
characters are ``='' and ``-'', respectively. These are actual characters
understood by some modems. When using
.I xchat
you should put
.B W
and
.B P
in the dial strings you specify in the Taylor configuration files.
This way, the
.I xchat
processor can make the substitution appropriate for the particular
modem in use. Make a separate
.I xchat
script for each modem type, e.g.,
.I "dial.hayes"
and specify the translation there. This way, the phone number strings
in the Taylor configuration files can be used with a variety of modems.
.SS "Default Timeouts For Dial Strings"
When a
.B dial
statement is executed, a default timeout value is set.
This is the timeout value used by a subsequent timeout statement
if the statement specifies a timeout value of 0.
.PP
The default timeout is given by:
.br
.nf
.in +2
\fIctime\fR + (\fIndigits\fR * \fIdgttime\fR) + (\fInwchar\fR * \fIwtime\fR) + (\fInpchar\fR * \fI ptime\fR)
.in -2
.fi
.PP
where
.I
ndigits, nwchar,
and
.I npchar
are the number of digits, wait characters, and pause characters in
the dial string, and
.I ctime, dgttime, wtime,
and
.I ptime
are 45 seconds, 0.1 seconds, 10 seconds, and 2 seconds,
respectively.
All of these times may be changed as specified below under
``Overriding Defaults.''
.SS "Trailing Carriage Returns Not Assumed"
In the
.B dial
and
.B sendstr
statements, the dial string or
parameter is sent with no trailing carriage return;
if a carriage return must be sent after one of these, a separate
send statement must provide it.
.SH "OVERRIDING DEFAULTS"
The script processor sets several default values. The following
statements, which override these defaults, may be useful in
certain circumstances.
.TP 2.0i
.BI "chrdly " int
Since many modems cannot accept dialing commands
at full ``computer speed'', the script processor
sends all strings with a brief inter-character
delay. This statement specifies the delay time,
in milliseconds. The default is 100 (0.1 second).
.TP 2.0i
.BI "pchar " str
Specifies the character to which
.BR P s
in the
dial string should be converted. Default is
``,'', for use with Hayes-type modems.
.TP 2.0i
.BI "ptime " int
Specifies the time, in milliseconds, to allow in
the default timeout for each pause character in
the dial string. Default is 2000 (2 seconds).
.TP 2.0i
.BI "wchar " str
Specifies the character to which
.BR W s
in the
dial string should be converted. Default is
``W'', for Hayes modems.
.TP 2.0i
.BI "wtime " int
Specifies the time, in milliseconds, to allow in
the default timeout for each wait-for-dialtone
character in the dial string. Default is 10000
(10 seconds).
.TP 2.0i
.BI "dgttime " int
Specifies the time, in milliseconds, to allow in
the default timeout for each digit character in
the dial string. Default is 100 (0.1 second).
.TP 2.0i
.BI "ctime " int
Specifies the time, in milliseconds, to allow in
the default timeout for carrier to appear after
the dial string is sent. Default is 45000 (45
seconds).
.SH "SEE ALSO"
uucico(8) for Taylor UUCP, and documentation for Taylor UUCP.
.SH AUTHOR
Robert B. Denny (denny@alisa.com)
.SH HISTORY
This program is an adaptation of the dial/login script processing
code that is a part of DECUS UUCP for VAX/VMS, written by Jamie
Hanrahan, et. al.
.SH BUGS
This version (1.1) does not support BSD terminal facilities. Anyone
volunteer to add this?

View File

@ -0,0 +1,16 @@
# Makefile for cu
# $Id: Makefile,v 1.2 1993/08/05 16:14:45 jtc Exp $
BINDIR= $(bindir)
BINOWN= $(owner)
BINMODE= 4555
PROG= cu
SRCS= cu.c prot.c log.c chat.c conn.c tcp.c tli.c copy.c
LDADD+= $(LIBUNIX) $(LIBUUCONF) $(LIBUUCP)
DPADD+= $(LIBUNIX) $(LIBUUCONF) $(LIBUUCP)
CFLAGS+= -I$(.CURDIR)/../common_sources\
-DVERSION=\"$(VERSION)\"
.include <bsd.prog.mk>
.PATH: $(.CURDIR)/../common_sources

286
gnu/libexec/uucp/cu/cu.1 Normal file
View File

@ -0,0 +1,286 @@
''' $Id: cu.1,v 1.1 1993/08/04 19:31:53 jtc Exp $
.TH cu 1 "Taylor UUCP 1.04"
.SH NAME
cu \- Call up another system
.SH SYNOPSIS
.B cu
[ options ] [ system | phone | "dir" ]
.SH DESCRIPTION
The
.I cu
command is used to call up another system and act as a dial in
terminal. It can also do simple file transfers with no error
checking.
.I cu
takes a single argument, besides the options. If the argument is the
string "dir" cu will make a direct connection to the port. This may
only be used by users with write access to the port, as it permits
reprogramming the modem.
Otherwise, if the argument begins with a digit, it is taken to be a
phone number to call. Otherwise, it is taken to be the name of a
system to call. The
.B \-z
option may be used to name a system beginning with a digit, and the
.B \-c
option may be used to name a phone number that does not begin with a
digit.
.I cu
locates a port to use in the UUCP configuration files. If a simple
system name is given, it will select a port appropriate for that
system. The
.B \-p, \-l
and
.B \-s
options may be used to control the port selection.
When a connection is made to the remote system,
.I cu
forks into two processes. One reads from the port and writes to the
terminal, while the other reads from the terminal and writes to the
port.
.I cu
provides several commands that may be used during the conversation.
The commands all begin with an escape character, initially
.B ~
(tilde). The escape character is only recognized at the beginning of
a line. To send an escape character to the remote system at the start
of a line, it must be entered twice. All commands are either a single
character or a word beginning with
.B %
(percent sign).
.I cu
recognizes the following commands:
.TP 5
.B ~.
Terminate the conversation.
.TP 5
.B ~! command
Run command in a shell. If command is empty, starts up a shell.
.TP 5
.B ~$ command
Run command, sending the standard output to the remote system.
.TP 5
.B ~| command
Run command, taking the standard input from the remote system.
.TP 5
.B ~+ command
Run command, taking the standard input from the remote system and
sending the standard output to the remote system.
.TP 5
.B ~#, ~%break
Send a break signal, if possible.
.TP 5
.B ~c directory, ~%cd directory
Change the local directory.
.TP 5
.B ~> file
Send a file to the remote system. This just dumps the file over the
communication line. It is assumed that the remote system is expecting
it.
.TP 5
.B ~<
Receive a file from the remote system. This prompts for the local
file name and for the remote command to execute to begin the file
transfer. It continues accepting data until the contents of the
.B eofread
variable are seen.
.TP 5
.B ~p from to, ~%put from to
Send a file to a remote Unix system. This runs the appropriate
commands on the remote system.
.TP 5
.B ~t from to, ~%take from to
Retrieve a file from a remote Unix system. This runs the appropriate
commands on the remote system.
.TP 5
.B ~s variable value
Set a
.I cu
variable to the given value. If value is not given, the variable is
set to
.B true.
.TP 5
.B ~! variable
Set a
.I cu
variable to
.B false.
.TP 5
.B ~z
Suspend the cu session. This is only supported on some systems. On
systems for which ^Z may be used to suspend a job,
.B ~^Z
will also suspend the session.
.TP 5
.B ~%nostop
Turn off XON/XOFF handling.
.TP 5
.B ~%stop
Turn on XON/XOFF handling.
.TP 5
.B ~v
List all the variables and their values.
.TP 5
.B ~?
List all commands.
.I cu
also supports several variables. They may be listed with the
.B ~v
command, and set with the
.B ~s
or
.B ~!
commands.
.TP 5
.B escape
The escape character. Initially
.B ~
(tilde).
.TP 5
.B delay
If this variable is true,
.I cu
will delay for a second after recognizing the escape character before
printing the name of the local system. The default is true.
.TP 5
.B eol
The list of characters which are considered to finish a line. The
escape character is only recognized after one of these is seen. The
default is carriage return, ^U, ^C, ^O, ^D, ^S, ^Q, ^R.
.TP 5
.B binary
Whether to transfer binary data when sending a file. If this is
false, then newlines in the file being sent are converted to carriage
returns. The default is false.
.TP 5
.B binary-prefix
A string used before sending a binary character in a file transfer, if
the
.B binary
variable is true. The default is ^Z.
.TP 5
.B echo-check
Whether to check file transfers by examining what the remote system
echoes back. This probably doesn't work very well. The default is
false.
.TP 5
.B echonl
The character to look for after sending each line in a file. The
default is carriage return.
.TP 5
.B timeout
The timeout to use, in seconds, when looking for a character, either
when doing echo checking or when looking for the
.B echonl
character. The default is 30.
.TP 5
.B kill
The character to use delete a line if the echo check fails. The
default is ^U.
.TP 5
.B resend
The number of times to resend a line if the echo check continues to
fail. The default is 10.
.TP 5
.B eofwrite
The string to write after sending a file with the
.B ~>
command. The default is ^D.
.TP 5
.B eofread
The string to look for when receiving a file with the
.B ~<
command. The default is $, which is intended to be a typical shell
prompt.
.TP 5
.B verbose
Whether to print accumulated information during a file transfer. The
default is true.
.SH OPTIONS
The following options may be given to
.I cu.
.TP 5
.B \-e
Use even parity.
.TP 5
.B \-o
Use odd parity. If both
.B \-e
and
.B \-o
are used, no parity is used. Otherwise the default parity of the line
is used.
.TP 5
.B \-h
Echo characters locally (half-duplex mode).
.TP 5
.B \-z system
The system to call.
.TP 5
.B \-c phone-number
The phone number to call.
.TP 5
.B \-p port
Name the port to use.
.TP 5
.B \-a port
Equivalent to
.B \-p port.
.TP 5
.B \-l line
Name the line to use by giving a device name. This may be used to
dial out on ports that are not listed in the UUCP configuration files.
Write access to the device is required.
.TP 5
.B \-s speed
The speed (baud rate) to use.
.TP 5
.B \-#
Where # is a number, equivalent to
.B \-s #.
.TP 5
.B \-n
Prompt for the phone number to use.
.TP 5
.B \-d
Enter debugging mode. Equivalent to
.B \-x all.
.TP 5
.B \-x type
Turn on particular debugging types. The following types are
recognized: abnormal, chat, handshake, uucp-proto, proto, port,
config, spooldir, execute, incoming, outgoing. Only abnormal, chat,
handshake, port, config, incoming and outgoing are meaningful for
.I cu.
Multiple types may be given, separated by commas, and the
.B \-x
option may appear multiple times. A number may also be given, which
will turn on that many types from the foregoing list; for example,
.B \-x 2
is equivalent to
.B \-x abnormal,chat.
.B \-x all
may be used to turn on all debugging options.
.TP 5
.B \-I file
Set configuration file to use. This option may not be available,
depending upon how
.I cu
was compiled.
.SH BUGS
This program does not work very well.
.SH FILES
The file name may be changed at compilation time, so this is only an
approximation.
.br
/usr/lib/uucp/config - Configuration file.

2068
gnu/libexec/uucp/cu/cu.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,76 @@
Makefile.in
MANIFEST
access.c
addbas.c
app3.c
app4.c
basnam.c
bytfre.c
chmod.c
cohtty.c
cwd.c
cusub.c
detach.c
dirent.c
dup2.c
efopen.c
epopen.c
exists.c
filnam.c
fsusg.c
fsusg.h
ftw.c
getcwd.c
indir.c
init.c
isdir.c
isfork.c
iswait.c
jobid.c
lcksys.c
link.c
locfil.c
lock.c
loctim.c
mail.c
mkdir.c
mkdirs.c
mode.c
move.c
opensr.c
pause.c
picksb.c
portnm.c
proctm.c
recep.c
remove.c
rename.c
rmdir.c
run.c
seq.c
serial.c
signal.c
sindir.c
size.c
sleep.c
splcmd.c
splnam.c
spool.c
spawn.c
srmdir.c
statsb.c
status.c
strerr.c
time.c
tmpfil.c
trunc.c
uacces.c
ufopen.c
ultspl.c
unknwn.c
uuto.c
walk.c
wldcrd.c
work.c
xqtfil.c
xqtsub.c

View File

@ -0,0 +1,22 @@
# This subdirectory contains Unix specific support functions.
# $Id: Makefile,v 1.2 1993/08/05 16:14:51 jtc Exp $
LIB= unix
SRCS= access.c addbas.c app3.c app4.c basnam.c bytfre.c cwd.c \
chmod.c cohtty.c cusub.c detach.c efopen.c epopen.c exists.c \
filnam.c fsusg.c indir.c init.c isdir.c isfork.c iswait.c \
jobid.c lcksys.c link.c locfil.c lock.c loctim.c mail.c \
mkdirs.c mode.c move.c opensr.c pause.c picksb.c portnm.c \
proctm.c recep.c run.c seq.c serial.c signal.c sindir.c size.c \
sleep.c spawn.c splcmd.c splnam.c spool.c srmdir.c statsb.c \
status.c time.c tmpfil.c trunc.c uacces.c ufopen.c ultspl.c \
unknwn.c uuto.c walk.c wldcrd.c work.c xqtfil.c xqtsub.c ftw.c
CFLAGS+= -I$(.CURDIR)/../common_sources \
-DOWNER=\"$(owner)\" -DSBINDIR=\"$(sbindir)\"
NOMAN= noman
NOPROFILE= noprofile
install:
.include <bsd.lib.mk>

View File

@ -0,0 +1,83 @@
/* access.c
Check access to files by the user and by the daemon. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
/* See if the user has access to a file, to prevent the setuid uucp
and uux programs handing out unauthorized access. */
boolean
fsysdep_access (zfile)
const char *zfile;
{
if (access (zfile, R_OK) == 0)
return TRUE;
ulog (LOG_ERROR, "%s: %s", zfile, strerror (errno));
return FALSE;
}
/* See if the daemon has access to a file. This is called if a file
is not being transferred to the spool directory, since if the
daemon does not have access the later transfer will fail. We
assume that the daemon will have the same euid (or egid) as the one
we are running under. If our uid (gid) and euid (egid) are the
same, we assume that we have access. Note that is not important
for security, since the check will be (implicitly) done again when
the daemon tries to transfer the file. This routine should work
whether the UUCP programs are installed setuid or setgid. */
boolean
fsysdep_daemon_access (zfile)
const char *zfile;
{
struct stat s;
uid_t ieuid, iuid, iegid, igid;
boolean fok;
ieuid = geteuid ();
if (ieuid == 0)
return TRUE;
iuid = getuid ();
iegid = getegid ();
igid = getgid ();
/* If our effective uid and gid are the same as our real uid and
gid, we assume the daemon will have access to the file. */
if (ieuid == iuid && iegid == igid)
return TRUE;
if (stat ((char *) zfile, &s) != 0)
{
ulog (LOG_ERROR, "stat (%s): %s", zfile, strerror (errno));
return FALSE;
}
/* If our euid is not our uid, but it is the file's uid, see if the
owner has read access. Otherwise, if our egid is not our gid,
but it is the file's gid, see if the group has read access.
Otherwise, see if the world has read access. We know from the
above check that at least one of our euid and egid are different,
so that is the only one we want to check. This check could fail
if the UUCP programs were both setuid and setgid, but why would
they be? */
if (ieuid != iuid && ieuid == s.st_uid)
fok = (s.st_mode & S_IRUSR) != 0;
else if (iegid != igid && iegid == s.st_gid)
fok = (s.st_mode & S_IRGRP) != 0;
else
fok = (s.st_mode & S_IROTH) != 0;
if (! fok)
{
ulog (LOG_ERROR, "%s: cannot be read by daemon", zfile);
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,50 @@
/* addbas.c
If we have a directory, add in a base name. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
/* If we have a directory, add a base name. */
char *
zsysdep_add_base (zfile, zname)
const char *zfile;
const char *zname;
{
size_t clen;
const char *zlook;
char *zfree;
char *zret;
#if DEBUG > 0
if (*zfile != '/')
ulog (LOG_FATAL, "zsysdep_add_base: %s: Can't happen", zfile);
#endif
clen = strlen (zfile);
if (zfile[clen - 1] != '/')
{
if (! fsysdep_directory (zfile))
return zbufcpy (zfile);
zfree = NULL;
}
else
{
/* Trim out the trailing '/'. */
zfree = zbufcpy (zfile);
zfree[clen - 1] = '\0';
zfile = zfree;
}
zlook = strrchr (zname, '/');
if (zlook != NULL)
zname = zlook + 1;
zret = zsysdep_in_dir (zfile, zname);
ubuffree (zfree);
return zret;
}

View File

@ -0,0 +1,29 @@
/* app3.c
Stick two directories and a file name together. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
char *
zsappend3 (zdir1, zdir2, zfile)
const char *zdir1;
const char *zdir2;
const char *zfile;
{
size_t cdir1, cdir2, cfile;
char *zret;
cdir1 = strlen (zdir1);
cdir2 = strlen (zdir2);
cfile = strlen (zfile);
zret = zbufalc (cdir1 + cdir2 + cfile + 3);
memcpy (zret, zdir1, cdir1);
memcpy (zret + cdir1 + 1, zdir2, cdir2);
memcpy (zret + cdir1 + cdir2 + 2, zfile, cfile);
zret[cdir1] = '/';
zret[cdir1 + cdir2 + 1] = '/';
zret[cdir1 + cdir2 + cfile + 2] = '\0';
return zret;
}

View File

@ -0,0 +1,33 @@
/* app4.c
Stick three directories and a file name together. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
char *
zsappend4 (zdir1, zdir2, zdir3, zfile)
const char *zdir1;
const char *zdir2;
const char *zdir3;
const char *zfile;
{
size_t cdir1, cdir2, cdir3, cfile;
char *zret;
cdir1 = strlen (zdir1);
cdir2 = strlen (zdir2);
cdir3 = strlen (zdir3);
cfile = strlen (zfile);
zret = zbufalc (cdir1 + cdir2 + cdir3 + cfile + 4);
memcpy (zret, zdir1, cdir1);
memcpy (zret + cdir1 + 1, zdir2, cdir2);
memcpy (zret + cdir1 + cdir2 + 2, zdir3, cdir3);
memcpy (zret + cdir1 + cdir2 + cdir3 + 3, zfile, cfile);
zret[cdir1] = '/';
zret[cdir1 + cdir2 + 1] = '/';
zret[cdir1 + cdir2 + cdir3 + 2] = '/';
zret[cdir1 + cdir2 + cdir3 + cfile + 3] = '\0';
return zret;
}

View File

@ -0,0 +1,22 @@
/* basnam.c
Get the base name of a file. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
/* Get the base name of a file name. */
char *
zsysdep_base_name (zfile)
const char *zfile;
{
const char *z;
z = strrchr (zfile, '/');
if (z != NULL)
return zbufcpy (z + 1);
return zbufcpy (zfile);
}

View File

@ -0,0 +1,19 @@
/* bytfre.c
Get the number of bytes free on a file system. */
#include "uucp.h"
#include "system.h"
#include "sysdep.h"
#include "fsusg.h"
long
csysdep_bytes_free (zfile)
const char *zfile;
{
struct fs_usage s;
if (get_fs_usage ((char *) zfile, (char *) NULL, &s) < 0)
return -1;
return s.fsu_bavail * (long) 512;
}

View File

@ -0,0 +1,25 @@
/* chmod.c
Change the mode of a file. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
/* Change the mode of a file. */
boolean
fsysdep_change_mode (zfile, imode)
const char *zfile;
unsigned int imode;
{
if (chmod ((char *) zfile, imode) < 0)
{
ulog (LOG_ERROR, "chmod (%s): %s", zfile, strerror (errno));
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,244 @@
/* Coherent tty locking support. This file was contributed by Bob
Hemedinger <bob@dalek.mwc.com> of Mark Williams Corporation and
lightly edited by Ian Lance Taylor. */
/* The bottom part of this file is lock.c.
* This is a hacked lock.c. A full lock.c can be found in the libmisc sources
* under /usr/src/misc.tar.Z.
*
* These are for checking for the existence of locks:
* lockexist(resource)
* lockttyexist(ttyname)
*/
#include "uucp.h"
#if HAVE_COHERENT_LOCKFILES
/* cohtty.c: Given a serial device name, read /etc/ttys and determine if
* the device is already enabled. If it is, disable the
* device and return a string so that it can be re-enabled
* at the completion of the uucico session as part of the
* function that resets the serial device before uucico
* terminates.
*
*/
#include "uudefs.h"
#include "sysdep.h"
#include <ctype.h>
#include <access.h>
/* fscoherent_disable_tty() is a COHERENT specific function. It takes the name
* of a serial device and then scans /etc/ttys for a match. If it finds one,
* it checks the first field of the entry. If it is a '1', then it will disable
* the port and set a flag. The flag will be checked later when uucico wants to
* reset the serial device to see if the device needs to be re-enabled.
*/
boolean
fscoherent_disable_tty (zdevice, pzenable)
const char *zdevice;
char **pzenable;
{
struct ttyentry{ /* this is an /etc/ttys entry */
char enable_disable[1];
char remote_local[1];
char baud_rate[1];
char tty_device[16];
};
struct ttyentry sought_tty;
int x,y,z; /* dummy */
FILE * infp; /* this will point to /etc/ttys */
char disable_command[66]; /* this will be the disable command
* passed to the system.
*/
char enable_device[16]; /* this will hold our device name
* to enable.
*/
*pzenable = NULL;
strcpy(enable_device,""); /* initialize our strings */
strcpy(sought_tty.tty_device,"");
if( (infp = fopen("/etc/ttys","r")) == NULL){
ulog(LOG_ERROR,"Error: check_disable_tty: failed to open /etc/ttys\n");
return FALSE;
}
while (NULL !=(fgets(&sought_tty, sizeof (sought_tty), infp ))){
sought_tty.tty_device[strlen(sought_tty.tty_device) -1] = '\0';
strcpy(enable_device,sought_tty.tty_device);
/* we must strip away the suffix to the com port name or
* we will never find a match. For example, if we are passed
* /dev/com4l to call out with and the port is already enabled,
* 9/10 the port enabled will be com4r. After we strip away the
* suffix of the port found in /etc/ttys, then we can test
* if the base port name appears in the device name string
* passed to us.
*/
for(z = strlen(sought_tty.tty_device) ; z > 0 ; z--){
if(isdigit(sought_tty.tty_device[z])){
break;
}
}
y = strlen(sought_tty.tty_device);
for(x = z+1 ; x <= y; x++){
sought_tty.tty_device[x] = '\0';
}
/* ulog(LOG_NORMAL,"found device {%s}\n",sought_tty.tty_device); */
if(strstr(zdevice, sought_tty.tty_device)){
if(sought_tty.enable_disable[0] == '1'){
ulog(LOG_NORMAL, "coh_tty: Disabling device %s {%s}\n",
zdevice, sought_tty.tty_device);
sprintf(disable_command, "/etc/disable %s",enable_device);
{
pid_t ipid;
const char *azargs[3];
int aidescs[3];
azargs[0] = "/etc/disable";
azargs[1] = enable_device;
azargs[2] = NULL;
aidescs[0] = SPAWN_NULL;
aidescs[1] = SPAWN_NULL;
aidescs[2] = SPAWN_NULL;
ipid = ixsspawn (azargs, aidescs, TRUE,
FALSE,
(const char *) NULL, TRUE,
TRUE,
(const char *) NULL,
(const char *) NULL,
(const char *) NULL);
if (ipid < 0)
x = 1;
else
x = ixswait ((unsigned long) ipid,
(const char *) NULL);
}
*pzenable = zbufalc (sizeof "/dev/"
+ strlen (enable_device));
sprintf(*pzenable,"/dev/%s", enable_device);
/* ulog(LOG_NORMAL,"Enable string is {%s}",*pzenable); */
return(x==0? TRUE : FALSE); /* disable either failed
or succeded */
}else{
return FALSE; /* device in tty entry not enabled */
}
}
}
return FALSE; /* no ttys entry found */
}
/* The following is COHERENT 4.0 specific. It is used to test for any
* existing lockfiles on a port which would have been created by init
* when a user logs into a port.
*/
#define LOCKSIG 9 /* Significant Chars of Lockable Resources. */
#define LOKFLEN 64 /* Max Length of UUCP Lock File Name. */
#define LOCKPRE "LCK.."
#define PIDLEN 6 /* Maximum length of string representing a pid. */
#ifndef LOCKDIR
#define LOCKDIR SPOOLDIR
#endif
/* There is a special version of DEVMASK for the PE multiport driver
* because of the peculiar way it uses the minor device number. For
* all other drivers, the lower 5 bits describe the physical port--
* the upper 3 bits give attributes for the port.
*/
#define PE_DRIVER 21 /* Major device number for the PE driver. */
#define PE_DEVMASK 0x3f /* PE driver minor device mask. */
#define DEVMASK 0x1f /* Minor device mask. */
/*
* Generates a resource name for locking, based on the major number
* and the lower 4 bits of the minor number of the tty device.
*
* Builds the name in buff as two "." separated decimal numbers.
* Returns NULL on failure, buff on success.
*/
static char *
gen_res_name(path, buff)
char *path;
char *buff;
{
struct stat sbuf;
int status;
if (0 != (status = stat(path, &sbuf))) {
/* Can't stat the file. */
return (NULL);
}
if (PE_DRIVER == major(sbuf.st_rdev)) {
sprintf(buff, "%d.%d", major(sbuf.st_rdev),
PE_DEVMASK & minor(sbuf.st_rdev));
} else {
sprintf(buff, "%d.%d", major(sbuf.st_rdev),
DEVMASK & minor(sbuf.st_rdev));
}
return(buff);
} /* gen_res_name */
/*
* lockexist(resource) char *resource;
*
* Test for existance of a lock on the given resource.
*
* Returns: (1) Resource is locked.
* (0) Resource is not locked.
*/
static boolean
lockexist(resource)
const char *resource;
{
char lockfn[LOKFLEN];
if ( resource == NULL )
return(0);
sprintf(lockfn, "%s/%s%.*s", LOCKDIR, LOCKPRE, LOCKSIG, resource);
return (!access(lockfn, AEXISTS));
} /* lockexist() */
/*
* lockttyexist(ttyname) char *ttyname;
*
* Test for existance of a lock on the given tty.
*
* Returns: (1) Resource is locked.
* (0) Resource is not locked.
*/
boolean
lockttyexist(ttyn)
const char *ttyn;
{
char resource[LOKFLEN];
char filename[LOKFLEN];
sprintf(filename, "/dev/%s", ttyn);
if (NULL == gen_res_name(filename, resource)){
return(0); /* Non-existent tty can not be locked :-) */
}
return(lockexist(resource));
} /* lockttyexist() */
#endif /* HAVE_COHERENT_LOCKFILES */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/* cwd.c
Routines dealing with the current working directory. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
/* See whether running this file through zsysdep_add_cwd would require
knowing the current working directory. This is used to avoid
determining the cwd if it will not be needed. */
boolean
fsysdep_needs_cwd (zfile)
const char *zfile;
{
return *zfile != '/' && *zfile != '~';
}
/* Expand a local file, putting relative pathnames in the current
working directory. Note that ~/file is placed in the public
directory, rather than in the user's home directory. This is
consistent with other UUCP packages. */
char *
zsysdep_local_file_cwd (zfile, zpubdir)
const char *zfile;
const char *zpubdir;
{
if (*zfile == '/')
return zbufcpy (zfile);
else if (*zfile == '~')
return zsysdep_local_file (zfile, zpubdir);
else
return zsysdep_add_cwd (zfile);
}
/* Add the current working directory to a remote file name. */
char *
zsysdep_add_cwd (zfile)
const char *zfile;
{
if (*zfile == '/' || *zfile == '~')
return zbufcpy (zfile);
if (zScwd == NULL)
{
ulog (LOG_ERROR, "Can't determine current directory");
return NULL;
}
return zsysdep_in_dir (zScwd, zfile);
}

View File

@ -0,0 +1,186 @@
/* detach.c
Detach from the controlling terminal.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "system.h"
#include "sysdep.h"
#include <errno.h>
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef TIOCNOTTY
#define HAVE_TIOCNOTTY 1
#else
#define HAVE_TIOCNOTTY 0
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
/* Detach from the controlling terminal. This is called by uucico if
it is calling out to another system, so that it can receive SIGHUP
signals from the port it calls out on. It is also called by uucico
just before it starts uuxqt, so that uuxqt is completely
independent of the terminal. */
void
usysdep_detach ()
{
#if ! HAVE_BSD_PGRP || ! HAVE_TIOCNOTTY
pid_t igrp;
/* First make sure we are not a process group leader. If we have
TIOCNOTTY, this doesn't matter, since TIOCNOTTY sets our process
group to 0 anyhow. */
#if HAVE_BSD_PGRP
igrp = getpgrp (0);
#else
igrp = getpgrp ();
#endif
if (igrp == getpid ())
{
boolean fignored;
pid_t ipid;
/* Ignore SIGHUP, since our process group leader is about to
die. */
usset_signal (SIGHUP, SIG_IGN, FALSE, &fignored);
ipid = ixsfork ();
if (ipid < 0)
ulog (LOG_FATAL, "fork: %s", strerror (errno));
if (ipid != 0)
_exit (EXIT_SUCCESS);
/* We'll always wind up as a child of process number 1, right?
Right? We have to wait for our parent to die before
reenabling SIGHUP. */
while (getppid () != 1)
sleep (1);
ulog_id (getpid ());
/* Restore SIGHUP catcher if it wasn't being ignored. */
if (! fignored)
usset_signal (SIGHUP, ussignal, TRUE, (boolean *) NULL);
}
#endif /* ! HAVE_BSD_PGRP || ! HAVE_TIOCNOTTY */
#if HAVE_TIOCNOTTY
/* Lose the original controlling terminal. If standard input has
been reopened to /dev/null, this will do no harm. If another
port has been opened to become the controlling terminal, it
should have been detached when it was closed. */
(void) ioctl (0, TIOCNOTTY, (char *) NULL);
#endif
/* Close stdin, stdout and stderr and reopen them on /dev/null, to
make sure we have no connection at all to the terminal. */
(void) close (0);
(void) close (1);
(void) close (2);
if (open ((char *) "/dev/null", O_RDONLY) != 0
|| open ((char *) "/dev/null", O_WRONLY) != 1
|| open ((char *) "/dev/null", O_WRONLY) != 2)
ulog (LOG_FATAL, "open (/dev/null): %s", strerror (errno));
#if HAVE_BSD_PGRP
/* Make sure our process group ID is set to 0. On BSD TIOCNOTTY
should already have set it 0, so this will do no harm. On System
V we presumably did not execute the TIOCNOTTY call, but the
System V setpgrp will detach the controlling terminal anyhow.
This lets us use the same code on both BSD and System V, provided
it compiles correctly, which life easier for the configure
script. We don't output an error if we got EPERM because some
BSD variants don't permit this usage of setpgrp (which means they
don't provide any way to pick up a new controlling terminal). */
if (setpgrp (0, 0) < 0)
{
if (errno != EPERM)
ulog (LOG_ERROR, "setpgrp: %s", strerror (errno));
}
#else /* ! HAVE_BSD_PGRP */
#if HAVE_SETSID
/* Under POSIX the setsid call creates a new session for which we
are the process group leader. It also detaches us from our
controlling terminal. I'm using the BSD setpgrp call first
because they should be equivalent for my purposes, but it turns
out that on Ultrix 4.0 setsid prevents us from ever acquiring
another controlling terminal (it does not change our process
group, and Ultrix 4.0 prevents us from setting our process group
to 0). */
(void) setsid ();
#else /* ! HAVE_SETSID */
#if HAVE_SETPGRP
/* Now we assume we have the System V setpgrp, which takes no
arguments, and we couldn't compile the HAVE_BSD_PGRP code above
because there was a prototype somewhere in scope. On System V
setpgrp makes us the leader of a new process group and also
detaches the controlling terminal. */
if (setpgrp () < 0)
ulog (LOG_ERROR, "setpgrp: %s", strerror (errno));
#else /* ! HAVE_SETPGRP */
#error Must detach from controlling terminal
#endif /* HAVE_SETPGRP */
#endif /* ! HAVE_SETSID */
#endif /* ! HAVE_BSD_PGRP */
/* At this point we have completely detached from our controlling
terminal. The next terminal device we open will probably become
our controlling terminal. */
}

View File

@ -0,0 +1,123 @@
/* dirent.c
Replacements for opendir, readdir and closedir for the original
Unix filesystem only.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
/* Simple emulations of opendir/readdir/closedir for systems which
have the original format of Unix directories. It's probably better
to get Doug Gwyn's public domain set of emulation functions. */
DIR *
opendir (zdir)
const char *zdir;
{
int o;
struct stat s;
DIR *qret;
o = open ((char *) zdir, O_RDONLY | O_NOCTTY, 0);
if (o < 0)
return NULL;
if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0
|| fstat (o, &s) < 0)
{
int isave;
isave = errno;
(void) close (o);
errno = isave;
return NULL;
}
if (! S_ISDIR (s.st_mode))
{
(void) close (o);
errno = ENOTDIR;
return NULL;
}
qret = (DIR *) xmalloc (sizeof (DIR));
qret->o = o;
return qret;
}
struct dirent *
readdir (q)
DIR *q;
{
struct direct sdir;
int cgot;
do
{
cgot = read (q->o, &sdir, sizeof (struct direct));
if (cgot <= 0)
return NULL;
if (cgot != sizeof (struct direct))
{
errno = ENOENT;
return NULL;
}
}
while (sdir.d_ino == 0);
strncpy (q->s.d_name, sdir.d_name, DIRSIZ);
q->s.d_name[DIRSIZ] = '\0';
return &q->s;
}
int
closedir (q)
DIR *q;
{
int o;
o = q->o;
xfree (q);
return close (o);
}

View File

@ -0,0 +1,69 @@
/* dup2.c
The Unix dup2 function, for systems which only have dup.
Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
/* I basically took this from the emacs 18.57 distribution, although I
cleaned it up a bit and made it POSIX compliant. */
int
dup2 (oold, onew)
int oold;
int onew;
{
if (oold == onew)
return onew;
(void) close (onew);
#ifdef F_DUPFD
return fcntl (oold, F_DUPFD, onew);
#else
{
int onext, oret, isave;
onext = dup (oold);
if (onext == onew)
return onext;
if (onext < 0)
return -1;
oret = dup2 (oold, onew);
isave = errno;
(void) close (onext);
errno = isave;
return oret;
}
#endif
}

View File

@ -0,0 +1,132 @@
/* efopen.c
Open a stdio file with appropriate permissions. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef O_APPEND
#ifdef FAPPEND
#define O_APPEND FAPPEND
#endif
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
FILE *
esysdep_fopen (zfile, fpublic, fappend, fmkdirs)
const char *zfile;
boolean fpublic;
boolean fappend;
boolean fmkdirs;
{
int imode;
int o;
FILE *e;
if (fpublic)
imode = IPUBLIC_FILE_MODE;
else
imode = IPRIVATE_FILE_MODE;
if (! fappend)
o = creat ((char *) zfile, imode);
else
{
#ifdef O_CREAT
o = open ((char *) zfile,
O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY,
imode);
#else
o = open ((char *) zfile, O_WRONLY | O_NOCTTY);
if (o < 0 && errno == ENOENT)
o = creat ((char *) zfile, imode);
#endif /* ! defined (O_CREAT) */
}
if (o < 0)
{
if (errno == ENOENT && fmkdirs)
{
if (! fsysdep_make_dirs (zfile, fpublic))
return NULL;
if (! fappend)
o = creat ((char *) zfile, imode);
else
{
#ifdef O_CREAT
o = open ((char *) zfile,
O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY,
imode);
#else
o = creat ((char *) zfile, imode);
#endif
}
}
if (o < 0)
{
ulog (LOG_ERROR, "open (%s): %s", zfile, strerror (errno));
return NULL;
}
}
#ifndef O_CREAT
#ifdef O_APPEND
if (fappend)
{
if (fcntl (o, F_SETFL, O_APPEND) < 0)
{
ulog (LOG_ERROR, "fcntl (%s, O_APPEND): %s", zfile,
strerror (errno));
(void) close (o);
return NULL;
}
}
#endif /* defined (O_APPEND) */
#endif /* ! defined (O_CREAT) */
if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0)
{
ulog (LOG_ERROR, "fcntl (%s, FD_CLOEXEC): %s", zfile,
strerror (errno));
(void) close (o);
return NULL;
}
if (fappend)
e = fdopen (o, (char *) "a");
else
e = fdopen (o, (char *) "w");
if (e == NULL)
{
ulog (LOG_ERROR, "fdopen: %s", strerror (errno));
(void) close (o);
}
return e;
}

View File

@ -0,0 +1,85 @@
/* epopen.c
A version of popen that goes through ixsspawn.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
/* A version of popen that goes through ixsspawn. This actually takes
an array of arguments rather than a string, and takes a boolean
read/write value rather than a string. It sets *pipid to the
process ID of the child. */
FILE *
espopen (pazargs, frd, pipid)
const char **pazargs;
boolean frd;
pid_t *pipid;
{
int aidescs[3];
pid_t ipid;
FILE *eret;
if (frd)
{
aidescs[0] = SPAWN_NULL;
aidescs[1] = SPAWN_READ_PIPE;
}
else
{
aidescs[0] = SPAWN_WRITE_PIPE;
aidescs[1] = SPAWN_NULL;
}
aidescs[2] = SPAWN_NULL;
ipid = ixsspawn (pazargs, aidescs, FALSE, FALSE,
(const char *) NULL, FALSE, TRUE,
(const char *) NULL, (const char *) NULL,
(const char *) NULL);
if (ipid < 0)
return NULL;
if (frd)
eret = fdopen (aidescs[1], (char *) "r");
else
eret = fdopen (aidescs[0], (char *) "w");
if (eret == NULL)
{
int ierr;
ierr = errno;
(void) close (frd ? aidescs[1] : aidescs[0]);
(void) kill (ipid, SIGKILL);
(void) ixswait ((unsigned long) ipid, (const char *) NULL);
errno = ierr;
return NULL;
}
*pipid = ipid;
return eret;
}

View File

@ -0,0 +1,16 @@
/* exists.c
Check whether a file exists. */
#include "uucp.h"
#include "sysdep.h"
#include "system.h"
boolean
fsysdep_file_exists (zfile)
const char *zfile;
{
struct stat s;
return stat ((char *) zfile, &s) == 0;
}

View File

@ -0,0 +1,376 @@
/* filnam.c
Get names to use for UUCP files.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "uuconf.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
/* We need a definition for SEEK_SET. */
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
/* External functions. */
#ifndef lseek
extern off_t lseek ();
#endif
#define ZCHARS \
"0123456789ABCDEFGHIJKLMNOPQRTSUVWXYZabcdefghijklmnopqrstuvwxyz"
/* Local functions. */
static boolean fscmd_seq P((const char *zsystem, char *zseq));
static char *zsfile_name P((int btype, const char *zsystem,
const char *zlocalname, int bgrade,
boolean fxqt, char *ztname, char *zdname,
char *zxname));
/* Get a new command sequence number (this is not a sequence number to
be used for communicating with another system, but a sequence
number to be used when generating the name of a command file).
The sequence number is placed into zseq, which should be five
characters long. */
static boolean
fscmd_seq (zsystem, zseq)
const char *zsystem;
char *zseq;
{
boolean ferr;
char *zfree;
const char *zfile;
int o;
int i;
/* Lock the sequence file. This may not be correct for all systems,
but it only matters if the system UUCP and this UUCP are running
at the same time. */
while (! fsdo_lock ("LCK..SEQ", TRUE, &ferr))
{
if (ferr || FGOT_SIGNAL ())
return FALSE;
sleep (5);
}
zfree = NULL;
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43
zfile = "SEQF";
#endif
#if SPOOLDIR_HDB || SPOOLDIR_SVR4
zfree = zsysdep_in_dir (".Sequence", zsystem);
zfile = zfree;
#endif
#if SPOOLDIR_ULTRIX
if (! fsultrix_has_spool (zsystem))
zfile = "sys/DEFAULT/.SEQF";
else
{
zfree = zsappend3 ("sys", zsystem, ".SEQF");
zfile = zfree;
}
#endif /* SPOOLDIR_ULTRIX */
#if SPOOLDIR_TAYLOR
zfree = zsysdep_in_dir (zsystem, "SEQF");
zfile = zfree;
#endif /* SPOOLDIR_TAYLOR */
#ifdef O_CREAT
o = open ((char *) zfile, O_RDWR | O_CREAT | O_NOCTTY, IPUBLIC_FILE_MODE);
#else
o = open ((char *) zfile, O_RDWR | O_NOCTTY);
if (o < 0 && errno == ENOENT)
{
o = creat ((char *) zfile, IPUBLIC_FILE_MODE);
if (o >= 0)
{
(void) close (o);
o = open ((char *) zfile, O_RDWR | O_NOCTTY);
}
}
#endif
if (o < 0)
{
if (errno == ENOENT)
{
if (! fsysdep_make_dirs (zfile, FALSE))
{
(void) fsdo_unlock ("LCK..SEQ", TRUE);
return FALSE;
}
#ifdef O_CREAT
o = open ((char *) zfile,
O_RDWR | O_CREAT | O_NOCTTY,
IPUBLIC_FILE_MODE);
#else
o = creat ((char *) zfile, IPUBLIC_FILE_MODE);
if (o >= 0)
{
(void) close (o);
o = open ((char *) zfile, O_RDWR | O_NOCTTY);
}
#endif
}
if (o < 0)
{
ulog (LOG_ERROR, "open (%s): %s", zfile, strerror (errno));
(void) fsdo_unlock ("LCK..SEQ", TRUE);
return FALSE;
}
}
if (read (o, zseq, CSEQLEN) != CSEQLEN)
strcpy (zseq, "0000");
zseq[CSEQLEN] = '\0';
/* We must add one to the sequence number and return the new value.
On Ultrix, arbitrary characters are allowed in the sequence
number. On other systems, the sequence number apparently must be
in hex. */
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_HDB || SPOOLDIR_SVR4
i = (int) strtol (zseq, (char **) NULL, 16);
++i;
if (i > 0xffff)
i = 0;
/* The sprintf argument has CSEQLEN built into it. */
sprintf (zseq, "%04x", (unsigned int) i);
#endif
#if SPOOLDIR_ULTRIX || SPOOLDIR_TAYLOR
for (i = CSEQLEN - 1; i >= 0; i--)
{
const char *zdig;
zdig = strchr (ZCHARS, zseq[i]);
if (zdig == NULL || zdig[0] == '\0' || zdig[1] == '\0')
zseq[i] = '0';
else
{
zseq[i] = zdig[1];
break;
}
}
#endif /* SPOOLDIR_ULTRIX || SPOOLDIR_TAYLOR */
if (lseek (o, (off_t) 0, SEEK_SET) < 0
|| write (o, zseq, CSEQLEN) != CSEQLEN
|| close (o) < 0)
{
ulog (LOG_ERROR, "lseek or write or close: %s", strerror (errno));
(void) close (o);
(void) fsdo_unlock ("LCK..SEQ", TRUE);
return FALSE;
}
(void) fsdo_unlock ("LCK..SEQ", TRUE);
return TRUE;
}
/* Get the name of a command or data file for a remote system. The
btype argument should be C for a command file or D for a data file.
If the grade of a data file is X, it is assumed that this is going
to become an execute file on some other system. The zsystem
argument is the system that the file will be transferred to. The
ztname argument will be set to a file name that could be passed to
zsysdep_spool_file_name. The zdname argument, if not NULL, will be
set to a data file name appropriate for the remote system. The
zxname argument, if not NULL, will be set to the name of an execute
file on the remote system. None of the names will be more than 14
characters long. */
/*ARGSUSED*/
static char *
zsfile_name (btype, zsystem, zlocalname, bgrade, fxqt, ztname, zdname, zxname)
int btype;
const char *zsystem;
const char *zlocalname;
int bgrade;
boolean fxqt;
char *ztname;
char *zdname;
char *zxname;
{
char abseq[CSEQLEN + 1];
char absimple[11 + CSEQLEN];
char *zname;
if (zlocalname == NULL)
zlocalname = zSlocalname;
while (TRUE)
{
if (! fscmd_seq (zsystem, abseq))
return NULL;
if (btype == 'C')
{
#if ! SPOOLDIR_TAYLOR
sprintf (absimple, "C.%.7s%c%s", zsystem, bgrade, abseq);
#else
sprintf (absimple, "C.%c%s", bgrade, abseq);
#endif
}
else if (btype == 'D')
{
/* This name doesn't really matter that much; it's just the
name we use on the local system. The name we use on the
remote system, which we return in zdname, should contain
our system name so that remote UUCP's running SPOOLDIR_V2
and the like can distinguish while files come from which
systems. */
#if SPOOLDIR_HDB || SPOOLDIR_SVR4
sprintf (absimple, "D.%.7s%c%s", zsystem, bgrade, abseq);
#else /* ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 */
#if ! SPOOLDIR_TAYLOR
sprintf (absimple, "D.%.7s%c%s", zlocalname, bgrade, abseq);
#else /* SPOOLDIR_TAYLOR */
if (fxqt)
sprintf (absimple, "D.X%s", abseq);
else
sprintf (absimple, "D.%s", abseq);
#endif /* SPOOLDIR_TAYLOR */
#endif /* ! SPOOLDIR_HDB && ! SPOOLDIR_SVR4 */
}
#if DEBUG > 0
else
ulog (LOG_FATAL, "zsfile_name: Can't happen");
#endif
zname = zsfind_file (absimple, zsystem, bgrade);
if (zname == NULL)
return NULL;
if (! fsysdep_file_exists (zname))
break;
ubuffree (zname);
}
if (ztname != NULL)
strcpy (ztname, absimple);
if (zdname != NULL)
sprintf (zdname, "D.%.7s%c%s", zlocalname, bgrade, abseq);
if (zxname != NULL)
sprintf (zxname, "X.%.7s%c%s", zlocalname, bgrade, abseq);
return zname;
}
/* Return a name to use for a data file to be copied to another
system. The name returned will be for a real file. The zlocalname
argument is the local name as seen by the remote system, the bgrade
argument is the file grade, and the fxqt argument is TRUE if this
file will become an execution file. The ztname argument, if not
NULL, will be set to a name that could be passed to
zsysdep_spool_file_name to get back the return value of this
function. The zdname argument, if not NULL, will be set to a name
that the file could be given on another system. The zxname
argument, if not NULL, will be set to a name for an execute file on
another system. */
char *
zsysdep_data_file_name (qsys, zlocalname, bgrade, fxqt, ztname, zdname,
zxname)
const struct uuconf_system *qsys;
const char *zlocalname;
int bgrade;
boolean fxqt;
char *ztname;
char *zdname;
char *zxname;
{
return zsfile_name ('D', qsys->uuconf_zname, zlocalname, bgrade, fxqt,
ztname, zdname, zxname);
}
/* Get a command file name. */
char *
zscmd_file (qsys, bgrade)
const struct uuconf_system *qsys;
int bgrade;
{
return zsfile_name ('C', qsys->uuconf_zname, (const char *) NULL,
bgrade, FALSE, (char *) NULL, (char *) NULL,
(char *) NULL);
}
/* Return a name for an execute file to be created locally. This is
used by uux to execute a command locally with remote files. */
char *
zsysdep_xqt_file_name ()
{
char abseq[CSEQLEN + 1];
char absx[11 + CSEQLEN];
char *zname;
while (TRUE)
{
if (! fscmd_seq (zSlocalname, abseq))
return NULL;
sprintf (absx, "X.%.7sX%s", zSlocalname, abseq);
zname = zsfind_file (absx, zSlocalname, -1);
if (zname == NULL)
return NULL;
if (! fsysdep_file_exists (zname))
break;
ubuffree (zname);
}
return zname;
}

View File

@ -0,0 +1,231 @@
/* fsusage.c -- return space usage of mounted filesystems
Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
This file was modified slightly by Ian Lance Taylor, December 1992,
for use with Taylor UUCP. */
#include "uucp.h"
#include "sysdep.h"
#include "fsusg.h"
int statfs ();
#if STAT_STATFS2_BSIZE
#ifndef _IBMR2 /* 4.3BSD, SunOS 4, HP-UX, AIX PS/2. */
#include <sys/vfs.h>
#endif
#endif
#if STAT_STATFS2_FSIZE /* 4.4BSD. */
#include <sys/mount.h>
#endif
#if STAT_STATFS2_FS_DATA /* Ultrix. */
#include <sys/param.h>
#include <sys/mount.h>
#endif
#if STAT_USTAT /* SVR2 and others. */
#include <ustat.h>
#endif
#if STAT_STATFS4 /* SVR3, Dynix, Irix. */
#include <sys/statfs.h>
#endif
#ifdef _AIX
#ifdef _IBMR2 /* AIX RS6000. */
#include <sys/statfs.h>
#endif
#endif
#ifdef _AIX
#ifdef _I386 /* AIX PS/2. */
#include <sys/stat.h>
#include <sys/dustat.h>
#endif
#endif
#if STAT_STATVFS /* SVR4. */
#include <sys/statvfs.h>
int statvfs ();
#endif
#define STAT_NONE 0
#if ! STAT_STATVFS
#if ! STAT_STATFS2_BSIZE
#if ! STAT_STATFS2_FSIZE
#if ! STAT_STATFS2_FS_DATA
#if ! STAT_STATFS4
#if ! STAT_USTAT
#undef STAT_NONE
#define STAT_NONE 1
#endif
#endif
#endif
#endif
#endif
#endif
#if ! STAT_NONE
/* Return the number of TOSIZE-byte blocks used by
BLOCKS FROMSIZE-byte blocks, rounding up. */
static long
adjust_blocks (blocks, fromsize, tosize)
long blocks;
int fromsize, tosize;
{
if (fromsize == tosize) /* E.g., from 512 to 512. */
return blocks;
else if (fromsize > tosize) /* E.g., from 2048 to 512. */
return blocks * (fromsize / tosize);
else /* E.g., from 256 to 512. */
return (blocks + 1) / (tosize / fromsize);
}
#endif
/* Fill in the fields of FSP with information about space usage for
the filesystem on which PATH resides.
DISK is the device on which PATH is mounted, for space-getting
methods that need to know it.
Return 0 if successful, -1 if not. */
int
get_fs_usage (path, disk, fsp)
char *path, *disk;
struct fs_usage *fsp;
{
#if STAT_NONE
return -1;
#endif
#if STAT_STATFS2_FS_DATA /* Ultrix. */
struct fs_data fsd;
if (statfs (path, &fsd) != 1)
return -1;
#define convert_blocks(b) adjust_blocks ((b), 1024, 512)
fsp->fsu_blocks = convert_blocks (fsd.fd_req.btot);
fsp->fsu_bfree = convert_blocks (fsd.fd_req.bfree);
fsp->fsu_bavail = convert_blocks (fsd.fd_req.bfreen);
fsp->fsu_files = fsd.fd_req.gtot;
fsp->fsu_ffree = fsd.fd_req.gfree;
#endif
#if STAT_STATFS2_BSIZE /* 4.3BSD, SunOS 4, HP-UX, AIX. */
struct statfs fsd;
if (statfs (path, &fsd) < 0)
return -1;
#define convert_blocks(b) adjust_blocks ((b), fsd.f_bsize, 512)
#endif
#if STAT_STATFS2_FSIZE /* 4.4BSD. */
struct statfs fsd;
if (statfs (path, &fsd) < 0)
return -1;
#define convert_blocks(b) adjust_blocks ((b), fsd.f_fsize, 512)
#endif
#if STAT_STATFS4 /* SVR3, Dynix, Irix. */
struct statfs fsd;
if (statfs (path, &fsd, sizeof fsd, 0) < 0)
return -1;
/* Empirically, the block counts on most SVR3 and SVR3-derived
systems seem to always be in terms of 512-byte blocks,
no matter what value f_bsize has. */
#define convert_blocks(b) (b)
#ifndef _SEQUENT_ /* _SEQUENT_ is DYNIX/ptx. */
#define f_bavail f_bfree
#endif
#endif
#if STAT_STATVFS /* SVR4. */
struct statvfs fsd;
if (statvfs (path, &fsd) < 0)
return -1;
/* f_frsize isn't guaranteed to be supported. */
#define convert_blocks(b) \
adjust_blocks ((b), fsd.f_frsize ? fsd.f_frsize : fsd.f_bsize, 512)
#endif
#if STAT_USTAT
{
struct stat sstat;
struct ustat s;
if (stat (path, &sstat) < 0
|| ustat (sstat.st_dev, &s) < 0)
return -1;
fsp->fsu_blocks = -1;
fsp->fsu_bfree = f_tfree;
fsp->fsu_bavail = f_tfree;
fsp->fsu_files = -1;
fsp->fsu_ffree = -1;
}
#endif
#if ! STAT_STATFS2_FS_DATA /* ! Ultrix */
#if ! STAT_USTAT
#if ! STAT_NONE
fsp->fsu_blocks = convert_blocks (fsd.f_blocks);
fsp->fsu_bfree = convert_blocks (fsd.f_bfree);
fsp->fsu_bavail = convert_blocks (fsd.f_bavail);
fsp->fsu_files = fsd.f_files;
fsp->fsu_ffree = fsd.f_ffree;
#endif
#endif
#endif
return 0;
}
#ifdef _AIX
#ifdef _I386
/* AIX PS/2 does not supply statfs. */
int
statfs (path, fsb)
char *path;
struct statfs *fsb;
{
struct stat stats;
struct dustat fsd;
if (stat (path, &stats))
return -1;
if (dustat (stats.st_dev, 0, &fsd, sizeof (fsd)))
return -1;
fsb->f_type = 0;
fsb->f_bsize = fsd.du_bsize;
fsb->f_blocks = fsd.du_fsize - fsd.du_isize;
fsb->f_bfree = fsd.du_tfree;
fsb->f_bavail = fsd.du_tfree;
fsb->f_files = (fsd.du_isize - 2) * fsd.du_inopb;
fsb->f_ffree = fsd.du_tinode;
fsb->f_fsid.val[0] = fsd.du_site;
fsb->f_fsid.val[1] = fsd.du_pckno;
return 0;
}
#endif
#endif /* _AIX && _I386 */

View File

@ -0,0 +1,31 @@
/* fsusage.h -- declarations for filesystem space usage info
Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
This files was modified slightly by Ian Lance Taylor for use with
Taylor UUCP. */
/* Space usage statistics for a filesystem. Blocks are 512-byte. */
struct fs_usage
{
long fsu_blocks; /* Total blocks. */
long fsu_bfree; /* Free blocks available to superuser. */
long fsu_bavail; /* Free blocks available to non-superuser. */
long fsu_files; /* Total file nodes. */
long fsu_ffree; /* Free file nodes. */
};
extern int get_fs_usage P((char *path, char *disk, struct fs_usage *fsp));

View File

@ -0,0 +1,250 @@
/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ian Lance Taylor (ian@airs.com).
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.
Modified by Ian Lanc Taylor for Taylor UUCP, June 1992. */
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_OPENDIR
#if HAVE_DIRENT_H
#include <dirent.h>
#else /* ! HAVE_DIRENT_H */
#include <sys/dir.h>
#define dirent direct
#endif /* ! HAVE_DIRENT_H */
#endif /* HAVE_OPENDIR */
#if HAVE_FTW_H
#include <ftw.h>
#endif
#ifndef PATH_MAX
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
#define PATH_MAX 1024
#endif
#endif
/* Traverse one level of a directory tree. */
static int
ftw_dir (dirs, level, descriptors, dir, len, func)
DIR **dirs;
int level;
int descriptors;
char *dir;
size_t len;
int (*func) P((const char *file, const struct stat *status, int flag));
{
int got;
struct dirent *entry;
got = 0;
errno = 0;
while ((entry = readdir (dirs[level])) != NULL)
{
size_t namlen;
struct stat s;
int flag, ret, newlev;
++got;
namlen = strlen (entry->d_name);
if (entry->d_name[0] == '.'
&& (namlen == 1 ||
(namlen == 2 && entry->d_name[1] == '.')))
{
errno = 0;
continue;
}
if (namlen + len + 1 > PATH_MAX)
{
#ifdef ENAMETOOLONG
errno = ENAMETOOLONG;
#else
errno = ENOMEM;
#endif
return -1;
}
dir[len] = '/';
memcpy ((dir + len + 1), entry->d_name, namlen + 1);
if (stat (dir, &s) < 0)
{
if (errno != EACCES)
return -1;
flag = FTW_NS;
}
else if (S_ISDIR (s.st_mode))
{
newlev = (level + 1) % descriptors;
if (dirs[newlev] != NULL)
closedir (dirs[newlev]);
dirs[newlev] = opendir (dir);
if (dirs[newlev] != NULL)
flag = FTW_D;
else
{
if (errno != EACCES)
return -1;
flag = FTW_DNR;
}
}
else
flag = FTW_F;
ret = (*func) (dir, &s, flag);
if (flag == FTW_D)
{
if (ret == 0)
ret = ftw_dir (dirs, newlev, descriptors, dir,
namlen + len + 1, func);
if (dirs[newlev] != NULL)
{
int save;
save = errno;
closedir (dirs[newlev]);
errno = save;
dirs[newlev] = NULL;
}
}
if (ret != 0)
return ret;
if (dirs[level] == NULL)
{
int skip;
dir[len] = '\0';
dirs[level] = opendir (dir);
if (dirs[level] == NULL)
return -1;
skip = got;
while (skip-- != 0)
{
errno = 0;
if (readdir (dirs[level]) == NULL)
return errno == 0 ? 0 : -1;
}
}
errno = 0;
}
return errno == 0 ? 0 : -1;
}
/* Call a function on every element in a directory tree. */
int
ftw (dir, func, descriptors)
const char *dir;
int (*func) P((const char *file, const struct stat *status, int flag));
int descriptors;
{
DIR **dirs;
int c;
DIR **p;
size_t len;
char buf[PATH_MAX + 1];
struct stat s;
int flag, ret;
if (descriptors <= 0)
descriptors = 1;
dirs = (DIR **) malloc (descriptors * sizeof (DIR *));
if (dirs == NULL)
return -1;
c = descriptors;
p = dirs;
while (c-- != 0)
*p++ = NULL;
len = strlen (dir);
memcpy (buf, dir, len + 1);
if (stat (dir, &s) < 0)
{
if (errno != EACCES)
{
free ((pointer) dirs);
return -1;
}
flag = FTW_NS;
}
else if (S_ISDIR (s.st_mode))
{
dirs[0] = opendir (dir);
if (dirs[0] != NULL)
flag = FTW_D;
else
{
if (errno != EACCES)
{
free ((pointer) dirs);
return -1;
}
flag = FTW_DNR;
}
}
else
flag = FTW_F;
ret = (*func) (buf, &s, flag);
if (flag == FTW_D)
{
if (ret == 0)
ret = ftw_dir (dirs, 0, descriptors, buf, len, func);
if (dirs[0] != NULL)
{
int save;
save = errno;
closedir (dirs[0]);
errno = save;
}
}
free ((pointer) dirs);
return ret;
}

View File

@ -0,0 +1,59 @@
/* getcwd.c
Replacement for the getcwd function that just calls /bin/pwd. */
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
char *
getcwd (zbuf, cbuf)
char *zbuf;
size_t cbuf;
{
const char *azargs[2];
FILE *e;
pid_t ipid;
int cread;
int ierr;
azargs[0] = PWD_PROGRAM;
azargs[1] = NULL;
e = espopen (azargs, TRUE, &ipid);
if (e == NULL)
return NULL;
ierr = 0;
cread = fread (zbuf, sizeof (char), cbuf, e);
if (cread == 0)
ierr = errno;
(void) fclose (e);
if (ixswait ((unsigned long) ipid, (const char *) NULL) != 0)
{
ierr = EACCES;
cread = 0;
}
if (cread != 0)
{
if (zbuf[cread - 1] == '\n')
zbuf[cread - 1] = '\0';
else
{
ierr = ERANGE;
cread = 0;
}
}
if (cread == 0)
{
errno = ierr;
return NULL;
}
return zbuf;
}

View File

@ -0,0 +1,133 @@
/* indir.c
See if a file is in a directory.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
/* See whether a file is in a directory, and optionally check access. */
boolean
fsysdep_in_directory (zfile, zdir, fcheck, freadable, zuser)
const char *zfile;
const char *zdir;
boolean fcheck;
boolean freadable;
const char *zuser;
{
size_t c;
char *zcopy, *zslash;
struct stat s;
if (*zfile != '/')
return FALSE;
c = strlen (zdir);
if (c > 0 && zdir[c - 1] == '/')
c--;
if (strncmp (zfile, zdir, c) != 0
|| (zfile[c] != '/' && zfile[c] != '\0'))
return FALSE;
if (strstr (zfile + c, "/../") != NULL)
return FALSE;
/* If we're not checking access, get out now. */
if (! fcheck)
return TRUE;
zcopy = zbufcpy (zfile);
/* Start checking directories after zdir. Otherwise, we would
require that all directories down to /usr/spool/uucppublic be
publically searchable; they probably are but it should not be a
requirement. */
zslash = zcopy + c;
do
{
char b;
struct stat shold;
b = *zslash;
*zslash = '\0';
shold = s;
if (stat (zcopy, &s) != 0)
{
if (errno != ENOENT)
{
ulog (LOG_ERROR, "stat (%s): %s", zcopy, strerror (errno));
ubuffree (zcopy);
return FALSE;
}
/* If this is the top directory, any problems will be caught
later when we try to open it. */
if (zslash == zcopy + c)
{
ubuffree (zcopy);
return TRUE;
}
/* Go back and check the last directory for read or write
access. */
s = shold;
break;
}
/* If this is not a directory, get out of the loop. */
if (! S_ISDIR (s.st_mode))
break;
/* Make sure the directory is searchable. */
if (! fsuser_access (&s, X_OK, zuser))
{
ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
ubuffree (zcopy);
return FALSE;
}
/* If we've reached the end of the string, get out. */
if (b == '\0')
break;
*zslash = b;
}
while ((zslash = strchr (zslash + 1, '/')) != NULL);
/* At this point s holds a stat on the last component of the path.
We must check it for readability or writeability. */
if (! fsuser_access (&s, freadable ? R_OK : W_OK, zuser))
{
ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
ubuffree (zcopy);
return FALSE;
}
ubuffree (zcopy);
return TRUE;
}

View File

@ -0,0 +1,394 @@
/* init.c
Initialize the system dependent routines.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
#include "sysdep.h"
#include <errno.h>
#include <pwd.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#if ! HAVE_GETHOSTNAME && HAVE_UNAME
#include <sys/utsname.h>
#endif
/* Use getcwd in preference to getwd; if we have neither, we will be
using a getcwd replacement. */
#if HAVE_GETCWD
#undef HAVE_GETWD
#define HAVE_GETWD 0
#else /* ! HAVE_GETCWD */
#if ! HAVE_GETWD
#undef HAVE_GETCWD
#define HAVE_GETCWD 1
#endif /* ! HAVE_GETWD */
#endif /* ! HAVE_GETCWD */
#if HAVE_GETWD
/* Get a value for MAXPATHLEN. */
#if HAVE_SYS_PARAMS_H
#include <sys/params.h>
#endif
#if HAVE_LIMITS_H
#include <limits.h>
#endif
#ifndef MAXPATHLEN
#ifdef PATH_MAX
#define MAXPATHLEN PATH_MAX
#else /* ! defined (PATH_MAX) */
#define MAXPATHLEN 1024
#endif /* ! defined (PATH_MAX) */
#endif /* ! defined (MAXPATHLEN) */
#endif /* HAVE_GETWD */
/* External functions. */
#ifndef getlogin
extern char *getlogin ();
#endif
#if GETPWNAM_DECLARATION_OK
#ifndef getpwnam
extern struct passwd *getpwnam ();
#endif
#endif
#if GETPWUID_DECLARATION_OK
#ifndef getpwuid
extern struct passwd *getpwuid ();
#endif
#endif
#if HAVE_GETCWD
#ifndef getcwd
extern char *getcwd ();
#endif
#endif
#if HAVE_GETWD
#ifndef getwd
extern char *getwd ();
#endif
#endif
#if HAVE_SYSCONF
#ifndef sysconf
extern long sysconf ();
#endif
#endif
/* Initialize the system dependent routines. We will probably be running
suid to uucp, so we make sure that nothing is obviously wrong. We
save the login name since we will be losing the real uid. */
static char *zSlogin;
/* The UUCP spool directory. */
const char *zSspooldir;
/* The UUCP lock directory. */
const char *zSlockdir;
/* The local UUCP name. */
const char *zSlocalname;
/* We save the current directory since we will do a chdir to the
spool directory. */
char *zScwd;
/* The maximum length of a system name is controlled by the type of spool
directory we use. */
#if SPOOLDIR_V2 || SPOOLDIR_BSD42 || SPOOLDIR_BSD43 || SPOOLDIR_ULTRIX
size_t cSysdep_max_name_len = 7;
#endif
#if SPOOLDIR_HDB || SPOOLDIR_SVR4
size_t cSysdep_max_name_len = 14;
#endif
#if SPOOLDIR_TAYLOR
#if HAVE_LONG_FILE_NAMES
size_t cSysdep_max_name_len = 255;
#else /* ! HAVE_LONG_FILE_NAMES */
size_t cSysdep_max_name_len = 14;
#endif /* ! HAVE_LONG_FILE_NAMES */
#endif /* SPOOLDIR_TAYLOR */
/* Initialize the system dependent routines. */
void
usysdep_initialize (puuconf,iflags)
pointer puuconf;
int iflags;
{
int cdescs;
int o;
int iuuconf;
char *z;
struct passwd *q;
ulog_id (getpid ());
/* Close everything but stdin, stdout and stderr. */
#if HAVE_GETDTABLESIZE
cdescs = getdtablesize ();
#else
#if HAVE_SYSCONF
cdescs = sysconf (_SC_OPEN_MAX);
#else
#ifdef OPEN_MAX
cdescs = OPEN_MAX;
#else
#ifdef NOFILE
cdescs = NOFILE;
#else
cdescs = 20;
#endif /* ! defined (NOFILE) */
#endif /* ! defined (OPEN_MAX) */
#endif /* ! HAVE_SYSCONF */
#endif /* ! HAVE_GETDTABLESIZE */
for (o = 3; o < cdescs; o++)
(void) close (o);
/* Make sure stdin, stdout and stderr are open. */
if (fcntl (0, F_GETFD, 0) < 0
&& open ((char *) "/dev/null", O_RDONLY, 0) != 0)
exit (EXIT_FAILURE);
if (fcntl (1, F_GETFD, 0) < 0
&& open ((char *) "/dev/null", O_WRONLY, 0) != 1)
exit (EXIT_FAILURE);
if (fcntl (2, F_GETFD, 0) < 0
&& open ((char *) "/dev/null", O_WRONLY, 0) != 2)
exit (EXIT_FAILURE);
iuuconf = uuconf_spooldir (puuconf, &zSspooldir);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
iuuconf = uuconf_lockdir (puuconf, &zSlockdir);
if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
iuuconf = uuconf_localname (puuconf, &zSlocalname);
if (iuuconf == UUCONF_NOT_FOUND)
{
#if HAVE_GETHOSTNAME
char ab[256];
if (gethostname (ab, sizeof ab - 1) < 0)
ulog (LOG_FATAL, "gethostname: %s", strerror (errno));
ab[sizeof ab - 1] = '\0';
ab[strcspn (ab, ".")] = '\0';
zSlocalname = zbufcpy (ab);
#else /* ! HAVE_GETHOSTNAME */
#if HAVE_UNAME
struct utsname s;
if (uname (&s) < 0)
ulog (LOG_FATAL, "uname: %s", strerror (errno));
zSlocalname = zbufcpy (s.nodename);
#else /* ! HAVE_UNAME */
ulog (LOG_FATAL, "Don't know how to get local node name");
#endif /* ! HAVE_UNAME */
#endif /* ! HAVE_GETHOSTNAME */
}
else if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
/* We always set our file modes to exactly what we want. */
umask (0);
/* Get the login name, making sure that it matches the uid. Many
systems truncate the getlogin return value to 8 characters, but
keep the full name in the password file, so we prefer the name in
the password file. */
z = getenv ("LOGNAME");
if (z == NULL)
z = getenv ("USER");
if (z == NULL)
z = getlogin ();
if (z == NULL)
q = NULL;
else
{
q = getpwnam (z);
if (q != NULL)
z = q->pw_name;
}
if (q == NULL || q->pw_uid != getuid ())
{
q = getpwuid (getuid ());
if (q == NULL)
z = NULL;
else
z = q->pw_name;
}
if (z != NULL)
zSlogin = zbufcpy (z);
/* On some old systems, an suid program run by root is started with
an euid of 0. If this happens, we look up the uid we should have
and set ourselves to it manually. This means that on such a
system root will not be able to uucp or uux files that are not
readable by uucp. */
if ((iflags & INIT_SUID) != 0
&& geteuid () == 0)
{
q = getpwnam (OWNER);
if (q != NULL)
setuid (q->pw_uid);
}
if ((iflags & INIT_GETCWD) != 0)
{
const char *zenv;
struct stat senv, sdot;
/* Get the current working directory. We have to get it now,
since we're about to do a chdir. We use PWD if it's defined
and if it really names the working directory, since if it's
not the same as whatever getcwd returns it's probably more
appropriate. */
zenv = getenv ("PWD");
if (zenv != NULL
&& stat ((char *) zenv, &senv) == 0
&& stat ((char *) ".", &sdot) == 0
&& senv.st_ino == sdot.st_ino
&& senv.st_dev == sdot.st_dev)
zScwd = zbufcpy (zenv);
else
{
#if HAVE_GETCWD
{
size_t c;
c = 128;
while (TRUE)
{
zScwd = (char *) xmalloc (c);
if (getcwd (zScwd, c) != NULL)
break;
xfree ((pointer) zScwd);
zScwd = NULL;
if (errno != ERANGE)
break;
c <<= 1;
}
}
#endif /* HAVE_GETCWD */
#if HAVE_GETWD
zScwd = (char *) xmalloc (MAXPATHLEN);
if (getwd (zScwd) == NULL)
{
xfree ((pointer) zScwd);
zScwd = NULL;
}
#endif /* HAVE_GETWD */
if (zScwd != NULL)
zScwd = (char *) xrealloc ((pointer) zScwd,
strlen (zScwd) + 1);
}
}
if ((iflags & INIT_NOCHDIR) == 0)
{
/* Connect to the spool directory, and create it if it doesn't
exist. */
if (chdir (zSspooldir) < 0)
{
if (errno == ENOENT
&& mkdir ((char *) zSspooldir, IDIRECTORY_MODE) < 0)
ulog (LOG_FATAL, "mkdir (%s): %s", zSspooldir,
strerror (errno));
if (chdir (zSspooldir) < 0)
ulog (LOG_FATAL, "chdir (%s): %s", zSspooldir,
strerror (errno));
}
}
}
/* Exit the program. */
void
usysdep_exit (fsuccess)
boolean fsuccess;
{
exit (fsuccess ? EXIT_SUCCESS : EXIT_FAILURE);
}
/* This is called when a non-standard configuration file is used, to
make sure the program doesn't hand out privileged file access.
This means that to test non-standard configuration files, you
should be logged in as uucp. This is called before
usysdep_initialize. It ensures that someone can't simply use an
alternate configuration file to steal UUCP transfers from other
systems. This will still permit people to set up their own
configuration file and pretend to be whatever system they choose.
The only real security is to use a high level of protection on the
modem ports. */
/*ARGSUSED*/
boolean fsysdep_other_config (z)
const char *z;
{
(void) setuid (getuid ());
(void) setgid (getgid ());
return TRUE;
}
/* Get the node name to use if it was not specified in the configuration
file. */
const char *
zsysdep_localname ()
{
return zSlocalname;
}
/* Get the login name. We actually get the login name in
usysdep_initialize, because after that we may switch away from the
real uid. */
const char *
zsysdep_login_name ()
{
if (zSlogin == NULL)
ulog (LOG_FATAL, "Can't get login name");
return zSlogin;
}

View File

@ -0,0 +1,18 @@
/* isdir.c
See whether a file exists and is a directory. */
#include "uucp.h"
#include "system.h"
#include "sysdep.h"
boolean
fsysdep_directory (z)
const char *z;
{
struct stat s;
if (stat ((char *) z, &s) < 0)
return FALSE;
return S_ISDIR (s.st_mode);
}

View File

@ -0,0 +1,25 @@
/* isfork.c
Retry fork several times before giving up. */
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
pid_t
ixsfork ()
{
int i;
pid_t iret;
for (i = 0; i < 10; i++)
{
iret = fork ();
if (iret >= 0 || errno != EAGAIN)
return iret;
sleep (5);
}
return iret;
}

View File

@ -0,0 +1,159 @@
/* iswait.c
Wait for a process to finish.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include <errno.h>
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
/* We use a typedef wait_status for wait (waitpid, wait4) to put
results into. We define the POSIX examination functions we need if
they are not already defined (if they aren't defined, I assume that
we have a standard wait status). */
#if HAVE_UNION_WAIT
typedef union wait wait_status;
#ifndef WIFEXITED
#define WIFEXITED(u) ((u).w_termsig == 0)
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(u) ((u).w_retcode)
#endif
#ifndef WTERMSIG
#define WTERMSIG(u) ((u).w_termsig)
#endif
#else /* ! HAVE_UNION_WAIT */
typedef int wait_status;
#ifndef WIFEXITED
#define WIFEXITED(i) (((i) & 0xff) == 0)
#endif
#ifndef WEXITSTATUS
#define WEXITSTATUS(i) (((i) >> 8) & 0xff)
#endif
#ifndef WTERMSIG
#define WTERMSIG(i) ((i) & 0x7f)
#endif
#endif /* ! HAVE_UNION_WAIT */
/* Wait for a particular process to finish. The ipid argument should
be pid_t, but then we couldn't have a prototype. If the zreport
argument is not NULL, then a wait error will be logged, and if the
exit status is non-zero it will be logged with zreport as the
header of the log message. If the zreport argument is NULL, no
errors will be logged. This function returns the exit status if
the process exited normally, or -1 on error or if the process was
killed by a signal (I don't just always return the exit status
because then the calling code would have to prepared to handle
union wait status vs. int status, and none of the callers care
which signal killed the program anyhow).
This functions keeps waiting until the process finished, even if it
is interrupted by a signal. I think this is right for all uses.
The controversial one would be when called from uuxqt to wait for a
requested process. Hitting uuxqt with SIGKILL will approximate the
actions taken if we return from here with an error anyhow. If we
do get a signal, we call ulog with a NULL argument to get it in the
log file at about the right time. */
int
ixswait (ipid, zreport)
unsigned long ipid;
const char *zreport;
{
wait_status istat;
#if HAVE_WAITPID
while (waitpid ((pid_t) ipid, (pointer) &istat, 0) < 0)
{
if (errno != EINTR)
{
if (zreport != NULL)
ulog (LOG_ERROR, "waitpid: %s", strerror (errno));
return -1;
}
ulog (LOG_ERROR, (const char *) NULL);
}
#else /* ! HAVE_WAITPID */
#if HAVE_WAIT4
while (wait4 ((pid_t) ipid, (pointer) &istat, 0,
(struct rusage *) NULL) < 0)
{
if (errno != EINTR)
{
if (zreport != NULL)
ulog (LOG_ERROR, "wait4: %s", strerror (errno));
return -1;
}
ulog (LOG_ERROR, (const char *) NULL);
}
#else /* ! HAVE_WAIT4 */
pid_t igot;
/* We could theoretically get the wrong child here if we're in some
kind of weird pipeline, so we don't give any error messages for
it. */
while ((igot = wait ((pointer) &istat)) != (pid_t) ipid)
{
if (igot < 0)
{
if (errno != EINTR)
{
if (zreport != NULL)
ulog (LOG_ERROR, "wait: %s", strerror (errno));
return -1;
}
ulog (LOG_ERROR, (const char *) NULL);
}
}
#endif /* ! HAVE_WAIT4 */
#endif /* ! HAVE_WAITPID */
DEBUG_MESSAGE2 (DEBUG_EXECUTE, "%s %d",
WIFEXITED (istat) ? "Exit status" : "Signal",
WIFEXITED (istat) ? WEXITSTATUS (istat) : WTERMSIG (istat));
if (WIFEXITED (istat) && WEXITSTATUS (istat) == 0)
return 0;
if (zreport != NULL)
{
if (! WIFEXITED (istat))
ulog (LOG_ERROR, "%s: Got signal %d", zreport, WTERMSIG (istat));
else
ulog (LOG_ERROR, "%s: Exit status %d", zreport,
WEXITSTATUS (istat));
}
if (WIFEXITED (istat))
return WEXITSTATUS (istat);
else
return -1;
}

View File

@ -0,0 +1,101 @@
/* jobid.c
Convert file names to jobids and vice versa.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uuconf.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
/* Translate a file name and an associated system into a job id.
These job ids are used by uustat. We use the system name attached
to the grade and sequence number. This won't work correctly if the
file name was actually created by some other version of uucp that
uses a different length for the sequence number. Too bad. */
char *
zsfile_to_jobid (qsys, zfile, bgrade)
const struct uuconf_system *qsys;
const char *zfile;
int bgrade;
{
size_t clen;
char *zret;
clen = strlen (qsys->uuconf_zname);
zret = zbufalc (clen + CSEQLEN + 2);
memcpy (zret, qsys->uuconf_zname, clen);
zret[clen] = bgrade;
memcpy (zret + clen + 1, zfile + strlen (zfile) - CSEQLEN, CSEQLEN + 1);
return zret;
}
/* Turn a job id back into a file name. */
char *
zsjobid_to_file (zid, pzsystem, pbgrade)
const char *zid;
char **pzsystem;
char *pbgrade;
{
size_t clen;
const char *zend;
char *zsys;
char abname[CSEQLEN + 11];
char *zret;
clen = strlen (zid);
if (clen <= CSEQLEN)
{
ulog (LOG_ERROR, "%s: Bad job id", zid);
return NULL;
}
zend = zid + clen - CSEQLEN - 1;
zsys = zbufalc (clen - CSEQLEN);
memcpy (zsys, zid, clen - CSEQLEN - 1);
zsys[clen - CSEQLEN - 1] = '\0';
/* This must correspond to zsfile_name. */
#if ! SPOOLDIR_TAYLOR
sprintf (abname, "C.%.7s%s", zsys, zend);
#else
sprintf (abname, "C.%s", zend);
#endif
zret = zsfind_file (abname, zsys, *zend);
if (zret != NULL && pzsystem != NULL)
*pzsystem = zsys;
else
ubuffree (zsys);
if (pbgrade != NULL)
*pbgrade = *zend;
return zret;
}

View File

@ -0,0 +1,41 @@
/* lcksys.c
Lock and unlock a remote system. */
#include "uucp.h"
#include "uudefs.h"
#include "uuconf.h"
#include "sysdep.h"
#include "system.h"
/* Lock a remote system. */
boolean
fsysdep_lock_system (qsys)
const struct uuconf_system *qsys;
{
char *z;
boolean fret;
z = zbufalc (strlen (qsys->uuconf_zname) + sizeof "LCK..");
sprintf (z, "LCK..%.8s", qsys->uuconf_zname);
fret = fsdo_lock (z, FALSE, (boolean *) NULL);
ubuffree (z);
return fret;
}
/* Unlock a remote system. */
boolean
fsysdep_unlock_system (qsys)
const struct uuconf_system *qsys;
{
char *z;
boolean fret;
z = zbufalc (strlen (qsys->uuconf_zname) + sizeof "LCK..");
sprintf (z, "LCK..%.8s", qsys->uuconf_zname);
fret = fsdo_unlock (z, FALSE);
ubuffree (z);
return fret;
}

View File

@ -0,0 +1,38 @@
/* link.c
Link two files. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
boolean
fsysdep_link (zfrom, zto, pfworked)
const char *zfrom;
const char *zto;
boolean *pfworked;
{
*pfworked = FALSE;
if (link (zfrom, zto) == 0)
{
*pfworked = TRUE;
return TRUE;
}
if (errno == ENOENT)
{
if (! fsysdep_make_dirs (zto, TRUE))
return FALSE;
if (link (zfrom, zto) == 0)
{
*pfworked = TRUE;
return TRUE;
}
}
if (errno == EXDEV)
return TRUE;
ulog (LOG_ERROR, "link (%s, %s): %s", zfrom, zto, strerror (errno));
return FALSE;
}

View File

@ -0,0 +1,95 @@
/* locfil.c
Expand a file name on the local system.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <pwd.h>
#if GETPWNAM_DECLARATION_OK
#ifndef getpwnam
extern struct passwd *getpwnam ();
#endif
#endif
/* Turn a file name into an absolute path, by doing tilde expansion
and moving any other type of file into the public directory. */
char *
zsysdep_local_file (zfile, zpubdir)
const char *zfile;
const char *zpubdir;
{
const char *zdir;
if (*zfile == '/')
return zbufcpy (zfile);
if (*zfile != '~')
zdir = zpubdir;
else
{
if (zfile[1] == '\0')
return zbufcpy (zpubdir);
if (zfile[1] == '/')
{
zdir = zpubdir;
zfile += 2;
}
else
{
size_t cuserlen;
char *zcopy;
struct passwd *q;
++zfile;
cuserlen = strcspn ((char *) zfile, "/");
zcopy = zbufalc (cuserlen + 1);
memcpy (zcopy, zfile, cuserlen);
zcopy[cuserlen] = '\0';
q = getpwnam (zcopy);
if (q == NULL)
{
ulog (LOG_ERROR, "User %s not found", zcopy);
ubuffree (zcopy);
return NULL;
}
ubuffree (zcopy);
if (zfile[cuserlen] == '\0')
return zbufcpy (q->pw_dir);
zdir = q->pw_dir;
zfile += cuserlen + 1;
}
}
return zsysdep_in_dir (zdir, zfile);
}

View File

@ -0,0 +1,477 @@
/* lock.c
Lock and unlock a file name.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char lock_rcsid[] = "$Id: lock.c,v 1.1 1993/08/04 19:32:33 jtc Exp $";
#endif
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
/* Lock something. If the fspooldir argument is TRUE, the argument is
a file name relative to the spool directory; otherwise the argument
is a simple file name which should be created in the system lock
directory (under HDB this is /etc/locks). */
boolean
fsdo_lock (zlock, fspooldir, pferr)
const char *zlock;
boolean fspooldir;
boolean *pferr;
{
char *zfree;
const char *zpath, *zslash;
size_t cslash;
pid_t ime;
char *ztempfile;
char abtempfile[sizeof "TMP1234567890"];
int o;
#if HAVE_V2_LOCKFILES
int i;
#else
char ab[12];
#endif
int cwrote;
const char *zerr;
boolean fret;
if (pferr != NULL)
*pferr = TRUE;
if (fspooldir)
{
zfree = NULL;
zpath = zlock;
}
else
{
zfree = zsysdep_in_dir (zSlockdir, zlock);
zpath = zfree;
}
ime = getpid ();
/* We do the actual lock by creating a file and then linking it to
the final file name we want. This avoids race conditions due to
one process checking the file before we have finished writing it,
and also works even if we are somehow running as root.
First, create the file in the right directory (we must create the
file in the same directory since otherwise we might attempt a
cross-device link). */
zslash = strrchr (zpath, '/');
if (zslash == NULL)
cslash = 0;
else
cslash = zslash - zpath + 1;
sprintf (abtempfile, "TMP%010lx", (unsigned long) ime);
ztempfile = zbufalc (cslash + sizeof abtempfile);
memcpy (ztempfile, zpath, cslash);
memcpy (ztempfile + cslash, abtempfile, sizeof abtempfile);
o = creat (ztempfile, IPUBLIC_FILE_MODE);
if (o < 0)
{
if (errno == ENOENT)
{
if (! fsysdep_make_dirs (ztempfile, FALSE))
{
ubuffree (zfree);
ubuffree (ztempfile);
return FALSE;
}
o = creat (ztempfile, IPUBLIC_FILE_MODE);
}
if (o < 0)
{
ulog (LOG_ERROR, "creat (%s): %s", ztempfile, strerror (errno));
ubuffree (zfree);
ubuffree (ztempfile);
return FALSE;
}
}
#if HAVE_V2_LOCKFILES
i = ime;
cwrote = write (o, &i, sizeof i);
#else
sprintf (ab, "%10d\n", (int) ime);
cwrote = write (o, ab, strlen (ab));
#endif
zerr = NULL;
if (cwrote < 0)
zerr = "write";
if (close (o) < 0)
zerr = "close";
if (zerr != NULL)
{
ulog (LOG_ERROR, "%s (%s): %s", zerr, ztempfile, strerror (errno));
(void) remove (ztempfile);
ubuffree (zfree);
ubuffree (ztempfile);
return FALSE;
}
/* Now try to link the file we just created to the lock file that we
want. If it fails, try reading the existing file to make sure
the process that created it still exists. We do this in a loop
to make it easy to retry if the old locking process no longer
exists. */
fret = TRUE;
if (pferr != NULL)
*pferr = FALSE;
o = -1;
zerr = NULL;
while (link (ztempfile, zpath) != 0)
{
int cgot;
int ipid;
boolean freadonly;
fret = FALSE;
if (errno != EEXIST)
{
ulog (LOG_ERROR, "link (%s, %s): %s", ztempfile, zpath,
strerror (errno));
if (pferr != NULL)
*pferr = TRUE;
break;
}
freadonly = FALSE;
o = open ((char *) zpath, O_RDWR | O_NOCTTY, 0);
if (o < 0)
{
if (errno == EACCES)
{
freadonly = TRUE;
o = open ((char *) zpath, O_RDONLY, 0);
}
if (o < 0)
{
if (errno == ENOENT)
{
/* The file was presumably removed between the link
and the open. Try the link again. */
fret = TRUE;
continue;
}
zerr = "open";
break;
}
}
/* The race starts here. See below for a discussion. */
#if HAVE_V2_LOCKFILES
cgot = read (o, &i, sizeof i);
#else
cgot = read (o, ab, sizeof ab - 1);
#endif
if (cgot < 0)
{
zerr = "read";
break;
}
#if HAVE_V2_LOCKFILES
ipid = i;
#else
ab[cgot] = '\0';
ipid = strtol (ab, (char **) NULL, 10);
#endif
/* On NFS, the link might have actually succeeded even though we
got a failure return. This can happen if the original
acknowledgement was lost or delayed and the operation was
retried. In this case the pid will be our own. This
introduces a rather improbable race condition: if a stale
lock was left with our process ID in it, and another process
just did the kill, below, but has not yet changed the lock
file to hold its own process ID, we could start up and make
it all the way to here and think we have the lock. I'm not
going to worry about this possibility. */
if (ipid == ime)
{
fret = TRUE;
break;
}
/* If the process still exists, we will get EPERM rather than
ESRCH. We then return FALSE to indicate that we cannot make
the lock. */
if (kill (ipid, 0) == 0 || errno == EPERM)
break;
ulog (LOG_ERROR, "Found stale lock %s held by process %d",
zpath, ipid);
/* This is a stale lock, created by a process that no longer
exists.
Now we could remove the file (and, if the file mode disallows
writing, that's what we have to do), but we try to avoid
doing so since it causes a race condition. If we remove the
file, and are interrupted any time after we do the read until
we do the remove, another process could get in, open the
file, find that it was a stale lock, remove the file and
create a new one. When we regained control we would remove
the file the other process just created.
These files are being generated partially for the benefit of
cu, and it would be nice to avoid the race however cu avoids
it, so that the programs remain compatible. Unfortunately,
nobody seems to know how cu avoids the race, or even if it
tries to avoid it at all.
There are a few ways to avoid the race. We could use kernel
locking primitives, but they may not be available. We could
link to a special file name, but if that file were left lying
around then no stale lock could ever be broken (Henry Spencer
would think this was a good thing).
Instead I've implemented the following procedure: seek to the
start of the file, write our pid into it, sleep for five
seconds, and then make sure our pid is still there. Anybody
who checks the file while we're asleep will find our pid
there and fail the lock. The only race will come from
another process which has done the read by the time we do our
write. That process will then have five seconds to do its
own write. When we wake up, we'll notice that our pid is no
longer in the file, and retry the lock from the beginning.
This relies on the atomicity of write(2). If it possible for
the writes of two processes to be interleaved, the two
processes could livelock. POSIX unfortunately leaves this
case explicitly undefined; however, given that the write is
of less than a disk block, it's difficult to imagine an
interleave occurring.
Note that this is still a race. If it takes the second
process more than five seconds to do the kill, the lseek, and
the write, both processes will think they have the lock.
Perhaps the length of time to sleep should be configurable.
Even better, perhaps I should add a configuration option to
use a permanent lock file, which eliminates any race and
forces the installer to be aware of the existence of the
permanent lock file.
We stat the file after the sleep, to make sure some other
program hasn't deleted it for us. */
if (freadonly)
{
(void) close (o);
o = -1;
(void) remove (zpath);
continue;
}
if (lseek (o, (off_t) 0, SEEK_SET) != 0)
{
zerr = "lseek";
break;
}
#if HAVE_V2_LOCKFILES
i = ime;
cwrote = write (o, &i, sizeof i);
#else
sprintf (ab, "%10d\n", (int) ime);
cwrote = write (o, ab, strlen (ab));
#endif
if (cwrote < 0)
{
zerr = "write";
break;
}
(void) sleep (5);
if (lseek (o, (off_t) 0, SEEK_SET) != 0)
{
zerr = "lseek";
break;
}
#if HAVE_V2_LOCKFILES
cgot = read (o, &i, sizeof i);
#else
cgot = read (o, ab, sizeof ab - 1);
#endif
if (cgot < 0)
{
zerr = "read";
break;
}
#if HAVE_V2_LOCKFILES
ipid = i;
#else
ab[cgot] = '\0';
ipid = strtol (ab, (char **) NULL, 10);
#endif
if (ipid == ime)
{
struct stat sfile, sdescriptor;
/* It looks like we have the lock. Do the final stat
check. */
if (stat ((char *) zpath, &sfile) < 0)
{
if (errno != ENOENT)
{
zerr = "stat";
break;
}
/* Loop around and try again. */
}
else
{
if (fstat (o, &sdescriptor) < 0)
{
zerr = "fstat";
break;
}
if (sfile.st_ino == sdescriptor.st_ino
&& sfile.st_dev == sdescriptor.st_dev)
{
/* Close the file before assuming we've succeeded to
pick up any trailing errors. */
if (close (o) < 0)
{
zerr = "close";
break;
}
o = -1;
/* We have the lock. */
fret = TRUE;
break;
}
}
}
/* Loop around and try the lock again. We keep doing this until
the lock file holds a pid that exists. */
(void) close (o);
o = -1;
fret = TRUE;
}
if (zerr != NULL)
{
ulog (LOG_ERROR, "%s (%s): %s", zerr, zpath, strerror (errno));
if (pferr != NULL)
*pferr = TRUE;
}
if (o >= 0)
(void) close (o);
ubuffree (zfree);
/* It would be nice if we could leave the temporary file around for
future calls, but considering that we create lock files in
various different directories it's probably more trouble than
it's worth. */
if (remove (ztempfile) != 0)
ulog (LOG_ERROR, "remove (%s): %s", ztempfile, strerror (errno));
ubuffree (ztempfile);
return fret;
}
/* Unlock something. The fspooldir argument is as in fsdo_lock. */
boolean
fsdo_unlock (zlock, fspooldir)
const char *zlock;
boolean fspooldir;
{
char *zfree;
const char *zpath;
if (fspooldir)
{
zfree = NULL;
zpath = zlock;
}
else
{
zfree = zsysdep_in_dir (zSlockdir, zlock);
zpath = zfree;
}
if (remove (zpath) == 0
|| errno == ENOENT)
{
ubuffree (zfree);
return TRUE;
}
else
{
ulog (LOG_ERROR, "remove (%s): %s", zpath, strerror (errno));
ubuffree (zfree);
return FALSE;
}
}

View File

@ -0,0 +1,25 @@
/* loctim.c
Turn a time epoch into a struct tm. This is trivial on Unix. */
#include "uucp.h"
#if HAVE_TIME_H
#include <time.h>
#endif
#include "system.h"
#ifndef localtime
extern struct tm *localtime ();
#endif
void
usysdep_localtime (itime, q)
long itime;
struct tm *q;
{
time_t i;
i = (time_t) itime;
*q = *localtime (&i);
}

View File

@ -0,0 +1,85 @@
/* mail.c
Send mail to a user.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_TIME_H
#include <time.h>
#endif
#ifndef ctime
extern char *ctime ();
#endif
/* Mail a message to a user. */
boolean
fsysdep_mail (zto, zsubject, cstrs, paz)
const char *zto;
const char *zsubject;
int cstrs;
const char **paz;
{
const char *az[3];
FILE *e;
pid_t ipid;
time_t itime;
int i;
az[0] = MAIL_PROGRAM;
az[1] = zto;
az[2] = NULL;
e = espopen (az, FALSE, &ipid);
if (e == NULL)
{
ulog (LOG_ERROR, "espopen (%s): %s", MAIL_PROGRAM,
strerror (errno));
return FALSE;
}
fprintf (e, "Subject: %s\n", zsubject);
fprintf (e, "To: %s\n", zto);
fprintf (e, "\n");
(void) time (&itime);
/* Remember that ctime includes a \n, so this skips a line. */
fprintf (e, "Message from UUCP on %s %s\n", zSlocalname,
ctime (&itime));
for (i = 0; i < cstrs; i++)
fputs (paz[i], e);
(void) fclose (e);
return ixswait ((unsigned long) ipid, MAIL_PROGRAM) == 0;
}

View File

@ -0,0 +1,58 @@
/* mkdir.c
Create a directory. We must go through a subsidiary program to
force our real uid to be the uucp owner before invoking the setuid
/bin/mkdir program. */
#include "uucp.h"
#include "sysdep.h"
#include <errno.h>
int
mkdir (zdir, imode)
const char *zdir;
int imode;
{
struct stat s;
const char *azargs[3];
int aidescs[3];
pid_t ipid;
/* Make sure the directory does not exist, since we will otherwise
get the wrong errno value. */
if (stat (zdir, &s) == 0)
{
errno = EEXIST;
return -1;
}
/* /bin/mkdir will create the directory with mode 777, so we set our
umask to get the mode we want. */
(void) umask ((~ imode) & (S_IRWXU | S_IRWXG | S_IRWXO));
azargs[0] = UUDIR_PROGRAM;
azargs[1] = zdir;
azargs[2] = NULL;
aidescs[0] = SPAWN_NULL;
aidescs[1] = SPAWN_NULL;
aidescs[2] = SPAWN_NULL;
ipid = ixsspawn (azargs, aidescs, FALSE, FALSE, (const char *) NULL,
TRUE, FALSE, (const char *) NULL,
(const char *) NULL, (const char *) NULL);
(void) umask (0);
if (ipid < 0)
return -1;
if (ixswait ((unsigned long) ipid, (const char *) NULL) != 0)
{
/* Make up an errno value. */
errno = EACCES;
return -1;
}
return 0;
}

View File

@ -0,0 +1,49 @@
/* mkdirs.c
Create any directories needed for a file name. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
boolean
fsysdep_make_dirs (zfile, fpublic)
const char *zfile;
boolean fpublic;
{
char *zcopy, *z;
int imode;
zcopy = zbufcpy (zfile);
if (fpublic)
imode = IPUBLIC_DIRECTORY_MODE;
else
imode = IDIRECTORY_MODE;
for (z = zcopy; *z != '\0'; z++)
{
if (*z == '/' && z != zcopy)
{
*z = '\0';
if (! fsysdep_directory (zcopy))
{
if (mkdir (zcopy, imode) != 0)
{
ulog (LOG_ERROR, "mkdir (%s): %s", zcopy,
strerror (errno));
ubuffree (zcopy);
return FALSE;
}
}
*z = '/';
}
}
ubuffree (zcopy);
return TRUE;
}

View File

@ -0,0 +1,33 @@
/* mode.c
Get the Unix file mode of a file. */
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
unsigned int
ixsysdep_file_mode (zfile)
const char *zfile;
{
struct stat s;
if (stat ((char *) zfile, &s) != 0)
{
ulog (LOG_ERROR, "stat (%s): %s", zfile, strerror (errno));
return 0;
}
#if S_IRWXU != 0700
#error Files modes need to be translated
#endif
/* We can't return 0, since that indicate an error. */
if ((s.st_mode & 0777) == 0)
return 0400;
return s.st_mode & 0777;
}

View File

@ -0,0 +1,176 @@
/* move.c
Move a file.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
/* Move (rename) a file from one name to another. This routine will
optionally create necessary directories, and fpublic indicates
whether the new directories should be publically accessible or not.
If fcheck is true, it will try to determine whether the named user
has write access to the new file. */
boolean
fsysdep_move_file (zorig, zto, fmkdirs, fpublic, fcheck, zuser)
const char *zorig;
const char *zto;
boolean fmkdirs;
boolean fpublic;
boolean fcheck;
const char *zuser;
{
struct stat s;
int o;
DEBUG_MESSAGE2 (DEBUG_SPOOLDIR,
"fsysdep_move_file: Moving %s to %s", zorig, zto);
/* Optionally make sure that zuser has write access on the
directory. */
if (fcheck)
{
char *zcopy;
char *zslash;
zcopy = zbufcpy (zto);
zslash = strrchr (zcopy, '/');
if (zslash == zcopy)
zslash[1] = '\0';
else
*zslash = '\0';
if (stat (zcopy, &s) != 0)
{
ulog (LOG_ERROR, "stat (%s): %s", zcopy, strerror (errno));
(void) remove (zorig);
ubuffree (zcopy);
return FALSE;
}
if (! fsuser_access (&s, W_OK, zuser))
{
ulog (LOG_ERROR, "%s: %s", zcopy, strerror (EACCES));
(void) remove (zorig);
ubuffree (zcopy);
return FALSE;
}
ubuffree (zcopy);
/* A malicious user now has a few milliseconds to change a
symbolic link to a directory uucp has write permission on but
the user does not (the obvious choice being /usr/lib/uucp).
The only certain method I can come up with to close this race
is to fork an suid process which takes on the users identity
and does the actual copy. This is sufficiently high overhead
that I'm not going to do it. */
}
/* We try to use rename to move the file. */
if (rename (zorig, zto) == 0)
return TRUE;
if (fmkdirs && errno == ENOENT)
{
if (! fsysdep_make_dirs (zto, fpublic))
{
(void) remove (zorig);
return FALSE;
}
if (rename (zorig, zto) == 0)
return TRUE;
}
#if HAVE_RENAME
/* On some systems the system call rename seems to fail for
arbitrary reasons. To get around this, we always try to copy the
file by hand if the rename failed. */
errno = EXDEV;
#endif
/* If we can't link across devices, we must copy the file by hand. */
if (errno != EXDEV)
{
ulog (LOG_ERROR, "rename (%s, %s): %s", zorig, zto,
strerror (errno));
(void) remove (zorig);
return FALSE;
}
/* Copy the file. */
if (stat ((char *) zorig, &s) < 0)
{
ulog (LOG_ERROR, "stat (%s): %s", zorig, strerror (errno));
(void) remove (zorig);
return FALSE;
}
/* Make sure the file gets the right mode by creating it before we
call fcopy_file. */
(void) remove (zto);
o = creat ((char *) zto, s.st_mode);
if (o < 0)
{
if (fmkdirs && errno == ENOENT)
{
if (! fsysdep_make_dirs (zto, fpublic))
{
(void) remove (zorig);
return FALSE;
}
o = creat ((char *) zto, s.st_mode);
}
if (o < 0)
{
ulog (LOG_ERROR, "creat (%s): %s", zto, strerror (errno));
(void) remove (zorig);
return FALSE;
}
}
(void) close (o);
if (! fcopy_file (zorig, zto, fpublic, fmkdirs))
{
(void) remove (zorig);
return FALSE;
}
if (remove (zorig) != 0)
ulog (LOG_ERROR, "remove (%s): %s", zorig, strerror (errno));
return TRUE;
}

View File

@ -0,0 +1,244 @@
/* opensr.c
Open files for sending and receiving.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
#include "sysdep.h"
#include <errno.h>
#if HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
#ifndef O_RDONLY
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
#ifndef time
extern time_t time ();
#endif
/* Open a file to send to another system, and return the mode and
the size. */
openfile_t
esysdep_open_send (qsys, zfile, fcheck, zuser)
const struct uuconf_system *qsys;
const char *zfile;
boolean fcheck;
const char *zuser;
{
struct stat s;
openfile_t e;
int o;
if (fsysdep_directory (zfile))
{
ulog (LOG_ERROR, "%s: is a directory", zfile);
return EFILECLOSED;
}
#if USE_STDIO
e = fopen (zfile, BINREAD);
if (e == NULL)
{
ulog (LOG_ERROR, "fopen (%s): %s", zfile, strerror (errno));
return NULL;
}
o = fileno (e);
#else
e = open ((char *) zfile, O_RDONLY | O_NOCTTY, 0);
if (e == -1)
{
ulog (LOG_ERROR, "open (%s): %s", zfile, strerror (errno));
return -1;
}
o = e;
#endif
if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0)
{
ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
(void) ffileclose (e);
return EFILECLOSED;
}
if (fstat (o, &s) == -1)
{
ulog (LOG_ERROR, "fstat: %s", strerror (errno));
s.st_mode = 0666;
}
/* We have to recheck the file permission, although we probably
checked it already, because otherwise there would be a window in
which somebody could change the contents of a symbolic link to
point to some file which was only readable by uucp. */
if (fcheck)
{
if (! fsuser_access (&s, R_OK, zuser))
{
ulog (LOG_ERROR, "%s: %s", zfile, strerror (EACCES));
(void) ffileclose (e);
return EFILECLOSED;
}
}
return e;
}
/* Get a temporary file name to receive into. We use the ztemp
argument to pick the file name, so that we relocate the file if the
transmission is aborted. */
char *
zsysdep_receive_temp (qsys, zto, ztemp)
const struct uuconf_system *qsys;
const char *zto;
const char *ztemp;
{
if (ztemp != NULL
&& *ztemp == 'D'
&& strcmp (ztemp, "D.0") != 0)
return zsappend3 (".Temp", qsys->uuconf_zname, ztemp);
else
return zstemp_file (qsys);
}
/* Open a temporary file to receive into. This should, perhaps, check
that we have write permission on the receiving directory, but it
doesn't. */
openfile_t
esysdep_open_receive (qsys, zto, ztemp, zreceive, pcrestart)
const struct uuconf_system *qsys;
const char *zto;
const char *ztemp;
const char *zreceive;
long *pcrestart;
{
int o;
openfile_t e;
/* If we used the ztemp argument in zsysdep_receive_temp, above,
then we will have a name consistent across conversations. In
that case, we may have already received some portion of this
file. */
o = -1;
*pcrestart = -1;
if (ztemp != NULL
&& *ztemp == 'D'
&& strcmp (ztemp, "D.0") != 0)
{
o = open ((char *) zreceive, O_WRONLY);
if (o >= 0)
{
struct stat s;
/* For safety, we insist on the file being less than 1 week
old. This can still catch people, unfortunately. I
don't know of any good solution to the problem of old
files hanging around. If anybody has a file they want
restarted, and they know about this issue, they can touch
it to bring it up to date. */
if (fstat (o, &s) < 0
|| s.st_mtime + 7 * 24 * 60 * 60 < time ((time_t *) NULL))
{
(void) close (o);
o = -1;
}
else
{
DEBUG_MESSAGE1 (DEBUG_SPOOLDIR,
"esysdep_open_receive: Reusing %s",
zreceive);
*pcrestart = (long) s.st_size;
}
}
}
if (o < 0)
o = creat ((char *) zreceive, IPRIVATE_FILE_MODE);
if (o < 0)
{
if (errno == ENOENT)
{
if (! fsysdep_make_dirs (zreceive, FALSE))
return EFILECLOSED;
o = creat ((char *) zreceive, IPRIVATE_FILE_MODE);
}
if (o < 0)
{
ulog (LOG_ERROR, "creat (%s): %s", zreceive, strerror (errno));
return EFILECLOSED;
}
}
if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0)
{
ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
(void) close (o);
(void) remove (zreceive);
return EFILECLOSED;
}
#if USE_STDIO
e = fdopen (o, (char *) BINWRITE);
if (e == NULL)
{
ulog (LOG_ERROR, "fdopen (%s): %s", zreceive, strerror (errno));
(void) close (o);
(void) remove (zreceive);
return EFILECLOSED;
}
#else
e = o;
#endif
return e;
}

View File

@ -0,0 +1,96 @@
/* pause.c
Pause for half a second. */
#include "uucp.h"
#include "sysdep.h"
#include "system.h"
/* Pick a timing routine to use. I somewhat arbitrarily picked usleep
above nap above napms above poll above select. */
#if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS || HAVE_POLL
#undef HAVE_SELECT
#define HAVE_SELECT 0
#endif
#if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS
#undef HAVE_POLL
#define HAVE_POLL 0
#endif
#if HAVE_USLEEP || HAVE_NAP
#undef HAVE_NAPMS
#define HAVE_NAPMS 0
#endif
#if HAVE_USLEEP
#undef HAVE_NAP
#define HAVE_NAP 0
#endif
#if HAVE_SELECT
#include <sys/time.h>
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif
#if HAVE_POLL
#if HAVE_STROPTS_H
#include <stropts.h>
#endif
#if HAVE_POLL_H
#include <poll.h>
#endif
#if ! HAVE_STROPTS_H && ! HAVE_POLL_H
/* We need a definition for struct pollfd, although it doesn't matter
what it contains. */
struct pollfd
{
int idummy;
};
#endif /* ! HAVE_STROPTS_H && ! HAVE_POLL_H */
#endif /* HAVE_POLL */
#if HAVE_TIME_H
#if HAVE_SYS_TIME_AND_TIME_H || ! USE_SELECT_TIMER
#include <time.h>
#endif
#endif
void
usysdep_pause ()
{
#if HAVE_NAPMS
napms (500);
#endif /* HAVE_NAPMS */
#if HAVE_NAP
#if HAVE_HUNDREDTHS_NAP
nap (50L);
#else
nap (500L);
#endif /* ! HAVE_HUNDREDTHS_NAP */
#endif /* HAVE_NAP */
#if HAVE_USLEEP
usleep (500 * (long) 1000);
#endif /* HAVE_USLEEP */
#if HAVE_POLL
struct pollfd sdummy;
/* We need to pass an unused pollfd structure because poll checks
the address before checking the number of elements. */
poll (&sdummy, 0, 500);
#endif /* HAVE_POLL */
#if HAVE_SELECT
struct timeval s;
s.tv_sec = 0;
s.tv_usec = 500 * (long) 1000;
select (0, (pointer) NULL, (pointer) NULL, (pointer) NULL, &s);
#endif /* USE_SELECT_TIMER */
#if ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP
#if ! USE_SELECT_TIMER && ! HAVE_POLL
sleep (1);
#endif /* ! USE_SELECT_TIMER && ! HAVE_POLL */
#endif /* ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP */
}

View File

@ -0,0 +1,230 @@
/* picksb.c
System dependent routines for uupick.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#if USE_RCS_ID
const char picksb_rcsid[] = "$Id: picksb.c,v 1.1 1993/08/04 19:32:42 jtc Exp $";
#endif
#include "uudefs.h"
#include "system.h"
#include "sysdep.h"
#include <errno.h>
#include <pwd.h>
#if HAVE_OPENDIR
#if HAVE_DIRENT_H
#include <dirent.h>
#else /* ! HAVE_DIRENT_H */
#include <sys/dir.h>
#define dirent direct
#endif /* ! HAVE_DIRENT_H */
#endif /* HAVE_OPENDIR */
#if GETPWUID_DECLARATION_OK
#ifndef getpwuid
extern struct passwd *getpwuid ();
#endif
#endif
/* Local variables. */
/* Directory of ~/receive/USER. */
static DIR *qStopdir;
/* Name of ~/receive/USER. */
static char *zStopdir;
/* Directory of ~/receive/USER/SYSTEM. */
static DIR *qSsysdir;
/* Name of system. */
static char *zSsysdir;
/* Prepare to get a list of all the file to uupick for this user. */
/*ARGSUSED*/
boolean
fsysdep_uupick_init (zsystem, zpubdir)
const char *zsystem;
const char *zpubdir;
{
const char *zuser;
zuser = zsysdep_login_name ();
zStopdir = (char *) xmalloc (strlen (zpubdir)
+ sizeof "/receive/"
+ strlen (zuser));
sprintf (zStopdir, "%s/receive/%s", zpubdir, zuser);
qStopdir = opendir (zStopdir);
if (qStopdir == NULL && errno != ENOENT)
{
ulog (LOG_ERROR, "opendir (%s): %s", zStopdir,
strerror (errno));
return FALSE;
}
qSsysdir = NULL;
return TRUE;
}
/* Return the next file from the uupick directories. */
/*ARGSUSED*/
char *
zsysdep_uupick (zsysarg, zpubdir, pzfrom, pzfull)
const char *zsysarg;
const char *zpubdir;
char **pzfrom;
char **pzfull;
{
struct dirent *qentry;
while (TRUE)
{
while (qSsysdir == NULL)
{
const char *zsystem;
char *zdir;
if (qStopdir == NULL)
return NULL;
if (zsysarg != NULL)
{
closedir (qStopdir);
qStopdir = NULL;
zsystem = zsysarg;
}
else
{
do
{
qentry = readdir (qStopdir);
if (qentry == NULL)
{
closedir (qStopdir);
qStopdir = NULL;
return NULL;
}
}
while (strcmp (qentry->d_name, ".") == 0
|| strcmp (qentry->d_name, "..") == 0);
zsystem = qentry->d_name;
}
zdir = zbufalc (strlen (zStopdir) + strlen (zsystem) + sizeof "/");
sprintf (zdir, "%s/%s", zStopdir, zsystem);
qSsysdir = opendir (zdir);
if (qSsysdir == NULL)
{
if (errno != ENOENT && errno != ENOTDIR)
ulog (LOG_ERROR, "opendir (%s): %s", zdir, strerror (errno));
}
else
{
ubuffree (zSsysdir);
zSsysdir = zbufcpy (zsystem);
}
ubuffree (zdir);
}
qentry = readdir (qSsysdir);
if (qentry == NULL)
{
closedir (qSsysdir);
qSsysdir = NULL;
continue;
}
if (strcmp (qentry->d_name, ".") == 0
|| strcmp (qentry->d_name, "..") == 0)
continue;
*pzfrom = zbufcpy (zSsysdir);
*pzfull = zsappend3 (zStopdir, zSsysdir, qentry->d_name);
return zbufcpy (qentry->d_name);
}
}
/*ARGSUSED*/
boolean
fsysdep_uupick_free (zsystem, zpubdir)
const char *zsystem;
const char *zpubdir;
{
xfree ((pointer) zStopdir);
if (qStopdir != NULL)
{
closedir (qStopdir);
qStopdir = NULL;
}
ubuffree (zSsysdir);
zSsysdir = NULL;
if (qSsysdir != NULL)
{
closedir (qSsysdir);
qSsysdir = NULL;
}
return TRUE;
}
/* Expand a local file name for uupick. */
char *
zsysdep_uupick_local_file (zfile)
const char *zfile;
{
struct passwd *q;
/* If this does not start with a simple ~, pass it to
zsysdep_local_file_cwd; as it happens, zsysdep_local_file_cwd
only uses the zpubdir argument if the file starts with a simple
~, so it doesn't really matter what we pass for zpubdir. */
if (zfile[0] != '~'
|| (zfile[1] != '/' && zfile[1] != '\0'))
return zsysdep_local_file_cwd (zfile, (const char *) NULL);
q = getpwuid (getuid ());
if (q == NULL)
{
ulog (LOG_ERROR, "Can't get home directory");
return NULL;
}
if (zfile[1] == '\0')
return zbufcpy (q->pw_dir);
return zsysdep_in_dir (q->pw_dir, zfile + 2);
}

View File

@ -0,0 +1,51 @@
/* portnm.c
Get the port name of stdin. */
#include "uucp.h"
#include "sysdep.h"
#include "system.h"
#if HAVE_TCP
#if HAVE_SYS_TYPES_TCP_H
#include <sys/types.tcp.h>
#endif
#include <sys/socket.h>
#endif
#ifndef ttyname
extern char *ttyname ();
#endif
/* Get the port name of standard input. I assume that Unix systems
generally support ttyname. If they don't, this function can just
return NULL. It uses getsockname to see whether standard input is
a TCP connection. */
const char *
zsysdep_port_name (ftcp_port)
boolean *ftcp_port;
{
const char *z;
*ftcp_port = FALSE;
#if HAVE_TCP
{
size_t clen;
struct sockaddr s;
clen = sizeof (struct sockaddr);
if (getsockname (0, &s, &clen) == 0)
*ftcp_port = TRUE;
}
#endif /* HAVE_TCP */
z = ttyname (0);
if (z == NULL)
return NULL;
if (strncmp (z, "/dev/", sizeof "/dev/" - 1) == 0)
return z + sizeof "/dev/" - 1;
else
return z;
}

View File

@ -0,0 +1,197 @@
/* proctm.c
Get the time spent in the process.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "sysdep.h"
#include "system.h"
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#if HAVE_LIMITS_H
#include <limits.h>
#endif
/* Prefer gettimeofday to ftime to times. */
#if HAVE_GETTIMEOFDAY || HAVE_FTIME
#undef HAVE_TIMES
#define HAVE_TIMES 0
#endif
#if HAVE_GETTIMEOFDAY
#undef HAVE_FTIME
#define HAVE_FTIME 0
#endif
#if HAVE_TIME_H && (HAVE_SYS_TIME_AND_TIME_H || ! HAVE_GETTIMEOFDAY)
#include <time.h>
#endif
#if HAVE_GETTIMEOFDAY
#include <sys/time.h>
#endif
#if HAVE_FTIME
#include <sys/timeb.h>
#endif
#if HAVE_TIMES
#if HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
#if TIMES_DECLARATION_OK
/* We use a macro to protect this because times really returns clock_t
and on some systems, such as Ultrix 4.0, clock_t is int. We don't
leave it out entirely because on some systems, such as System III,
the declaration is necessary for correct compilation. */
#ifndef times
extern long times ();
#endif
#endif /* TIMES_DECLARATION_OK */
#ifdef _SC_CLK_TCK
#define HAVE_SC_CLK_TCK 1
#else
#define HAVE_SC_CLK_TCK 0
#endif
/* TIMES_TICK may have been set in policy.h, or we may be able to get
it using sysconf. If neither is the case, try to find a useful
definition from the system header files. */
#if TIMES_TICK == 0 && (! HAVE_SYSCONF || ! HAVE_SC_CLK_TCK)
#ifdef CLK_TCK
#undef TIMES_TICK
#define TIMES_TICK CLK_TCK
#else /* ! defined (CLK_TCK) */
#ifdef HZ
#undef TIMES_TICK
#define TIMES_TICK HZ
#endif /* defined (HZ) */
#endif /* ! defined (CLK_TCK) */
#endif /* TIMES_TICK == 0 && (! HAVE_SYSCONF || ! HAVE_SC_CLK_TCK) */
#endif /* HAVE_TIMES */
#ifndef time
extern time_t time ();
#endif
#if HAVE_SYSCONF
#ifndef sysconf
extern long sysconf ();
#endif
#endif
/* Get the time in seconds and microseconds; this need only work
within the process when called from the system independent code.
It is also called by ixsysdep_time. */
long
ixsysdep_process_time (pimicros)
long *pimicros;
{
#if HAVE_GETTIMEOFDAY
struct timeval stime;
struct timezone stz;
(void) gettimeofday (&stime, &stz);
if (pimicros != NULL)
*pimicros = (long) stime.tv_usec;
return (long) stime.tv_sec;
#endif /* HAVE_GETTIMEOFDAY */
#if HAVE_FTIME
static boolean fbad;
if (! fbad)
{
struct timeb stime;
static struct timeb slast;
(void) ftime (&stime);
/* On some systems, such as SCO 3.2.2, ftime can go backwards in
time. If we detect this, we switch to using time. */
if (slast.time != 0
&& (stime.time < slast.time
|| (stime.time == slast.time &&
stime.millitm < slast.millitm)))
fbad = TRUE;
else
{
slast = stime;
if (pimicros != NULL)
*pimicros = (long) stime.millitm * (long) 1000;
return (long) stime.time;
}
}
if (pimicros != NULL)
*pimicros = 0;
return (long) time ((time_t *) NULL);
#endif /* HAVE_FTIME */
#if HAVE_TIMES
struct tms s;
long i;
static int itick;
if (itick == 0)
{
#if TIMES_TICK == 0
#if HAVE_SYSCONF && HAVE_SC_CLK_TCK
itick = (int) sysconf (_SC_CLK_TCK);
#else /* ! HAVE_SYSCONF || ! HAVE_SC_CLK_TCK */
const char *z;
z = getenv ("HZ");
if (z != NULL)
itick = (int) strtol (z, (char **) NULL, 10);
/* If we really couldn't get anything, just use 60. */
if (itick == 0)
itick = 60;
#endif /* ! HAVE_SYSCONF || ! HAVE_SC_CLK_TCK */
#else /* TIMES_TICK != 0 */
itick = TIMES_TICK;
#endif /* TIMES_TICK == 0 */
}
i = (long) times (&s);
if (pimicros != NULL)
*pimicros = (i % (long) itick) * ((long) 1000000 / (long) itick);
return i / (long) itick;
#endif /* HAVE_TIMES */
#if ! HAVE_GETTIMEOFDAY && ! HAVE_FTIME && ! HAVE_TIMES
if (pimicros != NULL)
*pimicros = 0;
return (long) time ((time_t *) NULL);
#endif /* ! HAVE_GETTIMEOFDAY && ! HAVE_FTIME && ! HAVE_TIMES */
}

View File

@ -0,0 +1,197 @@
/* recep.c
See whether a file has already been received.
Copyright (C) 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
*/
#include "uucp.h"
#include "uudefs.h"
#include "uuconf.h"
#include "sysdep.h"
#include "system.h"
#include <errno.h>
#if HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#else
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#endif
static char *zsreceived_name P((const struct uuconf_system *qsys,
const char *ztemp));
/* These routines are used to see whether we have already received a
file in a previous UUCP connection. It is possible for the
acknowledgement of a received file to be lost. The sending system
will then now know that the file was correctly received, and will
send it again. This can be a problem particularly with protocols
which support channels, since they may send several small files in
a single window, all of which may be received correctly although
the sending system never sees the acknowledgement. If these files
involve an execution, the execution will happen twice, which will
be bad.
We use a simple system. For each file we want to remember, we
create an empty file names .Received/SYS/TEMP, where SYS is the
name of the system and TEMP is the name of the temporary file used
by the sender. If no temporary file is used by the sender, we
don't remember that we received the file. This is not perfect, but
execution files will always have a temporary file, so the most
important case is handled. Also, any file received from Taylor
UUCP 1.04 or greater will always have a temporary file. */
/* Return the name we are going use for the marker, or NULL if we have
no name. */
static char *
zsreceived_name (qsys, ztemp)
const struct uuconf_system *qsys;
const char *ztemp;
{
if (ztemp != NULL
&& *ztemp == 'D'
&& strcmp (ztemp, "D.0") != 0)
return zsappend3 (".Received", qsys->uuconf_zname, ztemp);
else
return NULL;
}
/* Remember that we have already received a file. */
/*ARGSUSED*/
boolean
fsysdep_remember_reception (qsys, zto, ztemp)
const struct uuconf_system *qsys;
const char *zto;
const char *ztemp;
{
char *zfile;
int o;
zfile = zsreceived_name (qsys, ztemp);
if (zfile == NULL)
return TRUE;
o = creat (zfile, IPUBLIC_FILE_MODE);
if (o < 0)
{
if (errno == ENOENT)
{
if (fsysdep_make_dirs (zfile, TRUE))
{
ubuffree (zfile);
return FALSE;
}
o = creat (zfile, IPUBLIC_FILE_MODE);
}
if (o < 0)
{
ulog (LOG_ERROR, "creat (%s): %s", zfile, strerror (errno));
ubuffree (zfile);
return FALSE;
}
}
ubuffree (zfile);
/* We don't have to actually put anything in the file; we just use
the name. This is more convenient than keeping a file with a
list of names. */
if (close (o) < 0)
{
ulog (LOG_ERROR, "fsysdep_remember_reception: close: %s",
strerror (errno));
return FALSE;
}
return TRUE;
}
/* See if we have already received a file. Note that don't delete the
marker file here, because we need to know that the sending system
has received our denial first. This function returns TRUE if the
file has already been received, FALSE if it has not. */
/*ARGSUSED*/
boolean
fsysdep_already_received (qsys, zto, ztemp)
const struct uuconf_system *qsys;
const char *zto;
const char *ztemp;
{
char *zfile;
struct stat s;
boolean fret;
zfile = zsreceived_name (qsys, ztemp);
if (zfile == NULL)
return FALSE;
if (stat (zfile, &s) < 0)
{
if (errno != ENOENT)
ulog (LOG_ERROR, "stat (%s): %s", zfile, strerror (errno));
ubuffree (zfile);
return FALSE;
}
/* Ignore the file (return FALSE) if it is over one week old. */
fret = s.st_mtime + 7 * 24 * 60 * 60 >= time ((time_t *) NULL);
if (fret)
DEBUG_MESSAGE1 (DEBUG_SPOOLDIR, "fsysdep_already_received: Found %s",
zfile);
ubuffree (zfile);
return fret;
}
/* Forget that we have received a file. */
/*ARGSUSED*/
boolean
fsysdep_forget_reception (qsys, zto, ztemp)
const struct uuconf_system *qsys;
const char *zto;
const char *ztemp;
{
char *zfile;
zfile = zsreceived_name (qsys, ztemp);
if (zfile == NULL)
return TRUE;
if (remove (zfile) < 0
&& errno != ENOENT)
{
ulog (LOG_ERROR, "remove (%s): %s", zfile, strerror (errno));
ubuffree (zfile);
return FALSE;
}
return TRUE;
}

Some files were not shown because too many files have changed in this diff Show More