[hamradio-commits] [axmail] 01/04: Imported Upstream version 2.5
Dave Hibberd
hibby-guest at moszumanska.debian.org
Sat Sep 19 21:39:31 UTC 2015
This is an automated email from the git hooks/post-receive script.
hibby-guest pushed a commit to branch master
in repository axmail.
commit 4e24dd9ccceeb4d0158640e8748de5e45903fd89
Author: Dave Hibberd <d at vehibberd.com>
Date: Sat Sep 19 11:10:57 2015 +0100
Imported Upstream version 2.5
---
FAQ | 116 ++++++++++++
INSTALL | 62 ++++++
LICENSE | 339 +++++++++++++++++++++++++++++++++
Makefile | 52 +++++
README | 374 ++++++++++++++++++++++++++++++++++++
UPGRADING | 6 +
adduser.c | 193 +++++++++++++++++++
adduser.h | 2 +
axmail.c | 297 +++++++++++++++++++++++++++++
axmail.h | 4 +
command.c | 148 +++++++++++++++
command.h | 9 +
config.c | 285 ++++++++++++++++++++++++++++
config.h | 44 +++++
copying | 340 +++++++++++++++++++++++++++++++++
defines.h | 31 +++
etc/axmail.conf | 53 ++++++
etc/help/autofwd.hlp | 11 ++
etc/help/delete.hlp | 10 +
etc/help/help.hlp | 7 +
etc/help/info.hlp | 2 +
etc/help/kill.hlp | 10 +
etc/help/send.hlp | 7 +
etc/help/sfax.hlp | 20 ++
etc/welcome.txt | 11 ++
head.c | 214 +++++++++++++++++++++
head.h | 19 ++
lock.c | 36 ++++
lock.h | 3 +
mailcmd.c | 526 +++++++++++++++++++++++++++++++++++++++++++++++++++
mailcmd.h | 9 +
mbox.c | 357 ++++++++++++++++++++++++++++++++++
mbox.h | 46 +++++
quit.c | 250 ++++++++++++++++++++++++
quit.h | 2 +
setpwnam.c | 212 +++++++++++++++++++++
setpwnam.h | 5 +
utils.c | 167 ++++++++++++++++
utils.h | 15 ++
39 files changed, 4294 insertions(+)
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..576984b
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,116 @@
+axMail - an SMTP mailbox for the various linux node frontends.
+
+axMail appears to work with most linux based MTAs (Mail Transport Agent)
+but not all, and I haven't had a chance to test it with them all either,
+nor do I honestly care to install every MTA available for linux to do such
+so if you do run an MTA *not listed* below, please feel free to email me
+at: <n1uro at n1uro.com> and I'll add your report to this list. Consider this
+file a 'work in progress' as with the software itself. How to test is
+listed at the bottom.
+
+PostFix - tested fine
+Exim - tested fine
+Smail** - failed tests, and also causes a total loss of end user mail!
+Sendmail* - <unknown>
+Qmail*** - <unknown>
+
+* - In theory, the sendmail MTA should be ok since both exim and postfix
+ have sendmail compatable binaries/symlinks/etc.
+
+** - I don't know what it is with the smail MTA, but for some reason *all*
+ mail gets lost during the internal transfers from the system mailbox
+ and back to the system mailbox. Since smail has basically been
+ abandoned in favor of exim, I don't personally foresee this as an
+ issue.
+
+***- I've never installed a qmail system before and honestly don't feel
+ like doing that now hi!.. so if you run qmail and it works ok, please
+ let me know and I'll change it's status
+
+If there's an MTA that I have missed and you've tested it and it works
+please inform me and I'll add your results here.
+
+
+How to test axmail:
+
+You can run axmail at a command prompt!.. all it requires is that you put
+your callsign after it. BEFORE you run this via a commandline however I
+strongly suggest you make a backup of your system mail spool file by
+typing: cp /var/spool/mail/call /var/spool/mail/call.bak this way here if
+there is an issue and you have mail waiting, you won't lose any mail.
+
+I'll assume your account on your box is your callsign, so in my case I would
+execute:
+n1uro at nat-client0:~$ /usr/sbin/axmail n1uro
+and the standard greetings should appear along with the prompt and any
+mail waiting should appear listed.
+
+Pending the above test worked ok and unread/undeleted mail was saved back
+into the system mailbox, try it from the node as a user who doesn't have
+an account on the box. Hopefully when you exit, it'll tell you that you
+have new mail waiting! Go back in and you should see the welcome.txt file
+from /etc/ax25 listed as a greeting email message.
+
+Other quick FAQs:
+
+axMail works by comparing the user's system mail spool file, and as well
+as any existing axMail saved mail and merges them together 'offline' for
+lack of a better word to use. It then takes this mail and allows the user
+to read/reply/delete/save/etc.
+
+axMail has *always* supported file attachments, after all a file attachment
+is just an encoded file appended to the body of the email message... its just
+that most every client now-a-day automatically encodes/decodes them for you
+and you assume that a file attachment is a seperate entity. All you need to
+do to send and receive attachments via a packet terminal is the following
+(examples taken from a linux terminal);
+
+Sending: First encode the file by using uuencode. To do this run
+uuencode filename filename
+or if you want to make a file of it run: uuencode file file > file1
+then copy and paste that encoded text in it's full into the body of
+the mail message and send it.
+
+Receiving: copy and paste the output of your message into a temporary
+file and then run "uudecode -o filename tempfile". You will now have
+a pdf/doc/text/jpg file sent to you by someone.
+
+axMail now supports sending of fax transmissions! To configure axMail to
+be able to do such, configure an account with an online fax service such
+as eFax where you can email faxes and put the email address you'd use to
+send faxes to in a _new line_ called "FaxGate" inside /etc/ax25/axmail.conf.
+When users attempt to send a fax, your account will be hidden from them and
+all they'll see is that they're sending to "a" fax gateway system.
+
+People have asked about why new incoming mail isn't seen until after the
+user logs out of axMail. If axMail read directly off of the system
+mailspool file, then it'd lock out any new incoming mail from being posted
+to the user's mailbox as it'd have a lock on the spool file, and the
+message numbers could also possibly change while the user goes to select a
+message number to read. This would be very confusing to the end user.
+
+If you wish to allow users to use the internet or packet TCP/IP to pop3
+their mail from your system, they may do so... however keep in mind, any
+mail they read or list manually within axMail will have it's status
+changed from "new". As we all know about the pop3 protocol, mail not
+flagged as "new" isn't popped but it's considered as if the client is
+using a software package such as eudora or outlook (to name a couple...
+notice which I listed first? hi!) and they have their options set to leave
+a copy of their mail on the server. The user will have to log into your
+node and retrieve their mail from there. After all, isn't part of running
+packet node services is to encourage hams to actually use their radios to
+get to such things? :) All you as sysop/root on the box need to do is
+ensure that a pop3 daemon is installed and running, and that you configure
+axMail.conf to give the end user proper permissions in their shell to be
+able to use your pop3 daemon.
+
+I've gone to many days worth of studying how most boxes are configured
+I've taken it upon myself to try and get axMail as 'bullet proof' and as
+simple a process as it can possibly be. Unfortunately the program can not
+read your mind so you'll have to do *some* config work to it... but
+otherwise it should be a nice low-ram low-resource system for you and your
+users to enjoy.
+
+Comments and questions are always welcomed!
+
+73 de Brian N1URO
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..14f70e8
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,62 @@
+axMail v2.2 - an SMTP mailbox for the various linux node frontends.
+
+Current author: Brian Rogers (N1URO) <n1uro at n1uro.com>
+Past author: Marius Petrescu (YO2LOJ) <mpetrescu at online.ro>
+Creator: Heikki Hannikainen (OH7LZB) <hessu at pspt.fi>
+
+Additional Submissions: Stefano (IW3IJQ) <ziotibia1 at libero.it>
+
+As with any of the softwares I tweek n geek, *use at your own risk*!
+With that said, and the fact that this is GPL software if you find
+something that's borked... don't just submit a bug report. Fix it if
+you can. Rerelease it under your own callsign if you wish, or feel free
+to send me your code and I'll import it in.
+
+This is probably one of the simplest packages to install and configure!
+After you run tar zxvf axmail-0.0.8.tgz cd axmail-0.0.8 (which is where
+you should be now if you're reading this :) ) and run:
+
+make; make install
+
+(on newer gcc/libs I do know that there's a warning after it makes but
+it doesn't prevent the binary from compiling and so far it seems to test
+ok. I'll fix that if and when I get the chance but don't hold your breath
+on it hi!)
+
+cd /usr/local/etc/ax25 and using your favorite editor (vi, joe, pico, etc) and
+edit axmail.conf. In here you can specify how you wish the mailbox
+to handle accounting for end users. On *most* linux systems, the default
+should be "ok" but if you wish to have users contact you first, or if
+you wish to have the system auto-create a standard shell login, or popmail
+account for the users, etc... you may do so in the file. Double check your
+settings (it *is* possible you can configure axmail.conf so that everyone
+has root-group access... but why would you wish to do that? You've been
+*warned* so double check your config settings for auto-creation of
+accounts before saving!) The file is well commented to assist you. When
+you're finished and have become an expert, if you wish to you can delete
+the comment lines.
+
+You may also customize the file "welcome.txt" in /usr/local/etc/ax25/ if you
+wish to also. I suggest leaving the first line as-is as this is the so called
+"new user" welcome greeting email. I've supplied a basic and short
+greeting email message that users will get once they've created their
+mailbox. If you would rather new users email your mail account directly
+instead of root, you may wish to change that line.
+
+For the software itself... believe it or not, you're *DONE*! That's all!
+However... now we need to get it hooked into which ever node frontend you
+run so that users have a way of accessing it. axMail runs as an external
+process (ExtCmd) to the node. I've tested it with URONode (obviously) and
+with LinuxNode by Tomi. To do this cd /usr/local/etc/ax25 and using your
+favorite editor open node.conf and add the following line to your ExtCmds:
+
+ExtCmd MAil 1 root /usr/local/sbin/axmail axmail %u
+(note: MA in the word MAil is in CAPS)
+
+Save node.conf and telnet in to test! It should work just fine. Since you
+would have an existing account on your server, it's unlikely that you'll
+get the welcome message, but since you can edit it, you'll know what it
+says :)
+
+Happy mailing!
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f4b70f5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,52 @@
+all: axmail
+
+CC = gcc
+LD = gcc
+CFLAGS = -O2 -Wstrict-prototypes -g -I../lib
+LIBS = -lcrypt
+MODULES = utils.o config.o adduser.o command.o mailcmd.o mbox.o head.o lock.o axmail.o quit.o
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+upgrade: installbin installhelp
+
+install: installbin installconf installhelp
+
+installbin: all
+ install -m 0755 -s -o root -g root axmail /usr/local/sbin
+
+installconf:
+ install -m 755 -o root -g root -d /usr/local/etc/ax25
+ install -m 644 -o root -g root etc/axmail.conf /usr/local/etc/ax25
+ install -m 644 -o root -g root etc/welcome.txt /usr/local/etc/ax25
+
+installhelp:
+ install -m 755 -o root -g root -d /usr/local/var/ax25/axmail/help
+ install -m 644 -o root -g root etc/help/*.hlp /usr/local/var/ax25/axmail/help
+
+back:
+ rm -f ../mail.tar.gz
+ tar cvf ../mail.tar *
+ gzip ../mail.tar
+
+clean:
+ rm -f axmail *.o *~ *.bak core etc/*~ etc/help/*~
+
+distclean: clean
+ rm -f axmail
+
+axmail: $(MODULES)
+ $(LD) -o axmail $(MODULES) $(LIBS) $(LDFLAGS)
+
+utils.o: utils.h utils.c mbox.h
+config.o: config.h config.c defines.h axmail.h utils.h
+adduser.o: adduser.h adduser.c utils.h config.h defines.h
+command.o: command.h command.c config.h mailcmd.h mbox.h utils.h quit.h
+mailcmd.o: mailcmd.h mailcmd.c defines.h utils.h mbox.h config.h
+mbox.o: mbox.h mbox.c utils.h defines.h config.h head.h
+head.o: head.h head.c defines.h
+utils.o: utils.h utils.c
+lock.o: lock.h lock.c utils.h
+quit.o: quit.h quit.c config.h lock.h
+axmail.o: axmail.h axmail.c config.h adduser.h utils.h quit.h mbox.h
diff --git a/README b/README
new file mode 100644
index 0000000..44de3c2
--- /dev/null
+++ b/README
@@ -0,0 +1,374 @@
+axMail - an SMTP mailbox for the various linux node frontends.
+
+PREFACE:
+
+First off, sincere thanks to those who have written to tell me that
+they use axMail, like what I've done to axMail, and for the
+enthusiasm shown via words and/or code contributions for the program
+in hopes of keeping packet radio networks around the world alive!
+
+INTRO:
+
+Greetings and thanks for taking a look at the program. Below I've posted
+a kind of history of the program to the best of my knowledge taking text
+from existing files. Rather than trying to reinvent the wheel and after
+seeing this program before on Labrat's radio.linux.org.au site, I decided
+to try and give some life into it... partially with the assistance of Phil
+N1XTB nudging me pretty consistantly for many months in helping him get an
+SMTP agent in his linux based packet node server without having to install
+an xNOS overhead node ontop it. :)
+
+Please do take a moment and read the text based files included with this
+package so you're a bit familiar with what it does so that you don't get a
+false perception as to what it can and/or can not do. axMail just might
+not be what you're looking for or expecting for a node based plugin
+
+CHANGE HISTORY:
+axmail v2.5
+ Updated 30 May, 2015 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- added new delivery receipt function to the send routine. This
+ compliments the read receipt function in the event of high
+ priority mail. Typically the read receipt is an option generated
+ by the recipient who may not decide to generate one. At least this
+ modification ensures with an ESMTP delivery that the sender using
+ axMail will get a reciept from "MAILER-DAEMON" which will verify
+ the status of delivered mail. This change was done in mailcmd.c
+ and is designed with the sendmail binary included with postfix.
+- updated this README file.
+- updated version number in defines.h
+
+axmail v2.4
+ Updated 25 April, 2015 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- cleaned up mbox.c where I had originally placed the receipt checker
+ routine in. This caused loops within the buffer that displayed the
+ message. The true routine lives in mailcmd.c
+- added patch to Makefile provided by Jaroslav at Red Hat for distribution
+ downstream compiles to make packages.
+- changed version in defines.h
+- major change in command.c, added a new Autofwd command to allow users to
+ auto-forward mail from a remote system to their "home" axMail-FAX base
+ system. Could also be used to forward mail to their internet accounts.
+- added autofwd.hlp file.
+- alphabetized the commandset listing, removed redundantly spelled commands.
+- reworked Makefile and added an "upgrade" option so new files ONLY are
+ deployed after make. Execute using: "make upgrade"
+- updated this file.
+
+axmail v2.3.1
+ Updated 5 February, 2015 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- added a flag in mailcmd.c where if the request for a receipt exists in a mail
+ message, a bell and a warning sign is generated after the message has been
+ read by the user with instructions to use SR to generate a receipt. This
+ was a difficult routine for me to think of considering the various race
+ conditions that can be expected and met.
+- updated welcome.txt with version upgrade and new feature list.
+- updated README.
+
+axmail v2.3
+ Updated 5 February, 2015 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- Added a new "Receipt" request flag in mailcmd.c by request of Mitch AB4MW.
+ This defaults to NO but when flagged to YES, a request will be sent to the
+ remote client's agent. If the agent supports such, they will be prompted
+ whether or not to honor your receipt request. This is history as NO AGENT
+ FOR PACKET TERMINALS SUPPORTS THIS! The function of a generated read
+ receipt is similar to how HylaFax generates confirmation of transmission
+ receipt mails to your mailbox. Currently mail read in axMail will NOT
+ generate a receipt back. I may work on this later, but for now it doesn't
+ exist.
+* My thoughts of the receipt function is negative. The fact that I may be
+ sending notification that I'm in my email client to a remote destination
+ IMHO is such that a webcam may as well be turned on and watch me do email,
+ and send the stream to "Big Brother" and I don't mean the television show.
+ </rant>
+- Updated defines.h with the new version number.
+- Updated welcome.txt so the new version number is displayed.
+
+axmail v2.2
+ Updated 25 December, 2014 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- Made some maintenance changes, but forgot to log them in here.
+axmail v2.1.1
+ Updated 30 October, 2014 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- Makefile
+ Code provided by Bob Tenty VE3TOK to make it more compatable
+ with newer GCC compiler requirements.
+- utils.c
+ Code provided by Bob Tenty VE3TOK to fix a warning produced when
+ compiling.
+- defines.h
+ Changed version number to reflect the changes incorporated by
+ Bob Tenty VE3TOK and committed to the subversion repository.
+
+axmail v2.1
+ Updated 31 July, 2014 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- axmail.c
+ Code provided by Jaroslov OK2JRQ fixes a potential security hole in
+ the system privilege matching.
+- global
+ axMail is now under review for considerations as standard packaging in
+ RedHat's fedora project. It appears it's going to be added as a package.
+
+axmail v2.0
+ Updated 8 July, 2013 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- defines.h
+ Updated version number to reflect version release 2.0. Version 1.0.5
+ was simply a maintenance test package to try and reincorporate what
+ I had done up to version 1.0.6 which I believe was one of my last
+ releases up to 2009. Since I've done all that I can recall at this
+ point and time, I decided to match URONode's release numerics with
+ a 2.0 release version.
+
+axmail v1.0.5
+ Updated 5 July, 2013 by Brian Rogers (N1URO) <n1uro at n1uro.net>
+Changes:
+- defines.h
+ Updated email listings to reflect the most current ones I could find
+ including my own. Also added 2013 to the years worked on axMail by
+ me.
+
+- quit.c
+ Forced ALL mail, read or otherwise when user quits to save to the
+ user's system mailbox. This is for reverse compatability with those
+ who may also run a web-based email service on the internet such as
+ NeoMail, EMUMail, etc. Prior, the system was supposed to separate
+ any read mail (and all accompanying mail in that session) to the
+ axmail ~/mbox file. We don't want this for the specific reason of
+ "reverse email client" compatability.
+
+axmail v1.0.4
+ Updated 23 May, 2008 by Brian Rogers (N1URO) <brian at support.uroweb.net>
+ Changes:
+- setpwnam.c
+ Changed the way SIGPIPE was handled. Instead of being ignored, it will
+ now read a SIGQUIT properly if a QUIT is signaled to axmail either via
+ a shell prompt, or a node frontend. I've been noticing especially on
+ some timeouts that temp files don't flush as they should and the
+ user's directory can start to fill up.
+
+axMail v1.0.3
+ Updated 2 December, 2007 by Brian Rogers (N1URO) <brian at support.uroweb.net>
+Changes:
+- mailcmd.c
+ Reset the way I wanted to handle the user input routine for sending faxes.
+ Commented out some more unneeded/unused code in the do_fax routine... will
+ clean it up in next release or so.
+
+- mailcmd.c
+ cleaned up a bug I introduced in the never released 1.0.2 where the
+ X-Mailer was duping itself after each line of the body of a message.
+
+- sfax.hlp
+ Reworded the SFax help file to help show some examples of how to format
+ the header.
+
+axMail v1.0.2
+ Updated 24 November, 2007 by Brian Rogers (N1URO) <brian at support.uroweb.net>
+Changes:
+- mailcmd.c
+ Cleaned up some of the code in SFax. Also made some cosmetic changes.
+
+axMail v1.0.1
+ Updated 31 October, 2007 by Brian Rogers (N1URO) <brian at support.uroweb.net>
+Changes:
+- mailcmd.c
+ Added a new routine to allow users to send faxes. This is defined by the
+ command "SF" for Send Fax. The routine was taken from the "S"end function
+ however since it's a one-way transmission, there is no reply available
+ nor is there an option for users to fax to any fax service as some I know
+ are pay services.
+- config.h
+ added definitions for faxgate in axmail.conf
+- config.c
+ added routine to allow for faxgate as a variable and be called from
+ mailcmd.c
+- defines.h
+ version upgraded from v1.0.0 (unreleased - test version) to
+ v1.0.1
+- etc/axmail.conf
+ Added new line called "FaxGate" with an example of how to properly
+ configure this line.
+- etc/help/sfax.hlp
+ Added new file "sfax.hlp" which is an online help file for the SFax
+ command.
+
+axMail v0.0.9
+ Updated 26 September, 2006 by Brian Rogers (N1URO) <n1uro at n1uro.com>
+Changes:
+- mailcmd.c
+ Added a new routine that prompts the sender whether or not the message
+ is of an emergency/high priority mail message. If it's emergency message
+ then the headers are appended with an X-code flagged in such a manner
+ that Eudora and Outlook will display the received mail with a red flag
+ of sorts. The idea of such came to me in thinking of "what can I do
+ to help improve means of emergency communications using TCP/IP, Linux,
+ and packet radio?" Having the ability to "red flag" an SMTP message
+ I don't believe has yet to be available in any packet messaging
+ system... axMail I hope is the first.
+
+ If a user just hits enter, or selects "no" then the mail message
+ is sent under normal send routines.
+
+ found a minor bug in my routine where if an end user answered
+ "yes" in wanting to send an emergency/high priority message the system
+ ignored the request and sent it as 'normal' delivery. Made a minor
+ change to bullet-proof the responce.
+
+ Added online help text if user is unsure about sending a message
+ flagged urgent or normal. This text is available when the user is
+ prompted for priority selection by hitting "?" at the prompt.
+
+- defines.h
+ Version updated from v0.0.8 to v0.0.9
+
+axMail v0.0.8
+ Updated 2006 by Brian Rogers (N1URO) <n1uro at n1uro.com>
+
+Changes:
+ - mailcmd.c
+ Rewrote and incorporated code provided by IW3IJQ how axMail inserts
+ it's version number in the X-Mailer: string.
+ - mailcmd.c
+ Added an X-Origin: string to show those peeking at mail headers
+ just how the message was possibly sent... by AMATEUR RADIO!
+ - axmail.conf
+ Added config option in "AllowMail" for axhome, a rewrite of code
+ submitted by Stefano IW3IJQ. While I stripped out home directory
+ structures similar to that of qmail or axspawn, Stefano convinced
+ me that it may be easier to manage home directories for axMail users
+ who don't have shell access to branch out within a preset directory.
+ - defines.h
+ Updated version number from 0.0.7 to 0.0.8
+
+ - axmail.c and config.c
+ Rewrote and incorporated code to allow for the routines to use
+ what Stefano IW3IJQ originally labled "newuhome" to use "axhome".
+ While I was at it, I rewrote and shortened the error text pushed
+ to a user who doesn't have permission to use such a directory.
+
+ * Note: When I write error texts and menus, I try to write them for
+ users on a multi-hop 1200 baud path thus the shorter the better as
+ long as context isn't lost and for long distance hops where full
+ paclen may cause retries (worse yet timeouts!)
+
+axMail v0.0.7
+
+ Updated 2005 by Brian Rogers (N1URO) <n1uro at n1uro.com>
+
+Changes:
+ - cosmetics
+ My usual "I like seeing this this way" type cosmetics... too many
+ to mention!
+
+ - adduser.c
+ changed the hard coding of user 'home' directories so that instead
+ of them going into a period delimited sort, just dump em all into
+ /home/<user> which seems to be "the norm" on most systems I've had
+ to assist with.
+
+ - adduser.c
+ fixed a bug where creating a user was actually causing the program to
+ segfault upon exit the first time a user went into the mailbox! The
+ node frontends hid this segfault as the program still flushed itself
+ from ram but I spotted it when running it at a command prompt. The
+ segfault came when axMail attempted to write mail back to the user's
+ system mailbox and it didn't exist. How I fixed this is listed next.
+ This may just be a new bug that appeared with the upgrading of libs,
+ this I'm unsure of and since I have no desire to go backwards I have
+ decided to actually make a minor routine...
+
+ - welcome.txt
+ New users are now sent a "welcome" message that the sysop can easily
+ customize to their desires. It's located at /etc/ax25/welcome.txt.
+ I figured that since axMail was segfaulting because such a file did
+ not exist, I might as well make use of this need by having the program
+ send the user a greeting.
+
+ - defines.h
+ Changed paths to be more in line with the more modern type configs
+ as a default. Paths can still be defined by the sysop prior to
+ compiling axMail.
+
+ - Makefile
+ I changed the default of make install to include all of the subroutines
+ within the Makefile yet leaving such things as "make installbin"
+ available as runtime options if just a binary refresh creation is
+ desired.
+
+ - other
+ I'm sure I missed a note or two *shrug*
+
+axMail v0.0.6
+
+ Tweeks made by Marius Petrescu (?) I know there was a ver 0.0.6 which
+ I at one time had but lost and can't seem to find it. My (n1uro)
+ changes may have alread been incorporated.
+
+axMail v0.0.5
+
+ True mailbox functionalities created by Marius Petrescu.
+ Added Mailbox save routines (compatible with the command line
+ mail agent, including ~/mbox file)
+
+axMail v0.0.4
+
+ Copyright (c) 1996 Heikki Hannikainen (OH7LZB) <hessu at pspt.fi>
+
+ 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.
+
+
+ Don't give this one to anyone yet... it is NOT ready for distribution!
+
+ This is a simple mail user agent intended to provide the
+mail functions in xNOS in a Linux ax.25 environment. If required,
+it creates a normal user account for each new user (code mostly taken
+from axspawn by Joerg Reuter (DL1BKE)), so that they can receive mail
+on the system. axMail uses sendmail (or similar) to deliver mail, and
+reads mail from each user's system mailbox (/var/spool/mail/username).
+It does not provide any means of transferring mail between hosts.
+
+ axMail provides a simple, low-overhead user interface, much similar
+to /bin/mail, xNOS and the packet BBS systems. It's useful for providing
+good SMTP mail services for "dumb" ax.25 users over slow radio channels.
+
+ axMail is intended to be called from node. It takes one command
+line argument of the user's callsign (with or without SSID). It must
+be run as root, but it setuid()'s itself to the respective user's
+privileges as soon as possible. It might run from ax25d as well.
+It can also be executed from a shell with user privileges.
+
+ Some code (command parser, configuration file stuff) and the internal
+architecture was taken from the LinuxNode frontend by Tomi Manninen
+(OH2BNS). Thanks!
+
+INSTALLATION:
+
+ See the file: INSTALL
+
+TODO:
+ I know I can clean up the code a LOT more, will do so for a maintenance
+ release which will most likely be v1.0.2.
+
+ Suggestions?
+
+--
+Brian Rogers <n1uro at n1uro.net> [n1uro at n1uro.#cct.ct.usa.noam]
+ftp://ftp.n1uro.net/packet
diff --git a/UPGRADING b/UPGRADING
new file mode 100644
index 0000000..fc17377
--- /dev/null
+++ b/UPGRADING
@@ -0,0 +1,6 @@
+If you are upgrading axmail from ver 1.0.1, all you really need to do
+is copy the binary over the existing one.
+
+If you are upgrading axMail from any version equal to or earlier than 1.0.0
+back up your /etc/ax25/axmail.conf file and do a full install.
+
diff --git a/adduser.c b/adduser.c
new file mode 100644
index 0000000..0519fb8
--- /dev/null
+++ b/adduser.c
@@ -0,0 +1,193 @@
+
+/* adduser.c - create an user account (yecch) */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <errno.h>
+#include <crypt.h>
+#include <string.h>
+
+#include "adduser.h"
+#include "utils.h"
+#include "config.h"
+#include "defines.h"
+
+/* Ask for a new password, and keep it sane */
+
+void get_passwd(char *newuser, char *passw)
+{
+ char passi[12];
+
+repass: /* Get password */
+ getstr(passi, 10, "Enter password for the new account (6-8 characters, ? for help): ");
+
+ if (!strcmp(passi, "?")) {
+ printf("Your password must be 6 to 8 characters long, and it may not be the same as\n");
+ printf("your login name (in this case, your callsign).\n");
+ goto repass;
+ }
+ if ((strlen(passi) > 8) || (strlen(passi) < 6)) {
+ printf("Password must be 6-8 characters long.\n");
+ goto repass;
+ }
+ if (!strcasecmp(passi, newuser)) {
+ printf("Password may not be your login name (callsign).\n");
+ goto repass;
+ }
+
+ /* Crypt password */
+ strcpy(passw, crypt(passi, "ax")); /* Okay, salt _should_ be random... */
+}
+
+/* add a new user to /etc/passwd and do some init */
+
+int new_user(char *newuser)
+{
+ struct passwd pw, *pwp;
+ uid_t uid;
+ FILE *fp;
+ char homedir[256], userdir[256];
+ char buf[4096];
+ char subdir[4];
+ char passw[20];
+ char str[LINESIZE + 1];
+ int cnt = 0;
+ unsigned char *p, *q;
+ struct stat fst;
+ int fd_a, fd_b, fd_l;
+
+ /* Build path for home directory */
+
+ strncpy(subdir, newuser, 3);
+ subdir[3] = '\0';
+ sprintf(homedir, "%s/%s", def_homedir, newuser);
+ strcpy(userdir, homedir);
+
+ getname(fullname);
+
+ if (strlen(fullname) == 0) {
+ printf("Okay, using your callsign as your name. You may change it later.\n");
+ strcpy(fullname, newuser);
+ }
+
+ /* Get password */
+
+ switch (login_allowed) {
+ case 0: strcpy(passw, "*");
+ break;
+ case 1: get_passwd(newuser, passw);
+ break;
+ case 2: strcpy(passw, ""); /* Yuck! */
+ break;
+ }
+
+ /* Lock */
+ fd_l = open(LOCK_AXMAIL_FILE, O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
+ flock(fd_l, LOCK_EX);
+
+retry:
+ /* Find first free UID */
+ cnt++;
+
+ for (uid = first_uid; uid < 65535; uid++)
+ {
+ pwp = getpwuid(uid);
+ if (pwp == NULL)
+ break;
+ }
+
+ if (uid >= 65535 || uid < first_uid)
+ return -1;
+
+ /* build directories for home */
+
+ p = homedir;
+
+ while (*p == '/') p++;
+
+ chdir("/");
+
+ while(p)
+ {
+ q = strchr(p, '/');
+ if (q)
+ {
+ *q = '\0';
+ q++;
+ while (*q == '/') q++;
+ if (*q == 0) q = NULL;
+ }
+
+ if (stat(p, &fst) < 0)
+ {
+ if (errno == ENOENT)
+ {
+ mkdir(p, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
+
+ if (q == NULL)
+ {
+ chown(p, uid, user_gid);
+ chmod(p, S_IRUSR|S_IWUSR|S_IXUSR);
+ }
+ }
+ else
+ return -1;
+ }
+
+ if (chdir(p) < 0)
+ return -1;
+ p = q;
+ }
+
+ /* Add the user now */
+
+ fp = fopen(PASSWDFILE, "a+");
+ if (fp == NULL)
+ return -1;
+
+ pw.pw_name = newuser;
+ pw.pw_passwd = passw;
+ pw.pw_uid = uid;
+ pw.pw_gid = user_gid;
+ pw.pw_gecos = fullname;
+ pw.pw_dir = userdir;
+ pw.pw_shell = def_shell;
+
+ if ((getpwuid(uid) != NULL) && (cnt <= 10)) goto retry; /* oops?! */
+
+ if ((putpwent(&pw, fp) < 0) || (cnt > 10))
+ return -1;
+
+ flock(fd_l, LOCK_UN);
+ fclose(fp);
+
+ /* Copy ax25.profile */
+
+ fd_a = open(CONF_AXMAIL_PROF_FILE, O_RDONLY);
+
+ if (fd_a > 0)
+ {
+ fd_b = open(USERPROFILE, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR|S_IXUSR);
+
+ if (fd_b < 0)
+ return -1;
+
+ while ( (cnt = read(fd_a, &buf, sizeof(buf))) > 0 )
+ write(fd_b, &buf, cnt);
+ close(fd_b);
+ close(fd_a);
+ chown(USERPROFILE, uid, user_gid);
+
+ }
+/* Be nice and send the new user a welcome message :) */
+
+ sprintf(str, "%s -oem %s@%s < %s", BIN_AXMAIL_SENDMAIL, newuser, hostname, WELCOME);
+ system(str);
+ return 0;
+}
+
diff --git a/adduser.h b/adduser.h
new file mode 100644
index 0000000..ef0effd
--- /dev/null
+++ b/adduser.h
@@ -0,0 +1,2 @@
+
+extern int new_user(char *newuser);
diff --git a/axmail.c b/axmail.c
new file mode 100644
index 0000000..1fd716c
--- /dev/null
+++ b/axmail.c
@@ -0,0 +1,297 @@
+/* axmail.c - The command parser and main function */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <crypt.h>
+#include <error.h>
+
+#include "config.h"
+#include "axmail.h"
+#include "utils.h"
+#include "adduser.h"
+#include "quit.h"
+#include "mbox.h"
+
+/* Parse c-style escapes (neat to have!) */
+
+static char *parse_string(char *str)
+{
+ char *cp = str;
+ unsigned long num;
+
+ while (*str != '\0' && *str != '\"') {
+ if (*str == '\\') {
+ str++;
+ switch (*str++) {
+ case 'n':
+ *cp++ = '\n';
+ break;
+ case 't':
+ *cp++ = '\t';
+ break;
+ case 'v':
+ *cp++ = '\v';
+ break;
+ case 'b':
+ *cp++ = '\b';
+ break;
+ case 'r':
+ *cp++ = '\r';
+ break;
+ case 'f':
+ *cp++ = '\f';
+ break;
+ case 'a':
+ *cp++ = '\007';
+ break;
+ case '\\':
+ *cp++ = '\\';
+ break;
+ case '\"':
+ *cp++ = '\"';
+ break;
+ case 'x':
+ num = strtoul(--str, &str, 16);
+ *cp++ = (char) num;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ num = strtoul(--str, &str, 8);
+ *cp++ = (char) num;
+ break;
+ case '\0':
+ return NULL;
+ default:
+ *cp++ = *(str - 1);
+ break;
+ };
+ } else {
+ *cp++ = *str++;
+ }
+ }
+ if (*str == '\"')
+ str++; /* skip final quote */
+ *cp = '\0'; /* terminate string */
+ return str;
+}
+
+/* Parse command line to argv, honoring quotes and such */
+
+int parse_args(char *argv[],char *cmd)
+{
+ int ct = 0;
+ int quoted;
+
+ while (ct < 31)
+ {
+ quoted = 0;
+ while (*cmd && isspace(*cmd))
+ cmd++;
+ if (*cmd == 0)
+ break;
+ if (*cmd == '"') {
+ quoted++;
+ cmd++;
+ }
+ argv[ct++] = cmd;
+ if (quoted) {
+ if ((cmd = parse_string(cmd)) == NULL)
+ return 0;
+ } else {
+ while (*cmd && !isspace(*cmd))
+ cmd++;
+ }
+ if (*cmd)
+ *cmd++ = 0;
+ }
+ argv[ct] = NULL;
+ return ct;
+}
+
+/* Find the command from the command table and execute it. */
+
+int cmdparse(struct cmd *cmds, char *cmdline)
+{
+ struct cmd *cmdp;
+ int argc;
+ char *argv[32];
+
+ if ((argc = parse_args(argv, cmdline)) == 0 || *argv[0] == '#')
+ return 0;
+ strlwr(argv[0]);
+ for (cmdp = cmds; cmdp->function != NULL; cmdp++)
+ if (strncasecmp(cmdp->name, argv[0], strlen(argv[0])) == 0)
+ break;
+ if (cmdp->function == NULL)
+ return -1;
+ return (*cmdp->function)(argc, argv);
+}
+
+/* Signal handlers (which don't do all the things they SHOULD do) */
+
+static void alarm_handler(int sig)
+{
+ printf("\nTimeout! Closing...\n");
+ exit(1);
+}
+
+static void term_handler(int sig)
+{
+ printf("System going down! Closing...\n");
+ exit(1);
+}
+
+/* Initialisation for the user */
+
+int init_user(char *call)
+{
+ struct passwd *pw;
+ char pass[13], salt[3];
+ char *p;
+ char axhome[64];
+
+ /* Strip SSID */
+ if (local) {
+ pw = getpwuid(getuid());
+ } else {
+ strcpy(callsign, call);
+ strcpy(username, callsign);
+ strlwr(username);
+ p = strchr(username, '-');
+ if (p) *p = '\0';
+ pw = getpwnam(username);
+ }
+
+ if (!pw) {
+ if (local)
+ panic("Ouch, you don't seem to be in the password file.\n");
+ if (autocreate) {
+ syslog(LOG_NOTICE, "Adding new user %s", username);
+ if (new_user(username) < 0) {
+ syslog(LOG_NOTICE, "Could not add new user %s", username);
+ printf("Sorry, could not add new user.\n");
+ return -1;
+ }
+ printf("You have been added to the user list of %s.\nWelcome.\n", hostname);
+ pw = getpwnam(username);
+ } else {
+ syslog(LOG_NOTICE, "New user %s not accepted", username);
+ printf("Sorry, new users are not accepted at this time.\n");
+ return -1;
+ }
+ } else {
+ if (local) {
+ strcpy(username, pw->pw_name);
+ strcpy(callsign, username);
+ }
+ /* Strip full name from the gecos field... */
+ if (strchr(pw->pw_gecos, ',') == NULL)
+ strcpy(fullname, pw->pw_gecos);
+ else
+ strcpy(fullname, strtok(pw->pw_gecos, ","));
+ }
+
+ if (!local) {
+ if ((mail_allowed == 1) && (strcmp(pw->pw_passwd, "*"))) {
+ printf("Sorry, you are not allowed to use axmail (you have a password set).\n");
+ return -1;
+ }
+
+ if ((mail_allowed == 2) && (!strcmp(pw->pw_passwd, "*"))) {
+ printf("Sorry, you are not allowed to use axmail (locked out in password file).\n");
+ return -1;
+ }
+ if (mail_allowed == 3) {
+ sprintf(axhome, "%s/%s", def_homedir, username);
+ if (strcmp(pw->pw_dir, axhome)) {
+ printf("Sorry, you are not allowed to use axmail - bad axhome.\n");
+ return -1;
+ }
+ }
+
+ if (identification == 1) {
+ getstr(pass, 12, "Password: ");
+ strncpy(salt, pw->pw_passwd, 2);
+ salt[2] = '\0';
+ if (strcmp(pw->pw_passwd, (char *)crypt(pass, salt))) {
+ printf("Login incorrect.\n");
+ return -1;
+ }
+ }
+
+/* code supplied by Jaroslav Skarvada */
+ if ( (setgroups(0, NULL) == -1) || (setgid(pw->pw_gid) == -1) || (setuid(pw->pw_uid) == -1) )
+ panic("init_user: Argh, cannot setuid() or setgid() to %i.%i", pw->pw_uid, pw->pw_gid);
+ }
+
+ homedir = strdup(pw->pw_dir);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char *p;
+
+ signal(SIGALRM, alarm_handler);
+ signal(SIGTERM, term_handler);
+ openlog("axmail", LOG_PID, LOG_DAEMON);
+
+ if (getuid() != 0)
+ local = 1; /* Hey, we're being executed by a "normal"
+ * user, with user privileges!
+ */
+
+ if ((!local) && (argc != 2)) {
+ printf("axmail: Callsign not found as a parameter.\n");
+ syslog(LOG_NOTICE, "Callsign not found as a parameter\n");
+ return 1;
+ }
+
+ if (read_config() == -1) /* Read axmail.conf */
+ return 1;
+
+ printf("%s\n", VERSION);
+
+ if (init_user(argv[1]) == -1) /* Get user specific data, create user account */
+ return 1;
+
+ tinit(); /* Filenames etc */
+ getmail(); /* Scan mailbox */
+
+ if ((newm) || (messages))
+ printf("You have %i messages (%i new).\n", messages, newm);
+
+ prompt();
+ fflush(stdout);
+
+ p = malloc(1024);
+
+ while (1)
+ {
+ fgets(p, 1023, stdin);
+
+ if (p == NULL)
+ quit(0, 0);
+
+ if (cmdparse(Mailcmds, p) == -1)
+ printf("Unknown command. Type ? for a list.\n");
+
+ prompt();
+ fflush(stdout);
+ }
+
+}
+
diff --git a/axmail.h b/axmail.h
new file mode 100644
index 0000000..1a57bdc
--- /dev/null
+++ b/axmail.h
@@ -0,0 +1,4 @@
+
+extern int parse_args(char *argv[],char *cmd);
+extern int cmdparse(struct cmd *cmds, char *cmdline);
+
diff --git a/command.c b/command.c
new file mode 100644
index 0000000..0e9dd4b
--- /dev/null
+++ b/command.c
@@ -0,0 +1,148 @@
+/* command.c - Commands which have nothing to do with mail... */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "defines.h"
+#include "command.h"
+#include "config.h"
+#include "mailcmd.h"
+#include "mbox.h"
+#include "utils.h"
+#include "quit.h"
+
+struct cmd Mailcmds[] = {
+ { "?", do_help },
+ { "Autofwd", do_forward },
+ { "Bye", do_exit },
+ { "Cancel", do_quit },
+ { "Delete", do_kill },
+ { "Exit", do_exit },
+ { "Help", do_help },
+ { "Info", do_help },
+ { "Kill", do_kill },
+ { "List", do_list },
+ { "Name", do_name },
+ { "Quit", do_exit },
+ { "Read", do_read },
+ { "Send", do_send },
+ { "SFax", do_fax },
+ { "SReply", do_send },
+ { "STatus", do_status },
+ { "Unkill", do_unkill },
+ { "Verbose", do_read },
+ { NULL, NULL }
+};
+
+int do_status(int argc, char **argv)
+{
+ printf("Messages: %i\n", messages);
+ return 0;
+
+}
+
+int do_name(int argc, char **argv)
+{
+ char name[32];
+
+ getname(name);
+
+ if (strlen(name) == 0)
+ printf("Name not changed. ");
+ else { /* Okay, save it */
+ strcpy(fullname, name);
+ }
+
+ printf("You're now known as %s.\n", fullname);
+
+ return 0;
+}
+
+/* int do_forward(int argc, char **argv) */
+int do_forward(int argc, char **argv)
+{
+ char *email;
+ char *fwdfile;
+ char fwd[79];
+ char forward[79];
+
+ getaddy(fwd);
+ FILE *fptr;
+
+ sprintf(forward, "%s/.forward", homedir);
+ fwdfile = strdup(forward);
+ fptr = fopen(fwdfile, "w+");
+
+// if (strlen(fwd) == 0);
+// printf("Auto Forwarding stopped.\n");
+// else { /* Okay, save it */
+ fprintf(fptr, "%s", fwd);
+// }
+
+ printf("You're mail will be sent to:\n%s\nThank you.\n", fwd);
+ fclose(fptr);
+ return 0;
+}
+
+int do_help(int argc, char **argv)
+{
+ FILE *fp;
+ char fname[80], line[256];
+ struct cmd *cmdp;
+ int i = 0;
+
+ if (*argv[0] == '?') { /* "?" */
+ printf("Commands:\n");
+ for (cmdp = Mailcmds; cmdp->name != NULL; cmdp++) {
+ printf("%s%s", i ? ", " : "", cmdp->name);
+ if (++i == 10) {
+ printf("\n");
+ i = 0;
+ }
+ }
+ if (i) printf("\n");
+ return 0;
+ }
+ strcpy(fname, DATA_AXMAIL_HELP_DIR);
+ if (*argv[0] == 'i') { /* "info" */
+ strcat(fname, "info.hlp");
+ printf("%s - %s\n", VERSION, COPYRIGHT);
+ printf("%s", LICENSE);
+ } else if (argc == 1) { /* "help" */
+ strcat(fname, "help.hlp");
+ } else { /* "help <cmd>" */
+ if (strchr(argv[1], '/') == NULL) {
+ strlwr(argv[1]);
+ strcat(fname, argv[1]);
+ strcat(fname, ".hlp");
+ }
+ }
+ if ((fp = fopen(fname, "r")) == NULL) {
+ if (*argv[0] != 'i')
+ printf("No help for command %s.\n", argv[1] ? argv[1] : "help");
+ return 0;
+ }
+ if (*argv[0] != 'i')
+ printf("Help for command %s:\n", argv[1] ? argv[1] : "help");
+ while (fgets(line, 256, fp) != NULL) {
+ printf("%s", line);
+ }
+ fclose(fp);
+ return 0;
+}
+
+int do_quit(int argc, char **argv)
+{
+ quit(0, 0);
+ return 0;
+}
+
+int do_exit(int argc, char **argv)
+{
+ quit(1, 0);
+ return 0;
+}
+
diff --git a/command.h b/command.h
new file mode 100644
index 0000000..a47486b
--- /dev/null
+++ b/command.h
@@ -0,0 +1,9 @@
+
+/* in command.c */
+extern int do_status(int argc, char **argv);
+extern int do_name(int argc, char **argv);
+extern int do_help(int argc, char **argv);
+extern int do_quit(int argc, char **argv);
+extern int do_exit(int argc, char **argv);
+extern int do_forward(int argc, char **argv);
+/* extern int do_forward(void); */
diff --git a/config.c b/config.c
new file mode 100644
index 0000000..6790261
--- /dev/null
+++ b/config.c
@@ -0,0 +1,285 @@
+
+/* config.c - read configuration */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "config.h"
+#include "defines.h"
+#include "axmail.h"
+#include "utils.h"
+
+char callsign[20];
+char username[20];
+char fullname[31];
+char *homedir; /* User's home directory */
+char *maildir; /* User's mail directory (~/mail) */
+char *mailbox; /* System mailbox (/var/spool/mail/user) */
+char *userbox; /* User's mailbox (~/mbox) */
+char *mailconf; /* User's own axmail configuration */
+
+int local = 0; /* Running with user privileges? */
+
+char *tempMail; /* Temporary files: ~/mail/ax?(-pid-) */
+char *tempNewMail; /* Temporary files: ~/mail/axnew?(-pid-) */
+char *tempEdit;
+char *tempMesg;
+char *tempRcpt;
+
+char *hostname = NULL;
+char *def_shell = NULL;
+char *def_homedir = NULL;
+char *faxgate = NULL;
+
+int mail_allowed = 0;
+int identification = 0;
+
+int autocreate = FALSE;
+int login_allowed = FALSE;
+int first_uid = 400;
+int last_uid = 65535;
+gid_t user_gid = 0;
+
+long IdleTimeout = 900L; /* default to 15 mins */
+
+static int do_allowmail(int, char **);
+static int do_autocreate(int, char **);
+static int do_autogroup(int, char **);
+static int do_first_uid(int, char **);
+static int do_homedir(int, char **);
+static int do_faxgate(int, char **);
+static int do_hostname(int, char **);
+static int do_identification(int, char **);
+static int do_idletimeout(int, char **);
+static int do_loginallowed(int, char **);
+static int do_last_uid(int, char **);
+static int do_shell(int, char **);
+
+static struct cmd cfg_cmds[] = {
+ { "allowmail", do_allowmail },
+ { "autocreate", do_autocreate },
+ { "autogroup", do_autogroup },
+ { "faxgate", do_faxgate },
+ { "first_uid", do_first_uid },
+ { "homedir", do_homedir },
+ { "hostname", do_hostname },
+ { "identification", do_identification },
+ { "idletimeout", do_idletimeout },
+ { "loginallowed", do_loginallowed },
+ { "last_uid", do_last_uid },
+ { "shell", do_shell },
+ { NULL, NULL }
+};
+
+/* ***************************************************************** */
+
+static int do_allowmail(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ if (!strcasecmp(argv[1], "all"))
+ mail_allowed = 0;
+ else if (!strcasecmp(argv[1], "nologin"))
+ mail_allowed = 1;
+ else if (!strcasecmp(argv[1], "passwd"))
+ mail_allowed = 2;
+ else if (!strcasecmp(argv[1], "axhome"))
+ mail_allowed = 3;
+ else
+ return -1;
+ return 0;
+}
+
+static int do_autocreate(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ if (!strcasecmp(argv[1], "yes"))
+ autocreate = 1;
+ else
+ autocreate = 0;
+ return 0;
+}
+
+static int do_autogroup(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+
+ user_gid = atoi(argv[1]);
+
+ if (user_gid == 0) {
+ struct group * gp = getgrnam(argv[1]);
+ if (gp != NULL)
+ user_gid = gp->gr_gid;
+ else {
+ printf("Group %s not found.\n", argv[1]);
+ return -1;
+ }
+ endgrent();
+ }
+
+ if (user_gid == 0) {
+ printf("Default GID for new users must be set and non-zero.\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int do_faxgate(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ faxgate = strdup(argv[1]);
+ return 0;
+}
+
+static int do_first_uid(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ first_uid = atoi(argv[1]);
+ return 0;
+}
+
+static int do_last_uid(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ last_uid = atol(argv[1]);
+ return 0;
+}
+
+static int do_idletimeout(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ IdleTimeout = atol(argv[1]);
+ return 0;
+}
+
+static int do_homedir(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ def_homedir = strdup(argv[1]);
+ return 0;
+}
+
+static int do_hostname(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ hostname = strdup(argv[1]);
+ return 0;
+}
+
+static int do_identification(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ if (!strcasecmp(argv[1], "none"))
+ identification = 0;
+ else if (!strcasecmp(argv[1], "passwd"))
+ identification = 1;
+ else
+ return -1;
+ return 0;
+}
+
+static int do_loginallowed(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ if (!strcasecmp(argv[1], "yes"))
+ login_allowed = 1;
+ else if (!strcasecmp(argv[1], "crazy"))
+ login_allowed = 2;
+ else
+ login_allowed = 0;
+ return 0;
+}
+
+static int do_shell(int argc, char **argv)
+{
+ if (argc < 2)
+ return -1;
+ def_shell = strdup(argv[1]);
+ return 0;
+}
+
+/* ***************************************************************** */
+
+/* Set the temporary file names, paths and such, and make sure
+ they're available for us to use... */
+
+void tinit(void)
+{
+ int pid;
+ char pat[PATHSIZE];
+ struct stat fst;
+
+ umask(077);
+ pid = getpid();
+
+ sprintf(pat, "%s/mail", homedir);
+ maildir = strdup(pat);
+
+ sprintf(pat, "%s/axM%05d", maildir, pid);
+ tempMail = strdup(pat);
+ sprintf(pat, "%s/axnewM%05d", maildir, pid);
+ tempNewMail = strdup(pat);
+ sprintf(pat, "%s/axE%05d", maildir, pid);
+ tempEdit = strdup(pat);
+ sprintf(pat, "%s/axT%05d", maildir, pid);
+ tempMesg = strdup(pat);
+
+ sprintf(pat, "%s/mbox", homedir);
+ userbox = strdup(pat);
+
+ sprintf(pat, "%s%s", DATA_AXMAIL_MAIL_DIR, username);
+ mailbox = strdup(pat);
+
+ sprintf(pat, "%s%s", homedir, CONF_AXMAIL_USER_FILE);
+ mailconf = strdup(pat);
+
+ if (stat(maildir, &fst) < 0) {
+ printf("Creating directory %s...\n", maildir);
+ if (mkdir(maildir, S_IRUSR|S_IWUSR|S_IXUSR))
+ panic("tinit: Cannot create mail directory");
+ }
+}
+
+/* Read configuration */
+
+int read_config(void)
+{
+ FILE *fp;
+ char line[256];
+ int ret, n = 0;
+
+ if ((fp = fopen(CONF_AXMAIL_FILE, "r")) == NULL) {
+ printf("Cannot read axmail.conf\n");
+ return -1;
+ }
+ while (fgets(line, 256, fp) != NULL) {
+ n++;
+ ret = cmdparse(cfg_cmds, line);
+ if (ret == -1)
+ printf("Syntax error in config file at line %d: %s\n", n, line);
+ if (ret < 0) {
+ fclose(fp);
+ return -1;
+ }
+ }
+ fclose(fp);
+ return 0;
+}
+
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..a3f039c
--- /dev/null
+++ b/config.h
@@ -0,0 +1,44 @@
+
+#include <utmp.h>
+#include "defines.h"
+
+extern char callsign[20];
+extern char username[20];
+extern char fullname[31];
+extern char forward[79];
+
+extern char *homedir; /* User's home directory */
+extern char *fwdfile; /* User's .forward file (~/.forward) */
+extern char *maildir; /* User's mail directory (~/mail) */
+extern char *mailbox; /* System mailbox (/var/spool/mail/user) */
+extern char *userbox; /* User's mailbox (~/mbox) */
+extern char *mailconf; /* User's own axmail configuration */
+
+extern int local; /* Running with user privileges? */
+
+extern char *tempMail; /* Temporary files: ~/mail/ax?(-pid-) */
+extern char *tempRcpt; /* Temporary files: return receipt */
+extern char *tempNewMail; /* Temporary files: ~/mail/axnew?(-pid-) */
+extern char *tempEdit;
+extern char *tempMesg;
+
+extern char *faxgate; /* Email of your E-Fax Gateway */
+extern char *hostname;
+extern char *def_shell; /* Default settings for autoaccounts */
+extern char *def_homedir;
+
+extern int mail_allowed, identification, autocreate, login_allowed;
+extern int first_uid, last_uid;
+extern gid_t user_gid;
+extern char mboxname[PATHSIZE];
+extern long IdleTimeout;
+
+struct cmd {
+ char *name;
+ int (*function) (int argc, char **argv);
+};
+
+extern struct cmd Mailcmds[];
+
+extern void tinit(void);
+extern int read_config(void);
diff --git a/copying b/copying
new file mode 100644
index 0000000..dc63aac
--- /dev/null
+++ b/copying
@@ -0,0 +1,340 @@
+
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/defines.h b/defines.h
new file mode 100644
index 0000000..5886d90
--- /dev/null
+++ b/defines.h
@@ -0,0 +1,31 @@
+
+ /*
+ * defines.h - Compile-time configuration
+ */
+
+#define VERSION "axMail-Fax v2.5"
+#define COPYRIGHT "(c) 1996, 1998 Heikki Hannikainen (OH7LZB) <hessu at hes.iki.fi>\nMailbox save support (c) 2003 Marius Petrescu (YO2LOJ) <mpetrescu at online.ro>\nOther modifications (c) 2005, 2006, 2015 by Brian Rogers (N1URO) <n1uro at n1uro.net> "
+#define PROMPT "=> "
+
+#define CONF_AXMAIL_FILE "/usr/local/etc/ax25/axmail.conf"
+#define CONF_AXMAIL_PROF_FILE "/usr/local/etc/ax25/ax25.profile"
+#define CONF_AXMAIL_USER_FILE ".axmailrc"
+#define DATA_AXMAIL_HELP_DIR "/usr/local/var/ax25/axmail/help/"
+#define DATA_AXMAIL_MAIL_DIR "/usr/local/var/spool/mail/"
+#define LOCK_AXMAIL_FILE "/var/lock/axmail"
+#define BIN_AXMAIL_SENDMAIL "/usr/sbin/sendmail"
+
+
+#define FORWARDFILE ".forward"
+#define USERPROFILE ".profile"
+#define PASSWDFILE "/etc/passwd"
+
+#define WELCOME "/usr/local/etc/ax25/welcome.txt"
+
+#define PATHSIZE 1024
+#define LINESIZE 1024 /* Maximum length of a line in a message */
+
+#define TRUE 1
+#define FALSE 0
+
+#define LICENSE "\n This program is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation; either version 2 of the License, or\n (at your option) any later version. Usage may vary based on location.\n\n"
diff --git a/etc/axmail.conf b/etc/axmail.conf
new file mode 100644
index 0000000..72254bc
--- /dev/null
+++ b/etc/axmail.conf
@@ -0,0 +1,53 @@
+# /etc/ax25/axmail.conf - axMail configuration file
+#
+
+# Idle timeout (seconds).
+IdleTimeout 900
+
+# Local hostname.
+HostName <your>.ampr.org
+
+# Who (of those who are listed in /etc/passwd) are allowed to use axmail
+# all : All users who have an account (or have just created one)
+# nologin : Those who have "+" as password (the axmail-only accounts)
+# passwd : Those who have a password set (NOT those with "+" as password)
+# axhome : Those who put all ham home dirs within one branch
+AllowMail all
+
+# Do we ask for a password or rely on the callsign
+# none : Trust the callsign given on command line
+# passwd : Ask for a plaintext password (brrrr...)
+# TODO: MDn authenthication !
+Identification none
+
+#
+# ------ Parameters for automatically created user accounts
+#
+
+# Allow automatic creation of user accounts
+AutoCreate yes
+
+# Automatically created login accounts can login (through telnet, etc)
+# yes : User is prompted for password, when the account is created
+# no : Password is set to "+" (cannot login) (preferred, axmail-only
+# account)
+# crazy : Password is left empty (can login without password)
+LoginAllowed no
+
+# Group name or id for autoaccount
+AutoGroup ax25
+
+# First user id to use for automatically created accounts
+First_uid 2000
+
+# Maximum user id
+Last_uid 2999
+
+# Where to add the home directories for the new users
+HomeDir /home
+
+# User shell
+Shell /bin/false
+
+# Fax Gateway - must be defined without quotes
+FaxGate "your at faxgate.com"
diff --git a/etc/help/autofwd.hlp b/etc/help/autofwd.hlp
new file mode 100644
index 0000000..d2c9438
--- /dev/null
+++ b/etc/help/autofwd.hlp
@@ -0,0 +1,11 @@
+USAGE
+ Autofwd
+
+DESCRIPTION
+ This command will set the system to auto-forward any incoming
+ mail to this address to a "home" axMail-FAX system you would
+ usually use, OR you could set it to forward any mails from
+ this system to any SMTP based system ie: xNOS, internet, etc.
+ Just hitting the enter key will clear your mail forwarding
+ and your incoming mail to this system will be held here for you.
+
diff --git a/etc/help/delete.hlp b/etc/help/delete.hlp
new file mode 100644
index 0000000..94d9bcf
--- /dev/null
+++ b/etc/help/delete.hlp
@@ -0,0 +1,10 @@
+USAGE
+ kill [<message_number>]
+ delete [<message_number>]
+
+DESCRIPTION
+ This command removes specified message from mailbox.
+ If no message number is entered, then command removes
+ last viewed message.
+
+
diff --git a/etc/help/help.hlp b/etc/help/help.hlp
new file mode 100644
index 0000000..603d46b
--- /dev/null
+++ b/etc/help/help.hlp
@@ -0,0 +1,7 @@
+USAGE
+ help [<command>]
+
+DESCRIPTION
+ Gives help for the specified command or this text if no
+ command is specified. Commands can not be abbreviated.
+ Use the "?" command to retrieve a list of available commands.
diff --git a/etc/help/info.hlp b/etc/help/info.hlp
new file mode 100644
index 0000000..9f45a93
--- /dev/null
+++ b/etc/help/info.hlp
@@ -0,0 +1,2 @@
+This is an SMTP mail agent node plug-in for packet radio systems
+using linuxnode or URONode.
diff --git a/etc/help/kill.hlp b/etc/help/kill.hlp
new file mode 100644
index 0000000..94d9bcf
--- /dev/null
+++ b/etc/help/kill.hlp
@@ -0,0 +1,10 @@
+USAGE
+ kill [<message_number>]
+ delete [<message_number>]
+
+DESCRIPTION
+ This command removes specified message from mailbox.
+ If no message number is entered, then command removes
+ last viewed message.
+
+
diff --git a/etc/help/send.hlp b/etc/help/send.hlp
new file mode 100644
index 0000000..d2378fb
--- /dev/null
+++ b/etc/help/send.hlp
@@ -0,0 +1,7 @@
+USAGE
+ send [<mail recipient>]
+
+DESCRIPTION
+ This command sends message. If no mail recipient is specified,
+ then you will be asked.
+
diff --git a/etc/help/sfax.hlp b/etc/help/sfax.hlp
new file mode 100644
index 0000000..64b0eb1
--- /dev/null
+++ b/etc/help/sfax.hlp
@@ -0,0 +1,20 @@
+USAGE
+ sfax
+
+DESCRIPTION
+ This command sends a facsimile. The To: field will be preset for
+ you. You can specify a user but you *must* specify a full phone
+ number to fax to. Ex: n1uro at 14132416644
+
+ Notes: Faxes will send only! You will get a confirmation that your
+ fax was received into the system and another message after the
+ fax was either sent successfully or had issues sending. Faxes
+ will only work within the United States. Sending of faxes
+ elsewhere is a violation of this program.
+
+ IMPORTANT: you *must* include the beginning country code. For
+ the U.S it's 1, for the U.K. it's 011. An example of a properly
+ entered number would be: 12125551212
+
+
+
diff --git a/etc/welcome.txt b/etc/welcome.txt
new file mode 100644
index 0000000..3171913
--- /dev/null
+++ b/etc/welcome.txt
@@ -0,0 +1,11 @@
+Subject: Welcome to axMail v2.5
+
+Welcome to axmail! Your email address
+is listed above the prompt. For further
+assistance, try "?" or email root.
+
+axMail is the first mail client for packet
+that allows it's users the ability to send/receive
+receipts for their mail using just a dumb terminal.
+
+73!
diff --git a/head.c b/head.c
new file mode 100644
index 0000000..88dc58d
--- /dev/null
+++ b/head.c
@@ -0,0 +1,214 @@
+
+/* head.c - parse mail headers.
+ Grabbed from mailx 5.3b, reformatted, hacked and cleaned
+ to compile without warnings by Heikki Hannikainen <hessu at pspt.fi> */
+
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+/*
+ * Mail -- a mail program
+ *
+ * Routines for processing and detecting headlines.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "head.h"
+#include "defines.h"
+
+/*
+ * See if the passed line buffer is a mail header.
+ * Return true if yes. Note the extreme pains to
+ * accomodate all funny formats.
+ */
+
+int ishead(char linebuf[])
+{
+ char *cp;
+ struct headline hl;
+ char parbuf[LINESIZE];
+
+ cp = linebuf;
+ if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' ||
+ *cp++ != ' ')
+ return 0;
+ parse(linebuf, &hl, parbuf);
+ if (hl.l_from == NULL || hl.l_date == NULL) {
+ /* No from or date field */
+ return 0;
+ }
+ if (!isdate(hl.l_date)) {
+ /* Date field not legal date */
+ return 0;
+ }
+ /*
+ * I guess we got it!
+ */
+ return 1;
+}
+
+/*
+ * Split a headline into its useful components.
+ * Copy the line into dynamic string space, then set
+ * pointers into the copied line in the passed headline
+ * structure. Actually, it scans.
+ */
+
+void parse(char line[], struct headline *hl, char pbuf[])
+{
+ char *cp, *sp;
+ char word[LINESIZE];
+
+ hl->l_from = NULL;
+ hl->l_tty = NULL;
+ hl->l_date = NULL;
+ cp = line;
+ sp = pbuf;
+ /*
+ * Skip over "From" first.
+ */
+ cp = nextword(cp, word);
+ cp = nextword(cp, word);
+ if (*word)
+ hl->l_from = copyin(word, &sp);
+ if (cp != NULL && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') {
+ cp = nextword(cp, word);
+ hl->l_tty = copyin(word, &sp);
+ }
+ if (cp != NULL)
+ hl->l_date = copyin(cp, &sp);
+}
+
+/*
+ * Copy the string on the left into the string on the right
+ * and bump the right (reference) string pointer by the length.
+ * Thus, dynamically allocate space in the right string, copying
+ * the left string into it.
+ */
+
+char *copyin(char *src, char **space)
+{
+ char *cp, *top;
+
+ top = cp = *space;
+ while ((*cp++ = *src++))
+ ;
+ *space = cp;
+ return top;
+}
+
+#define L 1 /* A lower case char */
+#define S 2 /* A space */
+#define D 3 /* A digit */
+#define O 4 /* An optional digit or space */
+#define C 5 /* A colon */
+#define N 6 /* A new line */
+#define U 7 /* An upper case char */
+
+char ctypes[] = { U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0 };
+char tmztypes[] = { U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0 };
+
+/*
+ * Match the given string (cp) against the given template (tp).
+ * Return 1 if they match, 0 if they don't
+ */
+
+int cmatch(char *cp, char *tp)
+{
+
+ while (*cp && *tp)
+ switch (*tp++) {
+ case L:
+ if (!islower(*cp++))
+ return 0;
+ break;
+ case U:
+ if (!isupper(*cp++))
+ return 0;
+ break;
+ case S:
+ if (*cp++ != ' ')
+ return 0;
+ break;
+ case D:
+ if (!isdigit(*cp++))
+ return 0;
+ break;
+ case O:
+ if (*cp != ' ' && !isdigit(*cp))
+ return 0;
+ cp++;
+ break;
+ case C:
+ if (*cp++ != ':')
+ return 0;
+ break;
+ case N:
+ if (*cp++ != '\n')
+ return 0;
+ break;
+ }
+ if (*cp || *tp)
+ return 0;
+ return 1;
+}
+
+/*
+ * Test to see if the passed string is a ctime(3) generated
+ * date string as documented in the manual. The template
+ * below is used as the criterion of correctness.
+ * Also, we check for a possible trailing time zone using
+ * the auxtype template.
+ */
+
+int isdate(char date[])
+{
+
+ if (cmatch(date, ctypes))
+ return 1;
+ return cmatch(date, tmztypes);
+}
+
+/*
+ * Collect a liberal (space, tab delimited) word into the word buffer
+ * passed. Also, return a pointer to the next word following that,
+ * or NULL if none follow.
+ */
+
+char *nextword(char *wp, char *wbuf)
+{
+ char c;
+
+ if (wp == NULL) {
+ *wbuf = 0;
+ return NULL;
+ }
+ while ((c = *wp++) && c != ' ' && c != '\t') {
+ *wbuf++ = c;
+ if (c == '"') {
+ while ((c = *wp++) && c != '"')
+ *wbuf++ = c;
+ if (c == '"')
+ *wbuf++ = c;
+ else
+ wp--;
+ }
+ }
+ *wbuf = '\0';
+ for (; c == ' ' || c == '\t'; c = *wp++)
+ ;
+ if (c == 0)
+ return NULL;
+ return (wp - 1);
+}
diff --git a/head.h b/head.h
new file mode 100644
index 0000000..c7e9370
--- /dev/null
+++ b/head.h
@@ -0,0 +1,19 @@
+
+/*
+ * Structure used to return a break down of a head
+ * line (hats off to Bill Joy!)
+ */
+
+struct headline {
+ char *l_from; /* The name of the sender */
+ char *l_tty; /* His tty string (if any) */
+ char *l_date; /* The entire date string */
+};
+
+/* in head.c */
+extern char *nextword(char *wp, char *wbuf);
+extern char *copyin(char *src, char **space);
+extern void parse(char line[], struct headline *hl, char pbuf[]);
+extern int ishead(char linebuf[]);
+extern int isdate(char date[]);
+
diff --git a/lock.c b/lock.c
new file mode 100644
index 0000000..d03b056
--- /dev/null
+++ b/lock.c
@@ -0,0 +1,36 @@
+
+/* lock.c - file locking services */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/file.h>
+
+#include "lock.h"
+#include "utils.h"
+
+/* Lock a file descriptor. */
+
+int lock_fd(int fd)
+{
+ if (flock(fd, LOCK_EX)) {
+ syserr("Can't lock fd\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Unlock a file descriptor. */
+
+int unlock_fd(int fd)
+{
+ if (flock(fd, LOCK_UN)) {
+ syserr("Can't unlockfd\n");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/lock.h b/lock.h
new file mode 100644
index 0000000..e5d71df
--- /dev/null
+++ b/lock.h
@@ -0,0 +1,3 @@
+
+extern int lock_fd(int fd);
+extern int unlock_fd(int fd);
diff --git a/mailcmd.c b/mailcmd.c
new file mode 100644
index 0000000..c3474e9
--- /dev/null
+++ b/mailcmd.c
@@ -0,0 +1,526 @@
+
+/* mailcmd.c - Mail commands */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <syslog.h>
+
+#include "mailcmd.h"
+#include "defines.h"
+#include "config.h"
+#include "mbox.h"
+#include "utils.h"
+
+/* List messages */
+
+void printhead(int i, struct message *m) {
+ char ch = ' ';
+
+ if ((m->m_flag & (MREAD|MNEW)) == MNEW)
+ ch = 'N';
+ if ((m->m_flag & (MREAD|MNEW)) == 0)
+ ch = 'U';
+ if ((m->m_flag & (MDELETED)) == MDELETED)
+ ch = 'K';
+
+ printf("%c%c%4i %25.25s%6li %.39s\n",
+ (current == i+1) ? '>' : ' ',
+ ch, i+1, m->from, m->m_size, m->subj);
+}
+
+int do_list(int argc, char **argv)
+{
+ int i;
+
+ if (!(messages)) {
+ printf("No messages.\n");
+ return 0;
+ }
+
+ printf(" Num From Size Subject\n");
+
+ for (i = 0; i < messages; i++) {
+ printhead(i, &message[i]);
+ }
+
+ return 0;
+}
+
+/* Read a message (xNOS-stylish parameters) */
+
+int do_read(int argc, char **argv)
+{
+ char *myargv[64];
+ int myargc, argsmine;
+ char *tmpbuf;
+ int i;
+ int msg, maxmsg;
+
+ if (!(messages)) {
+ printf("You have no messages.\n");
+ return 0;
+ }
+
+ if (argc > 1) {
+ argsmine = 0;
+ for (i = 1; i < argc; i++)
+ myargv[i] = argv[i];
+ myargc = argc;
+ } else {
+ argsmine = 1;
+ if (current >= messages) {
+ printf("No more messages.\n");
+ return 0;
+ }
+ current++;
+ myargc = 2;
+ myargv[1] = malloc(17);
+ sprintf(myargv[1], "echo");
+ sprintf(myargv[1], "%i", current);
+ }
+
+ for (i = 1; i < myargc; i++) {
+ tmpbuf = strchr(myargv[i], '-');
+ msg = atoi(myargv[i]);
+ if (tmpbuf == NULL)
+ maxmsg = msg;
+ else
+ maxmsg = atoi(++tmpbuf);
+ if (maxmsg < msg) {
+ printf("Bad message number %i.\n", maxmsg);
+ continue;
+ }
+ for (; msg <= maxmsg; msg++) {
+ if (msg < 1 || msg > messages) {
+ printf("There's no message number %i.\n", msg);
+ continue;
+ }
+ readmesg(msg, (!strncmp(argv[0], "v", 1)));
+ printf("\n");
+ if (dot->receipt != NULL) {
+ printf("\aA receipt was asked for. Use the SR command to make one.\n");
+ }
+ }
+ }
+
+ if (argsmine)
+ for (i = 1; i < myargc; i++)
+ free(myargv[i]);
+
+ return 0;
+ if (dot->receipt != NULL) {
+ printf("Receipt is needed\n");
+ return 0;
+ }
+
+}
+
+/* Send a message (perhaps a reply) */
+
+int do_send(int argc, char **argv)
+{
+ FILE *f;
+ FILE *g;
+ char str[LINESIZE + 1];
+ int i;
+
+ int reply = 0;
+
+ if (!strncmp(argv[0], "sr", 2)) {
+ reply = 1;
+ if (argc == 1) {
+ if (current == 0) {
+ printf("No current message to reply to.\n");
+ return 0;
+ }
+ i = current;
+ } else
+ i = atoi(argv[1]);
+
+ i--;
+ if ((i < 0) || (i >= messages)) {
+ printf("There's no message %s.\n", argv[1]);
+ return 0;
+ }
+
+ dot = &message[i];
+ }
+
+ if ((f = fopen(tempMesg, "w")) == NULL) {
+ printf("Could not create temporary file.\n");
+ syslog(LOG_NOTICE, "do_send: Could not create temporary file.\n");
+ return 0;
+ }
+
+ fprintf(f, "From: %s <%s@%s>\n", fullname, username, hostname);
+
+ str[0] = '\0';
+ if (argc != 1) /* Recipient on command line */
+ for (i = 1; i < argc; i++) {
+ if (i > 1)
+ strcat(str, " ");
+ strncat(str, argv[i], LINESIZE - strlen(str));
+ }
+ else {
+ if (reply) {
+ strncpy(str, dot->from, LINESIZE);
+ printf("To: %s\n", str);
+ } else {
+ getstr(str, LINESIZE, "To: ");
+ if (str[0] == '\0') {
+ printf("No recipients, message cancelled.\n");
+ fclose(f);
+ remove(tempMesg);
+ return 0;
+ }
+ }
+ }
+
+ fprintf( f, "To: %s\n", str);
+ fprintf( f, "X-Mailer: %s\n", VERSION );
+ fprintf( f, "X-Origin: Amateur Radio Services\n" );
+ goto prio;;
+
+ /* adding priority receive rule */
+
+prio:
+ getstr(str, LINESIZE, "Is this message emergency or urgent? (y/N/?): ");
+
+ /* try to bullet-proof end-user responces a bit... */
+
+ if (!strcmp(str, "?")) {
+ printf("\nAnswering \"Y\" or \"yes\" here will flag the message as of being highest\n");
+ printf("priority in nature and with most mail client software will present\n");
+ printf("your message as an urgent read communication. By entering \"N\" or \"no\" or\n");
+ printf("by hitting the enter key will send your mail message via normal delivery.\n\n");
+ goto prio;
+ }
+
+ if (!strcasecmp(str, "Y") || !strcasecmp (str, "YES") || !strcasecmp (str, "YE")) {
+ fprintf( f, "X-Priority: 1 (Highest)\n" );
+ }
+ else
+ { fprintf( f,"X-Priority: 3 (Normal)\n" );
+ }
+
+receipt:
+ getstr(str, LINESIZE, "Read receipt requested? (y/N/?): ");
+
+ if (!strcmp(str, "?")) {
+ printf("\nAnswering \"Y\" or \"yes\" here will request a confirmation of \n");
+ printf("your message being opened by the remote user. By entering \"N\" or \"no\" or\n");
+ printf("by hitting the enter key will not request a confirmation receipt.\n\n");
+ goto receipt;
+ }
+
+ if (!strcasecmp(str, "Y") || !strcasecmp (str, "YES") || !strcasecmp (str, "YE")) {
+ fprintf( f, "Disposition-Notification-To: %s <%s@%s>\n", fullname, username, hostname);
+ }
+ else
+ { fprintf( f,"" );
+ }
+
+ if (reply) {
+ if (strncasecmp(dot->subj, "Re: ", 3))
+ snprintf(str, LINESIZE, "Re: %s", dot->subj);
+ else
+ snprintf(str, LINESIZE, "%s", dot->subj);
+ printf("Subject: %s\n", str);
+ } else
+ getstr(str, LINESIZE, "Subject: ");
+
+ fprintf(f, "Subject: %s\n", str);
+
+ if (reply)
+ fprintf(f, "In-Reply-To: %s\n", dot->id);
+
+ printf("Enter message text (end with \"/ex\" or \".\" on a line by itself):\n");
+ fflush(stdout);
+
+cont:
+ do {
+ fgets(str, LINESIZE, stdin);
+ if ( strcmp( str, ".\n") && strcmp( str, "/ex\n")) fputs(str, f);
+ } while (strcmp(str, ".\n") && strcmp(str, "/ex\n"));
+
+retry:
+ getstr(str, LINESIZE, "Deliver (Y/n/c/?): ");
+ if (!strcmp(str, "?")) {
+ printf("Answering \"N\" here will cancel the message. Answering \"C\" will\n");
+ printf("let you continue writing the message. Answering anything else will\n");
+ printf("proceed with delivering the message to the recipient.\n");
+ goto retry;
+ }
+ if (!strcasecmp(str, "c")) {
+ printf("Continue entering message text\n(end with \"/ex\" or \".\" on a line by itself):\n");
+ fflush(stdout);
+ goto cont;
+ }
+
+ if (fclose(f)) {
+ printf("Ouch, could not close temporary file.\n");
+ syslog(LOG_NOTICE, "do_send: Could not close temporary file.\n");
+ return 0;
+ }
+
+ if (strcasecmp(str, "n")) {
+ getstr(str, LINESIZE, "Request a delivery receipt? (y/N): ");
+ if (!strcasecmp(str, "y")) {
+ sprintf(str, "%s -N success,delay,failure -oem -t < %s", BIN_AXMAIL_SENDMAIL, tempMesg);
+ system(str);
+ printf("Message sent, delivery notification activated.\n");
+ } else {
+ sprintf(str, "%s -oem -t < %s", BIN_AXMAIL_SENDMAIL, tempMesg);
+ system(str);
+ printf("Message sent.\n");
+ }
+ } else
+ printf("Message canceled.\n");
+
+ if (remove(tempMesg)) {
+ printf("Ouch, could not remove temporary file.\n");
+ syslog(LOG_NOTICE, "do_send: Could not remove temporary file.\n");
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Kill a message */
+
+int do_kill(int argc, char **argv)
+{
+ int i, msg = 0, cnt = 0;
+ char *myargv[64];
+ int myargc, argsmine;
+
+ if (!(messages)) {
+ printf("You have no messages.\n");
+ return 0;
+ }
+
+ if (argc > 1) {
+ argsmine = 0;
+ for (i = 1; i < argc; i++)
+ myargv[i] = argv[i];
+ myargc = argc;
+ } else {
+ if (current == 0) {
+ printf("No current message to kill.\n");
+ return 0;
+ }
+ argsmine = 1;
+ myargc = 2;
+ myargv[1] = malloc(17);
+ sprintf(myargv[1], "%i", current);
+ }
+
+ for (i = 1; i < myargc; i++) {
+ msg = atoi(myargv[i]) - 1;
+
+ if ((msg < 0) || (msg >= messages)) {
+ printf("There's no message %s.\n", myargv[i]);
+ continue;
+ }
+
+ dot = &message[msg];
+
+ if ((dot->m_flag & MDELETED) == MDELETED) {
+ printf("Message %i is already dead.\n", msg + 1);
+ continue;
+ }
+
+ dot->m_flag |= MDELETED;
+ cnt++;
+ }
+
+ if (cnt == 1) /* GCC warns here, but what the heck! 8-) */
+ printf("Message %i killed.\n", msg + 1);
+ else if (cnt > 1)
+ printf("%i messages killed.\n", cnt);
+
+ if (argsmine)
+ for (i = 1; i < myargc; i++)
+ free(myargv[i]);
+
+ return 0;
+}
+
+/* Unkill a message */
+
+int do_unkill(int argc, char **argv)
+{
+ int i, msg = 0, cnt = 0;
+ char *myargv[64];
+ int myargc, argsmine;
+
+ if (!(messages)) {
+ printf("You have no messages.\n");
+ return 0;
+ }
+
+ if (argc > 1) {
+ argsmine = 0;
+ for (i = 1; i < argc; i++)
+ myargv[i] = argv[i];
+ myargc = argc;
+ } else {
+ if (current == 0) {
+ printf("No current message to unkill.\n");
+ return 0;
+ }
+ argsmine = 1;
+ myargc = 2;
+ myargv[1] = malloc(17);
+ sprintf(myargv[1], "%i", current);
+ }
+
+ for (i = 1; i < myargc; i++) {
+ msg = atoi(myargv[i]) - 1;
+
+ if ((msg < 0) || (msg >= messages)) {
+ printf("There's no message %s.\n", myargv[i]);
+ continue;
+ }
+
+ dot = &message[msg];
+
+ if ((dot->m_flag & MDELETED) != MDELETED) {
+ printf("Message %i is not dead.\n", msg + 1);
+ continue;
+ }
+
+ dot->m_flag ^= (dot->m_flag & MDELETED);
+ cnt++;
+ }
+
+ if (cnt == 1) /* GCC warns here, but what the heck! 8-) */
+ printf("Message %i unkilled.\n", msg + 1);
+ else if (cnt > 1)
+ printf("%i messages unkilled.\n", cnt);
+
+ if (argsmine)
+ for (i = 1; i < myargc; i++)
+ free(myargv[i]);
+
+ return 0;
+}
+
+/* Send a Fax */
+int do_fax(int argc, char **argv)
+{
+ FILE *f;
+ char str[LINESIZE + 1];
+ int i;
+
+ int reply = 0;
+
+ if (!strncmp(argv[0], "sr", 2)) {
+ reply = 1;
+ if (argc == 1) {
+ if (current == 0) {
+ printf("No current message to reply to.\n");
+ return 0;
+ }
+ i = current;
+ } else
+ i = atoi(argv[1]);
+
+ i--;
+ if ((i < 0) || (i >= messages)) {
+ printf("There's no message %s.\n", argv[1]);
+ return 0;
+ }
+
+ dot = &message[i];
+ }
+
+ if ((f = fopen(tempMesg, "w")) == NULL) {
+ printf("Could not create temporary file.\n");
+ syslog(LOG_NOTICE, "do_send: Could not create temporary file.\n");
+ return 0;
+ }
+
+ fprintf(f, "From: %s <%s@%s>\n", fullname, username, hostname);
+
+ str[0] = '\0';
+ if (argc != 1) /* Recipient on command line */
+ for (i = 1; i < argc; i++) {
+ if (i > 1)
+ strcat(str, " ");
+ strncat(str, argv[i], LINESIZE - strlen(str));
+ }
+ else {
+ }
+
+ printf("To: Fax Gateway\n");
+ fprintf( f, "To: %s\n", faxgate );
+ fprintf( f, "X-Mailer: %s\n", VERSION );
+ fprintf( f, "X-Origin: Amateur Radio Services\n" );
+ goto prio;;
+
+ /* adding priority receive rule */
+
+prio:
+/* if (reply) {
+ if (strncasecmp(dot->subj, "Re: ", 3))
+ snprintf(str, LINESIZE, "Re: %s", dot->subj);
+ else
+ snprintf(str, LINESIZE, "%s", dot->subj);
+ printf("Subject: %s\n", str);
+ } else */
+ getstr(str, LINESIZE, "Enter a header <firstname at fullphone Brief note here>\nEx: john at 16195551212 Hi From Packet\nHeader: ");
+
+ fprintf(f, "Subject: %s\n", str);
+
+ if (reply)
+ fprintf(f, "In-Reply-To: %s\n", dot->id);
+
+ printf("Enter fax message (end with \"/ex\" or \".\" on a line by itself):\n");
+ fflush(stdout);
+
+cont:
+ do {
+/* fprintf( f, "X-Mailer: %s\n", VERSION );
+ fprintf( f, "X-Origin: Amateur Radio Services\n" ); */
+ fgets(str, LINESIZE, stdin);
+ if ( strcmp( str, ".\n") && strcmp( str, "/ex\n")) fputs(str, f);
+ } while (strcmp(str, ".\n") && strcmp(str, "/ex\n"));
+
+retry:
+ getstr(str, LINESIZE, "Deliver (Y/n/c/?): ");
+ if (!strcmp(str, "?")) {
+ printf("Answering \"N\" here will cancel the message. Answering \"C\" will\n");
+ printf("let you continue writing the message. Answering anything else will\n");
+ printf("proceed with delivering the message to the recipient.\n");
+ goto retry;
+ }
+ if (!strcasecmp(str, "c")) {
+ printf("Continue entering message text\n(end with \"/ex\" or \".\" on a line by itself):\n");
+ fflush(stdout);
+ goto cont;
+ }
+
+ if (fclose(f)) {
+ printf("Ouch, could not close temporary file.\n");
+ syslog(LOG_NOTICE, "do_send: Could not close temporary file.\n");
+ return 0;
+ }
+
+ if (strcasecmp(str, "n")) {
+ sprintf(str, "%s -oem -t < %s", BIN_AXMAIL_SENDMAIL, tempMesg);
+ system(str);
+ printf("Message sent.\n");
+ } else
+ printf("Message canceled.\n");
+
+ if (remove(tempMesg)) {
+ printf("Ouch, could not remove temporary file.\n");
+ syslog(LOG_NOTICE, "do_send: Could not remove temporary file.\n");
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/mailcmd.h b/mailcmd.h
new file mode 100644
index 0000000..9938a8c
--- /dev/null
+++ b/mailcmd.h
@@ -0,0 +1,9 @@
+
+/* in mailcmd.c */
+extern int do_list(int argc, char **argv);
+extern int do_read(int argc, char **argv);
+extern int do_send(int argc, char **argv);
+extern int do_fax(int argc, char **argv);
+extern int do_kill(int argc, char **argv);
+extern int do_unkill(int argc, char **argv);
+
diff --git a/mbox.c b/mbox.c
new file mode 100644
index 0000000..b1df805
--- /dev/null
+++ b/mbox.c
@@ -0,0 +1,357 @@
+
+/*
+ * mbox.c - Read, parse and write the system mailbox
+ *
+ * Much taken from mailx-5.3b, which is
+ * Copyright (c) 1980 Regents of the University of California.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "mbox.h"
+#include "utils.h"
+#include "defines.h"
+#include "config.h"
+#include "head.h"
+
+FILE *mbox; /* Temporary mailbox in /tmp */
+struct message *message; /* Message list */
+struct message *dot; /* Current message pointer */
+int messages = 0; /* Amount of messages in list */
+int current = 0; /* Current message index */
+int newm = 0; /* New messages */
+
+long sysboxlen = 0; /* Length of the system mailbox at reading */
+ /* It will increase if new arrives */
+
+/* Check if we have this message in the message list yet */
+
+int havemessage(char *id)
+{
+ int i;
+
+ for (i = 0; i < messages; i++) {
+ if (!strcmp(message[i].id, id))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Open a temp file by creating and unlinking.
+ Return the open file descriptor. */
+
+int opentemp(char file[])
+{
+ int f;
+
+ if ((f = open(file, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0)
+ panic("opentemp: could not open file");
+ remove(file);
+ return f;
+}
+
+/* Take the data out of the passed ghost file and toss it into
+ a dynamically allocated message structure. */
+
+void makemessage(FILE *f)
+{
+ int size = (messages + 1) * sizeof (struct message);
+
+ if (message != 0)
+ free((char *) message);
+ if ((message = (struct message *) malloc((unsigned) size)) == 0)
+ panic("Insufficient memory for %d messages", messages);
+ dot = message;
+ size -= sizeof (struct message);
+ fflush(f);
+ lseek(fileno(f), (long) sizeof *message, 0);
+ if (read(fileno(f), (char *) message, size) != size)
+ panic("Message temporary file corrupted");
+ message[messages].m_size = 0;
+ message[messages].m_lines = 0;
+ message[messages].receipt = NULL;
+ message[messages].from = NULL;
+ message[messages].date = NULL;
+ message[messages].subj = NULL;
+ message[messages].id = NULL;
+ fclose(f);
+}
+
+/* Append the passed message descriptor onto the temp file.
+ If the write fails, return 1, else 0 */
+
+void append(struct message *mp, FILE *f)
+{
+ if (fwrite((char *) mp, sizeof *mp, 1, f) != 1)
+ panic("append: Could not append message");
+}
+
+/* Copy mailbox from ~/mail/mbox and /var/spool/mail to /tmp
+ (yo2loj - 13 april 2003) */
+
+int getmail(void)
+{
+ struct stat stb;
+
+ FILE *ibuf;
+ FILE *mestmp;
+
+ char buf[LINESIZE];
+ int count;
+
+ long offset = 0;
+ int inheader = 0;
+ int maybe = 1;
+ char *cp = NULL;
+ char c;
+
+
+ struct message this = { MUSED|MNEW, 0, 0, 0 };
+
+
+ if ((mbox = fopen(tempMail, "w")) == NULL)
+ panic("getmail: Could not create temporary file");
+
+
+ if ((ibuf = fopen(userbox, "r")) == NULL) goto sysbox;
+
+ if (fstat(fileno(ibuf), &stb) < 0) {
+ printf("Ouch, could not fstat() mailbox.\n");
+ syslog(LOG_NOTICE, "getmail: Could not fstat()");
+ fclose(ibuf);
+ goto sysbox;;
+ }
+
+ switch (stb.st_mode & S_IFMT) {
+ case S_IFREG: /* Good, a regular file */
+ break;
+ default: /* Yuck, i won't eat THAT! */
+ fclose(ibuf);
+ goto sysbox;
+ }
+
+ if (stb.st_size == 0) { /* Zero-sized mailbox? */
+ fclose(ibuf);
+ goto sysbox;;
+ }
+
+ /* copy old read mail */
+
+ while (fgets(buf, LINESIZE, ibuf) != NULL) {
+ count = strlen(buf);
+ fwrite(buf, sizeof *buf, count, mbox);
+ if (ferror(mbox))
+ panic("getmail: Could not write temporary file");
+ }
+
+ fclose(ibuf);
+
+sysbox:
+ if ((ibuf = fopen(mailbox, "r")) == NULL) goto rdexit;
+
+ if (fstat(fileno(ibuf), &stb) < 0) {
+ printf("Ouch, could not fstat() mailbox.\n");
+ syslog(LOG_NOTICE, "getmail: Could not fstat()");
+ fclose(ibuf);
+ goto rdexit;
+ }
+
+ switch (stb.st_mode & S_IFMT) {
+ case S_IFREG: /* Good, a regular file */
+ break;
+ default: /* Yuck, i won't eat THAT! */
+ fclose(ibuf);
+ goto rdexit;
+ }
+
+ if (stb.st_size == 0) { /* Zero-sized mailbox? */
+ fclose(ibuf);
+ goto rdexit;
+ }
+
+ /* copy unread and new mail */
+
+ while (fgets(buf, LINESIZE, ibuf) != NULL) {
+ count = strlen(buf);
+ fwrite(buf, sizeof *buf, count, mbox);
+ sysboxlen += count;
+ if (ferror(mbox))
+ panic("getmail: Could not write temporary file");
+ }
+
+ fclose(ibuf);
+
+rdexit:
+ fclose(mbox); /* all mail is now in temp file - digest it! */
+
+ if ((c = opentemp(tempMesg)) < 0)
+ exit(1);
+
+ if ((mestmp = fdopen(c, "r+")) == NULL)
+ panic("getmail: Could not open temporary file");
+
+ if ((mbox = fopen(tempMail, "r")) == NULL)
+ panic("getmail: Could not open temporary file");
+
+
+ for (;;) {
+ if (fgets(buf, LINESIZE, mbox) == NULL) {
+ /* End of file */
+ append(&this, mestmp);
+ makemessage(mestmp);
+ if (fclose(mbox))
+ panic("getmail: Could not close temporary mailbox");
+ return 0;
+ }
+ count = strlen(buf);
+ buf[count - 1] = '\0';
+ if (maybe && buf[0] == 'F' && ishead(buf)) {
+ messages++;
+ newm++;
+ append(&this, mestmp);
+ this.m_flag = MUSED|MNEW;
+ this.m_size = 0;
+ this.m_lines = 0;
+ this.m_offset = offset;
+ this.subj = NULL;
+ this.from = NULL;
+ this.date = NULL;
+ this.id = NULL;
+ inheader = 1;
+ } else if (buf[0] == 0) {
+ inheader = 0;
+ } else if (inheader) {
+ if (!strncasecmp(buf, "Status: ", 8)) {
+ cp = &buf[8];
+ if (strchr(cp, 'R') != NULL)
+ this.m_flag |= MREAD;
+ if (strchr(cp, 'O') != NULL) {
+ this.m_flag &= ~MNEW;
+ newm--;
+ }
+ }
+
+ if ((!strncasecmp(buf, "Disposition-Notification-To:", 28)) && (this.receipt == NULL)) {
+ cp = &buf[28];
+ while ((*cp) && (isspace(*cp)))
+ cp++;
+ this.receipt = strdup(cp);
+ }
+
+ if ((!strncasecmp(buf, "Subject:", 8)) && (this.subj == NULL)) {
+ cp = &buf[8];
+ while ((*cp) && (isspace(*cp)))
+ cp++;
+ this.subj = strdup(cp);
+ }
+
+ if ((!strncasecmp(buf, "From:", 5)) && (this.from == NULL)) {
+ cp = &buf[5];
+ while ((*cp) && (isspace(*cp)))
+ cp++;
+ this.from = strdup(cp);
+ }
+
+ if ((!strncasecmp(buf, "Date:", 5)) && (this.date == NULL)) {
+ cp = &buf[5];
+ while ((*cp) && (isspace(*cp)))
+ cp++;
+ this.date = strdup(cp);
+ }
+
+ if ((!strncasecmp(buf, "Message-ID:", 11)) && (this.id == NULL)) {
+ cp = &buf[11];
+ while ((*cp) && (isspace(*cp)))
+ cp++;
+ this.id = strdup(cp);
+ }
+ }
+ offset += count;
+ this.m_size += count;
+ this.m_lines++;
+ maybe = buf[0] == 0;
+
+ }
+
+
+ return 0;
+}
+
+/* Read a message */
+
+int readmesg(int msg, int verbose)
+{
+ int i, line = 0;
+ int inhdr = 1;
+ char buf[LINESIZE];
+
+ if ((msg < 1) || (msg > messages)) {
+ printf("There's no message %i.\n", msg);
+ return -1;
+ }
+
+ if ((mbox = fopen(tempMail, "r")) == NULL) {
+ printf("Could not open temporary mailbox.\n");
+ return -1;
+ }
+
+ i = msg - 1;
+ dot = &message[i];
+
+ if (fseek(mbox, dot->m_offset, SEEK_SET)) {
+ printf("readmesg: Could not fseek to message %i.\n", msg);
+ return -1;
+ }
+
+ current = msg;
+
+ printf("Message %i:%s%s%s\n", msg,
+ ((dot->m_flag & (MREAD|MNEW)) == MNEW) ? " (New)" : "",
+ ((dot->m_flag & (MREAD|MNEW)) == 0) ? " (Unread)": "",
+ ((dot->m_flag & (MDELETED)) == MDELETED) ? " (Deleted)" : ""
+ );
+
+ dot->m_flag |= MREAD;
+ dot->m_flag ^= (dot->m_flag & MNEW);
+
+ for (;;) {
+ if (fgets(buf, LINESIZE, mbox) == NULL) {
+ /* End of file */
+ fclose(mbox);
+ return 0;
+ }
+ line++;
+ if (inhdr) {
+ /* Headers */
+ if (((verbose) && (line != 1) && (strncasecmp(buf, "Status: ", 8)) && (strncasecmp(buf, "X-Status: ", 10)) ) ||
+ (!strncasecmp(buf, "Date:", 5)) ||
+ (!strncasecmp(buf, "From:", 5)) ||
+ (!strncasecmp(buf, "To:", 3)) ||
+ (!strncasecmp(buf, "Cc:", 3)) ||
+ (!strncasecmp(buf, "Subject:", 8)))
+ printf("%s", buf);
+
+ if (!strcmp("\n", buf)) {
+ inhdr = 0;
+ }
+ } else {
+ /* Data */
+ if (line == dot->m_lines) {
+ fclose(mbox);
+ return 0;
+ }
+ printf("%s", buf);
+ }
+
+ }
+ return 0;
+
+}
diff --git a/mbox.h b/mbox.h
new file mode 100644
index 0000000..c3d916a
--- /dev/null
+++ b/mbox.h
@@ -0,0 +1,46 @@
+/*
+ * flag bits.
+ */
+
+#define MUSED (1<<0) /* entry is used, but this bit isn't */
+#define MDELETED (1<<1) /* entry has been deleted */
+#define MSAVED (1<<2) /* entry has been saved */
+#define MTOUCH (1<<3) /* entry has been noticed */
+#define MPRESERVE (1<<4) /* keep entry in sys mailbox */
+#define MMARK (1<<5) /* message is marked! */
+#define MODIFY (1<<6) /* message has been modified */
+#define MNEW (1<<7) /* message has never been seen */
+#define MREAD (1<<8) /* message has been read sometime. */
+#define MSTATUS (1<<9) /* message status has changed */
+
+/*
+ * Structure used in the message list
+ */
+
+struct message {
+ short m_flag; /* flags, see below */
+ long m_offset; /* offset of message */
+ long m_size; /* Bytes in the message */
+ short m_lines; /* Lines in the message */
+ char *receipt; /* Receipt request */
+ char *notify; /* Delivery notify */
+ char *from; /* From */
+ char *date; /* Date string */
+ char *subj; /* Subject line */
+ char *id; /* Message ID */
+ char *whoti; /* Who to send a fax to */
+ char *phone; /* Phone to fax */
+ char *note; /* Note for fax cover */
+};
+
+extern FILE *mbox; /* Temporary mailbox in /tmp */
+extern struct message *message; /* Message list */
+extern struct message *dot; /* Current message pointer */
+extern int messages; /* Amount of messages in list */
+extern int current; /* Current message index */
+extern int newm; /* New messages */
+
+extern long sysboxlen; /* System mailbox length at start */
+
+extern int getmail(void);
+extern int readmesg(int msg, int verbose);
diff --git a/quit.c b/quit.c
new file mode 100644
index 0000000..ff46a1a
--- /dev/null
+++ b/quit.c
@@ -0,0 +1,250 @@
+
+/* quit.c - clean things up on exit. */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "utils.h"
+#include "quit.h"
+#include "config.h"
+#include "lock.h"
+#include "mbox.h"
+
+/* Remove a temporary file, if it exists */
+
+void cleartmp(char *fname)
+{
+ struct stat fst;
+
+ if (!stat(fname, &fst))
+ if (remove(fname))
+ printf("Ouch, couldn't remove %s.\n", fname);
+}
+
+/* Update system and user mailbox
+ (yo2loj - 13 april 2003) */
+
+int save_mbox(void)
+{
+ FILE *mb;
+ FILE *nm;
+ FILE *ub;
+ FILE *tmp;
+ FILE *dest;
+
+ long mblen=0;
+ int havenew = 0;
+
+ char buf[LINESIZE];
+ int count;
+
+ int i, line;
+ int inhdr;
+ char *status;
+ int hasstatus;
+
+ mb = fopen(mailbox, "r");
+ if (lock_fd(fileno(mb)))
+ return -1;
+
+ fseek(mb, 0, SEEK_END);
+ mblen = ftell(mb);
+
+ if (mblen < sysboxlen) {
+ printf("Mailbox changed by another program. Mailbox not saved.");
+ unlock_fd(fileno(mb));
+ fclose(mb);
+ return -1;
+ }
+
+ if (mblen > sysboxlen) {
+ printf("New mail has arrived.\n");
+ havenew = 1;
+
+ /* copy new mail to a temp file, will append to system mailbox later */
+
+ if ((nm = fopen(tempNewMail, "w+")) == NULL)
+ panic("save_mbox: Could not create temporary file");
+
+ fseek(mb, sysboxlen, SEEK_SET);
+
+ while (fgets(buf, LINESIZE, mb) != NULL) {
+ count = strlen(buf);
+ fwrite(buf, sizeof *buf, count, nm);
+ if (ferror(nm))
+ panic("save_mbox: Could not write temporary file");
+ }
+
+ }
+
+ if ((tmp = fopen(tempMail, "r")) == NULL)
+ panic("save_mbox: Could not open temporary mail file");
+
+ if (freopen(mailbox, "w", mb) == NULL)
+ panic("save_mbox: Could not open system mailbox for writing");
+
+ if ((ub = fopen(userbox, "w")) == NULL) {
+ /* error on user mailbox,
+ dump all to the system mailbox as last resort */
+
+ while (fgets(buf, LINESIZE, tmp) != NULL) {
+ count = strlen(buf);
+ fwrite(buf, sizeof *buf, count, mb);
+ if (ferror(mb))
+ panic("save_mbox: Could not write to system mailbox.");
+ }
+ fclose(tmp);
+ if (havenew) {
+ fseek(nm, 0, SEEK_SET);
+ while (fgets(buf, LINESIZE, nm) != NULL) {
+ count = strlen(buf);
+ fwrite(buf, sizeof *buf, count, mb);
+ if (ferror(mb))
+ panic("save_mbox: Could not write to system mailbox.");
+ }
+ fclose(nm);
+ }
+ unlock_fd(fileno(mb));
+ fclose(mb);
+ printf("Could not open user mailbox, dumping to system mailbox\n");
+ return -1;
+ }
+
+ /*
+ we have all processed messages in tmp and
+ any newly arrived (if any) in nm.
+ System mailbox is locked, empty and opened for write (mb),
+ User Mailbox is empty and opened for writing (ub).
+
+ - read message go to ~/mbox with status RO
+ - not read go back to system mailbox with status O
+ - deleted are purged
+ - any arrived go to system mailbox as they are
+ */
+
+ for (i=0; i<messages; i++) {
+ dot = &message[i];
+ if (fseek(tmp, dot->m_offset, SEEK_SET)) {
+ printf("save_mbox: Could not find message %i.\n", i);
+ continue;
+ }
+
+ if (dot->m_flag & MDELETED) {
+ dest = NULL;
+ status = NULL;
+ }
+ else if (dot->m_flag & MREAD) {
+ dest = mb;
+ status = "RO";
+ }
+ else if (dot->m_flag & MNEW) {
+ dest = mb;
+ status = "O";
+ }
+ else {
+ dest = mb;
+ status = NULL;
+ }
+
+ line = 0;
+ hasstatus = 0;
+ inhdr = 1;
+
+ for (;;) {
+ if (!dest) break;
+ if (fgets(buf, LINESIZE, tmp) == NULL) {
+ /* End of file */
+ break;
+ }
+ line ++;
+ if (inhdr) {
+ /* Header */
+ if (!strncasecmp(buf, "Status: ", 8)) {
+ hasstatus = 1;
+ if (status) sprintf(buf, "Status: %s\n", status);
+ } else if (!strcmp("\n", buf)) {
+ inhdr = 0;
+ if (!hasstatus) {
+ if (status) sprintf(buf, "Status: %s\n", status);
+ fwrite(buf, sizeof *buf, strlen(buf), dest);
+ }
+ strcpy(buf, "\n");
+ }
+ } else {
+ /* Data */
+ if (line == dot->m_lines + 1) break;
+ }
+ fwrite(buf, sizeof *buf, strlen(buf), dest);
+ }
+ }
+
+ fclose(tmp);
+
+ if (havenew) {
+ /* append the newly arrived mail */
+ fseek(nm, 0, SEEK_SET);
+ freopen(mailbox, "a+", mb);
+ while (fgets(buf, LINESIZE, nm) != NULL) {
+ count = strlen(buf);
+ fwrite(buf, sizeof *buf, count, mb);
+ if (ferror(mb))
+ panic("save_mbox: Could not write to system mailbox.");
+ }
+
+ fclose(nm);
+ }
+
+ unlock_fd(fileno(mb));
+ fclose(mb);
+ fclose(ub);
+
+ return 0;
+}
+
+/* On quit without save: check and announce if new mail has arrived */
+
+int chk_new_msg(void)
+{
+ FILE *mb;
+ long mblen=0;
+
+ mb = fopen(mailbox, "r");
+ if (lock_fd(fileno(mb)))
+ return -1;
+
+ fseek(mb, 0, SEEK_END);
+ mblen = ftell(mb);
+
+ if (mblen != sysboxlen) printf("New mail has arrived.\n");
+
+ unlock_fd(fileno(mb));
+ fclose(mb);
+
+ return 0;
+}
+
+/* quit. */
+
+void quit(int save, int code)
+{
+ if (save) {
+ printf("Exiting, saving changes in mailbox.\n");
+ } else
+ printf("Cancelling changes, mailbox not changed.\n");
+ if (save) {
+ save_mbox();
+ }
+ else
+ chk_new_msg();
+ printf("Bye %s! from axMail@%s.\n", username, hostname);
+ cleartmp(tempMail);
+ cleartmp(tempNewMail);
+ cleartmp(tempEdit);
+ cleartmp(tempMesg);
+
+ exit(code);
+}
+
diff --git a/quit.h b/quit.h
new file mode 100644
index 0000000..344ea1b
--- /dev/null
+++ b/quit.h
@@ -0,0 +1,2 @@
+
+extern void quit(int save, int code);
diff --git a/setpwnam.c b/setpwnam.c
new file mode 100644
index 0000000..1952ecd
--- /dev/null
+++ b/setpwnam.c
@@ -0,0 +1,212 @@
+/* setpwnam.c edit an entry in a password database. */
+
+/* because I use getpwent(), putpwent(), etc... */
+#define _SVID_SOURCE
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/resource.h>
+#ifdef BSD43
+#include <sys/file.h>
+#endif
+#include <paths.h>
+
+#include "setpwnam.h"
+
+extern int errno;
+
+typedef int boolean;
+#define false 0
+#define true 1
+
+#define PASSWD_FILE _PATH_PASSWD
+#define PTMP_FILE _PATH_PTMP
+#define PTMPTMP_FILE _PATH_PTMPTMP
+
+static int copy_pwd (struct passwd *src, struct passwd *dest);
+static char *xstrdup (char *str);
+static void pw_init(void);
+
+/*
+ * setpwnam () --
+ * takes a struct passwd in which every field is filled in and valid.
+ * If the given username exists in the passwd file, his entry is
+ * replaced with the given entry.
+ */
+int setpwnam (struct passwd *pwd)
+{
+ FILE *fp;
+ int x, save_errno, fd, ret;
+ struct passwd *entry;
+ boolean found;
+ struct passwd spwd;
+ int oldumask;
+
+ /* getpwent() returns a pointer to a static buffer.
+ * "pwd" might have some from getpwent(), so we have to copy it to
+ * some other buffer before calling getpwent().
+ */
+ if (copy_pwd (pwd, &spwd) < 0)
+ return (-1);
+
+ oldumask = umask(0); /* Create with exact permissions */
+ pw_init();
+
+ /* sanity check */
+ for (x = 0; x < 3; x++) {
+ if (x > 0) sleep (1);
+ fd = open (PTMPTMP_FILE, O_WRONLY|O_CREAT, 0644);
+ if(fd == -1) {
+ perror(PTMPTMP_FILE);
+ umask(oldumask);
+ return (-1);
+ }
+ ret = link(PTMPTMP_FILE, PTMP_FILE);
+ unlink(PTMPTMP_FILE);
+ if(ret == -1)
+ close(fd);
+ else
+ break;
+ }
+
+ umask(oldumask);
+ if (ret == -1) return (-1);
+
+ /* ptmp should be owned by root.root or root.wheel */
+ if (chown (PTMP_FILE, (uid_t) 0, (gid_t) 0) < 0)
+ perror ("chown");
+
+ /* open ptmp for writing and passwd for reading */
+ fp = fdopen (fd, "w");
+ if (! fp) goto fail;
+
+ setpwent ();
+
+ /* parse the passwd file */
+ found = false;
+ while ((entry = getpwent ()) != NULL) {
+ if (! strcmp (spwd.pw_name, entry->pw_name)) {
+ entry = &spwd;
+ found = true;
+ }
+ if (putpwent (entry, fp) < 0) goto fail;
+ }
+ if (fclose (fp) < 0) goto fail;
+ close (fd);
+ endpwent ();
+
+ if (! found) {
+ errno = ENOENT; /* give me something better */
+ goto fail;
+ }
+
+ /* we don't care if we can't remove the backup file */
+ unlink (PASSWD_FILE".OLD");
+ /* we don't care if we can't create the backup file */
+ link (PASSWD_FILE, PASSWD_FILE".OLD");
+ /* we DO care if we can't rename to the passwd file */
+ if (rename (PTMP_FILE, PASSWD_FILE) < 0)
+ goto fail;
+ /* finally: success */
+ return 0;
+
+ fail:
+ save_errno = errno;
+ if (fp) fclose (fp);
+ if (fd >= 0) close (fd);
+ endpwent ();
+ unlink (PTMP_FILE);
+ errno = save_errno;
+ return (-1);
+}
+
+#define memzero(ptr, size) memset((char *) ptr, 0, size)
+static int failed;
+
+static int copy_pwd (struct passwd *src, struct passwd *dest)
+{
+ /* this routine destroys abstraction barriers. it's not portable
+ * across systems, or even across different versions of the C library
+ * on a given system. it's dangerous and evil and wrong and I dispise
+ * getpwent() for forcing me to write this.
+ */
+ failed = 0;
+ memzero (dest, sizeof (struct passwd));
+ dest->pw_name = xstrdup (src->pw_name);
+ dest->pw_passwd = xstrdup (src->pw_passwd);
+ dest->pw_uid = src->pw_uid;
+ dest->pw_gid = src->pw_gid;
+ dest->pw_gecos = xstrdup (src->pw_gecos);
+ dest->pw_dir = xstrdup (src->pw_dir);
+ dest->pw_shell = xstrdup (src->pw_shell);
+ return (failed);
+}
+
+static char *xstrdup (char *str)
+{
+ char *dup;
+
+ if (! str)
+ return NULL;
+ dup = (char *) malloc (strlen (str) + 1);
+ if (! dup) {
+ failed = -1;
+ return NULL;
+ }
+ strcpy (dup, str);
+ return dup;
+}
+
+#ifdef NO_PUTPWENT
+
+int putpwent (const struct passwd *p, FILE *stream)
+{
+ if (p == NULL || stream == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (fprintf (stream, "%s:%s:%u:%u:%s:%s:%s\n",
+ p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid,
+ p->pw_gecos, p->pw_dir, p->pw_shell) < 0)
+ return (-1);
+ return(0);
+}
+
+#endif
+
+static void
+pw_init()
+{
+ struct rlimit rlim;
+
+ /* Unlimited resource limits. */
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ (void)setrlimit(RLIMIT_CPU, &rlim);
+ (void)setrlimit(RLIMIT_FSIZE, &rlim);
+ (void)setrlimit(RLIMIT_STACK, &rlim);
+ (void)setrlimit(RLIMIT_DATA, &rlim);
+ (void)setrlimit(RLIMIT_RSS, &rlim);
+
+ /* Don't drop core (not really necessary, but GP's). */
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ (void)setrlimit(RLIMIT_CORE, &rlim);
+
+ /* Turn off signals. */
+ (void)signal(SIGALRM, SIG_IGN);
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGPIPE, SIGQUIT);
+ (void)signal(SIGQUIT, SIG_IGN);
+ (void)signal(SIGTERM, SIG_IGN);
+ (void)signal(SIGTSTP, SIG_IGN);
+ (void)signal(SIGTTOU, SIG_IGN);
+
+ /* Create with exact permissions. */
+ (void)umask(0);
+}
diff --git a/setpwnam.h b/setpwnam.h
new file mode 100644
index 0000000..2c37cc2
--- /dev/null
+++ b/setpwnam.h
@@ -0,0 +1,5 @@
+
+#include <pwd.h>
+
+extern int setpwnam (struct passwd *pwd);
+
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..2f3ee43
--- /dev/null
+++ b/utils.c
@@ -0,0 +1,167 @@
+
+/* utils.c - common utilities */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <errno.h>
+
+#include "utils.h"
+#include "mbox.h"
+#include "config.h"
+
+//extern int sys_nerr;
+
+/* Send the prompt */
+
+void prompt(void)
+{
+ printf("%s@%s\nCurrent message %i of %i\n=> ", callsign, hostname, current, messages);
+}
+
+/* Prompt for email forwarding */
+void getaddy(char *forward)
+{
+ char email[79];
+ getstr(email, 79, "What email address do you want to autoforward mail to? This must be a full\nvalid email address. Example: n1uro at n1uro.com or just hit ENTER to clear.\n");
+ strcpy(forward, email);
+}
+
+/* Prompt for name */
+
+void getname(char *uname)
+{
+ char nam[81];
+
+rename:
+ getstr(nam, 80, "Enter your name (? for help): ");
+
+ if (!strcmp(nam, "?")) {
+ printf("The name entered will be used in the From: header of the messages you send.\n");
+ printf("It will also be shown in finger queries and a number of other places.\n");
+ printf("It is usually set to your full name, but you may also use a nickname\n");
+ printf("your friends know.\n");
+ goto rename;
+ }
+
+ if (strlen(nam) > 30) {
+ printf("The length of the name is limited to 30 characters.\n");
+ goto rename;
+ }
+
+ if (anyof(nam, "=<>()|:;!\\\",")) {
+ printf("Characters = < > ( ) | : ; ! \\ \" , are not allowed.\n");
+ goto rename;
+ }
+
+ if (anycntrls(nam)) {
+ printf("Control characters are not allowed.\n");
+ goto rename;
+ }
+
+ strcpy(uname, nam);
+}
+
+/* Get a string from the user, with maximum length limit */
+
+void getstr(char *str, int len, char *prompt)
+{
+ char *p;
+
+ printf("%s", prompt);
+ fflush(stdout);
+ fgets(str, len, stdin);
+
+ /* Strip CR */
+ p = strchr(str, '\n');
+ if (p != NULL)
+ strcpy(p, "");
+
+}
+
+/* Convert a string to upper case */
+
+char *strupr(char *s)
+{
+ char *p;
+
+ if (s == NULL)
+ return NULL;
+
+ for (p = s; *p != '\0'; p++)
+ *p = toupper(*p);
+
+ return s;
+}
+
+/* Convert a string to lower case */
+
+char *strlwr(char *s)
+{
+ char *p;
+
+ if (s == NULL)
+ return NULL;
+
+ for (p = s; *p != '\0'; p++)
+ *p = tolower(*p);
+
+ return s;
+}
+
+/* Check if any of the characters in the two strings match. */
+
+int anyof(char *s1, char *s2)
+{
+ while (*s1)
+ if (index(s2, *s1++))
+ return 1;
+ return 0;
+}
+
+/* Check if there are any control characters in there. */
+
+int anycntrls(char *s1)
+{
+ while (*s1)
+ if (iscntrl(*s1++))
+ return 1;
+ return 0;
+}
+
+/* Crash, log the reason */
+
+void panic(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ putchar('\n');
+ syslog(LOG_NOTICE, fmt, args);
+ va_end(args);
+
+ exit(1);
+}
+
+/* Report an error returned from a system call. */
+
+
+void syserr(const char *fmt, ...)
+{
+ int e = errno;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+
+/* routine changed by VE3TOK */
+ printf("Error number: %d\n", e);
+ perror("The following error occured: ");
+
+}
+
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..183113c
--- /dev/null
+++ b/utils.h
@@ -0,0 +1,15 @@
+
+extern void prompt(void);
+
+extern void getname(char *uname);
+extern void getstr(char *str, int len, char *prompt);
+
+extern char *strupr(char *s);
+extern char *strlwr(char *s);
+extern int anyof(char *s1, char *s2);
+extern int anycntrls(char *s1);
+
+extern void panic(const char *fmt, ...);
+extern void syserr(const char *fmt, ...);
+/* n1uro */
+char callsign[20];
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/axmail.git
More information about the pkg-hamradio-commits
mailing list