Initial revision
This commit is contained in:
commit
69f117bf78
60
CHANGES
Normal file
60
CHANGES
Normal file
@ -0,0 +1,60 @@
|
||||
* New: now "bforce" can start outgoing sessions simply on stdin/stdout.
|
||||
(command line option "-o")
|
||||
* New: file boxes support. New config keywords "filebox" and
|
||||
"filebox_directory"
|
||||
* Bugfix: now "bforce" will remove .bsy locks immediately after
|
||||
disconnection
|
||||
* New: implemented CRAM-MD5 authentication in the BinkP protocol
|
||||
* New: new command line option "-c" in the "bfstat" utility
|
||||
* New: BinkP seems to be working fine now
|
||||
* Bugfix: some file names could be spoiled on the Hydra protocol while
|
||||
receiving (it is a bug with receiving files with the name "d" instead
|
||||
of the real one)
|
||||
* New: implementation of the YooHoo handshake protocol
|
||||
* New: now will create .csy locks while dialing and convert it to
|
||||
the .bsy only at handshake
|
||||
* Bugfix: now daemon will not call to the nodes marked as Hold/Down
|
||||
in a nodelist
|
||||
* New: added sessions history loging. New config keyword "sessions_history"
|
||||
For the history file format look sources.
|
||||
* Bugfix: Hydra didn't send "short" file name, as a result some mailers
|
||||
with strict checks could not receive files with long names :))
|
||||
* New: removed check for "short" file name length in the Hydra
|
||||
|
||||
0.22 (31-07-2000)
|
||||
|
||||
* Bugfix: at incoming sessions used speed limit for outgoing sessions
|
||||
* Bugfix: RH1 mode didn't work correctly
|
||||
* Bugfix: outgoing BinkP password protected sessions allways fail
|
||||
with invalid password error
|
||||
* Bugfix: files from the AmigaDos Outbound send in incorrect order
|
||||
* New: passwords are case insensitive now (again)
|
||||
* New: improved EMSI handshake, now it should work better with systems
|
||||
using Cisco or something like that with login prompt
|
||||
* New: added writing of the remote intro to log (like *ico). To control
|
||||
this feature added new option "[No]Intro"
|
||||
* New: protocol selection options now works at incoming sessions too
|
||||
* New: added support for modem chat commands, e.g "ATz| ATm0|", mailer
|
||||
will wait for modem response ("OK" or "ERROR") after sending each
|
||||
substring and only then send the next one
|
||||
* Bugfix: file masks checker didn't work correctly than '!' (not)
|
||||
prefix was used. Now "DelayFiles", "SkipFiles" should work normaly
|
||||
* New: Added new expression elements: Exist <file name>, Mailer <mailer
|
||||
name substring>, Port <port name substring>
|
||||
* New: Added autoconfiguration of UUCP lock files directory
|
||||
* Bugfix: daemon could call even to "-Unpublished-" phone if it was
|
||||
specified in override.
|
||||
* Bugfix: could not parse received EMSI data packet if character ']' was
|
||||
escaped as '\5d' by remote mailer (e.g. DVMMail do such escaping)
|
||||
* New: added support for Tx/Rx windows and ASC/UUE packets in the Hydra
|
||||
* Bugfix: files skipped by remote mailer was not really skipped :)
|
||||
* New: extended algorithm of renaming received file if file with such name
|
||||
allready exist in the inbound directory:
|
||||
- For netmail packets and '.tic' files: generate new random name
|
||||
- For arcmail packets: rotate extension characters, as most other mailers do
|
||||
- For file requests: allways overwrite existing file
|
||||
- For all other files: add numeric extension as in previous versions
|
||||
* New: added ability to recode file names and intro text to another charset
|
||||
then sending/receiving. Recode tables are compartible with HPT. New
|
||||
config keywords: "Recode_file_in", "Recode_file_out", "Recode_intro_in"
|
||||
|
||||
67
CHANGES.kst
Normal file
67
CHANGES.kst
Normal file
@ -0,0 +1,67 @@
|
||||
0.22.7.kst1
|
||||
===========
|
||||
|
||||
* Attempt to fix warnings, when compiling with -Wall.
|
||||
+ make update -- install only binaries.
|
||||
* Better EMSI handling, when calling to cisco.
|
||||
+ Correct ZMH support in daemon.
|
||||
* Some fixes in contributed perl scripts.
|
||||
|
||||
0.22.7.kst2
|
||||
===========
|
||||
|
||||
+ Added option --with-uucp-lockdir=... to configure.
|
||||
* Using strncpy(3) instead of strcpy(3) if possible.
|
||||
|
||||
Added patches by Maxi Rovnich @ 2:5030/872:
|
||||
+ Support for maximum 'no dialtone' count.
|
||||
+ Support for download resyncing, while checking for free space.
|
||||
+ Ignore all files, but *.pnt, *.req, *.?lo and *.?ut in BSO.
|
||||
|
||||
0.22.7.kst3
|
||||
===========
|
||||
|
||||
* Compilation failed with --disable-hangup-watch-cd. Fixed.
|
||||
+ Ability to write daemon pid in file.
|
||||
* -f option had reverse meaning. Thanks to Eugene Korovin @ 2:5080/196.72
|
||||
+ -q option terminates daemon process (only if pidfile is used).
|
||||
|
||||
0.22.7.kst4
|
||||
===========
|
||||
|
||||
* Hydra was broken in kst2. Fixed.
|
||||
+ Bidirectional session drops only if rxcps and txcps are less than
|
||||
mincps at the same time.
|
||||
|
||||
0.22.7.kst5
|
||||
===========
|
||||
|
||||
+ port tcpip patch by Serge N. Pokhodyaev @ 2:5020/1838
|
||||
* lock fix, when outbound on not lockable filesystem.
|
||||
Patch by Andrew Dolgov @ 2:5030/394.41
|
||||
|
||||
0.22.7.kst6
|
||||
===========
|
||||
|
||||
* traffic wasn't shown if no files in boxes.
|
||||
Patch by Alexander Shiyan @ 2:5030/39.2
|
||||
* bfstat now correctly shows age of files.
|
||||
Patch by Alexander Shiyan @ 2:5030/39.2
|
||||
* logging 'undefined cmd' fixed.
|
||||
Thanks to Pavel I.Osipov @ 2:5020/770.50
|
||||
|
||||
0.22.8.kst7
|
||||
===========
|
||||
|
||||
Some changes taken from 0.22.8 by Alexander Belkin:
|
||||
* some bugfixes
|
||||
+ new environment variable $RC (session return code)
|
||||
+ sending of EMSI_ACK every time after recving of EMSI_DAT
|
||||
+ support for nodelist IBN flag
|
||||
|
||||
0.22.8.kst8
|
||||
===========
|
||||
|
||||
* fixed bug with flags CM in override
|
||||
* fixed bug with sending HUP to daemon
|
||||
|
||||
26
CHANGES.ugenk
Normal file
26
CHANGES.ugenk
Normal file
@ -0,0 +1,26 @@
|
||||
0.22.8.ugenk1
|
||||
=============
|
||||
+ initial release, based on bforce 0.22.8.kst8
|
||||
* fixed problem with worktime detecting
|
||||
+ makefiles fixed (removed make update, now make install installs config files with extension .sample)
|
||||
+ added --with-user and --with-group options to ``configure'' script.
|
||||
+ installation directories by default are compliance with default fidogate installation
|
||||
|
||||
0.22.8.ugenk2
|
||||
=============
|
||||
* pathes by Andrey Slusar @ 2:467/126
|
||||
(total 12: patch-bforce.c, patch-bfstat.c, patch-daemon.c, patch-expression.y,
|
||||
patch-nlookup.c, patch-prot_binkp.c, patch-prot_emsi.c, patch-prot_yoohoo.c, patch-prot_zmrecv.c,
|
||||
patch-prot_zmsend.c, patch-sess_call.c, patch-sess_stat.c)
|
||||
+ added syslog support (see SYSLOG)
|
||||
+ fixed nlookup (broken in ugenk1)
|
||||
+ spec file now goes with bforce
|
||||
|
||||
0.22.8.ugenk3
|
||||
=============
|
||||
+ fixed working with syslog (not tested yet, any volonteers?)
|
||||
* some bugfixes
|
||||
|
||||
0.22.8.ugenk4
|
||||
=============
|
||||
+ fixed problems with license (thnx to Jonathan Gonzales V. from gnu.org)
|
||||
340
COPYING
Normal file
340
COPYING
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
175
INSTALL
Normal file
175
INSTALL
Normal file
@ -0,0 +1,175 @@
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, a file
|
||||
`config.cache' that saves the results of its tests to speed up
|
||||
reconfiguring, and a file `config.log' containing compiler output
|
||||
(useful mainly for debugging `configure').
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
4. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. You can give `configure'
|
||||
initial values for variables by setting them in the environment. Using
|
||||
a Bourne-compatible shell, you can do that on the command line like
|
||||
this:
|
||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
||||
|
||||
Or on systems that have the `env' program, you can do it like this:
|
||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not supports the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a time
|
||||
in the source code directory. After you have installed the package for
|
||||
one architecture, use `make distclean' before reconfiguring for another
|
||||
architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' can not figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it can not guess the host type, give it the
|
||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name with three fields:
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the host type.
|
||||
|
||||
If you are building compiler tools for cross-compiling, you can also
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for and the `--build=TYPE' option to select the type of
|
||||
system on which you are compiling the package.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Operation Controls
|
||||
==================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Use and save the results of the tests in FILE instead of
|
||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
||||
debugging `configure'.
|
||||
|
||||
`--help'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--version'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
131
INSTALL.ru
Normal file
131
INSTALL.ru
Normal file
@ -0,0 +1,131 @@
|
||||
В этом файле описывается процесс установки и настройки
|
||||
фидонет-совместимого мейлера bforce 0.22.8.ugenk1.
|
||||
|
||||
В данном документе приняты следующие обозначения:
|
||||
|
||||
<SRCDIR> - путь, куда вы распаковали тарболл с исходными
|
||||
текстами bforce 0.22.8.ugenk1 (далее bforce)
|
||||
Тарболл - файл с расширением tar.gz, или tar.bz2
|
||||
|
||||
|
||||
Требования к системе
|
||||
====================
|
||||
|
||||
Для компиляции bforce вам потребуется компилятор (для
|
||||
gnu/bsd-систем gcc), так же GNU make (make для линукс,
|
||||
gmake для bsd).
|
||||
|
||||
Обратитесь к документации по вашей системе того, что бы
|
||||
узнать как установить вышеперечисленное программное обеспечение.
|
||||
|
||||
|
||||
Процесс компиляции
|
||||
==================
|
||||
|
||||
Распакуйте тарболл следующими командами:
|
||||
|
||||
gzip -d bforce-0.22.8.ugenk1.tar.gz
|
||||
или
|
||||
bzip2 -d bforce-0.22.8.ugenk1.tar.bz2
|
||||
|
||||
tar -xvf bforce-0.22.8.ugenk1.tar
|
||||
|
||||
Перейдите в директорию bforce-0.22.8.ugenk1/source:
|
||||
cd <SRCDIR>/bforce-0.22.8.ugenk1/source
|
||||
|
||||
Для создания Makefile, который наиболее подходит к вашей
|
||||
системе, наберите:
|
||||
|
||||
./configure --help
|
||||
|
||||
и внимательно прочитайте предлагаемую справку.
|
||||
Если вам не понятна предлагаемая справка, то просто запустите:
|
||||
|
||||
./configure
|
||||
|
||||
При необходимости исправьте Makefile для ваших нужд.
|
||||
Запустите команду make (для bsd - gmake):
|
||||
|
||||
make
|
||||
|
||||
В случае ошибок при выполнении команды make пишите bugreport на
|
||||
e.kozhuhovskiy@gmail.com
|
||||
|
||||
Возможно, прийдется пересоздать configure с помощью autoconf
|
||||
|
||||
Поздравляем, компиляция завершилась успешно.
|
||||
Для установки bforce наберите:
|
||||
|
||||
make install
|
||||
|
||||
Для bsd:
|
||||
|
||||
gmake install
|
||||
|
||||
|
||||
Настройка
|
||||
=========
|
||||
|
||||
Для нормальной работы вам нужно отредактировать конфигурационные файлы
|
||||
bforce. По умолчанию они находятся в /usr/local/fido/etc и называются
|
||||
bforce.conf - основной конфигурационный файл bforce
|
||||
bforce.passwd - файл определения паролей на сессии
|
||||
bforce.subst - файл переопределения данных из nodelist
|
||||
freq.dirs - файл задания списка директорий для freq-запросов
|
||||
freq.aliases - файл задания magic freqests
|
||||
|
||||
Так же вам необходимо подправить файл outman. По умолчанию он лежит в
|
||||
/usr/local/fido/bin. outman - это скрипт, вызываемый вами для создания
|
||||
прозвонок, файловых запросов и файл-аттачей на узлы ftn.
|
||||
|
||||
|
||||
Использование
|
||||
=============
|
||||
|
||||
bforce - основной файл bforce, служит для запуска
|
||||
демона, исходящих звонков и запуска из-под mgetty\portslave для приема
|
||||
входящих звонков.
|
||||
Попробуйте bforce --help
|
||||
|
||||
|
||||
bfindex - служит для обновления индексных файлов (перекомпиляции)
|
||||
нодлистов. Испрользование: bfindex
|
||||
|
||||
bfstat - служит для показа почтовой очереди. Использование: bfstat
|
||||
|
||||
nlookup - служит для поиска информации в нодлисте. Использование:
|
||||
nlookup <ftn_address>
|
||||
|
||||
outman - см. "Настройка". Попробуйте outman --help
|
||||
|
||||
|
||||
Дополнительные утилиты
|
||||
======================
|
||||
|
||||
Дополнительные утилиты для bforce находятся в <SRCDIR>/contrib:
|
||||
bflan - bforce log analyzer
|
||||
callout.sh - скрипт для отзвонки на аплинков
|
||||
outman - скрипт outman
|
||||
timesync.tcl - скрипт для синхорнизации времени
|
||||
init.d/bforce - init-скрипт для RedHat
|
||||
init.d/bforce.debian - init-скрипт для non-RedHat
|
||||
bfha - bforce history analyzer (bfha)
|
||||
bfha/README - bfha README
|
||||
bfha/bfha.pl - собственно, bfha
|
||||
u-srif - продвинутый freq-процессор
|
||||
u-srif/u-srif-index.py \ с поддержой отчетов,
|
||||
u-srif/u-srif-lookup.py \ ограничений,
|
||||
u-srif/u-srif.py \ индексации файловой базы,
|
||||
u-srif/conf \ что значительно ускоряет
|
||||
u-srif/conf/report.footer \ работу.
|
||||
u-srif/conf/report.header \ Написан на python.
|
||||
u-srif/conf/u-srif.aliases \ --------------------
|
||||
u-srif/conf/u-srif.conf \ -------------------
|
||||
u-srif/conf/u-srif.dirs \ ------------------
|
||||
u-srif/lib / ------------------
|
||||
u-srif/lib/uconfig.py / -------------------
|
||||
u-srif/lib/udbase.py / --------------------
|
||||
u-srif/lib/ufido.py / ---------------------
|
||||
u-srif/lib/unodestat.py / ----------------------
|
||||
u-srif/lib/utmpl.py / -----------------------
|
||||
u-srif/lib/uutil.py / ------------------------
|
||||
32
README
Normal file
32
README
Normal file
@ -0,0 +1,32 @@
|
||||
$Id$:
|
||||
|
||||
BinkleyForce FTN mailer
|
||||
-----------------------
|
||||
|
||||
BinkleyForce is a simple ifcico like FTN mailer. It can works via
|
||||
TCP/IP as well as on modem links. Look sample configs for more
|
||||
information.
|
||||
|
||||
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. See the COPYING file for further information.
|
||||
|
||||
Known Bugs
|
||||
----------
|
||||
- BinkD use and expect local file time at BinkP sessions, but
|
||||
BinkleyForce allways use UTC time (?)
|
||||
|
||||
Bug Reports
|
||||
-----------
|
||||
|
||||
E-Mail : adb@newmail.ru
|
||||
FidoNet : Alexander Belkin, 2:5020/1398.11
|
||||
|
||||
New Versions
|
||||
------------
|
||||
|
||||
http://adb.newmail.ru
|
||||
|
||||
|
||||
Copyright (c) 1998-2000 Alexander Belkin, Moscow, Russia.
|
||||
14
README.kst
Normal file
14
README.kst
Normal file
@ -0,0 +1,14 @@
|
||||
BinkleyForce FTN mailer (Branch KST)
|
||||
------------------------------------
|
||||
|
||||
Bug Reports
|
||||
-----------
|
||||
|
||||
E-Mail : kst@moecho.org
|
||||
FidoNet : Konstantin Stepanenkov, 2:5030/1251
|
||||
|
||||
New Versions
|
||||
------------
|
||||
|
||||
http://kst.spb.ru/bforce/
|
||||
|
||||
14
README.ugenk
Normal file
14
README.ugenk
Normal file
@ -0,0 +1,14 @@
|
||||
BinkleyForce FTN mailer (Branch ugenk)
|
||||
------------------------------------
|
||||
|
||||
Bug Reports
|
||||
-----------
|
||||
|
||||
E-Mail : e.kozhuhovskiy@gmail.com
|
||||
FidoNet : Evgeniy Kozhuhovskiy, 2:450/256, 2:450/267
|
||||
|
||||
New Versions
|
||||
------------
|
||||
|
||||
http://ugenk.bas-net.by/
|
||||
|
||||
10
SYSLOG
Normal file
10
SYSLOG
Normal file
@ -0,0 +1,10 @@
|
||||
Now binkleyforce supports logging to syslog (see syslogd(8) for
|
||||
details)
|
||||
|
||||
It uses LOG_UUCP facility, LOG_PID option. LOG_ERR and LOG_NOTICE
|
||||
levels are used.
|
||||
|
||||
To enable it, uncomment line 19 in source/include/logger.h
|
||||
( /* #define USE_SYSLOG */ )
|
||||
|
||||
TODO: add option to ``configure'' script
|
||||
11
TODO
Normal file
11
TODO
Normal file
@ -0,0 +1,11 @@
|
||||
"-" - bugfix
|
||||
"+" - feature
|
||||
|
||||
|
||||
- sed detection in makefile
|
||||
+ [io_modem.c] add random and smart algorythms selecting of tty.
|
||||
smart means (1) write time stat for every line and (2) evenly
|
||||
select a line to make a call
|
||||
+ HOLDALL emsi option, if specified flag exists
|
||||
+ add bind_ip option
|
||||
- fix Exec feature
|
||||
0
build-stamp
Normal file
0
build-stamp
Normal file
0
configure-stamp
Normal file
0
configure-stamp
Normal file
19
contrib/bfha/README
Normal file
19
contrib/bfha/README
Normal file
@ -0,0 +1,19 @@
|
||||
Данный скрипт предназначен для генерации статистики о работе мейлера
|
||||
binkleyforce путём анализа создаваемого им файла истории сессий (параметр
|
||||
`history_file' в bforce.conf). Статистика генерится за предыдущие сутки от
|
||||
момента запуска скрипта и постится в заданную ньюсгруппу. Доступны два типа
|
||||
статистики.
|
||||
|
||||
Перед первым запуском рекомендуется изменить значение конфигурационных
|
||||
переменных -- они находятся в начале скрипта.
|
||||
|
||||
Известные баги:
|
||||
|
||||
1. Hе учитывается случай, когда файл истории сессий повёрнут
|
||||
logrotate'ом (может потеряться часть статистики)
|
||||
2. Hеправильно считает cps (завышает), если трафик в обе стороны
|
||||
|
||||
Автор скрипта: Serge N. Pokhodyaev, 2:5020/1838, <snp@ru.ru>
|
||||
|
||||
Распространяется под GNU GPL.
|
||||
|
||||
575
contrib/bfha/bfha.pl
Normal file
575
contrib/bfha/bfha.pl
Normal file
@ -0,0 +1,575 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# bfha -- binkleyforce history analyzer
|
||||
#
|
||||
# Copyright (C) 2000 Serge N. Pokhodyaev
|
||||
#
|
||||
# E-mail: snp@ru.ru
|
||||
# Fido: 2:5020/1838
|
||||
#
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
#
|
||||
# çÅÎÅÒÉÔ ÓÔÁÔÉÓÔÉËÕ ÚÁ ÐÒÅÄÙÄÕÝÉÊ ÄÅÎØ
|
||||
#
|
||||
|
||||
#
|
||||
# TODO:
|
||||
#
|
||||
# 1. õÞÅÓÔØ ÓÌÕÞÁÊ, ËÏÇÄÁ ÌÏÇ ÐÏ×£ÒÎÕÔ logrotate'ÏÍ
|
||||
#
|
||||
# Known bugs:
|
||||
#
|
||||
# 1. HÅÐÒÁ×ÉÌØÎÏ ÓÞÉÔÁÅÔ cps (ÚÁ×ÙÛÁÅÔ) ÅÓÌÉ ÔÒÁÆÉË × ÏÂÅ ÓÔÏÒÏÎÙ
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Time::Local;
|
||||
use POSIX qw(strftime);
|
||||
|
||||
my $PROGNAME = 'bfha';
|
||||
my $VERSION = '$Revision$ ';
|
||||
|
||||
######## Configurable part ###################################################
|
||||
|
||||
my $inews = "/usr/bin/inews -h -O -S";
|
||||
|
||||
my $log = "/var/spool/fido/history";
|
||||
|
||||
my $rep_newsgroups = "ftn.1838.stat";
|
||||
my $rep_from = "\"Statistics generator\" <snp\@gloom.intra.eu.org>";
|
||||
my $rep1_subj = "Sessions history";
|
||||
my $rep2_subj = "Sessions history";
|
||||
my $rep3_subj = "Links statistics";
|
||||
|
||||
my $count_failed = 1;
|
||||
|
||||
#my %line_names = (
|
||||
# "ttyS1" => "Modem",
|
||||
# "tcpip" => "IP"
|
||||
#);
|
||||
|
||||
##############################################################################
|
||||
|
||||
my $devel = 0;
|
||||
|
||||
my (%st, %lines, %nodes, @nodes_sorted);
|
||||
my @tm;
|
||||
my $time;
|
||||
|
||||
die "Usage: $PROGNAME [-d]\n" if (!((0 == $#ARGV) && ($ARGV[0] eq '-d')) && !(-1 == $#ARGV));
|
||||
$devel = 1 if ((0 == $#ARGV) && ($ARGV[0] eq '-d'));
|
||||
|
||||
$log = "./history" if ($devel);
|
||||
|
||||
# Make version string
|
||||
#
|
||||
$VERSION =~ s/(\$Rev)ision:\s([\d.]+).*/$PROGNAME\/$2/;
|
||||
|
||||
# Get time of 0:00:00 of yesterday
|
||||
#
|
||||
@tm = localtime(time - 86400);
|
||||
$tm[0] = 0; # sec
|
||||
$tm[1] = 0; # min
|
||||
$tm[2] = 0; # hours
|
||||
$time = timelocal(@tm);
|
||||
|
||||
# At first read logs
|
||||
#
|
||||
undef %st;
|
||||
undef %lines;
|
||||
undef %nodes;
|
||||
die "Log reading error\n" if (0 != log_read($time));
|
||||
|
||||
@nodes_sorted = sort(node_cmp keys(%nodes));
|
||||
|
||||
# Now generate statistics
|
||||
#
|
||||
out_close();
|
||||
#rep1();
|
||||
rep2();
|
||||
rep3();
|
||||
|
||||
|
||||
sub log_read
|
||||
{
|
||||
my $i;
|
||||
my $t;
|
||||
my @l;
|
||||
|
||||
die if (0 != $#_);
|
||||
|
||||
$t = $_[0];
|
||||
|
||||
open(LOG, "< $log") || die("Can't open $log: $!\n");
|
||||
while (<LOG>)
|
||||
{
|
||||
chomp;
|
||||
@l = split(/,/);
|
||||
return 1 if ($#l != 11);
|
||||
return 1 if (! ($l[4] =~ /[IO]/));
|
||||
|
||||
# Check date
|
||||
#
|
||||
next if ($l[2] < $t);
|
||||
last if ($l[2] >= ($t + 86400));
|
||||
|
||||
# Entries without address
|
||||
#
|
||||
if ($l[1] eq '')
|
||||
{
|
||||
next if (0 == $count_failed);
|
||||
$l[1] = 'failed' if (0 != $count_failed);
|
||||
}
|
||||
|
||||
# Remove domain
|
||||
#
|
||||
$l[1] =~ s/@.*$//;
|
||||
|
||||
# Add statistics
|
||||
#
|
||||
$i = $#{$st{beg}} + 1;
|
||||
|
||||
$lines{$l[0]}[$#{$lines{$l[0]}} + 1] = $i;
|
||||
$nodes{$l[1]}[$#{$nodes{$l[1]}} + 1] = $i;
|
||||
|
||||
$st{beg}[$i] = $l[2];
|
||||
$st{len}[$i] = $l[3];
|
||||
$st{addr}[$i] = $l[1];
|
||||
$st{line}[$i] = $l[0];
|
||||
$st{rc}[$i] = $l[5];
|
||||
$st{snt_nm}[$i] = $l[6];
|
||||
$st{snt_am}[$i] = $l[7];
|
||||
$st{snt_f}[$i] = $l[8];
|
||||
$st{rcv_nm}[$i] = $l[9];
|
||||
$st{rcv_am}[$i] = $l[10];
|
||||
$st{rcv_f}[$i] = $l[11];
|
||||
$st{islst}[$i] = 0;
|
||||
$st{islst}[$i] = 1 if ($l[4] =~ /L/);
|
||||
$st{isprot}[$i] = 0;
|
||||
$st{isprot}[$i] = 1 if ($l[4] =~ /P/);
|
||||
$st{type}[$i] = 'I' if ($l[4] =~ /I/);
|
||||
$st{type}[$i] = 'O' if ($l[4] =~ /O/);
|
||||
}
|
||||
}
|
||||
|
||||
######## rep1 ################################################################
|
||||
|
||||
sub rep1
|
||||
{
|
||||
my ($i, $j);
|
||||
my (%se, %se_t);
|
||||
my $node;
|
||||
|
||||
out_open($rep1_subj);
|
||||
printf "Date: %s\n\n", strftime("%a, %e %b %Y", localtime($time));
|
||||
|
||||
$~ = "rep1_header";
|
||||
write;
|
||||
|
||||
$~ = "rep1_body";
|
||||
$se_t{num_in} = 0;
|
||||
$se_t{num_out} = 0;
|
||||
$se_t{snt} = 0;
|
||||
$se_t{rcv} = 0;
|
||||
$se_t{len} = 0;
|
||||
foreach $node (@nodes_sorted)
|
||||
{
|
||||
$se{num_in} = 0;
|
||||
$se{num_out} = 0;
|
||||
$se{snt} = 0;
|
||||
$se{rcv} = 0;
|
||||
$se{len} = 0;
|
||||
for ($i = 0; $i <= $#{$nodes{$node}}; ++$i)
|
||||
{
|
||||
$j = $nodes{$node}[$i];
|
||||
++$se{num_in} if ($st{type}[$j] eq 'I');
|
||||
++$se{num_out} if ($st{type}[$j] eq 'O');
|
||||
$se{snt} += $st{snt_am}[$j] + $st{snt_nm}[$j] + $st{snt_f}[$j];
|
||||
$se{rcv} += $st{rcv_am}[$j] + $st{rcv_nm}[$j] + $st{rcv_f}[$j];
|
||||
$se{len} += $st{len}[$j];
|
||||
}
|
||||
$se{time} = time_int2str($se{len});
|
||||
# FIXME (cps)
|
||||
$se{cps} = div_int(($se{snt} + $se{rcv}), $se{len});
|
||||
write;
|
||||
|
||||
$se_t{num_in} += $se{num_in};
|
||||
$se_t{num_out} += $se{num_out};
|
||||
$se_t{snt} += $se{snt};
|
||||
$se_t{rcv} += $se{rcv};
|
||||
$se_t{len} += $se{len};
|
||||
}
|
||||
|
||||
$~ = "rep1_footer";
|
||||
$se_t{time} = time_int2str($se_t{len});
|
||||
# FIXME (cps)
|
||||
$se_t{cps} = div_int(($se_t{snt} + $se_t{rcv}), $se_t{len});
|
||||
write;
|
||||
|
||||
print "\n";
|
||||
out_close();
|
||||
|
||||
|
||||
format rep1_header =
|
||||
¥ ¶ ¶ ¶ ¶ ¶ ¨
|
||||
¡ System <EFBFBD> Sessions <EFBFBD> Sent <EFBFBD> Received <EFBFBD> Time <EFBFBD> CPS ¡
|
||||
¡ address <EFBFBD> in out <EFBFBD> bytes <EFBFBD> bytes <EFBFBD> online <EFBFBD> ¡
|
||||
± ¼ ¼ ¼ ¼ ¼ µ
|
||||
.
|
||||
|
||||
format rep1_body =
|
||||
¡ @<<<<<<<<<<<<<< <EFBFBD> @>> @>> <EFBFBD> @>>>>>>>> <EFBFBD> @>>>>>>>>> <EFBFBD> @>>>>>>>> <EFBFBD> @>>>> ¡
|
||||
$node, $se{num_in}, $se{num_out}, $se{snt}, $se{rcv}, $se{time}, $se{cps}
|
||||
.
|
||||
|
||||
format rep1_footer =
|
||||
°€€€€€€€€€€€€€€€€€Š€€€€€€€€€€Š€€€€€€€€€€€Š€€€€€€€€€€€€Š€€€€€€€€€€€Š€€€€€€€´
|
||||
¡ TOTAL <EFBFBD> @>> @>> <EFBFBD> @>>>>>>>> <EFBFBD> @>>>>>>>>> <EFBFBD> @>>>>>>>> <EFBFBD> @>>>> ¡
|
||||
$se_t{num_in}, $se_t{num_out}, $se_t{snt}, $se_t{rcv}, $se_t{time}, $se_t{cps}
|
||||
« ¹ ¹ ¹ ¹ ¹ ®
|
||||
.
|
||||
}
|
||||
|
||||
######## rep2 ################################################################
|
||||
|
||||
sub rep2
|
||||
{
|
||||
my ($i, $j);
|
||||
my @t;
|
||||
my ($t1, $t2, $str, $lv);
|
||||
my $node;
|
||||
my %se;
|
||||
|
||||
out_open($rep2_subj);
|
||||
printf "Date: %s\n\n", strftime("%a, %e %b %Y", localtime($time));
|
||||
|
||||
$~ = "rep2_header";
|
||||
write;
|
||||
|
||||
$~ = "rep2_body";
|
||||
foreach $node (@nodes_sorted)
|
||||
{
|
||||
$se{snt} = 0;
|
||||
$se{rcv} = 0;
|
||||
$se{len} = 0;
|
||||
for ($i = 0; $i <= 95; ++$i)
|
||||
{
|
||||
$t[$i] = 0;
|
||||
}
|
||||
for ($i = 0; $i <= $#{$nodes{$node}}; ++$i)
|
||||
{
|
||||
$j = $nodes{$node}[$i];
|
||||
|
||||
# Fill array
|
||||
#
|
||||
$t1 = $st{beg}[$j] - $time;
|
||||
$t2 = $t1 + $st{len}[$j];
|
||||
$t2 = 86399 if ($t2 > 86399);
|
||||
$t1 = div_int($t1, 900);
|
||||
$t2 = div_int($t2, 900);
|
||||
while ($t1 <= $t2)
|
||||
{
|
||||
$t[$t1++] = 1;
|
||||
}
|
||||
|
||||
$se{snt} += $st{snt_am}[$j] + $st{snt_nm}[$j] + $st{snt_f}[$j];
|
||||
$se{rcv} += $st{rcv_am}[$j] + $st{rcv_nm}[$j] + $st{rcv_f}[$j];
|
||||
$se{len} += $st{len}[$j];
|
||||
}
|
||||
$se{time} = time_int2str($se{len});
|
||||
# FIXME (cps)
|
||||
$se{cps} = div_int(($se{snt} + $se{rcv}), $se{len});
|
||||
|
||||
# Visualize
|
||||
#
|
||||
$i = 0;
|
||||
$str = "";
|
||||
if ($t[$i++])
|
||||
{
|
||||
$str = $str . "<22>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = $str . "<22>";
|
||||
}
|
||||
while ($i < $#t)
|
||||
{
|
||||
$lv = 0;
|
||||
$lv += 1 if ($t[$i++]);
|
||||
$lv += 2 if ($t[$i++]);
|
||||
|
||||
if (0 == $lv)
|
||||
{
|
||||
if (div_rest(($i - 1), 8) == 0)
|
||||
{
|
||||
$str = $str . "<22>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = $str . " ";
|
||||
}
|
||||
}
|
||||
elsif (1 == $lv)
|
||||
{
|
||||
$str = $str . "Ž";
|
||||
}
|
||||
elsif (2 == $lv)
|
||||
{
|
||||
$str = $str . "<22>";
|
||||
}
|
||||
elsif (3 == $lv)
|
||||
{
|
||||
$str = $str . "<22>";
|
||||
}
|
||||
}
|
||||
if ($t[$i])
|
||||
{
|
||||
$str = $str . "Ž";
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = $str . "<22>";
|
||||
}
|
||||
|
||||
write;
|
||||
}
|
||||
|
||||
$~ = "rep2_footer";
|
||||
write;
|
||||
|
||||
out_close();
|
||||
|
||||
|
||||
format rep2_header =
|
||||
0 2 4 6 8 10 12 14 16 18 20 22 24
|
||||
†€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€Š€‰€‡
|
||||
.
|
||||
|
||||
format rep2_body =
|
||||
@<<<<<<<<<<<<<<@||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
$node, $str
|
||||
.
|
||||
|
||||
format rep2_footer =
|
||||
†€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€Š€ˆ€‡
|
||||
0 2 4 6 8 10 12 14 16 18 20 22 24
|
||||
.
|
||||
}
|
||||
|
||||
######## rep3 ################################################################
|
||||
|
||||
sub rep3
|
||||
{
|
||||
my $node;
|
||||
my (%se, %se_t);
|
||||
my ($i, $j);
|
||||
|
||||
out_open($rep3_subj);
|
||||
printf "Date: %s\n\n", strftime("%a, %e %b %Y", localtime($time));
|
||||
|
||||
$~ = "rep3_header";
|
||||
write;
|
||||
|
||||
$~ = "rep3_body";
|
||||
$se_t{num_in} = 0;
|
||||
$se_t{num_out} = 0;
|
||||
$se_t{time_in} = 0;
|
||||
$se_t{time_out} = 0;
|
||||
$se_t{snt} = 0;
|
||||
$se_t{rcv} = 0;
|
||||
$se_t{time} = 0;
|
||||
foreach $node (@nodes_sorted)
|
||||
{
|
||||
$se{num_in} = 0;
|
||||
$se{num_out} = 0;
|
||||
$se{time_in} = 0;
|
||||
$se{time_out} = 0;
|
||||
$se{snt} = 0;
|
||||
$se{rcv} = 0;
|
||||
$se{time} = 0;
|
||||
for ($i = 0; $i <= $#{$nodes{$node}}; ++$i)
|
||||
{
|
||||
$j = $nodes{$node}[$i];
|
||||
++$se{num_in} if ($st{type}[$j] eq 'I');
|
||||
++$se{num_out} if ($st{type}[$j] eq 'O');
|
||||
$se{time_in} += $st{len}[$j] if ($st{type}[$j] eq 'I');
|
||||
$se{time_out} += $st{len}[$j] if ($st{type}[$j] eq 'O');
|
||||
$se{snt} += $st{snt_am}[$j] + $st{snt_nm}[$j] + $st{snt_f}[$j];
|
||||
$se{rcv} += $st{rcv_am}[$j] + $st{rcv_nm}[$j] + $st{rcv_f}[$j];
|
||||
$se{time} += $st{len}[$j];
|
||||
}
|
||||
|
||||
# Total counters
|
||||
#
|
||||
$se_t{num_in} += $se{num_in};
|
||||
$se_t{num_out} += $se{num_out};
|
||||
$se_t{snt} += $se{snt};
|
||||
$se_t{rcv} += $se{rcv};
|
||||
$se_t{time} += $se{time};
|
||||
$se_t{time_out} += $se{time_out};
|
||||
$se_t{time_in} += $se{time_in};
|
||||
|
||||
# Output string
|
||||
#
|
||||
# FIXME (cps)
|
||||
$se{cps} = dash_if_zero(div_int(($se{snt} + $se{rcv}), $se{time}));
|
||||
$se{time} = time_int2str($se{time});
|
||||
$se{time_in} = time_int2str($se{time_in});
|
||||
$se{time_out} = time_int2str($se{time_out});
|
||||
$se{num_in} = dash_if_zero($se{num_in});
|
||||
$se{num_out} = dash_if_zero($se{num_out});
|
||||
$se{rcv} = shrink_size(dash_if_zero($se{rcv}));
|
||||
$se{snt} = shrink_size(dash_if_zero($se{snt}));
|
||||
write;
|
||||
}
|
||||
|
||||
$~ = "rep3_footer";
|
||||
# FIXME (cps)
|
||||
$se_t{cps} = dash_if_zero(div_int(($se_t{snt} + $se_t{rcv}), $se_t{time}));
|
||||
$se_t{time} = time_int2str($se_t{time});
|
||||
$se_t{time_in} = time_int2str($se_t{time_in});
|
||||
$se_t{time_out} = time_int2str($se_t{time_out});
|
||||
$se_t{num_in} = dash_if_zero($se_t{num_in});
|
||||
$se_t{num_out} = dash_if_zero($se_t{num_out});
|
||||
$se_t{rcv} = shrink_size(dash_if_zero($se_t{rcv}));
|
||||
$se_t{snt} = shrink_size(dash_if_zero($se_t{snt}));
|
||||
$~ = "rep3_footer";
|
||||
write;
|
||||
|
||||
print "\n";
|
||||
out_close();
|
||||
|
||||
|
||||
format rep3_header =
|
||||
¥ ¸ ¸ ¸ ¸ ¨
|
||||
¡ ¡ Sessions/Online ¡ Time ¡ Traffic ¡ ¡
|
||||
¡ Address ± ¸ µ online ± ¸ µ CPS ¡
|
||||
¡ ¡ Incoming ¡ Outgoing ¡ ¡ Rcvd ¡ Sent ¡ ¡
|
||||
± ¾ ¶ ¾ ¶ ¾ ¾ ¾ ¾ µ
|
||||
.
|
||||
|
||||
format rep3_body =
|
||||
¡ @<<<<<<<<<<<<<<¡@>><EFBFBD>@>>>>>>> ¡@>><EFBFBD>@>>>>>>> ¡@>>>>>>>> ¡@>>>>>¡@>>>>>¡@>>>>> ¡
|
||||
$node, $se{num_in}, $se{time_in}, $se{num_out}, $se{time_out}, $se{time}, $se{rcv}, $se{snt}, $se{cps}
|
||||
.
|
||||
|
||||
format rep3_footer =
|
||||
°€€€€€€€€€€€€€€€€½€€€Š€€€€€€€€€½€€€Š€€€€€€€€€½€€€€€€€€€€½€€€€€€½€€€€€€½€€€€€€€´
|
||||
¡ TOTAL ¡@>><EFBFBD>@>>>>>>> ¡@>><EFBFBD>@>>>>>>> ¡@>>>>>>>> ¡@>>>>>¡@>>>>>¡@>>>>> ¡
|
||||
$se_t{num_in}, $se_t{time_in}, $se_t{num_out}, $se_t{time_out}, $se_t{time}, $se_t{rcv}, $se_t{snt}, $se_t{cps}
|
||||
« » ¹ » ¹ » » » » ®
|
||||
.
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
|
||||
sub shrink_size
|
||||
{
|
||||
die if (0 != $#_);
|
||||
|
||||
return $_[0] if ($_[0] < 1024);
|
||||
return sprintf("%.1fk", $_[0] / 1024) if ($_[0] < 1048576);
|
||||
return sprintf("%.1fM", $_[0] / 1048576);
|
||||
}
|
||||
|
||||
sub dash_if_zero
|
||||
{
|
||||
die if (0 != $#_);
|
||||
|
||||
return "-" if (0 == $_[0]);
|
||||
return $_[0];
|
||||
}
|
||||
|
||||
sub time_int2str
|
||||
{
|
||||
my $time;
|
||||
my $h;
|
||||
my $m;
|
||||
my $s;
|
||||
|
||||
die if (0 != $#_);
|
||||
die if (86399 < $time);
|
||||
|
||||
return "-:--:--" if (0 == $_[0]);
|
||||
|
||||
$time = $_[0];
|
||||
$h = div_int($time, 3600);
|
||||
$time = div_rest($time, 3600);
|
||||
$m = div_int($time, 60);
|
||||
$s = div_rest($time, 60);
|
||||
|
||||
return sprintf("%d:%2.2d:%2.2d", $h, $m, $s);
|
||||
}
|
||||
|
||||
# ãÅÌÏÞÉÓÌÅÎÎÏÅ ÄÅÌÅÎÉÅ
|
||||
sub div_int
|
||||
{
|
||||
use integer;
|
||||
|
||||
die if (1 != $#_);
|
||||
|
||||
return 0 if ($_[1] == 0);
|
||||
return $_[0] / $_[1];
|
||||
}
|
||||
|
||||
|
||||
# ïÓÔÁÔÏË ÏÔ ÃÅÌÏÞÉÓÌÅÎÎÏÇÏ ÄÅÌÅÎÉÑ
|
||||
sub div_rest
|
||||
{
|
||||
die if (1 != $#_);
|
||||
|
||||
return 0 if ($_[1] == 0);
|
||||
return $_[0] - (div_int($_[0], $_[1]) * $_[1]);
|
||||
}
|
||||
|
||||
sub out_open
|
||||
{
|
||||
die if (0 != $#_);
|
||||
|
||||
open(STDOUT, "| $inews") || die("Can't pipe to inews: $!\n") if (! $devel);
|
||||
printf "Newsgroups: %s\n", $rep_newsgroups;
|
||||
printf "From: %s\n", $rep_from;
|
||||
printf "Subject: %s\n", $_[0];
|
||||
printf "X-FTN-Tearline: %s\n\n", $VERSION;
|
||||
}
|
||||
|
||||
sub out_close
|
||||
{
|
||||
close(STDOUT) if (! $devel);
|
||||
}
|
||||
|
||||
sub node_cmp
|
||||
{
|
||||
my (@na, @nb);
|
||||
|
||||
@na = split('[:/.]', $::a);
|
||||
@nb = split('[:/.]', $::b);
|
||||
|
||||
# zone
|
||||
return -1 if ($na[0] < $nb[0]);
|
||||
return 1 if ($na[0] > $nb[0]);
|
||||
|
||||
# net
|
||||
return -1 if ($na[1] < $nb[1]);
|
||||
return 1 if ($na[1] > $nb[1]);
|
||||
|
||||
# node
|
||||
return -1 if ($na[2] < $nb[2]);
|
||||
return 1 if ($na[2] > $nb[2]);
|
||||
|
||||
#point
|
||||
return -1 if ($na[3] < $nb[3]);
|
||||
return 1 if ($na[3] > $nb[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
384
contrib/bflan
Normal file
384
contrib/bflan
Normal file
@ -0,0 +1,384 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# It is a log file analyser for 'binkleyforce' mailer.
|
||||
#
|
||||
# Copyright (c) 1998-99 by Alexander Belkin
|
||||
#
|
||||
# $Id$:
|
||||
#
|
||||
# If you have any questions, suggestions or wishes, feel free to contact
|
||||
# with me. My address: 2:5020/1398.11@fidonet
|
||||
#
|
||||
# To post into news, use bflan |inews -h -O -S
|
||||
$program_name = "bforce-lan v1.0/Perl/Linux";
|
||||
$station_name = "My Station";
|
||||
$log_file = "/var/log/bforce/bf-log.ttyS0";
|
||||
$news_header = "From: Statistic Robot <postmaster\@fido.xxx.local>\n".
|
||||
"Newsgroups: junk\n".
|
||||
"Subject: Sessions statistic.\n";
|
||||
|
||||
#main
|
||||
#{
|
||||
if( &ReadLog($log_file) == 0 )
|
||||
{
|
||||
print $news_header;
|
||||
print "\n";
|
||||
print "\"$system_name\" statistic from <$TimeFirst> to <$TimeLast>\n";
|
||||
print "\n";
|
||||
&TotalStatistic();
|
||||
print "\n";
|
||||
&SessionsStatistic();
|
||||
}
|
||||
exit(0);
|
||||
#}
|
||||
|
||||
sub ReadLog
|
||||
{
|
||||
my($start);
|
||||
|
||||
if( open( FLOG, $_[0] ) == 0 )
|
||||
{
|
||||
print "Can't open log \"$_[0]\": $!\n";
|
||||
return 1;
|
||||
}
|
||||
$start = 0;
|
||||
$cnt = 0;
|
||||
$TimeFirst = "";
|
||||
$TimeLast = "";
|
||||
|
||||
# Read in information from logfile
|
||||
|
||||
while( <FLOG> )
|
||||
{
|
||||
chomp;
|
||||
|
||||
( $Mon, $Day, $Time, $Pid, $Text ) = split( /[ \t]+/, $_, 5 );
|
||||
|
||||
if( $TimeFirst eq "" )
|
||||
{
|
||||
$TimeFirst = "$Mon $Day $Time";
|
||||
}
|
||||
|
||||
if( $start == 0 )
|
||||
{
|
||||
if( !defined($Connect[$cnt]) )
|
||||
{
|
||||
$Address[$cnt] = "";
|
||||
$Connect[$cnt] = "?????";
|
||||
$InFiles[$cnt] = 0;
|
||||
$OutFiles[$cnt] = 0;
|
||||
$InBytes[$cnt] = 0;
|
||||
$OutBytes[$cnt] = 0;
|
||||
$Status[$cnt] = "U";
|
||||
$Success[$cnt] = " ";
|
||||
}
|
||||
if( $Text =~ /^calling/ )
|
||||
{
|
||||
$Text =~ /^calling ([\d:\/.]+)/;
|
||||
$PidsCall{$Pid} = $1;
|
||||
$Calls{$1} = 0 if (!defined( $Calls{$1} ));
|
||||
$Calls{$1}++;
|
||||
}
|
||||
elsif( $Text =~ /^connect/ )
|
||||
{
|
||||
$Text =~ /^connect "\D*(\d+).*$/;
|
||||
$Connect[$cnt] = $1;
|
||||
}
|
||||
elsif( $Text =~ /^TCP\/IP connect/ )
|
||||
{
|
||||
$Connect[$cnt] = "TCPIP";
|
||||
}
|
||||
elsif( $Text =~ /^outbound (\S+) session/ )
|
||||
{
|
||||
$start = 1;
|
||||
$Time =~ /^(..):(..):(..)$/;
|
||||
$Start[$cnt] = ( $1 * 60 + $2 ) * 60 + $3;
|
||||
$Direction[$cnt] = "O";
|
||||
$Address[$cnt] = $PidsCall{$Pid};
|
||||
$MySexyPid = $Pid;
|
||||
next;
|
||||
}
|
||||
elsif( $Text =~ /^inbound (\S+) session/ )
|
||||
{
|
||||
$start = 1;
|
||||
$Time =~ /^(..):(..):(..)$/;
|
||||
$Start[$cnt] = ( $1 * 60 + $2 ) * 60 + $3;
|
||||
$Direction[$cnt] = "I";
|
||||
# $kAddress[$cnt] = $PidsCall{$Pid} if( defined($PidsCall{$Pid}) );
|
||||
$MySexyPid = $Pid;
|
||||
next;
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
if( ($start == 1) && ($Pid eq $MySexyPid) )
|
||||
{
|
||||
if( $Text =~ /^remote is password protected system/ )
|
||||
{
|
||||
$Status[$cnt] = "P";
|
||||
}
|
||||
elsif( $Text =~ /^remote is listed system/ )
|
||||
{
|
||||
$Status[$cnt] = "L";
|
||||
}
|
||||
elsif( $Text =~ /^remote is unlisted system/ )
|
||||
{
|
||||
$Status[$cnt] = "U";
|
||||
}
|
||||
elsif( $Text =~ /^[ \t]*Address :/ )
|
||||
{
|
||||
next if( $Address[$cnt] ne "" );
|
||||
$Text =~ /^.+:[ \t]+([\d:.\/]+).*$/;
|
||||
$Address[$cnt] = $1;
|
||||
}
|
||||
elsif( $Text =~ /^rcvd: \".+\" \d+/ )
|
||||
{
|
||||
$Text =~ /^rcvd: \".+\" (\d+)/;
|
||||
$InBytes[$cnt] += $1;
|
||||
$InFiles[$cnt] ++;
|
||||
}
|
||||
elsif( $Text =~ /^sent: \".+\" \d+/ )
|
||||
{
|
||||
$Text =~ /^sent: \".+\" (\d+)/;
|
||||
$OutBytes[$cnt] += $1;
|
||||
$OutFiles[$cnt] ++;
|
||||
}
|
||||
elsif( $Text =~ /^session rc = \d+/ )
|
||||
{
|
||||
$Text =~ /^session rc = (\d+)/;
|
||||
if( $1 != 0 )
|
||||
{
|
||||
$Success[$cnt] = "A";
|
||||
}
|
||||
$Time =~ /^(..):(..):(..)$/;
|
||||
$Finish[$cnt] = ( $1 * 60 + $2 ) * 60 + $3;
|
||||
$OnLine[$cnt] = $Finish[$cnt] - $Start[$cnt];
|
||||
$OnLine[$cnt] += 86400 if(( $Finish[$cnt] - $Start[$cnt] ) < 0 );
|
||||
$start = 0;
|
||||
$cnt++;
|
||||
}
|
||||
}
|
||||
# got another PID!
|
||||
elsif( $Text =~ /^connect \".+\"/
|
||||
|| $Text =~ /^inbound (\S+) session/
|
||||
|| $Text =~ /^outbound (\S+) session/ )
|
||||
{
|
||||
# Possible there was incorrectly terminated session
|
||||
# due to mailer crash or killing, so getting this string
|
||||
# can mean that we need to break reading session statistic?
|
||||
# But we can also get it if log file used not only by one
|
||||
# mailer at the same time, so.. ignore :)
|
||||
}
|
||||
} # end of while( <FLOG> )
|
||||
|
||||
close(FLOG);
|
||||
|
||||
$TimeLast = "$Mon $Day $Time" if( $Mon && $Day && $Time );
|
||||
}
|
||||
|
||||
sub SessionsStatistic
|
||||
{
|
||||
local ($addr, $start, $finish, $online, $ibyte, $obyte, $cps, $speed);
|
||||
my ($i);
|
||||
|
||||
$~ = HEADER;
|
||||
write;
|
||||
$~ = EACH;
|
||||
|
||||
for ($i = 0; $i < $cnt; $i++)
|
||||
{
|
||||
$addr = $Address[$i];
|
||||
$stat = "$Direction[$i]$Status[$i]$Success[$i]";
|
||||
$start = sec2str($Start[$i], "short");
|
||||
$finish = sec2str($Finish[$i], "short");
|
||||
$online = sec2str($OnLine[$i], "long");
|
||||
$ibyte = $InBytes[$i];
|
||||
$in = $InFiles[$i];
|
||||
$obyte = $OutBytes[$i];
|
||||
$on = $OutFiles[$i];
|
||||
$cps = int( ($ibyte + $obyte) / $OnLine[$i] ) if ($OnLine[$i] > 0);
|
||||
$speed = $Connect[$i];
|
||||
$ibyte = num2siz( $ibyte );
|
||||
$obyte = num2siz( $obyte );
|
||||
write;
|
||||
}
|
||||
|
||||
$~ = FOOTER;
|
||||
write;
|
||||
}
|
||||
|
||||
sub TotalStatistic
|
||||
{
|
||||
undef( %hSystems );
|
||||
undef( %hCalls );
|
||||
undef( %hTimes );
|
||||
undef( %hSessions );
|
||||
undef( %hInBytes );
|
||||
undef( %hOutBytes );
|
||||
undef( %hInFiles );
|
||||
undef( %hOutFiles );
|
||||
local($cal, $ses, $time, $ibyte, $obyte, $inum, $onum, $icps, $ocps);
|
||||
local($acal, $ases, $atime, $aibyte, $aobyte, $ainum, $aonum, $aicps, $aocps);
|
||||
local($sys);
|
||||
my($i);
|
||||
|
||||
$acal = 0;
|
||||
$ases = 0;
|
||||
$atime = 0;
|
||||
$aibyte = 0;
|
||||
$aobyte = 0;
|
||||
$ainum = 0;
|
||||
$aonum = 0;
|
||||
$aicps = 0;
|
||||
$aocps = 0;
|
||||
|
||||
for( $i = 0; $i < $cnt; $i++ )
|
||||
{
|
||||
$sys = $Address[$i];
|
||||
if( !defined($hSystems{$sys}) )
|
||||
{
|
||||
$hSystems{$sys} = 1;
|
||||
$hCalls{$sys} = $Calls{$sys}; $Calls{$sys} = 0;
|
||||
$hTimes{$sys} = 0;
|
||||
$hSessions{$sys} = 0;
|
||||
$hInBytes{$sys} = 0;
|
||||
$hOutBytes{$sys} = 0;
|
||||
$hInFiles{$sys} = 0;
|
||||
$hOutFiles{$sys} = 0;
|
||||
}
|
||||
$hTimes{$sys} += $OnLine[$i];
|
||||
$hSessions{$sys} += 1;
|
||||
$hInBytes{$sys} += $InBytes[$i];
|
||||
$hOutBytes{$sys} += $OutBytes[$i];
|
||||
$hInFiles{$sys} += $InFiles[$i];
|
||||
$hOutFiles{$sys} += $OutFiles[$i];
|
||||
}
|
||||
@Syst = sort( keys( %hSystems ));
|
||||
|
||||
$~ = hHEADER;
|
||||
write;
|
||||
|
||||
$~ = hEACH;
|
||||
for( $i = 0; $i <= $#Syst; $i++ )
|
||||
{
|
||||
$sys = $Syst[$i];
|
||||
$cal = ( $hCalls{$sys} || 0 ); $acal += $cal;
|
||||
$ses = $hSessions{$sys}; $ases += $ses;
|
||||
$time = sec2str($hTimes{$sys}, "long"); $atime += $hTimes{$sys};
|
||||
$ibyte = $hInBytes{$sys}; $aibyte += $ibyte;
|
||||
$obyte = $hOutBytes{$sys}; $aobyte += $obyte;
|
||||
$inum = $hInFiles{$sys}; $ainum += $inum;
|
||||
$onum = $hOutFiles{$sys}; $aonum += $onum;
|
||||
|
||||
if( $hInFiles{$sys} > 0 || $hOutFiles{$sys} > 0 )
|
||||
{
|
||||
$cps = int( ($hInBytes{$sys} + $hOutBytes{$sys}) / $hTimes{$sys} );
|
||||
$acps += $cps;
|
||||
$sess++;
|
||||
}
|
||||
else
|
||||
{
|
||||
$cps = 0;
|
||||
}
|
||||
write;
|
||||
}
|
||||
|
||||
# Now, draw systems without sessions ..
|
||||
@Syst = sort( keys( %Calls ));
|
||||
$ses = "-";
|
||||
$time = "-";
|
||||
$ibyte = "-";
|
||||
$obyte = "-";
|
||||
$inum = "-";
|
||||
$onum = "-";
|
||||
$cps = "-";
|
||||
for( $i = 0; $i <= $#Syst; $i++ )
|
||||
{
|
||||
$sys = $Syst[$i];
|
||||
if( $Calls{$sys} )
|
||||
{
|
||||
$sys = $Syst[$i];
|
||||
$cal = $Calls{$sys}; $acal += $cal;
|
||||
write;
|
||||
}
|
||||
}
|
||||
$atime = sec2str($atime, "long");
|
||||
if( $sess > 0 )
|
||||
{
|
||||
$acps = int( $acps / $sess );
|
||||
}
|
||||
else
|
||||
{
|
||||
$acps = 0;
|
||||
}
|
||||
|
||||
$~ = hFOOTER;
|
||||
write;
|
||||
}
|
||||
|
||||
sub num2siz
|
||||
{
|
||||
my($num) = $_[0];
|
||||
my($siz);
|
||||
if($num < 1000) {
|
||||
$siz = $num.' ';
|
||||
} elsif($num < 10000000) {
|
||||
$siz = int($num/1024).'k';
|
||||
} else {
|
||||
$siz = int($num/(1024*1024)).'M';
|
||||
}
|
||||
return $siz;
|
||||
}
|
||||
|
||||
sub sec2str
|
||||
{
|
||||
my($sec) = $_[0];
|
||||
my($tip) = $_[1];
|
||||
my ($h, $m, $s);
|
||||
$h = int( $sec / 3600 );
|
||||
$m = int( ($sec - $h*3600) / 60);
|
||||
$s = int( $sec % 60 );
|
||||
if( $tip =~ /short/ ) {
|
||||
return sprintf("%02d:%02d", $h, $m);
|
||||
} elsif( $tip =~ /long/ ) {
|
||||
return sprintf("%03d:%02d:%02d", $h, $m, $s);
|
||||
}
|
||||
}
|
||||
|
||||
format HEADER =
|
||||
ª”” Call : 'I' - Incoming, 'O' - Outgoing
|
||||
ƒª” Status : 'U' - Unlisted, 'L' - Listed, 'P' - Protected
|
||||
ƒƒª Session : ' ' - Success, 'A' - Aborted
|
||||
¥<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˆ
|
||||
ƒ Time ƒStaƒ FTN ƒ On-Line ƒ Incoming ƒ Outgoing ƒ Avg.ƒSpeedƒ
|
||||
ƒhh:mm-hh:mmƒtusƒ Address ƒhhh:mm:ssƒ Bytesƒ N ƒ Bytesƒ N ƒ CPS ƒ ƒ
|
||||
–<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>…
|
||||
.
|
||||
format EACH =
|
||||
ƒ@<<<<-@<<<<ƒ@<<ƒ@<<<<<<<<<<<<<<ƒ@>>>>>>>>ƒ@>>>>>ƒ@>>ƒ@>>>>>ƒ@>>ƒ@>>>>ƒ@>>>>ƒ
|
||||
$start,$finish,$stat,$addr, $online, $ibyte, $in,$obyte, $on,$cps, $speed
|
||||
.
|
||||
format FOOTER =
|
||||
¤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ž
|
||||
@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
$Version
|
||||
.
|
||||
|
||||
format hHEADER =
|
||||
¥<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˆ
|
||||
ƒ FTN ƒ Total ƒ Time ƒ Incoming ƒ Outgoing ƒ CPS ƒ
|
||||
ƒ Address ƒCal.ƒSes.ƒ On-Line ƒ Bytes ƒ NN ƒ Bytes ƒ NN ƒ ƒ
|
||||
–<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD>¨<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>…
|
||||
.
|
||||
format hEACH =
|
||||
ƒ@<<<<<<<<<<<<<<ƒ@>>>ƒ@>>>ƒ@||||||||ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>ƒ
|
||||
$sys, $cal,$ses,$time, $ibyte, $inum,$obyte, $onum,$cps
|
||||
.
|
||||
format hFOOTER =
|
||||
“”””””””””””””””•””””•””””•”””””””””•”””””””””•””””•”””””””””•””””•”””””„
|
||||
ƒ TOTAL ƒ@>>>ƒ@>>>ƒ@||||||||ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>>>>>ƒ@>>>ƒ@>>>>ƒ
|
||||
$acal,$ases,$atime, $aibyte, $ainum,$aobyte,$aonum,$acps
|
||||
¤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ž
|
||||
@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
$Version
|
||||
.
|
||||
229
contrib/callout.sh
Normal file
229
contrib/callout.sh
Normal file
@ -0,0 +1,229 @@
|
||||
#!/bin/sh
|
||||
|
||||
Ver=1.1h
|
||||
|
||||
# óËÒÉÐÔ ÄÌÑ ÐÒÏÚ×ÏÎËÉ ÎÁ ÁÐÌÉÎËÏ×
|
||||
# ðÒÏ ×ÒÅÍÑ ÉÈ ÒÁÂÏÔÙ (É ÔÅÌÅÆÏÎÙ ÈÉÄÄÅÎÏ×) ÄÏÌÖÅÎ ÚÎÁÔØ ÍÅÊÌÅÒ
|
||||
#
|
||||
# úÁÔÏÞÅÎ ÄÌÑ ÍÅÊÌÅÒÁ BinkleyForce
|
||||
# äÌÑ ÄÒÕÇÉÈ ÐÒÁ×ÉÔØ ÆÕÎËÃÉÀ docallout
|
||||
|
||||
#
|
||||
# Copyright (c) 2000 by Georgi Fofanov, 2:5050/29@fidonet
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# ðÕÔØ Ë outbound'Õ ÎÕÖÎÏÊ ÚÏÎÙ (ÐÏËÁ ÚÎÁÅÍ ÔÏÌØËÏ ÐÒÏ ÏÄÎÕ ÚÏÎÕ)
|
||||
outb=/var/spool/ifmail/outb/
|
||||
|
||||
# ðÕÔØ Ë ËÁÔÁÌÏÇÕ Ó lock-ÆÁÊÌÁÍÉ (ÐÏÓÌÅÄÎÉÊ ÓÌÜÛ ÎÕÖÅÎ!)
|
||||
lock=/var/lock/
|
||||
|
||||
# ðÁÕÚÁ ÍÅÖÄÕ Ú×ÏÎËÁÍÉ
|
||||
# ÷ ÓÅËÕÎÄÁÈ
|
||||
dialdelay=120
|
||||
|
||||
# ðÅÒÉÏÄ ÓËÁÎÉÒÏ×ÁÎÉÑ outbound'Á
|
||||
# ðÏËÁ ÐÏÓÌÅ ÚÁ×ÅÒÛÅÎÉÑ ËÒÕÇÁ ÐÒÏÚ×ÏÎËÉ ÂÕÄÅÔ 2 ÐÁÕÚÙ - dialdelay É scan
|
||||
# ÷ ÓÅËÕÎÄÁÈ
|
||||
scan=60
|
||||
|
||||
# ðÁÕÚÁ ÍÅÖÄÕ ÐÒÏ×ÅÒËÁÍÉ lock-ÆÁÊÌÁ
|
||||
# ÷ ÓÅËÕÎÄÁÈ
|
||||
lockdelay=10
|
||||
|
||||
# òÁÓÐÏÌÏÖÅÎÉÅ ÍÅÊÌÅÒÁ
|
||||
mailer=/usr/local/bin/bforce
|
||||
|
||||
# ëÏÍÁÎÄÁ, ×ÙÐÏÌÎÑÅÍÁÑ ÐÏÓÌÅ ÕÓÐÅÛÎÏÊ ÓÅÓÓÉÉ
|
||||
after=/usr/local/bin/after_session
|
||||
|
||||
# õÓÔÒÏÊÓÔ×Ï, ÎÁ ËÏÔÏÒÏÍ ÓÉÄÉÔ ÍÏÄÅÍ
|
||||
TTY="ttyS1"
|
||||
|
||||
# úÄÅÓØ ÐÅÒÅÞÉÓÌÅÎÙ ÓÉÓÔÅÍÙ, ÎÁ ËÏÔÏÒÙÅ ÍÏÖÎÏ Ú×ÏÎÉÔØ É (ÞÅÒÅÚ ÐÒÏÂÅÌ) ÞÉÓÌÏ
|
||||
# ÉÈ ÍÏÄÅÍÎÙÈ ÌÉÎÉÊ
|
||||
# îÁÐÒÉÍÅÒ:
|
||||
# 2:5050/13 3
|
||||
# 2:5050/9 2
|
||||
# 2:5050/33 1
|
||||
sys_poll=/etc/fido/poll.list
|
||||
|
||||
# ðÏÌØÚÏ×ÁÔÅÌØ, ÏÔ ÉÍÅÎÉ ËÏÔÏÒÏÇÏ ÎÁÄÏ ÚÁÐÕÓËÁÔØ
|
||||
mailer_owner=fido
|
||||
|
||||
# ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ, ËÕÄÁ ÚÁÐÉÓÙ×ÁÅÔÓÑ ÓÐÉÓÏË ?lo É ?ut
|
||||
list_file=/var/spool/ifmail/list.lst
|
||||
|
||||
# ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ
|
||||
tmp_file=/var/spool/ifmail/list.tmp
|
||||
|
||||
# ÷ÒÅÍÅÎÎÙÊ ÆÁÊÌ, × ËÏÔÏÒÏÍ ÐÅÒÅÞÉÓÌÅÎÙ ÓÉÓÔÅÍÙ, ÎÁ ËÏÔÏÒÙÅ ÂÕÄÅÍ Ú×ÏÎÉÔØ
|
||||
poll_file=/var/spool/ifmail/polling.list
|
||||
|
||||
# íÁËÓÉÍÁÌØÎÏÅ ÞÉÓÌÏ ÐÏÐÙÔÏË ÄÏÚ×ÏÎÉÔØÓÑ ÎÁ ÓÉÓÔÅÍÕ
|
||||
MAXTRY=25
|
||||
|
||||
# óËÏÌØËÏ ×ÒÅÍÅÎÉ ÎÅ Ú×ÏÎÉÔØ ÎÁ ÓÉÓÔÅÍÕ, ÅÓÌÉ ÉÓÞÅÒÐÁÎÏ ÞÉÓÌÏ ÐÏÐÙÔÏË ÄÏÚ×ÏÎÁ
|
||||
# ÷ ÍÉÎÕÔÁÈ
|
||||
MAXTIME=60
|
||||
|
||||
# ðÒÏÉÚ×ÏÄÉÍ Ú×ÏÎÏË
|
||||
function docallout ()
|
||||
{
|
||||
local zone=$1 net=$2 node=$3 point=$4 curtry=$5 numline=$6 line
|
||||
|
||||
let line=${curtry}%${numline}
|
||||
|
||||
if [ $point = 0 ] ; then
|
||||
echo -n `date +%b\ %m\ %T` callout[$$] ú×ÏÎÉÍ ÎÁ ${zone}:${net}/${node} \(try \#${curtry}\)
|
||||
$mailer ${zone}:${net}/${node} -l $line
|
||||
let result=$?
|
||||
else
|
||||
echo -n `date +%b\ %m.%Y\ %T` callout[$$] ú×ÏÎÉÍ ÎÁ ${zone}:${net}/${node}.${point} \(try \#${curtry}\)
|
||||
$mailer ${zone}:${net}/${node}.${point} -l $line
|
||||
let result=$?
|
||||
fi
|
||||
|
||||
case $result in
|
||||
0 ) echo " ÕÓÐÅÛÎÏ" ;;
|
||||
* ) echo " ÏÛÉÂËÁ" \#$result ;;
|
||||
esac
|
||||
|
||||
if [ $result = 0 ] ; then
|
||||
echo `date +%s` 0 0 >$sts
|
||||
`$after`
|
||||
else
|
||||
echo `date +%s` $curtry $result >$sts
|
||||
fi
|
||||
}
|
||||
|
||||
# ðÒÏ×ÅÒÑÅÍ, ÍÏÖÎÏ ÌÉ Ú×ÏÎÉÔØ ÎÁ ÜÔÕ ÓÉÓÔÅÍÕ
|
||||
function checkcallout ()
|
||||
{
|
||||
local curtry=$1 zone=$2 net=$3 node=$4 point=$5 numline=0
|
||||
|
||||
if [ $point = 0 ] ; then
|
||||
`fgrep "${zone}:${net}/${node}" $sys_poll | awk '{ print "let numline=" $2 }'`
|
||||
else
|
||||
`fgrep "${zone}:${net}/${node}.${point}" $sys_poll | awk '{ print "let numline=" $2 }'`
|
||||
fi
|
||||
if [ $numline == 0 ] ; then return ; fi
|
||||
|
||||
docallout $zone $net $node $point $curtry $numline
|
||||
}
|
||||
|
||||
# óËÁÎÉÒÕÅÍ outbound
|
||||
function scandir ()
|
||||
{
|
||||
find -type f -and \( -name "*.?lo" -o -name "*.?ut" \) > $list_file
|
||||
for file in `cat $list_file` ; do
|
||||
eval `echo $file | awk '{ sub(/\.\//, "")
|
||||
if (substr($0, 9, 4) == ".pnt") {
|
||||
point = substr($0, 18, 4)
|
||||
} else {
|
||||
point = 0
|
||||
}
|
||||
printf "zonehex=%s nethex=%s nodehex=%s pointhex=%s let zone=0x%s net=0x%s node=0x%s point=0x%s",
|
||||
"2", substr($0, 1, 4), substr($0, 5, 4), point,
|
||||
"2", substr($0, 1, 4), substr($0, 5, 4), point
|
||||
}'`
|
||||
ext=${file:${#file}-3}
|
||||
sts=${file%%?ut}
|
||||
sts=${sts%%?lo}
|
||||
bsy=${sts}bsy
|
||||
sts=${sts}sts
|
||||
if [ $ext != hlo -a $ext != hut ] ; then
|
||||
echo ${zone} ${net} ${node} ${point} $sts $bsy >> $tmp_file
|
||||
fi
|
||||
done
|
||||
|
||||
rm $list_file
|
||||
|
||||
if [ -f $tmp_file ] ; then
|
||||
`cat $tmp_file | sort | uniq > $poll_file`
|
||||
rm $tmp_file
|
||||
n=0
|
||||
for sys in `cat $poll_file` ; do
|
||||
let n=${n}+1
|
||||
let tmp=${n}%6
|
||||
case $tmp in
|
||||
1 ) let zone=$sys ;;
|
||||
2 ) let net=$sys ;;
|
||||
3 ) let node=$sys ;;
|
||||
4 ) let point=$sys ;;
|
||||
5 ) sts=$sys ;;
|
||||
0 ) bsy=$sys ;;
|
||||
esac
|
||||
if [ $tmp == 0 ] ; then
|
||||
while [ -e ${lock}LCK..$TTY ]
|
||||
do
|
||||
sleep $lockdelay
|
||||
done
|
||||
if [ ! -f $bsy ] ; then
|
||||
if [ ! -f $sts ] ; then
|
||||
let lasttime=0 retries=0 errcode=0
|
||||
else
|
||||
`cat $sts|awk '{ print "let lasttime=" $1 " retries=" $2 " errcode=" $3 }'`
|
||||
fi
|
||||
let curtime=`date +%s`
|
||||
let timediff=${curtime}-${lasttime}
|
||||
let curtry=${retries}+1
|
||||
if [ $curtry -gt $MAXTRY ] ; then
|
||||
if [ $timediff -gt $MAXTIME ] ; then
|
||||
let curtry=1
|
||||
checkcallout $curtry $zone $net $node $point
|
||||
sleep $dialdelay
|
||||
fi
|
||||
else
|
||||
checkcallout $curtry $zone $net $node $point
|
||||
sleep $dialdelay
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
rm $poll_file
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function main ()
|
||||
{
|
||||
|
||||
cd $outb
|
||||
|
||||
while [ ! -f /tmp/callout.exit ] ; do
|
||||
if [ ! -e ${lock}LCK..$TTY ]; then
|
||||
scandir
|
||||
sleep $scan
|
||||
else
|
||||
sleep $lockdelay
|
||||
fi
|
||||
done
|
||||
rm /tmp/callout.exit
|
||||
}
|
||||
|
||||
if [ `whoami` != "$mailer_owner" ]; then
|
||||
echo "wrong uid, run as user $mailer_owner (rc=2)"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
. /etc/profile > /dev/null 2>&1
|
||||
let MAXTIME=${MAXTIME}*60
|
||||
main >> /var/log/ifmail/callout.log 2>&1
|
||||
|
||||
## éÚÍÅÎÅÎÉÑ
|
||||
|
||||
# Ver 1.1, 09 Jul 2000:
|
||||
#
|
||||
# ïÂÎÕÌÅÎÉÅ ÞÉÓÌÁ ÐÏÐÙÔÏË ÐÏÓÌÅ ÕÓÐÅÛÎÏÊ ÓÅÓÓÉÉ
|
||||
#
|
||||
# îÅ ÒÁÂÏÔÁÌ MAXTIME
|
||||
|
||||
# Ver 1.0, 08 Jul 2000:
|
||||
#
|
||||
# ðÅÒ×ÁÑ ÓÔÁÂÉÌØÎÁÑ ×ÅÒÓÉÑ
|
||||
51
contrib/init.d/bforce
Normal file
51
contrib/init.d/bforce
Normal file
@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# bforce FTN mailer
|
||||
#
|
||||
# chkconfig: 345 94 14
|
||||
# description: Starts and stops the binkleyforce mailer daemon
|
||||
#
|
||||
# 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.
|
||||
|
||||
OWNER=uucp
|
||||
BFORCE=/usr/local/fido/bin/bforce
|
||||
|
||||
# Source function library.
|
||||
. /etc/init.d/functions
|
||||
|
||||
[ -f $BFORCE ] || exit 0
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
# Start daemon.
|
||||
echo -n "Starting bforce: "
|
||||
su $OWNER -c ". /etc/rc.d/init.d/functions; daemon $BFORCE -d"
|
||||
echo
|
||||
touch /var/lock/subsys/bforce
|
||||
;;
|
||||
stop)
|
||||
# Stop daemon.
|
||||
echo -n "Shutting down bforce: "
|
||||
killproc bforce
|
||||
rm -f /var/lock/subsys/bforce
|
||||
echo
|
||||
;;
|
||||
status)
|
||||
status bforce
|
||||
exit $?
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
exit $?
|
||||
;;
|
||||
*)
|
||||
echo "Usage: bforce {start|stop|status|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
44
contrib/init.d/bforce.debian
Normal file
44
contrib/init.d/bforce.debian
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# bforce FTN mailer
|
||||
#
|
||||
# chkconfig: 345 94 14
|
||||
# description: Starts and stops the binkleyforce mailer daemon
|
||||
#
|
||||
# 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.
|
||||
|
||||
OWNER=uucp
|
||||
BFORCE=/usr/local/fido/bin/bforce
|
||||
|
||||
[ -f $BFORCE ] || exit 0
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
# Start daemon.
|
||||
echo -n "Starting bforce. "
|
||||
su $OWNER -c "daemon $BFORCE -d"
|
||||
echo
|
||||
touch /var/lock/subsys/bforce
|
||||
;;
|
||||
stop)
|
||||
# Stop daemon.
|
||||
echo -n "Shutting down bforce. "
|
||||
$BFORCE -q
|
||||
rm -f /var/lock/subsys/bforce
|
||||
echo
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
exit $?
|
||||
;;
|
||||
*)
|
||||
echo "Usage: bforce {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
366
contrib/outman
Normal file
366
contrib/outman
Normal file
@ -0,0 +1,366 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# Copyright (c) 2000 by Alexander Belkin <adb@newmail.ru>
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tcl script for creating polls, file requests and file attaches
|
||||
#
|
||||
# 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.
|
||||
|
||||
##################
|
||||
# Program settings
|
||||
|
||||
# Defaults for address completion
|
||||
set def_zone 2
|
||||
set def_net 5020
|
||||
set def_node 1398
|
||||
|
||||
# Path to your main BSO directory (not implemented)
|
||||
#set bso_dir "/var/spool/ftn/out"
|
||||
|
||||
# Path to your ASO directory
|
||||
set aso_dir "/var/spool/fido/amiga.out"
|
||||
|
||||
# Log file name
|
||||
set logfile "/var/log/bforce/outman.log"
|
||||
|
||||
# Uncomment this if you not need logging
|
||||
#set logfile {}
|
||||
|
||||
################################
|
||||
# The program's body starts here
|
||||
|
||||
set LOG {}
|
||||
|
||||
proc stupid_user {} {
|
||||
|
||||
puts "Usage: outman <\[poll|freq|send]> \[options] <address> \[files]\n"
|
||||
puts "options:"
|
||||
puts " -hold set hold flavor"
|
||||
puts " -normal set normal flavor (default)"
|
||||
puts " -crash set crash flavor"
|
||||
puts " -kill kill files after send"
|
||||
puts " -truncate truncate files after send"
|
||||
puts ""
|
||||
puts "Mail bug reports to <adb@newmail.ru>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
proc log {str} {
|
||||
|
||||
global LOG
|
||||
global logfile
|
||||
|
||||
if { $logfile != {} } {
|
||||
|
||||
if { $LOG == {} } {
|
||||
set LOG [open $logfile "a"]
|
||||
}
|
||||
|
||||
set seconds [clock seconds]
|
||||
|
||||
puts $LOG "[clock format $seconds -format "%d/%m %H:%M:%S"] $str"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
proc parse_addr {str} {
|
||||
|
||||
global def_zone
|
||||
global def_net
|
||||
global def_node
|
||||
set zone $def_zone
|
||||
set net $def_net
|
||||
set node $def_node
|
||||
set point 0
|
||||
|
||||
if { [regexp "^\[0-9]+:\[0-9]+/\[0-9]+\\.?\[0-9]*$" $str] } {
|
||||
|
||||
regexp "(\[0-9]+):(\[0-9]+)/(\[0-9]+)\\.?(\[0-9]*)$" $str \
|
||||
{} zone net node point
|
||||
|
||||
} elseif { [regexp "^\[0-9]+/\[0-9]+\\.?\[0-9]*$" $str] } {
|
||||
|
||||
regexp "(\[0-9]+)/(\[0-9]+)\\.?(\[0-9]*)$" $str \
|
||||
{} net node point
|
||||
|
||||
} elseif { [regexp "^\[0-9]+\\.?\[0-9]*$" $str] } {
|
||||
|
||||
regexp "^(\[0-9]*)\\.?(\[0-9]*)$" $str \
|
||||
{} node point
|
||||
|
||||
} elseif { [regexp "^\.\[0-9]+$" $str] } {
|
||||
|
||||
regexp "^\.(\[0-9]+)$" $str \
|
||||
{} point
|
||||
|
||||
} else {
|
||||
|
||||
puts "invalid address $str"
|
||||
return {}
|
||||
|
||||
}
|
||||
|
||||
if { $zone == {} } { set zone [$def_zone] }
|
||||
if { $net == {} } { set net [$def_net] }
|
||||
if { $node == {} } { set node [$def_node] }
|
||||
if { $point == {} } { set point 0 }
|
||||
|
||||
# puts "debug: address parse '$str' -> '$zone,$net,$node,$point'"
|
||||
|
||||
return "$zone $net $node $point"
|
||||
}
|
||||
|
||||
proc addrstr {addr} {
|
||||
|
||||
return [lindex $addr 0]:[lindex $addr 1]/[lindex $addr 2].[lindex $addr 3]
|
||||
}
|
||||
|
||||
#
|
||||
# TODO: support for outbounds not in the default zone
|
||||
#
|
||||
proc filename_bso {addr flavor} {
|
||||
|
||||
global bso_dir
|
||||
|
||||
set zone [lindex $addr 0]
|
||||
set net [lindex $addr 1]
|
||||
set node [lindex $addr 2]
|
||||
set point [lindex $addr 3]
|
||||
|
||||
if { $point } {
|
||||
|
||||
set name [format "%04x%04x.pnt/%08x" $net $node $point]
|
||||
|
||||
} else {
|
||||
|
||||
set name [format "%04x%04x" $net $node]
|
||||
|
||||
}
|
||||
|
||||
switch $flavor {
|
||||
"bsy" {
|
||||
return "$bso_dir/$name.bsy"
|
||||
}
|
||||
"freq" {
|
||||
return "$bso_dir/$name.req"
|
||||
}
|
||||
"hold" {
|
||||
return "$bso_dir/$name.hlo"
|
||||
}
|
||||
"crash" {
|
||||
return "$bso_dir/$name.clo"
|
||||
}
|
||||
default {
|
||||
return "$bso_dir/$name.flo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc filename_aso {addr flavor} {
|
||||
|
||||
global aso_dir
|
||||
|
||||
set name [lindex $addr 0].[lindex $addr 1].[lindex $addr 2].[lindex $addr 3]
|
||||
|
||||
switch $flavor {
|
||||
"bsy" {
|
||||
return "$aso_dir/$name.bsy"
|
||||
}
|
||||
"freq" {
|
||||
return "$aso_dir/$name.req"
|
||||
}
|
||||
"hold" {
|
||||
return "$aso_dir/$name.hlo"
|
||||
}
|
||||
"crash" {
|
||||
return "$aso_dir/$name.clo"
|
||||
}
|
||||
default {
|
||||
return "$aso_dir/$name.flo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc bsy_exist {addr} {
|
||||
|
||||
set bsyname [filename_aso $addr "bsy"]
|
||||
|
||||
if { [file exists $bsyname] } {
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
proc command_freq {addr files} {
|
||||
|
||||
set reqname [filename_aso $addr "freq"]
|
||||
set name {}
|
||||
|
||||
# puts "debug: file request name is '$reqname'"
|
||||
|
||||
set REQ [open $reqname "a"]
|
||||
|
||||
foreach name $files {
|
||||
puts $REQ $name
|
||||
log "request \"$name\" from [addrstr $addr]"
|
||||
}
|
||||
|
||||
close $REQ
|
||||
}
|
||||
|
||||
proc command_poll {addr flavor} {
|
||||
|
||||
set floname [filename_aso $addr $flavor]
|
||||
|
||||
if { ![file exists $floname] } {
|
||||
|
||||
set FLO [open $floname "a"]
|
||||
close $FLO
|
||||
log "poll [addrstr $addr] ($flavor)"
|
||||
|
||||
} else {
|
||||
|
||||
log "cannot create poll for [addrstr $addr]: allready polled"
|
||||
}
|
||||
}
|
||||
|
||||
proc command_send {addr files flavor action} {
|
||||
|
||||
set floname [filename_aso $addr $flavor]
|
||||
set name {}
|
||||
set curdir [exec pwd]
|
||||
|
||||
set FLO [open $floname "a"]
|
||||
|
||||
foreach name $files {
|
||||
if { [file exists $name] } {
|
||||
|
||||
if { [file pathtype $name] == "relative" } {
|
||||
if { [string match "./*" $name] } {
|
||||
set name [string range $name 2 end]
|
||||
}
|
||||
set name "$curdir/$name"
|
||||
}
|
||||
|
||||
log "send file \"$name\" ([file size $name] bytes) to [addrstr $addr] ($flavor)"
|
||||
|
||||
switch $action {
|
||||
"kill" {
|
||||
puts $FLO "^$name"
|
||||
}
|
||||
"truncate" {
|
||||
puts $FLO "#$name"
|
||||
}
|
||||
default {
|
||||
puts $FLO "@$name"
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
puts "skip file \"$name\" to [addrstr $addr]: file not exist"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
close $FLO
|
||||
}
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
|
||||
if { $argc < 2 } {
|
||||
stupid_user
|
||||
}
|
||||
|
||||
set command {}
|
||||
set address {}
|
||||
set addr {}
|
||||
set files {}
|
||||
set flavor "normal"
|
||||
set action "nothing"
|
||||
|
||||
for {set i 0} {$i < $argc} {incr i} {
|
||||
|
||||
set arg [lindex $argv $i]
|
||||
|
||||
if { [string index $arg 0] == "-" } {
|
||||
|
||||
switch [string range $arg 1 end] {
|
||||
"hold" {
|
||||
set flavor "hold"
|
||||
}
|
||||
"normal" {
|
||||
set flavor "normal"
|
||||
}
|
||||
"crash" {
|
||||
set flavor "crash"
|
||||
}
|
||||
"kill" {
|
||||
set action "kill"
|
||||
}
|
||||
"truncate" {
|
||||
set action "truncate"
|
||||
}
|
||||
default {
|
||||
puts "unknown command line option '$arg'"
|
||||
stupid_user
|
||||
}
|
||||
}
|
||||
|
||||
} elseif { $command == {} } {
|
||||
|
||||
set command $arg
|
||||
|
||||
} elseif { $address == {} } {
|
||||
|
||||
set address $arg
|
||||
set addr [parse_addr $address]
|
||||
if { $addr == {} } {
|
||||
stupid_user
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
lappend files $arg
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if { $command == {} || $address == {} } {
|
||||
stupid_user
|
||||
}
|
||||
|
||||
if { [bsy_exist $addr] } {
|
||||
puts "bsy file exist for address [addrstr $addr]"
|
||||
exit 2
|
||||
}
|
||||
|
||||
switch $command {
|
||||
"poll" {
|
||||
command_poll $addr $flavor
|
||||
}
|
||||
"freq" {
|
||||
command_freq $addr $files
|
||||
}
|
||||
"send" {
|
||||
command_send $addr $files $flavor $action
|
||||
}
|
||||
default {
|
||||
puts "unknown command $command"
|
||||
stupid_user
|
||||
}
|
||||
}
|
||||
|
||||
if { $LOG != {} } {
|
||||
close $LOG
|
||||
}
|
||||
|
||||
exit 0
|
||||
|
||||
116
contrib/timesync.tcl
Normal file
116
contrib/timesync.tcl
Normal file
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# Copyright (c) 2000 by Alexander Belkin <adb@newmail.ru>
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Time syncronization utility
|
||||
#
|
||||
# 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.
|
||||
|
||||
##################
|
||||
# Program settings
|
||||
|
||||
set bforce_log_file "/var/log/bforce/bf-log.ttyS0"
|
||||
set sync_with_addr "2:450/102"
|
||||
set max_time_diff 1800
|
||||
set min_time_diff 20
|
||||
set news_groups "local.robots"
|
||||
set from_user "Time Robot <root@fido.xxx.local>"
|
||||
set inews_cmd "/usr/bin/inews"
|
||||
|
||||
################################
|
||||
# The program's body starts here
|
||||
|
||||
set sess_pid ""
|
||||
set remote_times ""
|
||||
set local_times ""
|
||||
set TEXT ""
|
||||
|
||||
set INP [open $bforce_log_file "r"]
|
||||
foreach line [split [read $INP] "\n"] {
|
||||
|
||||
set fields [split $line " "]
|
||||
set pid [lindex $fields 3]
|
||||
set time [join [lrange $fields 0 2]]
|
||||
set data [join [lrange $fields 4 end]]
|
||||
|
||||
if { [string match "*Address : $sync_with_addr" $data] } {
|
||||
set sess_pid $pid
|
||||
set sess_time ""
|
||||
} elseif { [string match "*Time :*" $data] } {
|
||||
if { $sess_pid == $pid } {
|
||||
regexp "Time : (.+)" $data {} timestr
|
||||
if { $timestr != "" } {
|
||||
set sess_time $timestr
|
||||
}
|
||||
}
|
||||
} elseif { [string match "remote is*,protected" $data] } {
|
||||
if { $sess_pid == $pid } {
|
||||
if { $sess_time != "" && $time != "" } {
|
||||
lappend remote_times $sess_time
|
||||
lappend local_times $time
|
||||
}
|
||||
set sess_pid ""
|
||||
set sess_time ""
|
||||
}
|
||||
} elseif { [string match "remote is*" $data] } {
|
||||
if { $sess_pid == $pid } {
|
||||
set sess_pid ""
|
||||
set sess_time ""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
close $INP
|
||||
|
||||
set last_rem_time [lindex $remote_times end]
|
||||
set last_loc_time [lindex $local_times end]
|
||||
|
||||
if { $last_rem_time != "" && $last_loc_time != "" } {
|
||||
|
||||
regexp "(\[0-9]+):(\[0-9]+):(\[0-9]+)" $last_rem_time {} rh rm rs
|
||||
regexp "(\[0-9]+):(\[0-9]+):(\[0-9]+)" $last_loc_time {} lh lm ls
|
||||
set rem [expr "$rh*3600 + $rm*60 + $rs"]
|
||||
set loc [expr "$lh*3600 + $lm*60 + $ls"]
|
||||
set diff [expr "$rem - $loc"]
|
||||
|
||||
if { [expr abs($diff)] < $min_time_diff } {
|
||||
# Do nothing
|
||||
} elseif { [expr abs($diff)] <= $max_time_diff } {
|
||||
set old_sec [clock seconds]
|
||||
set new_sec [expr $old_sec + $diff]
|
||||
|
||||
exec /bin/date -s [clock format $new_sec -format "%d-%b-%Y %H:%M:%S"]
|
||||
exec /sbin/clock -wu
|
||||
|
||||
append TEXT "The System time was synchronized with the node $sync_with_addr\n\n"
|
||||
append TEXT "Old time : [clock format $old_sec]\n"
|
||||
append TEXT "New time : [clock format $new_sec]\n"
|
||||
append TEXT "Time difference : $diff second(s)\n"
|
||||
} else {
|
||||
set old_sec [clock seconds]
|
||||
set new_sec [expr $old_sec + $diff]
|
||||
|
||||
append TEXT "The System time WAS NOT synchronized with the node $sync_with_addr\n\n"
|
||||
append TEXT "Current time : [clock format $old_sec]\n"
|
||||
append TEXT "Want set time : [clock format $new_sec]\n"
|
||||
append TEXT "Time difference : $diff second(s) (must be lower $max_time_diff seconds)\n"
|
||||
}
|
||||
}
|
||||
|
||||
if { $TEXT != "" } {
|
||||
|
||||
set MSG "From: $from_user\n"
|
||||
append MSG "Subject: Time synchronization\n"
|
||||
append MSG "Newsgroups: $news_groups\n\n"
|
||||
append MSG $TEXT
|
||||
|
||||
exec $inews_cmd -h << $MSG
|
||||
}
|
||||
|
||||
exit 0
|
||||
|
||||
6
contrib/u-srif/INFO
Normal file
6
contrib/u-srif/INFO
Normal file
@ -0,0 +1,6 @@
|
||||
License notice for u-srif-py
|
||||
|
||||
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.
|
||||
27
contrib/u-srif/conf/report.footer
Normal file
27
contrib/u-srif/conf/report.footer
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
+-----------+----------------------+----------------------+
|
||||
| | Statistic | Limits |
|
||||
| Period +-------------+--------+-------------+--------+
|
||||
| | Size | Number | Size | Number |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Day | @%-11d,sent_day_size@ | @%-6d,sent_day_num@ | @%-11s,limit_size_day@ | @%-6s,limit_num_day@ |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Week | @%-11d,sent_week_size@ | @%-6d,sent_week_num@ | @%-11s,limit_size_week@ | @%-6s,limit_num_week@ |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Month | @%-11d,sent_month_size@ | @%-6d,sent_month_num@ | @%-11s,limit_size_month@ | @%-6s,limit_num_month@ |
|
||||
+-----------+-------------+--------+-------------+--------+
|
||||
| Total | @%-11d,sent_total_size@ | @%-6d,sent_total_num@ |
|
||||
+-----------+-------------+--------+
|
||||
|
||||
******************************************************************************
|
||||
File requests policy
|
||||
******************************************************************************
|
||||
|
||||
File requests supported at 00:00-05:30 and at least 9600 speed
|
||||
|
||||
There are aliases for file requests:
|
||||
|
||||
FILES - Happy Station files list
|
||||
BFORCE - The latest version of the binkleyforce mailer
|
||||
|
||||
Bye, call again!
|
||||
2
contrib/u-srif/conf/report.header
Normal file
2
contrib/u-srif/conf/report.header
Normal file
@ -0,0 +1,2 @@
|
||||
Hello, @%s,remote_sysop@!
|
||||
|
||||
6
contrib/u-srif/conf/u-srif.aliases
Normal file
6
contrib/u-srif/conf/u-srif.aliases
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
files /home/ftp/pub/info/happy.zip
|
||||
filelist /home/ftp/pub/info/happy.lst
|
||||
test /home/ftp/pub/fileecho/PNT5020/pnt5020.zip
|
||||
bforce /home/ftp/pub/bforce/bforce-last.tar.gz
|
||||
|
||||
21
contrib/u-srif/conf/u-srif.conf
Normal file
21
contrib/u-srif/conf/u-srif.conf
Normal file
@ -0,0 +1,21 @@
|
||||
##############################################################################
|
||||
### u-srif FREQ processor configuration file #################################
|
||||
##############################################################################
|
||||
|
||||
# Spool directory for files index, links statistic, etc.
|
||||
spool-dir /var/spool/u-srif
|
||||
|
||||
# Log file name
|
||||
log-file /var/log/ftn/u-srif.log
|
||||
|
||||
# File with list of freqable directories
|
||||
dir-list-file /usr/local/etc/u-srif/u-srif.dirs
|
||||
|
||||
# File with list of freqable directories
|
||||
alias-list-file /usr/local/etc/u-srif/u-srif.aliases
|
||||
|
||||
freq-policy /usr/local/etc/u-srif/policy.text
|
||||
|
||||
freq-magic bforce-cvs /usr/local/etc/u-srif/magic/bforce-cvs
|
||||
freq-alias = files /home/ftp/pub password
|
||||
|
||||
42
contrib/u-srif/conf/u-srif.dirs
Normal file
42
contrib/u-srif/conf/u-srif.dirs
Normal file
@ -0,0 +1,42 @@
|
||||
/home/ftp/pub/bforce/
|
||||
/home/ftp/pub/fileecho/ADV_FTNSOFT/
|
||||
/home/ftp/pub/fileecho/AFTNMISC/
|
||||
/home/ftp/pub/fileecho/AVP/
|
||||
/home/ftp/pub/fileecho/BOOK/
|
||||
/home/ftp/pub/fileecho/CRACKER/
|
||||
/home/ftp/pub/fileecho/CRACKS/
|
||||
/home/ftp/pub/fileecho/FAR/
|
||||
/home/ftp/pub/fileecho/FR_CO.FILES/
|
||||
/home/ftp/pub/fileecho/FWUTILS/
|
||||
/home/ftp/pub/fileecho/GSS_BETA/
|
||||
/home/ftp/pub/fileecho/GSS_SOFT/
|
||||
/home/ftp/pub/fileecho/G_CHEAT/
|
||||
/home/ftp/pub/fileecho/IT.FILES/
|
||||
/home/ftp/pub/fileecho/IT.MP3/
|
||||
/home/ftp/pub/fileecho/IT.MUSIC/
|
||||
/home/ftp/pub/fileecho/IT.NDL/
|
||||
/home/ftp/pub/fileecho/LARRY.FILES/
|
||||
/home/ftp/pub/fileecho/HAPPY.XCK/
|
||||
/home/ftp/pub/fileecho/MOBIL/
|
||||
/home/ftp/pub/fileecho/NET5020/
|
||||
/home/ftp/pub/fileecho/PNT5020/
|
||||
/home/ftp/pub/fileecho/RUFO/
|
||||
/home/ftp/pub/fileecho/STICK.FILES/
|
||||
/home/ftp/pub/fileecho/T-MAIL/
|
||||
/home/ftp/pub/fileecho/UNKNOWN/
|
||||
/home/ftp/pub/fileecho/XDOCREF/
|
||||
/home/ftp/pub/fileecho/XGAMSOL/
|
||||
/home/ftp/pub/fileecho/XHAMRADIO/
|
||||
/home/ftp/pub/fileecho/XHRDASUS/
|
||||
/home/ftp/pub/fileecho/XHRDDOCS/
|
||||
/home/ftp/pub/fileecho/XHRDIDC/
|
||||
/home/ftp/pub/fileecho/XHRDUSR/
|
||||
/home/ftp/pub/fileecho/XPICART/
|
||||
/home/ftp/pub/fileecho/XPICHUMOR/
|
||||
/home/ftp/pub/fileecho/XPICMUSIC/
|
||||
/home/ftp/pub/fileecho/XPICSHIP/
|
||||
/home/ftp/pub/fileecho/XPICSYSOP/
|
||||
/home/ftp/pub/fileecho/XPICWEAPON/
|
||||
/home/ftp/pub/files/uue_files/
|
||||
/home/ftp/pub/redhat-5.2/RedHat/RPMS/
|
||||
/home/ftp/pub/redhat-6.1/RedHat/RPMS/
|
||||
163
contrib/u-srif/lib/uconfig.py
Normal file
163
contrib/u-srif/lib/uconfig.py
Normal file
@ -0,0 +1,163 @@
|
||||
|
||||
import gdbm
|
||||
import string
|
||||
import os
|
||||
import ufido
|
||||
|
||||
ALIAS_TYPE_NORMAL = 1 # Traditional aliase
|
||||
ALIAS_TYPE_MAGIC = 2 # "Magic" alias
|
||||
|
||||
# TODO: These functions must generate an exception in case of errors
|
||||
def get_bool(str):
|
||||
str = string.lower(str)
|
||||
if str == 'yes' or str == 'true':
|
||||
return 1
|
||||
elif str == 'no' or str == 'false':
|
||||
return 0
|
||||
return None
|
||||
|
||||
def get_size(str):
|
||||
# TODO: support nice size formats like 64M, 10G
|
||||
return str
|
||||
|
||||
def get_alias(str, type):
|
||||
args = string.split(str)
|
||||
if len(args) < 2 or len(args) > 3:
|
||||
return None
|
||||
if len(args) == 3:
|
||||
passwd = args[2]
|
||||
else:
|
||||
passwd = None
|
||||
return Alias(args[0], args[1], passwd, type)
|
||||
|
||||
class Alias:
|
||||
""" Aliases implementation
|
||||
"""
|
||||
def __init__(self, name, filename, passwd, type):
|
||||
""" Alias initialisation
|
||||
"""
|
||||
self.name = name
|
||||
self.filename = filename
|
||||
self.type = type
|
||||
|
||||
def get(self, passwd):
|
||||
""" Get the list of files to send for this alias
|
||||
"""
|
||||
yield = []
|
||||
if self.type == ALIAS_TYPE_NORMAL:
|
||||
yield.append(self.filename)
|
||||
return yield
|
||||
elif self.type == ALIAS_TYPE_MAGIC:
|
||||
# Prepare the environment (TODO)
|
||||
putenv('PASSWORD', passwd)
|
||||
putenv('ADDRESS', None)
|
||||
putenv('PROTECTED', 'FALSE')
|
||||
putenv('LISTED', 'FALSE')
|
||||
# Execute magic program and process its output
|
||||
try:
|
||||
magic = popen(self.filename)
|
||||
line = magic.readline()
|
||||
while line:
|
||||
line = magic.readline()
|
||||
yield.append(string.strip(line))
|
||||
if magic.close():
|
||||
print "Magic return code is non-zero: ", self.filename
|
||||
return None
|
||||
return yield
|
||||
except IOError:
|
||||
print "Failed to run magic: ", self.filename
|
||||
return None
|
||||
|
||||
class Config:
|
||||
def read_dir_list(self):
|
||||
yield = []
|
||||
fp = open(self.dir_list_file, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
if line != '':
|
||||
yield.append(line)
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return yield
|
||||
|
||||
def read_alias_list(self):
|
||||
yield = []
|
||||
fp = open(self.alias_list_file, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
if line != '':
|
||||
[name, filename] = string.split(line, None, 1)
|
||||
yield.append(alias(name, filename))
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return yield
|
||||
|
||||
def read(self, name):
|
||||
fp = open(name, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
args = string.split(line, None, 1)
|
||||
if line[0:1] == '#' or len(line) == 0:
|
||||
pass
|
||||
elif len(args) != 2:
|
||||
print "Invalid string in config: ", line
|
||||
else:
|
||||
key = string.lower(args[0])
|
||||
val = args[1]
|
||||
if key == 'dir-list-file':
|
||||
self.dir_list_file = val
|
||||
elif key == 'send-report':
|
||||
self.send_report = get_bool(val)
|
||||
elif key == 'limit-size-day':
|
||||
self.limit_size_day = get_size(val)
|
||||
elif key == 'limit-size-week':
|
||||
self.limit_size_week = get_size(val)
|
||||
elif key == 'limit-size-month':
|
||||
self.limit_size_month = get_size(val)
|
||||
elif key == 'spool-dir':
|
||||
self.spool_dir = val
|
||||
elif key == 'freq-alias':
|
||||
self.freq_alias.append(get_alias(val, ALIAS_TYPE_NORMAL))
|
||||
elif key == 'freq-magic':
|
||||
self.freq_magic.append(get_alias(val, ALIAS_TYPE_MAGIC))
|
||||
elif key == 'log-file':
|
||||
self.log_file = val
|
||||
elif key == 'local-address':
|
||||
self.local_address.parse(var)
|
||||
elif key == 'report-header':
|
||||
self.report_header = val
|
||||
elif key == 'report-footer':
|
||||
self.report_footer = val
|
||||
elif key == 'report-from':
|
||||
self.report_from = val
|
||||
elif key == 'report-subj':
|
||||
self.report_subj = val
|
||||
elif key == 'stat-dbase':
|
||||
self.stat_dbase = val
|
||||
else:
|
||||
print "unknown config keyword:", key
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
|
||||
def __init__(self, name):
|
||||
self.dir_list_file = ''
|
||||
self.send_report = 0
|
||||
self.limit_size_day = 0
|
||||
self.limit_size_week = 0
|
||||
self.limit_size_month = 0
|
||||
self.spool_dir = ''
|
||||
self.freq_policy = ''
|
||||
self.freq_alias = []
|
||||
self.freq_magic = []
|
||||
self.log_file = ''
|
||||
self.local_address = ufido.address()
|
||||
self.report_header = ''
|
||||
self.report_footer = ''
|
||||
self.report_from = 'FREQ manager'
|
||||
self.report_subj = 'FREQ report'
|
||||
self.stat_dbase = None
|
||||
self.read(name)
|
||||
|
||||
151
contrib/u-srif/lib/udbase.py
Normal file
151
contrib/u-srif/lib/udbase.py
Normal file
@ -0,0 +1,151 @@
|
||||
|
||||
import os
|
||||
import gdbm
|
||||
import string
|
||||
|
||||
def get_file_desc(filename):
|
||||
path, name = os.path.split(filename)
|
||||
descname = os.path.join(path, '.desc', name + '.desc')
|
||||
if not os.path.isfile(descname):
|
||||
return None
|
||||
try:
|
||||
fp = open(descname, 'r')
|
||||
except IOError:
|
||||
print 'Cannot open', descname
|
||||
return None
|
||||
line = fp.readline()
|
||||
yield = ''
|
||||
while line:
|
||||
yield = yield + line
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return string.strip(yield)
|
||||
|
||||
def get_area_desc(areapath):
|
||||
descname = os.path.join(areapath, '.desc', '.desc')
|
||||
if not os.path.isfile(descname):
|
||||
return None
|
||||
try:
|
||||
fp = open(descname, 'r')
|
||||
except IOError:
|
||||
print 'Cannot open', descname
|
||||
return None
|
||||
line = fp.readline()
|
||||
yield = ''
|
||||
while line:
|
||||
yield = yield + line
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return string.strip(yield)
|
||||
|
||||
class file:
|
||||
def stat(self):
|
||||
if self.fake:
|
||||
return
|
||||
try:
|
||||
statinfo = os.stat(self.fullname)
|
||||
self.size = statinfo[6]
|
||||
self.time = statinfo[8]
|
||||
except OSError:
|
||||
self.size = -1
|
||||
self.time = -1
|
||||
self.desc = 'File is not accessable'
|
||||
|
||||
def set(self, fullname, name = None, area = '', dlcnt = 0,\
|
||||
mode = '', desc = '', fake = 0):
|
||||
if name == None:
|
||||
self.name = os.path.split(fullname)[1]
|
||||
else:
|
||||
self.name = name
|
||||
self.fullname = fullname
|
||||
self.dlcnt = dlcnt
|
||||
self.size = -1
|
||||
self.time = -1
|
||||
self.area = area
|
||||
self.mode = mode
|
||||
self.desc = desc
|
||||
self.fake = fake
|
||||
|
||||
def reset(self):
|
||||
self.name = ''
|
||||
self.fullname = ''
|
||||
self.area = ''
|
||||
self.dlcnt = 0
|
||||
self.mode = ''
|
||||
self.desc = ''
|
||||
self.size = -1
|
||||
self.time = -1
|
||||
self.fake = 0
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
class filebase:
|
||||
""" Index entry format: [fullname, area, dlcnt, accessmode, desc]
|
||||
"""
|
||||
def open(self, mode):
|
||||
self.db = gdbm.open(self.dbfile, mode)
|
||||
|
||||
def close(self):
|
||||
self.db.close()
|
||||
|
||||
def sync(self):
|
||||
self.db.sync()
|
||||
|
||||
def clean(self):
|
||||
for filename in self.db.keys():
|
||||
file = self.get(filename)
|
||||
if not os.path.isfile(file.fullname):
|
||||
print 'Remove file "%s" from index' % file.fullname
|
||||
del self.db[filename]
|
||||
|
||||
def get_all(self, filenames):
|
||||
""" Lookup files in the database and return list
|
||||
of file objects
|
||||
"""
|
||||
yield = []
|
||||
for name in filenames:
|
||||
files = self.get(name)
|
||||
if files and len(files) > 0:
|
||||
yield.extend(files)
|
||||
return yield
|
||||
|
||||
def get(self, filename):
|
||||
""" Lookup file by its name in the database and
|
||||
return list of file objects for this name
|
||||
"""
|
||||
yield = []
|
||||
if not self.db.has_key(filename):
|
||||
return None
|
||||
files_info = eval(self.db[filename])
|
||||
if files_info == None:
|
||||
newfile = file()
|
||||
newfile.set(filename, desc='File not found', fake=1)
|
||||
yield.append(newfile)
|
||||
else:
|
||||
for finfo in files_info:
|
||||
newfile = file()
|
||||
finfo = eval(finfo)
|
||||
newfile.set(finfo[0], area = finfo[1],\
|
||||
dlcnt = finfo[2], mode = finfo[3],\
|
||||
desc = finfo[4])
|
||||
yield.append(newfile)
|
||||
return yield
|
||||
|
||||
def put(self, file):
|
||||
finfo = []
|
||||
finfo.append(file.fullname)
|
||||
finfo.append(file.area)
|
||||
finfo.append(file.dlcnt)
|
||||
finfo.append(file.mode)
|
||||
finfo.append(file.desc)
|
||||
if self.db.has_key(file.name):
|
||||
files_info = eval(self.db[file.name])
|
||||
else:
|
||||
files_info = []
|
||||
files_info.append(repr(finfo))
|
||||
self.db[file.name] = repr(files_info)
|
||||
|
||||
def __init__(self, spooldir):
|
||||
self.dbfile = os.path.join(spooldir, 'filebase.db')
|
||||
|
||||
181
contrib/u-srif/lib/ufido.py
Normal file
181
contrib/u-srif/lib/ufido.py
Normal file
@ -0,0 +1,181 @@
|
||||
|
||||
import string
|
||||
import re
|
||||
import struct
|
||||
import time
|
||||
|
||||
#address_1 = re.compile('^\([0-9]+\):\([0-9]+\)/\([0-9]+\)\.?\([0-9]+\)?$')
|
||||
address_1 = re.compile('^(\d+):(\d+)/(\d+)\.?(\d+)?$')
|
||||
|
||||
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\
|
||||
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Jan')
|
||||
|
||||
class address:
|
||||
def is_set(self):
|
||||
if self.zone > 0 and self.net > 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def string(self):
|
||||
if self.invalid:
|
||||
yield = 'Invalid address'
|
||||
elif self.point > 0:
|
||||
yield = '%d:%d/%d.%d' % (self.zone, self.net, self.node, self.point)
|
||||
else:
|
||||
yield = '%d:%d/%d' % (self.zone, self.net, self.node)
|
||||
return yield
|
||||
|
||||
def parse(self, str):
|
||||
match = address_1.match(str)
|
||||
if match:
|
||||
try:
|
||||
self.zone = string.atoi(match.group(1))
|
||||
self.net = string.atoi(match.group(2))
|
||||
self.node = string.atoi(match.group(3))
|
||||
tmp = match.group(4)
|
||||
if tmp and tmp != '-1':
|
||||
self.point = string.atoi(tmp)
|
||||
else:
|
||||
self.point = 0
|
||||
self.invalid = 0
|
||||
except IndexError:
|
||||
self.__init__()
|
||||
return -1
|
||||
else:
|
||||
print "Regexp doesnt match!"
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def __init__(self):
|
||||
self.zone = 0
|
||||
self.net = 0
|
||||
self.node = 0
|
||||
self.point = 0
|
||||
self.invalid = 1
|
||||
|
||||
class message:
|
||||
def newmsg(self, addr_from, user_from, addr_to, user_to, subject):
|
||||
self.unix_time = time.time()
|
||||
self.addr_orig = addr_from
|
||||
self.addr_dest = addr_to
|
||||
self.user_orig = user_from
|
||||
self.user_dest = user_to
|
||||
self.subject = subject
|
||||
self.msgbody = ''
|
||||
self.append_line('\001FMPT %d' % self.addr_orig.point)
|
||||
self.append_line('\001TOPT %d' % self.addr_dest.point)
|
||||
|
||||
def append_line(self, string):
|
||||
self.msgbody = self.msgbody + string + '\r'
|
||||
|
||||
def append_text(self, text):
|
||||
for line in string.split(text, '\n'):
|
||||
self.append_line(line)
|
||||
|
||||
def append_file(self, filename):
|
||||
try:
|
||||
fp = open(filename, 'r')
|
||||
except IOError:
|
||||
print 'Cannot append file', filename
|
||||
return
|
||||
line = fp.readline()
|
||||
while line:
|
||||
self.append_line(string.rstrip(line))
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
|
||||
def __init__(self):
|
||||
self.unix_time = 0
|
||||
self.addr_orig = address()
|
||||
self.addr_dest = address()
|
||||
self.user_orig = ''
|
||||
self.user_dest = ''
|
||||
self.subject = ''
|
||||
self.msgbody = ''
|
||||
self.origin = ''
|
||||
|
||||
class packet:
|
||||
def reset(self):
|
||||
self.addr_orig = address()
|
||||
self.addr_dest = address()
|
||||
self.password = ''
|
||||
self.messages = []
|
||||
|
||||
# TODO
|
||||
def read(self, filename):
|
||||
self.reset()
|
||||
fp = open(filename, "w")
|
||||
fp.close()
|
||||
|
||||
def get_time_string(self, unix_time):
|
||||
msgtime = time.localtime(unix_time)
|
||||
return '%02d %s %02d %02d:%02d:%02d' % \
|
||||
(msgtime[2], months[msgtime[1]], msgtime[0] % 100, \
|
||||
msgtime[3], msgtime[4], msgtime[5])
|
||||
|
||||
def get_message_header(self, message):
|
||||
return struct.pack('7H20s',\
|
||||
2,\
|
||||
message.addr_orig.node,\
|
||||
message.addr_dest.node,\
|
||||
message.addr_orig.net,\
|
||||
message.addr_dest.net,\
|
||||
0,\
|
||||
0,\
|
||||
self.get_time_string(message.unix_time)) + \
|
||||
message.user_dest[0:36] + '\0' + \
|
||||
message.user_orig[0:36] + '\0' + \
|
||||
message.subject[0:72] + '\0'
|
||||
|
||||
def get_packet_header(self):
|
||||
now = time.localtime(time.time())
|
||||
return struct.pack('13H8s12H',\
|
||||
self.addr_orig.node,\
|
||||
self.addr_dest.node,\
|
||||
now[0], # Year\
|
||||
now[1], # Month\
|
||||
now[2], # Day\
|
||||
now[3], # Hour\
|
||||
now[4], # Minute\
|
||||
now[5], # Second\
|
||||
9600, # Baud\
|
||||
2, # PKT type\
|
||||
self.addr_orig.net,\
|
||||
self.addr_dest.net,\
|
||||
254, # Prod. code + Rev. number\
|
||||
self.password,\
|
||||
self.addr_orig.zone,\
|
||||
self.addr_dest.zone,\
|
||||
0, # AuxNet\
|
||||
0, # CWvalidationCopy\
|
||||
0, # ProductCode + Revision \
|
||||
0, # CapabilWord\
|
||||
self.addr_orig.zone,\
|
||||
self.addr_dest.zone,\
|
||||
self.addr_orig.point,\
|
||||
self.addr_dest.point,\
|
||||
0,
|
||||
0)
|
||||
|
||||
def write(self, filename):
|
||||
fp = open(filename, "w")
|
||||
fp.write(self.get_packet_header())
|
||||
|
||||
for msg in self.messages:
|
||||
fp.write(self.get_message_header(msg))
|
||||
fp.write(msg.msgbody)
|
||||
fp.write('\0')
|
||||
|
||||
fp.write('\0\0')
|
||||
fp.close()
|
||||
|
||||
def add_message(self, message):
|
||||
self.messages.append(message)
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
if __name__ == "__main__":
|
||||
tmp = address()
|
||||
tmp.parse('2:5020/2120')
|
||||
print tmp.string()
|
||||
102
contrib/u-srif/lib/unodestat.py
Normal file
102
contrib/u-srif/lib/unodestat.py
Normal file
@ -0,0 +1,102 @@
|
||||
import time
|
||||
import gdbm
|
||||
import ufido
|
||||
|
||||
class nodestat:
|
||||
""" [[month_id, month_size, month_num, month_time],
|
||||
[week_id, seek_size, week_num, week_time],
|
||||
[day_id, day_size, day_num, day_time],
|
||||
[total_size, total_num, total_time]]
|
||||
"""
|
||||
def __init__(self, dbpath, address):
|
||||
self.addr = address
|
||||
self.key = address.string()
|
||||
self.stat_session_size = 0
|
||||
self.stat_session_num = 0
|
||||
self.stat_session_time = 0
|
||||
self.stat_day_size = 0
|
||||
self.stat_day_num = 0
|
||||
self.stat_day_time = 0
|
||||
self.stat_week_size = 0
|
||||
self.stat_week_num = 0
|
||||
self.stat_week_time = 0
|
||||
self.stat_month_size = 0
|
||||
self.stat_month_num = 0
|
||||
self.stat_month_time = 0
|
||||
self.stat_total_size = 0
|
||||
self.stat_total_num = 0
|
||||
self.stat_total_time = 0
|
||||
self.dbpath = dbpath
|
||||
tt = time.localtime()
|
||||
self.month_id = time.strftime('%Y%m', tt)
|
||||
self.week_id = time.strftime('%Y%W', tt)
|
||||
self.day_id = time.strftime('%Y%j', tt)
|
||||
self.notexist = 0 # Entry for this node doesn't exist yet?
|
||||
|
||||
def upd_stat(self, num, size):
|
||||
self.stat_session_size = self.stat_session_size + size
|
||||
self.stat_session_num = self.stat_session_num + num
|
||||
self.stat_month_size = self.stat_month_size + size
|
||||
self.stat_month_num = self.stat_month_num + num
|
||||
self.stat_week_size = self.stat_week_size + size
|
||||
self.stat_week_num = self.stat_week_num + num
|
||||
self.stat_day_size = self.stat_day_size + size
|
||||
self.stat_day_num = self.stat_day_num + num
|
||||
self.stat_total_size = self.stat_total_size + size
|
||||
self.stat_total_num = self.stat_total_num + num
|
||||
|
||||
def get_stat(self):
|
||||
try:
|
||||
db = gdbm.open(self.dbpath, 'r')
|
||||
except gdbm.error:
|
||||
return 0
|
||||
if not db.has_key(self.key):
|
||||
self.notexist = 1
|
||||
db.close()
|
||||
return 0
|
||||
entry = eval(db[self.key])
|
||||
# Check month statistic
|
||||
if entry[0][0] == self.month_id:
|
||||
self.stat_month_size = entry[0][1]
|
||||
self.stat_month_num = entry[0][2]
|
||||
self.stat_month_time = entry[0][3]
|
||||
# Check week statistic
|
||||
if entry[1][0] == self.week_id:
|
||||
self.stat_week_size = entry[1][1]
|
||||
self.stat_week_num = entry[1][2]
|
||||
self.stat_week_time = entry[1][3]
|
||||
# Check day statistic
|
||||
if entry[2][0] == self.day_id:
|
||||
self.stat_day_size = entry[2][1]
|
||||
self.stat_day_num = entry[2][2]
|
||||
self.stat_day_time = entry[2][3]
|
||||
# Get total statistic
|
||||
self.stat_total_size = entry[3][0]
|
||||
self.stat_total_num = entry[3][1]
|
||||
self.stat_total_time = entry[3][2]
|
||||
db.close()
|
||||
return 0
|
||||
|
||||
def put_stat(self):
|
||||
db = gdbm.open(self.dbpath, 'cf')
|
||||
# Don't handle exceptions
|
||||
entry = [[self.month_id, self.stat_month_size, self.stat_month_num, self.stat_month_time],
|
||||
[self.week_id, self.stat_week_size, self.stat_week_num, self.stat_week_time],
|
||||
[self.day_id, self.stat_day_size, self.stat_day_num, self.stat_day_time],
|
||||
[self.stat_total_size, self.stat_total_num, self.stat_total_time]]
|
||||
db[self.key] = repr(entry)
|
||||
db.close()
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
addr = ufido.address()
|
||||
addr.parse('2:5020/2120')
|
||||
ns = nodestat('./tmp.db', addr)
|
||||
ns.upd_stat(2, 32768)
|
||||
ns.put_stat()
|
||||
addr2 = ufido.address()
|
||||
addr2.parse('2:5020/2120')
|
||||
ns2 = nodestat('./tmp.db', addr2)
|
||||
ns2.get_stat()
|
||||
print ns2.stat_total_num, ns2.stat_total_size
|
||||
|
||||
97
contrib/u-srif/lib/utmpl.py
Normal file
97
contrib/u-srif/lib/utmpl.py
Normal file
@ -0,0 +1,97 @@
|
||||
import string
|
||||
|
||||
class template:
|
||||
def __init__(self):
|
||||
self.local_address = ''
|
||||
self.local_sysop = ''
|
||||
self.local_location = ''
|
||||
self.local_phone = ''
|
||||
self.remote_address = ''
|
||||
self.remote_sysop = ''
|
||||
self.remote_location = ''
|
||||
self.remote_phone = ''
|
||||
self.remote_cid = ''
|
||||
self.limit_size_day = -1
|
||||
self.limit_size_week = -1
|
||||
self.limit_size_month = -1
|
||||
self.sent_size_day = -1
|
||||
self.sent_size_week = -1
|
||||
self.sent_size_month = -1
|
||||
self.sent_size = -1
|
||||
self.conn_speed = -1
|
||||
self.text = None
|
||||
|
||||
def set(self, srif=None, conf=None, nodestat=None):
|
||||
if srif:
|
||||
self.remote_address = srif.aka.string()
|
||||
self.remote_sysop = srif.sysop
|
||||
self.remote_location = srif.site
|
||||
self.remote_cid = srif.callerid
|
||||
self.conn_speed = srif.baud
|
||||
if conf:
|
||||
self.local_address = conf.local_address.string()
|
||||
self.limit_size_day = conf.limit_size_day
|
||||
self.limit_size_week = conf.limit_size_week
|
||||
self.limit_size_month = conf.limit_size_month
|
||||
if nodestat:
|
||||
self.sent_session_size = nodestat.stat_session_size
|
||||
self.sent_session_num = nodestat.stat_session_num
|
||||
self.sent_day_size = nodestat.stat_day_size
|
||||
self.sent_day_num = nodestat.stat_day_num
|
||||
self.sent_week_size = nodestat.stat_week_size
|
||||
self.sent_week_num = nodestat.stat_week_num
|
||||
self.sent_month_size = nodestat.stat_month_size
|
||||
self.sent_month_num = nodestat.stat_month_num
|
||||
self.sent_total_size = nodestat.stat_total_size
|
||||
self.sent_total_num = nodestat.stat_total_num
|
||||
|
||||
def __cmd__(self, str):
|
||||
try:
|
||||
[fmt, arg] = string.split(str, ',', 1)
|
||||
return eval('"' + fmt + '" % self.' + arg)
|
||||
except ValueError:
|
||||
return '@ValueError@'
|
||||
except AttributeError:
|
||||
return '@AttributeError@'
|
||||
|
||||
def process(self, text=None):
|
||||
if text == None:
|
||||
text = self.text
|
||||
if text == None:
|
||||
return None
|
||||
pos = 0
|
||||
while 1:
|
||||
pos = string.find(text, '@', pos)
|
||||
if pos < 0:
|
||||
break
|
||||
end_pos = string.find(text, '@', pos+1)
|
||||
if end_pos < 0:
|
||||
break
|
||||
if end_pos - pos > 1:
|
||||
# Process escaped command
|
||||
replace = self.__cmd__(text[pos+1:end_pos])
|
||||
if replace:
|
||||
text = text[:pos]+replace+text[end_pos+1:]
|
||||
# Fix the current position
|
||||
pos = end_pos + len(replace)-(end_pos-pos+1)
|
||||
else:
|
||||
# Leave text untouched
|
||||
pos = end_pos + 1
|
||||
else:
|
||||
# Replace '@@' by the single '@'
|
||||
text = text[:pos+1]+text[pos+2:]
|
||||
pos = end_pos
|
||||
return text
|
||||
|
||||
def readfile(self, path):
|
||||
try:
|
||||
fp = open(path, 'r')
|
||||
self.text = fp.read()
|
||||
fp.close()
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
test = template()
|
||||
print test.process("'@@'\n'@@'\n'@%d,conn_speed@'\n'@@@'")
|
||||
|
||||
54
contrib/u-srif/lib/uutil.py
Normal file
54
contrib/u-srif/lib/uutil.py
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
import string
|
||||
|
||||
# Header for the files information
|
||||
file_info_header = 'File Size Description\n'\
|
||||
+ '-' * 78
|
||||
|
||||
class ULog:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.fp = open(path, 'a')
|
||||
|
||||
def puts(self, string):
|
||||
fp.puts(strftime('%b %d %H:%M:%S ', gmtime())+string)
|
||||
|
||||
def close(self):
|
||||
fp.close()
|
||||
|
||||
def format_desc(desc, offset, width=78):
|
||||
""" Format file's description
|
||||
"""
|
||||
yield = ''
|
||||
desc = string.expandtabs(desc, 1)
|
||||
for line in string.split(desc, '\n'):
|
||||
line = string.rstrip(line)
|
||||
if line == '':
|
||||
continue
|
||||
pos = 0
|
||||
endpos = width
|
||||
while line[pos:endpos]:
|
||||
if yield:
|
||||
yield = yield + '\n'
|
||||
yield = yield + offset * ' '
|
||||
yield = yield + line[pos:endpos]
|
||||
pos = endpos
|
||||
endpos = endpos + width
|
||||
return yield
|
||||
|
||||
def format_file_info(name, size, desc, line_length=78):
|
||||
""" Format file information to meet human requirements
|
||||
"""
|
||||
if size < 0:
|
||||
yield = '%-20s ' % name + 11 * ' '
|
||||
else:
|
||||
yield = '%-20s %-11d' % (name, size)
|
||||
if desc:
|
||||
offset = len(yield) + 1
|
||||
width = line_length - offset
|
||||
desc = format_desc(desc, offset, width)
|
||||
yield = yield + ' ' + string.lstrip(desc)
|
||||
else:
|
||||
yield = yield + ' Description not available'
|
||||
return yield
|
||||
|
||||
50
contrib/u-srif/u-srif-index.py
Normal file
50
contrib/u-srif/u-srif-index.py
Normal file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import posix
|
||||
import os
|
||||
import libconf
|
||||
import libfbase
|
||||
|
||||
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
|
||||
# Read configuration
|
||||
Conf = libconf.config(USRIF_CONFIG)
|
||||
|
||||
# Open files index for writing
|
||||
FBase = libfbase.filebase(Conf.spool_dir)
|
||||
FBase.open('cwf')
|
||||
|
||||
file = libfbase.file()
|
||||
|
||||
# Process aliases from 'alias-list-file'
|
||||
for alias in Conf.read_alias_list():
|
||||
print 'Processing alias "%s": %s' % (alias.name, alias.filename)
|
||||
file_desc = libfbase.get_file_desc(alias.filename)
|
||||
file.set(alias.filename, name = alias.name, desc = file_desc)
|
||||
file.stat()
|
||||
FBase.put(file)
|
||||
|
||||
# Process dirs from 'dir-list-file'
|
||||
for dir in Conf.read_dir_list():
|
||||
area_desc = libfbase.get_area_desc(dir)
|
||||
print 'Processing: %s (%s)' % (dir, area_desc)
|
||||
files_list = posix.listdir(dir)
|
||||
for file_name in files_list:
|
||||
full_name = os.path.join(dir, file_name)
|
||||
if os.path.isfile(full_name):
|
||||
file_desc = libfbase.get_file_desc(full_name)
|
||||
file.set(full_name, area = area_desc, desc = file_desc)
|
||||
file.stat()
|
||||
FBase.put(file)
|
||||
|
||||
# Purge files index
|
||||
#print 'Purging removed files from files index'
|
||||
#FBase.clean()
|
||||
|
||||
FBase.close()
|
||||
sys.exit(0)
|
||||
|
||||
35
contrib/u-srif/u-srif-lookup.py
Normal file
35
contrib/u-srif/u-srif-lookup.py
Normal file
@ -0,0 +1,35 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
import sys
|
||||
|
||||
# Our own libraries
|
||||
sys.path.append('./lib')
|
||||
import uconfig
|
||||
import udbase
|
||||
from uutil import *
|
||||
|
||||
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
if len(sys.argv) < 2:
|
||||
print 'usage:', sys.argv[0], '<[file] [file] ..>'
|
||||
sys.exit(1)
|
||||
|
||||
# Read configuration
|
||||
Conf = uconfig.Config(USRIF_CONFIG)
|
||||
|
||||
# Lookup files in the database
|
||||
FBase = udbase.filebase(Conf.spool_dir)
|
||||
FBase.open('r')
|
||||
yield = FBase.get_all(sys.argv[1:])
|
||||
FBase.close()
|
||||
|
||||
# Pretty printing
|
||||
print file_info_header
|
||||
for file in yield:
|
||||
file.stat()
|
||||
print format_file_info(file.name, file.size, file.desc)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
182
contrib/u-srif/u-srif.py
Normal file
182
contrib/u-srif/u-srif.py
Normal file
@ -0,0 +1,182 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
import string
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Our own libraries
|
||||
sys.path.append('./lib')
|
||||
import uconfig
|
||||
import udbase
|
||||
import ufido
|
||||
import utmpl
|
||||
import unodestat
|
||||
from uutil import *
|
||||
|
||||
USRIF_CONFIG = '/usr/local/etc/u-srif/u-srif.conf'
|
||||
|
||||
class freq_report(ufido.message):
|
||||
def write_packet(self, pktname):
|
||||
self.packet.addr_orig = self.addr_orig
|
||||
self.packet.addr_dest = self.addr_dest
|
||||
self.packet.write(pktname)
|
||||
|
||||
def add_file(self, name, size, desc):
|
||||
text = format_file_info(name, size, desc)
|
||||
self.append_text(text)
|
||||
|
||||
def __init__(self):
|
||||
ufido.message.__init__(self)
|
||||
self.packet = ufido.packet()
|
||||
self.packet.add_message(self)
|
||||
|
||||
class srif_file:
|
||||
def read_req_list(self):
|
||||
yield = []
|
||||
fp = open(self.requestlist, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
yield.append(line)
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
return yield
|
||||
|
||||
def write_resp_list(self, list):
|
||||
fp = open(self.responselist, 'w')
|
||||
for file in list:
|
||||
fp.write('+' + file + '\n')
|
||||
fp.close()
|
||||
|
||||
def read(self, name):
|
||||
fp = open(name, 'r')
|
||||
line = fp.readline()
|
||||
while line:
|
||||
line = string.strip(line)
|
||||
args = string.split(line, None, 1)
|
||||
if len(args) == 2:
|
||||
if string.lower(args[0]) == 'sysop':
|
||||
self.sysop = args[1]
|
||||
if string.lower(args[0]) == 'aka':
|
||||
self.aka.parse(args[1])
|
||||
elif string.lower(args[0]) == 'baud':
|
||||
self.baud = args[1]
|
||||
elif string.lower(args[0]) == 'requestlist':
|
||||
self.requestlist = args[1]
|
||||
elif string.lower(args[0]) == 'responselist':
|
||||
self.responselist = args[1]
|
||||
elif string.lower(args[0]) == 'remotestatus':
|
||||
self.remotestatus = args[1]
|
||||
elif string.lower(args[0]) == 'systemstatus':
|
||||
self.systemstatus = args[1]
|
||||
elif string.lower(args[0]) == 'site':
|
||||
self.site = args[1]
|
||||
elif string.lower(args[0]) == 'callerid':
|
||||
self.callerid = args[1]
|
||||
elif string.lower(args[0]) == 'password':
|
||||
self.password = args[1]
|
||||
else:
|
||||
print "skipping keyword", args[0], "in SRIF"
|
||||
line = fp.readline()
|
||||
fp.close()
|
||||
|
||||
def __init__(self, name):
|
||||
self.sysop = ''
|
||||
self.aka = ufido.address()
|
||||
self.baud = 0
|
||||
self.requestlist = ''
|
||||
self.responselist = ''
|
||||
self.remotestatus = ''
|
||||
self.systemstatus = ''
|
||||
self.site = ''
|
||||
self.callerid = ''
|
||||
self.password = ''
|
||||
self.read(name)
|
||||
|
||||
def remote_addr(self):
|
||||
return self.aka
|
||||
|
||||
def isprotected(self):
|
||||
if string.lower(self.remotestatus) == 'protected':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def islisted(self):
|
||||
if string.lower(self.systemstatus) == 'listed':
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def append_new_file(fileslist, file):
|
||||
TotalFiles = TotalFiles + 1
|
||||
TotalSize = TotalSize + file.size
|
||||
fileslist.append(file.fullname)
|
||||
|
||||
##############################
|
||||
# The main program starts here
|
||||
|
||||
# Global variables
|
||||
yield_list = []
|
||||
|
||||
if len(sys.argv) <> 2:
|
||||
print 'usage: u-srif <srif file name>'
|
||||
sys.exit(1)
|
||||
|
||||
# Read configuration
|
||||
conf = uconfig.Config(USRIF_CONFIG)
|
||||
# Read SRIF files
|
||||
srif = srif_file(sys.argv[1])
|
||||
# Read node's statistic
|
||||
nodestat = unodestat.nodestat(conf.stat_dbase, srif.aka)
|
||||
nodestat.get_stat()
|
||||
|
||||
# Lookup requested files in the our database
|
||||
FBase = udbase.filebase(conf.spool_dir)
|
||||
FBase.open('r')
|
||||
yield = FBase.get_all(srif.read_req_list())
|
||||
FBase.close()
|
||||
|
||||
# Prepare found files for sending
|
||||
for file in yield:
|
||||
if not file.fake:
|
||||
file.stat()
|
||||
nodestat.upd_stat(1, file.size)
|
||||
yield_list.append(file.fullname)
|
||||
|
||||
# Store node's statistic
|
||||
nodestat.put_stat()
|
||||
|
||||
# Send FREQ report?
|
||||
if conf.send_report:
|
||||
# Prepare templates object
|
||||
tmpl = utmpl.template()
|
||||
tmpl.set(srif=srif, conf=conf, nodestat=nodestat)
|
||||
# Setup report object
|
||||
report = freq_report()
|
||||
report.newmsg(conf.local_address, conf.report_from, \
|
||||
srif.aka, srif.sysop, conf.report_subj)
|
||||
report.append_line('')
|
||||
# Append header
|
||||
tmpl.readfile(conf.report_header)
|
||||
text = tmpl.process()
|
||||
if text:
|
||||
report.append_text(text)
|
||||
# Append per files statistic
|
||||
for file in yield:
|
||||
report.add_file(file.name, file.size, file.desc)
|
||||
# Append footer
|
||||
tmpl.readfile(conf.report_footer)
|
||||
text = tmpl.process()
|
||||
if text:
|
||||
report.append_text(text)
|
||||
# Add empty line to the report
|
||||
report.append_line('')
|
||||
# Create netmail packet with the FREQ report
|
||||
pktname = '/var/tmp/12345678.pkt' # XXX
|
||||
report.write_packet(pktname)
|
||||
# Add packet file to the response files list
|
||||
yield_list.append(pktname)
|
||||
|
||||
# Dump reponse list
|
||||
srif.write_resp_list(yield_list)
|
||||
sys.exit(0)
|
||||
|
||||
242
debian/Makefile
vendored
Normal file
242
debian/Makefile
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
# Makefile.in generated by automake 1.7.9 from Makefile.am.
|
||||
# ../debian/Makefile. Generated from Makefile.in by configure.
|
||||
|
||||
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
# Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = .
|
||||
top_srcdir = ../..
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = /usr/bin/install -c
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = i686-pc-linux-gnu
|
||||
host_triplet = i686-pc-linux-gnu
|
||||
target_triplet = i686-pc-linux-gnu
|
||||
CC = gcc
|
||||
CFLAGS = -g -O2
|
||||
CPP = gcc -E
|
||||
CPPFLAGS =
|
||||
DEFS = -DHAVE_CONFIG_H
|
||||
ECHO_C =
|
||||
ECHO_N = -n
|
||||
ECHO_T =
|
||||
EGREP = grep -E
|
||||
EXEEXT =
|
||||
GROUP = news
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_SCRIPT = ${INSTALL}
|
||||
LDFLAGS =
|
||||
LIBOBJS =
|
||||
LIBS =
|
||||
LTLIBOBJS =
|
||||
OBJEXT = o
|
||||
OWNER = uucp
|
||||
PACKAGE_BUGREPORT = ugenk@tut.by
|
||||
PACKAGE_NAME = bforce
|
||||
PACKAGE_STRING = bforce 0.22.8.ugenk2
|
||||
PACKAGE_TARNAME = bforce
|
||||
PACKAGE_VERSION = 0.22.8.ugenk2
|
||||
PATH_SEPARATOR = :
|
||||
SHELL = /bin/sh
|
||||
YACC = bison -y
|
||||
ac_ct_CC = gcc
|
||||
bindir = ${exec_prefix}/bin
|
||||
build = i686-pc-linux-gnu
|
||||
build_alias =
|
||||
build_cpu = i686
|
||||
build_os = linux-gnu
|
||||
build_vendor = pc
|
||||
datadir = ${prefix}/share
|
||||
exec_prefix = ${prefix}
|
||||
host = i686-pc-linux-gnu
|
||||
host_alias =
|
||||
host_cpu = i686
|
||||
host_os = linux-gnu
|
||||
host_vendor = pc
|
||||
includedir = ${prefix}/include
|
||||
infodir = ${prefix}/info
|
||||
libdir = ${exec_prefix}/lib
|
||||
libexecdir = ${exec_prefix}/libexec
|
||||
localstatedir = ${prefix}/var
|
||||
mandir = ${prefix}/man
|
||||
oldincludedir = /usr/include
|
||||
prefix = /usr/local
|
||||
program_transform_name = s,x,x,
|
||||
sbindir = ${exec_prefix}/sbin
|
||||
sharedstatedir = ${prefix}/com
|
||||
sysconfdir = ${prefix}/etc
|
||||
target = i686-pc-linux-gnu
|
||||
target_alias =
|
||||
target_cpu = i686
|
||||
target_os = linux-gnu
|
||||
target_vendor = pc
|
||||
|
||||
# $Id$
|
||||
EXTRA_DIST = copyright changelog rules conffiles \
|
||||
control dirs init.d
|
||||
|
||||
subdir = ../debian
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_SOURCES =
|
||||
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu ../debian/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
|
||||
uninstall-info-am:
|
||||
tags: TAGS
|
||||
TAGS:
|
||||
|
||||
ctags: CTAGS
|
||||
CTAGS:
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
top_distdir = ..
|
||||
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkinstalldirs) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile
|
||||
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic distclean \
|
||||
distclean-generic distdir dvi dvi-am info info-am install \
|
||||
install-am install-data install-data-am install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
|
||||
uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
3
debian/Makefile.am
vendored
Normal file
3
debian/Makefile.am
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# $Id$
|
||||
EXTRA_DIST = copyright changelog rules conffiles \
|
||||
control dirs init.d
|
||||
242
debian/Makefile.in
vendored
Normal file
242
debian/Makefile.in
vendored
Normal file
@ -0,0 +1,242 @@
|
||||
# Makefile.in generated by automake 1.7.9 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
# Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
target_triplet = @target@
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
DEFS = @DEFS@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GROUP = @GROUP@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
OBJEXT = @OBJEXT@
|
||||
OWNER = @OWNER@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
SHELL = @SHELL@
|
||||
YACC = @YACC@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target = @target@
|
||||
target_alias = @target_alias@
|
||||
target_cpu = @target_cpu@
|
||||
target_os = @target_os@
|
||||
target_vendor = @target_vendor@
|
||||
|
||||
# $Id$
|
||||
EXTRA_DIST = copyright changelog rules conffiles \
|
||||
control dirs init.d
|
||||
|
||||
subdir = ../debian
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_SOURCES =
|
||||
DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu ../debian/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
|
||||
uninstall-info-am:
|
||||
tags: TAGS
|
||||
TAGS:
|
||||
|
||||
ctags: CTAGS
|
||||
CTAGS:
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
top_distdir = ..
|
||||
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkinstalldirs) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile
|
||||
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic distclean \
|
||||
distclean-generic distdir dvi dvi-am info info-am install \
|
||||
install-am install-data install-data-am install-exec \
|
||||
install-exec-am install-info install-info-am install-man \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \
|
||||
uninstall-info-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
6
debian/README.Debian
vendored
Normal file
6
debian/README.Debian
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
bforce for Debian
|
||||
-----------------
|
||||
|
||||
See CHANGES.ugenk
|
||||
|
||||
-- Evgeniy Kozhuhovskiy <e.kozhuhovskiy>, Sun, 4 Oct 2004 11:14:15 +0200
|
||||
25
debian/bfindex.1
vendored
Normal file
25
debian/bfindex.1
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
.TH BFINDEX "1" "April 2003"
|
||||
.SH NAME
|
||||
bfindex \- nodelist compiler for bforce
|
||||
.SH SYNOPSYS
|
||||
\fBbfindex [-fh]\fR
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBbfindex\fP is a nodelist compiler for BinkleyForce FTN mailer.
|
||||
.SH OPTIONS
|
||||
\fB\-f\fR
|
||||
force nodelist compiling
|
||||
.P
|
||||
\fB-h\fR
|
||||
show help message
|
||||
.SH SEE ALSO
|
||||
bforce(1),bfstat(1),nlookup(1)
|
||||
.SH AUTHOR
|
||||
Bforce was written by Alexander Belkin <adb@newmail.ru>, 2:5020/2120
|
||||
.P
|
||||
This manual page was written by Zhenja Kaluta <trinfo@mail.ru>
|
||||
|
||||
This is free documentation; 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.
|
||||
68
debian/bforce.1
vendored
Normal file
68
debian/bforce.1
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
.TH BFORCE "1" "April 2003"
|
||||
.SH NAME
|
||||
Bforce \- FTN mailer
|
||||
.SH SYNOPSYS
|
||||
\fBbforce [-fmh] [-I\fIinclude\fB] [-n\fIphone\fB]\
|
||||
[-l\fIline_number\fB] [-a\fIip_address\fB] \
|
||||
[-S\fIconnect\fB] [-p\fIdevice\fB] \fP<\fInode\fP>
|
||||
.P
|
||||
\fBbforce [-ih] [-I\fIinclude\fB] [-S\fIconnect\fB] \
|
||||
\fI<tsync|yoohoo|emsi|binkp|auto>
|
||||
.P
|
||||
\fBbforce [-dh] [-C\fIconfig\fB] [-I\fIinclude\fB]
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBbforce\fP BinkleyForce is a simple ifcico like FTN mailer. It can
|
||||
works via TCP/IP as well as on modem links.
|
||||
.SH OPTIONS
|
||||
\fB\-d\fR
|
||||
run as daemon
|
||||
.P
|
||||
\fB\-q\fR
|
||||
terminate daemon
|
||||
.P
|
||||
\fB\-i\fR
|
||||
run from inetd (for slave mode only)
|
||||
.P
|
||||
\fB\-f\fR
|
||||
ignore system's work time
|
||||
.P
|
||||
\fB\-o\fR
|
||||
starts outgoing session on stdin/stdout
|
||||
.P
|
||||
\fB-C \fIconfig\fR
|
||||
main config file name. Default is ("/etc/bforce/bforce.conf")
|
||||
.P
|
||||
\fB-I \fIconfig\fR
|
||||
additional config file name
|
||||
.P
|
||||
\fB-n \fIphone\fR
|
||||
override phone number
|
||||
.P
|
||||
\fB-l \fIline_number\fR
|
||||
call on this hidden line (default is 0)
|
||||
.P
|
||||
\fB-a \fIip_address\fR
|
||||
override internet address
|
||||
.P
|
||||
\fB-S \fIconnect_str\fR
|
||||
connect string (for slave mode only)
|
||||
.P
|
||||
\fB-p \fIport\fR
|
||||
override modem port (must be defined in config)
|
||||
.P
|
||||
\fB-h\fR
|
||||
show help message
|
||||
.SH SEE ALSO
|
||||
bfindex(1),bfstat(1),nlookup(1)
|
||||
.SH AUTHOR
|
||||
Bforce was written by Alexander Belkin <adb@newmail.ru>, 2:5020/2120
|
||||
.P
|
||||
This manual page was written by Zhenja Kaluta <trinfo@mail.ru>
|
||||
.P
|
||||
Revision 2 by Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com>
|
||||
|
||||
This is free documentation; 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.
|
||||
10
debian/bforce.postinst.debhelper
vendored
Normal file
10
debian/bforce.postinst.debhelper
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Automatically added by dh_installinit
|
||||
if [ -x "/etc/init.d/bforce" ]; then
|
||||
update-rc.d bforce defaults >/dev/null
|
||||
if [ -x /usr/sbin/invoke-rc.d ]; then
|
||||
invoke-rc.d bforce start || exit 0
|
||||
else
|
||||
/etc/init.d/bforce start || exit 0
|
||||
fi
|
||||
fi
|
||||
# End automatically added section
|
||||
5
debian/bforce.postrm.debhelper
vendored
Normal file
5
debian/bforce.postrm.debhelper
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Automatically added by dh_installinit
|
||||
if [ "$1" = "purge" ] ; then
|
||||
update-rc.d bforce remove >/dev/null || exit 0
|
||||
fi
|
||||
# End automatically added section
|
||||
9
debian/bforce.prerm.debhelper
vendored
Normal file
9
debian/bforce.prerm.debhelper
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# Automatically added by dh_installinit
|
||||
if [ -x "/etc/init.d/bforce" ]; then
|
||||
if [ -x /usr/sbin/invoke-rc.d ] ; then
|
||||
invoke-rc.d bforce stop || exit 0
|
||||
else
|
||||
/etc/init.d/bforce stop || exit 0
|
||||
fi
|
||||
fi
|
||||
# End automatically added section
|
||||
1
debian/bforce.substvars
vendored
Normal file
1
debian/bforce.substvars
vendored
Normal file
@ -0,0 +1 @@
|
||||
shlibs:Depends=libc6 (>= 2.3.2.ds1-4)
|
||||
47
debian/bfstat.1
vendored
Normal file
47
debian/bfstat.1
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
.TH BINDEX "1" "April 2003"
|
||||
.SH NAME
|
||||
bfstat \- binkley style outbound statistic
|
||||
.SH SYNOPSYS
|
||||
\fBbfstat [-afhprst] [-n \fInumber\fB]\fR
|
||||
.SH DESCRIPTION
|
||||
\fBbfstat\fP help you to see your outbound statistic in human readable
|
||||
form.
|
||||
.SH OPTIONS
|
||||
\fB\-a\fR
|
||||
sort by FTN address (default)
|
||||
.P
|
||||
\fB\-c\fR
|
||||
print incoming/outgoing calls statistic
|
||||
.P
|
||||
\fB\-f\fR
|
||||
disable queue sorting
|
||||
.P
|
||||
\fB\-n \fInumber\fR
|
||||
don't print more than <number> systems
|
||||
.P
|
||||
\fB\-p\fR
|
||||
print sizes in human readable format
|
||||
.P
|
||||
\fB\-r\fR
|
||||
reverse order while sorting
|
||||
.P
|
||||
\fB\-s\fR
|
||||
sort by total files size
|
||||
.P
|
||||
\fB\-t\fR
|
||||
disable total sizes printing
|
||||
.P
|
||||
\fB-h\fR
|
||||
show help message
|
||||
.SH SEE ALSO
|
||||
bforce(1),bindex(1),nlookup(1)
|
||||
.SH AUTHOR
|
||||
Bforce was written by Alexander Belkin <adb@newmail.ru>, 2:5020/2120
|
||||
.P
|
||||
This manual page was written by Zhenja Kaluta <trinfo@mail.ru>
|
||||
.P
|
||||
Revision 2 by Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com>
|
||||
This is free documentation; 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.
|
||||
27
debian/changelog
vendored
Normal file
27
debian/changelog
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
bforce (0.22.8.ugenk3-1) unstable; urgency=low
|
||||
|
||||
* New upstream release
|
||||
* revision of manual pages
|
||||
|
||||
-- Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com> Tue, 16 Nov 2004 08:42:04 +0200
|
||||
|
||||
bforce (0.22.8.ugenk2-2) unstable; urgency=low
|
||||
|
||||
* fixed some bugs in configfiles
|
||||
* sorry, bforce compiled without syslog support (maybe in the next version?)
|
||||
|
||||
-- Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com> Tue, 2 Nov 2004 10:44:03 +0200
|
||||
|
||||
bforce (0.22.8.ugenk2-1) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
* Really working rules ;)
|
||||
|
||||
-- Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com> Sun, 31 Oct 2004 12:04:10 +0200
|
||||
|
||||
bforce (0.22.8.ugenk1-1) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Evgeniy Kozhuhovskiy <ugenk@tut.by> Sun, 4 Jul 2004 11:14:15 +0200
|
||||
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
||||
4
|
||||
6
debian/conffiles
vendored
Normal file
6
debian/conffiles
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/etc/bforce/bforce.conf
|
||||
/etc/bforce/bforce.subst
|
||||
/etc/bforce/bforce.passwd
|
||||
/etc/bforce/freq.dirs
|
||||
/etc/bforce/freq.aliases
|
||||
|
||||
18
debian/control
vendored
Normal file
18
debian/control
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
Source: bforce
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com>
|
||||
Build-Depends: debhelper (>> 3.0.0), dpatch (>= 1.11)
|
||||
Standards-Version: 3.5.10
|
||||
|
||||
Package: bforce
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: Binkey Force FTN mailer
|
||||
FTN mailer is a program that transmit files (netmail and echomail)
|
||||
between your FTN node and other.
|
||||
.
|
||||
Bforce can be used to communicate over tcp/ip with binkp protocol or
|
||||
with classic FTN way -- modem links. Bforce is easy to configure and
|
||||
have good support of FTN standards.
|
||||
|
||||
14
debian/copyright
vendored
Normal file
14
debian/copyright
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
This package was debianized by Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com> on
|
||||
Sun, 4 Jul 2004 11:14:15 +0200.
|
||||
|
||||
It was downloaded from http://ugenk.bas-net.by
|
||||
|
||||
Upstream Author(s): Alexander Belkin, 2:5020/1398.11
|
||||
Konstantin Stepanenkov, 2:5030/1251
|
||||
Evgeniy Kozhuhovskiy, 2:450/256
|
||||
|
||||
Copyright:
|
||||
|
||||
All programs are either under the GPL or LGPL. On Debian systems,
|
||||
the complete text of the GPL and LGPL licenses can be found in the
|
||||
/usr/share/common-licenses/GPL and /usr/share/common-licenses/LGPL files.
|
||||
2
debian/default
vendored
Normal file
2
debian/default
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
#
|
||||
RUN="no"
|
||||
13
debian/dirs
vendored
Normal file
13
debian/dirs
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
usr/bin
|
||||
etc/bforce
|
||||
etc/default
|
||||
etc/default/bforce
|
||||
var/spool/fido/out
|
||||
var/spool/fido/in
|
||||
var/spool/fido/pin
|
||||
var/spool/fido/ndl
|
||||
var/spool/fido/fbox
|
||||
var/spool/bforce
|
||||
var/log/bforce
|
||||
var/run/bforce
|
||||
|
||||
9
debian/docs
vendored
Normal file
9
debian/docs
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
README
|
||||
README.kst
|
||||
README.ugenk
|
||||
TODO
|
||||
CHANGES
|
||||
CHANGES.kst
|
||||
CHANGES.ugenk
|
||||
INSTALL
|
||||
INSTALL.ru
|
||||
61
debian/init.d
vendored
Normal file
61
debian/init.d
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# skeleton example file to build /etc/init.d/ scripts.
|
||||
# This file should be used to construct scripts for /etc/init.d.
|
||||
#
|
||||
# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
|
||||
# Modified for Debian
|
||||
# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
|
||||
#
|
||||
# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DAEMON=/usr/sbin/bforce
|
||||
NAME=bforce
|
||||
DESC=bforce
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
# Include bforce defaults if available
|
||||
if [ -f /etc/default/bforce ] ; then
|
||||
. /etc/default/bforce
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting $DESC: "
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
|
||||
--exec $DAEMON -- $DAEMON_OPTS
|
||||
echo "$NAME."
|
||||
;;
|
||||
stop)
|
||||
echo -n "Stopping $DESC: "
|
||||
start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid \
|
||||
--exec $DAEMON
|
||||
echo "$NAME."
|
||||
;;
|
||||
restart|force-reload)
|
||||
echo -n "Restarting $DESC: "
|
||||
start-stop-daemon --stop --quiet --pidfile \
|
||||
/var/run/$NAME.pid --exec $DAEMON
|
||||
sleep 1
|
||||
start-stop-daemon --start --quiet --pidfile \
|
||||
/var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
|
||||
echo "$NAME."
|
||||
;;
|
||||
*)
|
||||
N=/etc/init.d/$NAME
|
||||
echo "Usage: $N {start|stop|restart|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
30
debian/nlookup.1
vendored
Normal file
30
debian/nlookup.1
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
.TH NLOOKUP "1" "April 2003"
|
||||
.SH NAME
|
||||
Bnlookup \- Nodelist search tool for bforce
|
||||
.SH SYNOPSYS
|
||||
\fBnlookup [-rh]\fR
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBnlookup\fP is a nodelist search tool for BinkleyForce FTN mailer.
|
||||
.SH OPTIONS
|
||||
\fB\-r\fR
|
||||
show nodelist string
|
||||
.P
|
||||
\fB\-m\fR
|
||||
show sysops e-mail (see FSP-1004.001 - p2)
|
||||
.P
|
||||
\fB-h\fR
|
||||
show help message
|
||||
.SH SEE ALSO
|
||||
bforce(1),bfstat(1),nlookup(1)
|
||||
.SH AUTHOR
|
||||
Bforce was written by Alexander Belkin <adb@newmail.ru>, 2:5020/2120
|
||||
.P
|
||||
This manual page was written by Zhenja Kaluta <trinfo@mail.ru>
|
||||
.P
|
||||
Revision 2 by Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com>
|
||||
|
||||
This is free documentation; 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.
|
||||
36
debian/outman.1
vendored
Normal file
36
debian/outman.1
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
.TH OUTMAN "1" "November 2004"
|
||||
.SH NAME
|
||||
outman \- creates polls, file requests and attach files in aso and bso
|
||||
.SH SYNOPSIS
|
||||
.B outman
|
||||
\fI<\fR[\fIpoll|freq|send\fR]\fI> \fR[\fIoptions\fR] \fI<address> \fR[\fIfiles\fR]
|
||||
.SH DESCRIPTION
|
||||
.SS "options:"
|
||||
.TP
|
||||
\fB\-hold\fR
|
||||
set hold flavor
|
||||
.TP
|
||||
\fB\-normal\fR
|
||||
set normal flavor (default)
|
||||
.TP
|
||||
\fB\-crash\fR
|
||||
set crash flavor
|
||||
.TP
|
||||
\fB\-kill\fR
|
||||
kill files after send
|
||||
.HP
|
||||
\fB\-truncate\fR truncate files after send
|
||||
.PP
|
||||
Mail bug reports to <e.kozhuhovskiy@gmail.com>
|
||||
.SH "SEE ALSO"
|
||||
bfindex(1), bfstat(1), nlookup(1), bforce(1)
|
||||
.SH AUTHOR
|
||||
Bforce was written by Alexander Belkin <adb@newmail.ru>, 2:5020/2120
|
||||
.P
|
||||
This manual page was written by Evgeniy Kozhuhovskiy <e.kozhuhovskiy@gmail.com>
|
||||
|
||||
This is free documentation; 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.
|
||||
|
||||
57
debian/postinst
vendored
Normal file
57
debian/postinst
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
#! /bin/sh
|
||||
# postinst script for bforce
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
#
|
||||
# quoting from the policy:
|
||||
# Any necessary prompting should almost always be confined to the
|
||||
# post-installation script, and should be protected with a conditional
|
||||
# so that unnecessary prompting doesn't happen if a package's
|
||||
# installation fails and the `postinst' is called with `abort-upgrade',
|
||||
# `abort-remove' or `abort-deconfigure'.
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
|
||||
if ! grep -s news /etc/group >/dev/null 2>&1; then
|
||||
addgroup --system news
|
||||
fi
|
||||
|
||||
if ! id uucp >/dev/null 2>&1; then
|
||||
adduser --system --disabled-password uucp
|
||||
chsh -s /bin/sh uucp
|
||||
adduser uucp dialout
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
38
debian/postrm
vendored
Normal file
38
debian/postrm
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
#! /bin/sh
|
||||
# postrm script for bforce
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <r>overwrit>r> <new-version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
44
debian/preinst
vendored
Normal file
44
debian/preinst
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
#! /bin/sh
|
||||
# preinst script for bforce
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
#
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
# if [ "$1" = "upgrade" ]
|
||||
# then
|
||||
# start-stop-daemon --stop --quiet --oknodo \
|
||||
# --pidfile /var/run/bforce.pid \
|
||||
# --exec /usr/sbin/bforce 2>/dev/null || true
|
||||
# fi
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
39
debian/prerm
vendored
Normal file
39
debian/prerm
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#! /bin/sh
|
||||
# prerm script for bforce
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
# install-info --quiet --remove /usr/info/bforce.info.gz
|
||||
;;
|
||||
failed-upgrade)
|
||||
;;
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
111
debian/rules
vendored
Executable file
111
debian/rules
vendored
Executable file
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/make -f
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# GNU copyright 1997 to 1999 by Joey Hess.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
# This is the debhelper compatibility version to use.
|
||||
export DH_COMPAT=3
|
||||
|
||||
|
||||
PACKAGE = bforce
|
||||
|
||||
|
||||
|
||||
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS += -g
|
||||
endif
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
INSTALL_PROGRAM += -s
|
||||
endif
|
||||
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
# Add here commands to configure the package.
|
||||
# cat $(CURDIR)/source/Makefile.in | sed 's/\(^INSTALL_.*\)-o \$${OWNER} -g \$${GROUP}/\1/' > \
|
||||
# $(CURDIR)/source/Makefile.in.new
|
||||
# mv $(CURDIR)/source/Makefile.in.new $(CURDIR)/source/Makefile.in
|
||||
cd source; ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --sysconfdir=/etc/bforce -with-user=uucp --with-group=news
|
||||
touch configure-stamp
|
||||
|
||||
|
||||
build: build-stamp
|
||||
|
||||
build-stamp: configure-stamp
|
||||
dh_testdir
|
||||
|
||||
# Add here commands to compile the package.
|
||||
$(MAKE) -C source 2>/dev/null
|
||||
# /usr/bin/docbook-to-man debian/bforce.sgml > bforce.1
|
||||
|
||||
touch build-stamp
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp configure-stamp
|
||||
|
||||
# Add here commands to clean up after the build process.
|
||||
-$(MAKE) -C source clean
|
||||
dh_clean
|
||||
rm -f source/config.cache source/include/config.h source/config.log\
|
||||
source/config.status source/Makefile
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
# Add here commands to install the package into debian/bforce.
|
||||
# $(MAKE) -C source install DESTDIR=$(CURDIR)/debian/bforce/
|
||||
# install $(CURDIR)/debian/default $(CURDIR)/debian/bforce/etc/default/bforce/
|
||||
/usr/bin/install -c -o uucp -g news source/bin/bforce $(CURDIR)/debian/bforce/usr/bin/bforce
|
||||
/usr/bin/install -c -o uucp -g news source/bin/bfindex $(CURDIR)/debian/bforce/usr/bin/bfindex
|
||||
/usr/bin/install -c -o uucp -g news source/bin/bfstat $(CURDIR)/debian/bforce/usr/bin/bfstat
|
||||
/usr/bin/install -c -o uucp -g news source/bin/nlookup $(CURDIR)/debian/bforce/usr/bin/nlookup
|
||||
/usr/bin/install -c -o uucp -g news contrib/outman $(CURDIR)/debian/bforce/usr/bin/outman
|
||||
/usr/bin/install -c -m 644 -o uucp -g news examples/bforce.conf $(CURDIR)/debian/bforce/etc/bforce/bforce.conf
|
||||
/usr/bin/install -c -m 644 -o uucp -g news examples/bforce.subst $(CURDIR)/debian/bforce/etc/bforce/bforce.subst
|
||||
/usr/bin/install -c -m 644 -o uucp -g news examples/bforce.passwd $(CURDIR)/debian/bforce/etc/bforce/bforce.passwd
|
||||
/usr/bin/install -c -m 644 -o uucp -g news examples/freq.aliases $(CURDIR)/debian/bforce/etc/bforce/freq.aliases
|
||||
/usr/bin/install -c -m 644 -o uucp -g news examples/freq.dirs $(CURDIR)/debian/bforce/etc/bforce/freq.dirs
|
||||
|
||||
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: build install
|
||||
# We have nothing to do by default.
|
||||
|
||||
# Build architecture-dependent files here.
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
# dh_installdebconf
|
||||
dh_installdocs -X.cvsignore
|
||||
dh_installexamples examples/*
|
||||
# dh_installlogrotate
|
||||
dh_installinit
|
||||
# dh_installcron
|
||||
dh_installman $(CURDIR)/debian/bfindex.1 $(CURDIR)/debian/bforce.1 \
|
||||
$(CURDIR)/debian/bfstat.1 $(CURDIR)/debian/nlookup.1
|
||||
# dh_installinfo
|
||||
dh_installchangelogs CHANGES
|
||||
dh_link
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
chown -R uucp:news $(CURDIR)/debian/bforce/etc/bforce
|
||||
chown -R uucp:news $(CURDIR)/debian/bforce/var/spool/fido $(CURDIR)/debian/bforce/var/spool/bforce
|
||||
chown -R uucp:news $(CURDIR)/debian/bforce/var/log/bforce $(CURDIR)/debian/bforce/var/run/bforce
|
||||
# dh_makeshlibs
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
96
debian/rules-1
vendored
Executable file
96
debian/rules-1
vendored
Executable file
@ -0,0 +1,96 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
export DH_VERBOSE=1
|
||||
|
||||
# This is the debhelper compatibility version to use.
|
||||
export DH_COMPAT=3
|
||||
|
||||
PACKAGE = bforce
|
||||
|
||||
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
|
||||
CFLAGS += -g
|
||||
endif
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
INSTALL_PROGRAM += -s
|
||||
endif
|
||||
|
||||
configure: #configure-stamp
|
||||
|
||||
#configure-stamp:
|
||||
dh_testdir
|
||||
# Add here commands to configure the package.
|
||||
# cat $(CURDIR)/source/Makefile.in | sed 's/\(^INSTALL_.*\)-o \$${OWNER} -g \$${GROUP}/\1/' > \
|
||||
# $(CURDIR)/source/Makefile.in.new
|
||||
# mv $(CURDIR)/source/Makefile.in.new $(CURDIR)/source/Makefile.in
|
||||
cd source; ./configure --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --sysconfdir=/etc/bforce --with-owner=uucp --with-group=news
|
||||
touch configure-stamp
|
||||
|
||||
|
||||
build: build-stamp
|
||||
|
||||
build-stamp: configure-stamp
|
||||
dh_testdir
|
||||
|
||||
# Add here commands to compile the package.
|
||||
$(MAKE) -C source
|
||||
# /usr/bin/docbook-to-man debian/bforce.sgml > bforce.1
|
||||
|
||||
touch build-stamp
|
||||
|
||||
#clean: unpatch
|
||||
# dh_testdir
|
||||
# dh_testroot
|
||||
# rm -f build-stamp configure-stamp
|
||||
#
|
||||
# # Add here commands to clean up after the build process.
|
||||
# -$(MAKE) -C source clean
|
||||
# dh_clean
|
||||
# rm -f source/config.cache source/include/config.h source/config.log\
|
||||
# source/config.status source/Makefile
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
# dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
# Add here commands to install the package into debian/bforce.
|
||||
$(MAKE) -C source install DESTDIR=$(CURDIR)/debian/bforce
|
||||
# install $(CURDIR)/debian/default $(CURDIR)/debian/bforce/etc/default/bforce
|
||||
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: configure build install
|
||||
# We have nothing to do by default.
|
||||
|
||||
# Build architecture-dependent files here.
|
||||
binary-arch: configure build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
# dh_installdebconf
|
||||
dh_installdocs -X.cvsignore
|
||||
dh_installexamples examples/*
|
||||
# dh_installlogrotate
|
||||
dh_installinit
|
||||
# dh_installcron
|
||||
dh_installman $(CURDIR)/debian/bfindex.1 $(CURDIR)/debian/bforce.1 \
|
||||
$(CURDIR)/debian/bfstat.1 $(CURDIR)/debian/nlookup.1
|
||||
# dh_installinfo
|
||||
dh_installchangelogs CHANGES CHANGES.kst CHANGES.ugenk
|
||||
dh_link
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
chown -R uucp:news $(CURDIR)/debian/bforce/etc/bforce
|
||||
chown -R uucp:news $(CURDIR)/debian/bforce/var/spool/fido $(CURDIR)/debian/bforce/var/spool/bforce
|
||||
chown -R uucp:news $(CURDIR)/debian/bforce/var/log/bforce $(CURDIR)/debian/bforce/var/run/bforce
|
||||
# dh_makeshlibs
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
567
examples/bforce.conf
Normal file
567
examples/bforce.conf
Normal file
@ -0,0 +1,567 @@
|
||||
##
|
||||
## This is an example binkleyforce configuration file
|
||||
##
|
||||
## Configuration line format:
|
||||
## <Keyword> [(<expression>)] <Value>
|
||||
##
|
||||
## For all addresses masks ``2:5020/*'' is equal to the ``2:5020/*.0''
|
||||
##
|
||||
## Expression elements:
|
||||
## <Address or address mask>
|
||||
## Time <interval>[,<interval>,..]
|
||||
## Speed <logic_operator> <number>
|
||||
## ConnSpeed <logic_operator> <number>
|
||||
## Flag <nodelist_flag>
|
||||
## Exec <command_name>
|
||||
## Inbound, Outbound, Listed, Protected
|
||||
##
|
||||
## You can split long strings by adding '\' character to the end of previous
|
||||
## line. Total length of string is unlimited. For example:
|
||||
##
|
||||
## Options NoZmodem \
|
||||
## NoZedZap
|
||||
##
|
||||
## Config reader directives:
|
||||
##
|
||||
## $INCLUDE <filename> Include this file
|
||||
## $LOGFILE <filename> Log to this file
|
||||
## $DEBUGFILE <filename> Write debug information to this file
|
||||
## $DEBUGLEVEL <debug_levels> Change debug level
|
||||
##
|
||||
## $IFEXP <expression> All data between ``$IFEXP'' and ``$ENDIF''
|
||||
## <config_keyword> <value> directives will be used with the specified
|
||||
## .... expression, empty lines are unallowed
|
||||
## $ENDIF
|
||||
##
|
||||
## Examples:
|
||||
##
|
||||
## $DEBUGLEVEL Outbound hShake
|
||||
##
|
||||
## $IFEXP ((2:*/*.* | !protected) & Time 23:00-01:00)
|
||||
## options NoFreqs
|
||||
## min_speed_in 14400
|
||||
## session_limit_in 600
|
||||
## $ENDIF
|
||||
##
|
||||
|
||||
$INCLUDE /usr/local/fido/etc/bforce.subst
|
||||
$INCLUDE /usr/local/fido/etc/bforce.passwd
|
||||
|
||||
address 2:450/256.0@fidonet
|
||||
address 2:450/247.128@fidonet
|
||||
address 20:26/100.0@easynet
|
||||
|
||||
#
|
||||
# Hide addresses from remote, where <address> must be one of your AKAs
|
||||
#
|
||||
# hide_our_aka <address>
|
||||
#
|
||||
|
||||
#
|
||||
# Allowed options:
|
||||
# [No]Zmodem, [No]ZedZap, [No]DirZap, [No]Janus, [No]Hydra
|
||||
# [No]Chat, [No]FTS1, [No]YooHoo, [No]EMSI, [No]EMSI-II
|
||||
# [No]Freqs, [No]MailOnly, [No]HoldXT, [No]HoldReq, [No]HoldHold
|
||||
# [No]HoldAll, [No]PickUp, [No]RH1
|
||||
#
|
||||
# Now it is highly recommended to set at least "NoDirZap NoJanus"
|
||||
#
|
||||
options NoDirZap NoJanus NoChat
|
||||
|
||||
#
|
||||
# Domain outbounds
|
||||
# Domain <domain_name> <outbound_dir> <zone>
|
||||
#
|
||||
#domain lasernet /var/spool/ftn/lasernet/ 161
|
||||
#domain medianet /var/spool/ftn/medianet/ 776
|
||||
#domain schoolnet /var/spool/ftn/schoolnet/ 461
|
||||
|
||||
#
|
||||
# Log/debug file names (if not defined, used builtins)
|
||||
#
|
||||
#log_file_daemon /var/log/bforce/bf-daemon
|
||||
#log_file /var/log/bforce/bf-log
|
||||
#debug_file /var/log/bforce/bf-debug
|
||||
|
||||
#
|
||||
# Existing of this file forbid any outgoing modem calls. Existing of
|
||||
# file with name <nodialflag>.ttyS1 forbid outgoing calls only via
|
||||
# modem on device /dev/ttyS1, and so on.
|
||||
#
|
||||
nodial_flag /etc/nodial
|
||||
|
||||
#
|
||||
# Debugging information completness level. Debugging is disabled by
|
||||
# default. Allowed debug levels: config, nodelist, outbound, info, hshake,
|
||||
# ttyio, modem, prot, freq, daemon, full
|
||||
#
|
||||
# It seems to be broken now, use "$DEBUGLEVEL" instead
|
||||
#
|
||||
#debug_level info hshake prot
|
||||
#
|
||||
|
||||
#
|
||||
# Inbound directories
|
||||
#
|
||||
inbound_directory (Protected) /var/spool/fido/bt/pin
|
||||
inbound_directory /var/spool/fido/bt/in
|
||||
|
||||
#
|
||||
# Path to your 4D outbound (use zone as extension)
|
||||
#
|
||||
#outbound_directory /var/spool/fido/bt/out
|
||||
|
||||
#
|
||||
# Path to your AmigaDos style 4D outbound.
|
||||
# (You can use all outbound styles at the same time)
|
||||
#
|
||||
amiga_outbound_directory /var/spool/fido/bt/out
|
||||
|
||||
#
|
||||
# Directory with your nodelists (for nodelist without full path)
|
||||
#
|
||||
nodelist_directory /var/spool/fido/ndl
|
||||
|
||||
#
|
||||
# Directory for status files
|
||||
#
|
||||
status_directory /var/spool/fido/bforce
|
||||
|
||||
#
|
||||
# Sessions history
|
||||
#
|
||||
history_file /var/log/bforce/history
|
||||
|
||||
#
|
||||
# Minimal connect speeds for incoming/outgoing sessions
|
||||
#
|
||||
#min_speed_in 1200
|
||||
#min_speed_out 1200
|
||||
|
||||
#
|
||||
# Time limit for incoming/outgoing session [seconds]
|
||||
#
|
||||
#session_limit_in 1800
|
||||
#session_limit_out 1800
|
||||
|
||||
#
|
||||
# Abort transfer if minimal CPS stays longer this time (in seconds)
|
||||
# Default value is 60 seconds.
|
||||
#
|
||||
#min_cps_time 120
|
||||
|
||||
#
|
||||
# Force usage of this value as minimal CPS (most priority)
|
||||
# min_cps_recv <Minimal_CPS>
|
||||
# min_cps_send <Minimal_CPS>
|
||||
#
|
||||
# For example:
|
||||
# min_cps_recv (2:5020/1398) 2100
|
||||
# min_cps_recv (2:5020/1682) 3000
|
||||
# min_cps_recv (2:5020/1811) 1400
|
||||
|
||||
#
|
||||
# Minimal CPS values for Zmodem ,ZedZap, DirZap protocols (Receive/Send)
|
||||
#
|
||||
# <Speed> <CPS>
|
||||
#
|
||||
zmodem_mincps_recv 300 15
|
||||
zmodem_mincps_recv 1200 90
|
||||
zmodem_mincps_recv 2400 120
|
||||
zmodem_mincps_recv 4800 240
|
||||
zmodem_mincps_recv 7200 360
|
||||
zmodem_mincps_recv 9600 480
|
||||
zmodem_mincps_recv 12000 600
|
||||
zmodem_mincps_recv 14400 720
|
||||
zmodem_mincps_recv 16800 840
|
||||
zmodem_mincps_recv 19200 960
|
||||
zmodem_mincps_recv 21600 1080
|
||||
zmodem_mincps_recv 23600 1180
|
||||
zmodem_mincps_recv 24000 1200
|
||||
zmodem_mincps_recv 26400 1320
|
||||
zmodem_mincps_recv 28800 1440
|
||||
zmodem_mincps_recv 31200 1600
|
||||
zmodem_mincps_recv 33600 1700
|
||||
|
||||
zmodem_mincps_send 300 15
|
||||
zmodem_mincps_send 1200 90
|
||||
zmodem_mincps_send 2400 120
|
||||
zmodem_mincps_send 4800 240
|
||||
zmodem_mincps_send 7200 360
|
||||
zmodem_mincps_send 9600 480
|
||||
zmodem_mincps_send 12000 600
|
||||
zmodem_mincps_send 14400 720
|
||||
zmodem_mincps_send 16800 840
|
||||
zmodem_mincps_send 19200 960
|
||||
zmodem_mincps_send 21600 1080
|
||||
zmodem_mincps_send 23600 1180
|
||||
zmodem_mincps_send 24000 1200
|
||||
zmodem_mincps_send 26400 1320
|
||||
zmodem_mincps_send 28800 1440
|
||||
zmodem_mincps_send 31200 1600
|
||||
zmodem_mincps_send 33600 1700
|
||||
|
||||
hydra_mincps_recv 300 15
|
||||
hydra_mincps_recv 1200 90
|
||||
hydra_mincps_recv 2400 120
|
||||
hydra_mincps_recv 4800 240
|
||||
hydra_mincps_recv 7200 360
|
||||
hydra_mincps_recv 9600 480
|
||||
hydra_mincps_recv 12000 600
|
||||
hydra_mincps_recv 14400 720
|
||||
hydra_mincps_recv 16800 840
|
||||
hydra_mincps_recv 19200 960
|
||||
hydra_mincps_recv 21600 1080
|
||||
hydra_mincps_recv 23600 1180
|
||||
hydra_mincps_recv 24000 1200
|
||||
hydra_mincps_recv 26400 1320
|
||||
hydra_mincps_recv 28800 1440
|
||||
hydra_mincps_recv 31200 1600
|
||||
hydra_mincps_recv 33600 1700
|
||||
|
||||
hydra_mincps_send 300 15
|
||||
hydra_mincps_send 1200 90
|
||||
hydra_mincps_send 2400 120
|
||||
hydra_mincps_send 4800 240
|
||||
hydra_mincps_send 7200 360
|
||||
hydra_mincps_send 9600 480
|
||||
hydra_mincps_send 12000 600
|
||||
hydra_mincps_send 14400 720
|
||||
hydra_mincps_send 16800 840
|
||||
hydra_mincps_send 19200 960
|
||||
hydra_mincps_send 21600 1080
|
||||
hydra_mincps_send 23600 1180
|
||||
hydra_mincps_send 24000 1200
|
||||
hydra_mincps_send 26400 1320
|
||||
hydra_mincps_send 28800 1440
|
||||
hydra_mincps_send 31200 1600
|
||||
hydra_mincps_send 33600 1700
|
||||
|
||||
#
|
||||
# Automatically set this permissions on the received files
|
||||
#
|
||||
mode_default 100660
|
||||
mode_arcmail 100660
|
||||
mode_netmail 100660
|
||||
mode_request 100660
|
||||
|
||||
#
|
||||
# In modem commands you can use:
|
||||
# '|' cartidge return
|
||||
# '^' high DTR
|
||||
# 'v' low DTR
|
||||
# '~' 1 second delay
|
||||
# '`' 1/4 second delay
|
||||
|
||||
#
|
||||
# Yor modem devices names (will use first not locked one)
|
||||
# ModemDev <device>[<:lock_speed>]
|
||||
#
|
||||
modem_port /dev/ttyS0:57600
|
||||
|
||||
#
|
||||
# Send this string to modem before calling
|
||||
#
|
||||
modem_reset_command AT|
|
||||
|
||||
#
|
||||
# Dial string
|
||||
#
|
||||
modem_dial_prefix ATDP
|
||||
|
||||
#
|
||||
# Dial string
|
||||
#
|
||||
modem_dial_suffix |
|
||||
|
||||
#
|
||||
# Hangup string
|
||||
#
|
||||
modem_hangup_command v~^~ATH0|
|
||||
|
||||
#
|
||||
# Command for getting modem statistic (after outgoing sessions)
|
||||
#
|
||||
#
|
||||
#modem_stat_command AT%S|
|
||||
# if your modem do not send statistic, use this:
|
||||
modem_stat_command AT|
|
||||
|
||||
#
|
||||
# List of modem responses on modem dial command
|
||||
#
|
||||
# First field is substring of modem response string, first match used!
|
||||
#
|
||||
# Second field value Default return code
|
||||
# connect --
|
||||
# busy 11
|
||||
# nocarrier 12
|
||||
# nodialtone 13
|
||||
# noanswer 14
|
||||
# error 15
|
||||
#
|
||||
# You are free to use something like: ModemDialResp "LINE IN USE" Error 200
|
||||
#
|
||||
# <Modem said> <Mailer think> [Return code]
|
||||
#
|
||||
modem_dial_response "CONNECT" connect
|
||||
modem_dial_response "BUSY" busy
|
||||
modem_dial_response "NO CARRIER" nocarrier
|
||||
modem_dial_response "NO DIAL" nodialTone
|
||||
modem_dial_response "NO ANSWER" noanswer
|
||||
modem_dial_response "VOICE" noanswer
|
||||
modem_dial_response "ERROR" error
|
||||
|
||||
#
|
||||
# Your nodelists. Will try all nodelists with matching address mask.
|
||||
#
|
||||
nodelist nodelist.ndl *:*/*.0
|
||||
nodelist 450_256.pnt 2:450/256.*
|
||||
nodelist easynet.ndl 20:26/*.0
|
||||
nodelist *:*/*.*
|
||||
|
||||
#
|
||||
# Nodelist phone numbers translation
|
||||
# phone_translate <what_translate> [to_what_translate]
|
||||
|
||||
phone_translate 375-17-
|
||||
phone_translate 375- 8W
|
||||
|
||||
|
||||
#
|
||||
# Your system information (for EMSI only)
|
||||
#
|
||||
system_name XXX Station
|
||||
location Minsk, Belarus
|
||||
sysop_name Evgeniy Kozhuhovskiy
|
||||
phone 375-17-2250238, voice: 375-29-5586164
|
||||
max_speed 57600
|
||||
flags XW,V34B,IDC,LMD
|
||||
emsi_OH_time 22:00-07:30
|
||||
emsi_FR_time 22:30-05:30
|
||||
|
||||
#
|
||||
# Our receiver buffer size [bytes]
|
||||
#
|
||||
recv_buffer_size 65536
|
||||
|
||||
#
|
||||
# Wait for modem response this time at calling [seconds]
|
||||
#
|
||||
wait_carrier_out 120
|
||||
|
||||
# Command to run external SRIF processor
|
||||
#
|
||||
#freq_srif_command /usr/local/lib/u-srif/u-srif
|
||||
|
||||
#
|
||||
# Files with list of aliases and dirs for FREQs
|
||||
#
|
||||
freq_alias_list /usr/local/fido/etc/freq.aliases
|
||||
freq_dir_list /usr/local/fido/etc/freq.dirs
|
||||
|
||||
#
|
||||
# Maximal number of files to send on FREQs
|
||||
#
|
||||
freq_limit_number 10
|
||||
|
||||
#
|
||||
# Size limit for file requests [bytes]
|
||||
#
|
||||
freq_limit_size 6000000
|
||||
|
||||
#
|
||||
# _SEND_ requested files not longer this time [seconds]
|
||||
#
|
||||
freq_limit_time 1200
|
||||
|
||||
#
|
||||
# Ignore this masks in file requests
|
||||
#
|
||||
freq_ignore_masks \\* \\*.\\* \\*.zip \\*.rar \\*.tgz \\*.mp3
|
||||
|
||||
#
|
||||
# Skip files with ZRPOS on zmodem protocol (else use ZSKIP)
|
||||
#
|
||||
#zmodem_skip_by_pos yes
|
||||
|
||||
#
|
||||
# Binkleyforce will send empty netmail packet on Zmodem/ZedZap/DirZap
|
||||
# protocols if there is nothing to send (default - No)
|
||||
#
|
||||
zmodem_send_dummy_pkt no
|
||||
|
||||
#
|
||||
# Initial block size [bytes] for Zmodem/ZedZap/DirZap protocols
|
||||
#
|
||||
#zmodem_start_block_size 512
|
||||
|
||||
#
|
||||
# Tx window size [bytes] for Zmodem/ZedZap/DirZap protocols
|
||||
#
|
||||
#zmodem_tx_window 32768
|
||||
|
||||
#
|
||||
# Automaticaly skip files with such names at receiving
|
||||
#
|
||||
skip_files_recv *.pif *.swp
|
||||
|
||||
#
|
||||
# Delay files with such names at receiving/sending
|
||||
#
|
||||
#delay_files_recv !%arcmail !%netmail # We will refuse all except mail
|
||||
#delay_files_send !%netmail # We will send only netmail
|
||||
# # packets
|
||||
#
|
||||
# Our netmail-only uplink
|
||||
#delay_files_recv (2:450/102) !%netmail
|
||||
#
|
||||
# Binkleyforce will delay all receiving files if free space space
|
||||
# in the inbound directory is lower this value [Kbytes]
|
||||
#
|
||||
#min_free_space 20000
|
||||
|
||||
#
|
||||
# Tables for recoding to another charset. Tables format is compartible
|
||||
# with HPT, FTrack and possible with something else.
|
||||
#
|
||||
# File names recoding
|
||||
#recode_file_out /usr/local/fido/etc/koi82alt.tbl
|
||||
#recode_file_in /usr/local/fido/etc/alt2koi8.tbl
|
||||
# Intro recoding (Buggy Sidoroff)
|
||||
#recode_intro_in (2:450/236) /usr/local/fido/etc/alt2koi8.tbl
|
||||
|
||||
#
|
||||
# External programs support. Possible execution options:
|
||||
#
|
||||
# nowait - don't wait for the process termination
|
||||
# logout - write stdout/stderr to the log
|
||||
# setsid - run command in a new session
|
||||
# useshell - run command by calling a shell (/bin/sh)
|
||||
#
|
||||
#run_after_handshake [logout]/bin/echo "Hello, world!"
|
||||
#run_after_session [nowait,setsid]/usr/local/lib/ftp/run-in
|
||||
#
|
||||
# To see a nodelist node information in the log file, write:
|
||||
#
|
||||
#run_after_handshake [useshell,logout]/usr/local/lib/ftn/nlookup $REM_ADDR_FTN
|
||||
|
||||
#
|
||||
# Path to the directory with "long" fileboxes. Such fileboxes names
|
||||
# has the format "<zone>.<net>.<node>.<point>" (e.g. "2.5020.2120.0").
|
||||
# The files from such fileboxes are allways queued with a "hold" flavor
|
||||
#
|
||||
#filebox_directory /var/spool/fido/bt/fbox
|
||||
|
||||
#
|
||||
# Personal fileboxes
|
||||
# filebox <path> <address> [flavor]
|
||||
#
|
||||
#filebox /var/spool/ftn/fbox/adb 2:5020/2120.1 hold
|
||||
#filebox /var/spool/ftn/fbox/pvc 2:5020/2091 normal
|
||||
|
||||
#
|
||||
# ?LO files content translation rules
|
||||
# flo_translate <find string> <replace string>
|
||||
#
|
||||
#flo_translate C:\\fido\\spool\\outbound /var/spool/ftn/out
|
||||
#flo_translate \\ /
|
||||
|
||||
#######################
|
||||
# DAEMON configuration
|
||||
|
||||
#
|
||||
# Try counters short description:
|
||||
#
|
||||
# <Keyword> <Tries number> <Action> [<Action argument>]
|
||||
#
|
||||
# Allowed 'Keywords':
|
||||
# 'Maxtries'
|
||||
# Increase : every time when we call system
|
||||
# Reset : successful session
|
||||
# 'Maxtries_noansw'
|
||||
# Increase : modem return "noanswer"
|
||||
# Reset : connect
|
||||
# 'Maxtries_noconn'
|
||||
# Increase : cannot connect
|
||||
# Reset : connect
|
||||
# 'Maxtries_hshake'
|
||||
# Increase : handshake failure
|
||||
# Reset : successful handshake
|
||||
# 'Maxtries_sessions'
|
||||
# Increase : any failures after connect (including connect speed too low)
|
||||
# Reset : successful session
|
||||
# 'Maxtries_nodial'
|
||||
# Increase : modem return "nodialtone"
|
||||
# Reset : connect
|
||||
#
|
||||
# Allowed 'Actions':
|
||||
# 'Undialable' - set undialable flag to the system, so we will never try
|
||||
# to call it more
|
||||
# 'Hold' - don't call system during next <Action argument> seconds
|
||||
# 'HoldAll' - don't make outgoing calls to ANY system during next
|
||||
# <Action argument> seconds
|
||||
#
|
||||
|
||||
maxtries 200 Undialable # Be carefull.. =)
|
||||
maxtries_noansw 5 Hold 7200 # Call two hours later
|
||||
maxtries_noconn 40 Hold 10800 # Don't call 3 hours
|
||||
maxtries_hshake 10 Hold 86400 # 1 day delay
|
||||
maxtries_sessions 10 Hold 3600 # Don't annoy uplinks
|
||||
maxtries_nodial 1 Hold 1200 # Call 20 min later
|
||||
|
||||
#
|
||||
# Minimum delay between reusings of the same modem [seconds]
|
||||
#
|
||||
daemon_circle_modem 40
|
||||
|
||||
#
|
||||
# Outbound queue rescan interval [seconds]
|
||||
#
|
||||
daemon_circle_rescan 60
|
||||
|
||||
#
|
||||
# Minimum delay between two outgoing calls to the same system,
|
||||
# depending on the mail/files flavor [seconds]
|
||||
#
|
||||
daemon_circle_normal 80
|
||||
daemon_circle_direct 40
|
||||
daemon_circle_crash 20
|
||||
daemon_circle_immed 10
|
||||
|
||||
#
|
||||
# Maximum number of the simultaneously running TCP/IP clients. Zero value
|
||||
# will forbid any outgoing calls via TCP/IP
|
||||
#
|
||||
daemon_maxclients_tcpip 3
|
||||
|
||||
#
|
||||
# Maximum number of the simultaneously running modem clients. Zero value
|
||||
# will forbid any outgoing calls via modems
|
||||
#
|
||||
daemon_maxclients_modem 1
|
||||
|
||||
#
|
||||
# Daemon PID file name
|
||||
#
|
||||
daemon_pid_file /var/run/bforce.pid
|
||||
|
||||
#
|
||||
# Syslog facility (see man 3 openlog and /usr/include/sys/syslog.h for list of facilities)
|
||||
# 64 == 8<3 ==
|
||||
# See SYSLOG for details
|
||||
#
|
||||
syslog_facility 64
|
||||
|
||||
#
|
||||
# Where to listen (0.0.0.0 for all available)
|
||||
#
|
||||
bind_ip 127.0.0.1
|
||||
|
||||
#
|
||||
# Holdall flag (if exists, no mail will sent)
|
||||
#
|
||||
nomail_flag /etc/nomail
|
||||
|
||||
|
||||
# That's all!
|
||||
9
examples/bforce.passwd
Normal file
9
examples/bforce.passwd
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Format: password <address> <password>
|
||||
#
|
||||
|
||||
password 2:5020/1398 passwd1
|
||||
password 2:5020/1682 passwd2
|
||||
password 2:5020/1811 passwd3
|
||||
password 776:308/8 passwd4
|
||||
|
||||
33
examples/bforce.subst
Normal file
33
examples/bforce.subst
Normal file
@ -0,0 +1,33 @@
|
||||
#
|
||||
# Example of overriding node with hidden lines:
|
||||
# Override 1:2/3 Phone 123-1313 Worktime 21:00-07:00 \
|
||||
# Hidden Phone 123-1314 Worktime 09:00-13:00 \
|
||||
# Hidden Phone 123-1315 Worktime 09:00-21:00 \
|
||||
# Hidden Phone 123-1316 Flags CM
|
||||
#
|
||||
# You may specify different time for different days of week:
|
||||
# Override 1:2/3 Phone 123-1313 Worktime Wk20:00-07:30,We00:00-24:00
|
||||
#
|
||||
# Allowed day prefixes: Sun, Mon, Tue, Wed, Thu, Fri, Sat, Any, Wk, We
|
||||
#
|
||||
# To use BinkP protocol, write:
|
||||
# Override 1:2/3 Ipaddr f3.n2.z1.fidonet.net Flags CM,BINKP
|
||||
#
|
||||
# If you want never call to certain node, write:
|
||||
# Override 1:2/3 Phone Unpublished
|
||||
#
|
||||
# Happy
|
||||
override 776:308/1 Ipaddr 192.168.1.1 Flags CM,IFC
|
||||
override 776:308/1.1 Ipaddr 192.168.1.2 Flags CM,BINKP
|
||||
|
||||
# Estar
|
||||
override 2:5020/758 Phone 961-2243
|
||||
|
||||
# Hard Core
|
||||
override 2:5020/1398 Phone 700-0245 Worktime 00:00-07:00
|
||||
|
||||
# Stick's
|
||||
override 2:5020/1682 Phone 308-5537 Worktime 23:30-07:00
|
||||
|
||||
override 2:5020/2120 Ipaddr 192.168.1.1 flags BINKP,CM
|
||||
|
||||
6
examples/freq.aliases
Normal file
6
examples/freq.aliases
Normal file
@ -0,0 +1,6 @@
|
||||
#
|
||||
# <Alias> <File> [!<Password>]
|
||||
#
|
||||
#files /home/ftp/pub/info/happy.zip
|
||||
#filelist /home/ftp/pub/info/happy.lst
|
||||
#test /home/ftp/pub/fileecho/PNT5020/pnt5020.zip
|
||||
10
examples/freq.dirs
Normal file
10
examples/freq.dirs
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# <Path> [!<Password>]
|
||||
#
|
||||
|
||||
#/home/ftp/secure/doc/xxx.zip !fdsn02vz
|
||||
#/home/ftp/pub/fileecho/AFTNMISC/
|
||||
#/home/ftp/pub/fileecho/AVP/
|
||||
#/home/ftp/pub/fileecho/LARRY.FILES/
|
||||
#/home/ftp/pub/fileecho/MOBIL/
|
||||
#/home/ftp/pub/fileecho/NET5020/
|
||||
2
patch-stamp
Normal file
2
patch-stamp
Normal file
@ -0,0 +1,2 @@
|
||||
Patches applied in the Debian version of :
|
||||
|
||||
70
rpm/bforce.spec
Normal file
70
rpm/bforce.spec
Normal file
@ -0,0 +1,70 @@
|
||||
Summary: Bforce, Fidonet mailer
|
||||
Name: bforce
|
||||
Version: 0.22.8
|
||||
Release: ugenk2
|
||||
Copyright: GPL
|
||||
Group: Fidonet/mailer
|
||||
Source0: bforce-%{version}.%{release}.tar.gz
|
||||
BuildRoot: %{_tmppath}/%{name}-root
|
||||
|
||||
%description
|
||||
BFORCE is a FTN mailer. Supports PSTN and binkp sessions.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}.%{release}
|
||||
|
||||
cd source
|
||||
./configure --prefix=/usr --disable-log-passwd --sysconfdir=/etc/bforce --bindir=/usr/bin --with-owner=uucp --with-group=news
|
||||
|
||||
%build
|
||||
cd source
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/bforce
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/sbin
|
||||
mkdir -p $RPM_BUILD_ROOT/var/log/bforce
|
||||
mkdir -p $RPM_BUILD_ROOT/var/spool/fido/bt/pin
|
||||
mkdir -p $RPM_BUILD_ROOT/var/spool/fido/bt/in
|
||||
mkdir -p $RPM_BUILD_ROOT/var/spool/fido/ndl
|
||||
mkdir -p $RPM_BUILD_ROOT/var/spool/fido/bforce
|
||||
|
||||
|
||||
install -o uucp -g news source/bin/bforce $RPM_BUILD_ROOT/usr/bin/bforce
|
||||
install -o uucp -g news source/bin/bfindex $RPM_BUILD_ROOT/usr/bin/bfindex
|
||||
install -o uucp -g news source/bin/bfstat $RPM_BUILD_ROOT/usr/bin/bfstat
|
||||
install -o uucp -g news source/bin/nlookup $RPM_BUILD_ROOT/usr/bin/nlookup
|
||||
install -o uucp -g news examples/bforce.conf $RPM_BUILD_ROOT/etc/bforce/bforce.conf.sample
|
||||
install -o uucp -g news examples/bforce.passwd $RPM_BUILD_ROOT/etc/bforce/bforce.passwd.sample
|
||||
install -o uucp -g news examples/bforce.subst $RPM_BUILD_ROOT/etc/bforce/bforce.subst.sample
|
||||
install -o uucp -g news examples/freq.aliases $RPM_BUILD_ROOT/etc/bforce/freq.aliases.sample
|
||||
install -o uucp -g news examples/freq.dirs $RPM_BUILD_ROOT/etc/bforce/freq.dirs.sample
|
||||
install -m755 -o uucp -g news contrib/outman $RPM_BUILD_ROOT/usr/bin/outman
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%doc README README.kst CHANGES CHANGES.kst COPYING INSTALL.ru README.ugenk
|
||||
|
||||
%attr(550,uucp,news) /usr/bin/bforce
|
||||
%attr(550,uucp,news) /usr/bin/bfindex
|
||||
%attr(550,uucp,news) /usr/bin/bfstat
|
||||
%attr(550,uucp,news) /usr/bin/nlookup
|
||||
%attr(550,uucp,news) /usr/bin/outman
|
||||
%attr(644,root,root) /usr/share/doc/bforce-0.22.8/*
|
||||
%dir %attr(770,uucp,news) /var/log/bforce
|
||||
%dir %attr(770,uucp,news) /var/spool/fido/ndl
|
||||
%attr(775,uucp,news) /var/spool/fido/bt
|
||||
%config %attr(600,uucp,news) /etc/bforce/bforce.conf.sample
|
||||
%config %attr(600,uucp,news) /etc/bforce/bforce.subst.sample
|
||||
%config %attr(600,uucp,news) /etc/bforce/bforce.passwd.sample
|
||||
%config %attr(600,uucp,news) /etc/bforce/freq.aliases.sample
|
||||
%config %attr(600,uucp,news) /etc/bforce/freq.dirs.sample
|
||||
|
||||
|
||||
|
||||
31
rpm/buildrpm.sh
Executable file
31
rpm/buildrpm.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 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.
|
||||
|
||||
RPMROOT='/home/ugenk/rpm'
|
||||
|
||||
if [ `whoami` != "root" ]; then
|
||||
echo "$0: your must be root run this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
cd ../source
|
||||
|
||||
make distclean
|
||||
|
||||
cd -
|
||||
|
||||
rm -f *.gz
|
||||
|
||||
tar -cvf bforce-`cat ../source/.version`.tar ../../bforce-`cat ../source/.version`/source/ ../../bforce-`cat ../source/.version`/CHANGES* ../../bforce-`cat ../source/.version`/COPYING ../../bforce-`cat ../source/.version`/INSTALL* ../../bforce-`cat ../source/.version`/README* ../../bforce-`cat ../source/.version`/SYSLOG ../../bforce-`cat ../source/.version`/TODO ../../bforce-`cat ../source/.version`/contrib ../../bforce-`cat ../source/.version`/examples ../../bforce-`cat ../source/.version`/debian
|
||||
|
||||
gzip bforce-`cat ../source/.version`.tar
|
||||
|
||||
cp -f bforce-`cat ../source/.version`.tar.gz $RPMROOT/SOURCES/
|
||||
|
||||
rpm -ba bforce.spec
|
||||
|
||||
1
source/.version
Normal file
1
source/.version
Normal file
@ -0,0 +1 @@
|
||||
0.22.8.ugenk4
|
||||
185
source/Makefile
Normal file
185
source/Makefile
Normal file
@ -0,0 +1,185 @@
|
||||
#
|
||||
# Copyright (c) 1999-2000, Alexander Belkin <adb@newmail.ru>
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
INCLUDES = -I./include
|
||||
CFLAGS = -g -O2
|
||||
LIBS =
|
||||
YACC = bison -y
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_PROGRAM = ${INSTALL}
|
||||
INSTALL_DATA = ${INSTALL} -m 644
|
||||
SRCDIR = .
|
||||
SRCDIRCONF = $(SRCDIR)/../examples
|
||||
CONTRIBDIR = $(SRCDIR)/../contrib
|
||||
|
||||
OWNER = uucp
|
||||
GROUP = news
|
||||
CONFDIR = /usr/local/etc
|
||||
BINDIR = /usr/local/bin
|
||||
LOGDIR = /var/log/bforce
|
||||
SPOOLDIR = /var/spool/bforce
|
||||
|
||||
DAEMON_LOGFILE = $(LOGDIR)/bf-daemon
|
||||
BFORCE_LOGFILE = $(LOGDIR)/bf-log
|
||||
BFORCE_DEBFILE = $(LOGDIR)/bf-debug
|
||||
BFORCE_CFGFILE = $(CONFDIR)/bforce.conf
|
||||
|
||||
DEFINES = -DDAEMON_LOGFILE=\"$(DAEMON_LOGFILE)\" \
|
||||
-DBFORCE_LOGFILE=\"$(BFORCE_LOGFILE)\" \
|
||||
-DBFORCE_DEBFILE=\"$(BFORCE_DEBFILE)\" \
|
||||
-DBFORCE_CFGFILE=\"$(BFORCE_CFGFILE)\" \
|
||||
-DBF_OS=\"linux-gnu\" -DHAVE_CONFIG_H
|
||||
|
||||
SUBDIRS = bforce bfutil
|
||||
|
||||
BFINDEX_OBJS = bfutil/bfindex.o \
|
||||
bforce/conf_deinit.o bforce/conf_proc.o \
|
||||
bforce/conf_read.o bforce/conf_get.o \
|
||||
bforce/logger.o bforce/nodelist.o \
|
||||
bforce/u_file.o bforce/u_ftn.o \
|
||||
bforce/u_misc.o bforce/u_string.o \
|
||||
bforce/u_time.o
|
||||
|
||||
NLOOKUP_OBJS = bfutil/nlookup.o \
|
||||
bforce/conf_deinit.o bforce/conf_proc.o \
|
||||
bforce/conf_read.o bforce/conf_get.o \
|
||||
bforce/logger.o bforce/nodelist.o \
|
||||
bforce/u_file.o bforce/u_ftn.o \
|
||||
bforce/u_misc.o bforce/u_string.o \
|
||||
bforce/u_time.o
|
||||
|
||||
BFSTAT_OBJS = bfutil/bfstat.o \
|
||||
bforce/conf_deinit.o bforce/conf_proc.o \
|
||||
bforce/conf_read.o bforce/conf_get.o \
|
||||
bforce/outb_flo.o bforce/outb_fsqueue.o \
|
||||
bforce/sess_stat.o \
|
||||
bforce/outb_getname.o bforce/outb_sysqueue.o \
|
||||
bforce/outb_scan.o bforce/logger.o \
|
||||
bforce/u_file.o \
|
||||
bforce/u_ftn.o bforce/u_misc.o \
|
||||
bforce/u_string.o bforce/u_time.o \
|
||||
bforce/u_plock.o
|
||||
|
||||
BFORCE_OBJS = bforce/bforce.o \
|
||||
bforce/daemon.o bforce/daemon_branch.o \
|
||||
bforce/daemon_call.o bforce/daemon_lines.o \
|
||||
bforce/conf_deinit.o \
|
||||
bforce/conf_proc.o bforce/conf_read.o \
|
||||
bforce/conf_get.o bforce/expression.o \
|
||||
bforce/freq_bark.o bforce/freq_proc.o \
|
||||
bforce/freq_srif.o bforce/freq_wazoo.o \
|
||||
bforce/io_modem.o bforce/io_tcpip.o \
|
||||
bforce/io_unix_lock.o bforce/io_unix_modem.o \
|
||||
bforce/io_unix_tio.o bforce/io_unix_tty.o \
|
||||
bforce/logger.o bforce/nodelist.o \
|
||||
bforce/os_unix.o bforce/outb_bsy.o \
|
||||
bforce/outb_flo.o bforce/outb_fsqueue.o \
|
||||
bforce/outb_getname.o bforce/outb_sysqueue.o \
|
||||
bforce/outb_scan.o bforce/prot_common.o \
|
||||
bforce/prot_binkp.o bforce/prot_binkp_api.o \
|
||||
bforce/prot_binkp_misc.o bforce/prot_hydra.o \
|
||||
bforce/prot_xmrecv.o bforce/prot_xmsend.o \
|
||||
bforce/prot_zmmisc.o bforce/prot_zmrecv.o \
|
||||
bforce/prot_zmsend.o \
|
||||
bforce/prot_yoohoo.o bforce/prot_yoohoo_api.o \
|
||||
bforce/prot_emsi.o bforce/prot_emsi_misc.o \
|
||||
bforce/prot_emsi_api.o \
|
||||
bforce/sess_common.o bforce/sess_stat.o \
|
||||
bforce/sess_call.o bforce/sess_answ.o \
|
||||
bforce/sess_init.o bforce/sess_main.o \
|
||||
bforce/u_crc.o bforce/u_ftn.o \
|
||||
bforce/u_md5.o \
|
||||
bforce/u_misc.o bforce/u_string.o \
|
||||
bforce/u_time.o bforce/u_file.o \
|
||||
bforce/u_pkt.o bforce/u_recode.o \
|
||||
bforce/u_plock.o
|
||||
|
||||
.c.o:
|
||||
@echo Compiling $*.c
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
|
||||
|
||||
all: bin/bforce bin/bfindex bin/bfstat bin/nlookup
|
||||
|
||||
expression.c: bforce/expression.y
|
||||
$(YACC) bforce/expression.y
|
||||
mv y.tab.c bforce/expression.c
|
||||
|
||||
bin/bforce: $(BFLIB_OBJS) $(BFORCE_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(BFORCE_OBJS) $(LIBS) -o $@
|
||||
|
||||
bin/bfindex: $(BFLIB_OBJS) $(BFINDEX_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(BFINDEX_OBJS) $(LIBS) -o $@
|
||||
|
||||
bin/nlookup: $(BFLIB_OBJS) $(NLOOKUP_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(NLOOKUP_OBJS) $(LIBS) -o $@
|
||||
|
||||
bin/bfstat: $(BFLIB_OBJS) $(BFSTAT_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(BFSTAT_OBJS) $(LIBS) -o $@
|
||||
|
||||
|
||||
clean:
|
||||
@for i in $(SUBDIRS); do (rm -f $$i/*.o || exit 1); done
|
||||
rm -f ./bforce/expression.c
|
||||
rm -f ./bin/bforce
|
||||
rm -f ./bin/bfindex
|
||||
rm -f ./bin/bfstat
|
||||
rm -f ./bin/nlookup
|
||||
rm -f ./bin/core
|
||||
clean-am:
|
||||
rm -f ./Makefile
|
||||
rm -f ./include/config.h
|
||||
rm -f ./config.log
|
||||
rm -f ./config.status
|
||||
clean-ac:
|
||||
rm -f ./configure
|
||||
|
||||
distclean: clean clean-am
|
||||
|
||||
distclean-m: distclean clean-ac
|
||||
|
||||
|
||||
ifnames:
|
||||
@for i in $(SUBDIRS); do (ifnames $$i/*.c || exit 1); done
|
||||
|
||||
bforce/expression.y.o: bforce/expression.y.c bforce/expression.l.c
|
||||
|
||||
bforce/expression.l.o: bforce/expression.y.c bforce/expression.l.c
|
||||
|
||||
installdirs:
|
||||
if [ ! -d $(CONFDIR) ]; then mkdir -p $(CONFDIR); fi
|
||||
if [ ! -d $(BINDIR) ]; then mkdir -p $(BINDIR); fi
|
||||
if [ ! -d $(LOGDIR) ]; then mkdir -p $(LOGDIR); fi
|
||||
if [ ! -d $(SPOOLDIR) ]; then mkdir -p $(SPOOLDIR); fi
|
||||
if [ ! -d $(SPOOLDIR)/bt/in ]; then mkdir -p $(SPOOLDIR)/bt/in; fi
|
||||
if [ ! -d $(SPOOLDIR)/bt/pin ]; then mkdir -p $(SPOOLDIR)/bt/pin; fi
|
||||
if [ ! -d $(SPOOLDIR)/bt/out ]; then mkdir -p $(SPOOLDIR)/bt/out; fi
|
||||
if [ ! -d $(SPOOLDIR)/ndl ]; then mkdir -p $(SPOOLDIR)/ndl; fi
|
||||
if [ ! -d $(SPOOLDIR)/bforce ]; then mkdir -p $(SPOOLDIR); fi
|
||||
chown $(OWNER).$(GROUP) $(CONFDIR)
|
||||
chown $(OWNER).$(GROUP) $(LOGDIR)
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/bt/in
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/bt/pin
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/bt/out
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/ndl
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)
|
||||
|
||||
install:
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/bforce $(BINDIR)/bforce
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/bfindex $(BINDIR)/bfindex
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/bfstat $(BINDIR)/bfstat
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/nlookup $(BINDIR)/nlookup
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(CONTRIBDIR)/outman $(BINDIR)/outman
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/bforce.conf $(CONFDIR)/bforce.conf.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/bforce.subst $(CONFDIR)/bforce.subst.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/bforce.passwd $(CONFDIR)/bforce.passwd.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/freq.aliases $(CONFDIR)/freq.aliases.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/freq.dirs $(CONFDIR)/freq.dirs.sample
|
||||
@echo "Please, edit $(BINDIR)/outman"
|
||||
185
source/Makefile.in
Normal file
185
source/Makefile.in
Normal file
@ -0,0 +1,185 @@
|
||||
#
|
||||
# Copyright (c) 1999-2000, Alexander Belkin <adb@newmail.ru>
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
CC = @CC@
|
||||
INCLUDES = -I./include
|
||||
CFLAGS = @CFLAGS@
|
||||
LIBS = @LIBS@
|
||||
YACC = @YACC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
SRCDIR = @srcdir@
|
||||
SRCDIRCONF = $(SRCDIR)/../examples
|
||||
CONTRIBDIR = $(SRCDIR)/../contrib
|
||||
|
||||
OWNER = @OWNER@
|
||||
GROUP = @GROUP@
|
||||
CONFDIR = @prefix@/etc
|
||||
BINDIR = @prefix@/bin
|
||||
LOGDIR = /var/log/bforce
|
||||
SPOOLDIR = /var/spool/bforce
|
||||
|
||||
DAEMON_LOGFILE = $(LOGDIR)/bf-daemon
|
||||
BFORCE_LOGFILE = $(LOGDIR)/bf-log
|
||||
BFORCE_DEBFILE = $(LOGDIR)/bf-debug
|
||||
BFORCE_CFGFILE = $(CONFDIR)/bforce.conf
|
||||
|
||||
DEFINES = -DDAEMON_LOGFILE=\"$(DAEMON_LOGFILE)\" \
|
||||
-DBFORCE_LOGFILE=\"$(BFORCE_LOGFILE)\" \
|
||||
-DBFORCE_DEBFILE=\"$(BFORCE_DEBFILE)\" \
|
||||
-DBFORCE_CFGFILE=\"$(BFORCE_CFGFILE)\" \
|
||||
-DBF_OS=\"@build_os@\" @DEFS@
|
||||
|
||||
SUBDIRS = bforce bfutil
|
||||
|
||||
BFINDEX_OBJS = bfutil/bfindex.o \
|
||||
bforce/conf_deinit.o bforce/conf_proc.o \
|
||||
bforce/conf_read.o bforce/conf_get.o \
|
||||
bforce/logger.o bforce/nodelist.o \
|
||||
bforce/u_file.o bforce/u_ftn.o \
|
||||
bforce/u_misc.o bforce/u_string.o \
|
||||
bforce/u_time.o
|
||||
|
||||
NLOOKUP_OBJS = bfutil/nlookup.o \
|
||||
bforce/conf_deinit.o bforce/conf_proc.o \
|
||||
bforce/conf_read.o bforce/conf_get.o \
|
||||
bforce/logger.o bforce/nodelist.o \
|
||||
bforce/u_file.o bforce/u_ftn.o \
|
||||
bforce/u_misc.o bforce/u_string.o \
|
||||
bforce/u_time.o
|
||||
|
||||
BFSTAT_OBJS = bfutil/bfstat.o \
|
||||
bforce/conf_deinit.o bforce/conf_proc.o \
|
||||
bforce/conf_read.o bforce/conf_get.o \
|
||||
bforce/outb_flo.o bforce/outb_fsqueue.o \
|
||||
bforce/sess_stat.o \
|
||||
bforce/outb_getname.o bforce/outb_sysqueue.o \
|
||||
bforce/outb_scan.o bforce/logger.o \
|
||||
bforce/u_file.o \
|
||||
bforce/u_ftn.o bforce/u_misc.o \
|
||||
bforce/u_string.o bforce/u_time.o \
|
||||
bforce/u_plock.o
|
||||
|
||||
BFORCE_OBJS = bforce/bforce.o \
|
||||
bforce/daemon.o bforce/daemon_branch.o \
|
||||
bforce/daemon_call.o bforce/daemon_lines.o \
|
||||
bforce/conf_deinit.o \
|
||||
bforce/conf_proc.o bforce/conf_read.o \
|
||||
bforce/conf_get.o bforce/expression.o \
|
||||
bforce/freq_bark.o bforce/freq_proc.o \
|
||||
bforce/freq_srif.o bforce/freq_wazoo.o \
|
||||
bforce/io_modem.o bforce/io_tcpip.o \
|
||||
bforce/io_unix_lock.o bforce/io_unix_modem.o \
|
||||
bforce/io_unix_tio.o bforce/io_unix_tty.o \
|
||||
bforce/logger.o bforce/nodelist.o \
|
||||
bforce/os_unix.o bforce/outb_bsy.o \
|
||||
bforce/outb_flo.o bforce/outb_fsqueue.o \
|
||||
bforce/outb_getname.o bforce/outb_sysqueue.o \
|
||||
bforce/outb_scan.o bforce/prot_common.o \
|
||||
bforce/prot_binkp.o bforce/prot_binkp_api.o \
|
||||
bforce/prot_binkp_misc.o bforce/prot_hydra.o \
|
||||
bforce/prot_xmrecv.o bforce/prot_xmsend.o \
|
||||
bforce/prot_zmmisc.o bforce/prot_zmrecv.o \
|
||||
bforce/prot_zmsend.o \
|
||||
bforce/prot_yoohoo.o bforce/prot_yoohoo_api.o \
|
||||
bforce/prot_emsi.o bforce/prot_emsi_misc.o \
|
||||
bforce/prot_emsi_api.o \
|
||||
bforce/sess_common.o bforce/sess_stat.o \
|
||||
bforce/sess_call.o bforce/sess_answ.o \
|
||||
bforce/sess_init.o bforce/sess_main.o \
|
||||
bforce/u_crc.o bforce/u_ftn.o \
|
||||
bforce/u_md5.o \
|
||||
bforce/u_misc.o bforce/u_string.o \
|
||||
bforce/u_time.o bforce/u_file.o \
|
||||
bforce/u_pkt.o bforce/u_recode.o \
|
||||
bforce/u_plock.o
|
||||
|
||||
.c.o:
|
||||
@echo Compiling $*.c
|
||||
@$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@
|
||||
|
||||
all: bin/bforce bin/bfindex bin/bfstat bin/nlookup
|
||||
|
||||
expression.c: bforce/expression.y
|
||||
$(YACC) bforce/expression.y
|
||||
mv y.tab.c bforce/expression.c
|
||||
|
||||
bin/bforce: $(BFLIB_OBJS) $(BFORCE_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(BFORCE_OBJS) $(LIBS) -o $@
|
||||
|
||||
bin/bfindex: $(BFLIB_OBJS) $(BFINDEX_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(BFINDEX_OBJS) $(LIBS) -o $@
|
||||
|
||||
bin/nlookup: $(BFLIB_OBJS) $(NLOOKUP_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(NLOOKUP_OBJS) $(LIBS) -o $@
|
||||
|
||||
bin/bfstat: $(BFLIB_OBJS) $(BFSTAT_OBJS)
|
||||
@echo "Linking $@"
|
||||
@$(CC) $(BFLIB_OBJS) $(BFSTAT_OBJS) $(LIBS) -o $@
|
||||
|
||||
|
||||
clean:
|
||||
@for i in $(SUBDIRS); do (rm -f $$i/*.o || exit 1); done
|
||||
rm -f ./bforce/expression.c
|
||||
rm -f ./bin/bforce
|
||||
rm -f ./bin/bfindex
|
||||
rm -f ./bin/bfstat
|
||||
rm -f ./bin/nlookup
|
||||
rm -f ./bin/core
|
||||
clean-am:
|
||||
rm -f ./Makefile
|
||||
rm -f ./include/config.h
|
||||
rm -f ./config.log
|
||||
rm -f ./config.status
|
||||
clean-ac:
|
||||
rm -f ./configure
|
||||
|
||||
distclean: clean clean-am
|
||||
|
||||
distclean-m: distclean clean-ac
|
||||
|
||||
|
||||
ifnames:
|
||||
@for i in $(SUBDIRS); do (ifnames $$i/*.c || exit 1); done
|
||||
|
||||
bforce/expression.y.o: bforce/expression.y.c bforce/expression.l.c
|
||||
|
||||
bforce/expression.l.o: bforce/expression.y.c bforce/expression.l.c
|
||||
|
||||
installdirs:
|
||||
if [ ! -d $(CONFDIR) ]; then mkdir -p $(CONFDIR); fi
|
||||
if [ ! -d $(BINDIR) ]; then mkdir -p $(BINDIR); fi
|
||||
if [ ! -d $(LOGDIR) ]; then mkdir -p $(LOGDIR); fi
|
||||
if [ ! -d $(SPOOLDIR) ]; then mkdir -p $(SPOOLDIR); fi
|
||||
if [ ! -d $(SPOOLDIR)/bt/in ]; then mkdir -p $(SPOOLDIR)/bt/in; fi
|
||||
if [ ! -d $(SPOOLDIR)/bt/pin ]; then mkdir -p $(SPOOLDIR)/bt/pin; fi
|
||||
if [ ! -d $(SPOOLDIR)/bt/out ]; then mkdir -p $(SPOOLDIR)/bt/out; fi
|
||||
if [ ! -d $(SPOOLDIR)/ndl ]; then mkdir -p $(SPOOLDIR)/ndl; fi
|
||||
if [ ! -d $(SPOOLDIR)/bforce ]; then mkdir -p $(SPOOLDIR); fi
|
||||
chown $(OWNER).$(GROUP) $(CONFDIR)
|
||||
chown $(OWNER).$(GROUP) $(LOGDIR)
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/bt/in
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/bt/pin
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/bt/out
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)/ndl
|
||||
chown $(OWNER).$(GROUP) $(SPOOLDIR)
|
||||
|
||||
install:
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/bforce $(BINDIR)/bforce
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/bfindex $(BINDIR)/bfindex
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/bfstat $(BINDIR)/bfstat
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(SRCDIR)/bin/nlookup $(BINDIR)/nlookup
|
||||
$(INSTALL_PROGRAM) -o $(OWNER) -g $(GROUP) $(CONTRIBDIR)/outman $(BINDIR)/outman
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/bforce.conf $(CONFDIR)/bforce.conf.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/bforce.subst $(CONFDIR)/bforce.subst.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/bforce.passwd $(CONFDIR)/bforce.passwd.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/freq.aliases $(CONFDIR)/freq.aliases.sample
|
||||
$(INSTALL_DATA) -o $(OWNER) -g $(GROUP) $(SRCDIRCONF)/freq.dirs $(CONFDIR)/freq.dirs.sample
|
||||
@echo "Please, edit $(BINDIR)/outman"
|
||||
485
source/bforce/bforce.c
Normal file
485
source/bforce/bforce.c
Normal file
@ -0,0 +1,485 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "version.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "bforce.h"
|
||||
#include "nodelist.h"
|
||||
#include "session.h"
|
||||
|
||||
/* PID of our child process (if use fork) */
|
||||
pid_t child_pid = 0;
|
||||
|
||||
const char *BFERR[] = {
|
||||
/* 00 */ "Successfull",
|
||||
/* 01 */ "Fatal error occured",
|
||||
/* 02 */ "Unknown phone number(or ip address)",
|
||||
/* 03 */ "Modem port busy (or open error)",
|
||||
/* 04 */ "System locked now",
|
||||
/* 05 */ "Try later",
|
||||
/* 06 */ "Modem not response",
|
||||
/* 07 */ "Not working now",
|
||||
/* 08 */ "Unused entry",
|
||||
/* 09 */ "Unused entry",
|
||||
/* 10 */ "Can't connect to remote",
|
||||
/* 11 */ "Can't connect to remote: busy",
|
||||
/* 12 */ "Can't connect to remote: nocarrier",
|
||||
/* 13 */ "Can't connect to remote: nodialtone",
|
||||
/* 14 */ "Can't connect to remote: noanswer",
|
||||
/* 15 */ "Can't connect to remote: error",
|
||||
/* 16 */ "Can't connect to remote: user defined 16",
|
||||
/* 17 */ "Can't connect to remote: user defined 17",
|
||||
/* 18 */ "Can't connect to remote: user defined 18",
|
||||
/* 19 */ "Can't connect to remote: user defined 19",
|
||||
/* 20 */ "Connect speed too low",
|
||||
/* 21 */ "Cannot handshake with remote",
|
||||
/* 22 */ "Xmiting error",
|
||||
/* 23 */ "CPS too low",
|
||||
/* 24 */ "Reached stop time",
|
||||
/* 25 */ "Unused entry",
|
||||
/* 26 */ "Unused entry",
|
||||
/* 27 */ "Unused entry"
|
||||
};
|
||||
|
||||
static void deinit_opts(s_bforce_opts *opts);
|
||||
|
||||
/*
|
||||
static void print_compiled_configuration(void)
|
||||
{
|
||||
printf("BFORCE_LOGFILE = "BFORCE_LOGFILE"\n");
|
||||
printf("BFORCE_DEBFILE = "BFORCE_DEBFILE"\n");
|
||||
printf("DAEMON_LOGFILE = "DAEMON_LOGFILE"\n");
|
||||
printf("BFORCE_CFGFILE = "BFORCE_CFGFILE"\n");
|
||||
printf("BF_OS = "BF_OS"\n");
|
||||
}
|
||||
*/
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf_usage(NULL,
|
||||
"usage: bforce [-fmh] [-I<include>] [-n<phone>] [-l<line_number>]\n"
|
||||
" [-a<ip_address>] [-S<connect>] [-p<device>] <node>\n"
|
||||
" bforce [-ih] [-I<include>] [-S<connect>]\n"
|
||||
" <tsync|yoohoo|emsi|binkp|auto> (this implies slave mode)\n"
|
||||
" bforce [-dh] [-C<config>] [-I<include>]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -d run as daemon\n"
|
||||
" -q terminate daemon\n"
|
||||
" -i run from inetd (for slave mode only)\n"
|
||||
" -f ignore system's work time\n"
|
||||
" -o starts outgoing session on stdin/stdout\n"
|
||||
" -C <config> main config file name (\"%s\")\n"
|
||||
" -I <config> additional config file name\n"
|
||||
" -n <phone> override phone number\n"
|
||||
" -l <line_number> call on this hidden line (default is 0) \n"
|
||||
" -a <ip_address> override internet address\n"
|
||||
" -S <connect_str> connect string (for slave mode only)\n"
|
||||
" -p <port> override modem port (must be defined in config)\n"
|
||||
" -h show this help message\n"
|
||||
"\n",
|
||||
conf_getconfname()
|
||||
);
|
||||
}
|
||||
|
||||
int bforce_create_dirs(void)
|
||||
{
|
||||
const char *p_dirname = conf_string(cf_status_directory);
|
||||
|
||||
if( p_dirname )
|
||||
{
|
||||
if( access(p_dirname, F_OK) == -1 || !is_directory(p_dirname) )
|
||||
{
|
||||
if( directory_create(p_dirname, 0700) == -1 )
|
||||
{
|
||||
logerr("cannot create spool directory \"%s\"", p_dirname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Universal signal handler for parent processes :) Will resend
|
||||
* signals to child process
|
||||
*/
|
||||
static RETSIGTYPE parent_sighandler(int sig)
|
||||
{
|
||||
/* Send this signal to our child */
|
||||
if( child_pid ) kill(child_pid, sig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero value to indicate error, on success - return zero
|
||||
* to child process and NEVER return to parent process
|
||||
*/
|
||||
static int usefork(void)
|
||||
{
|
||||
pid_t cpid; /* child PID */
|
||||
pid_t wpid; /* waitpid() returned value */
|
||||
int status = 0;
|
||||
|
||||
cpid = fork();
|
||||
|
||||
if( cpid == 0 )
|
||||
{ return 0; }
|
||||
|
||||
if( cpid < 0 )
|
||||
{ logerr("failed fork() call"); return 1; }
|
||||
|
||||
/*
|
||||
* Now we are parent process
|
||||
*/
|
||||
|
||||
/* Put PID into global variable */
|
||||
child_pid = cpid;
|
||||
|
||||
/* Setup signals handling */
|
||||
signal(SIGHUP, parent_sighandler);
|
||||
signal(SIGINT, parent_sighandler);
|
||||
signal(SIGTERM, parent_sighandler);
|
||||
signal(SIGUSR1, parent_sighandler);
|
||||
signal(SIGUSR2, parent_sighandler);
|
||||
|
||||
/* Wait until child die */
|
||||
while( (wpid = waitpid(cpid, &status, 0)) < 0 && errno == EINTR )
|
||||
{
|
||||
/* EMPTY LOOP */
|
||||
}
|
||||
|
||||
if( wpid == cpid && WIFEXITED(status) )
|
||||
{
|
||||
/* Child was terminated with _exit() */
|
||||
exit(WEXITSTATUS(status));
|
||||
}
|
||||
else if( wpid < 0 && WIFSIGNALED(status) )
|
||||
{
|
||||
/* Child was terminated by signal */
|
||||
kill(getpid(), WTERMSIG(status));
|
||||
}
|
||||
exit(BFERR_FATALERROR);
|
||||
}
|
||||
|
||||
static int bforce_master(const s_bforce_opts *opts)
|
||||
{
|
||||
s_falist *tmpl;
|
||||
int rc, maxrc = BFERR_NOERROR;
|
||||
|
||||
#ifdef GETPGRP_VOID
|
||||
if( getpgrp() == getpid() )
|
||||
#else
|
||||
if( getpgrp(0) == getpid() )
|
||||
#endif
|
||||
{
|
||||
/* We are process group leader -> fork() */
|
||||
if( usefork() ) return BFERR_FATALERROR;
|
||||
}
|
||||
|
||||
for( tmpl = opts->addrlist; tmpl; tmpl = tmpl->next )
|
||||
{
|
||||
int callopt = 0;
|
||||
|
||||
if( opts->iaddr ) callopt |= CALLOPT_INET;
|
||||
if( opts->force ) callopt |= CALLOPT_FORCE;
|
||||
|
||||
rc = call_system(tmpl->addr, opts);
|
||||
|
||||
if( rc > maxrc ) maxrc = rc;
|
||||
}
|
||||
|
||||
return maxrc;
|
||||
}
|
||||
|
||||
static int bforce_slave(const s_bforce_opts *opts)
|
||||
{
|
||||
return answ_system(opts->stype, opts->connect, opts->inetd);
|
||||
}
|
||||
|
||||
static int bforce_daemon(const s_bforce_opts *opts)
|
||||
{
|
||||
int forkrc = fork();
|
||||
|
||||
if( forkrc == -1 )
|
||||
{
|
||||
logerr("cannot run daemon: failed fork() call");
|
||||
return BFERR_FATALERROR;
|
||||
}
|
||||
else if( forkrc > 0 )
|
||||
{
|
||||
return BFERR_NOERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are inside a child process.
|
||||
* Create new session and run daemon
|
||||
*/
|
||||
setsid();
|
||||
|
||||
return daemon_run(opts->confname, opts->incname, opts->quit);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
s_bforce_opts opts;
|
||||
int rc = 0;
|
||||
int ch = 0;
|
||||
int role = 0;
|
||||
|
||||
memset(&opts, '\0', sizeof(s_bforce_opts));
|
||||
|
||||
while( (ch=getopt(argc, argv, "hodqr:ifC:I:n:l:a:S:p:")) != EOF )
|
||||
{
|
||||
switch( ch ) {
|
||||
case 'h':
|
||||
usage();
|
||||
exit(BFERR_NOERROR);
|
||||
case 'd':
|
||||
if( opts.inetd || opts.force || opts.phone
|
||||
|| opts.hiddline || opts.iaddr || opts.connect
|
||||
|| opts.device || opts.quit )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{ opts.daemon = 1; }
|
||||
break;
|
||||
case 'q':
|
||||
if( opts.inetd || opts.force || opts.phone
|
||||
|| opts.hiddline || opts.iaddr || opts.connect
|
||||
|| opts.device || opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{ opts.daemon = 1; opts.quit = 1; }
|
||||
break;
|
||||
case 'i':
|
||||
if( opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{ opts.inetd = 1; }
|
||||
break;
|
||||
case 'f':
|
||||
if( opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{ opts.force = 1; }
|
||||
break;
|
||||
case 'o':
|
||||
if( opts.dontcall )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{ opts.dontcall = TRUE; }
|
||||
break;
|
||||
case 'C':
|
||||
if( opts.confname ) free(opts.confname);
|
||||
if( optarg ) opts.confname = (char *)xstrcpy(optarg);
|
||||
break;
|
||||
case 'I':
|
||||
if( opts.incname ) free(opts.incname);
|
||||
if( optarg ) opts.incname = (char *)xstrcpy(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
if( opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{
|
||||
if( opts.phone ) free(opts.phone);
|
||||
if( optarg ) opts.phone = (char *)xstrcpy(optarg);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if( ISDEC(optarg) && opts.daemon == 0 )
|
||||
opts.hiddline = atoi(optarg);
|
||||
else
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
break;
|
||||
case 'a':
|
||||
if( opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{
|
||||
if( opts.iaddr ) free(opts.iaddr);
|
||||
if( optarg ) opts.iaddr = (char *)xstrcpy(optarg);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
if( opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{
|
||||
if( opts.connect ) free(opts.connect);
|
||||
if( optarg ) opts.connect = (char *)xstrcpy(optarg);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if( opts.daemon )
|
||||
{ usage(); exit(BFERR_FATALERROR); }
|
||||
else
|
||||
{
|
||||
if( opts.device ) free(opts.device);
|
||||
if( optarg ) opts.device = (char *)xstrcpy(optarg);
|
||||
}
|
||||
break;
|
||||
default :
|
||||
usage();
|
||||
exit(BFERR_FATALERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Expression checker use it, so init first */
|
||||
init_state(&state);
|
||||
|
||||
/* Set space available for process title */
|
||||
#ifndef HAVE_SETPROCTITLE
|
||||
setargspace(argv, envp);
|
||||
#endif
|
||||
|
||||
/* Initialise random number generation */
|
||||
(void)srand((unsigned)time(NULL));
|
||||
|
||||
/* Initialise current locale */
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
/* Set secure process umask */
|
||||
(void)umask(~(S_IRUSR|S_IWUSR));
|
||||
|
||||
/* Now process non-option arguments */
|
||||
if( opts.daemon == FALSE )
|
||||
{
|
||||
const char *p;
|
||||
s_faddr addr;
|
||||
s_falist **alist = &opts.addrlist;
|
||||
|
||||
while( (optind < argc) && (p = argv[optind++]) )
|
||||
{
|
||||
for( ; *p == '*'; p++ );
|
||||
|
||||
if( strcasecmp(p, "tsync") == 0 )
|
||||
{
|
||||
role = 0;
|
||||
opts.stype = SESSION_FTSC;
|
||||
}
|
||||
else if( strcasecmp(p, "yoohoo") == 0 )
|
||||
{
|
||||
role = 0;
|
||||
opts.stype = SESSION_YOOHOO;
|
||||
}
|
||||
else if( strcasecmp(p, "**EMSI_INQC816") == 0 )
|
||||
{
|
||||
role = 0;
|
||||
opts.stype = SESSION_EMSI;
|
||||
}
|
||||
else if( strncasecmp(p, "emsi", 4) == 0 )
|
||||
{
|
||||
role = 0;
|
||||
opts.stype = SESSION_EMSI;
|
||||
}
|
||||
else if( strcasecmp(p, "binkp") == 0 )
|
||||
{
|
||||
role = 0;
|
||||
opts.stype = SESSION_BINKP;
|
||||
}
|
||||
else if( strcasecmp(p, "auto") == 0 )
|
||||
{
|
||||
role = 0;
|
||||
opts.stype = SESSION_UNKNOWN;
|
||||
}
|
||||
else if( ftn_addrparse(&addr, p, FALSE) == 0 )
|
||||
{
|
||||
role = 1;
|
||||
(*alist) = (s_falist*)xmalloc(sizeof(s_falist));
|
||||
memset(*alist, '\0', sizeof(s_falist));
|
||||
(*alist)->addr = addr;
|
||||
alist = &(*alist)->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("invalid address \"%s\"", p);
|
||||
usage();
|
||||
exit(BFERR_FATALERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if( opts.dontcall && role == 0 )
|
||||
{
|
||||
usage();
|
||||
exit(BFERR_FATALERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/* if( (rc = log_open(log_getfilename(LOG_FILE_SESSION), NULL, NULL)) )
|
||||
{
|
||||
log("can't continue without logging");
|
||||
gotoexit(BFERR_FATALERROR);
|
||||
}
|
||||
*/
|
||||
/* Process primary config file */
|
||||
if( opts.confname && *opts.confname )
|
||||
rc = conf_readconf(opts.confname, 0);
|
||||
else
|
||||
rc = conf_readconf(conf_getconfname(), 0);
|
||||
|
||||
if( rc ) gotoexit(BFERR_FATALERROR);
|
||||
|
||||
/* Process additional config file, ignore errors */
|
||||
if( opts.incname && *opts.incname )
|
||||
(void)conf_readconf(opts.incname, 1);
|
||||
|
||||
/* Reopen log file if it was defined in config */
|
||||
if( log_open(log_getfilename(LOG_FILE_SESSION), NULL, NULL) )
|
||||
{
|
||||
log("can't continue without logging");
|
||||
gotoexit(BFERR_FATALERROR);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Same for the debug file */
|
||||
(void)debug_setfilename(log_getfilename(LOG_FILE_DEBUG));
|
||||
#endif
|
||||
|
||||
if( opts.daemon )
|
||||
rc = bforce_daemon(&opts);
|
||||
else if( role )
|
||||
rc = bforce_master(&opts);
|
||||
else
|
||||
rc = bforce_slave(&opts);
|
||||
|
||||
exit:
|
||||
|
||||
deinit_conf();
|
||||
deinit_opts(&opts);
|
||||
|
||||
/* Shutdown logging services */
|
||||
if( log_isopened() ) log_close();
|
||||
#ifdef DEBUG
|
||||
if( debug_isopened() ) debug_close();
|
||||
#endif
|
||||
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
static void deinit_opts(s_bforce_opts *opts)
|
||||
{
|
||||
if( opts->confname ) free(opts->confname);
|
||||
if( opts->incname ) free(opts->incname);
|
||||
if( opts->phone ) free(opts->phone);
|
||||
if( opts->iaddr ) free(opts->iaddr);
|
||||
if( opts->connect ) free(opts->connect);
|
||||
if( opts->device ) free(opts->device);
|
||||
if( opts->addrlist ) deinit_falist(opts->addrlist);
|
||||
|
||||
memset(opts, '\0', sizeof(s_bforce_opts));
|
||||
}
|
||||
|
||||
135
source/bforce/conf_deinit.c
Normal file
135
source/bforce/conf_deinit.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
void deinit_conf(void)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
s_cval_entry *next;
|
||||
int i;
|
||||
|
||||
for( i = 0; bforce_config[i].name; i++ )
|
||||
{
|
||||
for( ptrl = bforce_config[i].data; ptrl; ptrl = next )
|
||||
{
|
||||
next = ptrl->next;
|
||||
deinit_cval_entry(ptrl, bforce_config[i].type);
|
||||
free(ptrl);
|
||||
}
|
||||
bforce_config[i].data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void deinit_cval_entry(s_cval_entry *dest, bforce_config_keyword type)
|
||||
{
|
||||
/*
|
||||
* Other config variables doesn't use allocated memory
|
||||
*/
|
||||
switch(type) {
|
||||
case CT_ADDRESS:
|
||||
case CT_NODELIST:
|
||||
case CT_PASSWORD:
|
||||
if( dest->d.falist.what )
|
||||
free(dest->d.falist.what);
|
||||
break;
|
||||
case CT_DOMAIN:
|
||||
deinit_domain(&dest->d.domain);
|
||||
break;
|
||||
case CT_DIALRESP:
|
||||
deinit_dialresp(&dest->d.dialresp);
|
||||
break;
|
||||
case CT_MODEMPORT:
|
||||
deinit_modemport(&dest->d.modemport);
|
||||
break;
|
||||
case CT_OVERRIDE:
|
||||
deinit_override(&dest->d.override);
|
||||
break;
|
||||
case CT_PATH:
|
||||
case CT_STRING:
|
||||
deinit_string(&dest->d.string);
|
||||
break;
|
||||
case CT_TRANSLATE:
|
||||
deinit_translate(&dest->d.translate);
|
||||
break;
|
||||
default:
|
||||
DEB((D_CONFIG, "deinit_cval_entry: type %d doesn't use dynamic memory",
|
||||
type));
|
||||
}
|
||||
}
|
||||
|
||||
void deinit_dialresp(s_dialresp *dest)
|
||||
{
|
||||
if( dest->mstr ) free(dest->mstr);
|
||||
}
|
||||
|
||||
void deinit_domain(s_domain *dest)
|
||||
{
|
||||
if( dest->domain ) free(dest->domain);
|
||||
if( dest->path ) free(dest->path);
|
||||
}
|
||||
|
||||
void deinit_expr(s_expr *dest)
|
||||
{
|
||||
if( dest->expr ) free(dest->expr);
|
||||
}
|
||||
|
||||
void deinit_falist(s_falist *dest)
|
||||
{
|
||||
s_falist *ptrl, *next;
|
||||
|
||||
for( ptrl = dest; ptrl; ptrl = next )
|
||||
{
|
||||
next = ptrl->next;
|
||||
if( ptrl->what ) free(ptrl->what);
|
||||
free(ptrl);
|
||||
}
|
||||
}
|
||||
|
||||
void deinit_modemport(s_modemport *dest)
|
||||
{
|
||||
if( dest->name ) free(dest->name);
|
||||
}
|
||||
|
||||
void deinit_override(s_override *dest)
|
||||
{
|
||||
s_override *ptrl, *next;
|
||||
|
||||
if( dest->sIpaddr ) free(dest->sIpaddr);
|
||||
if( dest->sPhone ) free(dest->sPhone);
|
||||
if( dest->sFlags ) free(dest->sFlags);
|
||||
for( ptrl = dest->hidden; ptrl; ptrl = next )
|
||||
{
|
||||
next = ptrl->hidden;
|
||||
if( ptrl->sIpaddr ) free(ptrl->sIpaddr);
|
||||
if( ptrl->sPhone ) free(ptrl->sPhone);
|
||||
if( ptrl->sFlags ) free(ptrl->sFlags);
|
||||
free(ptrl);
|
||||
}
|
||||
}
|
||||
|
||||
void deinit_string(s_string *dest)
|
||||
{
|
||||
if( dest->str ) free(dest->str);
|
||||
}
|
||||
|
||||
void deinit_translate(s_translate *dest)
|
||||
{
|
||||
if( dest->find ) free(dest->find);
|
||||
if( dest->repl ) free(dest->repl);
|
||||
}
|
||||
|
||||
108
source/bforce/conf_get.c
Normal file
108
source/bforce/conf_get.c
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
|
||||
s_cval_entry *conf_first(bforce_config_keyword keyword)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
for( ptrl = bforce_config[keyword].data; ptrl; ptrl = ptrl->next )
|
||||
if( !ptrl->expr.expr || eventexpr(&ptrl->expr) )
|
||||
return ptrl;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s_cval_entry *conf_next(s_cval_entry *ptrl)
|
||||
{
|
||||
ASSERT(ptrl);
|
||||
|
||||
for( ptrl = ptrl->next; ptrl; ptrl = ptrl->next )
|
||||
if( !ptrl->expr.expr || eventexpr(&ptrl->expr) )
|
||||
return ptrl;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool conf_boolean(bforce_config_keyword keyword)
|
||||
{
|
||||
s_cval_entry *ptrl = conf_first(keyword);
|
||||
|
||||
return ptrl ? ptrl->d.boolean.istrue : FALSE;
|
||||
}
|
||||
|
||||
mode_t conf_filemode(bforce_config_keyword keyword)
|
||||
{
|
||||
s_cval_entry *ptrl = conf_first(keyword);
|
||||
|
||||
return ptrl ? ptrl->d.filemode.mode : (mode_t)0;
|
||||
}
|
||||
|
||||
long conf_options(bforce_config_keyword keyword)
|
||||
{
|
||||
long result = 0L;
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
for( ptrl = conf_first(keyword); ptrl; ptrl = conf_next(ptrl) )
|
||||
result = ((~ptrl->d.options.mask) & result) | ptrl->d.options.value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
long conf_connlist(bforce_config_keyword keyword, long speed)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
for( ptrl = conf_first(keyword); ptrl; ptrl = conf_next(ptrl) )
|
||||
if( ptrl->d.connlist.speed == speed )
|
||||
return ptrl->d.connlist.value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *conf_string(bforce_config_keyword keyword)
|
||||
{
|
||||
s_cval_entry *ptrl = conf_first(keyword);
|
||||
|
||||
return ptrl ? ptrl->d.string.str : (char*)NULL;
|
||||
}
|
||||
|
||||
long conf_number(bforce_config_keyword keyword)
|
||||
{
|
||||
s_cval_entry *ptrl = conf_first(keyword);
|
||||
|
||||
return ptrl ? ptrl->d.number.num : (long)0L;
|
||||
}
|
||||
|
||||
s_override *conf_override(bforce_config_keyword keyword, s_faddr addr)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
for( ptrl = conf_first(keyword); ptrl; ptrl = conf_next(ptrl) )
|
||||
if( !ftn_addrcomp(ptrl->d.override.addr, addr) )
|
||||
return &ptrl->d.override;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s_tries *conf_tries(bforce_config_keyword keyword)
|
||||
{
|
||||
s_cval_entry *ptrl = conf_first(keyword);
|
||||
|
||||
return ptrl ? &ptrl->d.tries : NULL;
|
||||
}
|
||||
|
||||
997
source/bforce/conf_proc.c
Normal file
997
source/bforce/conf_proc.c
Normal file
@ -0,0 +1,997 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "outbound.h" /* Required only for ``proc_filebox()'' */
|
||||
|
||||
struct tab_options {
|
||||
const char *keystr;
|
||||
unsigned long value_no;
|
||||
unsigned long value_yes;
|
||||
} options[] = {
|
||||
{ "Zmodem", OPTIONS_NO_ZMODEM, 0 },
|
||||
{ "ZedZap", OPTIONS_NO_ZEDZAP, 0 },
|
||||
{ "DirZap", OPTIONS_NO_DIRZAP, 0 },
|
||||
{ "Janus", OPTIONS_NO_JANUS, 0 },
|
||||
{ "Hydra", OPTIONS_NO_HYDRA, 0 },
|
||||
{ "BinkP", OPTIONS_NO_BINKP, 0 },
|
||||
{ "TCP", OPTIONS_NO_TCP, 0 },
|
||||
{ "Chat", OPTIONS_NO_CHAT, 0 },
|
||||
{ "FTS1", OPTIONS_NO_FTS1, 0 },
|
||||
{ "YooHoo", OPTIONS_NO_YOOHOO, 0 },
|
||||
{ "EMSI", OPTIONS_NO_EMSI, 0 },
|
||||
{ "EMSI-II", OPTIONS_NO_EMSI_II, 0 },
|
||||
{ "Freqs", OPTIONS_NO_FREQS, 0 },
|
||||
{ "MailOnly", 0, OPTIONS_MAILONLY },
|
||||
{ "HoldXT" , 0, OPTIONS_HOLDXT },
|
||||
{ "HoldReq", 0, OPTIONS_HOLDREQ },
|
||||
{ "HoldAll", 0, OPTIONS_HOLDALL },
|
||||
{ "HoldHold", 0, OPTIONS_HOLDHOLD },
|
||||
{ "PickUp", OPTIONS_NO_PICKUP, 0 },
|
||||
{ "RH1", OPTIONS_NO_RH1, 0 },
|
||||
{ "Intro", OPTIONS_NO_INTRO, 0 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct tab_resptypes {
|
||||
const char *str;
|
||||
int value;
|
||||
int retv;
|
||||
} resptypes[] = {
|
||||
{ "Connect", RESPTYPE_CONNECT, 0 },
|
||||
{ "Busy", RESPTYPE_BUSY, 11 },
|
||||
{ "Nocarrier", RESPTYPE_NOCARRIER, 12 },
|
||||
{ "Nodialtone", RESPTYPE_NODIALTONE, 13 },
|
||||
{ "Noanswer", RESPTYPE_NOANSWER, 14 },
|
||||
{ "Error", RESPTYPE_ERROR, 15 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
#define CONF_KEY(name, type) { #name, type, NULL, cf_##name }
|
||||
#define CONF_END() { NULL, 0, NULL, 0 }
|
||||
|
||||
s_conf_entry bforce_config[BFORCE_NUMBER_OF_KEYWORDS+1] = {
|
||||
CONF_KEY(address, CT_ADDRESS),
|
||||
CONF_KEY(amiga_outbound_directory, CT_PATH),
|
||||
CONF_KEY(binkp_timeout, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle_crash, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle_direct, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle_immed, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle_modem, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle_normal, CT_NUMBER),
|
||||
CONF_KEY(daemon_circle_rescan, CT_NUMBER),
|
||||
CONF_KEY(daemon_maxclients_modem, CT_NUMBER),
|
||||
CONF_KEY(daemon_maxclients_tcpip, CT_NUMBER),
|
||||
CONF_KEY(daemon_pid_file, CT_STRING),
|
||||
CONF_KEY(delay_files_recv, CT_STRING),
|
||||
CONF_KEY(delay_files_send, CT_STRING),
|
||||
CONF_KEY(disable_aka_matching, CT_BOOLEAN),
|
||||
CONF_KEY(domain, CT_DOMAIN),
|
||||
CONF_KEY(emsi_FR_time, CT_STRING),
|
||||
CONF_KEY(emsi_OH_time, CT_STRING),
|
||||
CONF_KEY(emsi_slave_sends_nak, CT_BOOLEAN),
|
||||
CONF_KEY(filebox, CT_FILEBOX),
|
||||
CONF_KEY(filebox_directory, CT_PATH),
|
||||
CONF_KEY(flags, CT_STRING),
|
||||
CONF_KEY(flo_translate, CT_TRANSLATE),
|
||||
CONF_KEY(freq_alias_list, CT_STRING),
|
||||
CONF_KEY(freq_dir_list, CT_STRING),
|
||||
CONF_KEY(freq_ignore_masks, CT_STRING),
|
||||
CONF_KEY(freq_limit_number, CT_NUMBER),
|
||||
CONF_KEY(freq_limit_size, CT_NUMBER),
|
||||
CONF_KEY(freq_limit_time, CT_NUMBER),
|
||||
CONF_KEY(freq_min_speed, CT_NUMBER),
|
||||
CONF_KEY(freq_srif_command, CT_STRING),
|
||||
CONF_KEY(hide_our_aka, CT_ADDRESS),
|
||||
CONF_KEY(history_file, CT_STRING),
|
||||
CONF_KEY(hydra_options, CT_OPTIONS),
|
||||
CONF_KEY(hydra_mincps_recv, CT_CONNLIST),
|
||||
CONF_KEY(hydra_mincps_send, CT_CONNLIST),
|
||||
CONF_KEY(hydra_tx_window, CT_NUMBER),
|
||||
CONF_KEY(hydra_rx_window, CT_NUMBER),
|
||||
CONF_KEY(inbound_directory, CT_PATH),
|
||||
CONF_KEY(location, CT_STRING),
|
||||
CONF_KEY(log_file, CT_STRING),
|
||||
CONF_KEY(log_file_daemon, CT_STRING),
|
||||
CONF_KEY(max_speed, CT_NUMBER),
|
||||
CONF_KEY(maxtries, CT_TRIES),
|
||||
CONF_KEY(maxtries_nodial, CT_TRIES),
|
||||
CONF_KEY(maxtries_noansw, CT_TRIES),
|
||||
CONF_KEY(maxtries_noconn, CT_TRIES),
|
||||
CONF_KEY(maxtries_hshake, CT_TRIES),
|
||||
CONF_KEY(maxtries_sessions, CT_TRIES),
|
||||
CONF_KEY(min_cps_recv, CT_NUMBER),
|
||||
CONF_KEY(min_cps_send, CT_NUMBER),
|
||||
CONF_KEY(min_cps_time, CT_NUMBER),
|
||||
CONF_KEY(min_free_space, CT_NUMBER),
|
||||
CONF_KEY(min_speed_in, CT_NUMBER),
|
||||
CONF_KEY(min_speed_out, CT_NUMBER),
|
||||
CONF_KEY(mode_netmail, CT_FILEMODE),
|
||||
CONF_KEY(mode_arcmail, CT_FILEMODE),
|
||||
CONF_KEY(mode_request, CT_FILEMODE),
|
||||
CONF_KEY(mode_ticfile, CT_FILEMODE),
|
||||
CONF_KEY(mode_default, CT_FILEMODE),
|
||||
CONF_KEY(modem_can_send_break, CT_BOOLEAN),
|
||||
CONF_KEY(modem_dial_prefix, CT_STRING),
|
||||
CONF_KEY(modem_dial_suffix, CT_STRING),
|
||||
CONF_KEY(modem_dial_response, CT_DIALRESP),
|
||||
CONF_KEY(modem_hangup_command, CT_STRING),
|
||||
CONF_KEY(modem_port, CT_MODEMPORT),
|
||||
CONF_KEY(modem_reset_command, CT_STRING),
|
||||
CONF_KEY(modem_stat_command, CT_STRING),
|
||||
CONF_KEY(nodelist, CT_NODELIST),
|
||||
CONF_KEY(nodelist_directory, CT_PATH),
|
||||
CONF_KEY(nodial_flag, CT_STRING),
|
||||
CONF_KEY(override, CT_OVERRIDE),
|
||||
CONF_KEY(options, CT_OPTIONS),
|
||||
CONF_KEY(outbound_directory, CT_PATH),
|
||||
CONF_KEY(password, CT_PASSWORD),
|
||||
CONF_KEY(phone, CT_STRING),
|
||||
CONF_KEY(phone_translate, CT_TRANSLATE),
|
||||
CONF_KEY(recode_file_in, CT_STRING),
|
||||
CONF_KEY(recode_file_out, CT_STRING),
|
||||
CONF_KEY(recode_intro_in, CT_STRING),
|
||||
CONF_KEY(recv_buffer_size, CT_NUMBER),
|
||||
CONF_KEY(rescan_delay, CT_NUMBER),
|
||||
CONF_KEY(run_after_handshake, CT_STRING),
|
||||
CONF_KEY(run_after_session, CT_STRING),
|
||||
CONF_KEY(session_limit_in, CT_NUMBER),
|
||||
CONF_KEY(session_limit_out, CT_NUMBER),
|
||||
CONF_KEY(skip_files_recv, CT_STRING),
|
||||
CONF_KEY(status_directory, CT_PATH),
|
||||
CONF_KEY(system_name, CT_STRING),
|
||||
CONF_KEY(sysop_name, CT_STRING),
|
||||
CONF_KEY(uucp_lock_directory, CT_PATH),
|
||||
CONF_KEY(wait_carrier_in, CT_NUMBER),
|
||||
CONF_KEY(wait_carrier_out, CT_NUMBER),
|
||||
CONF_KEY(zmodem_mincps_recv, CT_CONNLIST),
|
||||
CONF_KEY(zmodem_mincps_send, CT_CONNLIST),
|
||||
CONF_KEY(zmodem_send_dummy_pkt, CT_BOOLEAN),
|
||||
CONF_KEY(zmodem_skip_by_pos, CT_BOOLEAN),
|
||||
CONF_KEY(zmodem_start_block_size, CT_NUMBER),
|
||||
CONF_KEY(zmodem_tx_window, CT_NUMBER),
|
||||
CONF_KEY(nomail_flag, CT_STRING),
|
||||
CONF_KEY(bind_ip, CT_STRING),
|
||||
#ifdef USE_SYSLOG
|
||||
CONF_KEY(syslog_facility, CT_NUMBER),
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
CONF_KEY(debug_file, CT_STRING),
|
||||
CONF_KEY(debug_level, CT_DEBLEVEL),
|
||||
#endif
|
||||
CONF_END()
|
||||
};
|
||||
|
||||
static int proc_override(s_override *dest, char *value);
|
||||
static int proc_options(s_options *options, char *value);
|
||||
static int proc_string(s_string *dest, char *value);
|
||||
static int proc_number(s_number *dest, char *value);
|
||||
static int proc_filemode(s_filemode *dest, char *value);
|
||||
static int proc_boolean(s_boolean *dest, char *value);
|
||||
static int proc_address(s_falist *dest, char *value);
|
||||
static int proc_nodelist(s_falist *dest, char *value);
|
||||
static int proc_modemport(s_modemport *dest, char *value);
|
||||
static int proc_domain(s_domain *dest, char *value);
|
||||
static int proc_password(s_falist *dest, char *value);
|
||||
static int proc_path(s_string *dest, char *value);
|
||||
static int proc_dialresp(s_dialresp *dest, char *value);
|
||||
static int proc_translate(s_translate *dest, char *value);
|
||||
static int proc_speeddep(s_connlist *dest, char *value);
|
||||
static int proc_tries(s_tries *dest, char *value);
|
||||
#ifdef DEBUG
|
||||
static int proc_debuglevel(s_number *dest, char *value);
|
||||
#endif
|
||||
static int proc_filebox(s_filebox *dest, char *value);
|
||||
|
||||
static int append_config_entry(s_conf_entry *conf_ent, s_cval_entry *cval_entry)
|
||||
{
|
||||
s_cval_entry **ptrl;
|
||||
|
||||
for( ptrl = &conf_ent->data; *ptrl; ptrl = &(*ptrl)->next );
|
||||
|
||||
*ptrl = (s_cval_entry *)xmalloc(sizeof(s_cval_entry));
|
||||
memcpy(*ptrl, cval_entry, sizeof(s_cval_entry));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int proc_configline(const char *k, const char *e, const char *v)
|
||||
{
|
||||
s_cval_entry temp_value;
|
||||
int rc = PROC_RC_ABORT;
|
||||
int i;
|
||||
char *copy;
|
||||
|
||||
ASSERT(k != NULL && v != NULL );
|
||||
|
||||
DEB((D_CONFIG, "conf_proc: key \"%s\" expr \"%s\" value \"%s\"",
|
||||
k, e, v));
|
||||
|
||||
copy = xstrcpy(v);
|
||||
|
||||
for( i = 0; bforce_config[i].name; i++ )
|
||||
if( !strcmp(bforce_config[i].name, k) )
|
||||
break;
|
||||
|
||||
if( bforce_config[i].name )
|
||||
{
|
||||
/*
|
||||
* Make all changes in temp_value structure
|
||||
*/
|
||||
memset(&temp_value, '\0', sizeof(s_cval_entry));
|
||||
|
||||
switch(bforce_config[i].type) {
|
||||
case CT_ADDRESS:
|
||||
rc = proc_address(&temp_value.d.falist, copy);
|
||||
break;
|
||||
case CT_BOOLEAN:
|
||||
rc = proc_boolean(&temp_value.d.boolean, copy);
|
||||
break;
|
||||
case CT_CONNLIST:
|
||||
rc = proc_speeddep(&temp_value.d.connlist, copy);
|
||||
break;
|
||||
case CT_DIALRESP:
|
||||
rc = proc_dialresp(&temp_value.d.dialresp, copy);
|
||||
break;
|
||||
case CT_DOMAIN:
|
||||
rc = proc_domain(&temp_value.d.domain, copy);
|
||||
break;
|
||||
case CT_FILEMODE:
|
||||
rc = proc_filemode(&temp_value.d.filemode, copy);
|
||||
break;
|
||||
case CT_MODEMPORT:
|
||||
rc = proc_modemport(&temp_value.d.modemport, copy);
|
||||
break;
|
||||
case CT_NODELIST:
|
||||
rc = proc_nodelist(&temp_value.d.falist, copy);
|
||||
break;
|
||||
case CT_NUMBER:
|
||||
rc = proc_number(&temp_value.d.number, copy);
|
||||
break;
|
||||
case CT_OPTIONS:
|
||||
rc = proc_options(&temp_value.d.options, copy);
|
||||
break;
|
||||
case CT_OVERRIDE:
|
||||
rc = proc_override(&temp_value.d.override, copy);
|
||||
break;
|
||||
case CT_PATH:
|
||||
rc = proc_path(&temp_value.d.string, copy);
|
||||
break;
|
||||
case CT_PASSWORD:
|
||||
rc = proc_password(&temp_value.d.falist, copy);
|
||||
break;
|
||||
case CT_STRING:
|
||||
rc = proc_string(&temp_value.d.string, copy);
|
||||
break;
|
||||
case CT_TRANSLATE:
|
||||
rc = proc_translate(&temp_value.d.translate, copy);
|
||||
break;
|
||||
case CT_TRIES:
|
||||
rc = proc_tries(&temp_value.d.tries, copy);
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case CT_DEBLEVEL:
|
||||
rc = proc_debuglevel(&temp_value.d.number, copy);
|
||||
break;
|
||||
#endif
|
||||
case CT_FILEBOX:
|
||||
rc = proc_filebox(&temp_value.d.filebox, copy);
|
||||
break;
|
||||
default:
|
||||
log("internal error, unknown keyword type = %d",
|
||||
bforce_config[i].type);
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
if( rc == PROC_RC_OK || rc == PROC_RC_WARN )
|
||||
{
|
||||
if( e && *e )
|
||||
{
|
||||
temp_value.expr.expr = xstrcpy(e);
|
||||
temp_value.expr.error = 0;
|
||||
}
|
||||
append_config_entry(&bforce_config[i], &temp_value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("unknown keyword \"%s\"", k);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
|
||||
free(copy);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: Override <Address> <Overrides..> [Hidden <Overrides>]
|
||||
*/
|
||||
static int proc_override(s_override *dest, char *value)
|
||||
{
|
||||
s_override **p = &dest;
|
||||
s_faddr addr;
|
||||
int rc = PROC_RC_OK;
|
||||
char *key = NULL;
|
||||
char *arg = NULL;
|
||||
char *n = NULL;
|
||||
char *p_addr = NULL;
|
||||
bool neednew = FALSE;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_addr = string_token(value, &n, NULL, 0);
|
||||
if( p_addr == NULL || *p_addr == '\0' || ftn_addrparse(&addr, p_addr, FALSE) )
|
||||
return(PROC_RC_IGNORE);
|
||||
|
||||
memset(dest, '\0', sizeof(s_override));
|
||||
dest->addr = addr;
|
||||
|
||||
while( key || (key = string_token(NULL, &n, NULL, 1)) )
|
||||
{
|
||||
if( (arg = string_token(NULL, &n, NULL, 1)) == NULL || *arg == '\0' )
|
||||
{
|
||||
log("no argument(s) for override \"%s\"", key);
|
||||
if( rc < PROC_RC_WARN )
|
||||
rc = PROC_RC_WARN;
|
||||
break;
|
||||
}
|
||||
|
||||
if( neednew )
|
||||
{
|
||||
(*p) = (s_override*)xmalloc(sizeof(s_override));
|
||||
memset(*p, '\0', sizeof(s_override));
|
||||
(*p)->addr = addr;
|
||||
neednew = FALSE;
|
||||
}
|
||||
|
||||
if( strcasecmp(key, "phone") == 0 )
|
||||
{
|
||||
if( (*p)->sPhone )
|
||||
free((*p)->sPhone);
|
||||
(*p)->sPhone = xstrcpy(arg);
|
||||
key = NULL;
|
||||
}
|
||||
else if( strcasecmp(key, "ipaddr") == 0 )
|
||||
{
|
||||
if( (*p)->sIpaddr )
|
||||
free((*p)->sIpaddr);
|
||||
(*p)->sIpaddr = xstrcpy(arg);
|
||||
key = NULL;
|
||||
}
|
||||
else if( strcasecmp(key, "worktime") == 0 )
|
||||
{
|
||||
if( timevec_parse_list(&((*p)->worktime), arg) == -1 )
|
||||
{
|
||||
log("invalid work time \"%s\"", arg);
|
||||
if( rc < PROC_RC_WARN )
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
key = NULL;
|
||||
}
|
||||
else if( strcasecmp(key, "freqtime") == 0 )
|
||||
{
|
||||
if( timevec_parse_list(&((*p)->freqtime), arg) == -1 )
|
||||
{
|
||||
log("invalid freq time \"%s\"", arg);
|
||||
if( rc < PROC_RC_WARN )
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
key = NULL;
|
||||
}
|
||||
else if( strcasecmp(key, "flags") == 0 )
|
||||
{
|
||||
if( (*p)->sFlags )
|
||||
free((*p)->sFlags);
|
||||
(*p)->sFlags = xstrcpy(arg);
|
||||
key = NULL;
|
||||
}
|
||||
else if( strcasecmp(key, "hidden") == 0 )
|
||||
{
|
||||
neednew = TRUE;
|
||||
p = &((*p)->hidden);
|
||||
key = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("unknown keyword \"%s\" in override", key);
|
||||
if( rc < PROC_RC_WARN )
|
||||
rc = PROC_RC_WARN;
|
||||
key = arg;
|
||||
}
|
||||
}
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: Options <options..>
|
||||
*/
|
||||
static int proc_options(s_options *dest, char *value)
|
||||
{
|
||||
int i, rc = PROC_RC_OK;
|
||||
char *key = NULL, *n = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
for( key = string_token(value, &n, NULL, 0); key;
|
||||
key = string_token(NULL, &n, NULL, 0) )
|
||||
{
|
||||
for( i = 0; options[i].keystr; i++ )
|
||||
{
|
||||
if( strcasecmp(key, options[i].keystr) == 0 )
|
||||
{
|
||||
if( options[i].value_no )
|
||||
{
|
||||
dest->value &= ~options[i].value_no;
|
||||
dest->mask |= options[i].value_no;
|
||||
}
|
||||
if( options[i].value_yes )
|
||||
{
|
||||
dest->value |= options[i].value_yes;
|
||||
dest->mask |= options[i].value_yes;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if( options[i].value_no == 0 && options[i].value_yes == 0 )
|
||||
ASSERT_MSG();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else if( (strncasecmp(key, "no", 2) == 0
|
||||
&& strcasecmp(key+2, options[i].keystr) == 0)
|
||||
|| (*key == '!'
|
||||
&& strcasecmp(key+1, options[i].keystr) == 0) )
|
||||
{
|
||||
if( options[i].value_no )
|
||||
{
|
||||
dest->value |= options[i].value_no;
|
||||
dest->mask |= options[i].value_no;
|
||||
}
|
||||
if( options[i].value_yes )
|
||||
{
|
||||
dest->value &= ~options[i].value_yes;
|
||||
dest->mask |= options[i].value_yes;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if( !options[i].value_no && !options[i].value_yes )
|
||||
ASSERT_MSG();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !options[i].keystr )
|
||||
{
|
||||
log("unknown option \"%s\"", key);
|
||||
if( rc < PROC_RC_WARN )
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
}
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Any value>
|
||||
*/
|
||||
static int proc_string(s_string *dest, char *value)
|
||||
{
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
dest->str = xstrcpy(value);
|
||||
|
||||
return PROC_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Number>
|
||||
*/
|
||||
static int proc_number(s_number *dest, char *value)
|
||||
{
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
if( !ISDEC(value) )
|
||||
{
|
||||
log("value \"%s\" isn't numeric", value);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
dest->num = atol(value);
|
||||
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Octal permissions>
|
||||
*/
|
||||
static int proc_filemode(s_filemode *dest, char *value)
|
||||
{
|
||||
int rc = PROC_RC_OK;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
if( !ISOCT(value) )
|
||||
{
|
||||
log("value \"%s\" isn't octal number", value);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
sscanf(value, "%o", (unsigned int *)&dest->mode);
|
||||
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Yes|No|True|False>
|
||||
*/
|
||||
static int proc_boolean(s_boolean *dest, char *value)
|
||||
{
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
if( !strcasecmp(value, "yes")
|
||||
|| !strcasecmp(value, "true") )
|
||||
{
|
||||
dest->istrue = 1;
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
else if( !strcasecmp(value, "no")
|
||||
|| !strcasecmp(value, "false") )
|
||||
{
|
||||
dest->istrue = 0;
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
log("unexpected argument \"%s\", must be \"Yes\" or \"No\"", value);
|
||||
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <FTN address|Inet address>
|
||||
*/
|
||||
static int proc_address(s_falist *dest, char *value)
|
||||
{
|
||||
s_faddr addr;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
if( ftn_addrparse(&addr, value, FALSE) )
|
||||
{
|
||||
log("can't parse address \"%s\"", value);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
dest->addr = addr;
|
||||
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <File name> <Address>
|
||||
*/
|
||||
static int proc_nodelist(s_falist *dest, char *value)
|
||||
{
|
||||
s_faddr addr;
|
||||
char *n = NULL;
|
||||
char *p_name = NULL;
|
||||
char *p_addr = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_name = string_token(value, &n, NULL, 1);
|
||||
p_addr = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_name && *p_name && p_addr && *p_addr )
|
||||
{
|
||||
if( ftn_addrparse(&addr, p_addr, TRUE) == 0 )
|
||||
{
|
||||
dest->addr = addr;
|
||||
dest->what = xstrcpy(p_name);
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("can't parse address \"%s\"", p_addr);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
}
|
||||
|
||||
log("incorrect nodelist specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <domain> <path> <zone>
|
||||
*/
|
||||
static int proc_domain(s_domain *dest, char *value)
|
||||
{
|
||||
char *n = NULL;
|
||||
char *p_domn = NULL;
|
||||
char *p_path = NULL;
|
||||
char *p_zone = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_domn = string_token(value, &n, NULL, 1);
|
||||
p_path = string_token(NULL, &n, NULL, 1);
|
||||
p_zone = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_domn && *p_domn && p_path && *p_path && p_zone && *p_zone )
|
||||
{
|
||||
if( ISDEC(p_zone) )
|
||||
{
|
||||
dest->domain = xstrcpy(p_domn);
|
||||
dest->zone = atoi(p_zone);
|
||||
if( p_path[strlen(p_path)-1] == DIRSEPCHR )
|
||||
dest->path = xstrcpy(p_path);
|
||||
else
|
||||
dest->path = string_concat(p_path, DIRSEPSTR, NULL);
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("zone isn't numeric value in domain specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
}
|
||||
|
||||
log("incorrect domain specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <port>[:<lockspeed>]
|
||||
*/
|
||||
static int proc_modemport(s_modemport *dest, char *value)
|
||||
{
|
||||
char *p_speed = NULL;
|
||||
long speed = 0;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_speed = strrchr(value, ':');
|
||||
|
||||
if( p_speed ) {
|
||||
if( ISDEC(p_speed+1) )
|
||||
{
|
||||
p_speed[0] = '\0';
|
||||
speed = atol(p_speed+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("incorrect modem port \"%s\": bad lock speed", value);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
}
|
||||
|
||||
dest->name = xstrcpy(value);
|
||||
dest->speed = speed;
|
||||
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Address> <Password>
|
||||
*/
|
||||
static int proc_password(s_falist *dest, char *value)
|
||||
{
|
||||
s_faddr addr;
|
||||
char *n = NULL;
|
||||
char *p_addr = NULL;
|
||||
char *p_passwd = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_addr = string_token(value, &n, NULL, 1);
|
||||
p_passwd = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_addr && *p_addr && p_passwd && *p_passwd )
|
||||
{
|
||||
if( ftn_addrparse(&addr, p_addr, FALSE) == 0 )
|
||||
{
|
||||
dest->addr = addr;
|
||||
dest->what = xstrcpy(p_passwd);
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("can't parse address \"%s\"", value);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
}
|
||||
|
||||
log("incorrect password specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Path>
|
||||
*/
|
||||
static int proc_path(s_string *dest, char *value)
|
||||
{
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
if( value[strlen(value)-1] == DIRSEPCHR )
|
||||
dest->str = xstrcpy(value);
|
||||
else
|
||||
dest->str = string_concat(value, DIRSEPSTR, NULL);
|
||||
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <<String1[:RC]> [String2[:RC]] ..>
|
||||
*/
|
||||
static int proc_dialresp(s_dialresp *dest, char *value)
|
||||
{
|
||||
int i;
|
||||
char *n = NULL;
|
||||
char *p_mstr = NULL;
|
||||
char *p_type = NULL;
|
||||
char *p_retv = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_mstr = string_token(value, &n, NULL, 1);
|
||||
p_type = string_token(NULL, &n, NULL, 1);
|
||||
p_retv = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_mstr && *p_mstr && p_type && *p_type )
|
||||
{
|
||||
if( p_retv && !ISDEC(p_retv) )
|
||||
{
|
||||
log("return code isn't numeric in modem response specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
for( i = 0; resptypes[i].str; i++ )
|
||||
if( strcasecmp(p_type, resptypes[i].str) == 0 )
|
||||
break;
|
||||
|
||||
if( resptypes[i].str )
|
||||
{
|
||||
dest->mstr = xstrcpy(p_mstr);
|
||||
dest->type = resptypes[i].value;
|
||||
dest->retv = p_retv ? atoi(p_retv) : resptypes[i].retv;
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
log("unknown response type \"%s\"", p_type);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
log("incorrect modem response specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Search value> <Replace value>
|
||||
*/
|
||||
static int proc_translate(s_translate *dest, char *value)
|
||||
{
|
||||
char *n = NULL;
|
||||
char *p_find = NULL;
|
||||
char *p_repl = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_find = string_token(value, &n, NULL, 1);
|
||||
p_repl = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_find && *p_find )
|
||||
{
|
||||
dest->find = xstrcpy(p_find);
|
||||
if( p_repl )
|
||||
dest->repl = xstrcpy(p_repl);
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
|
||||
log("incorrect translation rule specification");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Connect speed> <Number>
|
||||
*/
|
||||
static int proc_speeddep(s_connlist *dest, char *value)
|
||||
{
|
||||
char *n = NULL;
|
||||
char *p_speed = NULL;
|
||||
char *p_value = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_speed = string_token(value, &n, NULL, 1);
|
||||
p_value = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_speed && *p_speed && p_value && *p_value )
|
||||
{
|
||||
if( ISDEC(p_speed) && ISDEC(p_value) )
|
||||
{
|
||||
dest->speed = atoi(p_speed);
|
||||
dest->value = atoi(p_value);
|
||||
return(PROC_RC_OK);
|
||||
}
|
||||
log("non-numeric value \"%s\" or \"%s\"", p_speed, p_value);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
log("incorrect speed dependent config string");
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Tries number> [<Action> <Action argument(s)>]
|
||||
*/
|
||||
static int proc_tries(s_tries *dest, char *value)
|
||||
{
|
||||
int rc = PROC_RC_OK;
|
||||
char *n = NULL;
|
||||
char *p_tries = NULL;
|
||||
char *p_action = NULL;
|
||||
char *p_arg = NULL;
|
||||
int action = TRIES_ACTION_UNDIALABLE;
|
||||
int arg = 0;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_tries = string_token(value, &n, NULL, 0);
|
||||
p_action = string_token(NULL, &n, NULL, 0);
|
||||
p_arg = string_token(NULL, &n, NULL, 0);
|
||||
|
||||
if( p_tries && *p_tries && ISDEC(p_tries) )
|
||||
{
|
||||
if( p_action && *p_action )
|
||||
{
|
||||
if( strcasecmp(p_action, "undialable") == 0 )
|
||||
{
|
||||
if( p_arg && *p_arg )
|
||||
{
|
||||
log("no argument needed for action 'undialable'");
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
action = TRIES_ACTION_UNDIALABLE;
|
||||
arg = 0;
|
||||
}
|
||||
else if( strcasecmp(p_action, "hold") == 0 )
|
||||
{
|
||||
if( p_arg && *p_arg && !ISDEC(p_arg) )
|
||||
{
|
||||
log("non-numeric argument for action 'hold'");
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
else if( p_arg == NULL )
|
||||
{
|
||||
log("no argument for action 'hold'");
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
action = TRIES_ACTION_HOLDSYSTEM;
|
||||
arg = atoi(p_arg);
|
||||
}
|
||||
else if( strcasecmp(p_action, "holdall") == 0 )
|
||||
{
|
||||
if( p_arg && *p_arg && !ISDEC(p_arg) )
|
||||
{
|
||||
log("non-numeric argument for action 'holdall'");
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
else if( p_arg == NULL )
|
||||
{
|
||||
log("no argument for action 'holdall'");
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
action = TRIES_ACTION_HOLDALL;
|
||||
arg = atoi(p_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("unknown action '%s'", p_action);
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
}
|
||||
dest->tries = atoi(p_tries);
|
||||
dest->action = action;
|
||||
dest->arg = arg;
|
||||
return(rc);
|
||||
}
|
||||
|
||||
log("non-numeric tries number \"%s\"", p_tries);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Line format: DebugLevel <Level> [<Level>]..
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
static int proc_debuglevel(s_number *dest, char *value)
|
||||
{
|
||||
int rc = PROC_RC_OK;
|
||||
long deblevel = 0L;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
if( debug_parsestring(value, &deblevel) ) rc = PROC_RC_WARN;
|
||||
|
||||
dest->num = deblevel;
|
||||
|
||||
return(rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Line format: <Keyword> <Directory> <Address>
|
||||
*/
|
||||
static int proc_filebox(s_filebox *dest, char *value)
|
||||
{
|
||||
s_faddr addr;
|
||||
char *n = NULL;
|
||||
char *p_path = NULL;
|
||||
char *p_addr = NULL;
|
||||
char *p_flav = NULL;
|
||||
|
||||
ASSERT(dest != NULL && value != NULL);
|
||||
|
||||
p_path = string_token(value, &n, NULL, 1);
|
||||
p_addr = string_token(NULL, &n, NULL, 1);
|
||||
p_flav = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
if( p_path && *p_path && p_addr && *p_addr )
|
||||
{
|
||||
if( ftn_addrparse(&addr, p_addr, TRUE) == 0 )
|
||||
{
|
||||
int flavor = FLAVOR_HOLD;
|
||||
int rc = PROC_RC_OK;
|
||||
|
||||
if( !is_directory(p_path) )
|
||||
{
|
||||
log("filebox directory \"%s\" doesn't exist", p_path);
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
if( p_flav && *p_flav )
|
||||
{
|
||||
if( strcasecmp(p_flav, "hold") == 0 )
|
||||
flavor = FLAVOR_HOLD;
|
||||
else if( strcasecmp(p_flav, "normal") == 0 )
|
||||
flavor = FLAVOR_NORMAL;
|
||||
else if( strcasecmp(p_flav, "crash") == 0 )
|
||||
flavor = FLAVOR_CRASH;
|
||||
else if( strcasecmp(p_flav, "immediate") == 0 )
|
||||
flavor = FLAVOR_IMMED;
|
||||
else
|
||||
{
|
||||
log("unknown filebox flavor \"%s\"", p_flav);
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
}
|
||||
dest->addr = addr;
|
||||
if( p_path[strlen(p_path)-1] == DIRSEPCHR )
|
||||
dest->path = xstrcpy(p_path);
|
||||
else
|
||||
dest->path = string_concat(p_path, DIRSEPSTR, NULL);
|
||||
dest->flavor = flavor;
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("can't parse address \"%s\"", p_addr);
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
}
|
||||
|
||||
log("incorrect filebox specification");
|
||||
return PROC_RC_IGNORE;
|
||||
}
|
||||
457
source/bforce/conf_read.c
Normal file
457
source/bforce/conf_read.c
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
|
||||
#define COMMENTCHR '#'
|
||||
#define PREPROCCHR '$'
|
||||
#define ESCAPECHR '\\'
|
||||
|
||||
int conf_postreadcheck(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *conf_getconfname(void)
|
||||
{
|
||||
const char *name = getenv("BFCONFIG");
|
||||
if( name == NULL || *name == '\0' ) name = BFORCE_CFGFILE;
|
||||
return(name);
|
||||
}
|
||||
|
||||
int conf_readpasswdlist(s_falist **pwdlist, char *fname)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare config string for parsing, check for comments
|
||||
* Return: zero - good string, non-zero - .. (you know)
|
||||
*/
|
||||
static int conf_checkstr(char *str)
|
||||
{
|
||||
int rc = 0;
|
||||
char *p = NULL;
|
||||
|
||||
ASSERT(str != NULL);
|
||||
|
||||
if( isspace(*str) ) string_trimleft(str);
|
||||
if( *str == '\0' || *str == COMMENTCHR )
|
||||
{ rc = 1; }
|
||||
|
||||
if( (p = strrchr(str, COMMENTCHR)) && *(p-1) != ESCAPECHR )
|
||||
{ *p = '\0'; }
|
||||
|
||||
string_trimright(str);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse config string on: keyword, expression and value
|
||||
* Return: zero - no errors, non-zero - incorrect syntax
|
||||
*/
|
||||
static void conf_parsestr(char *str, char **key, char **expr, char **value)
|
||||
{
|
||||
char *k = NULL; /* Keyword */
|
||||
char *e = NULL; /* Expression */
|
||||
char *v = NULL; /* Value */
|
||||
char *p = NULL;
|
||||
int brackets = 0;
|
||||
|
||||
ASSERT(str != NULL && key != NULL && expr != NULL && value != NULL);
|
||||
|
||||
*key = NULL; *expr = NULL; *value = NULL;
|
||||
|
||||
/* Get config keyword */
|
||||
k = str;
|
||||
while( isspace(*k) ) k++;
|
||||
p = k;
|
||||
while( !isspace(*p) && *p ) p++;
|
||||
if( *p == '\0' )
|
||||
{ *key = k; return; }
|
||||
*p++ = '\0';
|
||||
|
||||
while( isspace(*p) ) p++;
|
||||
v = p;
|
||||
|
||||
/* Get config expression (if specified) */
|
||||
if( *p == '(' )
|
||||
{
|
||||
++p;
|
||||
while( isspace(*p) ) p++;
|
||||
for( e = p, brackets = 1; brackets > 0 && *p; )
|
||||
{
|
||||
if( *(p-1) != ESCAPECHR )
|
||||
{
|
||||
switch( *p ) {
|
||||
case '(':
|
||||
++brackets; break;
|
||||
case ')':
|
||||
--brackets; break;
|
||||
}
|
||||
}
|
||||
if( brackets > 0 ) ++p;
|
||||
}
|
||||
if( *p != ')' ) return; /* No closing bracket */
|
||||
/* Remove trailing spaces */
|
||||
v = p--;
|
||||
while( p > e && isspace(*p) ) *p-- = '\0';
|
||||
*v++ = '\0';
|
||||
}
|
||||
|
||||
/* Get config value */
|
||||
while( isspace(*v) ) v++;
|
||||
if( *v == '\0' )
|
||||
{ *key = k; *expr = e; return; }
|
||||
/* Remove trailing spaces */
|
||||
p = v + strlen(v+1);
|
||||
while( p > v && isspace(*p) ) *p-- = '\0';
|
||||
|
||||
/* Return information to function caller */
|
||||
*key = k;
|
||||
*expr = e;
|
||||
*value = v;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int conf_readconf(const char *confname, int inclevel)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
char tmp[BF_MAXCFGLINE + 1];
|
||||
int rc, maxrc = 0;
|
||||
int line = 0;
|
||||
char *fullstr = NULL; /* Result of strings concatenation */
|
||||
char *value = NULL;
|
||||
char *expr = NULL;
|
||||
char *p_key = NULL;
|
||||
char *p_expr = NULL;
|
||||
char *p_value = NULL;
|
||||
char *p = NULL;
|
||||
char *ifexpr = NULL; /* Pointer to the `common' block expression */
|
||||
bool isappend = FALSE; /* Append new string to the previous? */
|
||||
bool isifexpr = FALSE; /* We are in `common' config block! */
|
||||
|
||||
if( inclevel == 0 )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Check config table correctness */
|
||||
for( i = 0; bforce_config[i].name; i++ )
|
||||
{
|
||||
if( i != (int)bforce_config[i].real_key )
|
||||
{
|
||||
log("invalid config table: found %d instead of %d",
|
||||
bforce_config[i].real_key, i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( (fp = file_open(confname,"r")) == NULL )
|
||||
{
|
||||
logerr("can't open config file \"%s\"", confname);
|
||||
return(PROC_RC_IGNORE);
|
||||
}
|
||||
|
||||
DEB((D_CONFIG, "readconfig: start reading config \"%s\"", confname));
|
||||
|
||||
while( fgets(tmp, sizeof(tmp), fp) )
|
||||
{
|
||||
++line;
|
||||
string_chomp(tmp);
|
||||
|
||||
if( conf_checkstr(tmp) )
|
||||
{
|
||||
if( isifexpr )
|
||||
{
|
||||
log("warning: automatically close expression at empty line %d", line);
|
||||
if( ifexpr ) { free(ifexpr); ifexpr = NULL; }
|
||||
isifexpr = FALSE;
|
||||
}
|
||||
|
||||
if( !isappend )
|
||||
continue;
|
||||
|
||||
log("warning: appending empty or comment line %d", line);
|
||||
isappend = FALSE;
|
||||
}
|
||||
|
||||
p = tmp + strlen(tmp+1);
|
||||
|
||||
if( *p == '\\' && *(p-1) != ESCAPECHR )
|
||||
{
|
||||
*p = '\0';
|
||||
if( fullstr && isappend )
|
||||
{
|
||||
fullstr = xstrcat(fullstr, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fullstr ) free(fullstr);
|
||||
fullstr = xstrcpy(tmp);
|
||||
isappend = TRUE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if( isappend )
|
||||
{
|
||||
if( fullstr )
|
||||
{ fullstr = xstrcat(fullstr, tmp); }
|
||||
else
|
||||
{ ASSERT_MSG(); }
|
||||
isappend = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have string without comments
|
||||
* and trailing/leading spaces in:
|
||||
* - if single string than in $tmp[]
|
||||
* - if concatanated strings than look $fullstr
|
||||
*/
|
||||
|
||||
p_key = NULL;
|
||||
p_expr = NULL;
|
||||
p_value = NULL;
|
||||
|
||||
conf_parsestr(fullstr ? fullstr : tmp, &p_key, &p_expr, &p_value);
|
||||
|
||||
DEB((D_CONFIG, "conf_readconf: [%d] key \"%s\" expr \"%s\" value \"%s\"",
|
||||
line, p_key, p_expr, p_value));
|
||||
|
||||
if( p_value )
|
||||
{
|
||||
value = xstrcpy(p_value);
|
||||
string_dequote(value, p_value);
|
||||
}
|
||||
|
||||
if( p_expr )
|
||||
{
|
||||
expr = xstrcpy(p_expr);
|
||||
string_dequote(expr, p_expr);
|
||||
}
|
||||
|
||||
if( p_key && *p_key == PREPROCCHR )
|
||||
{
|
||||
/* Preprocessor directives */
|
||||
|
||||
rc = PROC_RC_OK;
|
||||
|
||||
if( strcasecmp(p_key+1, "include") == 0 )
|
||||
{
|
||||
if( value == NULL || expr )
|
||||
{
|
||||
log("incorrect usage of `%s' directive", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else if( inclevel < MAXINCLUDELEVEL )
|
||||
{
|
||||
DEB((D_CONFIG, "conf_readconf: process inlude file \"%s\"", value));
|
||||
rc = conf_readconf(value, inclevel + 1);
|
||||
if( rc ) rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEB((D_CONFIG, "conf_readconf: too deep include"));
|
||||
log("including level too deep");
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
}
|
||||
else if( strcasecmp(p_key+1, "ifexp") == 0 )
|
||||
{
|
||||
if( value || isifexpr )
|
||||
{
|
||||
log("incorrect usage of `%s' directive", p_key);
|
||||
rc = PROC_RC_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ifexpr )
|
||||
{ free(ifexpr); ifexpr = NULL; }
|
||||
if( expr )
|
||||
ifexpr = xstrcpy(expr);
|
||||
isifexpr = TRUE;
|
||||
}
|
||||
}
|
||||
else if( strcasecmp(p_key+1, "endif") == 0 )
|
||||
{
|
||||
if( value || expr || !isifexpr )
|
||||
{
|
||||
log("incorrect usage of `%s' directive", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ifexpr ) { free(ifexpr); ifexpr = NULL; }
|
||||
isifexpr = FALSE;
|
||||
}
|
||||
}
|
||||
else if( strcasecmp(p_key+1, "logfile") == 0 )
|
||||
{
|
||||
if( value == NULL || expr )
|
||||
{
|
||||
log("incorrect usage of `%s' directive", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( log_reopen(value, NULL, NULL) )
|
||||
{
|
||||
log("can't continue without logging");
|
||||
rc = PROC_RC_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( strcasecmp(p_key+1, "debugfile") == 0 )
|
||||
{
|
||||
if( value == NULL || expr )
|
||||
{
|
||||
log("incorrect usage of `%s' directive", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else
|
||||
#ifdef DEBUG
|
||||
{
|
||||
if( debug_isopened() ) debug_close();
|
||||
debug_setfilename(value);
|
||||
}
|
||||
#else
|
||||
{
|
||||
log("incorrect directive `%s': no debug code", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if( strcasecmp(p_key+1, "debuglevel") == 0 )
|
||||
{
|
||||
if( value == NULL || expr )
|
||||
{
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else
|
||||
#ifdef DEBUG
|
||||
{
|
||||
unsigned long newlevel = 0L;
|
||||
|
||||
if( debug_parsestring(value, &newlevel) )
|
||||
{
|
||||
rc = PROC_RC_WARN;
|
||||
}
|
||||
debug_setlevel(newlevel, 1);
|
||||
}
|
||||
#else
|
||||
{
|
||||
log("incorrect directive `%s': no debug code", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
log("unknown directive `%s'", p_key);
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
}
|
||||
else if( p_key && value )
|
||||
{
|
||||
if( isifexpr && expr )
|
||||
{
|
||||
log("can't use expressions inside $ifexpr block");
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
else if( isifexpr )
|
||||
{
|
||||
rc = proc_configline(p_key, ifexpr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = proc_configline(p_key, expr, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("incorrect config string");
|
||||
rc = PROC_RC_IGNORE;
|
||||
}
|
||||
|
||||
if( fullstr )
|
||||
{ free(fullstr); fullstr = NULL; }
|
||||
if( value )
|
||||
{ free(value); value = NULL; }
|
||||
if( expr )
|
||||
{ free(expr); expr = NULL; }
|
||||
|
||||
switch(rc) {
|
||||
case PROC_RC_OK:
|
||||
break;
|
||||
case PROC_RC_WARN:
|
||||
log("warning in config \"%s\" line %d", confname, line);
|
||||
break;
|
||||
case PROC_RC_IGNORE:
|
||||
log("ignore line %d in config \"%s\"", line, confname);
|
||||
break;
|
||||
case PROC_RC_ABORT:
|
||||
log("fatal error in config \"%s\" in line %d", confname, line);
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG();
|
||||
break;
|
||||
}
|
||||
if( rc == PROC_RC_ABORT ) { maxrc = 1; break; }
|
||||
} /* end of while */
|
||||
|
||||
file_close(fp);
|
||||
|
||||
if( isifexpr )
|
||||
{ maxrc = 1; log("unterminated directive `#ifexp'"); }
|
||||
|
||||
if( fullstr )
|
||||
free(fullstr);
|
||||
if( ifexpr )
|
||||
free(ifexpr);
|
||||
|
||||
DEB((D_CONFIG, "readconfig: exit with maxrc = %d", maxrc));
|
||||
|
||||
return maxrc;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void debug_override(void)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
char abuf[BF_MAXADDRSTR+1];
|
||||
|
||||
DEB((D_CONFIG, "debug_override: BEGIN"));
|
||||
|
||||
for( ptrl = bforce_config[cf_override].data; ptrl; ptrl = ptrl->next )
|
||||
{
|
||||
DEB((D_CONFIG, "log_overridelist: address %s",
|
||||
ftn_addrstr(abuf, ptrl->d.override.addr)));
|
||||
DEB((D_CONFIG, "log_overridelist: \tIpaddr = \"%s\"",
|
||||
ptrl->d.override.sIpaddr));
|
||||
DEB((D_CONFIG, "log_overridelist: \tPhone = \"%s\"",
|
||||
ptrl->d.override.sPhone));
|
||||
DEB((D_CONFIG, "log_overridelist: \tWorktime = \"%s\"",
|
||||
timevec_string(abuf, &ptrl->d.override.worktime, sizeof(abuf))));
|
||||
DEB((D_CONFIG, "log_overridelist: \tFlags = \"%s\"",
|
||||
ptrl->d.override.sFlags));
|
||||
}
|
||||
|
||||
DEB((D_CONFIG, "debug_override: END"));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
1041
source/bforce/daemon.c
Normal file
1041
source/bforce/daemon.c
Normal file
File diff suppressed because it is too large
Load Diff
161
source/bforce/daemon_branch.c
Normal file
161
source/bforce/daemon_branch.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "daemon.h"
|
||||
|
||||
static s_daemon_branch *daemon_branch_tab = NULL;
|
||||
static signed int daemon_branch_num = 0;
|
||||
|
||||
|
||||
#define ASSERT_POS(pos) ASSERT((pos) >= 0 && ((pos) + 1) <= daemon_branch_num \
|
||||
&& daemon_branch_tab)
|
||||
|
||||
bool daemon_branch_exist(s_faddr addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < daemon_branch_num; i++ )
|
||||
if( !ftn_addrcomp(daemon_branch_tab[i].addr, addr) )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void daemon_branch_check_stop_timers(void)
|
||||
{
|
||||
int i;
|
||||
time_t now = time(0);
|
||||
|
||||
for( i = 0; i < daemon_branch_num; i++ )
|
||||
if( daemon_branch_tab[i].stop && !daemon_branch_tab[i].wait
|
||||
&& now >= daemon_branch_tab[i].stop )
|
||||
{
|
||||
if( kill(daemon_branch_tab[i].pid, SIGKILL) == -1 )
|
||||
logerr("cannot kill branch with PID %d",
|
||||
(int)daemon_branch_tab[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
int daemon_branch_exit(pid_t pid, int rc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < daemon_branch_num; i++ )
|
||||
if( daemon_branch_tab[i].pid == pid )
|
||||
{
|
||||
daemon_branch_tab[i].rc = rc;
|
||||
daemon_branch_tab[i].wait = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int daemon_branch_get_first_waiting(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < daemon_branch_num; i++ )
|
||||
if( daemon_branch_tab[i].wait )
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_daemon_branch *daemon_branch_get_pointer(int pos)
|
||||
{
|
||||
ASSERT_POS(pos);
|
||||
|
||||
if( pos + 1 > daemon_branch_num )
|
||||
{
|
||||
log("internal error: branch position is out of range");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &daemon_branch_tab[pos];
|
||||
}
|
||||
|
||||
void daemon_branch_add(s_faddr addr, pid_t pid, bool tcpip, const char *pname)
|
||||
{
|
||||
if( daemon_branch_tab )
|
||||
{
|
||||
daemon_branch_tab =
|
||||
(s_daemon_branch *)xrealloc(daemon_branch_tab,
|
||||
sizeof(s_daemon_branch)*(daemon_branch_num + 1));
|
||||
memset(&daemon_branch_tab[daemon_branch_num], '\0',
|
||||
sizeof(s_daemon_branch));
|
||||
}
|
||||
else
|
||||
{
|
||||
daemon_branch_tab =
|
||||
(s_daemon_branch *)xmalloc(sizeof(s_daemon_branch));
|
||||
memset(daemon_branch_tab, '\0', sizeof(s_daemon_branch));
|
||||
daemon_branch_num = 0;
|
||||
}
|
||||
|
||||
daemon_branch_tab[daemon_branch_num].addr = addr;
|
||||
daemon_branch_tab[daemon_branch_num].wait = FALSE;
|
||||
daemon_branch_tab[daemon_branch_num].tcpip = tcpip;
|
||||
daemon_branch_tab[daemon_branch_num].pid = pid;
|
||||
daemon_branch_tab[daemon_branch_num].start = time(NULL);
|
||||
|
||||
if( pname )
|
||||
daemon_branch_tab[daemon_branch_num].portname = xstrcpy(pname);
|
||||
|
||||
daemon_branch_num++;
|
||||
}
|
||||
|
||||
void daemon_branch_remove(int pos)
|
||||
{
|
||||
ASSERT_POS(pos);
|
||||
|
||||
if( daemon_branch_tab[pos].portname )
|
||||
free(daemon_branch_tab[pos].portname);
|
||||
|
||||
if( daemon_branch_num > 1 )
|
||||
{
|
||||
memmove(&daemon_branch_tab[pos],
|
||||
&daemon_branch_tab[pos+1],
|
||||
sizeof(s_daemon_branch)*(daemon_branch_num - pos - 1));
|
||||
daemon_branch_tab =
|
||||
(s_daemon_branch *)xrealloc(daemon_branch_tab,
|
||||
sizeof(s_daemon_branch)*(daemon_branch_num - 1));
|
||||
daemon_branch_num--;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(daemon_branch_tab);
|
||||
daemon_branch_tab = NULL;
|
||||
daemon_branch_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int daemon_branch_number(void)
|
||||
{
|
||||
return daemon_branch_num;
|
||||
}
|
||||
|
||||
void daemon_branch_deinit(void)
|
||||
{
|
||||
if( daemon_branch_tab )
|
||||
free(daemon_branch_tab);
|
||||
|
||||
daemon_branch_tab = NULL;
|
||||
daemon_branch_num = 0;
|
||||
}
|
||||
|
||||
202
source/bforce/daemon_call.c
Normal file
202
source/bforce/daemon_call.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "nodelist.h"
|
||||
#include "io.h"
|
||||
#include "session.h"
|
||||
#include "outbound.h"
|
||||
#include "daemon.h"
|
||||
|
||||
static s_modemport *daemon_getfree_port(const char *lockdir)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
/* Find first not locked modem device */
|
||||
for( ptrl = conf_first(cf_modem_port); ptrl; ptrl = conf_next(ptrl) )
|
||||
{
|
||||
if( port_checklock(lockdir, &ptrl->d.modemport) == LOCKCHECK_NOLOCK
|
||||
&& modem_candialout(ptrl->d.modemport.name) == TRUE
|
||||
&& daemon_line_isready(ptrl->d.modemport.name) )
|
||||
return &ptrl->d.modemport;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int daemon_call_branch(s_sysentry *syst, const char *lockdir, s_modemport *port)
|
||||
{
|
||||
int rc = BFERR_NOERROR;
|
||||
char abuf[BF_MAXADDRSTR+1];
|
||||
|
||||
/*
|
||||
* First of all restore the default signal handlers
|
||||
*/
|
||||
signal(SIGCHLD, SIG_DFL);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGUSR1, SIG_DFL);
|
||||
signal(SIGUSR2, SIG_DFL);
|
||||
|
||||
/*
|
||||
* Initialise ``state'' information structure
|
||||
*/
|
||||
init_state(&state);
|
||||
state.caller = TRUE;
|
||||
state.valid = TRUE;
|
||||
state.node = syst->node;
|
||||
state.listed = syst->node.listed;
|
||||
state.modemport = (!syst->tcpip) ? port : NULL;
|
||||
if( syst->lineptr )
|
||||
state.override = *syst->lineptr;
|
||||
if( *state.node.addr.domain )
|
||||
*state.node.addr.domain = '\0';
|
||||
|
||||
/*
|
||||
* Apply overrides to the node information
|
||||
*/
|
||||
if( state.override.sFlags )
|
||||
{
|
||||
strnxcat(state.node.flags, ",", sizeof(state.node.flags));
|
||||
strnxcat(state.node.flags, state.override.sFlags, sizeof(state.node.flags));
|
||||
}
|
||||
|
||||
if( !syst->tcpip && state.override.sPhone )
|
||||
(void)strnxcpy(state.node.phone, state.override.sPhone, sizeof(state.node.phone));
|
||||
else if( syst->tcpip && state.override.sIpaddr )
|
||||
(void)strnxcpy(state.node.phone, state.override.sIpaddr, sizeof(state.node.phone));
|
||||
|
||||
/*
|
||||
* Try to lock address of system we are going to call
|
||||
*/
|
||||
#ifdef BFORCE_USE_CSY
|
||||
if( out_bsy_lock(state.node.addr, TRUE) )
|
||||
#else
|
||||
if( out_bsy_lock(state.node.addr) )
|
||||
#endif
|
||||
gotoexit(BFERR_SYSTEM_LOCKED);
|
||||
|
||||
setproctitle("bforce calling %s, %s",
|
||||
ftn_addrstr(abuf, state.node.addr), state.node.phone);
|
||||
|
||||
if( syst->tcpip )
|
||||
{
|
||||
rc = call_system_tcpip();
|
||||
}
|
||||
else /* via Modem */
|
||||
{
|
||||
state.modemport = port;
|
||||
if( port_lock(lockdir, state.modemport) )
|
||||
{
|
||||
log("cannot lock modem port");
|
||||
rc = BFERR_PORTBUSY;
|
||||
}
|
||||
else /* Locked port */
|
||||
{
|
||||
rc = call_system_modem();
|
||||
port_unlock(lockdir, state.modemport);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
out_bsy_unlockall();
|
||||
|
||||
log("session rc = %d (\"%s\")", rc, BFERR_NAME(rc));
|
||||
|
||||
(void)session_stat_update(&state.node.addr,
|
||||
&state.sess_stat, TRUE, rc);
|
||||
|
||||
deinit_state(&state);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int daemon_call(s_sysentry *syst)
|
||||
{
|
||||
pid_t chld_pid;
|
||||
const char *p_lockdir = NULL;
|
||||
char abuf[BF_MAXADDRSTR+1];
|
||||
s_modemport *modemport = NULL;
|
||||
|
||||
/*
|
||||
* Check number of allowed clients
|
||||
*/
|
||||
if( (syst->tcpip == TRUE && max_tcpip && max_tcpip <= tcpip_clients)
|
||||
|| (syst->tcpip == FALSE && max_modem && max_modem <= modem_clients) )
|
||||
{
|
||||
DEB((D_DAEMON, "daemon_call: too many clients!"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether this node is allready locked
|
||||
*/
|
||||
if( out_bsy_check(syst->node.addr) )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Set state structure to make expressions works properly now
|
||||
*/
|
||||
state.caller = TRUE;
|
||||
state.valid = TRUE;
|
||||
state.node = syst->node;
|
||||
state.listed = syst->node.listed;
|
||||
state.inet = syst->tcpip;
|
||||
|
||||
if( syst->tcpip == FALSE )
|
||||
{
|
||||
if( (p_lockdir = conf_string(cf_uucp_lock_directory)) == NULL )
|
||||
p_lockdir = BFORCE_LOCK_DIR;
|
||||
|
||||
if( (modemport = daemon_getfree_port(p_lockdir)) == NULL )
|
||||
{
|
||||
init_state(&state);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
log("call %s line %d via %s",
|
||||
ftn_addrstr(abuf, syst->node.addr), syst->line,
|
||||
syst->tcpip ? "TCP/IP" : modemport->name);
|
||||
|
||||
chld_pid = fork();
|
||||
|
||||
if( chld_pid > 0 )
|
||||
{
|
||||
(void)daemon_branch_add(syst->node.addr, chld_pid, syst->tcpip,
|
||||
syst->tcpip ? NULL : modemport->name);
|
||||
|
||||
init_state(&state);
|
||||
|
||||
if( syst->tcpip )
|
||||
++tcpip_clients;
|
||||
else
|
||||
++modem_clients;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if( chld_pid < 0 )
|
||||
{
|
||||
logerr("failed fork() call");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Now we are in child process */
|
||||
|
||||
exit(daemon_call_branch(syst, p_lockdir, modemport));
|
||||
}
|
||||
|
||||
106
source/bforce/daemon_lines.c
Normal file
106
source/bforce/daemon_lines.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
|
||||
enum { LINE_TYPE_MODEM, LINE_TYPE_TCPIP };
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
time_t holdtimer;
|
||||
int type;
|
||||
} s_line;
|
||||
|
||||
static s_line *lines_tab = NULL;
|
||||
static int lines_num = 0;
|
||||
|
||||
int daemon_line_add(const char *name, int type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lines_num; i++ )
|
||||
if( !strcmp(lines_tab[i].name, name) )
|
||||
return i;
|
||||
|
||||
log("register new line \"%s\"", name);
|
||||
|
||||
if( lines_tab )
|
||||
{
|
||||
lines_tab = (s_line *)xrealloc(lines_tab, sizeof(s_line)*(lines_num+1));
|
||||
memset(&lines_tab[lines_num], '\0', sizeof(s_line));
|
||||
}
|
||||
else
|
||||
{
|
||||
lines_tab = (s_line *)xmalloc(sizeof(s_line));
|
||||
memset(lines_tab, '\0', sizeof(s_line));
|
||||
}
|
||||
|
||||
lines_tab[lines_num].name = xstrcpy(name);
|
||||
lines_tab[lines_num].type = type;
|
||||
|
||||
return lines_num++;
|
||||
}
|
||||
|
||||
void daemon_line_hold(const char *name, int holdtime)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lines_num; i++ )
|
||||
if( !strcmp(lines_tab[i].name, name) )
|
||||
{
|
||||
timer_set(&lines_tab[i].holdtimer, holdtime);
|
||||
return;
|
||||
}
|
||||
|
||||
i = daemon_line_add(name, 0);
|
||||
timer_set(&lines_tab[i].holdtimer, holdtime);
|
||||
}
|
||||
|
||||
bool daemon_line_isready(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lines_num; i++ )
|
||||
if( !strcmp(lines_tab[i].name, name) )
|
||||
{
|
||||
if( !timer_running(lines_tab[i].holdtimer)
|
||||
|| timer_expired(lines_tab[i].holdtimer) )
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
(void)daemon_line_add(name, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void daemon_lines_deinit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lines_num; i++ )
|
||||
if( lines_tab[i].name )
|
||||
free(lines_tab[i].name);
|
||||
|
||||
if( lines_tab )
|
||||
{
|
||||
free(lines_tab);
|
||||
lines_tab = NULL;
|
||||
}
|
||||
|
||||
lines_num = 0;
|
||||
}
|
||||
|
||||
1733
source/bforce/expression.tab.c
Normal file
1733
source/bforce/expression.tab.c
Normal file
File diff suppressed because it is too large
Load Diff
443
source/bforce/expression.y
Normal file
443
source/bforce/expression.y
Normal file
@ -0,0 +1,443 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
%token COMMA
|
||||
%token TEXT
|
||||
%token NUMBER
|
||||
%token INCOMING
|
||||
%token OUTGOING
|
||||
%token LISTED
|
||||
%token PROTECTED
|
||||
%token CONNSPEED
|
||||
%token EXEC
|
||||
%token EXIST
|
||||
%token PORT
|
||||
%token MAILER
|
||||
%token TZ
|
||||
%token FLAG
|
||||
%token SPEED
|
||||
%token PHONE
|
||||
%token TIME
|
||||
%token ADDRESS
|
||||
%token EQ
|
||||
%token NE
|
||||
%token GT
|
||||
%token GE
|
||||
%token LT
|
||||
%token LE
|
||||
%token AND
|
||||
%token OR
|
||||
%token NOT
|
||||
%token XOR
|
||||
%token OPENB
|
||||
%token CLOSEB
|
||||
%token AROP
|
||||
%token LOGOP
|
||||
|
||||
%expect 2
|
||||
%{
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "util.h"
|
||||
#include "logger.h"
|
||||
#include "session.h"
|
||||
#include "nodelist.h"
|
||||
#include "io.h"
|
||||
|
||||
static struct tm *now = NULL;
|
||||
static int expr_result = 0;
|
||||
static char *expr_p_pos = NULL;
|
||||
static char *expr_p_text = NULL;
|
||||
|
||||
/*
|
||||
* These are expression element checkers (not only)
|
||||
* Return values:
|
||||
* 0 - FALSE
|
||||
* 1 - TRUE
|
||||
* -1 - cannot check, because some data is not available yet
|
||||
* -2 - invalid element (we should not check this expression more)
|
||||
*/
|
||||
static int expr_check_incoming(void);
|
||||
static int expr_check_outgoing(void);
|
||||
static int expr_check_protected(void);
|
||||
static int expr_check_listed(void);
|
||||
static int expr_check_logic(int e1, int op, int e2);
|
||||
static int expr_check_phone(const char *phone);
|
||||
static int expr_check_arop(int num1, int op, int num2);
|
||||
static int expr_check_flag(const char *str);
|
||||
static int expr_check_exec(const char *str);
|
||||
static int expr_check_exist(const char *str);
|
||||
static int expr_check_port(const char *str);
|
||||
static int expr_check_mailer(const char *str);
|
||||
static int expr_check_addr(const char *str);
|
||||
static int expr_check_time(const char *str);
|
||||
|
||||
static int yylex(void);
|
||||
static int yyparse(void);
|
||||
static int yyerror(const char *s);
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
fullline : expression
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] expression return %d", $1));
|
||||
expr_result = $1;
|
||||
}
|
||||
;
|
||||
expression : elemexp
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] elemexp return %d", $1));
|
||||
$$ = $1;
|
||||
}
|
||||
| NOT expression
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] not exprression %d", $2));
|
||||
if( ($2) < 0 )
|
||||
$$ = 0;
|
||||
else
|
||||
$$ = !($2);
|
||||
}
|
||||
| expression LOGOP expression
|
||||
{
|
||||
$$ = expr_check_logic($1, $2, $3);
|
||||
}
|
||||
| OPENB expression CLOSEB
|
||||
{
|
||||
DEB((D_EVENT, "eventexp: [yacc] backeted.expr %d", $2));
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
elemexp : INCOMING
|
||||
{
|
||||
$$ = expr_check_incoming();
|
||||
}
|
||||
| OUTGOING
|
||||
{
|
||||
$$ = expr_check_outgoing();
|
||||
}
|
||||
| LISTED
|
||||
{
|
||||
$$ = expr_check_listed();
|
||||
}
|
||||
| PROTECTED
|
||||
{
|
||||
$$ = expr_check_protected();
|
||||
}
|
||||
| FLAG flagstring
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| CONNSPEED AROP NUMBER
|
||||
{
|
||||
if( state.valid && state.connspeed > 0 )
|
||||
$$ = expr_check_arop(state.connspeed, $2, $3);
|
||||
else
|
||||
$$ = -1;
|
||||
}
|
||||
| SPEED AROP NUMBER
|
||||
{
|
||||
if( state.valid && state.node.speed > 0 )
|
||||
$$ = expr_check_arop(state.node.speed, $2, $3);
|
||||
else
|
||||
$$ = -1;
|
||||
}
|
||||
| TZ AROP NUMBER
|
||||
{
|
||||
$$ = expr_check_arop(time_gmtoffset(), $2, $3);
|
||||
}
|
||||
| PHONE TEXT
|
||||
{
|
||||
$$ = expr_check_phone(expr_p_text);
|
||||
}
|
||||
| TIME timestring
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| EXEC TEXT
|
||||
{
|
||||
$$ = expr_check_exec(expr_p_text);
|
||||
}
|
||||
| EXIST TEXT
|
||||
{
|
||||
$$ = expr_check_exist(expr_p_text);
|
||||
}
|
||||
| PORT TEXT
|
||||
{
|
||||
$$ = expr_check_port(expr_p_text);
|
||||
}
|
||||
| MAILER TEXT
|
||||
{
|
||||
$$ = expr_check_mailer(expr_p_text);
|
||||
}
|
||||
| TEXT
|
||||
{
|
||||
$$ = expr_check_addr(expr_p_text);
|
||||
if( $$ == -2 )
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
flagstring : TEXT
|
||||
{
|
||||
$$ = expr_check_flag(expr_p_text);
|
||||
}
|
||||
| TEXT COMMA flagstring
|
||||
{
|
||||
$$ = expr_check_logic($1, OR, $3);
|
||||
}
|
||||
;
|
||||
timestring : TEXT
|
||||
{
|
||||
$$ = expr_check_time(expr_p_text);
|
||||
if( $$ == -2 )
|
||||
YYABORT;
|
||||
}
|
||||
| TEXT COMMA timestring
|
||||
{
|
||||
$$ = expr_check_logic($1, OR, $3);
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
#include "expression_lex.c"
|
||||
|
||||
static int expr_check_incoming(void)
|
||||
{
|
||||
if( !state.valid )
|
||||
return -1;
|
||||
|
||||
return state.caller ? 0 : 1;
|
||||
}
|
||||
|
||||
static int expr_check_outgoing(void)
|
||||
{
|
||||
if( !state.valid )
|
||||
return -1;
|
||||
|
||||
return state.caller ? 1 : 0;
|
||||
}
|
||||
|
||||
static int expr_check_protected(void)
|
||||
{
|
||||
if( !state.valid || !state.node.addr.zone )
|
||||
return -1;
|
||||
|
||||
return state.protected ? 1 : 0;
|
||||
}
|
||||
|
||||
static int expr_check_listed(void)
|
||||
{
|
||||
if( !state.valid || !state.node.addr.zone )
|
||||
return -1;
|
||||
|
||||
return state.node.listed ? 1 : 0;
|
||||
}
|
||||
|
||||
static int expr_check_logic(int e1, int op, int e2)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] logic: %d %d %d", e1, op, e2));
|
||||
|
||||
if( e1 < 0 ) e1 = 0;
|
||||
if( e2 < 0 ) e2 = 0;
|
||||
|
||||
switch(op) {
|
||||
case AND:
|
||||
return (e1 && e2);
|
||||
case OR:
|
||||
return (e1 || e2);
|
||||
case XOR:
|
||||
return (e1 ^ e2);
|
||||
}
|
||||
|
||||
log("invalid logical operator in expression");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int expr_check_phone(const char *phone)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] phone: is %s in %s",
|
||||
phone, state.node.phone));
|
||||
|
||||
if( !state.valid )
|
||||
return 0;
|
||||
|
||||
return strstr(state.node.phone, phone) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int expr_check_arop(int num1, int op, int num2)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] arop: %d %d %d", num1, op, num2));
|
||||
|
||||
switch(op) {
|
||||
case EQ: return (num1 == num2);
|
||||
case NE: return (num1 != num2);
|
||||
case GT: return (num1 > num2);
|
||||
case GE: return (num1 >= num2);
|
||||
case LT: return (num1 < num2);
|
||||
case LE: return (num1 <= num2);
|
||||
}
|
||||
|
||||
log("invalid arithmetic operator in expression");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int expr_check_flag(const char *str)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] flag: \"%s\"", str));
|
||||
|
||||
if( !state.valid )
|
||||
return 0;
|
||||
|
||||
return !nodelist_checkflag(state.node.flags, str);
|
||||
}
|
||||
|
||||
static int expr_check_exec(const char *str)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] exec: \"%s\"", str));
|
||||
|
||||
return session_run_command(str) ? 0 : 1;
|
||||
}
|
||||
|
||||
static int expr_check_exist(const char *str)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] exist: \"%s\"", str));
|
||||
|
||||
return access(str, F_OK) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int expr_check_port(const char *str)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] port: \"%s\"", str));
|
||||
|
||||
if( !state.valid )
|
||||
return -1;
|
||||
|
||||
if( !strcasecmp(str, "tcpip") )
|
||||
{
|
||||
return state.inet ? 1 : 0;
|
||||
}
|
||||
else if( state.modemport && state.modemport->name )
|
||||
{
|
||||
return strstr(state.modemport->name, str) ? 1 : 0;
|
||||
}
|
||||
else if( isatty(0) )
|
||||
{
|
||||
return strstr(ttyname(0), str) ? 1 : 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int expr_check_mailer(const char *str)
|
||||
{
|
||||
char *p;
|
||||
|
||||
DEB((D_EVENT, "[yacc] mailer: \"%s\"", str));
|
||||
|
||||
if( !state.valid )
|
||||
return -1;
|
||||
|
||||
if( state.handshake && state.handshake->remote_mailer )
|
||||
p = state.handshake->remote_mailer(state.handshake);
|
||||
else
|
||||
return -1;
|
||||
|
||||
return (p && string_casestr(p, str)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int expr_check_addr(const char *str)
|
||||
{
|
||||
s_faddr addr;
|
||||
#ifdef DEBUG
|
||||
char abuf1[BF_MAXADDRSTR+1];
|
||||
char abuf2[BF_MAXADDRSTR+1];
|
||||
|
||||
DEB((D_EVENT, "[yacc] addr: \"%s\" (session with \"%s\")",
|
||||
ftn_addrstr(abuf1, addr),
|
||||
ftn_addrstr(abuf2, state.node.addr)));
|
||||
#endif
|
||||
|
||||
if( !state.valid )
|
||||
return -1;
|
||||
|
||||
if( ftn_addrparse(&addr, str, TRUE) )
|
||||
{
|
||||
log("invalid address \"%s\"", str);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return !ftn_addrcomp_mask(state.node.addr, addr);
|
||||
}
|
||||
|
||||
static int expr_check_time(const char *str)
|
||||
{
|
||||
DEB((D_EVENT, "[yacc] time: \"%s\"", str));
|
||||
|
||||
switch( time_check(str, now) ) {
|
||||
case -1:
|
||||
log("invalid time string \"%s\"", str);
|
||||
return -2;
|
||||
case 0:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool eventexpr(s_expr *expr)
|
||||
{
|
||||
time_t tt;
|
||||
char *tmp;
|
||||
|
||||
if( !expr || !expr->expr )
|
||||
return 1;
|
||||
|
||||
if( expr->error )
|
||||
return 0;
|
||||
|
||||
DEB((D_EVENT, "eventexpr: [yacc] check expression \"%s\"",
|
||||
expr->expr));
|
||||
|
||||
tt = time(NULL);
|
||||
now = localtime(&tt);
|
||||
tmp = (char*)xstrcpy(expr->expr);
|
||||
|
||||
expr_p_pos = tmp;
|
||||
expr_result = 0;
|
||||
|
||||
if( yyparse() )
|
||||
{
|
||||
expr->error = TRUE;
|
||||
|
||||
log("cannot parse expression \"%s\"", expr->expr);
|
||||
DEB((D_EVENT, "eventexpr: [yacc] $yyparse return error"));
|
||||
|
||||
expr_result = 0;
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
|
||||
DEB((D_EVENT, "eventexpr: [yacc] checking result is \"%s\" (%d)",
|
||||
(expr_result == 1) ? "TRUE" : "FALSE", expr_result));
|
||||
|
||||
return (expr_result == 1) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static int yyerror(const char *str)
|
||||
{
|
||||
log("expression check failure: %s", str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
174
source/bforce/expression_lex.c
Normal file
174
source/bforce/expression_lex.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
typedef struct lextable {
|
||||
const char *str;
|
||||
int value;
|
||||
int retc;
|
||||
int len;
|
||||
} s_lextable;
|
||||
|
||||
static bool initialised = FALSE;
|
||||
static s_lextable *next = NULL;
|
||||
|
||||
static s_lextable operators[] =
|
||||
{
|
||||
{ "==", EQ, AROP, 0 },
|
||||
{ "!=", NE, AROP, 0 },
|
||||
{ ">", GT, AROP, 0 },
|
||||
{ ">=", GE, AROP, 0 },
|
||||
{ "<", LT, AROP, 0 },
|
||||
{ "<=", LE, AROP, 0 },
|
||||
{ "(", OPENB, OPENB, 0 },
|
||||
{ ")", CLOSEB, CLOSEB, 0 },
|
||||
{ "&&", AND, LOGOP, 0 },
|
||||
{ "&", AND, LOGOP, 0 },
|
||||
{ "||", OR, LOGOP, 0 },
|
||||
{ "|", OR, LOGOP, 0 },
|
||||
{ "Xor", XOR, LOGOP, 0 },
|
||||
{ "!", NOT, NOT, 0 },
|
||||
{ ",", COMMA, COMMA, 0 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
s_lextable elements[] =
|
||||
{
|
||||
{ "TZ", TZ, TZ, 0 },
|
||||
{ "Address", ADDRESS, ADDRESS, 0 },
|
||||
{ "Time", TIME, TIME, 0 },
|
||||
{ "Phone", PHONE, PHONE, 0 },
|
||||
{ "Flag", FLAG, FLAG, 0 },
|
||||
{ "Incoming", INCOMING, INCOMING, 0 },
|
||||
{ "Outgoing", OUTGOING, OUTGOING, 0 },
|
||||
{ "Listed", LISTED, LISTED, 0 },
|
||||
{ "Protected", PROTECTED, PROTECTED, 0 },
|
||||
{ "Connspeed", CONNSPEED, CONNSPEED, 0 },
|
||||
{ "Exec", EXEC, EXEC, 0 },
|
||||
{ "Exist", EXIST, EXIST, 0 },
|
||||
{ "Port", PORT, PORT, 0 },
|
||||
{ "Mailer", MAILER, MAILER, 0 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void expr_inittables(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; operators[i].str; i++ )
|
||||
operators[i].len = strlen(operators[i].str);
|
||||
|
||||
for( i = 0; elements[i].str; i++ )
|
||||
elements[i].len = strlen(elements[i].str);
|
||||
}
|
||||
|
||||
static int yylex(void)
|
||||
{
|
||||
int i, retc = 0;
|
||||
s_lextable *entry = NULL;
|
||||
|
||||
ASSERT(expr_p_pos != NULL);
|
||||
|
||||
if( !initialised )
|
||||
{ expr_inittables(); initialised = TRUE; }
|
||||
|
||||
if( next )
|
||||
{
|
||||
/*
|
||||
* Found operator left from previous call to yylex()
|
||||
*/
|
||||
yylval = next->value;
|
||||
DEB((D_EVENT, "yylex: got next \"%s\", yylval = %d, ret = %d",
|
||||
next->str, next->value, next->retc));
|
||||
retc = next->retc;
|
||||
next = NULL;
|
||||
return retc;
|
||||
}
|
||||
|
||||
while( isspace(*expr_p_pos) ) expr_p_pos++;
|
||||
|
||||
if( *expr_p_pos == '\0' ) return 0;
|
||||
|
||||
for( i = 0; operators[i].str; i++ )
|
||||
{
|
||||
if( strncasecmp(expr_p_pos, operators[i].str, operators[i].len) == 0 )
|
||||
{ entry = &operators[i]; break; }
|
||||
}
|
||||
|
||||
if( entry == NULL )
|
||||
{
|
||||
for( i = 0; elements[i].str; i++ )
|
||||
{
|
||||
if( strncasecmp(expr_p_pos, elements[i].str, elements[i].len) == 0 )
|
||||
{ entry = &elements[i]; break; }
|
||||
}
|
||||
}
|
||||
|
||||
if( entry )
|
||||
{
|
||||
expr_p_pos += entry->len;
|
||||
yylval = entry->value;
|
||||
DEB((D_EVENT, "yylex: got token \"%s\", yylval = %d, ret = %d",
|
||||
entry->str, entry->value, entry->retc));
|
||||
return entry->retc;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if( *expr_p_pos == '"' )
|
||||
{
|
||||
expr_p_text = ++expr_p_pos;
|
||||
|
||||
while( *expr_p_pos != '"' && *expr_p_pos )
|
||||
++expr_p_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
expr_p_text = expr_p_pos++;
|
||||
|
||||
while( !isspace(*expr_p_pos) && *expr_p_pos )
|
||||
{
|
||||
for( i = 0; operators[i].str; i++ )
|
||||
if( strncasecmp(expr_p_pos, operators[i].str, operators[i].len) == 0 )
|
||||
{
|
||||
next = &operators[i];
|
||||
goto enough;
|
||||
}
|
||||
expr_p_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
enough:
|
||||
if( *expr_p_pos )
|
||||
{
|
||||
*expr_p_pos = '\0';
|
||||
if( next && next->len > 1 )
|
||||
expr_p_pos += next->len;
|
||||
else
|
||||
expr_p_pos += 1;
|
||||
}
|
||||
|
||||
if( ISDEC(expr_p_text) )
|
||||
{
|
||||
/* It is decimal number */
|
||||
yylval = atol(expr_p_text);
|
||||
DEB((D_EVENT, "yylex: got NUMBER %d", yylval));
|
||||
return NUMBER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It is text */
|
||||
DEB((D_EVENT, "yylex: got TEXT \"%s\"", expr_p_text));
|
||||
return(yylval = TEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
source/bforce/freq_bark.c
Normal file
18
source/bforce/freq_bark.c
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "freq.h"
|
||||
406
source/bforce/freq_proc.c
Normal file
406
source/bforce/freq_proc.c
Normal file
@ -0,0 +1,406 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "outbound.h"
|
||||
#include "freq.h"
|
||||
|
||||
static void deinit_reqlist(s_reqlist *dest);
|
||||
static void deinit_frlist(s_frlist *dest);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Log requested files, passwords and other specified information */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static void req_logreqlist(s_reqlist *reqlist)
|
||||
{
|
||||
s_reqlist *rlist;
|
||||
char *p = NULL;
|
||||
char buf[100];
|
||||
|
||||
for( rlist = reqlist; rlist; rlist = rlist->next )
|
||||
{
|
||||
if( rlist->fmask == NULL ) continue;
|
||||
|
||||
p = xstrcpy("requested \"");
|
||||
p = xstrcat(p, rlist->fmask);
|
||||
p = xstrcat(p, "\"");
|
||||
if( rlist->passwd )
|
||||
{
|
||||
p = xstrcat(p, ", password \"");
|
||||
p = xstrcat(p, rlist->passwd);
|
||||
p = xstrcat(p, "\"");
|
||||
}
|
||||
if( rlist->newer )
|
||||
{
|
||||
p = xstrcat(p, ", newer \"");
|
||||
p = xstrcat(p, time_string_long(buf, sizeof(buf), rlist->newer));
|
||||
p = xstrcat(p, "\"");
|
||||
}
|
||||
if( rlist->older )
|
||||
{
|
||||
p = xstrcat(p, ", older \"");
|
||||
p = xstrcat(p, time_string_long(buf, sizeof(buf), rlist->older));
|
||||
p = xstrcat(p, "\"");
|
||||
}
|
||||
log("FREQ: %s", string_printable(p));
|
||||
if( p ) { free(p); p = NULL; }
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Read files containing list of public dirs and file aliases */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static void req_readfrlist(char *fname, s_frlist **frlist, int magic)
|
||||
{
|
||||
FILE *fp;
|
||||
s_frlist **ptrl;
|
||||
char sbuf[BF_MAXREQLINE+1];
|
||||
char *magc = NULL;
|
||||
char *path = NULL;
|
||||
char *pwd = NULL;
|
||||
char *n = NULL;
|
||||
|
||||
DEB((D_FREQ, "req_readfrlist: reading \"%s\", magic = %d", fname, magic));
|
||||
|
||||
if( (fp = file_open(fname, "r")) == NULL )
|
||||
{
|
||||
logerr("FREQ: can't open dirlist \"%s\"", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
for( ptrl = frlist; *ptrl; ptrl = &(*ptrl)->next )
|
||||
{
|
||||
/* EMPTY LOOP */
|
||||
}
|
||||
|
||||
while( fgets(sbuf, sizeof(sbuf), fp) )
|
||||
{
|
||||
string_chomp(sbuf);
|
||||
|
||||
if( *sbuf == '#' ) continue;
|
||||
|
||||
if( magic )
|
||||
{
|
||||
magc = string_token(sbuf, &n, NULL, 1);
|
||||
path = string_token(NULL, &n, NULL, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
path = string_token(sbuf, &n, NULL, 1);
|
||||
}
|
||||
|
||||
pwd = string_token(NULL, &n, NULL, 1);
|
||||
|
||||
/* make sure it is password */
|
||||
if( pwd && *pwd == '!' ) pwd++; else pwd = NULL;
|
||||
|
||||
if( path && *path && (!magic || (magc && *magc)) )
|
||||
{
|
||||
DEB((D_FREQ, "req_readfrlist: add path = \"%s\", magic = \"%s\", passwd = \"%s\"",
|
||||
path, magc, pwd));
|
||||
|
||||
(*ptrl) = (s_frlist*)xmalloc(sizeof(s_frlist));
|
||||
memset(*ptrl, '\0', sizeof(s_frlist));
|
||||
|
||||
if( path && *path ) (*ptrl)->path = xstrcpy(path);
|
||||
if( !magic && *(path + strlen(path) - 1) != DIRSEPCHR )
|
||||
{
|
||||
/* add trailing DIRSEP ('/' or ..) to paths */
|
||||
(*ptrl)->path = xstrcat((*ptrl)->path, DIRSEPSTR);
|
||||
}
|
||||
if( magc && *magc ) (*ptrl)->magic = xstrcpy(magc);
|
||||
if( pwd && *pwd ) (*ptrl)->passwd = xstrcpy(pwd);
|
||||
ptrl = &(*ptrl)->next;
|
||||
}
|
||||
}
|
||||
|
||||
file_close(fp);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Add files to send files list, check limits. Return non-zero value */
|
||||
/* if can't send more files. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static int req_addfile(char *fname, s_freq *freq)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
DEB((D_FREQ, "req_addfile: try to add \"%s\"", fname));
|
||||
|
||||
if( stat(fname, &st) )
|
||||
{
|
||||
logerr("FREQ: can't stat requested file \"%s\"", fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( S_ISREG(st.st_mode) == 0 )
|
||||
{
|
||||
log("FREQ: requested file isn't regular \"%s\"", fname);
|
||||
}
|
||||
else if( (freq->sizelimit > 0)
|
||||
&& ((freq->fsize + st.st_size) > freq->sizelimit) )
|
||||
{
|
||||
DEB((D_FREQ, "req_addfile:sending FREQ file \"%s\" exceed size limit", fname));
|
||||
}
|
||||
else
|
||||
{
|
||||
freq->fnumber += 1;
|
||||
freq->fsize += st.st_size;
|
||||
|
||||
log("FREQ: send \"%s\", %d byte(s)", fname, st.st_size);
|
||||
|
||||
(*freq->flast) = (s_filelist*)xmalloc(sizeof(s_filelist));
|
||||
memset(*freq->flast, '\0', sizeof(s_filelist));
|
||||
(*freq->flast)->fname = fname ? xstrcpy(fname) : NULL;
|
||||
(*freq->flast)->size = st.st_size;
|
||||
(*freq->flast)->type = TYPE_REQANSW;
|
||||
(*freq->flast)->status = STATUS_WILLSEND;
|
||||
(*freq->flast)->action = ACTION_NOTHING;
|
||||
freq->flast = &(*freq->flast)->next;
|
||||
}
|
||||
}
|
||||
|
||||
if( (freq->fileslimit > 0) && (freq->fnumber >= freq->fileslimit) )
|
||||
{
|
||||
log("FREQ: reached files number limit (%d file(s))", freq->fileslimit);
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Return non-zero if got incorrect password for password protected file */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static int checkpasswd(char *ourpwd, char *gotpwd)
|
||||
{
|
||||
if( ourpwd == NULL || *ourpwd == '\0' ) return(0);
|
||||
if( gotpwd && strcasecmp(ourpwd, gotpwd) == 0 ) return(0);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Run external (SRIF compartible) FREQ processor */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static void req_proc_ext(s_freq *freq, char *reqname)
|
||||
{
|
||||
char srfname[L_tmpnam+5];
|
||||
char rspname[L_tmpnam+5];
|
||||
char *comline = NULL;
|
||||
|
||||
if( tmpnam(srfname) )
|
||||
{
|
||||
strncpy(rspname, srfname, L_tmpnam+4);
|
||||
rspname[L_tmpnam+4] = '\0';
|
||||
strcat(srfname, ".srf");
|
||||
strcat(rspname, ".rsp");
|
||||
if( req_createsrif(srfname, reqname, rspname) == 0 )
|
||||
{
|
||||
comline = xstrcpy(freq->srifproc);
|
||||
comline = xstrcat(comline, " ");
|
||||
comline = xstrcat(comline, srfname);
|
||||
if( session_run_command(comline) == 0 )
|
||||
{
|
||||
req_addfilelist(rspname, freq);
|
||||
}
|
||||
unlink(srfname);
|
||||
unlink(rspname);
|
||||
if( comline ) { free(comline); }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logerr("FREQ: can't generate temp name for SRIF");
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Run internal FREQ processor */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static void req_proc_int(s_freq *freq)
|
||||
{
|
||||
s_reqlist *rlist;
|
||||
s_frlist *frl;
|
||||
struct dirent *dirent;
|
||||
DIR *dirp;
|
||||
char *fname = NULL;
|
||||
int stop = 0; /* Stop processing FREQs */
|
||||
int msg = 0; /* Show "incorrect password" message only once */
|
||||
|
||||
for( frl = freq->frlist; !stop && frl; frl = frl->next )
|
||||
{
|
||||
if( frl->magic && *frl->magic )
|
||||
{
|
||||
/* MAGIC */
|
||||
DEB((D_FREQ, "req_proc_int: checking our magic \"%s\"", frl->magic));
|
||||
|
||||
for( rlist = freq->reqlist; rlist; rlist = rlist->next )
|
||||
{
|
||||
if( !strcasecmp(frl->magic, rlist->fmask) )
|
||||
{
|
||||
if( 0 == checkpasswd(frl->passwd, rlist->passwd) )
|
||||
{
|
||||
rlist->skip = 1;
|
||||
stop = req_addfile(frl->path, freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("FREQ: incorrect password for magic \"%s\"", frl->magic);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( stop == 0 )
|
||||
{
|
||||
/* Check - may be there is no more */
|
||||
/* requests - so break it out */
|
||||
for( rlist = freq->reqlist; rlist; rlist = rlist->next )
|
||||
{
|
||||
if( rlist->skip == 0 ) break;
|
||||
}
|
||||
stop = (rlist == NULL);
|
||||
}
|
||||
}
|
||||
else if( frl->path && *frl->path )
|
||||
{
|
||||
/* FREQ DIR */
|
||||
if( (dirp = opendir(frl->path)) == NULL )
|
||||
{
|
||||
logerr("FREQ: can't open freq dir \"%s\"", frl->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* REGULAR DIR */
|
||||
DEB((D_FREQ, "req_proc_int: checking dir \"%s\"", frl->path));
|
||||
|
||||
while( !stop && (dirent = readdir(dirp)) )
|
||||
{
|
||||
if( *dirent->d_name == '.' ) continue;
|
||||
for( rlist = freq->reqlist; rlist; rlist = rlist->next )
|
||||
{
|
||||
if( rlist->skip == 0
|
||||
&& 0 == strcasemask(dirent->d_name, rlist->fmask) )
|
||||
{
|
||||
if( 0 == checkpasswd(frl->passwd, rlist->passwd) )
|
||||
{
|
||||
fname = xstrcpy(frl->path);
|
||||
fname = xstrcat(fname, dirent->d_name);
|
||||
stop = req_addfile(fname, freq);
|
||||
free(fname);
|
||||
}
|
||||
else if( msg == 0 )
|
||||
{
|
||||
log("FREQ: incorrect password");
|
||||
++msg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Start FREQs processing, run int. or ext. processor */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
void req_proc(char *reqname, s_filelist **filelist)
|
||||
{
|
||||
char *p = NULL;
|
||||
time_t timer = time(NULL);
|
||||
s_freq freq;
|
||||
|
||||
/* Init FREQ information structure */
|
||||
memset(&freq, '\0', sizeof(s_freq));
|
||||
freq.fileslimit = conf_number(cf_freq_limit_number);
|
||||
freq.sizelimit = conf_number(cf_freq_limit_size);
|
||||
freq.filelist = filelist;
|
||||
freq.flast = filelist;
|
||||
|
||||
if( (p = conf_string(cf_freq_srif_command)) && *p )
|
||||
{
|
||||
/* Try external (SRIF) FREQ processor */
|
||||
log("FREQ: starting external processor");
|
||||
|
||||
freq.srifproc = xstrcpy(p);
|
||||
|
||||
req_proc_ext(&freq, reqname);
|
||||
|
||||
if( freq.srifproc )
|
||||
free(freq.srifproc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Run internal FREQ processor */
|
||||
log("FREQ: starting internal processor");
|
||||
|
||||
if( req_readwazooreq(reqname, &freq.reqlist) == 0 )
|
||||
{
|
||||
req_logreqlist(freq.reqlist);
|
||||
|
||||
if( (p = conf_string(cf_freq_alias_list)) && *p )
|
||||
req_readfrlist(p, &freq.frlist, 1);
|
||||
|
||||
if( (p = conf_string(cf_freq_dir_list)) && *p )
|
||||
req_readfrlist(p, &freq.frlist, 0);
|
||||
|
||||
if( freq.frlist )
|
||||
{
|
||||
req_proc_int(&freq);
|
||||
deinit_frlist(freq.frlist);
|
||||
}
|
||||
deinit_reqlist(freq.reqlist);
|
||||
}
|
||||
}
|
||||
|
||||
log("FREQ: stat %d file(s), %d byte(s), %d second(s)",
|
||||
freq.fnumber, freq.fsize, time(NULL)-timer);
|
||||
|
||||
#ifdef DEBUG
|
||||
if( freq.filelist )
|
||||
log_filelist(*freq.filelist);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void deinit_reqlist(s_reqlist *dest)
|
||||
{
|
||||
s_reqlist *ptrl, *next;
|
||||
|
||||
for( ptrl = dest; ptrl; ptrl = next )
|
||||
{
|
||||
next = ptrl->next;
|
||||
if( ptrl->fmask ) free(ptrl->fmask);
|
||||
if( ptrl->passwd ) free(ptrl->passwd);
|
||||
free(ptrl);
|
||||
}
|
||||
}
|
||||
|
||||
static void deinit_frlist(s_frlist *dest)
|
||||
{
|
||||
s_frlist *ptrl, *next;
|
||||
|
||||
for( ptrl = dest; ptrl; ptrl = next )
|
||||
{
|
||||
next = ptrl->next;
|
||||
if( ptrl->magic ) free(ptrl->magic);
|
||||
if( ptrl->path ) free(ptrl->path);
|
||||
if( ptrl->passwd ) free(ptrl->passwd);
|
||||
if( ptrl->expr ) free(ptrl->expr);
|
||||
free(ptrl);
|
||||
}
|
||||
}
|
||||
153
source/bforce/freq_srif.c
Normal file
153
source/bforce/freq_srif.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "freq.h"
|
||||
#include "session.h"
|
||||
|
||||
int req_createsrif(char *sname, char *req, char *rsp)
|
||||
{
|
||||
FILE *fp;
|
||||
char *cptr;
|
||||
s_faddr *aptr;
|
||||
char abuf[BF_MAXADDRSTR+1];
|
||||
|
||||
if( (fp = file_open(sname, "w")) == NULL )
|
||||
{
|
||||
logerr("can't create srif file \"%s\"", sname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(state.session) {
|
||||
case SESSION_EMSI:
|
||||
fprintf(fp, "SessionType EMSI\n");
|
||||
break;
|
||||
case SESSION_BINKP:
|
||||
fprintf(fp, "SessionType OTHER\n");
|
||||
break;
|
||||
case SESSION_YOOHOO:
|
||||
fprintf(fp, "SessionType WAZOO\n");
|
||||
break;
|
||||
case SESSION_FTSC:
|
||||
fprintf(fp, "SessionType FTSC0001\n");
|
||||
break;
|
||||
case SESSION_UNKNOWN:
|
||||
ASSERT_MSG();
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(fp, "Baud %ld\n",
|
||||
state.connspeed ? state.connspeed : 115200);
|
||||
|
||||
fprintf(fp, "Time -1\n");
|
||||
fprintf(fp, "RequestList %s\n", req);
|
||||
fprintf(fp, "ResponseList %s\n", rsp);
|
||||
|
||||
fprintf(fp, "RemoteStatus %s\n",
|
||||
state.protected ? "PROTECTED" : "UNPROTECTED");
|
||||
|
||||
fprintf(fp, "SystemStatus %s\n",
|
||||
state.listed ? "LISTED" : "UNLISTED");
|
||||
|
||||
if( state.handshake && state.handshake->remote_sysop_name
|
||||
&& (cptr = state.handshake->remote_sysop_name(state.handshake)) )
|
||||
fprintf(fp, "Sysop %s\n", cptr);
|
||||
else
|
||||
fprintf(fp, "Sysop SysOp\n");
|
||||
|
||||
if( state.handshake && state.handshake->remote_address
|
||||
&& (aptr = state.handshake->remote_address(state.handshake)) )
|
||||
fprintf(fp, "AKA %s\n", ftn_addrstr(abuf, *aptr));
|
||||
else
|
||||
return -1;
|
||||
|
||||
if( state.handshake && state.handshake->remote_system_name
|
||||
&& (cptr = state.handshake->remote_system_name(state.handshake)) )
|
||||
fprintf(fp, "Site %s\n", cptr);
|
||||
|
||||
if( state.handshake && state.handshake->remote_location
|
||||
&& (cptr = state.handshake->remote_location(state.handshake)) )
|
||||
fprintf(fp, "Location %s\n", cptr);
|
||||
|
||||
if( state.handshake && state.handshake->remote_phone
|
||||
&& (cptr = state.handshake->remote_phone(state.handshake)) )
|
||||
fprintf(fp, "Phone %s\n", cptr);
|
||||
|
||||
if( state.handshake && state.handshake->remote_mailer
|
||||
&& (cptr = state.handshake->remote_mailer(state.handshake)) )
|
||||
fprintf(fp, "Mailer %s\n", cptr);
|
||||
|
||||
file_close(fp);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void req_addfilelist(char *listname, s_freq *freq)
|
||||
{
|
||||
FILE *fp;
|
||||
char fnbuf[BF_MAXPATH+1], *p;
|
||||
int action = ACTION_NOTHING;
|
||||
struct stat st;
|
||||
|
||||
if( (fp = file_open(listname, "r")) == NULL )
|
||||
{
|
||||
logerr("can't open freq answer list \"%s\" (%d)", listname, strlen(listname));
|
||||
return;
|
||||
}
|
||||
|
||||
while( fgets(fnbuf, sizeof(fnbuf), fp) )
|
||||
{
|
||||
p = fnbuf;
|
||||
action = ACTION_NOTHING;
|
||||
|
||||
string_chomp(fnbuf);
|
||||
|
||||
/*
|
||||
* We won't remove leading and trailing spaces
|
||||
*/
|
||||
|
||||
if( *p == '\0' )
|
||||
continue; /* Empty line! */
|
||||
|
||||
switch(*p) {
|
||||
case '=': ++p; action = ACTION_UNLINK; break;
|
||||
case '+': ++p; action = ACTION_NOTHING; break;
|
||||
case '-': ++p; action = ACTION_FORCEUNLINK; break;
|
||||
}
|
||||
|
||||
if( stat(p, &st) == 0 )
|
||||
{
|
||||
DEB((D_FREQ, "adding file \"%s\", %d", p, st.st_size));
|
||||
|
||||
(*freq->flast) = (s_filelist*)xmalloc(sizeof(s_filelist));
|
||||
memset(*freq->flast, '\0', sizeof(s_filelist));
|
||||
|
||||
(*freq->flast)->fname = xstrcpy(p);
|
||||
(*freq->flast)->size = st.st_size;
|
||||
(*freq->flast)->action = action;
|
||||
(*freq->flast)->status = STATUS_WILLSEND;
|
||||
freq->flast = &(*freq->flast)->next;
|
||||
|
||||
freq->fnumber += 1;
|
||||
freq->fsize += st.st_size;
|
||||
}
|
||||
else
|
||||
logerr("can't stat file from answer list \"%s\"", p);
|
||||
}
|
||||
|
||||
file_close(fp);
|
||||
}
|
||||
|
||||
113
source/bforce/freq_wazoo.c
Normal file
113
source/bforce/freq_wazoo.c
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "freq.h"
|
||||
|
||||
int req_readwazooreq(char *reqname, s_reqlist **reqlist)
|
||||
{
|
||||
s_reqlist **tmpl;
|
||||
char s[BF_MAXPATH+1];
|
||||
char *p, *fname, *pwd = NULL, *older = NULL, *newer = NULL;
|
||||
char *p_ignorelist = NULL;
|
||||
FILE *fp;
|
||||
|
||||
DEB((D_FREQ, "req_readreq: open '.req' file = \"%s\"", reqname));
|
||||
|
||||
if( (fp = file_open(reqname, "r")) == NULL )
|
||||
{
|
||||
logerr("can't open req file \"%s\"", reqname);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* $tmpl must point to last entry's next field */
|
||||
for( tmpl = reqlist; *tmpl; tmpl = &(*tmpl)->next )
|
||||
{
|
||||
/* EMPTY LOOP */
|
||||
}
|
||||
|
||||
/* Get file masks that we should ignore */
|
||||
p_ignorelist = conf_string(cf_freq_ignore_masks);
|
||||
|
||||
while( fgets(s, sizeof(s), fp) )
|
||||
{
|
||||
p = s;
|
||||
fname = NULL;
|
||||
pwd = NULL;
|
||||
older = NULL;
|
||||
newer = NULL;
|
||||
|
||||
string_chomp(s);
|
||||
|
||||
/* Remove leading spaces */
|
||||
while( isspace(*p) ) ++p;
|
||||
if( *p == '\0' ) continue; /* Empty line :( */
|
||||
|
||||
/* Get file name */
|
||||
fname = p;
|
||||
while( *p && !isspace(*p) ) ++p;
|
||||
|
||||
if( *p ) *p++ = '\0';
|
||||
|
||||
/* Check our ignore list */
|
||||
if( p_ignorelist && *p_ignorelist && fname && *fname )
|
||||
{
|
||||
if( !checkmasks(p_ignorelist, fname) )
|
||||
{
|
||||
log("FREQ: ignore request \"%s\"", fname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is there possible password or update time? */
|
||||
while( *p )
|
||||
{
|
||||
/* Remove spaces between fields */
|
||||
while( isspace(*p) ) ++p;
|
||||
|
||||
switch( *p ) {
|
||||
case '!' : pwd = ++p; break;
|
||||
case '+' : older = ++p; break;
|
||||
case '-' : newer = ++p; break;
|
||||
}
|
||||
/* Get field */
|
||||
while( *p && !isspace(*p) ) ++p;
|
||||
if( *p ) *p++ = '\0';
|
||||
}
|
||||
|
||||
if( fname && *fname )
|
||||
{
|
||||
DEB((D_FREQ, "req_readreq: file=\"%s\", pwd=\"%s\", newer=\"%s\", older=\"%s\"", fname, pwd, newer, older));
|
||||
|
||||
*(tmpl) = (s_reqlist*)xmalloc(sizeof(s_reqlist));
|
||||
memset(*tmpl, '\0', sizeof(s_reqlist));
|
||||
|
||||
(*tmpl)->fmask = (char*)xstrcpy(fname);
|
||||
if( pwd && *pwd ) (*tmpl)->passwd = (char*)xstrcpy(pwd);
|
||||
if( newer && *newer ) (*tmpl)->newer = atol(newer);
|
||||
if( older && *older ) (*tmpl)->older = atol(older);
|
||||
|
||||
/* prepare $tmpl for next entry */
|
||||
tmpl = &(*tmpl)->next;
|
||||
}
|
||||
}
|
||||
|
||||
DEB((D_FREQ, "req_readreq: close '.req' file"));
|
||||
|
||||
file_close(fp);
|
||||
|
||||
return(0);
|
||||
}
|
||||
465
source/bforce/io_modem.c
Normal file
465
source/bforce/io_modem.c
Normal file
@ -0,0 +1,465 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
const char *modem_errlist[] =
|
||||
{
|
||||
"No error",
|
||||
"Modem return ERROR",
|
||||
"Can't send string to modem",
|
||||
"Modem not response",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Get connect speed from connect string returned by modem */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
long modem_getconnspeed(const char *connstr)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for( p = connstr; *p; p++ )
|
||||
{
|
||||
if( isdigit(*p) )
|
||||
return atol(p);
|
||||
}
|
||||
|
||||
return 0L;
|
||||
}
|
||||
|
||||
bool modem_isgood_phone(const char *str)
|
||||
{
|
||||
if( !str || !str[0] )
|
||||
return FALSE;
|
||||
|
||||
if( str[0] == '-' && str[1] == '\0' )
|
||||
return FALSE;
|
||||
|
||||
if( string_casestr(str, "unpublished") )
|
||||
return FALSE;
|
||||
|
||||
if( string_casestr(str, "unknown") )
|
||||
return FALSE;
|
||||
|
||||
if( string_casestr(str, "none") )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Translate phone number using given rules, returned value must be free'ed! */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
char *modem_transphone(char *buffer, const char *phone, size_t buflen)
|
||||
{
|
||||
const char *p;
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
ASSERT(phone != NULL);
|
||||
|
||||
DEB((D_MODEM, "translate_phone: want translate \"%s\"", phone));
|
||||
|
||||
for( ptrl = conf_first(cf_phone_translate); ptrl;
|
||||
ptrl = conf_next(ptrl) )
|
||||
{
|
||||
if( !ptrl->d.translate.find )
|
||||
continue;
|
||||
|
||||
if( (p = strstr(phone, ptrl->d.translate.find)) )
|
||||
{
|
||||
DEB((D_MODEM, "translate_phone: replace \"%s\" with \"%s\"",
|
||||
ptrl->d.translate.find, ptrl->d.translate.repl));
|
||||
|
||||
strnxcpy(buffer, phone, buflen);
|
||||
|
||||
if( p - phone < buflen - 1 )
|
||||
{
|
||||
buffer[p - phone] = '\0';
|
||||
|
||||
if( ptrl->d.translate.repl )
|
||||
strnxcat(buffer, ptrl->d.translate.repl, buflen);
|
||||
|
||||
strnxcat(buffer, p + strlen(ptrl->d.translate.find), buflen);
|
||||
}
|
||||
|
||||
DEB((D_MODEM, "translate_phone: result is \"%s\"", buffer));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
return strnxcpy(buffer, phone, buflen);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Send string to modem, using some control character sequences, like */
|
||||
/* '\r' - CR, '\P' - phone number, etc.. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int modem_putstr(const char *str)
|
||||
{
|
||||
const char *ptr;
|
||||
int rc;
|
||||
bool flushed = FALSE;
|
||||
|
||||
DEB((D_MODEM, "modem_putstr: want to send \"%s\"", str));
|
||||
|
||||
rc = TTY_SUCCESS;
|
||||
ptr = str;
|
||||
|
||||
while( *ptr )
|
||||
{
|
||||
/* Flush buffer before "special" operations */
|
||||
if( !flushed && strchr("~`^v", *ptr) )
|
||||
{
|
||||
flushed = TRUE;
|
||||
if( (rc = tty_flushout()) < 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch( *ptr ) {
|
||||
case '~':
|
||||
sleep(1);
|
||||
break;
|
||||
case '`':
|
||||
usleep(250000L);
|
||||
break;
|
||||
case '^':
|
||||
rc = tio_set_dtr(0, 1);
|
||||
break;
|
||||
case 'v':
|
||||
rc = tio_set_dtr(0, 0);
|
||||
break;
|
||||
case '|':
|
||||
case '\r':
|
||||
rc = tty_putc('\r', 2);
|
||||
if( !rc && !(rc = tty_flushout()) )
|
||||
{
|
||||
/*
|
||||
* Make sure that we will never send
|
||||
* anything to the modem immediately
|
||||
* after CR
|
||||
*/
|
||||
/* i changed value for my modem
|
||||
* (from 250000 */
|
||||
usleep(500000);
|
||||
flushed = TRUE;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
++ptr;
|
||||
switch(*ptr) {
|
||||
case '\0':
|
||||
rc = tty_putc('\\', 2);
|
||||
break;
|
||||
case 'r':
|
||||
rc = tty_putc('\r', 2);
|
||||
break;
|
||||
case 'n':
|
||||
rc = tty_putc('\n', 2);
|
||||
break;
|
||||
default:
|
||||
rc = tty_putc(*ptr, 2);
|
||||
}
|
||||
flushed = FALSE;
|
||||
break;
|
||||
default:
|
||||
rc = tty_putc(*ptr, 2);
|
||||
flushed = FALSE;
|
||||
}
|
||||
|
||||
if( rc < 0 )
|
||||
return rc;
|
||||
|
||||
++ptr;
|
||||
}
|
||||
|
||||
if( !flushed && (rc = tty_flushout()) < 0 )
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void modem_clearin(int timeout)
|
||||
{
|
||||
time_t timer;
|
||||
|
||||
timer_set(&timer, timeout);
|
||||
|
||||
while( CHARWAIT(1) )
|
||||
{
|
||||
CLEARIN();
|
||||
|
||||
if( timer_expired(timer) )
|
||||
return;
|
||||
|
||||
usleep(100000); /* 0.1 seconds delay */
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Reads in at most one less than $bufsize characters from modem and */
|
||||
/* stores them into the buffer pointed to by $buf, check for timeout. */
|
||||
/* $timer must be set with tty_settimer() call! */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int modem_getline(char *buf, int bufsize, time_t timer)
|
||||
{
|
||||
int rc = 0, pos = 0;
|
||||
|
||||
ASSERT(buf != NULL || bufsize == 0);
|
||||
|
||||
while(1)
|
||||
{
|
||||
if( timer_expired(timer) )
|
||||
return TTY_TIMEOUT;
|
||||
|
||||
if( (rc = tty_getc(1)) < 0 && rc != TTY_TIMEOUT )
|
||||
return rc;
|
||||
else if( rc == '\r' || rc == '\n' )
|
||||
return pos;
|
||||
else if( rc > 0 )
|
||||
{
|
||||
if( pos < bufsize-1 )
|
||||
{
|
||||
buf[pos++] = rc;
|
||||
buf[pos ] = '\0';
|
||||
} else
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Dial using phone number $phone, if connection will be established - */
|
||||
/* put connect string to *connstr (must be freed) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int modem_dial(const char *dialstr, int timeout, char **connstr)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
char buf[MODEM_MAX_RESP+1];
|
||||
time_t timer;
|
||||
int len = 0;
|
||||
|
||||
ASSERT(dialstr != NULL && connstr != NULL);
|
||||
|
||||
*connstr = NULL;
|
||||
|
||||
if( modem_putstr(dialstr) != TTY_SUCCESS )
|
||||
{
|
||||
log("error sending dial string \"%s\"", dialstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timer_set(&timer, timeout);
|
||||
|
||||
while(1)
|
||||
{
|
||||
if( timer_expired(timer) )
|
||||
{
|
||||
log("dialing timed out");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (len = modem_getline(buf, sizeof(buf), timer)) < 0 )
|
||||
{
|
||||
if( len == TTY_TIMEOUT )
|
||||
log("dialing timed out");
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if( len > 0 )
|
||||
{
|
||||
DEB((D_MODEM, "modem_dial: got \"%s\"", buf));
|
||||
|
||||
for( ptrl = conf_first(cf_modem_dial_response); ptrl;
|
||||
ptrl = conf_next(ptrl) )
|
||||
{
|
||||
if( ptrl->d.dialresp.mstr && strstr(buf, ptrl->d.dialresp.mstr) )
|
||||
{
|
||||
if( ptrl->d.dialresp.retv == RESPTYPE_CONNECT )
|
||||
{
|
||||
*connstr = xstrcpy(buf);
|
||||
return 0;
|
||||
}
|
||||
return ptrl->d.dialresp.retv;
|
||||
}
|
||||
}
|
||||
if( *buf )
|
||||
log("modem: \"%s\"", string_printable(buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int modem_command(const char *command, int timeout, bool logit)
|
||||
{
|
||||
time_t timer;
|
||||
size_t count = 0;
|
||||
int len = 0;
|
||||
char buffer[MODEM_MAX_RESP+1];
|
||||
char cmdstr[MODEM_MAX_COMMAND+1];
|
||||
char *n;
|
||||
char *p;
|
||||
|
||||
ASSERT(command != NULL);
|
||||
|
||||
strnxcpy(cmdstr, command, sizeof(cmdstr));
|
||||
|
||||
DEB((D_MODEM, "modem_command: command string \"%s\"", cmdstr));
|
||||
|
||||
CLEARIN();
|
||||
|
||||
for( p = string_token(cmdstr, &n, NULL, 1); p;
|
||||
p = string_token(NULL, &n, NULL, 1) )
|
||||
{
|
||||
DEB((D_MODEM, "modem_command: send \"%s\"",
|
||||
string_printable(p)));
|
||||
|
||||
if( modem_putstr(p) < 0 )
|
||||
return MODEM_CANTSEND;
|
||||
|
||||
count = 0;
|
||||
timer_set(&timer, timeout);
|
||||
|
||||
while(1)
|
||||
{
|
||||
if( timer_expired(timer) )
|
||||
return MODEM_NORESP;
|
||||
|
||||
if( (len = modem_getline(buffer, sizeof(buffer), timer)) < 0 )
|
||||
{
|
||||
return MODEM_NORESP;
|
||||
}
|
||||
else if( len > 0 )
|
||||
{
|
||||
count += len;
|
||||
|
||||
if( count > MODEM_MAX_RESP_SIZE )
|
||||
{
|
||||
log("modem response exceeds limit %ld bytes",
|
||||
(long)count);
|
||||
return MODEM_NORESP;
|
||||
}
|
||||
|
||||
DEB((D_MODEM, "modem_command: got \"%s\"",
|
||||
string_printable(buffer)));
|
||||
|
||||
if( !strcmp(buffer, "ERROR") )
|
||||
return MODEM_ERROR;
|
||||
else if( !strcmp(buffer, "OK") )
|
||||
break;
|
||||
else if( logit )
|
||||
log("modem: \"%s\"", string_printable(buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MODEM_OK;
|
||||
}
|
||||
|
||||
int modem_hangup(const char *command, int timeout)
|
||||
{
|
||||
#ifdef MODEM_HANGUP_WATCH_CARRIER
|
||||
time_t timer;
|
||||
|
||||
ASSERT(command != NULL);
|
||||
|
||||
if( tio_get_dcd(0) == 1 )
|
||||
{
|
||||
DEB((D_MODEM, "modem_hangup: send \"%s\"", command));
|
||||
|
||||
if( modem_putstr(command) < 0 )
|
||||
return MODEM_CANTSEND;
|
||||
|
||||
timer_set(&timer, timeout);
|
||||
|
||||
while( tio_get_dcd(0) == 1 )
|
||||
{
|
||||
if( timer_expired(timer) )
|
||||
return MODEM_NORESP;
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
sleep(2); CLEARIN(); CLEAROUT();
|
||||
|
||||
return MODEM_OK;
|
||||
#else /* MODEM_HANGUP_WATCH_CARRIER */
|
||||
return modem_command(command, timeout, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool modem_candialout(const char *modemdev)
|
||||
{
|
||||
char tmp[BF_MAXPATH+1];
|
||||
const char *p_nodial = conf_string(cf_nodial_flag);
|
||||
char *p = NULL;
|
||||
|
||||
if( p_nodial && *p_nodial )
|
||||
{
|
||||
if( access(p_nodial, F_OK) == 0 )
|
||||
return FALSE;
|
||||
|
||||
strnxcpy(tmp, p_nodial, sizeof(tmp));
|
||||
strnxcat(tmp, ".", sizeof(tmp));
|
||||
strnxcat(tmp, (p = port_get_name(modemdev)), sizeof(tmp));
|
||||
|
||||
if( p )
|
||||
free(p);
|
||||
|
||||
if( access(tmp, F_OK) == 0 )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Return pointer to the first not locked now tty */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
s_modemport *modem_getfree_port(const char *lockdir)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
/* Find first not locked modem device */
|
||||
for( ptrl = conf_first(cf_modem_port); ptrl; ptrl = conf_next(ptrl) )
|
||||
{
|
||||
if( port_checklock(lockdir, &ptrl->d.modemport) == LOCKCHECK_NOLOCK
|
||||
&& modem_candialout(ptrl->d.modemport.name) == TRUE )
|
||||
return &ptrl->d.modemport;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Return pointer to the first tty whose name contain substring `ttyname' */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
s_modemport *modem_getmatch_port(const char *substr)
|
||||
{
|
||||
s_cval_entry *ptrl;
|
||||
|
||||
/* Find first matching modem device */
|
||||
for( ptrl = conf_first(cf_modem_port); ptrl; ptrl = conf_next(ptrl) )
|
||||
{
|
||||
if( strstr(ptrl->d.modemport.name, substr) )
|
||||
return &ptrl->d.modemport;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
250
source/bforce/io_tcpip.c
Normal file
250
source/bforce/io_tcpip.c
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
#define DEFAULT_PORT 60179 /* Birthday .. mother fucker :) */
|
||||
|
||||
static RETSIGTYPE tcpip_interrupt(int sig)
|
||||
{
|
||||
tty_abort = TRUE;
|
||||
log("terminating on signal %d", sig);
|
||||
}
|
||||
|
||||
static RETSIGTYPE tcpip_brokenpipe(int sig)
|
||||
{
|
||||
tty_abort = TRUE;
|
||||
if( tty_online )
|
||||
log("connection closed");
|
||||
else
|
||||
log("terminating on signal %d", sig);
|
||||
}
|
||||
|
||||
static int tcpip_connect2(struct sockaddr_in server)
|
||||
{
|
||||
int fd;
|
||||
|
||||
DEB((D_INFO, "tcpip_connect2: trying \"%s\" at port %d",
|
||||
inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port)));
|
||||
|
||||
if( (fd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
|
||||
{
|
||||
logerr("can't create socket");
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* make new fd == stdin if it isn't already */
|
||||
if( fd > 0 )
|
||||
{
|
||||
(void)close(0);
|
||||
if( dup(fd) != 0 )
|
||||
{
|
||||
logerr("cannot dup socket to stdin");
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* make stdout and stderr, too */
|
||||
(void)close(1);
|
||||
(void)close(2);
|
||||
|
||||
if( dup(0) != 1 )
|
||||
{
|
||||
logerr("cannot dup stdin to stdout");
|
||||
return(1);
|
||||
}
|
||||
if( dup(0) != 2 )
|
||||
{
|
||||
logerr("cannot dup stdin to stderr");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if( fd > 2 ) (void)close(fd);
|
||||
|
||||
/* switch off stdio buffering */
|
||||
setbuf(stdin, (char *)NULL);
|
||||
setbuf(stdout, (char *)NULL);
|
||||
setbuf(stderr, (char *)NULL);
|
||||
|
||||
clearerr(stdin);
|
||||
clearerr(stdout);
|
||||
clearerr(stderr);
|
||||
|
||||
if( connect(0, (struct sockaddr*)&server, sizeof(server)) == -1 )
|
||||
{
|
||||
logerr("can't connect to %s", inet_ntoa(server.sin_addr));
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( tcpip_init() )
|
||||
{
|
||||
tcpip_shutdown();
|
||||
return 1;
|
||||
}
|
||||
|
||||
log("TCP/IP connect to %s on port %d",
|
||||
inet_ntoa(server.sin_addr), (int)ntohs(server.sin_port));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int tcpip_connect(const char *hostname, e_tcpmode tcpmode)
|
||||
{
|
||||
int rc = 0;
|
||||
struct hostent *he = NULL;
|
||||
struct servent *se = NULL;
|
||||
struct sockaddr_in server;
|
||||
char *host = xstrcpy(hostname);
|
||||
char *p = strrchr(host, ':');
|
||||
const char *port = NULL;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
|
||||
if( p )
|
||||
{ *p++ = '\0'; port = p; }
|
||||
else if( tcpmode == TCPMODE_BINKP )
|
||||
port = "binkp";
|
||||
else if( tcpmode == TCPMODE_TELNET )
|
||||
port = "telnet";
|
||||
else /* Default service name is "fido" */
|
||||
port = "fido";
|
||||
|
||||
if( ISDEC(port) )
|
||||
server.sin_port = htons(atoi(port));
|
||||
else if( (se = getservbyname(port, "tcp")) )
|
||||
server.sin_port = se->s_port;
|
||||
else
|
||||
{ log("invalid port or service name \"%s\"", port); rc = 1; }
|
||||
|
||||
if( rc == 0 )
|
||||
{
|
||||
if( (he = gethostbyname(host)) )
|
||||
{
|
||||
memcpy(&server.sin_addr, he->h_addr, he->h_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = 1;
|
||||
switch(h_errno) {
|
||||
case HOST_NOT_FOUND:
|
||||
log("host \"%s\" not found", host);
|
||||
break;
|
||||
case NO_ADDRESS:
|
||||
log("no IP address found for host \"%s\"", host);
|
||||
break;
|
||||
case NO_RECOVERY:
|
||||
log("non-recoverable name server error occured");
|
||||
break;
|
||||
case TRY_AGAIN:
|
||||
log("temporary error occured on name server");
|
||||
break;
|
||||
default:
|
||||
log("unknown error while resolving host \"%s\"", host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( host ) { free(host); host = NULL; }
|
||||
|
||||
return rc ? rc : tcpip_connect2(server);
|
||||
}
|
||||
|
||||
int tcpip_init(void)
|
||||
{
|
||||
int nbio_arg = 1;
|
||||
int alive_arg = 1;
|
||||
struct linger lingeropt;
|
||||
|
||||
tty_online = TRUE;
|
||||
tty_abort = FALSE;
|
||||
tty_hangup = FALSE;
|
||||
tty_modem = FALSE;
|
||||
|
||||
/*
|
||||
* Set sockets I/O to the non-blocking mode
|
||||
*/
|
||||
if( ioctl(0, FIONBIO, (char *)&nbio_arg, sizeof(nbio_arg)) == -1 )
|
||||
{
|
||||
logerr("failed to set non-blocking mode for stdin");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( ioctl(1, FIONBIO, (char *)&nbio_arg, sizeof(nbio_arg)) == -1 )
|
||||
{
|
||||
logerr("failed to set non-blocking mode for stdout");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set SO_LONGER socket option, so then we will close
|
||||
* socket the system will block our close() call and
|
||||
* try to deliver queued data.
|
||||
*/
|
||||
memset(&lingeropt, '\0', sizeof(struct linger));
|
||||
|
||||
lingeropt.l_onoff = 1;
|
||||
lingeropt.l_linger = 5*100; /* 5 seconds */
|
||||
|
||||
if( setsockopt(1, SOL_SOCKET, SO_LINGER, (char*)&lingeropt, sizeof(struct linger)) == -1 )
|
||||
{
|
||||
logerr("failed to set SO_LINGER socket option for the stdout");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set SO_KEEPALIVE socket option. The connection will be
|
||||
* considered broken if remote side fail to respond on
|
||||
* periodicaly transmitted message. We should not hang
|
||||
* even without such features.
|
||||
*/
|
||||
if( setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char*)&alive_arg, sizeof(alive_arg)) == -1 )
|
||||
{
|
||||
logerr("failed to set SO_KEEPALIVE socket option");
|
||||
return 1;
|
||||
}
|
||||
|
||||
signal(SIGHUP, tcpip_interrupt);
|
||||
signal(SIGINT, tcpip_interrupt);
|
||||
signal(SIGTERM, tcpip_interrupt);
|
||||
signal(SIGPIPE, tcpip_brokenpipe);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int tcpip_shutdown(void)
|
||||
{
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool tcpip_isgood_host(const char *str)
|
||||
{
|
||||
if( !str || !str[0] )
|
||||
return FALSE;
|
||||
|
||||
if( str[0] == '-' && str[1] == '\0' )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
379
source/bforce/io_unix_lock.c
Normal file
379
source/bforce/io_unix_lock.c
Normal file
@ -0,0 +1,379 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* Set lock files type: Ascii, binary or SVR4? (not implemented yet)
|
||||
*/
|
||||
#if (BFORCE_LOCK_TYPE == 1)
|
||||
# define LOCK_ASCII
|
||||
#elif (BFORCE_LOCK_TYPE == 2)
|
||||
# define LOCK_BIN
|
||||
#else
|
||||
# error "Not implemented lock files type (BFORCE_LOCK_TYPE)"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set lock files directory
|
||||
*/
|
||||
#ifndef BFORCE_LOCK_DIR
|
||||
# error "Not defined lock files directory (BFORCE_LOCK_DIR)"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set prefix for lock file names
|
||||
*/
|
||||
#ifndef BFORCE_LOCK_PREFIX
|
||||
# define BFORCE_LOCK_PREFIX "LCK.."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How much times we will try to lock (if device
|
||||
* is allready locked by another process)
|
||||
*/
|
||||
#ifndef BFORCE_LOCK_TRIES
|
||||
# define BFORCE_LOCK_TRIES 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Delay in seconds between tries
|
||||
*/
|
||||
#ifndef BFORCE_LOCK_DELAY
|
||||
# define BFORCE_LOCK_DELAY 1
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
/* "Low level" interface for tty lock files access (private) */
|
||||
/* */
|
||||
/* char *lock_getname(const char *lockdir, const s_modemport *modemport) */
|
||||
/* pid_t lock_read_pid(const char *lckname) */
|
||||
/* int lock_check(const char *lckname) */
|
||||
/* int lock_create(const char *lckname, const char *tmpname) */
|
||||
/* */
|
||||
/* ========================================================================= */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Get lock file name with full path (this value must be free'ed) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static char *lock_getname(const char *lockdir, const s_modemport *modemport)
|
||||
{
|
||||
char *lckname;
|
||||
char *p = NULL;
|
||||
|
||||
ASSERT(modemport != NULL);
|
||||
|
||||
if( lockdir && *lockdir )
|
||||
lckname = (char *)xstrcpy(lockdir);
|
||||
else
|
||||
lckname = (char *)xstrcpy(BFORCE_LOCK_DIR);
|
||||
|
||||
lckname = (char *)xstrcat(lckname, BFORCE_LOCK_PREFIX);
|
||||
lckname = (char *)xstrcat(lckname, (p = port_get_name(modemport->name)));
|
||||
|
||||
if( p )
|
||||
free(p);
|
||||
|
||||
return lckname;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Get lock file's PID. Return zero on error and leave errno with last error */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static pid_t lock_read_pid(const char *lckname)
|
||||
{
|
||||
int len, fd;
|
||||
pid_t pid;
|
||||
char buf[32];
|
||||
|
||||
ASSERT(lckname != NULL);
|
||||
|
||||
if( (fd = open(lckname, O_RDONLY)) < 0 )
|
||||
return 0;
|
||||
|
||||
if( (len = read(fd, buf, sizeof(buf)-1)) < 0 )
|
||||
{
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
if( len == sizeof(pid) || sscanf(buf, "%d", &pid) != 1 || pid == 0 )
|
||||
{
|
||||
/* We found binary lock file? */
|
||||
pid = *((int *)buf);
|
||||
#ifndef LOCK_BINARY
|
||||
log("warning: found binary lock file %s", lckname);
|
||||
#endif
|
||||
}
|
||||
#ifdef LOCK_BINARY
|
||||
else
|
||||
{
|
||||
/* Found ASCII lock file */
|
||||
log("warning: found ascii lock file %s", lckname);
|
||||
}
|
||||
#endif
|
||||
close(fd);
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Validate lock file, check it's process still lives. */
|
||||
/* Return: */
|
||||
/* CHECKLOCK_NOLOCK - no lock file found */
|
||||
/* CHECKLOCK_LOCKED - valid lock file */
|
||||
/* CHECKLOCK_ERROR - invalid lock file name, access error, etc. */
|
||||
/* CHECKLOCK_OURLOCK - if it is our lock file (with our PID) */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static int lock_check(const char *lckname)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
struct stat st;
|
||||
|
||||
ASSERT(lckname != NULL);
|
||||
|
||||
if( stat(lckname, &st) && errno == ENOENT )
|
||||
return LOCKCHECK_NOLOCK;
|
||||
|
||||
if( (pid = lock_read_pid(lckname)) == 0 )
|
||||
{
|
||||
if( errno == ENOENT )
|
||||
return LOCKCHECK_NOLOCK;
|
||||
return LOCKCHECK_LOCKED;
|
||||
}
|
||||
|
||||
DEB((D_MODEM, "lock_check: lock PID = %d", pid));
|
||||
|
||||
if( pid == getpid() )
|
||||
{ return LOCKCHECK_OURLOCK; }
|
||||
|
||||
if( kill(pid, 0) == -1 )
|
||||
{
|
||||
if( errno == ESRCH )
|
||||
{
|
||||
/*
|
||||
* That process no longer exists, remove lock file
|
||||
*/
|
||||
log("found stale lock file with PID %d", pid);
|
||||
|
||||
if( unlink(lckname) == -1 )
|
||||
{
|
||||
logerr("cannot remove lockfile \"%s\", lckname");
|
||||
return LOCKCHECK_ERROR;
|
||||
} else
|
||||
return LOCKCHECK_NOLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOCKCHECK_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* locking process still lives */
|
||||
return LOCKCHECK_LOCKED;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Create lock file using link(tmpname, lckname). Return zero on success. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static int lock_create(const char *lckname, const char *tmpname)
|
||||
{
|
||||
int rc, fd;
|
||||
int tries;
|
||||
|
||||
#ifdef LOCK_BINARY
|
||||
pid_t pid;
|
||||
#else
|
||||
char buf[32];
|
||||
#endif
|
||||
|
||||
ASSERT(lckname != NULL && tmpname != NULL);
|
||||
|
||||
if( (fd = open(tmpname, O_CREAT | O_RDWR, 0644)) < 0 )
|
||||
{
|
||||
logerr("can't open temp file \"%s\"", tmpname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
chmod(tmpname, 0644);
|
||||
|
||||
#ifdef LOCK_BINARY
|
||||
pid = getpid();
|
||||
rc = ( write(fd, (char *)&pid, sizeof(pid)) != sizeof(pid) );
|
||||
#else
|
||||
sprintf(buf, "%10d\n", (int)getpid());
|
||||
rc = ( write(fd, (char *)buf, strlen(buf)) != strlen(buf) );
|
||||
#endif
|
||||
close(fd);
|
||||
|
||||
if( rc )
|
||||
{
|
||||
logerr("can't write PID to temp. lock file \"%s\"", tmpname);
|
||||
unlink(tmpname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for( tries = 0; tries < BFORCE_LOCK_TRIES; tries++ )
|
||||
{
|
||||
if( link(tmpname, lckname) == -1 )
|
||||
{
|
||||
if( errno == EEXIST )
|
||||
{
|
||||
rc = lock_check(lckname);
|
||||
if( rc == LOCKCHECK_ERROR )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if( rc == LOCKCHECK_OURLOCK )
|
||||
{
|
||||
/* There is our lock! :) */
|
||||
unlink(tmpname);
|
||||
return 0;
|
||||
}
|
||||
else if( rc == LOCKCHECK_LOCKED )
|
||||
{
|
||||
/* sleep some time */
|
||||
sleep(BFORCE_LOCK_DELAY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("can't create link to temp. lock file \"%s\"", lckname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Successful lock */
|
||||
unlink(tmpname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Can't create lock file */
|
||||
unlink(tmpname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
/* PUBLIC functions for tty lock files access */
|
||||
/* */
|
||||
/* int port_checklock(const char *lockdir, const char *dev) */
|
||||
/* int port_lock(char *lockdir, char *dev) */
|
||||
/* int port_unlock(const char *lockdir, const char *dev) */
|
||||
/* */
|
||||
/* ========================================================================= */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Check, is tty locked? Return one of return values of lock_check() */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int port_checklock(const char *lockdir, const s_modemport *modemport)
|
||||
{
|
||||
int rc;
|
||||
char *lckname;
|
||||
|
||||
if( (lckname = lock_getname(lockdir, modemport)) == NULL )
|
||||
{
|
||||
log("can't get lock file name");
|
||||
return LOCKCHECK_ERROR;
|
||||
}
|
||||
|
||||
DEB((D_MODEM, "checkttylock: lock device = \"%s\", lockfile = \"%s\"",
|
||||
modemport->name, lckname));
|
||||
|
||||
rc = lock_check(lckname);
|
||||
|
||||
if( lckname )
|
||||
free(lckname);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Lock serial port. On success return zero value */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int port_lock(const char *lockdir, const s_modemport *modemport)
|
||||
{
|
||||
int rc;
|
||||
char *lckname;
|
||||
char *tmpname, *p_tmpname;
|
||||
|
||||
if( lockdir && *lockdir )
|
||||
tmpname = xstrcpy(lockdir);
|
||||
else
|
||||
tmpname = xstrcpy(BFORCE_LOCK_DIR);
|
||||
|
||||
tmpname = xstrcat(tmpname, "bfXXXXXX");
|
||||
|
||||
if( (p_tmpname = mktemp(tmpname)) == NULL )
|
||||
{
|
||||
logerr("can't generate unique file name from \"%s\"", tmpname);
|
||||
free(tmpname); return 1;
|
||||
}
|
||||
|
||||
if( (lckname = lock_getname(lockdir, modemport)) == NULL )
|
||||
{
|
||||
log("can't get lock file name");
|
||||
return(1);
|
||||
}
|
||||
|
||||
DEB((D_MODEM, "locktty: lock device = \"%s\", tmpfile = \"%s\", lockfile = \"%s\"",
|
||||
modemport->name, p_tmpname, lckname));
|
||||
|
||||
rc = lock_create(lckname, p_tmpname);
|
||||
|
||||
if( tmpname )
|
||||
free(tmpname);
|
||||
if( lckname )
|
||||
free(lckname);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Unlock serial port. Return zero on success. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
int port_unlock(const char *lockdir, const s_modemport *modemport)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
char *lckname;
|
||||
|
||||
if( (lckname = lock_getname(lockdir, modemport)) == NULL )
|
||||
return 1;
|
||||
|
||||
DEB((D_MODEM, "unlocktty: unlock device = \"%s\", lockfile = \"%s\"",
|
||||
modemport->name, lckname));
|
||||
|
||||
if( (pid = lock_read_pid(lckname)) == 0 )
|
||||
{
|
||||
free(lckname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( pid == getpid() && unlink(lckname) == -1 )
|
||||
{
|
||||
free(lckname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(lckname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
242
source/bforce/io_unix_modem.c
Normal file
242
source/bforce/io_unix_modem.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* Get verbal device name, remove "/dev/" part and replace all '/'
|
||||
* characters by the '-' character. Returned value must be freed.
|
||||
*/
|
||||
char *port_get_name(const char *devname)
|
||||
{
|
||||
char *yield = NULL;
|
||||
|
||||
if( !devname )
|
||||
yield = xstrcpy("unknown");
|
||||
else if( !strncmp(devname, "/dev/", 5) )
|
||||
yield = xstrcpy(devname + 5);
|
||||
else
|
||||
yield = xstrcpy(devname);
|
||||
|
||||
string_replchar(yield, '/', '-');
|
||||
|
||||
return yield;
|
||||
}
|
||||
|
||||
#ifndef MODEM_WATCH_CARRIER
|
||||
static RETSIGTYPE linedrop(int sig)
|
||||
{
|
||||
if( tty_online )
|
||||
{
|
||||
log("carrier lost");
|
||||
tty_hangup = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("terminating on signal %d", sig);
|
||||
tty_abort = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static RETSIGTYPE interrupt(int sig)
|
||||
{
|
||||
tty_abort = TRUE;
|
||||
log("terminating on signal %d", sig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open modem device $port, save old termios to $oldtio
|
||||
*/
|
||||
int port_open(const s_modemport *port, int detach, TIO *oldtio)
|
||||
{
|
||||
int fd;
|
||||
|
||||
ASSERT(port != NULL);
|
||||
|
||||
DEB((D_MODEM, "openport: open device \"%s\" locked at %ld",
|
||||
port->name, (long)port->speed));
|
||||
|
||||
if( (fd = open(port->name, O_RDWR | O_NONBLOCK)) < 0 )
|
||||
{ logerr("cannot open device \"%s\"", port->name); return 1; }
|
||||
|
||||
/* make new fd == stdin if it isn't already */
|
||||
if( fd > 0 )
|
||||
{
|
||||
if( detach )
|
||||
(void)close(0);
|
||||
if( dup(fd) != 0 )
|
||||
{ logerr("cannot make device \"%s\" stdin", port->name); return(1); }
|
||||
}
|
||||
|
||||
/* make stdout and stderr, too */
|
||||
if( detach )
|
||||
{ (void)close(1); (void)close(2); }
|
||||
|
||||
if( dup(0) != 1 )
|
||||
{ logerr("cannot dup stdin to stdout"); return(1); }
|
||||
|
||||
if( dup(0) != 2 )
|
||||
{ logerr("cannot dup stdin to stderr"); return(1); }
|
||||
|
||||
if( fd > 2 )
|
||||
(void)close(fd);
|
||||
|
||||
/* Set port modes (LOCAL mode) */
|
||||
if( port_init(0, port->speed, oldtio, TRUE) )
|
||||
return(1);
|
||||
|
||||
/* Make it controlling tty */
|
||||
if( detach )
|
||||
tio_ctty(0);
|
||||
|
||||
/*
|
||||
* Switch off stdio buffering. We are
|
||||
* not going to use streamed I/O, but..
|
||||
*/
|
||||
setbuf(stdin, (char *)NULL);
|
||||
setbuf(stdout, (char *)NULL);
|
||||
setbuf(stderr, (char *)NULL);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set terminal options as required. Don't forget that settings of
|
||||
* the file descriptor copies made with dup() are shared.
|
||||
*/
|
||||
int port_init(int fd, int portspeed, TIO *oldtio, bool local)
|
||||
{
|
||||
TIO tio;
|
||||
|
||||
/* Install signal handlers */
|
||||
#ifdef MODEM_WATCH_CARRIER
|
||||
signal(SIGHUP, interrupt);
|
||||
#else
|
||||
signal(SIGHUP, linedrop);
|
||||
#endif
|
||||
signal(SIGINT, interrupt);
|
||||
signal(SIGTERM, interrupt);
|
||||
|
||||
/*
|
||||
* Set descriptor I/O to the non-blocking mode
|
||||
*/
|
||||
if( fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) == -1 )
|
||||
{
|
||||
logerr("cannot set non-blocking mode for stdin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( isatty(fd) )
|
||||
{
|
||||
/* Report to tty I/O routines that we are using modem */
|
||||
tty_modem = 1;
|
||||
|
||||
if( tio_get(fd, &tio) == -1 )
|
||||
{
|
||||
logerr("initport error: cannot get terminal settings");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save old settings. We will restore them on exit.
|
||||
*/
|
||||
if( oldtio )
|
||||
*oldtio = tio;
|
||||
|
||||
/* Set "raw" mode */
|
||||
tio_set_raw_mode(&tio);
|
||||
|
||||
/* Set hardware flow control */
|
||||
if( tio_set_flow_control(fd, &tio, FLOW_HARD) == -1 )
|
||||
return -1;
|
||||
|
||||
/* Should we ignore DCD? */
|
||||
#ifdef MODEM_WATCH_CARRIER
|
||||
tio_set_local(&tio, TRUE);
|
||||
#else
|
||||
tio_set_local(&tio, local);
|
||||
#endif
|
||||
|
||||
/* Set port speed */
|
||||
if( portspeed )
|
||||
{
|
||||
/* set bit rate */
|
||||
tio_set_speed(&tio, portspeed);
|
||||
}
|
||||
|
||||
if( tio_set(fd, &tio) == -1 )
|
||||
{
|
||||
logerr("initport error: cannot set terminal settings");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int port_carrier(int fd, bool online)
|
||||
{
|
||||
tty_online = online;
|
||||
|
||||
#ifndef MODEM_WATCH_CARRIER
|
||||
if( isatty(fd) )
|
||||
{
|
||||
TIO tio;
|
||||
|
||||
if( tio_get(fd, &tio) == -1 )
|
||||
{
|
||||
logerr("port_carrier error: cannot get terminal settings");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tio_set_local(&tio, online ? FALSE : TRUE);
|
||||
|
||||
if( tio_set(fd, &tio) == -1 )
|
||||
{
|
||||
logerr("port_carrier error: cannot set terminal settings");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore old terminal settings
|
||||
*/
|
||||
int port_deinit(int fd, TIO *oldtio)
|
||||
{
|
||||
if( tio_set(fd, oldtio) == -1 )
|
||||
{
|
||||
logerr("deinitport error: cannot restore terminal settings");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Close port
|
||||
*/
|
||||
void port_close(void)
|
||||
{
|
||||
DEB((D_MODEM, "closeport: close modem port"));
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
336
source/bforce/io_unix_tio.c
Normal file
336
source/bforce/io_unix_tio.c
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* Hardware handshake flags (stolen from mgetty)
|
||||
*/
|
||||
#ifdef CRTSCTS
|
||||
# define TIO_FLOW_HARD CRTSCTS /* linux, SunOS */
|
||||
#else
|
||||
# ifdef CRTSFL
|
||||
# define TIO_FLOW_HARD CRTSFL /* SCO 3.2v4.2 */
|
||||
# else
|
||||
# ifdef RTSFLOW
|
||||
# define TIO_FLOW_HARD RTSFLOW | CTSFLOW /* SCO 3.2v2 */
|
||||
# else
|
||||
# ifdef CTSCD
|
||||
# define TIO_FLOW_HARD CTSCD /* AT&T 3b1? */
|
||||
# else
|
||||
# define TIO_FLOW_HARD 0
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Software hadshake flags
|
||||
*/
|
||||
#define TIO_FLOW_SOFT (IXON | IXOFF)
|
||||
|
||||
/*
|
||||
* Supported baud rates
|
||||
*/
|
||||
static struct speedtab {
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
speed_t bspeed;
|
||||
#else
|
||||
unsigned short bspeed;
|
||||
#endif
|
||||
int nspeed;
|
||||
const char *speed;
|
||||
} speedtab[] = {
|
||||
{ B300, 300, "300" },
|
||||
#ifdef B600
|
||||
{ B600, 600, "600" },
|
||||
#endif
|
||||
#ifdef B900
|
||||
{ B900, 900, "900" },
|
||||
#endif
|
||||
{ B1200, 1200, "1200" },
|
||||
#ifdef B1800
|
||||
{ B1800, 1800, "1800" },
|
||||
#endif
|
||||
{ B2400, 2400, "2400" },
|
||||
#ifdef B3600
|
||||
{ B3600, 3600, "3600" },
|
||||
#endif
|
||||
{ B4800, 4800, "4800" },
|
||||
#ifdef B7200
|
||||
{ B7200, 7200, "7200" },
|
||||
#endif
|
||||
{ B9600, 9600, "9600" },
|
||||
#ifdef B14400
|
||||
{ B14400, 14400, "14400" },
|
||||
#endif
|
||||
#ifdef B19200
|
||||
{ B19200, 19200, "19200" },
|
||||
#endif /* B19200 */
|
||||
#ifdef B28800
|
||||
{ B28800, 28800, "28800" },
|
||||
#endif
|
||||
#ifdef B38400
|
||||
{ B38400, 38400, "38400" },
|
||||
#endif /* B38400 */
|
||||
#ifdef EXTA
|
||||
{ EXTA, 19200, "EXTA" },
|
||||
#endif
|
||||
#ifdef EXTB
|
||||
{ EXTB, 38400, "EXTB" },
|
||||
#endif
|
||||
#ifdef B57600
|
||||
{ B57600, 57600, "57600" },
|
||||
#endif
|
||||
#ifdef B76800
|
||||
{ B76800, 76800, "76800" },
|
||||
#endif
|
||||
#ifdef B115200
|
||||
{ B115200, 115200, "115200" },
|
||||
#endif
|
||||
#ifdef B230400
|
||||
{ B230400, 230400, "230400" },
|
||||
#endif
|
||||
#ifdef B460800
|
||||
{ B460800, 460800, "460800" },
|
||||
#endif
|
||||
{ 0, 0, "" }
|
||||
};
|
||||
|
||||
|
||||
/* get current tio settings for given filedescriptor */
|
||||
|
||||
int tio_get(int fd, TIO *tio)
|
||||
{
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
return tcgetattr(fd, tio);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set current tio settings for given filedescriptor */
|
||||
|
||||
int tio_set(int fd, TIO *tio)
|
||||
{
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
return tcsetattr(fd, TCSANOW, tio);
|
||||
#endif
|
||||
}
|
||||
|
||||
int tio_set_speed(TIO *tio, unsigned int speed)
|
||||
{
|
||||
int i;
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
speed_t bspeed = -1;
|
||||
#else
|
||||
int bspeed = -1;
|
||||
#endif
|
||||
|
||||
for( i = 0; speedtab[i].nspeed; i++ )
|
||||
{
|
||||
if( speedtab[i].nspeed == speed )
|
||||
{
|
||||
bspeed = speedtab[i].bspeed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( bspeed == -1 )
|
||||
{
|
||||
log("unsupported speed %d", speed);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
cfsetospeed(tio, bspeed);
|
||||
cfsetispeed(tio, bspeed);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get port speed. Return integer value, not symbolic constant */
|
||||
|
||||
int tio_get_speed(TIO *tio)
|
||||
{
|
||||
int i;
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
speed_t bspeed = cfgetospeed(tio);
|
||||
#endif
|
||||
|
||||
for( i = 0; speedtab[i].nspeed; i++ )
|
||||
{
|
||||
if( speedtab[i].bspeed == bspeed )
|
||||
return speedtab[i].nspeed;
|
||||
}
|
||||
|
||||
return-1;
|
||||
}
|
||||
|
||||
int tio_set_flow_control(int fd, TIO *tio, int flow)
|
||||
{
|
||||
#if defined(HAVE_SYS_TERMIOX_H)
|
||||
struct termiox tix;
|
||||
#endif
|
||||
|
||||
DEB((D_MODEM, "tio_set_flow_control: setting HARD=%s, SOFT=%s",
|
||||
(flow & FLOW_HARD) ? "On" : "Off",
|
||||
(flow & FLOW_SOFT) ? "On" : "Off"));
|
||||
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
tio->c_cflag &= ~TIO_FLOW_HARD;
|
||||
tio->c_iflag &= ~TIO_FLOW_SOFT;
|
||||
#ifdef IXANY
|
||||
tio->c_iflag &= ~IXANY;
|
||||
#endif
|
||||
|
||||
if( flow & FLOW_HARD )
|
||||
tio->c_cflag |= TIO_FLOW_HARD;
|
||||
if( flow & FLOW_SOFT )
|
||||
tio->c_iflag |= TIO_FLOW_SOFT;
|
||||
#endif /* HAVE_TERMIOS_H */
|
||||
|
||||
#if defined(HAVE_SYS_TERMIOX_H)
|
||||
if( ioctl(fd, TCGETX, &tix) == -1 )
|
||||
{
|
||||
logerr("failed ioctl(TCGETX)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( flow & FLOW_HARD )
|
||||
tix.x_hflag |= (RTSXOFF | CTSXON);
|
||||
else
|
||||
tix.x_hflag &= ~(RTSXOFF | CTSXON);
|
||||
|
||||
if( ioctl(fd, TCSETX, &tix) == -1 )
|
||||
{
|
||||
logerr("failed ioctl(TCSETX)");
|
||||
return -1;
|
||||
}
|
||||
#endif /* HAVE_SYS_TERMIOX_H */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tio_set_raw_mode(TIO *tio)
|
||||
{
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
tio->c_cflag &= ~(CSTOPB | PARENB | PARODD);
|
||||
tio->c_cflag |= (CS8 | CREAD | HUPCL);
|
||||
tio->c_iflag = TIO_FLOW_SOFT;
|
||||
tio->c_oflag = 0;
|
||||
tio->c_lflag = 0;
|
||||
tio->c_cc[VMIN] = 128;
|
||||
tio->c_cc[VTIME] = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tio_set_local(TIO *tio, bool local)
|
||||
{
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
if( local )
|
||||
tio->c_cflag |= CLOCAL;
|
||||
else
|
||||
tio->c_cflag &= ~CLOCAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int tio_set_dtr(int fd, bool on)
|
||||
{
|
||||
int mctl = TIO_RS232_DTR;
|
||||
|
||||
DEB((D_MODEM, "tio_setdtr: setting DTR = %s", on ? "On" : "Off"));
|
||||
|
||||
if( on )
|
||||
{
|
||||
if( ioctl(fd, TIOCMBIS, &mctl ) < 0 )
|
||||
{
|
||||
logerr("cannot set DTR = On: TIOCMBIS failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ioctl(fd, TIOCMBIC, &mctl ) < 0 )
|
||||
{
|
||||
logerr("cannot set DTR = Off: TIOCMBIC failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tio_ctty(int fd)
|
||||
{
|
||||
if( setsid() < 0 )
|
||||
logerr("cannot make myself session leader (setsid)");
|
||||
|
||||
#ifdef TIOCSCTTY
|
||||
if( ioctl(fd, TIOCSCTTY, 0) < 0 )
|
||||
{
|
||||
logerr("cannot set controlling tty (ioctl)");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tio_send_break(void)
|
||||
{
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
if( tcsendbreak(1, 0) < 0 )
|
||||
{
|
||||
logerr("tcsendbreak(1,0) failed");
|
||||
#else
|
||||
if( ioctl(1, TCSBRK) < 0 )
|
||||
{
|
||||
logerr("ioctl(1,TCSBRK) failed");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tio_get_dcd(int fd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if( ioctl(fd, TIOCMGET, &flags ) < 0 )
|
||||
return -1;
|
||||
|
||||
return (flags & TIO_RS232_DCD) ? 1 : 0;
|
||||
}
|
||||
|
||||
int tio_get_rs232_state(void)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if( ioctl(0, TIOCMGET, &flags ) < 0 )
|
||||
return -1;
|
||||
|
||||
DEB((D_MODEM, "tio_getrs232: [%s]-[%s]-[%s]-[%s]-[%s]-[%s]",
|
||||
( flags & TIO_RS232_RTS ) ? "RTS" : "rts",
|
||||
( flags & TIO_RS232_CTS ) ? "CTS" : "cts",
|
||||
( flags & TIO_RS232_DSR ) ? "DSR" : "dsr",
|
||||
( flags & TIO_RS232_DTR ) ? "DTR" : "dtr",
|
||||
( flags & TIO_RS232_DCD ) ? "DCD" : "dcd",
|
||||
( flags & TIO_RS232_RNG ) ? "RNG" : "rng"));
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
438
source/bforce/io_unix_tty.c
Normal file
438
source/bforce/io_unix_tty.c
Normal file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
#ifndef RX_BUFSIZE
|
||||
#define RX_BUFSIZE 4096
|
||||
#endif
|
||||
#ifndef TX_BUFSIZE
|
||||
#define TX_BUFSIZE 4096
|
||||
#endif
|
||||
|
||||
int tty_status = TTY_SUCCESS;
|
||||
int tty_hangup = 0;
|
||||
int tty_abort = 0;
|
||||
int tty_online = 0;
|
||||
int tty_modem = 0;
|
||||
|
||||
static unsigned char rx_buf[RX_BUFSIZE];
|
||||
static unsigned char tx_buf[TX_BUFSIZE];
|
||||
static unsigned int rx_pos = 0;
|
||||
static unsigned int tx_pos = 0;
|
||||
static unsigned int rx_left = 0; /* Received bytes left */
|
||||
static unsigned int tx_left = TX_BUFSIZE; /* Free space left */
|
||||
|
||||
#ifdef MODEM_WATCH_CARRIER
|
||||
# define CARRIER_CHECK() if( tty_modem && tty_online && !tty_hangup \
|
||||
&& !tio_get_dcd(0) ) { \
|
||||
log("carrier lost"); tty_hangup = 1; }
|
||||
#else
|
||||
# define CARRIER_CHECK()
|
||||
#endif
|
||||
|
||||
const char *tty_errstr(int status)
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
switch(status) {
|
||||
case TTY_SUCCESS: msg = "No errors"; break;
|
||||
case TTY_TIMEOUT: msg = "Time Out"; break;
|
||||
case TTY_HANGUP: msg = "Hanged Up"; break;
|
||||
case TTY_ERROR: msg = "IO Error"; break;
|
||||
default: msg = "Unknown error"; break;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*
|
||||
* On success, tty_select() return zero value and set/reset
|
||||
* rd and wr to the appropriate values
|
||||
*/
|
||||
int tty_select(bool *rd, bool *wr, int timeout)
|
||||
{
|
||||
fd_set rfds, wfds;
|
||||
struct timeval tv;
|
||||
int rc;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
if( rd ) { FD_SET(0,&rfds); *rd = FALSE; }
|
||||
if( wr ) { FD_SET(1,&wfds); *wr = FALSE; }
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
{ return( tty_status = TTY_HANGUP ); }
|
||||
|
||||
rc = select(2, &rfds, &wfds, NULL, &tv);
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( rc < 0 )
|
||||
{
|
||||
if( errno == EINTR )
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
{ tty_status = TTY_HANGUP; }
|
||||
else
|
||||
{ tty_status = TTY_SUCCESS; }
|
||||
else
|
||||
{ tty_status = TTY_ERROR; }
|
||||
}
|
||||
else if( rc == 0 )
|
||||
{
|
||||
tty_status = TTY_TIMEOUT;
|
||||
}
|
||||
else /* ( rc > 0 ) */
|
||||
{
|
||||
tty_status = TTY_ERROR;
|
||||
if( rd && FD_ISSET(0,&rfds) )
|
||||
{ tty_status = TTY_SUCCESS; *rd = TRUE; }
|
||||
if( wr && FD_ISSET(1,&wfds) )
|
||||
{ tty_status = TTY_SUCCESS; *wr = TRUE; }
|
||||
}
|
||||
|
||||
DEB((D_TTYIO, "tty_select: return code = %s, rc = %d (rd=%s, wr=%s)",
|
||||
tty_errstr(tty_status), rc,
|
||||
rd ? *rd ? "true" : "false" : "null",
|
||||
wr ? *wr ? "true" : "false" : "null"));
|
||||
|
||||
return tty_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is a frontend to tty_select(), that also checks our program buffer
|
||||
*/
|
||||
int tty_xselect(bool *rd, bool *wr, int timeout)
|
||||
{
|
||||
if( rd && rx_pos > 0 )
|
||||
{
|
||||
(void)tty_select(NULL, wr, 0); *rd = TRUE;
|
||||
return TTY_SUCCESS;
|
||||
}
|
||||
return tty_select(rd, wr, timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero value if some data available for reading
|
||||
* in input queue OR in our RX buffer
|
||||
*/
|
||||
int tty_charwait(int timeout)
|
||||
{
|
||||
bool rd = FALSE;
|
||||
|
||||
if( rx_pos > 0 )
|
||||
return 1;
|
||||
else if( tty_select(&rd, NULL, timeout) == 0 && rd == TRUE )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On success return number of bytes received
|
||||
*/
|
||||
int tty_read(unsigned char *buf, size_t size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
DEB((D_TTYIO, "tty_read: want read %d byte(s)", size));
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
{ return( tty_status = TTY_HANGUP ); }
|
||||
|
||||
rc = read(0, buf, size);
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
{
|
||||
tty_status = TTY_HANGUP;
|
||||
}
|
||||
else if( rc < 0 )
|
||||
{
|
||||
if( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK )
|
||||
{ tty_status = TTY_TIMEOUT; }
|
||||
else
|
||||
{ tty_status = TTY_ERROR; }
|
||||
}
|
||||
else /* ( rc >= 0 ) */
|
||||
tty_status = TTY_SUCCESS;
|
||||
|
||||
DEB((D_TTYIO, "tty_read: return code = %s, rc = %d",
|
||||
tty_errstr(tty_status), rc));
|
||||
|
||||
return tty_status == TTY_SUCCESS ? rc : tty_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* On success return number of bytes received
|
||||
*/
|
||||
int tty_read_timeout(unsigned char *buf, size_t size, int timeout)
|
||||
{
|
||||
int rc;
|
||||
bool rd = FALSE;
|
||||
|
||||
tty_status = TTY_SUCCESS;
|
||||
|
||||
DEB((D_TTYIO, "tty_read_timeout: want read %d byte(s), timeout = %d", size, timeout));
|
||||
|
||||
if( timeout > 0 )
|
||||
{
|
||||
if( (rc = tty_select(&rd, NULL, timeout)) < 0 )
|
||||
return rc;
|
||||
|
||||
if( rd )
|
||||
{
|
||||
if( (rc = tty_read(buf, size)) == 0 )
|
||||
return TTY_ERROR;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
return TTY_TIMEOUT;
|
||||
}
|
||||
|
||||
return tty_read(buf, size);
|
||||
}
|
||||
|
||||
int tty_write(const unsigned char *buf, size_t size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
DEB((D_TTYIO, "tty_write: want write %d byte(s)", size));
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
{ return(tty_status = TTY_HANGUP); }
|
||||
|
||||
rc = write(1, buf, size);
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( rc < 0 )
|
||||
{
|
||||
if( errno == EINTR )
|
||||
{
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
{ tty_status = TTY_HANGUP; }
|
||||
else
|
||||
{ tty_status = TTY_TIMEOUT; }
|
||||
}
|
||||
else if( errno == EAGAIN || errno == EWOULDBLOCK )
|
||||
{
|
||||
tty_status = TTY_TIMEOUT;
|
||||
}
|
||||
else if( errno == EPIPE )
|
||||
{
|
||||
tty_hangup = 1;
|
||||
tty_status = TTY_HANGUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
tty_status = TTY_ERROR;
|
||||
}
|
||||
}
|
||||
else if( rc == 0 )
|
||||
tty_status = TTY_TIMEOUT;
|
||||
else /* ( rc > 0 ) */
|
||||
tty_status = TTY_SUCCESS;
|
||||
|
||||
DEB((D_TTYIO, "tty_write: return code = %s, rc = %d",
|
||||
tty_errstr(tty_status), rc));
|
||||
|
||||
return (tty_status == TTY_SUCCESS) ? rc : tty_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* On success return number of bytes sent
|
||||
*/
|
||||
int tty_write_timeout(const unsigned char *buf, size_t size, int timeout)
|
||||
{
|
||||
time_t timer;
|
||||
int rc, pos = 0;
|
||||
|
||||
DEB((D_TTYIO, "tty_write_timeout: want write %d byte(s), timeout = %d", size, timeout));
|
||||
|
||||
tty_status = TTY_SUCCESS;
|
||||
timer_set(&timer, timeout);
|
||||
|
||||
while( pos < size )
|
||||
{
|
||||
if( timer_expired(timer) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if( (rc = tty_write(buf + pos, size - pos)) < 0 )
|
||||
{
|
||||
if( rc == TTY_TIMEOUT )
|
||||
usleep(10000); /* 0.01 sec */
|
||||
else
|
||||
return rc;
|
||||
}
|
||||
else /* ( rc > 0 ) */
|
||||
{
|
||||
DEB((D_TTYIO, "tty_write_timeout: written %d byte(s)", rc));
|
||||
pos += rc;
|
||||
}
|
||||
}
|
||||
|
||||
return (pos > 0) ? pos : TTY_TIMEOUT;
|
||||
}
|
||||
|
||||
int tty_putc(unsigned char ch, int timeout)
|
||||
{
|
||||
return tty_write_timeout(&ch, 1, timeout);
|
||||
}
|
||||
|
||||
int tty_puts(const unsigned char *s, int timeout)
|
||||
{
|
||||
return tty_write_timeout(s, strlen(s), timeout);
|
||||
}
|
||||
|
||||
int tty_getc(int timeout)
|
||||
{
|
||||
int rc;
|
||||
|
||||
tty_status = TTY_SUCCESS;
|
||||
|
||||
if( rx_left == 0 )
|
||||
{
|
||||
rx_pos = 0;
|
||||
if( (rc = tty_read_timeout(rx_buf, sizeof(rx_buf), timeout)) < 0 )
|
||||
{
|
||||
DEB((D_TTYIO, "tty_getc: tty_read() result \"%s\"", tty_errstr(rc)));
|
||||
return rc;
|
||||
}
|
||||
else if( rc == 0 )
|
||||
return TTY_ERROR; /* Isn't it? */
|
||||
|
||||
rx_left = rc;
|
||||
}
|
||||
|
||||
rx_left--;
|
||||
return rx_buf[rx_pos++];
|
||||
}
|
||||
|
||||
int tty_bufc(unsigned char ch, int timeout)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if( tx_left == 0 )
|
||||
{
|
||||
if( (rc = tty_flushbuf(timeout)) < 0 ) return rc;
|
||||
else if( rc == 0 ) return TTY_TIMEOUT;
|
||||
}
|
||||
|
||||
tx_buf[tx_pos++] = ch;
|
||||
--tx_left;
|
||||
|
||||
return(tty_status = TTY_SUCCESS);
|
||||
}
|
||||
|
||||
int tty_flushout(void)
|
||||
{
|
||||
DEB((D_TTYIO, "tty_flushout: flushing out"));
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
return(tty_status = TTY_HANGUP);
|
||||
|
||||
#ifdef FUCKING_TCDRAIN
|
||||
if( tty_modem )
|
||||
{
|
||||
while( tcdrain(1) == -1 )
|
||||
{
|
||||
if( errno == EINTR )
|
||||
{
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
return(tty_status = TTY_HANGUP);
|
||||
}
|
||||
else if( errno == EPIPE )
|
||||
return(tty_status = TTY_HANGUP);
|
||||
else if( errno == EAGAIN || errno == EWOULDBLOCK )
|
||||
return(tty_status = TTY_SUCCESS);
|
||||
else
|
||||
return(tty_status = TTY_ERROR);
|
||||
}
|
||||
}
|
||||
#endif /* FUCKING_TCDRAIN */
|
||||
|
||||
return(tty_status = TTY_SUCCESS);
|
||||
}
|
||||
|
||||
int tty_flushbuf(int timeout)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
tty_status = TTY_SUCCESS;
|
||||
|
||||
DEB((D_TTYIO, "tty_flushbuf: flushing internal TX buffer"));
|
||||
|
||||
if( tx_pos )
|
||||
{
|
||||
if( (rc = tty_write_timeout(tx_buf, tx_pos, timeout)) < 0 )
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
tx_pos -= rc;
|
||||
tx_left += rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tty_clearin(void)
|
||||
{
|
||||
DEB((D_TTYIO, "tty_clearin: clear RX buffers"));
|
||||
|
||||
tcflush(0, TCIFLUSH);
|
||||
|
||||
rx_left = 0;
|
||||
rx_pos = 0;
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
return(tty_status = TTY_HANGUP);
|
||||
|
||||
return(tty_status = TTY_SUCCESS);
|
||||
}
|
||||
|
||||
int tty_clearout(void)
|
||||
{
|
||||
DEB((D_TTYIO, "tty_clearout: clear TX buffers"));
|
||||
|
||||
tcflush(1, TCOFLUSH);
|
||||
|
||||
tx_left = TX_BUFSIZE;
|
||||
tx_pos = 0;
|
||||
|
||||
CARRIER_CHECK();
|
||||
|
||||
if( (tty_online && tty_hangup) || tty_abort )
|
||||
return(tty_status = TTY_HANGUP);
|
||||
|
||||
return(tty_status = TTY_SUCCESS);
|
||||
}
|
||||
570
source/bforce/logger.c
Normal file
570
source/bforce/logger.c
Normal file
@ -0,0 +1,570 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "version.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* Local variables for logger
|
||||
*/
|
||||
static FILE *log_fp = NULL;
|
||||
static char log_name[BF_MAXPATH+1] = BFORCE_LOGFILE;
|
||||
static char log_extension[32] = "";
|
||||
static char log_ident[32] = "";
|
||||
static char log_ttyname[32] = "";
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Local variables needed to make debug work
|
||||
*/
|
||||
static FILE *debug_fp = NULL;
|
||||
static long debug_current_debuglevel = 0L;
|
||||
static char debug_name[BF_MAXPATH+1] = BFORCE_DEBFILE;
|
||||
static bool debug_invalid_name = FALSE;
|
||||
|
||||
/*
|
||||
* Debug level names
|
||||
*/
|
||||
struct debuglevel {
|
||||
const char *keystr;
|
||||
unsigned long value;
|
||||
} debuglevels[] = {
|
||||
{ "Config", D_CONFIG },
|
||||
{ "Override", D_OVERRIDE },
|
||||
{ "Event", D_EVENT },
|
||||
{ "Nodelist", D_NODELIST },
|
||||
{ "Outbound", D_OUTBOUND },
|
||||
{ "Info", D_INFO },
|
||||
{ "HShake", D_HSHAKE },
|
||||
{ "TtyIO", D_TTYIO },
|
||||
{ "Modem", D_MODEM },
|
||||
{ "Prot", D_PROT },
|
||||
{ "Freq", D_FREQ },
|
||||
{ "Statem", D_STATEM },
|
||||
{ "Daemon", D_DAEMON },
|
||||
{ "Full", D_FULL },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
#endif /* ifdef USE_SYSLOG */
|
||||
|
||||
#ifndef USE_SYSLOG
|
||||
const char *log_getfilename(int whatfor)
|
||||
{
|
||||
const char *p = NULL;
|
||||
|
||||
switch(whatfor) {
|
||||
case LOG_FILE_DAEMON:
|
||||
if( (p = conf_string(cf_log_file_daemon)) == NULL )
|
||||
p = DAEMON_LOGFILE;
|
||||
break;
|
||||
case LOG_FILE_SESSION:
|
||||
if( (p = conf_string(cf_log_file)) == NULL )
|
||||
p = BFORCE_LOGFILE;
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case LOG_FILE_DEBUG:
|
||||
if( (p = conf_string(cf_debug_file)) == NULL )
|
||||
p = BFORCE_DEBFILE;
|
||||
break;
|
||||
#endif
|
||||
case LOG_FILE_HISTORY:
|
||||
break;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logging part
|
||||
*/
|
||||
bool log_isopened(void)
|
||||
{
|
||||
return log_fp ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
int log_open(const char *logname, const char *ext, const char *tty)
|
||||
{
|
||||
if( log_fp )
|
||||
log("warning: opening new log file, but previous was not closed");
|
||||
|
||||
if( logname )
|
||||
{
|
||||
/* Reset previous settings */
|
||||
*log_name = '\0';
|
||||
*log_extension = '\0';
|
||||
*log_ttyname = '\0';
|
||||
|
||||
strnxcpy(log_name, logname, sizeof(log_name));
|
||||
|
||||
if( tty && *tty )
|
||||
strnxcpy(log_ttyname, tty, sizeof(log_ttyname));
|
||||
|
||||
if( ext && *ext )
|
||||
{
|
||||
strnxcpy(log_extension, ext, sizeof(log_extension));
|
||||
strnxcat(log_name, ".", sizeof(log_name));
|
||||
strnxcat(log_name, ext, sizeof(log_name));
|
||||
}
|
||||
|
||||
if( (log_fp = fopen(log_name, "a")) == NULL )
|
||||
{
|
||||
logerr("can't open log file \"%s\"", log_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if( log_name )
|
||||
{
|
||||
/* Open previously set log file */
|
||||
|
||||
if( (log_fp = fopen(log_name, "a")) == NULL )
|
||||
{
|
||||
logerr("can't open log file \"%s\"", log_name);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_close(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
ASSERT(log_fp);
|
||||
|
||||
if( log_fp )
|
||||
{
|
||||
rc = fclose(log_fp); log_fp = NULL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int log_reopen(const char *logname, const char *ext, const char *tty)
|
||||
{
|
||||
ASSERT(logname != NULL);
|
||||
|
||||
if( log_isopened() )
|
||||
{
|
||||
if( !strcmp(logname, log_name)
|
||||
&& !strcmp(log_extension ? log_extension : "", ext ? ext : "") )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
log_close();
|
||||
}
|
||||
|
||||
return log_open(logname, ext, tty);
|
||||
}
|
||||
|
||||
/* void log_setident(const char *ident)
|
||||
{
|
||||
if( ident )
|
||||
strnxcpy(log_ident, ident, sizeof(log_ident));
|
||||
else
|
||||
*log_ident = '\0';
|
||||
} */
|
||||
|
||||
int log(const char *s, ...)
|
||||
|
||||
{
|
||||
char timestr[40];
|
||||
va_list args;
|
||||
|
||||
time_string_log(timestr, sizeof(timestr), 0);
|
||||
|
||||
va_start(args, s);
|
||||
|
||||
/*
|
||||
* If log file is not opened print messages to the stderr
|
||||
*/
|
||||
if( log_fp == NULL )
|
||||
{
|
||||
fprintf(stderr, "%s ", timestr);
|
||||
vfprintf(stderr, s, args);
|
||||
putc('\n', stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
else
|
||||
{
|
||||
int mypid = getpid();
|
||||
|
||||
if( log_ident[0] && log_ttyname[0] )
|
||||
fprintf(log_fp, "%s %s.%s[%d] ", timestr, log_ident, log_ttyname, mypid);
|
||||
else if( log_ident[0] )
|
||||
fprintf(log_fp, "%s %s[%d] ", timestr, log_ident, mypid);
|
||||
else if( log_ttyname[0] )
|
||||
fprintf(log_fp, "%s %s[%d] ", timestr, log_ttyname, mypid);
|
||||
else
|
||||
fprintf(log_fp, "%s [%d] ", timestr, mypid);
|
||||
|
||||
vfprintf(log_fp, s, args);
|
||||
putc('\n', log_fp);
|
||||
fflush(log_fp);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int logerr(const char *s, ...)
|
||||
{
|
||||
char timestr[40];
|
||||
va_list args;
|
||||
|
||||
time_string_log(timestr, sizeof(timestr), 0);
|
||||
|
||||
va_start(args, s);
|
||||
|
||||
/*
|
||||
* If log file is not opened print messages to the stderr
|
||||
*/
|
||||
if( log_fp == NULL )
|
||||
{
|
||||
fprintf(stderr, "%s ", timestr);
|
||||
vfprintf(stderr, s, args);
|
||||
putc('\n', stderr);
|
||||
|
||||
if( errno == EACCES )
|
||||
{
|
||||
fprintf(stderr, "\tmessage: \"%s\" : errno = %d (euid = %d, egid = %d)\n",
|
||||
strerror(errno), errno, geteuid(), getegid());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\tmessage: \"%s\" : errno = %d\n",
|
||||
strerror(errno), errno);
|
||||
}
|
||||
|
||||
fflush(stderr);
|
||||
}
|
||||
else
|
||||
{
|
||||
int mypid = getpid();
|
||||
|
||||
if( *log_ident && *log_ttyname )
|
||||
fprintf(log_fp, "%s %s.%s[%d] ", timestr, log_ident, log_ttyname, mypid);
|
||||
else if( *log_ident )
|
||||
fprintf(log_fp, "%s %s[%d] ", timestr, log_ident, mypid);
|
||||
else if( *log_ttyname )
|
||||
fprintf(log_fp, "%s %s[%d] ", timestr, log_ttyname, mypid);
|
||||
else
|
||||
fprintf(log_fp, "%s [%d] ", timestr, mypid);
|
||||
|
||||
vfprintf(log_fp, s, args);
|
||||
putc('\n', log_fp);
|
||||
|
||||
/*
|
||||
* Print error message according to the errno value
|
||||
*/
|
||||
if( errno == EACCES )
|
||||
{
|
||||
fprintf(log_fp, "\tmessage: \"%s\" : errno = %d (euid = %d, egid = %d)\n",
|
||||
strerror(errno), errno, geteuid(), getegid());
|
||||
}
|
||||
else if( errno )
|
||||
{
|
||||
fprintf(log_fp, "\tmessage: \"%s\" : errno = %d\n",
|
||||
strerror(errno), errno);
|
||||
}
|
||||
|
||||
fflush(log_fp);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* ifndef USE_SYSLOG */
|
||||
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
|
||||
const char *log_getfilename(int whatfor)
|
||||
{
|
||||
const char *p = "/dev/null";
|
||||
return p;
|
||||
}
|
||||
|
||||
bool log_isopened(void)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int log_open(const char *logname, const char *ext, const char *tty)
|
||||
{
|
||||
char *p = "bforce";
|
||||
int fac = conf_number(cf_syslog_facility);
|
||||
if( tty && *tty )
|
||||
strncpy(p, tty, sizeof(p));
|
||||
openlog(p, LOG_PID, fac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_reopen(const char *logname, const char *ext, const char *tty)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_close(void)
|
||||
{
|
||||
|
||||
closelog();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int log(const char *s, ...)
|
||||
|
||||
{
|
||||
char timestr[40];
|
||||
va_list args;
|
||||
|
||||
int fac = conf_number(cf_syslog_facility);
|
||||
const int LP_TTY = fac || LOG_INFO;
|
||||
const int LP_A = fac || LOG_NOTICE;
|
||||
const int LP_O = fac || LOG_DEBUG;
|
||||
const int log_priority = fac || LOG_ERR;
|
||||
|
||||
time_string_log(timestr, sizeof(timestr), 0);
|
||||
|
||||
va_start(args, s);
|
||||
|
||||
int mypid = getpid();
|
||||
|
||||
if( log_ident[0] && log_ttyname[0] )
|
||||
syslog(LP_TTY, "%s %s.%s[%d] ", timestr, log_ident, log_ttyname, mypid);
|
||||
else if( log_ident[0] )
|
||||
syslog(LP_A, "%s %s[%d] ", timestr, log_ident, mypid);
|
||||
else if( log_ttyname[0] )
|
||||
syslog(LP_O, "%s %s[%d] ", timestr, log_ttyname, mypid);
|
||||
else
|
||||
fprintf(log_priority, "%s [%d] ", timestr, mypid);
|
||||
|
||||
|
||||
/* vsyslog(log_priority, s, args);*/
|
||||
/* putc('\n', log_fp);
|
||||
fflush(log_fp);
|
||||
|
||||
} */
|
||||
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int logerr(const char *s, ...)
|
||||
|
||||
{
|
||||
char timestr[40];
|
||||
va_list args;
|
||||
|
||||
int fac = conf_number(cf_syslog_facility);
|
||||
const int log_priority = fac || LOG_ERR;
|
||||
|
||||
time_string_log(timestr, sizeof(timestr), 0);
|
||||
|
||||
va_start(args, s);
|
||||
|
||||
int mypid = getpid();
|
||||
|
||||
/* if( log_ident[0] && log_ttyname[0] )
|
||||
syslog(log_priority, "%s %s.%s[%d] ", timestr, log_ident, log_ttyname, mypid);
|
||||
else if( log_ident[0] )
|
||||
syslog(log_priority, "%s %s[%d] ", timestr, log_ident, mypid);
|
||||
else if( log_ttyname[0] )
|
||||
fprintf(log_priority, "%s %s[%d] ", timestr, log_ttyname, mypid);
|
||||
else
|
||||
fprintf(log_priority, "%s [%d] ", timestr, mypid);
|
||||
*/
|
||||
|
||||
vsyslog(log_priority, s, args);
|
||||
/* putc('\n', log_fp);
|
||||
fflush(log_fp);
|
||||
|
||||
} */
|
||||
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* ifdef USE_SYSLOG */
|
||||
|
||||
|
||||
/*
|
||||
* Debugging part
|
||||
*/
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void debug_setlevel(long newlevel, bool logit)
|
||||
{
|
||||
if( logit && newlevel != debug_current_debuglevel )
|
||||
{
|
||||
log("changing debug level from 0x%07x to 0x%07x",
|
||||
debug_current_debuglevel, newlevel);
|
||||
debug_current_debuglevel = newlevel;
|
||||
}
|
||||
}
|
||||
|
||||
bool debug_isopened(void)
|
||||
{
|
||||
return debug_fp ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
int debug_parsestring(char *str, unsigned long *deblevel)
|
||||
{
|
||||
int i, rc = 0;
|
||||
char *n;
|
||||
char *p_str = NULL;
|
||||
|
||||
ASSERT(str != NULL);
|
||||
|
||||
*deblevel = 0L;
|
||||
|
||||
for( p_str = string_token(str, &n, NULL, 0); p_str;
|
||||
p_str = string_token(NULL, &n, NULL, 0) )
|
||||
{
|
||||
for( i = 0; debuglevels[i].keystr; i++ )
|
||||
{
|
||||
if( strcasecmp(p_str, debuglevels[i].keystr) == 0 )
|
||||
{
|
||||
*deblevel |= debuglevels[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( debuglevels[i].keystr == NULL )
|
||||
{
|
||||
log("unknown debug level \"%s\"", p_str);
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void debug_setfilename(const char *debugname)
|
||||
{
|
||||
ASSERT(debugname != NULL);
|
||||
|
||||
if( !strcmp(debug_name, debugname) ) return;
|
||||
|
||||
if( debug_isopened() ) debug_close();
|
||||
|
||||
/* Reset ignore flag */
|
||||
if( debug_invalid_name )
|
||||
debug_invalid_name = FALSE;
|
||||
|
||||
strnxcpy(debug_name, debugname, sizeof(debug_name));
|
||||
}
|
||||
|
||||
int debug_open(const char *debugname)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
ASSERT(debug_fp == NULL);
|
||||
|
||||
if( debugname )
|
||||
{
|
||||
if( (debug_fp = fopen(debugname, "a")) == NULL )
|
||||
{
|
||||
logerr("can't open debug file \"%s\"", debugname);
|
||||
return -1;
|
||||
}
|
||||
strnxcpy(debug_name, debugname, sizeof(debug_name));
|
||||
}
|
||||
else if( debug_name )
|
||||
{
|
||||
if( (debug_fp = fopen(debug_name, "a")) == NULL )
|
||||
{
|
||||
/* Don't try to open it next time */
|
||||
debug_invalid_name = TRUE;
|
||||
|
||||
logerr("can't open debug file \"%s\"", debug_name);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
|
||||
/* Put banner */
|
||||
fprintf(debug_fp, "****************************************************\n");
|
||||
fprintf(debug_fp, " Starting binkleyforce version %s\n", BF_VERSION);
|
||||
fprintf(debug_fp, " Time: %s, PID: %d, UID: %d, GID: %d, EUID: %d, EGID %d\n",
|
||||
time_string_long(buf, sizeof(buf), 0), getpid(),
|
||||
getuid(), getgid(), geteuid(), getegid());
|
||||
fprintf(debug_fp, "****************************************************\n");
|
||||
fflush(debug_fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int debug_close(void)
|
||||
{
|
||||
char buf[40];
|
||||
int rc = 0;
|
||||
|
||||
ASSERT(debug_fp != NULL);
|
||||
|
||||
if( debug_fp )
|
||||
{
|
||||
fprintf(debug_fp, "****************************************************\n");
|
||||
fprintf(debug_fp, " Closing Binkley-Force debug file at %s\n",
|
||||
time_string_long(buf, sizeof(buf), 0));
|
||||
fprintf(debug_fp, "****************************************************\n");
|
||||
|
||||
rc = fclose(debug_fp) ? 0 : -1; debug_fp = NULL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int debug(unsigned long what, const char *str, ...)
|
||||
{
|
||||
char buf[40];
|
||||
va_list args;
|
||||
|
||||
if( (what == 0 && debug_current_debuglevel)
|
||||
|| (debug_current_debuglevel & what) )
|
||||
{
|
||||
if( debug_fp == NULL && debug_invalid_name == FALSE )
|
||||
{
|
||||
debug_open(NULL);
|
||||
}
|
||||
|
||||
if( debug_fp )
|
||||
{
|
||||
fprintf(debug_fp, "%s ", time_string_log(buf, sizeof(buf), 0));
|
||||
va_start(args, str);
|
||||
vfprintf(debug_fp, str, args);
|
||||
va_end(args);
|
||||
putc('\n', debug_fp);
|
||||
fflush(debug_fp);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* DEBUG */
|
||||
585
source/bforce/nodelist.c
Normal file
585
source/bforce/nodelist.c
Normal file
@ -0,0 +1,585 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
#include "logger.h"
|
||||
#include "util.h"
|
||||
#include "nodelist.h"
|
||||
|
||||
#define NODELIST_LOCK_TRIES 3
|
||||
#define NODELIST_LOCK_DELAY 1 /* seconds */
|
||||
|
||||
struct keyword {
|
||||
const char *keystr;
|
||||
const int keyval;
|
||||
} keywords[] = {
|
||||
{ "", KEYWORD_EMPTY },
|
||||
{ "Zone", KEYWORD_ZONE },
|
||||
{ "Region", KEYWORD_REGION },
|
||||
{ "Host", KEYWORD_HOST },
|
||||
{ "Hub", KEYWORD_HUB },
|
||||
{ "Pvt", KEYWORD_PVT },
|
||||
{ "Hold", KEYWORD_HOLD },
|
||||
{ "Down", KEYWORD_DOWN },
|
||||
{ "Boss", KEYWORD_BOSS },
|
||||
{ "Point", KEYWORD_POINT },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Check flag for existing in nodelist flags string
|
||||
*
|
||||
* Arguments:
|
||||
* nodeflags pointer to the node's nodelist flags string
|
||||
* flag pointer to the flag that we want to check
|
||||
*
|
||||
* Return value:
|
||||
* zero value if flag is presented in flags, and non-zero if not
|
||||
*/
|
||||
int nodelist_checkflag(const char *nodeflags, const char *flag)
|
||||
{
|
||||
char *p, *q;
|
||||
|
||||
if( (p = strstr(nodeflags, flag)) )
|
||||
{
|
||||
if( p == nodeflags || *(p-1) == ',' )
|
||||
{
|
||||
if( (q = strchr(p, ',')) == NULL || (q - p) == strlen(flag) )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Get nodelist keyword (e.g. Host, Hub, Point, etc.) value
|
||||
* (e.g. KEYWORD_HOST, KEYWORD_HUB, etc.)
|
||||
*
|
||||
* Arguments:
|
||||
* keywordval pointer to the keyword string
|
||||
*
|
||||
* Return value:
|
||||
* One of KEYWORD_* values, and -1 for unknown keywords
|
||||
*/
|
||||
int nodelist_keywordval(const char *keyword)
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; keywords[i].keystr; i++ )
|
||||
{
|
||||
if( strcmp(keyword, keywords[i].keystr) == 0 )
|
||||
{
|
||||
return keywords[i].keyval;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nodelist_parse_Txy(s_node *node, const char *xy)
|
||||
{
|
||||
long beg;
|
||||
long end;
|
||||
long tz;
|
||||
|
||||
if( xy[0] >= 'A' && xy[0] <= 'X' )
|
||||
beg = (xy[0] - 'A') * 60;
|
||||
else if( xy[0] >= 'a' && xy[0] <= 'x' )
|
||||
beg = (xy[0] - 'a') * 60 + 30;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if( xy[1] >= 'A' && xy[1] <= 'X' )
|
||||
end = (xy[1] - 'A') * 60;
|
||||
else if( xy[1] >= 'a' && xy[1] <= 'x' )
|
||||
end = (xy[1] - 'a') * 60 + 30;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if( beg == end )
|
||||
return -1;
|
||||
|
||||
/* Convert it to local time */
|
||||
if( (tz = time_gmtoffset()) )
|
||||
{
|
||||
beg -= tz;
|
||||
if( beg > 1440 )
|
||||
beg = beg - 1440;
|
||||
else if( beg < 0 )
|
||||
beg = beg + 1440;
|
||||
else if( beg == 1440 )
|
||||
beg = 0;
|
||||
|
||||
end -= tz;
|
||||
if( end > 1440 )
|
||||
end = end - 1440;
|
||||
else if( end < 0 )
|
||||
end = end + 1440;
|
||||
else if( end == 1440 )
|
||||
end = 0;
|
||||
}
|
||||
|
||||
timevec_add(&node->worktime, DAY_MONDAY, DAY_SUNDAY, beg, end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Nodelist string parser
|
||||
*
|
||||
* Arguments:
|
||||
* node put here all obtained information
|
||||
* str pointer to the nodelist string
|
||||
*
|
||||
* Return value:
|
||||
* zero value if string was parsed successfuly, and non-zero if wasn't
|
||||
*/
|
||||
int nodelist_parsestring(s_node *node, char *str)
|
||||
{
|
||||
char *argv[NODELIST_POSFLAGS+1];
|
||||
char *p;
|
||||
|
||||
if( string_parse(argv, NODELIST_POSFLAGS+1, str, ',') != NODELIST_POSFLAGS+1 )
|
||||
return -1;
|
||||
|
||||
if( !ISDEC(argv[NODELIST_POSNUMBER]) || !ISDEC(argv[NODELIST_POSSPEED]) )
|
||||
return -1;
|
||||
if( (node->keyword = nodelist_keywordval(argv[NODELIST_POSKEYWORD])) == -1 )
|
||||
return -1;
|
||||
|
||||
if( node->addr.zone )
|
||||
{
|
||||
int number = atoi(argv[NODELIST_POSNUMBER]);
|
||||
bool goodstr = FALSE;
|
||||
|
||||
switch(node->keyword) {
|
||||
case KEYWORD_ZONE:
|
||||
goodstr = (node->addr.zone == number);
|
||||
break;
|
||||
case KEYWORD_REGION:
|
||||
case KEYWORD_HOST:
|
||||
goodstr = (node->addr.net == number);
|
||||
break;
|
||||
case KEYWORD_POINT:
|
||||
goodstr = (node->addr.point == number);
|
||||
break;
|
||||
default:
|
||||
goodstr = (node->addr.node == number);
|
||||
break;
|
||||
}
|
||||
if( !goodstr ) return -1;
|
||||
}
|
||||
|
||||
strnxcpy(node->name, argv[NODELIST_POSNAME], sizeof(node->name));
|
||||
strnxcpy(node->location, argv[NODELIST_POSLOCATION], sizeof(node->location));
|
||||
strnxcpy(node->sysop, argv[NODELIST_POSSYSOP], sizeof(node->sysop));
|
||||
strnxcpy(node->phone, argv[NODELIST_POSPHONE], sizeof(node->phone));
|
||||
strnxcpy(node->flags, argv[NODELIST_POSFLAGS], sizeof(node->flags));
|
||||
node->speed = atoi(argv[NODELIST_POSSPEED]);
|
||||
|
||||
/*
|
||||
* Replace all '_' by space character
|
||||
*/
|
||||
string_replchar(node->name, '_', ' ');
|
||||
string_replchar(node->location, '_', ' ');
|
||||
string_replchar(node->sysop, '_', ' ');
|
||||
|
||||
/*
|
||||
* Get system work time (usefull flags: CM,Txy)
|
||||
*/
|
||||
if( nodelist_checkflag(node->flags, "CM") == 0 )
|
||||
{
|
||||
timevec_add(&node->worktime, DAY_MONDAY, DAY_SUNDAY, 0, 1440);
|
||||
}
|
||||
else
|
||||
{
|
||||
for( p = node->flags; p && *p; p = strchr(p, ',') )
|
||||
{
|
||||
if( p[1] == 'T' && p[2] && p[3] && (p[4] == ',' || p[4] == '\0') )
|
||||
{
|
||||
if( nodelist_parse_Txy(node, p+2) == -1 )
|
||||
log("invalid nodelist Txy flag in \"%s\"", node->flags);
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default work time according to ZMH
|
||||
*/
|
||||
if( node->addr.point == 0 )
|
||||
{
|
||||
switch(node->addr.zone) {
|
||||
case 1: nodelist_parse_Txy(node, "JK"); break;
|
||||
case 2: nodelist_parse_Txy(node, "cd"); break;
|
||||
case 3: nodelist_parse_Txy(node, "ST"); break;
|
||||
case 4: nodelist_parse_Txy(node, "IJ"); break;
|
||||
case 5: nodelist_parse_Txy(node, "BC"); break;
|
||||
case 6: nodelist_parse_Txy(node, "UV"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Open nodelist, nodelist index, do some checks
|
||||
*
|
||||
* Arguments:
|
||||
* dir pointer to the nodelist's directory
|
||||
* name pointer to the nodelist file name
|
||||
* mode are we going to read nodelist index? Or write?
|
||||
*
|
||||
* Return value:
|
||||
* pointer to the allocated nodelist structure (will be used with all
|
||||
* nodelist operations), and NULL to indicate errors.
|
||||
*/
|
||||
s_nodelist *nodelist_open(const char *dir, const char *name, int mode)
|
||||
{
|
||||
s_nodelist tmp;
|
||||
const char *openmode;
|
||||
int lockmode;
|
||||
|
||||
memset(&tmp, '\0', sizeof(s_nodelist));
|
||||
|
||||
/*
|
||||
* Select nodelist index open mode
|
||||
*/
|
||||
if( mode == NODELIST_READ )
|
||||
{
|
||||
openmode = "r";
|
||||
lockmode = FILELOCK_READ;
|
||||
}
|
||||
else if( mode == NODELIST_WRITE )
|
||||
{
|
||||
openmode = "w";
|
||||
lockmode = FILELOCK_WRITE;
|
||||
}
|
||||
else
|
||||
ASSERT(0);
|
||||
|
||||
/*
|
||||
* Get nodelist and nodelist index file names
|
||||
*/
|
||||
if( *name == DIRSEPCHR )
|
||||
{
|
||||
strnxcpy(tmp.name_nodelist, name, sizeof(tmp.name_nodelist));
|
||||
strnxcpy(tmp.name_index, name, sizeof(tmp.name_index));
|
||||
}
|
||||
else
|
||||
{
|
||||
strnxcpy(tmp.name_nodelist, dir, sizeof(tmp.name_nodelist));
|
||||
strnxcat(tmp.name_nodelist, name, sizeof(tmp.name_nodelist));
|
||||
strnxcpy(tmp.name_index, tmp.name_nodelist, sizeof(tmp.name_index));
|
||||
}
|
||||
strnxcat(tmp.name_index, ".index", sizeof(tmp.name_index));
|
||||
|
||||
DEB((D_NODELIST, "nodelist_open: nodelist name = \"%s\"", tmp.name_nodelist));
|
||||
DEB((D_NODELIST, "nodelist_open: nodelist index = \"%s\"", tmp.name_index));
|
||||
DEB((D_NODELIST, "nodelist_open: open mode = \"%s\"", openmode));
|
||||
|
||||
/*
|
||||
* Try to open and lock nodelist
|
||||
*/
|
||||
if( (tmp.fp_nodelist = file_open(tmp.name_nodelist, "r")) == NULL )
|
||||
{
|
||||
logerr("cannot open nodelist \"%s\"", tmp.name_nodelist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to open and lock nodelist index
|
||||
*/
|
||||
if( (tmp.fp_index = file_open(tmp.name_index, openmode)) == NULL )
|
||||
{
|
||||
logerr("cannot open nodelist index \"%s\"", tmp.name_index);
|
||||
fclose(tmp.fp_nodelist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we open nodelist for reading then we should check that
|
||||
* nodelist index has correct header and up to date
|
||||
*/
|
||||
if( mode == NODELIST_READ )
|
||||
{
|
||||
if( nodelist_checkheader(&tmp) == -1 )
|
||||
{
|
||||
file_close(tmp.fp_nodelist);
|
||||
file_close(tmp.fp_index);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return xmemcpy(&tmp, sizeof(s_nodelist));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Check nodelist index header for valid nodelist date and size
|
||||
*
|
||||
* Arguments:
|
||||
* nlp opened nodelist
|
||||
*
|
||||
* Return value:
|
||||
* zero value if header is correct, and -1 if not
|
||||
*/
|
||||
int nodelist_checkheader(s_nodelist *nlp)
|
||||
{
|
||||
unsigned long nltime;
|
||||
unsigned long nlsize;
|
||||
struct stat nlstat;
|
||||
char buffer[NODELIST_HDRSIZE];
|
||||
|
||||
if( fread(buffer, sizeof(buffer), 1, nlp->fp_index) != 1 )
|
||||
{
|
||||
logerr("cannot read header from nodelist index \"%s\"", nlp->name_index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( fstat(fileno(nlp->fp_nodelist), &nlstat) == -1 )
|
||||
{
|
||||
logerr("cannot stat nodelist \"%s\"", nlp->name_nodelist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nltime = buffer_getlong(buffer + 0);
|
||||
nlsize = buffer_getlong(buffer + 4);
|
||||
|
||||
if( (unsigned long)nlstat.st_mtime != nltime )
|
||||
{
|
||||
log("invalid nodelist index: incorrect nodelist date %ld (expected %ld)",
|
||||
(long)nlstat.st_mtime, (long)nltime);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (unsigned long)nlstat.st_size != nlsize )
|
||||
{
|
||||
log("invalid nodelist index: incorrect nodelist size %ld (expected %ld)",
|
||||
(long)nlstat.st_size, (long)nlsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Create/update nodelist index header. Nodelist must be opened for
|
||||
* writing. Now nodelist index header contain nodelist modification
|
||||
* time and nodelist size.
|
||||
*
|
||||
* Arguments:
|
||||
* nlp opened nodelist
|
||||
*
|
||||
* Return value:
|
||||
* zero value on success, and -1 at errors
|
||||
*/
|
||||
int nodelist_createheader(s_nodelist *nlp)
|
||||
{
|
||||
struct stat nlstat;
|
||||
char hdrbuf[NODELIST_HDRSIZE];
|
||||
|
||||
memset(&hdrbuf, '\0', sizeof(hdrbuf));
|
||||
|
||||
if( fstat(fileno(nlp->fp_nodelist), &nlstat) == -1 )
|
||||
{
|
||||
logerr("cannot stat nodelist \"%s\"", nlp->name_nodelist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_putlong(hdrbuf + 0, nlstat.st_mtime);
|
||||
buffer_putlong(hdrbuf + 4, nlstat.st_size);
|
||||
|
||||
if( fseek(nlp->fp_index, 0L, SEEK_SET) == -1 )
|
||||
{
|
||||
logerr("cannot seek to zero offset of index");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( fwrite(hdrbuf, sizeof(hdrbuf), 1, nlp->fp_index) != 1 )
|
||||
{
|
||||
logerr("cannot write nodelist index header");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Close nodelist and nodelist index files
|
||||
*
|
||||
* Arguments:
|
||||
* nlp pointer to the opened nodelist
|
||||
*
|
||||
* Return value:
|
||||
* Zero value if close was successful, and non-zero if not
|
||||
*/
|
||||
int nodelist_close(s_nodelist *nlp)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
ASSERT(nlp && nlp->fp_nodelist && nlp->fp_index);
|
||||
|
||||
if( nlp->fp_nodelist && file_close(nlp->fp_nodelist) )
|
||||
logerr("cannot close nodelist \"%s\"", nlp->name_nodelist);
|
||||
|
||||
if( nlp->fp_index && file_close(nlp->fp_index) )
|
||||
{
|
||||
logerr("cannot close nodelist index \"%s\"", nlp->name_index);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
free(nlp);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int nodelist_putindex(s_nodelist *nlp, const s_bni *bni)
|
||||
{
|
||||
char buffer[NODELIST_ENTRYSIZE];
|
||||
|
||||
ASSERT(nlp && nlp->fp_index);
|
||||
|
||||
buffer_putint(buffer + 0, bni->zone);
|
||||
buffer_putint(buffer + 2, bni->net);
|
||||
buffer_putint(buffer + 4, bni->node);
|
||||
buffer_putint(buffer + 6, bni->point);
|
||||
buffer_putint(buffer + 8, bni->hub);
|
||||
buffer_putlong(buffer + 10, bni->offset);
|
||||
|
||||
if( fwrite(buffer, sizeof(buffer), 1, nlp->fp_index) != 1 )
|
||||
{
|
||||
logerr("error writing nodelist index file \"%s\"", nlp->name_index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nodelist_findindex(s_nodelist *nlp, s_bni *bni, s_faddr addr)
|
||||
{
|
||||
long readitems;
|
||||
char buffer[NODELIST_ENTRYSIZE * NODELIST_READAHEAD];
|
||||
char *p;
|
||||
|
||||
if( fseek(nlp->fp_index, NODELIST_HDRSIZE, SEEK_SET) ) return -1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if( (readitems = fread(buffer, NODELIST_ENTRYSIZE, NODELIST_READAHEAD, nlp->fp_index)) > 0 )
|
||||
{
|
||||
for( p = buffer; readitems > 0; readitems-- )
|
||||
{
|
||||
if( buffer_getint(p + 0) == addr.zone
|
||||
&& buffer_getint(p + 2) == addr.net
|
||||
&& buffer_getint(p + 4) == addr.node
|
||||
&& buffer_getint(p + 6) == addr.point )
|
||||
{
|
||||
bni->zone = buffer_getint(p + 0);
|
||||
bni->net = buffer_getint(p + 2);
|
||||
bni->node = buffer_getint(p + 4);
|
||||
bni->point = buffer_getint(p + 6);
|
||||
bni->hub = buffer_getint(p + 8);
|
||||
bni->offset = buffer_getlong(p + 10);
|
||||
return 0;
|
||||
}
|
||||
p += NODELIST_ENTRYSIZE;
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nodelist_getstr(s_nodelist *nlp, size_t offset, char *buffer, size_t buflen)
|
||||
{
|
||||
ASSERT(nlp && nlp->fp_nodelist);
|
||||
|
||||
if( fseek(nlp->fp_nodelist, offset, SEEK_SET) == 0
|
||||
&& fgets(buffer, buflen, nlp->fp_nodelist) )
|
||||
{
|
||||
string_chomp(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nodelist_lookup_string(char *buffer, size_t buflen, s_faddr addr)
|
||||
{
|
||||
s_bni bni;
|
||||
s_cval_entry *ptrl;
|
||||
s_nodelist *nlp;
|
||||
const char *ndldir = NULL;
|
||||
|
||||
ndldir = conf_string(cf_nodelist_directory);
|
||||
|
||||
/*
|
||||
* Try all nodelists with matching address mask
|
||||
*/
|
||||
for( ptrl = conf_first(cf_nodelist); ptrl; ptrl = conf_next(ptrl) )
|
||||
{
|
||||
if( ftn_addrcomp_mask(addr, ptrl->d.falist.addr) == 0 )
|
||||
{
|
||||
if( (nlp = nodelist_open(ndldir, ptrl->d.falist.what, NODELIST_READ)) )
|
||||
{
|
||||
int rc = nodelist_findindex(nlp, &bni, addr);
|
||||
|
||||
if( !rc )
|
||||
rc = nodelist_getstr(nlp, bni.offset, buffer, buflen);
|
||||
|
||||
nodelist_close(nlp);
|
||||
|
||||
if( !rc )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nodelist_lookup(s_node *node, s_faddr addr)
|
||||
{
|
||||
char buf[512];
|
||||
char abuf[BF_MAXADDRSTR+1];
|
||||
|
||||
nodelist_initnode(node, addr);
|
||||
|
||||
if( nodelist_lookup_string(buf, sizeof(buf), addr) == 0 )
|
||||
{
|
||||
node->listed = TRUE;
|
||||
if( nodelist_parsestring(node, buf) == -1 )
|
||||
{
|
||||
log("invalid nodelist string for address %s",
|
||||
ftn_addrstr(abuf, addr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nodelist_initnode(s_node *node, s_faddr addr)
|
||||
{
|
||||
memset(node, '\0', sizeof(s_node));
|
||||
|
||||
node->addr = addr;
|
||||
strcpy(node->name, "<none>");
|
||||
strcpy(node->sysop, "<none>");
|
||||
strcpy(node->location, "<none>");
|
||||
strcpy(node->phone, "<none>");
|
||||
}
|
||||
|
||||
15
source/bforce/os_os2.c
Normal file
15
source/bforce/os_os2.c
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* binkleyforce -- unix FTN mailer project
|
||||
*
|
||||
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "confread.h"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user