pax_global_header00006660000000000000000000000064125772322610014521gustar00rootroot0000000000000052 comment=4e24dd9ccceeb4d0158640e8748de5e45903fd89 axmail-2.5/000077500000000000000000000000001257723226100126425ustar00rootroot00000000000000axmail-2.5/FAQ000066400000000000000000000133511257723226100131770ustar00rootroot00000000000000axMail - 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: 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* - Qmail*** - * - 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@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 axmail-2.5/INSTALL000066400000000000000000000060701257723226100136760ustar00rootroot00000000000000axMail v2.2 - an SMTP mailbox for the various linux node frontends. Current author: Brian Rogers (N1URO) Past author: Marius Petrescu (YO2LOJ) Creator: Heikki Hannikainen (OH7LZB) Additional Submissions: Stefano (IW3IJQ) 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! axmail-2.5/LICENSE000066400000000000000000000430761257723226100136610ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. axmail-2.5/Makefile000066400000000000000000000027611257723226100143100ustar00rootroot00000000000000all: 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 axmail-2.5/README000066400000000000000000000367401257723226100135340ustar00rootroot00000000000000axMail - 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) 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) 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) 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) 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. - 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) Changes: - Made some maintenance changes, but forgot to log them in here. axmail v2.1.1 Updated 30 October, 2014 by Brian Rogers (N1URO) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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/ 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) 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@n1uro.#cct.ct.usa.noam] ftp://ftp.n1uro.net/packet axmail-2.5/UPGRADING000066400000000000000000000003751257723226100141120ustar00rootroot00000000000000If 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. axmail-2.5/adduser.c000066400000000000000000000072631257723226100144450ustar00rootroot00000000000000 /* adduser.c - create an user account (yecch) */ #include #include #include #include #include #include #include #include #include #include #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; } axmail-2.5/adduser.h000066400000000000000000000000451257723226100144410ustar00rootroot00000000000000 extern int new_user(char *newuser); axmail-2.5/axmail.c000066400000000000000000000136511257723226100142670ustar00rootroot00000000000000/* axmail.c - The command parser and main function */ #include #include #include #include #include #include #include #include #include #include #include #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); } } axmail-2.5/axmail.h000066400000000000000000000001471257723226100142700ustar00rootroot00000000000000 extern int parse_args(char *argv[],char *cmd); extern int cmdparse(struct cmd *cmds, char *cmdline); axmail-2.5/command.c000066400000000000000000000056141257723226100144320ustar00rootroot00000000000000/* command.c - Commands which have nothing to do with mail... */ #include #include #include #include #include #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 " */ 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; } axmail-2.5/command.h000066400000000000000000000004771257723226100144410ustar00rootroot00000000000000 /* 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); */ axmail-2.5/config.c000066400000000000000000000134551257723226100142630ustar00rootroot00000000000000 /* config.c - read configuration */ #include #include #include #include #include #include #include #include #include #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; } axmail-2.5/config.h000066400000000000000000000024421257723226100142620ustar00rootroot00000000000000 #include #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); axmail-2.5/copying000066400000000000000000000430771257723226100142500ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. axmail-2.5/defines.h000066400000000000000000000024441257723226100144340ustar00rootroot00000000000000 /* * defines.h - Compile-time configuration */ #define VERSION "axMail-Fax v2.5" #define COPYRIGHT "(c) 1996, 1998 Heikki Hannikainen (OH7LZB) \nMailbox save support (c) 2003 Marius Petrescu (YO2LOJ) \nOther modifications (c) 2005, 2006, 2015 by Brian Rogers (N1URO) " #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" axmail-2.5/etc/000077500000000000000000000000001257723226100134155ustar00rootroot00000000000000axmail-2.5/etc/axmail.conf000066400000000000000000000027371257723226100155500ustar00rootroot00000000000000# /etc/ax25/axmail.conf - axMail configuration file # # Idle timeout (seconds). IdleTimeout 900 # Local hostname. HostName .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@faxgate.com" axmail-2.5/etc/help/000077500000000000000000000000001257723226100143455ustar00rootroot00000000000000axmail-2.5/etc/help/autofwd.hlp000066400000000000000000000006321257723226100165240ustar00rootroot00000000000000USAGE 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. axmail-2.5/etc/help/delete.hlp000066400000000000000000000003771257723226100163230ustar00rootroot00000000000000USAGE kill [] delete [] DESCRIPTION This command removes specified message from mailbox. If no message number is entered, then command removes last viewed message. axmail-2.5/etc/help/help.hlp000066400000000000000000000003611257723226100160020ustar00rootroot00000000000000USAGE help [] 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. axmail-2.5/etc/help/info.hlp000066400000000000000000000001351257723226100160040ustar00rootroot00000000000000This is an SMTP mail agent node plug-in for packet radio systems using linuxnode or URONode. axmail-2.5/etc/help/kill.hlp000066400000000000000000000003771257723226100160140ustar00rootroot00000000000000USAGE kill [] delete [] DESCRIPTION This command removes specified message from mailbox. If no message number is entered, then command removes last viewed message. axmail-2.5/etc/help/send.hlp000066400000000000000000000002331257723226100160010ustar00rootroot00000000000000USAGE send [] DESCRIPTION This command sends message. If no mail recipient is specified, then you will be asked. axmail-2.5/etc/help/sfax.hlp000066400000000000000000000012471257723226100160170ustar00rootroot00000000000000USAGE 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@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 axmail-2.5/etc/welcome.txt000066400000000000000000000004521257723226100156120ustar00rootroot00000000000000Subject: 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! axmail-2.5/head.c000066400000000000000000000105671257723226100137200ustar00rootroot00000000000000 /* head.c - parse mail headers. Grabbed from mailx 5.3b, reformatted, hacked and cleaned to compile without warnings by Heikki Hannikainen */ /* * 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 #include #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); } axmail-2.5/head.h000066400000000000000000000010061257723226100137110ustar00rootroot00000000000000 /* * 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[]); axmail-2.5/lock.c000066400000000000000000000007201257723226100137350ustar00rootroot00000000000000 /* lock.c - file locking services */ #include #include #include #include #include #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; } axmail-2.5/lock.h000066400000000000000000000000731257723226100137430ustar00rootroot00000000000000 extern int lock_fd(int fd); extern int unlock_fd(int fd); axmail-2.5/mailcmd.c000066400000000000000000000315051257723226100144200ustar00rootroot00000000000000 /* mailcmd.c - Mail commands */ #include #include #include #include #include #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 \nEx: john@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; } axmail-2.5/mailcmd.h000066400000000000000000000004301257723226100144160ustar00rootroot00000000000000 /* 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); axmail-2.5/mbox.c000066400000000000000000000175351257723226100137660ustar00rootroot00000000000000 /* * 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 #include #include #include #include #include #include #include #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; } axmail-2.5/mbox.h000066400000000000000000000030401257723226100137550ustar00rootroot00000000000000/* * 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); axmail-2.5/quit.c000066400000000000000000000121321257723226100137670ustar00rootroot00000000000000 /* quit.c - clean things up on exit. */ #include #include #include #include #include #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; im_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); } axmail-2.5/quit.h000066400000000000000000000000471257723226100137760ustar00rootroot00000000000000 extern void quit(int save, int code); axmail-2.5/setpwnam.c000066400000000000000000000117711257723226100146530ustar00rootroot00000000000000/* setpwnam.c edit an entry in a password database. */ /* because I use getpwent(), putpwent(), etc... */ #define _SVID_SOURCE #include #include #include #include #include #include #include #include #include #ifdef BSD43 #include #endif #include #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); } axmail-2.5/setpwnam.h000066400000000000000000000000761257723226100146540ustar00rootroot00000000000000 #include extern int setpwnam (struct passwd *pwd); axmail-2.5/utils.c000066400000000000000000000055451257723226100141570ustar00rootroot00000000000000 /* utils.c - common utilities */ #include #include #include #include #include #include #include #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@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: "); } axmail-2.5/utils.h000066400000000000000000000005521257723226100141550ustar00rootroot00000000000000 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];