linpac-0.28/ 0000775 0000764 0000764 00000000000 14006074455 007731 5 0000000 0000000 linpac-0.28/Makefile.am 0000664 0000764 0000764 00000002516 14006074433 011705 0000000 0000000 ## Process this file with automake to produce Makefile.in
## Automake options should match the init call in configure.ac
AUTOMAKE_OPTIONS = gnu -Wall -Werror
## See https://bugzilla.redhat.com/show_bug.cgi?id=901333 for more
## information about ACLOCAL_AMFLAGS
## The work-around for this bug is to commit the m4/ directory.
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = contrib ctt data doc macro mail src inst plugins
dist_pkgdata_DATA = README NEWS
EXTRA_DIST = linpac.lsm COPYING generate-ChangeLog.sh
dist-hook:
sh $(top_srcdir)/generate-ChangeLog.sh $(top_srcdir) $(distdir)
.PHONY: noinstall
noinstall:
@if [ -x ./src/linpac ]; then \
(cd src && @LN_S@ applications bin >/dev/null 2>/dev/null); \
(cd src && @LN_S@ ../macro macro >/dev/null 2>/dev/null); \
(cd src && @LN_S@ ../mail mail >/dev/null 2>/dev/null); \
(cd src && mkdir save >/dev/null 2>/dev/null); \
(cd src && mkdir user >/dev/null 2>/dev/null); \
(cd src && mkdir log >/dev/null 2>/dev/null); \
(cd src/applications && @LN_S@ autobin autotx); \
(cd src/applications && @LN_S@ rawio rawtx); \
(cd src/applications && @LN_S@ yapp yapptx); \
(cd src/applications && @LN_S@ mailer/mail mail); \
cp ctt/*.ctt src; \
(cd src/applications/liblinpac && make install); \
echo LinPac is now prepared for running from ./src; \
else echo Please execute the 'make' command first; \
fi
linpac-0.28/COPYING 0000664 0000764 0000764 00000043076 14006074433 010712 0000000 0000000 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: 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.
Copyright (C) 19yy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 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.
linpac-0.28/README 0000664 0000764 0000764 00000022514 14006074433 010531 0000000 0000000
LinPac version 0.28 (stable release)
Copyright (c) 2021 by David Ranch (KI6ZHD) and Martin Cooper (KD6YAM)
Linpac is a modular, Ncurses console-oriented AX.25 packet radio terminal with a
built-in messaging client. Using Linux's native AX.25 network stack, it
can support eight concurrent connected sessions (QSOs) as well as send
UNPROTO packets (UI) to any preconfigured ax25 digi path. Local messaging
support is currently fairly simple yet Linpac is designed to relay all
messages to remote BBSes for full messaging if configured. Linpac "stable"
currently supports an Ncurses-based CLI client but there is also an unstable
Java-based client/server version with a GUI client that's partially
operational but needs work.
If you encounter any problems when compiling or using LinPac please go to
http://linpac.sourceforge.net for support.
Current contributors:
- David Ranch (KI6ZHD)
Packet radio mail: KI6ZHD@N0ARY.#NCA.CA.USA.NOAM
- Martin Cooper (KD6YAM) - Polling load reduction; mail bug fixes; many warning cleanups
- Jerry Dunmire (KA6HLD) - Auto-tools
- Steven Loomis (K6SPI) - Misc patches
Many thanks to the original author of Linpac for creating this flexible
and valuable package for Linux:
Radek Burget OK2JBG ( radkovo@centrum.cz )
QUICK INSTALATION FROM A RELEASE PACKAGE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Release packages can be identified by the presence of the ./configure in
this directory. If the ./configure script is not present, then see the
'Hacking' instructions below.
Optional:
---------
If you plan to use Linpac for recieving and sending your packet mail via a
remote BBS system (not required), you must install the ax25mail-utils
package first BEFORE first running Linpac. This package can be found
at http://ax25mail.sf.net
Before compilation of Linpac, you must have these other packages installed:
NOTE: Though some distributions offer the AX25 libraries natively in
their own repositories, they are usually very old and lack several
important fixes. You can read more about these improvements here:
https://github.com/ve7fet/linuxax25
Required dependencies:
~~~~~~~~~~~~~~~~~~~~~~
Debian / Ubunutu package names: libax25 ax25-apps libncurses5-dev perl
Optional install: ax25-tools ax25-xtools ax25mail-utils
Centos / Fedora package names: libax25 ax25apps ncurses-libs perl
Optional install: ax25tools ax25mail-utils
I recommend all users install or build the AX.25 stack from
this alternative provider for now:
https://github.com/ve7fet/linuxax25
Once you have installed the above dependencies, please run:
./configure
NOTE: If the "configure" prompt isn't present, you probably got your source
code from Git. If so, run the following:
autoreconf --install
./configure
If autoreconf doesn't run, it probably means you need to install Autotools:
deb-based:
sudo apt-get install automake autoconf
rpm-based
yum install automake autoconf
If "autoreconf --install" fails with:
src/applications/liblinpac/Makefile.am:4: error: Libtool library used but 'LIBTOOL' is undefined
src/applications/liblinpac/Makefile.am:4: The usual way to define 'LIBTOOL' is to add 'LT_INIT'
src/applications/liblinpac/Makefile.am:4: to 'configure.ac' and run 'aclocal' and 'autoconf' again.
src/applications/liblinpac/Makefile.am:4: If 'LT_INIT' is in 'configure.ac', make sure
src/applications/liblinpac/Makefile.am:4: its definition is in aclocal's search path.
Do the following:
deb-based:
sudo apt-get install libtool
libtoolize
autoreconf --install
rpm-based:
sudo yum install libtool
libtoolize
autoreconf --install
The default installation destination directory prefix is /usr/local/*. If you
want to change this, add the following configuure --prefix switch:
./configure --prefix=DIR
where DIR is the new destination directory prefix.
(LinPac installs into PREFIX/bin and PREFIX/share/linpac)
After this just type
make
to compile the package. At that point, you can install the application a few
ways:
For Debian/Ubuntu folks:
--
Consider using the "checkinstall" tool instead of "make install".
This tool must be installed seperately but it will run the
equivelent of "make install" but instead, wrap everything into an
unofficial .deb file with proper packaging
or
For rpm based folks:
--
Consider using the included contrib/packaging/rpm/linpac.spec
file with the rpmbuild tool. This tool must be installed seperately
but takes care of creating a clean RPM package to install
or
# The old classic way
make install
ldconfig
or
make install-strip
ldconfig
One of these options will install Linpac onto your system. The "install-strip"
command will also strip the debugging information from the program (the installation
is then MUCH SMALLER) but harder to report issues to the developer.
ONCE INSTALLED
~~~~~~~~~~~~~~
Once Linpac is installed, you MUST configure the Linux AX.25 system first.
Linpac is only an application that uses a fully functional AX.25 stack.
Please review the various resources on the Internet on how to do this
such as:
- Official AX25 HOWTO (old, dated but still useful)
http://tldp.org/HOWTO/AX25-HOWTO/
- John Ackermann's pages:
http://www.febo.com/packet/linux-ax25/ax25-config.html
- David Ranch's pages:
http://www.trinityos.com/HAM/CentosDigitalModes/hampacketizing-centos.html#7.ax25initsetup
KNOWN PROBLEMS
~~~~~~~~~~~~~~
- There are reported issues with Ncurses 6.1 (not 6.0) and Linpac where this buggy 6.1 version
is present in Raspbian Buster (10.1), Ubuntu 18.04, etc. Examples include:
* in the monitor window, the first character is sometimes being cut off, but many times
it's not cut off and looks fine.
* in the mail window, weird things are going on with the "background window"
A workaround for now is to run the following command before you run Linpac:
export TERM="simpleterm"
- Signifincant issue with AX.25 and Raspbian Stretch
I have confirmed that with Raspian Stretch, there is some sort of conflict with
it's newly enabled predictable network interface names. What are those? If you
run the command "ifconfig" or "ip addr", you will no longer see Ethernet
interfaces with names like "eth0" but instead, you'll see something like
"enxb827eb5f05". How's that for catchy? For known reasons to the AX.25 kernel
maintainers, in the sa_data kernel data structure, both the stock Raspbian AX.25
.debs and the 3rd party VE7FET ax.25 debs will give errors like the following when
ANY network interface name is longer than 13 characters:
SIOCGIFHWADDR: No such device
Programs like beacon will fail to start. Linpac will also crash upon start with
/usr/bin/linpac: line 181: 9811 Segmentation fault $PKG_BINDIR/linpac $*
Fortunately, if you disable predictable network interface names, things work fine.
To do this, do the following steps:
sudo vi /boot/cmdline.txt
#append the following to the end of the one line in this file
net.ifnames=0 biosdevname=0
Reboot your Raspberry Pi and things will work from there on out. Btw, if Linpac
crashed on you, your terminal might be screwed up and not working properly.
To fix that, run the commands:
stty sane
rm -f rm /var/lock/LinPac.0
- The --enable-LINKSTATIC configuration option does not work.
Please see the linpac-todo.txt file in this source package as well as see
http://linpac.sf.net for other possible problems and their solutions.
NOTES FOR HACKING with the Source code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's always recommended to start with the "develop" Git branch as it will
always have the newest code. From there, a clean checkout from the source
repository is not ready to configure and compile. You will need the GNU
autotools (https://en.wikipedia.org/wiki/GNU_build_system) to create the
./configure script and Makfile templates. Once the autotools are
installed the full build procedure is:
autoreconf --install
./configure
make
make install
You can make a release package for distribution using:
make dist
For debugging Linpac, it is useful to run Linpac in the place of compile
without installing it. For this the command 'make noinstall' can be used.
This will create the directory structure in the ./src directory. This is
only available with the staticaly linked applications.
CONFIGURATION OPTIONS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Most of the configuration options are described in the INSTALL file.
[broken at the moment]
There is one custom option for linpac; --enable-LINKSTATIC.
The applicatons are linked using the shared library by default (the library
liblinpac.so is installed in /usr/local/lib). You can link all the
applications staticaly by running
configure --enable-LINKSTATIC
linpac-0.28/doc/ 0000775 0000764 0000764 00000000000 14006074455 010476 5 0000000 0000000 linpac-0.28/doc/manual.html 0000664 0000764 0000764 00000200312 14006074433 012553 0000000 0000000
LinPac User Manual
LinPac is a packet radio terminal for Linux that allows wide configurability
and easy addition of new functions and special functions needed by the user. The
aim is to minimize the amount of 'hard coded' functions and create a complete
set of applications that can be easy expanded and/or completely reconfigured.
All functions described in this manual match the standard configuration
that comes with the distribution package.
2 First configuration
When linpac is started for the first time on your computer, it automaticaly
creates the directory called LinPac in the running user's home
directory. This directory will contain the user's personal LinPac configuration
settings. After creating this directory, LinPac asks for basic callsign, port
and other information and prepares a useable configuration for you. An example setup
dialog is as shown, where we are using the bogus call "n0call" logging into
the local home BBS "n0ary-1":
$ linpac
Hello dear user. You seem to run LinPac for the first time.
LinPac has to create a directory in your home directory for storing
your personal configuration.
For creating your personal configuration please answer following questions:
Your callsign:
n0call
Enter your home BBS callsign with SSID :
n0ary-1
Enter the name of port to connect N0ARY-1
d710
Enter the digipeaters used to connect N0ARY-1 or press enter
when no digipeaters are used:
Enter the full hierarchical address of N0ARY-1
(e.g. #MOR.CZE.EU)
#NCA.CA.USA.NOAM
Thank you, N0CALL
Please wait a moment for creating your personal configuration
Installation done.
Press ENTER to run LinPac
The above information is then stored in the $HOME/LinPac/macro/init.mac file as
various 'functions'. These functions are based on the very simple interpreted
language (actually it's not a language but something like the batch files in
DOS). In the LinPac/macro directory are all the scripts written in this
language. The init.mac macro is loaded at start of loading Linpac and contains
the commands to setup the callsigns and other settings. You can modify this file
to change the initial configuration of LinPac. Other macros can be run in LinPac
as desired or required. The simplest case of a macro is a normal text file that is
just printed to the screen (or sent to the remote peer) when executed. The language
is described in chapter 6.
You may also want to review or change following macro files:
info.mac - contains information about your system
ctext.mac - executed when the peer connects and should
contain the greeting text
quit.mac - called when user enters the Quit command (end
of connection) and should print some farewell text and disconnect
After this you should be able to make your first connection.
3 LinPac controls
After automatically running the LinPac setup routine, the main screen should appear.
If you see a segmentation fault, please see
Linux AX.25 issues with long predictable network interface names for a work around.
Moving on, in Linpac's main interface in the standard configuraion, the screen is divided
into five parts (described from the top of the screen to the bottom):
QSO window: this window contains the text that came from the
peer and also the sent text and some special messages (different text colours).
Status line: displays your callsign, current time and some
information about the current connection.
Editor: allows you to enter the text you want to send to
the peer or the commands you want to execute
Channel list: displays the list of channels with the callsign
of connected users. The currently selected channel is highlighted.
Monitor : displays the traffic on your radio ports
LinPac is mostly driven by commands. The commands are entered using the
editor and must start with a colon (':') in the first column. Lines that
don't begin with a colon are sent to the peer, if connected.
LinPac allows up to eight connections to be made simultaneously. For each connection
one channel is used. You can switch between channels by pressing the F1 -
F8 keys. Each has its own QSO window, status line and editor. The channel
list and the monitor are common across all the channels.
There is a special channel invoked by pressing F10. This channel has no
QSO window and doesn't allow making a connection. The text written is sent
out immediately using UI frames (beacon).
3.1 Keyboard
The following list contains the important shortcuts:
Global F1 - F8 : switch to channel 1 - 8 F10 : switch to monitor Alt-X : end of LinPac
QSO Window PgUp, PgDn, ctrl-R, ctrl-V : scroll one page
up / down ctrl-E, ctrl-X : scroll one line up / down ctrl-B : skip to end of buffer
Editor Cursor keys, Home, End, Backspace, Del
: text editing ctrl-Y : delete current line Enter : send current line
Some applications (e.g. mailer) can use the whole screen. Each channel
can run only one such application at a time. It's possible to switch
to this application using Alt-<channel_number> (e.g.
Alt-5) and switch back to terminal using F1 - F10.
3.2 Entering commands
Each command is invoked using its name. Some commands can be abbreviated.
In this manual the mandatory part is always written in upper case. The
remainder of the command name is optional. Some commands require some extra
arguments. The arguments are written after the command and are separated by
one or more spaces. If you want to enter an argument containing more than
one word, that argument must be entered in quotation marks.
Examples:
:color red blue - calls the 'color' command with two arguments
- 'red' and 'blue' :color 'light red' or :color "light red" - calls the 'color' command with one argument
'light red'
Most of the commands work on the currently selected channel. If you want
to execute the command on some other channel, you can enter the number of
the channel this way. For example, to make an OUTGOING connection to destination
OK0PAB on Linpac channel 5:
:connect@5 OK0PAB
In this case the 'connect' command is executed on channel 5.
The complete list of commands with descriptions is available in Appendix
A.
3.3 Initiating a connection
To initiate a connection the :Connect command is used. Just
switch to the channel you want to use by pressing F1 - F8 and
enter the following command:
:connect CALLSIGN
Replace the CALLSIGN with the real callsign of the station you want
to connect. The command can be abbreviated to the first letter only. Example:
:c OK0PAB
This command will initiate the connecting sequence to OK0PAB. To close
the connection, you can use the :Disconnect command by entering
:d
When your system has multiple radio ports, you can specify its name
before the callsign like this:
:c 2:OK0PAB
This command will try to connect OK0PAB via port 2. When no port name is
specified, the default one is used. Initially the default port is
the first port in /etc/axports (your system AX.25 port configuration
file). If you want to change the default port, just use the command :port.
:port 2
This will change the default port name to '2'. In some cases it is useful
to set another default port for some selected channels. For this the variable
CHN_PORT can be used (see chapter 4). When set,
the content of this variable overrides the default port selection for
the particular channel. For example, when you set the variable for channel
4 using
:set CHN_PORT@4 1
the port '1' will be used as the default one for the channel 4. For other
channels, the previously set default port will be used.
3.4 Receiving and sending files
The standard distribution can receive files using plain text or binary
transfer and using file transfer protocols YAPP and Autobin. LinPac will
automaticaly start to receive the file when the peer begins to send using
the YAPP or Autobin protocols. The 7+ files are automaticaly saved too. When
you want to save the incoming text you have to use the command
:Write <filename>
The incoming text will be saved until you stop the saving using
:Write off
For receiving a plain binary file, the corresponding command :WBin
can be used. This way of transferring binary files is not recommended; use
the autobin or yapp protocol instead.
The following commands are available for sending files:
:rprg <filename> - sends the file using the Autobin
protocol :yput <filename> - sends the file using the YAPP
protocol :rbin <filename> - sends the binary file (no protocol
- not recommended) :read <filename> - semds the text file
3.5 Remote commands
LinPac allows the remote user to enter commands. For remote control,
all LinPac commands are available but there can be (and should be) some restrictions
for each user.
The remote command must start with the // sequence. For example
if some connected user sends you the text '//info' your terminal
will send back the station information.
The remote commands can be disabled using the command :remote off
and enabled by :remote on. You can also specify that only some commands
be available for remote users. The default list of available remote commands
is defined in the init.mac file (the DEF_RCMD line). It is also
possible to enable various commands for each user. This is described
in chapter 5.
3.6 Character encoding
Some countries use different national character encodings
for some historical reasons. A user who has his Linux console configured
for example for some of the standard ISO encodings may be incompatible with another
one using a traditional encoding. To solve this LinPac allows the translation
of the input and output of each channel using a translation table. The translation
tables are stored in files *.ctt in the LinPac home directory.
All known encodings must be defined in the file called encodings
in the LinPac home directory. This file contains a single line for each encoding
that specifies its alias (name which will identify the encoding in
LinPac), encoding name (an official name such as iso-8859-1) and optionally
the name of the translation table file to be used (without the extension
.ctt).
Note that LinPac does not support multi-byte encodings such as UTF-8
or other Unicode encodings.
The current encoding can be switched using the :TRanslate command separately
for each channel. To specify the default encoding for each user you can
add the line
ENC=<alias>
to the appropriate record in the station database. (The station database is described
in chapter 5.) When no encoding is specified for the
user, the default one is used. The default encoding alias is stored in the
DEF_ENC@0 variable which is set in the macro init.mac.
When the conversion table is not specified in the encodings file LinPac
only changes the name of currently used encoding but doesn't provide any
conversion. However some applications (such as QLinPac which works in unicode)
are able to do their own conversions.
3.7 Huffman compression
Some packet radio terminals and BBS software allows the compression of
transferred text. When switched on, the sender does the compression of all
data before sending them to the other station and the recipient has to decompress
the data after receiving them. This makes the communication more reliable
and reduces the load of the radio link.
The line compression in LinPac is activated using the :comp command.
The compression is switched on using :comp on and switched off
using :comp off. To ensure that the compression is activated or
deactivated on both ends of the link simultaneously LinPac sends the remote
command :comp 1 or :comp 0 to the other station automatically.
The arguments 1 and 0 have the same effect as on and off,
but they don't cause sending any command to the other station.
In the case in which the remote system doesn't support the :comp command
it's necessary to switch on the compression on the remote system manually
and then use the:comp 1 command in LinPac.
4 Variables
Each channel has its own set of variables. Some of the variables are used
to store the configuration data. The user can create and remove variables
and change the values of existing variables using following commands:
:set <variable> <value> - sets the
value of the variable. If the variable doesn't exist, a new one is created.
:get <variable> - prints the value of the variable
:unset <variable> - removes the variable
Some examples:
:set NAME John :set WHOLE_NAME 'John Big' :get NAME :unset NAME
The name of the variable can contain the specification of the channel.
For example the variable NAME@5 is the variable 'NAME'
defined on channel 5.
When LinPac finds the character '%' followed by the name of variable,
it automatically replaces this text with the value of the variable. Considering the
previous example, the text %NAME will be replaced with John.
4.1 Special variables
There are some special internal variables that don't allow changing their
value. Their value is set and changed directly by LinPac and these variables
can be used to add some actual information to the text. The list follows:
%V - LinPac version (e.g. 0.26) %C - The callsign of connected station %N - The name of connected station (when known), else replaced
by the contents of %U macro %Y- Channel callsign (mycall) %K- Current channel number %T - Current time %D - Current date %B - Audible bell %Z - Current time zone %U - The text used when the name is unknown. This can contain
other macros (typicaly %C). %P- The port number %M- The number of connected users %A- The time since the last operator activity %_- End of line (CR) %<- Contents of the last line received, this is cleared by
reading %#number - Replaced by a character with an ASCII value
<number> (e.g. %#27 means ESC) %(command) - Replaced by the command result. %[expression] - Replaced by the result of mathematical
expression
Variables for use in macros only:
%R - the number of macro arguments (up to 9) %0 - the name of the macro %1 - %9 - macro arguments
For example try to write following text in the editor and press enter:
The time is %T and the date is %D.
5 Station database
The station database holds various information about known stations. All
the information is stored in the 'station.data' file and can be
changed using the normal text editor or using the LinPac :Name command.
5.1 The station.data file format
The information about each station is written in a paragraph starting
with the station callsign in square brackets. Each line in the paragraph
contains one definition like:
<item_name>=<value>
A typical station information paragraph might look like this:
[OK0NMA] NAME=PC/FlexNet Brno TYPE=FLEXNET LOC=JN89HE QRG=144.8125 MHz SYSNUM=85946
There are no mandatory items; the user can add various items depending
on what information he wants to store. The current LinPac distribution uses following
item names for standard information:
NAME - Text information about the station, or the operator's name.
LinPac shows this information when connected to that station. LOC - QRA
locator of the station. Shown after connect too.
TYPE - The type of the station. For standard stations the types
FLEXNET, THENET, FBB, BAYBOX, DIEBOX, TNOS, JNOS, DXC and TERM for user terminals
are recomended, but you can add any other type.
LANG - The language to communicate with the station. This is currently
supported by macros only. When this item is set, LinPac will try to
find the macro in the directory macro/<LANG>/.
NICKNAME - The nickname of the operator.
The standard LinPac configuration also uses these item names:
TERM - What type of terminal is used. If 'ansi' is set,
LinPac switches to the ansi-color mode after connecting this station. ENC - The character encoding. Used to automaticaly switch to the
i/o character conversion. RCMD - The list of enabled remote commands for this station. QRG - The user frequency. Used by the logbook. SYSNUM and PWD - Sysop password for the station. See chapter
8.2 for more information.
5.2 The 'Name' command
The :Name command is used to modify the station database. Running
the command without arguments results printing the name of currently connected
station. Arguments can be used to modify the data:
<name> - modify the NAME item -l <locator> - modify the LOC item -t <type> - TYPE -L <language> - LANG -n <nickname> - NICKNAME -s <item>=<value> - modify other item
The command 'Name -i' prints all information about the station.
When you need to change the information about a station other than the connected
station, add the argument -c <callsign>.
Examples:
:Name David :Name -c KI6ZHD -l CM97ai David :Name -i
5.3 Using the database
After any connection is established, LinPac reads the information about the
connected station from the database and creates the set of variables with
names STN_<database_item_name> containing the values
of the items. These variables can be used in macros as described below.
6 About macros
6.1 Creating macros
A macro is a LinPac command that is created using the macro language,
and uses other LinPac commands to perform some action. A macro can be defined
by creating the file macro/<command_name>.mac. It's
possible to define an abbreviated form of the command; this is described
in chapter 7. There are two ways to define a macro:
a) Text macros
This way is suitable for commands which are intended to produce a larger
text output (for example station information). When executing this macro,
each line that doesn't start with ':' is printed (sent out). All commands
must start with the colon. This is suitable for modifying the text output
using the IF ~ ELSE ~ ENDIF commands or for including some other commands.
b) Command macros
A command macro must start with the line :MACRO <name>
Each line of a command macro is interpreted as a command (doesn't start
with the colon and doesn't need to start at the begining of line). Text
output is provided by the 'echo' command. This way is more synoptical and
allows including comments that must start with the sequence ';;'
and end at the end of the line.
A macro is called with its name. When the first arguments starts with
the '@' symbol the macro is executed from the specified label. For example
the command :convers @SEND will execute the macro 'convers.mac'
from the label 'SEND' (see next chapter to see how to define the label).
6.2 Commands used in macros
A macro can contain all LinPac and user defined commands. There
are also some special commands that can be used in macros only:
MACRO [name]
Start of the command script definition (see previous section).
LABEL <label_name>
Creates a label with specified name. In the command scripts the notation
:<label_name> can be used.
GOTO <label_name>
Jump to specified label.
IF ~ ELSE ~ ENDIF
Conditional commands. There are two ways to specify a condition:
normal notation (for more than one command)
IF <condition>
.
.
(commands to be executed when the condition is true)
.
. ELSE
.
.
(commands to be executed when the condition is false)
.
. ENDIF
The ELSE part is not necessary - the IF ~ ENDIF notation is possible.
abbreviated notation (for one conditional command)
IF (<condition>) command
The parentheses are necessary in this case.
The following example shows how to use conditions and how to use the data
from the station database. We want to create a macro that will greet the
operator of the connected station with his nickname or with his name, if the
nickname is not defined.
a) The solution using a text macro (the comments are actually
not allowed in the text macros, they are here for explanation only)
:if %(exist STN_NICKNAME) == 1 ;; when NICKNAME is defined Hello %STN_NICKNAME
;; greet with the nickname :else
;; else (not defined) Hello %N !
;; greet with the name :endif
;;(following commands are always executed) You have connected to %Y at %T. ;; Say your callsign and current time
b) The solution using a command macro
:macro GREETING ;; start the command macro if %(exist STN_NICKNAME) == 1 ;; when NICKNAME is defined echo Hello %STN_NICKNAME ;; greet with the
nickname else
;; else (not defined) echo Hello %N !
;; greet with the name endif
;; (following commands are always executed) echo You have connected to %Y at %T. ;; Say your callsign and current
time
6.3 Special system macros
There are some special macros that are executed automaticaly by LinPac
in some cases:
init.mac - This is executed when LinPac is started and its function
is to set the callsigns, screen options, and some other parameters.
cinit.mac - This is always executed when a connection is established.
The distribution version of this macro sets the channel parameters in order
to configure station settings from the station database (allowed remote commands, i/o encoding,
terminal type) and executes the logbook command to sign the start of a connection.
LinPac always passes two arguments to this macro. The first (%1) argument
is the callsign of the connected station and the second (%2) argument is the
callsign of the previously connected station that provides the connection,
or empty in case of direct connection.
ctext.mac - This macro is executed when some station connects to
the terminal. It should print some greeting text. No arguments are passed.
cexit.mac - This is always executed when a connection closes.
The distribution version of this macro just executes the logbook command
to sign the end of the connection and clears the list of allowed remote commands.
There is always one argument passed by LinPac (%1), containing the callsign
of the disconnected station.
7 Creating new commands
A new command can be represented by a macro or by an external program
(standard linux program or special LinPac application). Macros are placed
in the $LINPACDIR/macro directory and external programs are placed
in the $LINPACDIR/bin directory. In both of these directories is
the file 'commands' that contains the list of commands in that directory.
You should specify here the name of the file, the name of the command in LinPac
(use upper case to specify the mandatory part of the command). It's
not necessary to include the macros here if you don't want to define the
abbreviation.
In case of external programs, it is also possibile to specify
program flags. Currently the following flags are supported:
A - Ascii mode program. LinPac provides CR <-> LF conversion
when communicating with this program. This is the default setting.
B - Binary mode. Disables the text conversions.
C - Leaves the stdout stream of the program on the console and reads its
stderr stream instead.
D - DOS conversion - ignore LF characters.
S - Reads both stdin and stderr streams of the program (shell mode).
L - Local. This program is never available as a remote command.
R - This program is always run as a remote command (its messages are
always sent out).
P - LinPac removes the paths from filenames that are passed as the argument
of this command when the FIXPATH command is on. This is a security option.
8 Standard applications
8.1 File transfer protocols
At present LinPac supports two protocols for transferring files:
Autobin - a simple protocol suitable for short files
YAPP - a very sophisticated transfer protocol that provides
better error detection and is able to resume a previously interrupted transfer
Usage of these protocols is described in chapter 3.4.
LinPac can also automatically save incomming 7+ files. After saving all
parts of a file LinPac tries to call the '7plus' program to decode the file.
Received 7+ files are not removed automatically.
8.2 Automatic password generation
8.2.1 Login passwords
LinPac provides automatic replies to the login authorization requests
for the following systems: F6FBB BBS (VE2BLY C_FILTER), BAYBOX, TNOS (numeric
MD5). Each station which requests a login password must have an entry
in the station database containing at least following fields:
A
TYPE=<station_type> (FBB, BAYBOX or TNOS) LOGINPW=<login_password> PWPROMPT=<BBS_prompt>
BBS_prompt is the text which the BBS sends when requesting
the authorization. Usually it looks like 'Password>' or 'OK0XYZ>'.
8.2.2 Sysop and general use passwords
LinPac provides automatic authorization to the following systems: F6FBB BBS
(MD2 password), FLEXNET (older versions, the 'magic' numbers system and newer
TheNet-like system), THENET and BAYBOX. Each station you want to authenticate
with must have an entry in the station database. For password generation, the following
fields must be set:
TYPE=<station_type> PWD=<your_password> or SYSNUM=<magic_number>
Known station types are:
FBB - An F6FBB BBS. The PWD field must contain your password.
THENET - A TheNet node. Again the PWD must contain the password.
BAYBOX - The same system as TheNet.
FPAC - A FPAC node. Password must be stored in the PWD field.
FLEXNET - FlexNet node. If the magic number algorithm is
used (older versions of flexdigi) the SYSNUM field must contain your magic
number and the PWD field must not be set. When the TheNet algorithm is used
(newer versions of flexdigi), the PWD field must contain the password and
the SYSNUM field must not be used.
In case of FBB the authorization algorithm can be chosen by setting
the MD field in the station database:
MD=5 - this value will select the MD5 algorithm MD=2 - this value will select the MD2 algorithm
When no value is set, MD2 algorithm is used.
After connecting to the station you want to authenticate with, the authorization
sequence begins with the :PW command. LinPac will send the authorization
command to the station and tries to answer the authorization request using
your password. If the password is correct, authorization should finish successfully.
The PW command accepts the following parameters:
:PW [<command> [<system> [<password>]]]
where
<command> is the command to be sent to the remote
station to start the authorization sequence (sys by default)
<system> is one of the above-mentioned supported
systems; this system is used instead of the one specified in station database
<password> is the password that will be used instead
of the one specified in the station database
It's recommended that you create simple macros for frequently used authorizations
that require special arguments to the PW command.
8.3 Utilities for mail exchange
LinPac contains support for exchanging messages with remote Kantronics PBBSs as well
as F6FBB BBS systems. This support utilizies some tools from the ax25mail-utils so please
install that package first. THe next step would be to configure Linpac and ax25mail-utils's
configuration settings with the following variables either in Linpac's channel 0 or in
Linpac's init.mac file:
Example #1: Kantronics KPC3:
HOME_TYPE - This sets the type of remote system you're connecting to.
Supported options are either "PBBS" for Kantronics KPC3 type TNCs or "FBB" for F6FBB
BBSes. Only "PBBS" is well understood though the FBB support has been there for some time.
HOME_BBS - The AX.25 path to the home PBBS including the port name.
For example d710:AA6WK-1 means use the d710 AX.25 port as defined
in the /etc/ax25/axports configuration file and connect to the PBBS AA6WK-1.
It's important to note that the callsigns in Linpac are CaSe-SeNsItIvE so make sure these
two variables use the SAME case.
HOME_ADDR - The full hierarchical address of the BBS (which technically isn't
required for PBBSes). For example
AA6WK.#NCA.CA.USA.NOAM.
To set the variable while in Linpac, the :SET command can be used. You can also
put this same line (but without the colon) in Linpac's init.mac file:
The recommended place to set this variables is in the startup macro init.mac.
The default version of this macro contains an example of setting these variables.
After setting these variables, the following commands are available:
Example #2:
HOME_TYPE - This sets the type of remote system you're connecting to.
Supported options are either "PBBS" for Kantronics KPC3 type TNCs or "FBB" for F6FBB
BBSes. Only "PBBS" is well understood though the FBB support has been there for some time.
HOME_BBS - The AX.25 path to the home BBS including the port name.
For example kiss:OK0PAB OK0NMA means use the kiss AX.25 port
as defined in the /etc/ax25/axports configuration file and connec to the BBS
OK0PAB via the digipeater OK0NMA. It's important to note that the
callsigns are CaSe-SeNsItIvE in Linpac so make sure these two variables use the SAME case.
HOME_ADDR - The full hierarchical address of the BBS. For example
OK0PAB.#MOR.CZE.EU.
To set the variable while in Linpac, the :SET command can be used. You can also
put this same line (but without the colon) in Linpac's init.mac file:
The recommended place to set this variables is in the startup macro init.mac.
The default version of this macro contains an example of setting these variables.
After setting these variables, the following commands are available:
Now you need to configure the ax25mail-utils program by editing the /etc/ax25/axgetlist.conf
file. The following example is to support connecting to PBBSes in example #1 above:
[AA6WK-1]
MYCALL N0CALL
BBSCALL AA6WK-1
BBSPORT d710
CMD_LIST LO +;L
CMD_LIST_FROM LO +;L $
CMD_DISC B
HEADER_LINES 1
FORMAT <NUM> <FLAGS> <SIZE> <TO> <FROM> <DATE> <TIME> <SUBJ>
DATEFMT mm/dd/yyyy
BPFPOS 1--
Each remote BBS gets it's own section, unique callsign, and any other specific settings to support
the sending and receiving of messages.
NOTE: the associated ax25mail-utils /etc/ax25/axgetmail.conf configuration file
NOT currently mentioned in this documentation is only used for remote "FBB" setups. That
support is currently not documented yet.
Urgent: Linpac's packet messaging support is still a work in progress so some quirks exist for now:
All remote BBS systems that use SSID numbers will have their message index files "flattened"
aka written to the same base callsign name without the SSID in /var/ax25/ulistd/. In
the future, this filename should include the -SSID#
All non-private messages will be stored in /var/ax25/mail/<callsign-SSID>
All private messages will be stored in /var/ax25/mail/<callsign-SSID>
There is a known bug in Linpac's message system due to the index "flattening" issue where
messages cannot be written to disk or found in the :mail interface. To work around this issue, do
the following in the directory of the Linux user who is running Linpac:
Now that the basics (and workarounds) are setup, let's fetch any pending messages for you on your
configured remote BBS system. Enter in the following command on the Linux prompt (this example
is following example #1 above):
axgetlist -b AA6WK-1
NOTE: The above Linux command must be run as the same Unix user that is running the Linpac
program.
The axgetlist utility will now fetch an index of all messages on the remote BBS system and
store this list in /var/ax25/ulistd/<bbs-name> (all SSIDs are currently stripped).
While this Linux command line-based index capture occurs, the packet traffic will NOT show up in
Linpac's main send/receive UI as this command is running outside of Linpac. You will see the AX.25
traffic if you have Linpac's AX.25 traffic monitor working. The resulting downloaded index file
will then be used to manually download any messages with the getmsg command or interact
with those remote messages them via Linpac's :mail interface
:GETMSG <message_number> [<message_number>
...]
From the main Linpac interface, this command reads specified messages from the remote BBS and
stores them into /var/ax25/mail/<BBS_callsign>/<message_number>.
The file system directory for the remote BBS must be created before using this command (use upper
case for the BBS callsign). When the message number starts with the letter 'p', the message
is considered a PERSONAL one and it's killed automatically after download. You can specify the kill
command by setting the KILLPERS variable in channel 0 using the # character for
the number of the message (e.g. :set KILLPERS@0 "kill #"). When this variable is not
set, the default command K # is used. This can also be set in the init.mac file.
:SP <address> or :SB <address>
These commands can be used for creating new private messages or bulletins.
The usage is the same as for the FBB BBS.
:FORWARD
Transfers all new messages to the BBS.
:DELMSG <message_number>
Marks the message for delete.
:PACK
Deletes all marked messages.
8.4 Mail client
This application allows full screen message editing and browsing. It provides
a graphical (Ncurses) frontend to mail exchange utilities. The mail client is started
by the :MAIL command from Linpac's Channel 0 (aka.. the F1-key view). If
you run this command from any other Linpac channel, it won't display any messages!
After the mail interface opens, the H key shows the operating instructions.
In the INCOMING mail folder, you should see a list of messages available to download.
Toggle the messages you want to fetch with the SPACEBAR and then use the "d" key to download
those messages.
8.5 Logbook
Logbook is a simple application that is started from the cinit.mac and
cexit.mac scripts (at the begining and at the end of each connection). It
creates the file in the 'log' directory for each callsign and writes there
the time when the connections were started and finished and the QRG. The QRG
is taken from the QRG field of the station entry in station database.
If the station has no QRG defined, the value from the QRG@0 variable
is taken.
9 Command line options
LinPac accepts following command line options:
-m : disable monitor. When this option is used, LinPac doesn't
create it's internal monitor objects and saves memory.
-s : disable ax25spyd. Linpac normally tries to connect
ax25spyd to get monitor data and when the connection fails, the
listen utility is used instead. When -s swicth is used, LinPac
doesn't try to connect ax25spyd at all.
-d : daemon mode. LinPac doesn't initialize the screen and runs
in the background.
-p <string> : specify the arguments for the listen
program. Default value is ar8.
10 Copying
LinPac is Copyright (c) 2002-2020 by David Ranch KI6ZHD and
Copyright (c) 1998-2002 by Radek Burget, OK2JBG
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;
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
(contained in file 'license').
You should have received a copy of the GNU General Public License along
with this program; if not, see <https://www.gnu.org/licenses/>.
Appendix A - LinPac commands
Built-in commands
a) action commands
ABort [address]
Cancels an action. Some commands are cancelled without specifying any address
(e.g. autobin). Addresses for some commands:
Action
Address for abort
autobin RX/TX
autobin (or none)
yapp RX/TX
yapp (or none)
7plus autosave
7plus (or none)
read / RBin
read (or none)
write / WBin
write (or none)
forward
forward (mandatory)
Most of the other commands don't need any address.
COMPress [on | off | 1 | 0]
Switch the link compression on or off. The arguments 1 and 0 have the
same meaning as on or off but the remote station is not synchronized.
Connect [port:]call [digi [digi...]]
Initiate a connection to the specified station.
Disconnect
Disconnect the channel.
Echo <text>
Print (send) the specified text.
FLUSH
Flush an output buffer (for example in scripts before disconnect or before
requesting input).
SYstem
End of LinPac, cancel all connections.
UNproto <text>
Send specified text in a UI frame.
VERsion
Print version information.
b) Commands for variable handling
SET <variable> <value>
Assign a value to the variable. If the variable doesn't exist, it is created.
UNSET <variable>
Remove the variable.
GET <variable>
Return the value of the variable. Usually is better to use macro %variable
(see file macros.txt)
EXISTs <variable>
Return 1 when variable exists, 0 when it doesn't exist.
c) information commands
ENVINFO
Display information about the variable environment.
ISCONnected
Return "1" when the channel is connected, "0" otherwise.
MAXCHannels
Return the number of LinPac channels (typically 8).
PCALL
Return the physical callsign of the connected station (first station connected)
UTCTime
Return current UTC time (operating system value).
d) setup commands
CBell [on|off]
When on, LinPac gives an audio signal when any station connects or
disconnects.
FIXPath [on|off]
When FIXPath=ON then the paths to files mentioned in the parameters are
ignored for external commands marked with a P flag. That means only the
default paths are usable.
INFOLEvel [0 | 1 | 2]
Set the mode of information line:
0 - off (no connection info)
1 - show importatnt informations
2 - show all available informations
KNax [on|off]
Enable/disable sound signal when data is received.
Language [language]
Sets the language used. Currently supported in scripts only.
LIsten [on|off]
When listen is off, all connect requests are ignored by LinPac. Default
value is on.
MBIN [on|off]
When switched on, the monitor shows binary data. When switched off, the
binary data is hidden and replaced with the <Binary data> information.
MONitor [on|off]
Enable/disable monitor function. This command is usually followed by STATLINE
and CHNLINE commands to adjust the screen layout.
MONPort <port_specification> Monitor the specified port(s) only. Port specification is either a port name
(as defined in /etc/ax25/axports) or * for monitoring all the ports.
MYcall <call>
Change the channel callsign.
Port <port_name>
Set the default port for the Connect command. This is usually the first
port defined in the /etc/ax25/axports file but can be overriden here.
This can be overriden for particular channels by setting the CHN_PORT
variable for the channel (see chapter 3.3).
PRIVate [on|off]
Mark the channel as private. No stations are allowed to connect on this
channel.
RCMD [<command list>]
Specify the list of available external commands. Only commands
from this list are available to a remote user. It's possible to include abbreviated
commands. The remote commands can be executed only on a channel which provides
a connection. Adding the @ character just after the command name in
the list (e.g. GET@) means that the remote user is allowed to specify the
channel on which the command should be executed (e.g. //GET@5 NAME).
REMote [on|off]
Enable or disable remote commands.
RXFlow [on|off]
Enable or disable data RX. The data is received only when RXFlow
is enabled on all channels.
TIMEZone [zone]
Set the time zone. Used for information only, doesn't affect time.
UNDest [call]
The destination address for UI / unconnected frames. You can use up to a maximum
of seven digipeaters by by including the remote digis in a space delinated list. Here
is an example where you MUST include the double quotes to complete the proper syntax:
undest "DAVID KLPRC3 KBETH KBANN KBULN"
UNPort <port_name>
Set the default port for the UI frames / unproto traffic command or F10
unproto traffic area. This is usually the first port defined in the
/etc/ax25/axports file but can be overriden here. This can be overriden
for particular channels by setting the unport variable for the channel.
UNSrc [call]
The source callsign for UI frames.
WAtch <port | 0> <pattern> <command/text>
Start to watch the specified port (0 for all ports). When the specified pattern
is received then the specified command is executed or text is sent. (Commands
must start with a colon.)
e) Screen control commands
STATLINE <n>
Place the status line at the n-th line of the screen.
CHNLINE <n>
Place the channel line at the n-th line of the screen.
SWAPEDit
Replace the editor window with the QSO window and vice versa.
INFOLine <nm> <text>
Change the specified info line text. If the info line doesn't exist, it's
created.
REMOVEINFO <nm>
Remove the specified info line.
TRanslate <alias>
Switch I/O character translation (see chapter 3.6).
Running this command on channel 0 (unproto channel) switches the translation
table in all channels including the unproto channel and the monitor window.
TErm <type>
Set the terminal type. If 'ansi' is entered then ANSI-color control sequences
are interpreted.
SCRLimit <low-limit> <high-limit>
When the size of the window buffer exceeds the high limit, then the size
of the buffer is truncated to low-limit. The values are in bytes; default is
356352 and 524288 (384 and 512 kB).
DEFColor <color_name> <foreground_color> <background_color>
Change the color of some part of screen. The color_name parameter specifies
which part of screen to change. The following values can be used:
QSO_RX - received text in QSO window
QSO_TX - sent text in QSO window
QSO_INFO - local information in QSO window
QSO_CTRL - control characters in QSO window
ED_TEXT - normal text in editor
ED_INFO - command results in editor
ED_CTRL - control characters in editor
CI_NORM - channel info line - channel numbers
CI_SLCT - selected channel
CI_NCHN - normal channel
CI_PRVT - private channel
IL_TEXT - status lines
For specifying foreground and background colors, these values can be used:
BLACK, RED, GREEN, BROWN, BLUE, MAGENTA, CYAN, LIGHTGRAY
These additional colors can be used for foreground only:
DARKGRAY, LIGHTRED, LIGHTGREEN, YELLOW, LIGHTBLUE, LIGHTMAGENTA, LIGHTCYAN,
WHITE
f) system commands
RESULT <text>
Return the text as the result of a script.
g) string commands
STRMid <start> <length> <string>
Return the substring starting at <start> position and <length>
characters long.
STRLeft <length> <string>
Return the left substring of specified length.
STRRight <length> <string>
Return the right substring of specified length.
STRLen <string>
Return the length of the string.
STRPos <substring> <string>
Return the position of the substring in the string or -1 when the string
doesn't contain the substring.
UPCASE <string>
Return the string converted into upper case.
External commands
Bell
Call the operator using an acoustic signal.
Compose [p|b] <address> [<subject>] [<filename>]
Create either a Private message or a Bulletin packet message for the specified
callsign or fully formatted packet BBS address. When no subject is specified, the
user is prompted for the subject. When filename is specified, the message is
created from the file, otherwise the text is read from the LinPac console.
CATCH -iol <pattern> <command/text>
Catch is the extended version of WAtch command. It scans one or
more data streams (-i = input stream, -o = output stream, -l = local info
stream) for the configured pattern. The pattern can contain * and ? wildcards.
The command can contain string $1 .. $n which are replaced
with the string corresponding to the n-th wildcard in the pattern. The $0
string is replaced with the whole string that matches the pattern. See catch
-h for extended parameters.
DELMSG <message_number>
Mark the packet message for deletion
FORWARD
Transmit all new packet messages to a BBS
GETMsg <numers>
Fetch packet messages from the configured BBS
JOIN <channel_number>
This is a form of a group chat feature where you can join the specified Linpac
channel to current Linpac channel. All data received on any of these channels is
automatically redirected to the other channel. Stop with :ABort join.
MAIL
Simple full-screen packet message client
MHeard
List of heard stations.
Name
Store station name or change a station database entry. (see Name -h)
PACK
Delete all packet messages marked for deletion
Read <filename>
Send the specified text file (see Wbin / Rbin commands for BINARY files)
RPRg <filename>
Transmit the specified file using Autobin protocol
RTt
Measure the round trip time to the other connected Linpac station. Think of this
as a "ping" time but results can be highly variable due to on-frequency packet
collisions, poor packet decodes, RF propogation, etc.
SENDFile [p|b] <file> <address> [<num_messages>]
This command takes a binary file, splits the file into num_messages
parts using 7plus and creates a separate packet message for each part.
When num_messages is not specified, the command tries to use
the variable BLOCK7P@0 which should contain the maximum size of
one block. If this variable is not set, blocks of 5 KB are created.
WBin / RBin
The same as Read / Write file transfers but to be used with BINARY files.
(See Read / Write commands for TEXT files)
Write <filename>
Start to write received TEXT to the file. (see Wbin / Rbin commands for
BINARY files)
YPUT <filename>
Transmit the file using the YAPP protocol.
Macros
Activity
Show the time since the last operator activity. This is also posted when
users first log into the Linpac system
Conv
Enter the conference.
Info
Print local station information.
Help
Print brief help information.
PW [<command> [<system> [<password>] ] ]
Start the authorization to the BBS or the node. See chapter 8.2.2 .
Quit
Send the quit text and disconnect.
Users / CStatus
Print list of connected users.
Commands for creating scripts
MACRO [name]
Start of the command script definition (see below).
LABEL <label_name>
Create a label with specified name. In the command scripts the notation
:<label_name> can be used.
GOTO <label_name>
Jump to specified label.
IF ~ ELSE ~ ENDIF
Conditional commands. There are two ways to specify a condition:
normal notation (for more than one command)
IF <condition>
.
.
(commands to be done when the condition is true)
.
. ELSE
.
.
(commands to be done when the condition is false)
.
. ENDIF
The ELSE part is not necessary - the IF ~ ENDIF notation is possible.
abbreviated notation (for one conditional command)
IF (<condition>) command
The parentheses are necessary in this case.
RETURN [<data>]
Abort the macro execution and return the data as a result.
SLEEP <seconds>
Pause the macro for specified time in seconds.
WAITFOR <condition>
Pause the macro until the condition is true.
Appendix B - Linpac FAQ / Questions and Answers / Getting more help
Q: X doesn't work right in Linpact. Why? A: Have you looked in the errors.txt file found in the main LinPac directory? It can provide a lot of clues.
Q: When I start Linpac, I get "Segmentation fault". What is the fix? A: You are probably running an old version of Linpac. Please try the newest release
version available at https://sourceforge.net/projects/linpac/
or possibly the newest DEVELOP branch. This will most likely require you to
compile Linpac to get it running
Q: When I start Linpac, all of the text in the AX.25 monitor is indented
to the right. How do I fix this? A: Exit Linpac, go into the directory where Linpac is installed, and delete the file:
monitor.screen
Now restart Linpac. Did that solve your issue? No? Also try deleting the files window*.screen and restart Linpac
Q: My question isn't addressed in this document, where else can I get help? A: Consider reviewing these other URLS:
Zapne sledování daného portu (0 - v¹echny porty). Pokud od protistanice
pøijde zadaný øetìzec, vykoná se pøíkaz (pøíkaz musí zaèínat dvojteèkou,
jinak jde o text k vypsání)
e) pøíkazy pro ovládání obrazovky
STATLINE
Umístí hlavní stavový øádek na n-tý øádek obrazovky.
CHNLINE
Umístí øádek pro pøepínání kanálù na n-tý øádek obrazovky.
SWAPEDit
Zamìní okno editoru s oknem spojení.
INFOLine <èíslo>
Zmìní stavový øádek oznaèený èíslem na zadaný text. Pokud takový øádek
neexistuje, je vytvoøen.
REMOVEINFO <èíslo>
Odstraní stavový øádek oznaèený daným èíslem.
TRanslate
Zapne pøekódování vstupu a výstupu podle zadané tabulky. Tabulky jsou
ulo¾eny v souborech *.ctt
TErm
Nastavý typ terminálu. Pokud se zadá typ 'ansi', pøepne se terminál do
re¾imu ansi barev.
SCRLimit
Kdy¾ velikost bufferu s pøijímanými daty pøesáhne hodnotu high-limit,
potom je buffer zkrácen na low-limit. Hodnoty se udávájí v bajtech.
Implicitní hodnoty jsou 384 kB a 512 kB.
f) systémové pøíkazy
RESULT
Vrátí zadaný text jako výsledek skriptu.
g) pøíkazy pro práci s øetìzci
STRMid <øetìzec>
Vrací podøetìzec zadaného øetìzce zaèínající na pozici
délky maximálnì znakù
STRLeft <øetìzec>
Vrací prvních znakù øetìzce
STRRight <øetìzec>
Vrací posledních znakù øetìzce
STRLen <øetìzec>
Vrací délku øetìzce
STRPos <øetìzec>
Hledá v øetìzci podøetìzec, vrací pozici zaèátku nebo -1 kdy¾ nebyl
nalezen
UPCASE <øetìzec>
Pøevede øetezec na velká písmena
2) Externí pøíkazy
RPrg
Vy¹le soubor protokolem autobin.
Bell
Zvukový signál pro pøivolání operátora.
Compose
Vytvoøení privátní zprávy/bulettinu pro danou znaèku.
FORWARD
Odeslání dosud neodeslaných zpráv do domácí BBS.
MHeard
Vypsání sly¹ených stanic.
MAIL
Vyvolá nástroj pro ètení a psaní po¹ty
Name
Ulo¾ení jména a editace databáze stanic (viz. Name -h)
RTt
Mìøení èasu pøenosu mezi stanicemi.
YPUT
Vyslání souboru protokolem YAPP.
Write
Zaèátek ukládání pøíchozího textu do souboru. Ukonèí se :Write off.
Read
Vyslání zadaného textového souboru.
WBin / RBin
Jako Write / Read, ale pro binární soubory.
GETMsg <èíslo>
Získání zprávy z domácí BBS.
3) Makra
Activity
Výpis èasu od poslední akce operátora.
Conv
Vstup do konference
Info
Informace o stanici.
Help
Struèná nápovìda k pøíkazùm
Quit
Vyslání ukonèovacího textu a ukonèení spojení.
Users / CStatus
Seznam pøipojených u¾ivatelù
Pøíkazy pro vytváøení skriptù
=============================
MACRO [název]
Uvozuje definici pøíkazového skriptu (viz ní¾e)
LABEL
Definuje návì¹tí daného jména. U pøíkazových skriptù lze nahradit
zápisem :.
GOTO
Skok na dané návì¹tí.
IF ~ ELSE ~ ENDIF
Podmínkové pøíkazy. Existují dva zpùsoby zápisu podmínky:
- normální zápis (pro více pøíkazù):
IF
.
.
(pøíkazy, které se mají vykonat pøi splnìní podmínky)
.
.
ELSE
.
.
(pøíkazy, které se mají vykonat pøi nesplnìní podmínky)
.
.
ENDIF
Èást ELSE lze vynechat a pou¾ít pouze IF ~ ENDIF.
- zkrácený zápis (pro jeden pøíkaz)
IF () pøíkaz
(podmínka je uvedena v závorkách, pøíkaz se provede pøi jejím splnìní)
Pro zápis podmínek lze vyu¾ít operátory = (nebo ==), <, >, <= (nebo =<),
>= (nebo =>), != (nebo <>). Pokud oba operátory jsou èísla, porovnají se
jako èísla, jinak se porovnají jako øetìzce.
Vytváøení skriptù
=================
Skript lze definovat vytvoøením souboru macro/
.mac. Pokud mù¾e být
pøíkaz zkrácen, je tøeba jej uvést v souboru "commands" ve stejném adresáøi.
Existují dva zpùsoby zápisu skriptu:
a) Textové skripty
Tento zpùsob definice je vhodný pro pøíkazy, jejich¾ hlavním úkolem je
vypsat nìjaký text (napøíklad informace o stanici). Po spu¹tìní takto
definovaného pøíkazu je ka¾dý øádek souboru, který nezaèíná dvojteèkou
zobrazen na obrazovku (odeslán protistanici). Pøíkazy musí zaèínat
dvojteèkou, je mo¾no pou¾ít v¹echny pøíkazy LinPacu i ostatní u¾ivatelem
definované pøíkazy a navíc speciální pøíkazy pro skripty. Tímto zpùsobem lze
do textu vlo¾it napøíklad informaci o probíhajících spojeních (pøíkazem
:Users) nebo modifikovat text pomocí pøíkazu :IF,:ELSE a :ENDIF.
b) Pøíkazové skripty
Pøedchozí zpùsob definice umo¾òuje snadné vypisování textu, av¹ak pøi
pou¾ití vìt¹ího mno¾ství pøíkazù se definice stává velmi nepøehlednou.
Definice ve formì pøíkazù je oproti tomu vhodná k zápisu vìt¹ího mno¾ství
pøíkazù s men¹ím mno¾stvím vypisovaného textu.
První øádek takové definice musí tvoøit pøíkaz :MACRO (na zaèátku øádku)
za kterým mù¾e následovat jakýkoliv text (napø. jméno makra atd.). Za tímto
øádkem lze psát pøíkazy, pøed které se u¾ nepí¹e dvojteèka. Tyto pøíkazy
nemusí zaèínat na zaèátku øádku (mohou být libovolnì odsazeny), prázdné
øádky se pøeskakují. Text se vypisuje pomocí pøíkazu Echo.
linpac-0.28/doc/czech/stanice.txt 0000664 0000764 0000764 00000010605 14006074433 013677 0000000 0000000 [Document encoding ISO-8859-2]
LinPac - Databáze stanic
------------------------
Databáze je urèena pro ukládání v¹ech informací o protistanicích. Ve¹keré
tyto informace jsou ulo¾eny v souboru "station.data" a lze je mìnit buï
pøímo editací tohoto souboru, nebo prostøednictvím pøíkazu Name (popsáno
dále).
1. Formát souboru station.data
------------------------------
Informace o ka¾dé stanici jsou uvedeny v odstavci, který zaèíná znaèkou
stanice v hranatých závorkách a konèí buï hlavièkou popisu jiné stanice nebo
koncem souboru. Ka¾dý øádek obsahuje jednu definici ve tvaru
=.
Typický záznam o stanici mù¾e tedy vypadat napøíklad takto:
[OK0NMA]
NAME=PC/Flexnet Brno
TYPE=FLEXNET
LOC=JN89HE
QRG=144.8125 MHz
SYSNUM=85964
®ádná polo¾ka není povinná a u¾ivatel mù¾e do databáze pøidávat libovolné
dal¹í polo¾ky podle toho, jaké informace potøebuje uchovávat. Nicménì pro
zachování urèitého standardu se pro standardní informace doporuèuje pou¾ívat
tìchto jmen:
NAME - textové informace o stanici nebo jméno operátora. Pokud je tato
polo¾ka uvedena v databázi, LinPac zobrazí její obsah pøi spojení
s danou stanicí.
LOC - QRA lokátor stanice. LinPac se opìt pokusí zobrazit tuto informaci
pøi návázání spojení s protistanicí.
TYPE - Typ protistanice. Pro obvykle pou¾ívané typy se doporuèuje:
FLEXNET, THENET, FBB, BAYBOX, DIEBOX, TNOS, JNOS, DXC
a pro u¾ivatelské terminály TERM. Takto udaný typ je ov¹em vyu¾íván
pouze u¾ivatelem, lze proto pou¾ít libovolné oznaèení typu stanice.
LANG - Jazyk kterým se má komunikovat s protistanicí. Pokud je definován,
LinPac se pøi spu¹tìní makra hledat soubor s definicí makra nejprve
v podadresáøi s tímto jménem (macro/).
NICKNAME - pøezdívka operátora, v èe¹tinì lze vyu¾ít pro ulo¾ení pátého
pádu jména.
Standardní konfigurace LinPacu vyu¾ívá navíc je¹tì tyto polo¾ky:
TERM - jaký druh terminálu se má pou¾ít. Pokud je nastaveno 'ansi',
LinPac se po spojení s touto stanicí pøepne do re¾imu zobrazování
barev, co¾ lze vyu¾ít napøíklad u TNOS BBS. Stejný efekt má
i pøíkaz TErm (viz prikazy.txt)
ENC - pou¾ité pøekódování vstupu a výstupu. Pøi spojení se pøepne na
kódovací tabulku s tímto jménem. To umo¾òuje komunikovat s ka¾dou
protistanicí v jiném kódování èe¹tiny. Stejný efekt má pøíkaz
TRanslate.
RCMD - seznam povolených vzdálených pøíkazù.
QRG - frekvence u¾ivatelského vstupu dané stanice, pou¾ije se v záznamech
do stanièního deníku.
2. Pou¾ití pøíkazu Name
-----------------------
Pøíkaz name lze pou¾ít ke zmìnám v databázi stanic bez nutnosti pøímé
editace souboru. Samotný pøíkaz bez parametrù zpùsobí vypsání zadaného
jména právì pøipojené protistanice. Zadáním dal¹ích parametrù se provede
zmìna údajù o právì pøipojené stanici. Pou¾itelné parametry:
- zmìna polo¾ky NAME
-l - zmìna polo¾ky LOC
-t - TYPE
-L - LANG
-n
- NICKNAME
-s = - zmìna jiné polo¾ky.
Pøíkaz Name -i vypí¹e v¹echny zadané informace o stanici.
Pokud chceme mìnit informace o jiné ne¾ právì pøipojené stanici,
pøidáme parametr -c .
Pøíklad:
:NAME -c OK2JBG -n Radku -l JN89HF Radek
3. Vyu¾ití údajù v databázi
---------------------------
Jak ji¾ bylo popsáno, LinPac pro vnitøní potøebu vyu¾ívá pouze polo¾ky se
jmény NAME, LOC a LANG. Vyu¾ití ostatních polo¾ek závisí na u¾ivateli. Pøi
ka¾dém spojení se stanicí, která má záznam v databázi stanice se vytvoøí
promìnné se jmény STN_, které lze vyhodnotit v makrech.
Pøíklad pou¾ití: chci aby se ka¾dá pøipojená stanice oslovila pøezdívkou
operátora a pokud pøezdívka není zadána, aby se oslovila jménem operátora.
Pøi ka¾dém pøipojení protistanice se spou¹tí makro 'ctext.mac' ulo¾ené
v adresáøi macro. Obsah tohoto souboru v na¹em pøípadì mù¾e vypadat
napøíklad takto:
:if %(exist STN_NICKNAME) == 1 ;;pokud existuje STN_NICKNAME
Ahoj %STN_NICKNAME ! ;;pozdrav pøezdívkou
:else ;;jinak (pokud neexistuje)
Ahoj %N ! ;;pozdrav jménem
:endif ;;(dal¹í pøíkazy se provedou v¾dy)
Pøipojil ses k %Y v %T. ;;Sdìl svoji znaèku a èas.
Teï ji¾ staèí jen pøidat øádek NICKNAME=pøezdívka k záznamu ka¾dé stanice,
kterou chci oslovovat pøezdívkou.
linpac-0.28/doc/events.txt 0000664 0000764 0000764 00000044617 14006074433 012473 0000000 0000000 LinPac internal events
----------------------
This list contains the description of almost all events that can occur in
LinPac. Each application can generate any of these events and it can also
handle any of them.
The names of the source objects are written in parenthesis. The list of
internal LinPac objects can be found in the file objects.txt.
a) User interaction
EV_KEY_PRESS (key pressed)
Generated by: The user interface (Keyscan) when a keyboard key is pressed
Handled by : User interface
Data : x - key code (ncurses-compatibile)
y - 0 when Alt wasn't pressed
EV_KEY_PRESS_MULTI (multiple keys pressed)
Generated by: The user interface (Keyscan) when multiple printable keyboard
keys are pressed in rapid succession
Handled by : User interface
Data : data - pointer to c-string
EV_TEXT_RAW (raw output text)
Generated by: Text editor (Editor*) when the text line is confirmed
Macro processor (Macro*) (line from a macro)
Remote command source (Command)
Handled by : Text cooker (Cooker) - replacing the text macros
Data : chn - channel number
data - pointer to c-string
x - contains source description:
FLAG_REMOTE - remote command
FLAG_MACRO - command from macro, wasn't processed with
macro command interpreter (can contain
some macro command such as IF ot GOTO)
FLAG_FM_MACRO - command from macro that is not a special
macro command (already processed with macro
command interpreter)
FLAG_EDIT - from text editor (local user)
EV_TEXT_ARGS (cooking arguments for EV_TEXT_RAW, must be sent just before
each EV_TEXT_RAW when needed).
Generated by: Macro processor (Macro*) before sending EV_TEXT_RAW line
to tell the Cooker object the arguments of the Macro
(for cooking %1 - %9).
Handled by : Text cooker (Cooker)
Data : chn - channel number
data - strings arguments separated by \0
x - data length
EV_TEXT_COOKED (cooked output text)
Generated by: Text variables processor (Cooker) after receiving the
EV_TEXT_RAW event and replacing the variables with their
values.
Any application that wants to send out some text or command.
Handled by : Command processor (Command) (when the text starts with ':')
I/O interface (Ax25io) (when the text doesn't start with
':') - the output is cached (text is not transmitted
immediately)
Data : chn - channel number
data - pointer to c-string
x - source description copied from the received EV_TEXT_RAW
event
EV_TEXT_FLUSH (flush output)
Generated by: any source
Handled by : I/O interface (Ax25io) - transmits the cache contents and
clears the cache
Data : chn - channel number
x = FLAG_FLUSH_IMMEDIATE - flush the output buffer now
= 0 - flush after cooking last EV_TEXT_RAW (usual value)
EV_EDIT_INFO (insert info into editor)
Generated by: Command processor (Command)
Handled by : Text editor (Editor*) - inserts the information behind current
line and moves after this text
Data : chn - channel number
data - pointer to c-string
EV_CALL_CHANGE (change the callsign)
Generated by: Command processor (Command) (:mycall command, :connect command)
Handled by : AX.25 I/O interface (Ax25io) - changes the callsign of the
channel
Data : chn - channel number
data - new callsign (c-string)
EV_UNPROTO_SRC (change unproto source)
Generated by: Command processor (Command) (:unsrc)
Handled by : AX.25 I/O interface (Ax25io) - changes the unproto source
callsign
Data : chn - channel number
data - new callsign (c-string)
EV_UNPROTO_DEST (change unproto destination)
Generated by: Command processor (Command) (:undest)
Handled by : AX.25 I/O interface - (Ac25io) changes the unproto destination
callsign
Data : chn - channel number
data - new callsign (c-string)
EV_UNPROTO_PORT (change unproto port)
Generated by: Command processor (Command) (:unport)
Handled by : AX.25 I/O interface (Ax25io) - changes the unproto port
Data : chn - channel number
data - new port name (c-string)
EV_WANT_RESULT (execute the command and generate a result event)
Generated by: Variable processor (Cooker) when replacing %(command)
Handled by : Command processor - executes the command and generates the
EV_CMD_RESULT event containing the result
Data : chn - channel number
data - command string (without the initial ':') (c-string)
x - result ID. The EV_CMD_RESULT generated by command
processor will have the same ID (for recognizing the right
result)
EV_CMD_RESULT (the command result)
Generated by: Command processor as the answer to EV_WANT_RESULT event or
after executing a command that returns some result (:strlen
...)
The application using the appl_result() function.
Handled by : Command processor - when ID == FLAG_NO_HANDLE then generates
the EV_EDIT_INFO event to display the
result in editor
The creator if EV_WANT_RESULT with the same result ID.
Data : chn - channel number
data - result text (c-string)
x - result ID - can contain the ID of the EV_WANT_RESULT event
that caused this event or it can contain
FLAG_NO_HANDLE (value -1) when this is not the
answer to any EV_WANT_RESULT
EV_DO_COMMAND (execute the command)
Generated by: any source
Handled by : Command processor - executes this command
Data : chn - channel number
data - command without the initial ':' (c-string)
EV_SELECT_CHN (current channel change)
Generated by: User interface (Keyscan) (user pressed F1 - F10)
Applications that want to switch the channel
Handled by : Many objects (object activation/deactivation etc...)
Data : chn - new channel number:
1 to 8 - normal channels (F1 - F8)
0 - unproto channel (F10)
-1 to -8 - channels for fullscreen applications (Alt-1 - Alt-8)
-10 - channel for fullscreen application (Alt-0)
EV_USER_ACT (user is active)
Geterated by: User interface (Keyscan) (user has done some action)
Handled by : User activity counter (clears)
Data : none
b) Macros
EV_MACRO_STARTED (macro processing has been started)
Generated by: Macro processor (Macro*)
Handled by : Macro processor - pauses processing other macros on the
channel
Data : chn - channel nuber
data - pointer to new macro processor (for identification)
EV_MACRO_FINISHED (macro processing has been finished)
Generated by: Macro processor
Handled by : Macro processor - resumes processing other macros on the
channel
Data : chn - channel nuber
data - pointer to finishing macro processor (for identification)
c) Character input/output
EV_DATA_INPUT (data block received)
Generated by: I/O interface (Ax25io) after receiving some data
Handled by : User interface (QSOWin*) - display incomming text
Incomming text watcher (Watch) - scan for pattrens
Data : chn - channel number
data - pointer to char buffer (char[])
x - block length (characters)
EV_DATA_OUTPUT (data block transmitted)
Generated by: I/O interface (Ax25io) after transmitting some data
Handled by : User interface (QSOWin*) - display outgoing text
Data : chn - channel number
data - pointer to char buffer (char[])
x - block length (characters)
EV_LOCAL_MSG (local info text)
Generated by: I/O interface
Handled by : User interface - display local info
Data : chn - channel number
data - pointer to char buffer (char[])
x - block length (characters)
EV_LINE_RECV (text line received)
Generated by: I/O interface (Ax25io) after receiving end of line
in incomming data
Handled by : Command processor - check for "//" - external commands
Incomming text watcher - check for "connected to" ...
Data : chn - channel number
data - pointer to char buffer (char[])
x - block length (characters)
EV_RX_CTL (rx data flow control)
Generated by: Command processor (Command) - :rxflow on/off
I/O interface when new incomming connection establishes
(for synchronization reasons)
Handled by : I/O interface (Ax25io)
Data : x - 0 = rxflow is off, 1 = rxflow is on
d) Connection
EV_CONN_LOC (begin connection)
Generated by: Command processor (:connect)
Application that wants to initiate the connection
Handled by : I/O interface - begins the connection
Data : chn - channel number
data - c-string with destination address in format
port:CALL DIGI1 DIGI2 ...
EV_DISC_LOC (close connection)
Generated by: Command processor (:disconnect)
Application that wants to close the connection
Handled by : I/O interface - closes the connection
Data : chn - channel number
EV_CONN_TO (connection established)
Generated by: I/O interface when connection establishes
Handled by : User interface (QSOWin*) (display the message...)
Data : chn - channel number
data - connected callsign (c-string)
x - 0 when we initiated the connection
(else other party has initiated the connection)
EV_DISC_FM (connection closed)
Generated by: I/O interface when station disconnects
Handled by : User interface (QSOWin*) (display the message...)
Data : chn - channel number
data - disconnected callsign (c-string)
EV_DISC_TIME (disconnected for timeout)
Generated by: I/O interface when station disconnects for timeout
Handled by : User interface (QSOWin*) (display the message...)
Data : chn - channel number
data - disconnected callsign (c-string)
EV_CONN_REQ (unsuccesful connect request)
Generated by: I/O interface when some station requests the connection and
there is no free channel
Handled by : User interface (QSOWin*) (display the message...)
Data : chn - channel number
data - callsign (c-string)
EV_FAILURE (connection failure)
Generated by: I/O interface when connection breaks
Handled by : User interface (QSOWin*) (display the message...)
Data : chn - channel number
data - callsign (c-string)
EV_RECONN_TO (reconnected to)
Generated by: Incomming text watcher (Watch) when the message is detected
Handled by : User interface (InfoLine...)
Data : chn - channel number
data - new callsign (c-string)
x - 1 when connected forward ("connected to" message)
else connected back ("reconnected to" message)
EV_STATUS_CHANGE (connection status changed)
Generated by: I/O interface when connection status changes
Handled by : User interface (display new status)
Data : chn - channel number
x - new status:
ST_DISC - disconnected
ST_DISP - disconnecting
ST_TIME - disconnecting for timeout
ST_CONN - connected
ST_CONP - connecting in progress
EV_DISABLE_CHN (disable connections to the channel)
Generated by: Command processor (:priv)
Applications that want to reserve the channel
Handled by : I/O interface (marks the channel)
User interface (shows the ++++++ instead of ------)
Data : chn - channel number
EV_ENABLE_CHN (enable connections to the channel)
Generated by: Command processor (:priv)
Application
Handled by : I/O interface
User interface
Data : chn - channel number
EV_LISTEN_ON (enable incomming connections)
Generated by: Command processor (:list)
Handled by : I/O interface (creates listening sockets)
Data : none
EV_LISTEN_OFF (disable (=ignore) incomming connections)
Generated by: Command processor (:list)
Handled by : I/O interface (closes listening sockets)
Data : none
e) Screen
EV_DISABLE_SCREEN (disable output to QSO window)
Generated by: Applications (in case of binary transfer...)
Handled by : User interface (stops displaying the data in QSO window)
Data : chn - channel number
EV_ENABLE_SCREEN (enable output to QSO window)
Generated by: Applications (end of binary transfer...)
Handled by : User interface (enables output to window)
Data : chn - channel number
EV_CHANGE_STLINE (change or create additional status line)
Generated by: Command processor (:infoline)
Applications using the statline() function
Handled by : User interface (add or change the status line)
Data : chn - channel number
data - status text (c-string)
x - line ID. If the line with this ID doesn't exist, it's
created. If it exists, the content is changed.
EV_REMOVE_STLINE (remove aditional statusline)
Generated by: Command processor (:removeinfo)
Applications using the remove_statline() function
Handled by : User interface
Data : chn - channel number
x - line ID
EV_CONV_IN (install input conversion table)
EV_CONV_OUT (install output conversion table)
Generated by: Command processor (:trans)
Handled by : User interface
Data : chn - channel number, 0 means all channels and monitor window
x - table length, max 256
data - x bytes, each byte represents the output character when
the character with ASCII value equal to index of that
byte is received. When the value of received character
is greater than x no conversion is done.
EV_CONV_NAME (use specified i/o character encoding)
Generated by: Command processor (:trans)
Handled by : User interface
Data : chn - channel number, 0 means all channels and monitor window
data - c-string containing encoding name
EV_SET_TERM (set terminal type - none, ansi, ...)
Generated by: Command processor (:term)
Handled by : User interface
Data : chn - channel number
data - terminal name (c-string)
EV_REDRAW_SCREEN (redraw the screen)
Generated by: Command processor (:redraw)
Handled by : User interface
Data : none
EV_MONITOR_CTL (control the monitor)
Generated by: Command processor (:monitor)
Handled by : User interface (monitor window)
Data : x = 0 : disable monitor function (stop displaying anything
into the monitor window)
x = 1 : enable monitor function
f) Application communication
EV_APP_MESSAGE (message from application to other application)
Generated by: application
Handled by : application
Data : data - message text (c-string)
EV_APP_RESULT (an application result)
Generated by: application
Handled by : Event manager - after the application finishes the
EV_CMD_RESULT with the same data is generated.
Data : data - the result message (c-string)
EV_REG_COMMAND (register a command for an application)
Genereted by: application (wants to provide an user command)
Handled by : Command processor (Command) - considers the command as the
known one, when execution of this commands is requested,
generates EV_APP_COMMAND.
Data : data - command name (c-string)
EV_UNREG_COMMAND (cancel command registration)
Generated by: application
Handled by : Command processor (Command) - command registration is
caneclled.
Data : data - command name (c-string)
EV_APP_COMMAND (a command to be executed by an application)
Generated by: Command processor (Command) - registered command requested
Handled by : application that provides such command
Data : chn - execution channel
data - command name and arguments (c-string)
g) Other events
EV_STAT_REQ (application requests the AX.25 connection status)
Generated by: application
Handled by : LinPac status server (Status) - generates EV_STATUS
Data : chn - channel number
EV_STATUS (connection status info)
Generated by: LinPac status server (the answer to EV_STAT_REQ event)
Handled by : application
Data : chn - channel number
data - points to the ax25_status structure
EV_DISABLE_OBJ (temporarily disable an internal object)
Generated by: anybody
Handled by : Event manager (stops sending the events to this object)
Data : data - object name (e.g. QSOWindow1) (c-string)
EV_ENABLE_OBJ (enable an internal object)
Generated by: anybody
Handled by : Event manager (resumes sending the events to this object)
Data : data - object name (c-string)
EV_ADD_WATCH (watch for pattern in input data)
Generated by: Command processor (Command) - :watch
Handled by : Input text watcher (Watch)
Data : chn - channel (0 = all the channels)
data - text pattern
EV_ABORT (abort application)
Generated by: Command processor (:abort)
Handled by : application (compares the address with its own one and aborts)
Data : chn - channel number
data - abort address (command parameter) (c-string)
EV_VOID (void event - synchronization reasons)
Generated by: anybody
Handled by : nobody
Data : none
EV_SYSREQ (request special actions - debugging...)
Generated by: normally nobody
Handled by : Event manager
Data : x - request number. Currently implemented:
0: check if debugging is supported
1: dump a list of active internal modules to errorlog
2: toggle macro debugging (this dumps the internal macro
notation to errorlog each time a macro is executed)
EV_QUIT (quit LinPac)
Generated by: Command processor (:system)
Handled by : Event manager (stops working)
Data : none
linpac-0.28/doc/objects.txt 0000664 0000764 0000764 00000003641 14006074433 012610 0000000 0000000 LinPac internal objects
-----------------------
This is a list of LinPac internal objects. Each object is identified by its
name (up to 10 characters).
Object name | Description
----------------+-----------------------------------------------------------
SCREEN | Screen manager.
|
Keyscan | Reads the keyboard, generates appropriate events when one or
| more keys are pressed (EV_KEY_PRESS, EV_KEY_PRESS_MULTI)
|
Command | Interpret commands represented by EV_DO_COMMANDS,
| EV_TEXT_COOKED (starting with :) or EV_LINE_RECV
| (remote commands)
|
Ax25io | Ax25 i/o interface. Sends/receives packets, generates
| EV_DATA_INPUT, EV_DATA_OUTPUT, EV_LOCAL_MSG, creates
| packets from EV_TEXT_COOKED and sends them.
|
Cooker | Converts EV_TEXT_RAW to EV_TEXT_COOKED (macro
| replacement).
|
ChnInfo | Channel information line (shows callsigns depending on the
| connection/reconnection events)
|
InfoLine | Connection status line.
|
MonWin | Monitor window.
|
QSOWin1 - | QSO windows for each channel. Displays the data contained
QSOWin8 | in EV_DATA_INPUT, EV_DATA_OUTPUT and EV_LOCAL_MSG events.
|
Editor0 - | Editor windows each channel (0 = unproto mode). Reads the
Editor8 | EV_KEY_PRESSED and EV_KEY_PRESS_MULTI events and produces
| EV_TEXT_RAW events.
|
Statln1 - | Managers of additional status lines (one for each
Statln8 | channel).
|
StnDB | Station database. Reacts to (re)connection events and
| produces information messages, sets the variables, etc.
|
Watch | Input data watcher. Looks for patterns in input data,
| produces command events when some pattern is found.
|
Sound | Produces various sounds when some particular event occurs.
|
Status | Registers connection status, generates status events.
|
----------------+------------------------------------------------------------
linpac-0.28/doc/applguide.html 0000664 0000764 0000764 00000110443 14006074433 013255 0000000 0000000
LinPac External Application Programming Guide
LinPac - Packet Radio Terminal for Linux
Version 0.28
(c) Martin Cooper KD6YAM 2020
(c) David Ranch KI6ZHD (linpac@trinnet.net) 2002 - 2020
(c) 1998 - 2001 by Radek Burget OK2JBG
This guide is written for programmers who want to add some new functions
to LinPac. In the following text, basic knowledge of Linux programming
is assumed. Reading the LinPac User Manual before proceeding is also
recommended.
2 What is an external program?
An external program is a standard Linux application which uses LinPac to
communicate with remote stations. There are basically two types of LinPac
external programs:
Standard Linux applications that use standard input and output streams.
These programs can be used without LinPac too. LinPac allows redirection
of the input stream (stdin) of the application and any of the output streams
(stdout, stderr) or both of them. LinPac can also provide CR/LF conversions
in these streams. These parameters are set when adding the external program
to LinPac - see Section 7, "Creating
new commands", in the User Manual.
Applications written using LinPac's application interface. These applications
can share some information with LinPac, and they can control almost all
functions of LinPac.
No special knowledge of LinPac is needed for creating the first type
of programs, because no LinPac functions are used. The remainder of
this guide is dedicated to the second type of applications.
3 Basic concepts of the API
The LinPac application interface is based on events. Every action
in LinPac, such as pressing a key, receiving data, executing a command,
etc., is represented by a data structure called an event, which describes
exactly what happened. LinPac's internal structure consists of separate
objects which
communicate with each other using these events. Each object provides its
own functionality, and often generates events. For example, the object
Keyscan produces an event each time any key is pressed.
All the events generated by any object are put into the common event
queue. The LinPac kernel simply takes the events from the queue one by
one and sends them to all the objects (including the one that generated
the event). Thus each event generated by any part of LinPac is forwarded
to all of the objects. The reaction of each object fully depends on its
functionality, but of course it can include generation of other events.
The list of LinPac internal objects and their names can be found in
the file objects.txt.
An additional feature of the API is a shared variable environment. This
is a set of variables that is shared with LinPac; the values are automatically
synchronized with all the external programs. These variables are accessed
using special functions of the API as described below.
4 How applications communicate with LinPac
LinPac uses TCP/IP sockets for communication with external
programs (applications). The connection is always initiated by the application
after it starts. There are basically two ways that an application may be started:
The application is started by LinPac, through being associated with a LinPac command.
In this case LinPac registers the channel on which the application was started
and expects the connection attempt from the application. After the application
initializes and contacts LinPac, it is provided with the working channel and whether
it was started by a remote or local user. LinPac may also redirect the input
and output streams of the application (depending upon LinPac settings).
The application is started without using LinPac. In this case LinPac assumes
that the application runs on channel 0 and was started by the local user. The
input and output streams of the application are not redirected.
In both cases, the start of an application causes the creation of a new
object in LinPac called an event gate. This object represents the application
within LinPac. Bearing in mind the previous chapter, this means that the application
is forwarded all of the events generated by any LinPac object, and all of the
events generated by the application are forwarded to all LinPac objects.
NOTE: All of the communication via TCP/IP sockets is provided by
the LinPac application library. The user application should not attempt to access the
sockets directly.
5 Using the application library
During LinPac installation, the application library liblinpac is
created and installed by default to /usr/local/lib. The interface
to this library is contained in the file lpapp.h, which is installed
by default to /usr/local/include/linpac. The next chapter
illustrates how to use the library within a user application.
5.1 The simplest application
The following application example just tries to contact LinPac, and prints the
result.
#include <stdio.h>
#include <unistd.h>
#include <linpac/lpapp.h>
int main()
{
if (lp_start_appl())
{
printf("Application started\n");
sleep(10);
printf("Application finished\n");
lp_end_appl();
}
else
{
printf("LinPac is not running\n");
return 1;
}
return 0;
}
The function lp_start_appl() tries to contact LinPac and returns
1
in case of success or 0 when a connection to LinPac cannot be made (probably
because it's not running). This function should precede the usage of any other
application library functions.
The function lp_end_appl() closes the connection to LinPac.
To compile this example, use:
$ gcc -o test1 test1.c -llinpac
This example just detects if LinPac is running, and it can be executed
directly from the shell. When running from the shell, no streams are redirected
to LinPac, and the application appears to run on channel 0 of LinPac. This is
useful for some applications that are used to control LinPac from outside.
However this is not a typical use case.
For most applications, it is better to copy the executable to the
$LINPACDIR/bin
directory and then add it to the file
$LINPACDIR/bin/commands as described in the User
Manual. After this, the application can be executed as a LinPac command.
In this scenario, the streams are properly redirected and the application output
is visible in the LinPac QSO window. It is also possible to select the channel
on which to run the application.
NOTE: The LinPac application library (liblinpac) can be
linked without problems with both C and C++ code.
6 Application programming
6.1 Events
LinPac is completely driven by events. Each part of LinPac, including
applications, can generate events to inform other parts (internal modules
or applications) that something has happened. Each event is sent to all
LinPac components and applications. For example when some station connects
to some LinPac channel, the internal AX.25 interface generates an event
reporting that the station has connected and includes its callsign. All
components and applications now know who has connected, and they can take
some actions. For example, the output window prints information about the connection,
the macro processor executes the cinit.mac macro, and so on. Each application
can handle all of the events too, and can generate events which are handled
by other components.
An event is represented by the following structure:
struct Event
{
int type;
int chn;
int x,y;
char ch;
void *data;
};
The meaning of each field is as follows:
type
Specifies the type of the event. Actually it determines what happened.
There is a symbolic constant defined for each known event type.
chn
Specifies the channel to which the event applies.
For example, if the type of the event specifies that some data was received,
the chn field contains the number of the channel which has
received that data. There are many events that apply for all the channels. For
those events, this field is not significant.
x, y
The meaning of these fields depends on the event type. The y
field is usually not used, other than by some internal events.
ch
This field is used only by some internal events.
data
Depends on the type of the event. It usually points to some string data
or a char buffer.
All of the event types are described in the event
list.
6.2 Sending and receiving events
For sending events the following function is used:
int lp_emit_event(int chn, int type, int x, void *data);
This generates a new event using the specified values. Each argument
corresponds to one of the fields in the Event structure.
There are two modes for handling incoming events:
a) Reading each event on demand
This mode is started by the lp_event_handling_off() call.
In this mode, events are read explicitly using the function:
int get_event(Event *ev);
This function returns 0 when no event is available. When an
event is available, it returns 1 and fills the Event
structure with the received event data.
WARNING #1: The data field in your Event structure must
point to a dynamically allocated buffer. The size of the buffer is reallocated
automatically after receiving an event. When the data field is
set to NULL, a new buffer is allocated. This field must be initialized.
WARNING #2: In this mode, the application must read all events.
It is not a good idea to stop reading events, because the event
queue may overflow. LinPac will automatically kill the application when the
event queue exceeds some reasonable number of events.
b) Automatic event processing
This mode is started by the lp_event_handling_on() call. All
events are read automatically. Programmers can define their own function
that will be called automatically when an event occurs. When no such
function is defined, all events are discarded.
The event handling function must have following prototype:
void my_event_handler(Event *ev);
(The function name may be different.) After initializing the application,
the event handling function must be registered using the function:
lp_set_event_handler()
from the application library.
The following example is an application that prints the types of all events
received and stops when an EV_ABORT event is received. This event
can be generated using the :ABort command in LinPac.
#include <stdio.h>
#include <linpac/lpapp.h>
int aborted = 0;
//User event handling function. This function is called each time
//an event occurs
void my_event_handler(Event *ev)
{
printf("The event of type %i has been received\n", ev->type);
if (ev->type == EV_ABORT) aborted = 1;
}
int main()
{
if (lp_start_appl())
{
lp_event_handling_on(); //turn on automatic event handling
lp_set_event_handler(my_event_handler); //define own event handler
printf("Application started\n");
printf("Stop with the ':Abort' command\n");
do ; while(!aborted); //wait until application is aborted
printf("Application finished\n");
lp_end_appl();
}
else
{
printf("LinPac is not running\n");
return 1;
}
return 0;
}
This example contains "active waiting" (the do ; while(...)
construction). This is very ugly and inefficient. For this reason, the LinPac API offers an
alternative for waiting for events, namely the lp_wait_event() function.
Let's change the example to use this function:
#include <stdio.h>
#include <linpac/lpapp.h>
int main()
{
if (lp_start_appl())
{
lp_event_handling_on(); //turn on automatic event handling
printf("Application started\n");
printf("Stop with the ':Abort' command\n");
lp_wait_event(lp_channel(), EV_ABORT); //wait for the abort event
printf("Application finished\n");
lp_end_appl();
}
else
{
printf("LinPac is not running\n");
return 1;
}
return 0;
}
WARNING: Note that some system calls may be interrupted when
an event is received. An interrupted system call returns an error result (for
example the read() call returns -1), sets errno to
EAGAIN, and must be called again. To avoid this, use the interrupt-safe
versions of the system calls contained in this application library. (See
Chapter 7.3.1.)
6.3 Synchronization
An event generated by an application is sent to all modules and applications,
including the application that generated the event. When there is a
need to wait until the event is accepted by LinPac, the simplest way is
to wait until the event we have sent is received back.
For testing that all events were processed, there is an EV_VOID event.
It is not handled by any module. After sending all events, just generate
an EV_VOID event and wait until it returns. After that, you can be
assured that all previous events have been processed.
6.4 Shared variables and configuration
Each shared variable is denoted by its name (string) and channel number. Each
variable has a value represented by a string (char[]). Access to
these variables is provided by following functions:
The value of each variable is automatically synchronized with LinPac
and all running applications. The variables whose names start with "_"
are reserved for system use. These variables can be used for obtaining
system configuration and status but it may be potentialy dangerous to change
some of these variables.
NOTE: Many of the variables contain boolean values. Their
value is 1 when true, 0 otherwise.
Currently the following system variables are defined (in channel 0):
_remote
1 when remote commands are enabled
_cbell
1 when connect sound is enabled
_knax
1 when sound signal for each frame is enabled
_def_port
default port name
_unportname
port name for unproto frames
_unport
port number for unproto frames
_info_level
status-line level (0 to 2)
_no_name
default station name
_timezone
local timezone name
_swap_edit
1 when swapedit is on
_fixpath
1 when fixpath is on
_daemon
1 when linpac works as a daemon
_monitor
1 when monitor is enabled
_no_monitor
1 when monitor is disabled from command line
_listen
1 when accepting connections is enabled
_disable_spyd
1 when ax25spyd support is disabled from command line
_mon_bin
1 when monitor filters binary characters
_monparms
command line arguments for 'listen' program
_maxchn
maximal number of channels
_last_act
time of last user activity (same format as the time() system call).
These variables may be read using the lp_get_var() function defined
above. Furthermore there are two special functions defined for reading
these variables. These functions expect the name of the system variable
without the leading underscore.
char *lp_sconfig(const char *name)
Returns the value of the configuration variable as a string.
int lp_iconfig(const char *name)
Returns the value of the configuration variable as an integer.
The following system variables are defined for each channel:
_call
callsign for each channel
_cwit
connected with callsign
_cphy
physical connection to
_port
connected on which port
_state
connection status
There are also special functions for reading values of these variables:
int lp_chn_status(int chn)
Returns the status of a channel. The following status constants are defined:
ST_DISC
channel disconnected
ST_DISP
disconnect in progress
ST_TIME
disconnecting for timeout
ST_CONN
channel connected
ST_CONP
connecting in progress
char *lp_chn_call(int chn)
Returns channel callsign.
char *lp_chn_cwit(int chn)
Returns the callsign of connected station.
char *lp_chn_cphy(int chn)
Returns the callsign of physicaly connected station (the first connected station).
int lp_chn_port(int chn)
Returns the number of the port used for connection.
The last two functions enable changing the time of last users's response:
time_t lp_last_activity()
Returns the time of last activity of the user.
void lp_set_last_activity(time_t timeval)
Sets the last activity time.
6.5 Connection status
There are two special events reserved for obtaining the AX.25 connection
status. When an application wants to get the status of the connection
on a certain LinPac channel, it generates the EV_STAT_REQ event on this channel.
In response, LinPac generates the EV_STATUS event. The data field
of this event points to the ax25_status structure (see Chapter
7.2). When there is no active connection on the channel, no EV_STATUS
event is generated.
6.6 Event usage examples
The following examples show how to use events for controlling LinPac. The
complete list of events can be found in the file events.txt.
6.6.1 Connecting to a remote station
When initiating the connection, the first step is to check that the channel
is free (i.e. it is not in use for another connection). The status of a channel
can be checked using the lp_chn_status() function (see
Chapter 6.4).
The second step is emiting the EV_CONN_LOC event on the appropriate
channel. The data field of the event contains a C string with
the destination address in the form port:callsign [digi [digi ...]].
The last step is to wait until the connection is established. For this
the function lp_wait_connect() can be used. An example piece of
code follows:
int chn = lp_channel();
if (lp_chn_status(chn) == ST_DISC)
{
char addr[30];
strcpy(addr, "kiss:OK0PAB OK0NMA");
lp_emit_event(chn, EV_CONN_LOC, 0, addr);
lp_wait_connect(chn, "OK0PAB");
/* ... connection established ... */
}
6.6.2 Using LinPac commands in programs
Any application may run LinPac commands by emitting the EV_DO_COMMAND
event. For example, to download a message from a BBS using the getmsg
command following code can be used:
Another option is to use the EV_WANT_RESULT event. The usage
is similar to the previous example, but the x field of the event has
special meaning: as a response to this event, LinPac will generate an
EV_CMD_RESULT event
with the same x field and with the data field containing
the result of the command.
An example follows:
char cmd[30];
int id = 0;
Event *ev;
sprintf(cmd, "getmsg %i", message_number);
lp_emit_event(lp_channel(), EV_WANT_RESULT, 1234, cmd);
while (id != 1234) /* wait for the command result */
{
lp_wait_event(lp_channel(), EV_CMD_RESULT);
ev = lp_awaited_event();
id = ev->x;
}
printf("The result is: %s\n", (char *)ev.data);
typedef struct
{
char devname[8];
int state;
int vs, vr, va;
int t1, t2, t3, t1max, t2max, t3max;
int idle, idlemax;
int n2, n2max;
int rtt;
int window;
int paclen;
bool dama;
int sendq, recvq;
} ax25_status;
7.3 Functions
7.3.1 Uninterruptable versions of some system calls
The following functions work the same way as the original system calls, but
they are interrupt-safe. That is, they don't fail with errno == EAGAIN.
char *safe_fgets(char *s, int size, FILE *stream);
int safe_fgetc(FILE *stream);
7.3.2 Basic communication functions
int lp_start_appl()
Starts communication with LinPac. A non-zero return value means success; a
zero value means that LinPac cannot be contacted (probably because it's not
running).
int lp_get_event(Event *ev)
Read an event from the queue. A non-zero return value means a successful
read; a zero value means that the event queue is empty. The data
field of the event structure must be initialized before using this
function (to NULL or to some buffer). This function should not be used when
automatic event processing is used.
int lp_emit_event(int chn, int type, int x, void *data)
Generate a new event. The arguments correspond to the fields in the
event structure. The return value is always 0.
void lp_wait_event(int chn, int type)
Wait until an event with the same chn and type
values are received.
void lp_wait_init(int chn, int type)
The same as lp_wait_event() but returns immediately. Waiting
is provided by following function lp_wait_realize().
void lp_wait_realize()
Realizes waiting initialized by lp_wait_init(). All the events
that arrived since the last lp_wait_init() call are ignored.
lp_wait_realize() may exit immediately if the event has already
arrived.
Event *lp_awaited_event()
After return from a call to lp_wait_event() or
lp_wait_realize(), this function returns the event that stopped
the waiting.
Free the memory used by the data field of Event structure received
using lp_get_event().
void lp_clear_event_queue()
Remove all events from the event queue. This has no purpose when automatic
event processing is enabled.
void lp_end_appl()
Closes the connection to LinPac.
7.3.3 Automatic event handling functions
void lp_event_handling_on()
Enables automatic event handling. From this point onwards, each event
is automatically read from the queue, treated with an event handler function
(if defined) and then discarded.
void lp_event_handling_off()
Disables automatic event handling. Events must be read from the queue
using the lp_get_event() function.
void lp_set_event_handler(handler_type handler)
Defines the event handler function, a function with signature
void my_event_handler(Event *ev). The event handler is
called automatically each time an event is received, when automatic event
handling is enabled.
7.3.4 Environment functions
LinPac has its own environment for storing variables. Each application
can share and modify this environment using environment-related functions. Each
channel has its own environment. See Chapter 6.4 for a
detailed description and list of functions.
7.3.5 User functions
void lp_appl_result(const char *fmt, ...)
Set the final result of the application. This function generates an
EV_APP_RESULT event with the specified message string. The
argument format is the same as for printf().
void lp_statline(const char *fmt, ...)
Displays or changes the additional status line in the LinPac user
interface. Only one additional status line is displayed. This function
generates a EV_CHANGE_STLINE event with the x field
(line ID) containing the PID of the application. To display more than one
status line for the application, additional EV_CHANGE_STLINE
events must be generated manually.
void lp_remove_statline()
Removes the additional status line.
void lp_disable_screen()
Disables displaying data in the QSO window on application's channel.
The EV_DISABLE_SCREEN event is used to accomplish this.
void lp_enable_screen()
Enables displaying data in the QSO window. The EV_ENABLE_SCREEN
event is used to accomplish this.
void lp_wait_connect(int chn, const char *call)
Waits for a connection with the specified callsign on the specified
channel.
7.3.6 Tool functions
char *time_stamp(int utc)
Returns a pointer to a C string that contains the actual time. If
utc is 0, then local time is used; otherwise UTC time is used.
char *date_stamp(int utc)
Returns the date-string.
void replace_macros(int chn, char *s)
Replaces macro variables in the string (i.e. %xxx) with their
values. The %(command) macro is not replaced.
void get_port_name(int n)
Returns the name of the nth port in axports (starting from 0).
7.3.7 Application information functions
char *lp_version()
Returns the current LinPac version.
int lp_channel()
Returns the channel number on which the application was started. Returns
0 when the application was not started using LinPac.
int lp_app_remote()
Returns a non-zero value if the application was started using a remote
command in LinPac (i.e. the application is communicating with a remote user).
8 The shell interface
In addition to the C API described in the above chapters, LinPac also provides
a set of functions that allow programmers to create new LinPac commands using
bash shell scripts. While this set of functions is limited, it is sufficient
to enable quite sophisticated and complex commands to be added to LinPac
without requiring programming in C or C++.
8.1 Writing the script
The shell functions are all accessed through the lpapi command,
which has the following form:
lpapi <channel> [command] [arguments]
The specifics of the available commands are described in the following sections.
The channel on which the script application is running is made available to
the script as the $LPCHN shell environment variable. The use of
this variable is demonstrated below.
8.1.1 Ensuring that LinPac is running
The first step in any LinPac shell command should be to ensure that LinPac is
running, such that subsequent use of the shell interface can proceed. This is
accomplished by calling the API as follows:
lpapi 0
This command will exit with a 0 result code if LinPac is running. Any other
result code indicates that LinPac is not running, in which case the script
should most likely echo an error message to the user and exit. As usual, the
result code can be determined by examining the special $? value.
8.1.2 Accessing configuration and state
It is important that a shell script be able to determine the current status of
LinPac and retrieve configuration values. The API provides several functions
to enable this.
All of these functions return values that can be assigned to
a shell variable, and are used in the following manner (using "call" as an
example here):
MYVAR=`lpapi $LPCHN call`
The available functions are as follows:
call
Return the callsign for the specified channel.
cwit
Return the callsign of the station connected on the specified channel.
port
Return the port of the station connected on the specified channel.
state
Return current status of the specified channel (as a number).
pname <number>
Return the name of port with the specified number.
get <variable>
Return the value of specified variable on the specified channel.
8.1.3 Executing commands
Accomplishing real work with the shell interface will usually require calling
into LinPac to execute other LinPac commands. This is achieved using the
do command, which is functionally equivalent to generating the
EV_DO_COMMAND event from the C API.
The do command has the following form:
lpapi <channel> do <command> [arguments]
However, since do is a reserved word in Bash shell scripts,
it is necessary to use Bash's eval command to invoke it as a
LinPac function, as follows:
eval lpapi <channel> do "<command> [arguments]"
IMPORTANT: The do command is asynchronous.
That is, the shell command may return before the command issued to LinPac has
completed. A script will need to account for this in considering subsequent
actions.
8.1.4 Simple shell example
TBD
8.2 Creating the command
The steps to add the script to LinPac as a new command are essentially the same
as for an application written in C, described in Chapter 5.1
above. That is:
Copy the script to the $LINPACDIR/bin directory, making
sure that the permissions allow execution.
Add the new command to the file $LINPACDIR/bin/commands as
described in the User Manual.
Last update: 16 Feb 2020
linpac-0.28/doc/Makefile.in 0000664 0000764 0000764 00000044756 14006074450 012476 0000000 0000000 # Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
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@
subdir = doc
DIST_COMMON = $(dist_doc_DATA) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-dvi-recursive install-exec-recursive \
install-html-recursive install-info-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(docdir)"
DATA = $(dist_doc_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
distdir
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LINPACLINK = @LINPACLINK@
LIPO = @LIPO@
LISTEN = @LISTEN@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = czech charsets
dist_doc_DATA = manual.txt manual.html applguide.txt applguide.html events.txt \
objects.txt ioctl.txt
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu doc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
install-dist_docDATA: $(dist_doc_DATA)
@$(NORMAL_INSTALL)
test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
@list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
done
uninstall-dist_docDATA:
@$(NORMAL_UNINSTALL)
@list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(docdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(docdir)" && rm -f $$files
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
@fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile $(DATA)
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(docdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
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:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am: install-dist_docDATA
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-dist_docDATA
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
install-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am check check-am clean clean-generic clean-libtool \
ctags ctags-recursive distclean distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dist_docDATA install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
ps ps-am tags tags-recursive uninstall uninstall-am \
uninstall-dist_docDATA
# 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:
linpac-0.28/doc/applguide.txt 0000664 0000764 0000764 00000107266 14006074433 013141 0000000 0000000 LinPac - Packet Radio Terminal for Linux
--------------------------------------------------------------------------
Version 0.28
(c) Martin Cooper KD6YAM 2020
(c) David Ranch KI6ZHD (linpac@trinnet.net) 2002 - 2020
(c) 1998 - 2001 by Radek Burget OK2JBG
External Application Programming Guide
Contents
1 Introduction
2 What is an external program?
3 Basic concepts of the API
4 How applications communicate with LinPac
5 Using the application library
5.1 The simplest application
6 Application programming
6.1 Events
6.2 Sending and receiving events
6.3 Synchronization
6.4 Shared variables and configuration
6.5 Connection status
6.6 Event usage examples
6.6.1 Connecting to a remote station
6.6.2 Using LinPac commands in programs
7 The application library interface
7.1 Constants
7.2 Data structures
7.3 Functions
7.3.1 Uninterruptable versions of some system calls
7.3.2 Basic communication functions
7.3.3 Automatic event handling functions
7.3.4 Environment functions
7.3.5 User functions
7.3.6 Tool functions
7.3.7 Application information functions
8 The shell interface
8.1 Writing the script
8.1.1 Ensuring that LinPac is running
8.1.2 Accessing configuration and state
8.1.3 Executing commands
8.1.4 Simple shell example
8.2 Creating the command
1 Introduction
This guide is written for programmers who want to add some new functions
to LinPac. In the following text, basic knowledge of Linux programming is
assumed. Reading the LinPac User Manual before proceeding is also
recommended.
2 What is an external program?
An external program is a standard Linux application which uses LinPac to
communicate with remote stations. There are basically two types of LinPac
external programs:
*Â Standard Linux applications that use standard input and output
streams. These programs can be used without LinPac too. LinPac allows
redirection of the input stream (stdin) of the application and any of
the output streams (stdout, stderr) or both of them. LinPac can also
provide CR/LF conversions in these streams. These parameters are set
when adding the external program to LinPac - see Section 7, "Creating
new commands", in the User Manual.
*Â Applications written using LinPac's application interface. These
applications can share some information with LinPac, and they can
control almost all functions of LinPac.
No special knowledge of LinPac is needed for creating the first type of
programs, because no LinPac functions are used. The remainder of this
guide is dedicated to the second type of applications.
3 Basic concepts of the API
The LinPac application interface is based on events. Every action in
LinPac, such as pressing a key, receiving data, executing a command, etc.,
is represented by a data structure called an event, which describes
exactly what happened. LinPac's internal structure consists of separate
objects which communicate with each other using these events. Each object
provides its own functionality, and often generates events. For example,
the object Keyscan produces an event each time any key is pressed.
All the events generated by any object are put into the common event
queue. The LinPac kernel simply takes the events from the queue one by one
and sends them to all the objects (including the one that generated the
event). Thus each event generated by any part of LinPac is forwarded to
all of the objects. The reaction of each object fully depends on its
functionality, but of course it can include generation of other events.
The list of LinPac internal objects and their names can be found in the
file objects.txt.
An additional feature of the API is a shared variable environment. This is
a set of variables that is shared with LinPac; the values are
automatically synchronized with all the external programs. These variables
are accessed using special functions of the API as described below.
4 How applications communicate with LinPac
LinPac uses TCP/IP sockets for communication with external programs
(applications). The connection is always initiated by the application
after it starts. There are basically two ways that an application may be
started:
*Â The application is started by LinPac, through being associated with a
LinPac command. In this case LinPac registers the channel on which the
application was started and expects the connection attempt from the
application. After the application initializes and contacts LinPac, it
is provided with the working channel and whether it was started by a
remote or local user. LinPac may also redirect the input and output
streams of the application (depending upon LinPac settings).
*Â The application is started without using LinPac. In this case LinPac
assumes that the application runs on channel 0 and was started by the
local user. The input and output streams of the application are not
redirected.
In both cases, the start of an application causes the creation of a new
object in LinPac called an event gate. This object represents the
application within LinPac. Bearing in mind the previous chapter, this
means that the application is forwarded all of the events generated by any
LinPac object, and all of the events generated by the application are
forwarded to all LinPac objects.
NOTE: All of the communication via TCP/IP sockets is provided by the
LinPac application library. The user application should not attempt to
access the sockets directly.
5 Using the application library
During LinPac installation, the application library liblinpac is created
and installed by default to /usr/local/lib. The interface to this library
is contained in the file lpapp.h, which is installed by default to
/usr/local/include/linpac. The next chapter illustrates how to use the
library within a user application.
5.1 The simplest application
The following application example just tries to contact LinPac, and prints
the result.
--------------------------------------------------------------------------
#include
#include
#include
int main()
{
if (lp_start_appl())
{
printf("Application started\n");
sleep(10);
printf("Application finished\n");
lp_end_appl();
}
else
{
printf("LinPac is not running\n");
return 1;
}
return 0;
}
--------------------------------------------------------------------------
The function lp_start_appl() tries to contact LinPac and returns 1 in case
of success or 0 when a connection to LinPac cannot be made (probably
because it's not running). This function should precede the usage of any
other application library functions.
The function lp_end_appl() closes the connection to LinPac.
To compile this example, use:
$ gcc -o test1 test1.c -llinpac
This example just detects if LinPac is running, and it can be executed
directly from the shell. When running from the shell, no streams are
redirected to LinPac, and the application appears to run on channel 0 of
LinPac. This is useful for some applications that are used to control
LinPac from outside. However this is not a typical use case.
For most applications, it is better to copy the executable to the
$LINPACDIR/bin directory and then add it to the file
$LINPACDIR/bin/commands as described in the User Manual. After this, the
application can be executed as a LinPac command. In this scenario, the
streams are properly redirected and the application output is visible in
the LinPac QSO window. It is also possible to select the channel on which
to run the application.
NOTE: The LinPac application library (liblinpac) can be linked without
problems with both C and C++ code.
6 Application programming
6.1 Events
LinPac is completely driven by events. Each part of LinPac, including
applications, can generate events to inform other parts (internal modules
or applications) that something has happened. Each event is sent to all
LinPac components and applications. For example when some station connects
to some LinPac channel, the internal AX.25 interface generates an event
reporting that the station has connected and includes its callsign. All
components and applications now know who has connected, and they can take
some actions. For example, the output window prints information about the
connection, the macro processor executes the cinit.mac macro, and so on.
Each application can handle all of the events too, and can generate events
which are handled by other components.
An event is represented by the following structure:
struct Event
{
int type;
int chn;
int x,y;
char ch;
void *data;
};
The meaning of each field is as follows:
type
Specifies the type of the event. Actually it determines what
happened. There is a symbolic constant defined for each known
event type.
chn
Specifies the channel to which the event applies. For example, if
the type of the event specifies that some data was received, the
chn field contains the number of the channel which has received
that data. There are many events that apply for all the channels.
For those events, this field is not significant.
x, y
The meaning of these fields depends on the event type. The y field
is usually not used, other than by some internal events.
ch
This field is used only by some internal events.
data
Depends on the type of the event. It usually points to some string
data or a char buffer.
All of the event types are described in the event list.
6.2 Sending and receiving events
For sending events the following function is used:
int lp_emit_event(int chn, int type, int x, void *data);
This generates a new event using the specified values. Each argument
corresponds to one of the fields in the Event structure.
There are two modes for handling incoming events:
a) Reading each event on demand
This mode is started by the lp_event_handling_off() call. In this mode,
events are read explicitly using the function:
int get_event(Event *ev);
This function returns 0 when no event is available. When an event is
available, it returns 1 and fills the Event structure with the received
event data.
WARNING #1: The data field in your Event structure must point to a
dynamically allocated buffer. The size of the buffer is reallocated
automatically after receiving an event. When the data field is set to
NULL, a new buffer is allocated. This field must be initialized.
WARNING #2: In this mode, the application must read all events. It is not
a good idea to stop reading events, because the event queue may overflow.
LinPac will automatically kill the application when the event queue
exceeds some reasonable number of events.
b) Automatic event processing
This mode is started by the lp_event_handling_on() call. All events are
read automatically. Programmers can define their own function that will be
called automatically when an event occurs. When no such function is
defined, all events are discarded.
The event handling function must have following prototype:
void my_event_handler(Event *ev);
(The function name may be different.) After initializing the application,
the event handling function must be registered using the function:
lp_set_event_handler()
from the application library.
The following example is an application that prints the types of all
events received and stops when an EV_ABORT event is received. This event
can be generated using the :ABort command in LinPac.
--------------------------------------------------------------------------
#include
#include
int aborted = 0;
//User event handling function. This function is called each time
//an event occurs
void my_event_handler(Event *ev)
{
printf("The event of type %i has been received\n", ev->type);
if (ev->type == EV_ABORT) aborted = 1;
}
int main()
{
if (lp_start_appl())
{
lp_event_handling_on(); //turn on automatic event handling
lp_set_event_handler(my_event_handler); //define own event handler
printf("Application started\n");
printf("Stop with the ':Abort' command\n");
do ; while(!aborted); //wait until application is aborted
printf("Application finished\n");
lp_end_appl();
}
else
{
printf("LinPac is not running\n");
return 1;
}
return 0;
}
--------------------------------------------------------------------------
This example contains "active waiting" (the do ; while(...) construction).
This is very ugly and inefficient. For this reason, the LinPac API offers
an alternative for waiting for events, namely the lp_wait_event()
function. Let's change the example to use this function:
--------------------------------------------------------------------------
#include
#include
int main()
{
if (lp_start_appl())
{
lp_event_handling_on(); //turn on automatic event handling
printf("Application started\n");
printf("Stop with the ':Abort' command\n");
lp_wait_event(lp_channel(), EV_ABORT); //wait for the abort event
printf("Application finished\n");
lp_end_appl();
}
else
{
printf("LinPac is not running\n");
return 1;
}
return 0;
}
--------------------------------------------------------------------------
WARNING: Note that some system calls may be interrupted when an event is
received. An interrupted system call returns an error result (for example
the read() call returns -1), sets errno to EAGAIN, and must be called
again. To avoid this, use the interrupt-safe versions of the system calls
contained in this application library. (See Chapter 7.3.1.)
6.3 Synchronization
An event generated by an application is sent to all modules and
applications, including the application that generated the event. When
there is a need to wait until the event is accepted by LinPac, the
simplest way is to wait until the event we have sent is received back.
For testing that all events were processed, there is an EV_VOID event. It
is not handled by any module. After sending all events, just generate an
EV_VOID event and wait until it returns. After that, you can be assured
that all previous events have been processed.
6.4 Shared variables and configuration
Each shared variable is denoted by its name (string) and channel number.
Each variable has a value represented by a string (char[]). Access to
these variables is provided by following functions:
void lp_set_var(int chn, const char *name, const char *value)
Changes the value of the variable. If the variable doesn't exist,
it is created.
char *lp_get_var(int chn, const char *name)
Reads the value of the variable. Returns NULL if the variable
doesn't exist.
void lp_del_var(int chn, const char *name)
Deletes the variable.
void lp_clear_var_names(int chn, const char *prefix)
Deletes all variables with the specified name.
The value of each variable is automatically synchronized with LinPac and
all running applications. The variables whose names start with "_" are
reserved for system use. These variables can be used for obtaining system
configuration and status but it may be potentialy dangerous to change some
of these variables.
NOTE: Many of the variables contain boolean values. Their value is 1 when
true, 0 otherwise.
Currently the following system variables are defined (in channel 0):
_remote
1 when remote commands are enabled
_cbell
1 when connect sound is enabled
_knax
1 when sound signal for each frame is enabled
_def_port
default port name
_unportname
port name for unproto frames
_unport
port number for unproto frames
_info_level
status-line level (0 to 2)
_no_name
default station name
_timezone
local timezone name
_swap_edit
1 when swapedit is on
_fixpath
1 when fixpath is on
_daemon
1 when linpac works as a daemon
_monitor
1 when monitor is enabled
_no_monitor
1 when monitor is disabled from command line
_listen
1 when accepting connections is enabled
_disable_spyd
1 when ax25spyd support is disabled from command line
_mon_bin
1 when monitor filters binary characters
_monparms
command line arguments for 'listen' program
_maxchn
maximal number of channels
_last_act
time of last user activity (same format as the time() system
call).
These variables may be read using the lp_get_var() function defined above.
Furthermore there are two special functions defined for reading these
variables. These functions expect the name of the system variable without
the leading underscore.
char *lp_sconfig(const char *name)
Returns the value of the configuration variable as a string.
int lp_iconfig(const char *name)
Returns the value of the configuration variable as an integer.
The following system variables are defined for each channel:
_call
callsign for each channel
_cwit
connected with callsign
_cphy
physical connection to
_port
connected on which port
_state
connection status
There are also special functions for reading values of these variables:
int lp_chn_status(int chn)
Returns the status of a channel. The following status constants
are defined:
ST_DISC
channel disconnected
ST_DISP
disconnect in progress
ST_TIME
disconnecting for timeout
ST_CONN
channel connected
ST_CONP
connecting in progress
char *lp_chn_call(int chn)
Returns channel callsign.
char *lp_chn_cwit(int chn)
Returns the callsign of connected station.
char *lp_chn_cphy(int chn)
Returns the callsign of physicaly connected station (the first
connected station).
int lp_chn_port(int chn)
Returns the number of the port used for connection.
The last two functions enable changing the time of last users's response:
time_t lp_last_activity()
Returns the time of last activity of the user.
void lp_set_last_activity(time_t timeval)
Sets the last activity time.
6.5 Connection status
There are two special events reserved for obtaining the AX.25 connection
status. When an application wants to get the status of the connection on a
certain LinPac channel, it generates the EV_STAT_REQ event on this
channel. In response, LinPac generates the EV_STATUS event. The data field
of this event points to the ax25_status structure (see Chapter 7.2). When
there is no active connection on the channel, no EV_STATUS event is
generated.
6.6 Event usage examples
The following examples show how to use events for controlling LinPac. The
complete list of events can be found in the file events.txt.
6.6.1 Connecting to a remote station
When initiating the connection, the first step is to check that the
channel is free (i.e. it is not in use for another connection). The status
of a channel can be checked using the lp_chn_status() function (see
Chapter 6.4).
The second step is emiting the EV_CONN_LOC event on the appropriate
channel. The data field of the event contains a C string with the
destination address in the form port:callsign [digi [digi ...]].
The last step is to wait until the connection is established. For this the
function lp_wait_connect() can be used. An example piece of code follows:
--------------------------------------------------------------------------
int chn = lp_channel();
if (lp_chn_status(chn) == ST_DISC)
{
char addr[30];
strcpy(addr, "kiss:OK0PAB OK0NMA");
lp_emit_event(chn, EV_CONN_LOC, 0, addr);
lp_wait_connect(chn, "OK0PAB");
/* ... connection established ... */
}
--------------------------------------------------------------------------
6.6.2 Using LinPac commands in programs
Any application may run LinPac commands by emitting the EV_DO_COMMAND
event. For example, to download a message from a BBS using the getmsg
command following code can be used:
--------------------------------------------------------------------------
char cmd[30];
sprintf(cmd, "getmsg %i", message_number);
lp_emit_event(lp_channel(), EV_DO_COMMAND, 0, cmd);
--------------------------------------------------------------------------
Another option is to use the EV_WANT_RESULT event. The usage is similar to
the previous example, but the x field of the event has special meaning: as
a response to this event, LinPac will generate an EV_CMD_RESULT event with
the same x field and with the data field containing the result of the
command.
An example follows:
--------------------------------------------------------------------------
char cmd[30];
int id = 0;
Event *ev;
sprintf(cmd, "getmsg %i", message_number);
lp_emit_event(lp_channel(), EV_WANT_RESULT, 1234, cmd);
while (id != 1234) /* wait for the command result */
{
lp_wait_event(lp_channel(), EV_CMD_RESULT);
ev = lp_awaited_event();
id = ev->x;
}
printf("The result is: %s\n", (char *)ev.data);
--------------------------------------------------------------------------
7 The application library interface
7.1 Constants
LPAPP_VERSION
the version of LinPac that the library came with
ST_xxxx
connection status constants (see Chapter 6.4)
7.2 Data structures
struct ax25_status
contains the AX.25 connection status:
typedef struct
{
char devname[8];
int state;
int vs, vr, va;
int t1, t2, t3, t1max, t2max, t3max;
int idle, idlemax;
int n2, n2max;
int rtt;
int window;
int paclen;
bool dama;
int sendq, recvq;
} ax25_status;
7.3 Functions
7.3.1 Uninterruptable versions of some system calls
The following functions work the same way as the original system calls,
but they are interrupt-safe. That is, they don't fail with errno ==
EAGAIN.
size_t safe_read(int fd, void *buf, size_t count);
size_t safe_write(int fd, const void *buf, size_t count);
char *safe_fgets(char *s, int size, FILE *stream);
int safe_fgetc(FILE *stream);
7.3.2 Basic communication functions
int lp_start_appl()
Starts communication with LinPac. A non-zero return value means
success; a zero value means that LinPac cannot be contacted
(probably because it's not running).
int lp_get_event(Event *ev)
Read an event from the queue. A non-zero return value means a
successful read; a zero value means that the event queue is empty.
The data field of the event structure must be initialized before
using this function (to NULL or to some buffer). This function
should not be used when automatic event processing is used.
int lp_emit_event(int chn, int type, int x, void *data)
Generate a new event. The arguments correspond to the fields in
the event structure. The return value is always 0.
void lp_wait_event(int chn, int type)
Wait until an event with the same chn and type values are
received.
void lp_wait_init(int chn, int type)
The same as lp_wait_event() but returns immediately. Waiting is
provided by following function lp_wait_realize().
void lp_wait_realize()
Realizes waiting initialized by lp_wait_init(). All the events
that arrived since the last lp_wait_init() call are ignored.
lp_wait_realize() may exit immediately if the event has already
arrived.
Event *lp_awaited_event()
After return from a call to lp_wait_event() or lp_wait_realize(),
this function returns the event that stopped the waiting.
Event *lp_copy_event(Event *dest, const Event *src)
Copy the event structure (using a deep copy).
void lp_discard_event(Event *ev)
Free the memory used by the data field of Event structure received
using lp_get_event().
void lp_clear_event_queue()
Remove all events from the event queue. This has no purpose when
automatic event processing is enabled.
void lp_end_appl()
Closes the connection to LinPac.
7.3.3 Automatic event handling functions
void lp_event_handling_on()
Enables automatic event handling. From this point onwards, each
event is automatically read from the queue, treated with an event
handler function (if defined) and then discarded.
void lp_event_handling_off()
Disables automatic event handling. Events must be read from the
queue using the lp_get_event() function.
void lp_set_event_handler(handler_type handler)
Defines the event handler function, a function with signature void
my_event_handler(Event *ev). The event handler is called
automatically each time an event is received, when automatic event
handling is enabled.
7.3.4 Environment functions
LinPac has its own environment for storing variables. Each application can
share and modify this environment using environment-related functions.
Each channel has its own environment. See Chapter 6.4 for a detailed
description and list of functions.
7.3.5 User functions
void lp_appl_result(const char *fmt, ...)
Set the final result of the application. This function generates
an EV_APP_RESULT event with the specified message string. The
argument format is the same as for printf().
void lp_statline(const char *fmt, ...)
Displays or changes the additional status line in the LinPac user
interface. Only one additional status line is displayed. This
function generates a EV_CHANGE_STLINE event with the x field (line
ID) containing the PID of the application. To display more than
one status line for the application, additional EV_CHANGE_STLINE
events must be generated manually.
void lp_remove_statline()
Removes the additional status line.
void lp_disable_screen()
Disables displaying data in the QSO window on application's
channel. The EV_DISABLE_SCREEN event is used to accomplish this.
void lp_enable_screen()
Enables displaying data in the QSO window. The EV_ENABLE_SCREEN
event is used to accomplish this.
void lp_wait_connect(int chn, const char *call)
Waits for a connection with the specified callsign on the
specified channel.
7.3.6 Tool functions
char *time_stamp(int utc)
Returns a pointer to a C string that contains the actual time. If
utc is 0, then local time is used; otherwise UTC time is used.
char *date_stamp(int utc)
Returns the date-string.
void replace_macros(int chn, char *s)
Replaces macro variables in the string (i.e. %xxx) with their
values. The %(command) macro is not replaced.
void get_port_name(int n)
Returns the name of the nth port in axports (starting from 0).
7.3.7 Application information functions
char *lp_version()
Returns the current LinPac version.
int lp_channel()
Returns the channel number on which the application was started.
Returns 0 when the application was not started using LinPac.
int lp_app_remote()
Returns a non-zero value if the application was started using a
remote command in LinPac (i.e. the application is communicating
with a remote user).
8 The shell interface
In addition to the C API described in the above chapters, LinPac also
provides a set of functions that allow programmers to create new LinPac
commands using bash shell scripts. While this set of functions is limited,
it is sufficient to enable quite sophisticated and complex commands to be
added to LinPac without requiring programming in C or C++.
8.1 Writing the script
The shell functions are all accessed through the lpapi command, which has
the following form:
lpapi [command] [arguments]
The specifics of the available commands are described in the following
sections.
The channel on which the script application is running is made available
to the script as the $LPCHN shell environment variable. The use of this
variable is demonstrated below.
8.1.1 Ensuring that LinPac is running
The first step in any LinPac shell command should be to ensure that LinPac
is running, such that subsequent use of the shell interface can proceed.
This is accomplished by calling the API as follows:
lpapi 0
This command will exit with a 0 result code if LinPac is running. Any
other result code indicates that LinPac is not running, in which case the
script should most likely echo an error message to the user and exit. As
usual, the result code can be determined by examining the special $?
value.
8.1.2 Accessing configuration and state
It is important that a shell script be able to determine the current
status of LinPac and retrieve configuration values. The API provides
several functions to enable this.
All of these functions return values that can be assigned to a shell
variable, and are used in the following manner (using "call" as an example
here):
MYVAR=`lpapi $LPCHN call`
The available functions are as follows:
call
Return the callsign for the specified channel.
cwit
Return the callsign of the station connected on the specified
channel.
port
Return the port of the station connected on the specified channel.
state
Return current status of the specified channel (as a number).
pname
Return the name of port with the specified number.
get
Return the value of specified variable on the specified channel.
8.1.3 Executing commands
Accomplishing real work with the shell interface will usually require
calling into LinPac to execute other LinPac commands. This is achieved
using the do command, which is functionally equivalent to generating the
EV_DO_COMMAND event from the C API.
The do command has the following form:
lpapi do [arguments]
However, since do is a reserved word in Bash shell scripts, it is
necessary to use Bash's eval command to invoke it as a LinPac function, as
follows:
eval lpapi do " [arguments]"
IMPORTANT: The do command is asynchronous. That is, the shell command may
return before the command issued to LinPac has completed. A script will
need to account for this in considering subsequent actions.
8.1.4 Simple shell example
TBD
8.2 Creating the command
The steps to add the script to LinPac as a new command are essentially the
same as for an application written in C, described in Chapter 5.1 above.
That is:
 1. Copy the script to the $LINPACDIR/bin directory, making sure that the
permissions allow execution.
 2. Add the new command to the file $LINPACDIR/bin/commands as described
in the User Manual.
--------------------------------------------------------------------------
Last update: 16 Feb 2020
References
Visible links
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS3
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS5
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS5_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_3
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_5
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_6
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_6_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_6_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_3
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_5
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_6
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_7
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8_1_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8_1_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8_1_3
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8_1_4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS8_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/manual.html#POS7
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/objects.txt
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/manual.html
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/events.txt
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_3_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS7_2
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/events.txt
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS6_4
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/applguide.html#POS5_1
. file:///home/archive/Linpac/BitBucket-Git/linpac/doc/manual.html
linpac-0.28/doc/manual.txt 0000664 0000764 0000764 00000164327 14006074433 012445 0000000 0000000 LinPac - Packet Radio Terminal for Linux
--------------------------------------------------------------------------
Version 0.28
(c) 2020 - 1998 by David Ranch KI6ZHD
User manual
Index
1 [1]What is LinPac
2 [2]First configuration
3 [3]LinPac controls
3.1 [4]Keyboard
3.2 [5]Entering commands
3.3 [6]Initiating a connection
3.4 [7]Receiving and sending files
3.5 [8]Remote commands
3.6 [9]Character encoding
3.7 [10]Huffman compression
4 [11]Variables
4.1 [12]Special variables
5 [13]Station database
5.1 [14]The station.data file format
5.2 [15]The 'Name' command
5.3 [16]Using the database
6 [17]About macros
6.1 [18]Creating macros
6.2 [19]Commands used in macros
6.3 [20]Special system macros
7 [21]Creating new commands
8 [22]Standard applications
8.1 [23]File transfer protocols
8.2 [24]Automatic password generation
8.2.1 [25]Login passwords
8.2.2 [26]Sysop and general use passwords
8.3 [27]Utilities for mail exchange
8.4 [28]Mail client
8.5 [29]Logbook
9 [30]Command line options
10 [31]Copying
Appendix A: [32]List of LinPac commands
Appendix B: [33]Linpac FAQ / Questions and Answers / Getting more help
Appendix C: [34]Errata
--------------------------------------------------------------------------
1 What is LinPac
LinPac is a packet radio terminal for Linux that allows wide
configurability and easy addition of new functions and special functions
needed by the user. The aim is to minimize the amount of 'hard coded'
functions and create a complete set of applications that can be easy
expanded and/or completely reconfigured.
All functions described in this manual match the standard configuration
that comes with the distribution package.
2 First configuration
When linpac is started for the first time on your computer, it
automaticaly creates the directory called LinPac in the running user's
home directory. This directory will contain the user's personal LinPac
configuration settings. After creating this directory, LinPac asks for
basic callsign, port and other information and prepares a useable
configuration for you. An example setup dialog is as shown, where we are
using the bogus call "n0call" logging into the local home BBS "n0ary-1":
$ linpac
Hello dear user. You seem to run LinPac for the first time.
LinPac has to create a directory in your home directory for storing
your personal configuration.
For creating your personal configuration please answer following questions:
Your callsign:
n0call
Enter your home BBS callsign with SSID :
n0ary-1
Enter the name of port to connect N0ARY-1
d710
Enter the digipeaters used to connect N0ARY-1 or press enter
when no digipeaters are used:
Enter the full hierarchical address of N0ARY-1
(e.g. #MOR.CZE.EU)
#NCA.CA.USA.NOAM
Thank you, N0CALL
Please wait a moment for creating your personal configuration
Installation done.
Press ENTER to run LinPac
The above information is then stored in the $HOME/LinPac/macro/init.mac
file as various 'functions'. These functions are based on the very simple
interpreted language (actually it's not a language but something like the
batch files in DOS). In the LinPac/macro directory are all the scripts
written in this language. The init.mac macro is loaded at start of loading
Linpac and contains the commands to setup the callsigns and other
settings. You can modify this file to change the initial configuration of
LinPac. Other macros can be run in LinPac as desired or required. The
simplest case of a macro is a normal text file that is just printed to the
screen (or sent to the remote peer) when executed. The language is
described in [35]chapter 6.
You may also want to review or change following macro files:
*Â info.mac - contains information about your system
*Â ctext.mac - executed when the peer connects and should contain the
greeting text
*Â quit.mac - called when user enters the Quit command (end of
connection) and should print some farewell text and disconnect
After this you should be able to make your first connection.
3 LinPac controls
After automatically running the LinPac setup routine, the main screen
should appear. If you see a segmentation fault, please see [36]Linux AX.25
issues with long predictable network interface names for a work around.
Moving on, in Linpac's main interface in the standard configuraion, the
screen is divided into five parts (described from the top of the screen to
the bottom):
*Â QSO window: this window contains the text that came from the peer and
also the sent text and some special messages (different text colours).
*Â Status line: displays your callsign, current time and some information
about the current connection.
*Â Editor: allows you to enter the text you want to send to the peer or
the commands you want to execute
*Â Channel list: displays the list of channels with the callsign of
connected users. The currently selected channel is highlighted.
*Â Monitor : displays the traffic on your radio ports
LinPac is mostly driven by commands. The commands are entered using the
editor and must start with a colon (':') in the first column. Lines that
don't begin with a colon are sent to the peer, if connected.
LinPac allows up to eight connections to be made simultaneously. For each
connection one channel is used. You can switch between channels by
pressing the F1 - F8 keys. Each has its own QSO window, status line and
editor. The channel list and the monitor are common across all the
channels.
There is a special channel invoked by pressing F10. This channel has no
QSO window and doesn't allow making a connection. The text written is sent
out immediately using UI frames (beacon).
3.1 Keyboard
The following list contains the important shortcuts:
Global
F1 - F8 : switch to channel 1 - 8
F10 : switch to monitor
Alt-X : end of LinPac
QSO Window
PgUp, PgDn, ctrl-R, ctrl-V : scroll one page up / down
ctrl-E, ctrl-X : scroll one line up / down
ctrl-B : skip to end of buffer
Editor
Cursor keys, Home, End, Backspace, Del : text editing
ctrl-Y : delete current line
Enter : send current line
Some applications (e.g. mailer) can use the whole screen. Each channel can
run only one such application at a time. It's possible to switch to this
application using Alt- (e.g. Alt-5) and switch back to
terminal using F1 - F10.
3.2 Entering commands
Each command is invoked using its name. Some commands can be abbreviated.
In this manual the mandatory part is always written in upper case. The
remainder of the command name is optional. Some commands require some
extra arguments. The arguments are written after the command and are
separated by one or more spaces. If you want to enter an argument
containing more than one word, that argument must be entered in quotation
marks.
Examples:
:color red blue - calls the 'color' command with two arguments - 'red'
and 'blue'
:color 'light red' or
:color "light red" - calls the 'color' command with one argument 'light
red'
Most of the commands work on the currently selected channel. If you want
to execute the command on some other channel, you can enter the number of
the channel this way. For example, to make an OUTGOING connection to
destination OK0PAB on Linpac channel 5:
:connect@5 OK0PAB
In this case the 'connect' command is executed on channel 5.
The complete list of commands with descriptions is available in Appendix
A.
3.3 Initiating a connection
To initiate a connection the :Connect command is used. Just switch to the
channel you want to use by pressing F1 - F8 and enter the following
command:
:connect CALLSIGN
Replace the CALLSIGN with the real callsign of the station you want to
connect. The command can be abbreviated to the first letter only. Example:
:c OK0PAB
This command will initiate the connecting sequence to OK0PAB. To close the
connection, you can use the :Disconnect command by entering
:d
When your system has multiple radio ports, you can specify its name before
the callsign like this:
:c 2:OK0PAB
This command will try to connect OK0PAB via port 2. When no port name is
specified, the default one is used. Initially the default port is the
first port in /etc/axports (your system AX.25 port configuration file). If
you want to change the default port, just use the command :port.
:port 2
This will change the default port name to '2'. In some cases it is useful
to set another default port for some selected channels. For this the
variable CHN_PORT can be used (see [37]chapter 4). When set, the content
of this variable overrides the default port selection for the particular
channel. For example, when you set the variable for channel 4 using
:set CHN_PORT@4 1
the port '1' will be used as the default one for the channel 4. For other
channels, the previously set default port will be used.
3.4 Receiving and sending files
The standard distribution can receive files using plain text or binary
transfer and using file transfer protocols YAPP and Autobin. LinPac will
automaticaly start to receive the file when the peer begins to send using
the YAPP or Autobin protocols. The 7+ files are automaticaly saved too.
When you want to save the incoming text you have to use the command
:Write
The incoming text will be saved until you stop the saving using
:Write off
For receiving a plain binary file, the corresponding command :WBin can be
used. This way of transferring binary files is not recommended; use the
autobin or yapp protocol instead.
The following commands are available for sending files:
:rprg - sends the file using the Autobin protocol
:yput - sends the file using the YAPP protocol
:rbin - sends the binary file (no protocol - not recommended)
:read - semds the text file
3.5 Remote commands
LinPac allows the remote user to enter commands. For remote control, all
LinPac commands are available but there can be (and should be) some
restrictions for each user.
The remote command must start with the // sequence. For example if some
connected user sends you the text '//info' your terminal will send back
the station information.
The remote commands can be disabled using the command :remote off and
enabled by :remote on. You can also specify that only some commands be
available for remote users. The default list of available remote commands
is defined in the init.mac file (the DEF_RCMD line). It is also possible
to enable various commands for each user. This is described in [38]chapter
5.
3.6 Character encoding
Some countries use different national character encodings for some
historical reasons. A user who has his Linux console configured for
example for some of the standard ISO encodings may be incompatible with
another one using a traditional encoding. To solve this LinPac allows the
translation of the input and output of each channel using a translation
table. The translation tables are stored in files *.ctt in the LinPac home
directory.
All known encodings must be defined in the file called encodings in the
LinPac home directory. This file contains a single line for each encoding
that specifies its alias (name which will identify the encoding in
LinPac), encoding name (an official name such as iso-8859-1) and
optionally the name of the translation table file to be used (without the
extension .ctt).
Note that LinPac does not support multi-byte encodings such as UTF-8 or
other Unicode encodings.
The current encoding can be switched using the :TRanslate command
separately for each channel. To specify the default encoding for each user
you can add the line
ENC=
to the appropriate record in the station database. (The station database
is described in [39]chapter 5.) When no encoding is specified for the
user, the default one is used. The default encoding alias is stored in the
DEF_ENC@0 variable which is set in the macro init.mac.
When the conversion table is not specified in the encodings file LinPac
only changes the name of currently used encoding but doesn't provide any
conversion. However some applications (such as QLinPac which works in
unicode) are able to do their own conversions.
3.7 Huffman compression
Some packet radio terminals and BBS software allows the compression of
transferred text. When switched on, the sender does the compression of all
data before sending them to the other station and the recipient has to
decompress the data after receiving them. This makes the communication
more reliable and reduces the load of the radio link.
The line compression in LinPac is activated using the :comp command. The
compression is switched on using :comp on and switched off using :comp
off. To ensure that the compression is activated or deactivated on both
ends of the link simultaneously LinPac sends the remote command :comp 1 or
:comp 0 to the other station automatically. The arguments 1 and 0 have the
same effect as on and off, but they don't cause sending any command to the
other station.
In the case in which the remote system doesn't support the :comp command
it's necessary to switch on the compression on the remote system manually
and then use the:comp 1 command in LinPac.
4 Variables
Each channel has its own set of variables. Some of the variables are used
to store the configuration data. The user can create and remove variables
and change the values of existing variables using following commands:
:set - sets the value of the variable. If the
variable doesn't exist, a new one is created.
:get - prints the value of the variable
:unset - removes the variable
Some examples:
:set NAME John
:set WHOLE_NAME 'John Big'
:get NAME
:unset NAME
The name of the variable can contain the specification of the channel. For
example the variable NAME@5 is the variable 'NAME' defined on channel 5.
When LinPac finds the character '%' followed by the name of variable, it
automatically replaces this text with the value of the variable.
Considering the previous example, the text %NAME will be replaced with
John.
4.1 Special variables
There are some special internal variables that don't allow changing their
value. Their value is set and changed directly by LinPac and these
variables can be used to add some actual information to the text. The list
follows:
%V - LinPac version (e.g. 0.26)
%C - The callsign of connected station
%N - The name of connected station (when known), else replaced by the
contents of %U macro
%Y- Channel callsign (mycall)
%K- Current channel number
%T - Current time
%D - Current date
%B - Audible bell
%Z - Current time zone
%U - The text used when the name is unknown. This can contain other
macros (typicaly %C).
%P- The port number
%M- The number of connected users
%A- The time since the last operator activity
%_- End of line (CR)
%<- Contents of the last line received, this is cleared by reading
%#number - Replaced by a character with an ASCII value (e.g.
%#27 means ESC)
%(command) - Replaced by the command result.
%[expression] - Replaced by the result of mathematical expression
Variables for use in macros only:
%R - the number of macro arguments (up to 9)
%0 - the name of the macro
%1 - %9 - macro arguments
For example try to write following text in the editor and press enter:
The time is %T and the date is %D.
5 Station database
The station database holds various information about known stations. All
the information is stored in the 'station.data' file and can be changed
using the normal text editor or using the LinPac :Name command.
5.1 The station.data file format
The information about each station is written in a paragraph starting with
the station callsign in square brackets. Each line in the paragraph
contains one definition like:
=
A typical station information paragraph might look like this:
[OK0NMA]
NAME=PC/FlexNet Brno
TYPE=FLEXNET
LOC=JN89HE
QRG=144.8125 MHz
SYSNUM=85946
There are no mandatory items; the user can add various items depending on
what information he wants to store. The current LinPac distribution uses
following item names for standard information:
NAME - Text information about the station, or the operator's name.
LinPac shows this information when connected to that station. LOC - QRA
locator of the station. Shown after connect too.
TYPE - The type of the station. For standard stations the types FLEXNET,
THENET, FBB, BAYBOX, DIEBOX, TNOS, JNOS, DXC and TERM for user terminals
are recomended, but you can add any other type.
LANG - The language to communicate with the station. This is currently
supported by macros only. When this item is set, LinPac will try to find
the macro in the directory macro//.
NICKNAME - The nickname of the operator.
The standard LinPac configuration also uses these item names:
TERM - What type of terminal is used. If 'ansi' is set, LinPac switches
to the ansi-color mode after connecting this station.
ENC - The character encoding. Used to automaticaly switch to the i/o
character conversion.
RCMD - The list of enabled remote commands for this station.
QRG - The user frequency. Used by the logbook.
SYSNUM and PWD - Sysop password for the station. See chapter [40]8.2 for
more information.
5.2 The 'Name' command
The :Name command is used to modify the station database. Running the
command without arguments results printing the name of currently connected
station. Arguments can be used to modify the data:
- modify the NAME item
-l - modify the LOC item
-t - TYPE
-L - LANG
-n - NICKNAME
-s = - modify other item
The command 'Name -i' prints all information about the station. When you
need to change the information about a station other than the connected
station, add the argument -c .
Examples:
:Name David
:Name -c KI6ZHD -l CM97ai David
:Name -i
5.3 Using the database
After any connection is established, LinPac reads the information about
the connected station from the database and creates the set of variables
with names STN_ containing the values of the items.
These variables can be used in macros as described below.
6 About macros
6.1 Creating macros
A macro is a LinPac command that is created using the macro language, and
uses other LinPac commands to perform some action. A macro can be defined
by creating the file macro/.mac. It's possible to define an
abbreviated form of the command; this is described in [41]chapter 7. There
are two ways to define a macro:
a) Text macros
This way is suitable for commands which are intended to produce a larger
text output (for example station information). When executing this macro,
each line that doesn't start with ':' is printed (sent out). All commands
must start with the colon. This is suitable for modifying the text output
using the IF ~ ELSE ~ ENDIF commands or for including some other commands.
b) Command macros
A command macro must start with the line
:MACRO
Each line of a command macro is interpreted as a command (doesn't start
with the colon and doesn't need to start at the begining of line). Text
output is provided by the 'echo' command. This way is more synoptical and
allows including comments that must start with the sequence ';;' and end
at the end of the line.
A macro is called with its name. When the first arguments starts with the
'@' symbol the macro is executed from the specified label. For example the
command :convers @SEND will execute the macro 'convers.mac' from the label
'SEND' (see next chapter to see how to define the label).
6.2 Commands used in macros
A macro can contain all LinPac and user defined commands. There are also
some special commands that can be used in macros only:
MACRO [name]
Start of the command script definition (see previous section).
LABEL
Creates a label with specified name. In the command scripts the notation
: can be used.
GOTO
Jump to specified label.
IF ~ ELSE ~ ENDIF
Conditional commands. There are two ways to specify a condition:
*Â normal notation (for more than one command) Â
IF
.
.
(commands to be executed when the condition is true)
.
.
ELSE
.
.
(commands to be executed when the condition is false)
.
.
ENDIF
The ELSE part is not necessary - the IF ~ ENDIF notation is possible.
Â
*Â abbreviated notation (for one conditional command)
IF () command
The parentheses are necessary in this case.
The following example shows how to use conditions and how to use the data
from the station database. We want to create a macro that will greet the
operator of the connected station with his nickname or with his name, if
the nickname is not defined.
a) The solution using a text macro (the comments are actually not allowed
in the text macros, they are here for explanation only)
:if %(exist STN_NICKNAME) == 1 ;; when NICKNAME is defined
Hello %STN_NICKNAMEÂ Â Â Â Â Â Â Â Â Â Â ;; greet with the nickname
:else                         ;; else (not defined)
Hello %N !                    ;; greet with the name
:endif                        ;;(following commands are always
executed)
You have connected to %Y at %T. ;; Say your callsign and current time
b) The solution using a command macro
:macro GREETING ;; start the command macro
if %(exist STN_NICKNAME) == 1 ;; when NICKNAME is defined
echo Hello %STN_NICKNAMEÂ Â Â Â ;; greet with the nickname
else                        ;; else (not defined)
echo Hello %N !             ;; greet with the name
endif                       ;; (following commands are always executed)
echo You have connected to %Y at %T. ;; Say your callsign and current
time
6.3 Special system macros
There are some special macros that are executed automaticaly by LinPac in
some cases:
init.mac - This is executed when LinPac is started and its function is
to set the callsigns, screen options, and some other parameters.
cinit.mac - This is always executed when a connection is established.
The distribution version of this macro sets the channel parameters in
order to configure station settings from the station database (allowed
remote commands, i/o encoding, terminal type) and executes the logbook
command to sign the start of a connection. LinPac always passes two
arguments to this macro. The first (%1) argument is the callsign of the
connected station and the second (%2) argument is the callsign of the
previously connected station that provides the connection, or empty in
case of direct connection.
ctext.mac - This macro is executed when some station connects to the
terminal. It should print some greeting text. No arguments are passed.
cexit.mac - This is always executed when a connection closes. The
distribution version of this macro just executes the logbook command to
sign the end of the connection and clears the list of allowed remote
commands. There is always one argument passed by LinPac (%1), containing
the callsign of the disconnected station.
7 Creating new commands
A new command can be represented by a macro or by an external program
(standard linux program or special LinPac application). Macros are placed
in the $LINPACDIR/macro directory and external programs are placed in the
$LINPACDIR/bin directory. In both of these directories is the file
'commands' that contains the list of commands in that directory. You
should specify here the name of the file, the name of the command in
LinPac (use upper case to specify the mandatory part of the command). It's
not necessary to include the macros here if you don't want to define the
abbreviation.
In case of external programs, it is also possibile to specify program
flags. Currently the following flags are supported:
A - Ascii mode program. LinPac provides CR <-> LF conversion when
communicating with this program. This is the default setting.
B - Binary mode. Disables the text conversions.
C - Leaves the stdout stream of the program on the console and reads its
stderr stream instead.
D - DOS conversion - ignore LF characters.
S - Reads both stdin and stderr streams of the program (shell mode).
L - Local. This program is never available as a remote command.
R - This program is always run as a remote command (its messages are
always sent out).
P - LinPac removes the paths from filenames that are passed as the
argument of this command when the FIXPATH command is on. This is a
security option.
8 Standard applications
8.1 File transfer protocols
At present LinPac supports two protocols for transferring files:
*Â Autobin - a simple protocol suitable for short files
*Â YAPP - a very sophisticated transfer protocol that provides better
error detection and is able to resume a previously interrupted
transfer
Usage of these protocols is described in chapter [42]3.4.
LinPac can also automatically save incomming 7+ files. After saving all
parts of a file LinPac tries to call the '7plus' program to decode the
file. Received 7+ files are not removed automatically.
8.2 Automatic password generation
8.2.1 Login passwords
LinPac provides automatic replies to the login authorization requests for
the following systems: F6FBB BBS (VE2BLY C_FILTER), BAYBOX, TNOS (numeric
MD5). Each station which requests a login password must have an entry in
the station database containing at least following fields:
A
TYPE= (FBB, BAYBOX or TNOS)
LOGINPW=
PWPROMPT=
BBS_prompt is the text which the BBS sends when requesting the
authorization. Usually it looks like 'Password>' or 'OK0XYZ>'.
8.2.2 Sysop and general use passwords
LinPac provides automatic authorization to the following systems: F6FBB
BBS (MD2 password), FLEXNET (older versions, the 'magic' numbers system
and newer TheNet-like system), THENET and BAYBOX. Each station you want to
authenticate with must have an entry in the station database. For password
generation, the following fields must be set:
TYPE=
PWD= or
SYSNUM=
Known station types are:
*Â FBB - An F6FBB BBS. The PWD field must contain your password.
*Â THENET - A TheNet node. Again the PWD must contain the password.
*Â BAYBOX - The same system as TheNet.
*Â FPAC - A FPAC node. Password must be stored in the PWD field.
*Â FLEXNET - FlexNet node. If the magic number algorithm is used (older
versions of flexdigi) the SYSNUM field must contain your magic number
and the PWD field must not be set. When the TheNet algorithm is used
(newer versions of flexdigi), the PWD field must contain the password
and the SYSNUM field must not be used.
In case of FBB the authorization algorithm can be chosen by setting the MD
field in the station database:
MD=5 - this value will select the MD5 algorithm
MD=2 - this value will select the MD2 algorithm
When no value is set, MD2 algorithm is used.
After connecting to the station you want to authenticate with, the
authorization sequence begins with the :PW command. LinPac will send the
authorization command to the station and tries to answer the authorization
request using your password. If the password is correct, authorization
should finish successfully.
The PW command accepts the following parameters:
:PW [ [ []]]
where
*Â is the command to be sent to the remote station to start the
authorization sequence (sys by default)
*Â is one of the above-mentioned supported systems; this system
is used instead of the one specified in station database
*Â is the password that will be used instead of the one
specified in the station database
It's recommended that you create simple macros for frequently used
authorizations that require special arguments to the PW command.
8.3 Utilities for mail exchange
LinPac contains support for exchanging messages with remote Kantronics
PBBSs as well as F6FBB BBS systems. This support utilizies some tools from
the ax25mail-utils so please install that package first. THe next step
would be to configure Linpac and ax25mail-utils's configuration settings
with the following variables either in Linpac's channel 0 or in Linpac's
init.mac file:
Example #1: Kantronics KPC3:
*Â HOME_TYPE - This sets the type of remote system you're connecting to.
Supported options are either "PBBS" for Kantronics KPC3 type TNCs or
"FBB" for F6FBB BBSes. Only "PBBS" is well understood though the FBB
support has been there for some time.
*Â HOME_BBS - The AX.25 path to the home PBBS including the port name.
For example d710:AA6WK-1 means use the d710 AX.25 port as defined in
the /etc/ax25/axports configuration file and connect to the PBBS
AA6WK-1. It's important to note that the callsigns in Linpac are
CaSe-SeNsItIvE so make sure these two variables use the SAME case.
*Â HOME_ADDR - The full hierarchical address of the BBS (which
technically isn't required for PBBSes). For example
AA6WK.#NCA.CA.USA.NOAM.
To set the variable while in Linpac, the :SET command can be used. You can
also put this same line (but without the colon) in Linpac's init.mac file:
:set HOME_TYPE "PBBS"
:set HOME_BBS@0 "d710:AA6WK-1"
:set HOME_ADDR "AA6WK.#NCA.CA.USA.NOAM"
The recommended place to set this variables is in the startup macro
init.mac. The default version of this macro contains an example of setting
these variables. After setting these variables, the following commands are
available:
Example #2:
*Â HOME_TYPE - This sets the type of remote system you're connecting to.
Supported options are either "PBBS" for Kantronics KPC3 type TNCs or
"FBB" for F6FBB BBSes. Only "PBBS" is well understood though the FBB
support has been there for some time.
*Â HOME_BBS - The AX.25 path to the home BBS including the port name. For
example kiss:OK0PAB OK0NMA means use the kiss AX.25 port as defined in
the /etc/ax25/axports configuration file and connec to the BBS OK0PAB
via the digipeater OK0NMA. It's important to note that the callsigns
are CaSe-SeNsItIvE in Linpac so make sure these two variables use the
SAME case.
*Â HOME_ADDR - The full hierarchical address of the BBS. For example
OK0PAB.#MOR.CZE.EU.
To set the variable while in Linpac, the :SET command can be used. You can
also put this same line (but without the colon) in Linpac's init.mac file:
:set HOME_TYPE "FBB"
:set HOME_BBS@0 "kiss:OK0PAB OK0NMA"
:set HOME_ADDR "OK0PAB.#MOR.CZE.EU"
The recommended place to set this variables is in the startup macro
init.mac. The default version of this macro contains an example of setting
these variables. After setting these variables, the following commands are
available:
Now you need to configure the ax25mail-utils program by editing the
/etc/ax25/axgetlist.conf file. The following example is to support
connecting to PBBSes in example #1 above:
[AA6WK-1]
MYCALL N0CALL
BBSCALL AA6WK-1
BBSPORT d710
CMD_LIST LO +;L
CMD_LIST_FROM LO +;L $
CMD_DISC B
HEADER_LINES 1
FORMAT