diff options
author | in2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2002-03-07 23:13:44 +0800 |
---|---|---|
committer | in2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2002-03-07 23:13:44 +0800 |
commit | ae31e19f92e717919ac8e3db9039eb38d2b89aae (patch) | |
tree | c70164d6a1852344f44b04a653ae2815043512af | |
download | pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.gz pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.bz2 pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.lz pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.xz pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.zst pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.zip |
Initial revision
git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
446 files changed, 68629 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 00000000..80c7b7f0 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,2 @@ +tmp +pttbbs.conf diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d60c31a9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..dabc6044 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +SUBDIR= mbbsd util innbbsd +BBSHOME?=$(HOME) + +all install clean: + @for i in $(SUBDIR); do\ + cd $$i;\ + make BBSHOME=$(BBSHOME) OSTYPE=$(OSTYPE) $@;\ + cd ..;\ + done @@ -0,0 +1,12 @@ + +§Ö³t¦w¸Ë¤èªk½Ð°Ñ¾\ INSTALL + +±`¨£°ÝÃD¤Î sendmail.cf ªº³]ªk½Ð¨£ FAQ + +sample ¤U¦³ crontab ¤Î rc.local ªº½d¨Ò + +¦³¥ô¦ó°ÝÃD½Ðmailµ¹ pttbbs@ptt2.csie.ntu.edu.tw + +¤]¥i¨ì ptt2.csie.ntu.edu.tw / ptt2.twbbs.org ªº PttSrc ªO¸ß°Ý + +ÁÂÁ :) diff --git a/docs/ANCESTOR b/docs/ANCESTOR new file mode 100644 index 00000000..269e7cea --- /dev/null +++ b/docs/ANCESTOR @@ -0,0 +1,23 @@ +Pirate Bulletin Board System Version: 1.00 +Copyright (C) 1990 Edward A. Luke + +Eagles Bulletin Board System Version: 2.00-3.00 +Copyright (C) 1992, 1993, 1994 Raymond R. Rocker, Dominic B. Tynes + Guy T. Vega + +Phoenix Bulletin Board System Version: 3.00-4.0 +Copyright (C) 1993, 1994 Ming-Feng Chen, Ji-Tzay Yang + Tsun-Yi Wen + +¯µ±K±¡¤H¸ê°T¯¸ Version: 3.1-4.0 +Copyright (C) 1994 ²ÅãŲ, ¼B¨Î®p + +MapleBridge Bulletin Board System Version: 2.36 +Copyright (C) 1994-1995 Jeng-Hermes Lin, Hung-Pin Chen + SoC, Xshadow + +SunOfBeach Bulletin Board System Version: 0.22 +Copyleft ($) 1996 Kaede, woju + +Ptt Bulletin Board System Ptt, Jaky, Action, Heat, Dunk +§å½ð½ð¹ê·~§{ CharlieL, DickG, DavidYu diff --git a/docs/CHANGE b/docs/CHANGE new file mode 100644 index 00000000..2ddb6869 --- /dev/null +++ b/docs/CHANGE @@ -0,0 +1,76 @@ +Version 1.0.2 2001/07/17 + +* ·s¼W util/merge_passwd +* ·s¼W util/merge_board +* ×¥¿ load fromcache ¶W¹L 300 ¦æ·| segfault ªº bug +* ×¥¿¨Ó·½¦r¦ê¦b FreeBSD ¤U·|¦³¶Ã½Xªº°ÝÃD +* ×¥¿ mbbsd ¤¤ select() ¤£¦nªº¥Îªk +* ×¥¿ more.c ¤¤ªº¦w¥þ°ÝÃD (by kcwu) + +-------------------------------------------------- +Version 1.0.1 2001/04/26 + +* ±N¤å¥ó·h¦Ü docs ¥Ø¿ý¤U +* קï config.h ¤¤ªº MAX_ACTIVE, MAX_CPULOAD + ¨Ã¥[¤J FORCE_PROCESS_REGISTER_FORM ªº¿ï¶µ +* ·s¼W×´_¿ò¥¢¬ÝªOªº¥\¯à (press 'R') +* ×¥¿°T®§ªº¿ù»~ +* ×¥¿«ÕÆF¤ô²y +* ²¾°£¦b¨Ï¥ÎªÌ¦W³æ«ö'N'קï¼ÊºÙªº¥\¯à, ¸Ó¥\¯à¥i¯à¦³bug¦s¦b +* ·s¼W util/shmsweep + +-------------------------------------------------- +Version 1.0.0 2000/09/16 + +* ×¥¿ Select ¬ÝªOªº bug +* ·s¼W Reaper, §R°£¹L´Á±b¸¹ +* ·s¼W chickens ¨ì sample ¤¤ +* ·s¼W initbbs ªº¥\¯à: ªì©l¤Æ°ÊºA¬ÝªO, ½d¥»ºëÆF +* ·s¼W FAQ + +-------------------------------------------------- +Version 0.9.7 2000/08/31 + +* ·s¼W tunepasswd +* ×¥¿ innbbsd ªº bug +* xchatd ¹B§@¥¿±` +* ¾ã¦X buildir +* ×¥¿ Makefile ¦b¬Y¨Ç Linux ¤WµLªk¥¿±`¤u§@ªº bug +* ¦b sample ªº¥Ø¿ý¤U¥´ make install §Y¥i¦Û°Ê¦w¸Ë sample ³]©wÀÉ + +-------------------------------------------------- +Version 0.9.6 2000/06/28 + +* ×¥¿¨Ï¥Î¼È¦sÀÉ·|·í±¼ªº bug +* ¾ã¦X FreeBSD ©M Linux ªº Makefile, ¤£»Ýn¦A¤â°Êקï +* §â pttbbs.conf ±q include ·h¨ì pttsrc ¤U +* ·s¼W outmail ¨ú¥N bmda +* ¾ã¦X xchatd (¥¼´ú¸Õ) +* ¾ã¦X innbbsd (¥¼´ú¸Õ) + +-------------------------------------------------- +Version 0.9.5 2000/06/07 + +* ×¥¿¦b Linux µLªk talk ªº bug +* ¦pªG¬ÝªO¦Cªí¬OªÅªºªº¸Ü, ¦Û°Ê¶i¤J¶}ªO¥\¯à +* ·s¼W initbbs ¤u¨ãµ{¦¡ +* ·s¼W BBSHOME environment variable ªº¨Ï¥Î (¨£ INSTALL) +* ·h²¾³¡¥÷³]©w¨ì include/pttbbs.conf +* ×¥¿¦bFreeBSD¤WµLªk¨ú±o swapinfo ªº bug + +-------------------------------------------------- +Version 0.9.4 2000/06/03 + +* §âµ{¦¡¤¤¦³¥Î¨ì ncurses ªº¦a¤è²¾°£, ¤£¦A»Ýn -ltermcap, -lncurses +* ×¥¿¤@Ó³y¦¨µL½a°j°éªº Bug +* ²¾°£¥H¨Ï¥ÎªÌ¦WºÙ·j´M¥þ¯¸¤å³¹ªº¥\¯à + +-------------------------------------------------- +Version 0.9.3 2000/05/23 + +* ×¥¿¦b Linux ¤W Makefile ªº°ÝÃD + +-------------------------------------------------- +Version 0.9.2 2000/05/20 + +* port ¨ì Linux ¤W diff --git a/docs/FAQ b/docs/FAQ new file mode 100644 index 00000000..bc2904a0 --- /dev/null +++ b/docs/FAQ @@ -0,0 +1,146 @@ + §@ªÌ DavidYu (^^Y) ¬ÝªO PttSrc + ¼ÐÃD Re: ¦w¸Ë§¹³s½u®É..... + ®É¶¡ Thu May 18 15:08:04 2000 +¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w + +¡° ¤Þz¡mJamesCheng (ºô²y¤ñ±Æ²y¦nª±°Õ¡I)¡n¤§»Ê¨¥¡G +: §Ú¦b¦w¸Ë§¹¤§«á ¥Îroot°õ¦æ mbbsd 23 +: ³s½u¬Ý¥X²{ +: Escape character is '^]'. +: ¡iª«ªv¼Ö¶é¡j¡· ª«ªv²Ä¤G¯¸ ¡·(pt.mc.ntu.edu.tw) +: ½Õ´T(140.112.122.44) ¨t²Ît²ü 0.00 0.01 0.00 +: Connection closed by foreign host. +: µM«á¨t²Î¥X²{¤U¦C°T®§ +: [shmget error] key = 8ab +: errno = 12: Cannot allocate memory +: ³o¬O¦óì¦]©O¡H +shared memoryn¥[¤j +¦bkernel config file¤¤¥[¤@¦æ +options SHMMAXPGS=4100 +«·smake kernel + +-- +¡° µo«H¯¸: §å½ð½ð¹ê·~§{(ptt.twbbs.org) +¡» From: oio.m6.ntu.edu.t + + §@ªÌ DavidYu (Do it YOURSELF!) ¬ÝªO PttSrc + ¼ÐÃD Re: ½Ð°Ý¤@¤U... + ®É¶¡ Sat May 27 18:41:39 2000 +¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w + +¡° ¤Þz¡mclifflu ( ·Ð§r·Ð§r·Ð~~~)¡n¤§»Ê¨¥¡G +: ¡° ¤Þz¡mhscat (´_¯¸¤F¡I)¡n¤§»Ê¨¥¡G +: : ¤£¹L§Ú¦³¤@Ó¤p¤pªº°ÝÃD +: : ¯à¤£¯à«ü¾É¤@¤U...·Qn¶}·sªºª©À³¸Ó±qþÃä¶}©O¡H +: ¥D¿ï³æ¤Uªº (0)Admin ?? +: : ¦]¬°§Ú¹ê¦b§ä¤£¨ì«ç»ò¶}·s¬ÝªO...:~~~~... +¤£¤£¤£.. +¶}ªOn±q¤ÀÃþ¬ÝªOªº¦a¤è¶},³o³¡¥÷¦³ÂI¤p¤pªº½ÆÂø, +©M¥H©¹ªºª©¥»¤£¤@¼Ë,§Ú¨Ó²³æ»¡©ú¤@¤U: + +º¥ý¤¶²Ð¬ÝªO. +¬ÝªO¦³¨âºØ, ¤@¯ë¬ÝªO©M¸s²Õ¬ÝªO. ¦pªG¥ÎÀɮרt²Îªº¬[ºc¨Ó¬Ýªº¸Ü, +¤@¯ë¬ÝªO¦p¦P file, ¦Ó¸s²Õ¬ÝªO´N¬O directory +(¦b©Ò¦³¬ÝªO¦Cªíªº¦a¤è¥u·|¥X²{¤@¯ë¬ÝªO) + +¤@ӬݪO¦³UID¤ÎGID³o¨âÓÄÝ©Ê. UID¬Ouniqueªº,±q1¶}©l¤À°t,¨t²Î¦b¶}ªO®É·|¦ +Û°Êallocate¤@Ó. ¦ÓGID¬O«ü©w³oӬݪO¦bþ¤@Ó¸s²Õ¬ÝªO¤§¤U(¬ÝªO¬O¾ðª¬¬[ºcªº) +©Ò¥H¦pªG¦³¤@Ó¸s²Õ¬ÝªOªºUID¬Ox, «hGID¬°xªº¬ÝªO³£·|Â\¦b¸Ó¸s²Õ¬ÝªO¤§¤U +¦Ó¦pªG¬ÝªOGID¬°0(«O¯dªºUID)ªº¸Ü,¸Ó¬ÝªO´N·|¥X²{¦b¤@¶}©l±q¥D¿ï³æ¶iCLASSªº +¨ºÓ¦a¤è + +¦Ü©ó¶}ªOªº¤èªk. +º¥ý±qCLASS¶i¨ì§A·Qn¶}·sªOªºÃþ§O¤U,µM«á«ö¤jB³]©w +¦p¦¹·s¶}ªºªO´N·|¦Û°Êassign GID ¨ì¨ºÓÃþ§O¤U + +¦pªGn¯ë°Ê¤@Ó¤w¸g¶}¦nªºªO¨ì¨ä¥LÃþ§Oªº¸Ü +¥ý§ä¥X¨ºÓÃþ§O(¸s²Õ¬ÝªO)ªºUID, «ö¤jE¥i¥H¬Ý¨ì +µM«á§ân·h°ÊªºªOªºGID³]¦¨¨ºÓUID¤Î¥i + +ȱoª`·Nªº¬O, ¦pªG§â¬YӨϥΪ̳]¦¨¬Y¸s²Õ¬ÝªOªºªO¥Dªº¸Ü +«h·í¥L±qCLASS¶i¨ì¨ºÓ¸s²Õ®É·|Àò±o¤p²ÕªøªºÅv(¥i¥H¶}ªO,³]©w¬ÝªOµ¥µ¥) +n¯S§O¤p¤ß + +¤ñ¸û³Â·Ðªº¦a¤è: +¤@Ó·s¶}ªº¸s²Õ¸Ì±¨Ã¨S¦³¥ô¦ó¬ÝªO,©Ò¥HµLªk±q¿ï³æ¶i¥h¸Ì±¶}ªO +³o®ÉÔ´N»Ýn¦b¥i¶}ªOªº¦a¤è¥ý¶}ÓªO,µM«á¦A§â¨ºÓªOªºGID³]¹L¥h§Y¥i +(³o¤]¬O¬°¤°»ò»Ýn¤@Óinitialªº.BOARDSªºì¦] :p) + +-- +¡° µo«H¯¸: §å½ð½ð¹ê·~§{(ptt.twbbs.org) +¡» From: meow.cc.ntu.edu. + + §@ªÌ DavidYu (ÜI~~~~~~~~~~) ¬ÝªO PttSrc + ¼ÐÃD sendmail.cfn§ïªº¦a¤è(°Ñ¦Ò¥Î) + ®É¶¡ Sun Jul 9 09:39:53 2000 +¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w + +¦³ÃC¦âªº¬On¥[¤W¥hªº +nª`·N,tab©Mspace¤£¯à²V¥Î + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### +S0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>98 $1 handle local hacks +R$+.bbs < @ $=w .> $#bbsmail $: $1 bbs mail gateway +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +R$* $: $>Parse1 $1 final parsing + +...... + +# handle locally delivered names +R$+.bbs $#bbsmail $:$1 bbs mail gateway +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +R$=L $#local $: @ $1 special local names +R$+ $#local $: $1 regular local names + +########################################################################### +### Ruleset 5 -- special rewriting after aliases have been expanded ### +########################################################################### + +...... + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### @(#)local.m4 8.30 (Berkeley) 6/30/1998 ##### + +Mlocal, P=/usr/libexec/mail.local, F=lsDFMAw5:/|@qSXfmnz9P, S=10/30, R= + T=DNS/RFC822/X-Unix, + A=mail.local -l +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=10/30, R=20/40, D=$z:/, + T=X-Unix, + A=sh -c $u +Mbbsmail, P=/home/bbs/bin/bbsmail, F=lsSDFMhPu, U=bbs, S=10,R=20/40, +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + A=bbsmail $u +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +-- +¡° µo«H¯¸: §å½ð½ð¹ê·~§{(ptt.twbbs.org) +¡» From: oio.m6.ntu.edu.t + + §@ªÌ DavidYu (ï~~~~~~~~~~~~~~~) ¬ÝªO PttSrc + ¼ÐÃD [anno] tunepasswd + ®É¶¡ Sat Jul 29 09:18:06 2000 +¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w + +·s¼W¤F¤@Ó tunepasswd ªºµ{¦¡ + +¦pªG§A¦b .PASSWD «Ø¥ß«á¤S§ï¹L¤F MAX_USERS + +§A¥²¶·n°õ¦æ tunepasswd ¤@¦¸¨Óקï .PASSWD Àɪº¤j¤p + +°õ¦æªº®ÉÔ¤£¥i¥H¦³¥ô¦óBBSªºµ{¦¡¦b°õ¦æ + +shared memory ¤]À³¸Ón²M°£, §_«h·|¦³¤£¹w´Áªº¿ù»~µo¥Í + +°õ¦æ tunepasswd ·|²£¥Í¤@Óì¨Óªº³Æ¥÷ÀÉ .PASSWD~ + +-- +¡° µo«H¯¸: §å½ð½ð¹ê·~§{(ptt.twbbs.org) +¡» From: oio.m6.ntu.edu.t diff --git a/docs/INSTALL b/docs/INSTALL new file mode 100644 index 00000000..5bd484d5 --- /dev/null +++ b/docs/INSTALL @@ -0,0 +1,49 @@ +©³¤U¬O§Ö³t¦w¸Ëªº¤èªk + +== + +¥ý¨ú±o root Åv + +1. ¥´ vipw, ¥[¤J©³¤U¨â¦æ + + bbs:*:9999:99::0:0:Ptt BBS:/home/bbs:/home/bbs/bin/bbsrf + bbsadm::9999:99::0:0:Ptt BBS:/home/bbs:/bin/csh + +2. °õ¦æ passwd bbsadm ³] bbsadmªº±K½X +3. ¦b /etc/group ¤¤¥[¤J¤@¦æ + + bbs:*:99: + +4. °õ¦æ mkdir /home/bbs +5. °õ¦æ chown bbs.bbs /home/bbs +6. °õ¦æ chmod 700 /home/bbs + +µM«á¤Á´«¦¨ bbsadm ªº¨¥÷ + +7. ¨ú±o¸Ñ¶} pttbbs-VERSION.tar.gz (¥ô¦ó¥Ø¿ý¤U¬Ò¥i). +8. °õ¦æ cd pttbbs +9. ¦pªG¤§«e¨S¦³³]©w¹L pttbbs.conf ªº¸Ü, ½Ð cp sample/pttbbs.conf pttbbs.conf +10. קï pttbbs.conf +11. °õ¦æ make OSTYPE=FreeBSD BBSHOME=/home/bbs all install + (Linux¨Ï¥ÎªÌ½Ð§â "FreeBSD" §ï¦¨ "linux") +12. ¦pªG¬O·s¬[°_¨Óªº¯¸, ½Ð°õ¦æ cd sample; make install +12. °õ¦æ cd /home/bbs; bin/initbbs + +°²¦p¤@¤Á³£«Ü¶¶§Qªº¸Ü,³o¼Ë¤l¤j·§´N¦w¸Ë§¹¤F +±µ¤U¨Ó¬O±Ò°Ê bbs ªº³¡¥÷ + +13. °õ¦æ bin/uhash_loader (*µù1) +14. ¥Î root °õ¦æ bin/mbbsd 23 (µù2) + +telnet localhost 23 ¬Ý¬Ý +new¤@Ó±b¸¹¥sSYSOP,µM«álogout¦Alogin, ³o¼Ë¤l´N·|¾Ö¦³¯¸ªøÅvÅo~ +¦Anew¤@Ó±b¸¹¥s guest, ³o¼Ë¤l§O¤H´N¥i¥H¥Î guest °ÑÆ[§Aªº¯¸¤F +¶}ªO,¶}¸s²Õ,¥H¤Î·h°Ê¸s²Õªº¤èªk½Ð¬Ý PttSrc ªOªº¤åºK + +µù: +1. ³oÓµ{¦¡¬O¦b initial shared memory ¥Îªº, ¥u¦³¶}¾÷«á²Ä¤@¦¸°õ¦æ, ©Î¬O + §A¤â°Ê²M°£ shm «á¤~»Ýn°õ¦æ + +2. bin/mbbsd 23 ¬O«ü©wn bind 23 port, ¨Ì·Ó UNIX ³W©w, 1024 ¥H¤Uªº port + ¶·n¦³ root Åv, ©Ò¥H¦pªGn bind 23 port ªº¸Ü´Nn¥Î root ¥h°õ¦æ, + 3000 port «h¤£»Ýn diff --git a/include/common.h b/include/common.h new file mode 100644 index 00000000..333bed8c --- /dev/null +++ b/include/common.h @@ -0,0 +1,198 @@ +/* $Id: common.h,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifndef INCLUDE_COMMON_H +#define INCLUDE_COMMON_H + +#define STR_GUEST "guest" +#define DEFAULT_BOARD str_sysop + +#define FN_PASSWD BBSHOME "/.PASSWDS" /* User records */ +#define FN_USSONG "ussong" /* ÂIºq²Îp */ +#define FN_POST_NOTE "post.note" /* po¤å³¹³Æ§Ñ¿ý */ +#define FN_APPLICATION "application" +#define FN_MONEY "etc/money" +#define FN_OVERRIDES "overrides" +#define FN_REJECT "reject" +#define FN_WATER "water" +#define FN_CANVOTE "can_vote" +#define FN_VISABLE "visable" +#define FN_USIES "usies" /* BBS log */ +#define FN_BOARD ".BRD" /* board list */ +#define FN_USEBOARD "usboard" /* ¬Ýª©²Îp */ +#define FN_NOTE_ANS "note.ans" +#define FN_TOPSONG "etc/topsong" +#define FN_OVERRIDES "overrides" +#define FN_TICKET "ticket" +#define FN_TICKET_END "ticket.end" +#define FN_TICKET_ITEMS "ticket.items" +#define FN_TICKET_RECORD "ticket.data" +#define FN_TICKET_USER "ticket.user" +#define FN_TICKET_OUTCOME "ticket.outcome" +#define FN_TICKET_BRDLIST "boardlist" + +#define MSG_DEL_CANCEL "¨ú®ø§R°£" +#define MSG_SELECT_BOARD "\033[7m¡i ¿ï¾Ü¬ÝªO ¡j\033[m\n" \ + "½Ð¿é¤J¬ÝªO¦WºÙ(«öªÅ¥ÕÁä¦Û°Ê·j´M)¡G" +#define MSG_CLOAKED "«¢«¢¡I§ÚÁô§Î¤F¡I¬Ý¤£¨ì°Ç... :P" +#define MSG_UNCLOAK "§Ún«²{¦¿´ò¤F...." +#define MSG_BIG_BOY "§Ú¬O¤j«Óô! ^o^Y" +#define MSG_BIG_GIRL "¥@¬ö¤j¬ü¤k *^-^*" +#define MSG_LITTLE_BOY "§Ú¬O©³}°Õ... =)" +#define MSG_LITTLE_GIRL "³Ì¥i·Rªº¬ü¬Ü! :>" +#define MSG_MAN "³Á·í³Ò¨û¨û (^O^)" +#define MSG_WOMAN "¥s§Ú¤pªü«¼!! /:>" +#define MSG_PLANT "´Óª«¤]¦³©Ê§O³á.." +#define MSG_MIME "Äqª«Á`¨S©Ê§O¤F§a" +#define MSG_PASSWD "½Ð¿é¤J±zªº±K½X: " +#define MSG_POSTER "\033[34;46m ¤å³¹¿ïŪ "\ + "\033[31;47m (y)\033[30m¦^«H "\ + "\033[31m(=[]<>)\033[30m¬ÛÃö¥DÃD "\ + "\033[31m(/?)\033[30m·j´M¼ÐÃD "\ + "\033[31m(aA)\033[30m·j´M§@ªÌ "\ + "\033[31m(x)\033[30mÂà¿ý "\ + "\033[31m(V)\033[30m§ë²¼ \033[m" +#define MSG_SEPERATOR "\ +¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + +#define MSG_CLOAKED "«¢«¢¡I§ÚÁô§Î¤F¡I¬Ý¤£¨ì°Ç... :P" +#define MSG_UNCLOAK "§Ún«²{¦¿´ò¤F...." + +#define MSG_WORKING "³B²z¤¤¡A½ÐµyÔ..." + +#define MSG_CANCEL "¨ú®ø¡C" +#define MSG_USR_LEFT "User ¤w¸gÂ÷¶}¤F" +#define MSG_NOBODY "¥Ø«eµL¤H¤W½u" + +#define MSG_DEL_OK "§R°£§¹²¦" +#define MSG_DEL_CANCEL "¨ú®ø§R°£" +#define MSG_DEL_ERROR "§R°£¿ù»~" +#define MSG_DEL_NY "½Ð½T©w§R°£(Y/N)?[N] " + +#define MSG_FWD_OK "¤å³¹Âà±H§¹¦¨!" +#define MSG_FWD_ERR1 "Âà±H¥¢»~: system error" +#define MSG_FWD_ERR2 "Âà±H¥¢»~: address error" + +#define MSG_SURE_NY "½Ð±z½T©w(Y/N)¡H[N] " +#define MSG_SURE_YN "½Ð±z½T©w(Y/N)¡H[Y] " + +#define MSG_BID "½Ð¿é¤J¬ÝªO¦WºÙ¡G" +#define MSG_UID "½Ð¿é¤J¨Ï¥ÎªÌ¥N¸¹¡G" +#define MSG_PASSWD "½Ð¿é¤J±zªº±K½X: " + +#define MSG_BIG_BOY "§Ú¬O¤j«Óô! ^o^Y" +#define MSG_BIG_GIRL "¥@¬ö¤j¬ü¤k *^-^*" +#define MSG_LITTLE_BOY "§Ú¬O©³}°Õ... =)" +#define MSG_LITTLE_GIRL "³Ì¥i·Rªº¬ü¬Ü! :>" +#define MSG_MAN "³Á·í³Ò¨û¨û (^O^)" +#define MSG_WOMAN "¥s§Ú¤pªü«¼!! /:>" +#define MSG_PLANT "´Óª«¤]¦³©Ê§O³á.." +#define MSG_MIME "Äqª«Á`¨S©Ê§O¤F§a" + +#define ERR_BOARD_OPEN ".BOARD ¶}±Ò¿ù»~" +#define ERR_BOARD_UPDATE ".BOARD §ó·s¦³»~" +#define ERR_PASSWD_OPEN ".PASSWDS ¶}±Ò¿ù»~" + +#define ERR_BID "§A·d¿ù¤F°Õ¡I¨S¦³³oÓªO³á¡I" +#define ERR_UID "³o¸Ì¨S¦³³oÓ¤H°Õ¡I" +#define ERR_PASSWD "±K½X¤£¹ï³á¡I§A¦³¨S¦³«_¥Î¤H®aªº¦W¦r°Ú¡H" +#define ERR_FILENAME "ÀɦW¤£¦Xªk¡I" +#define MSG_MAILER \ +"\033[34;46m ÂE¶©¹ªð \033[31;47m(R)\033[30m¦^«H\033[31m(x)\033[30mÂà¹F\ +\033[31m(y)\033[30m¸s²Õ¦^«H\033[31m(D)\033[30m§R°£\ +\033[31m(c)\033[30m¦¬¤J«H¥ó§¨\033[31m(z)\033[30m«H¥ó§¨ \033[31m[G]\033[30mÄ~Äò?\033[0m" +#define MSG_SHORTULIST "\033[7m\ +¨Ï¥ÎªÌ¥N¸¹ ¥Ø«eª¬ºA ¢x¨Ï¥ÎªÌ¥N¸¹ ¥Ø«eª¬ºA ¢x¨Ï¥ÎªÌ¥N¸¹ ¥Ø«eª¬ºA \033[0m" + + +#define STR_AUTHOR1 "§@ªÌ:" +#define STR_AUTHOR2 "µo«H¤H:" +#define STR_POST1 "¬ÝªO:" +#define STR_POST2 "¯¸¤º:" + +/* Flags to getdata input function */ +#define NOECHO 0 +#define DOECHO 1 +#define LCECHO 2 + +#define YEA 1 /* Booleans (Yep, for true and false) */ +#define NA 0 + + +#define IRH 1 /* ¦n¤ÍÃö«Y */ +#define HRM 2 +#define IBH 4 +#define IFH 8 +#define HFM 16 +#define ST_FRIEND (IBH | IFH | HFM) +#define ST_REJECT (IRH | HRM) + +/* Áä½L³]©w */ +#define KEY_TAB 9 +#define KEY_ESC 27 +#define KEY_UP 0x0101 +#define KEY_DOWN 0x0102 +#define KEY_RIGHT 0x0103 +#define KEY_LEFT 0x0104 +#define KEY_HOME 0x0201 +#define KEY_INS 0x0202 +#define KEY_DEL 0x0203 +#define KEY_END 0x0204 +#define KEY_PGUP 0x0205 +#define KEY_PGDN 0x0206 + +#define QCAST int (*)(const void *, const void *) +#define Ctrl(c) (c & 037) +#define chartoupper(c) ((c >= 'a' && c <= 'z') ? c+'A'-'a' : c) + +#define LEN_AUTHOR1 5 +#define LEN_AUTHOR2 7 + +/* ----------------------------------------------------- */ +/* ¸s²Õ¦W³æ¼Ò¦¡ Ptt */ +/* ----------------------------------------------------- */ +#define FRIEND_OVERRIDE 0 +#define FRIEND_REJECT 1 +#define FRIEND_ALOHA 2 +#define FRIEND_POST 3 +#define FRIEND_SPECIAL 4 +#define FRIEND_CANVOTE 5 +#define BOARD_WATER 6 +#define BOARD_VISABLE 7 + +#define LOCK_THIS 1 // lock³o½u¤£¯à«½Æª± +#define LOCK_MULTI 2 // lock©Ò¦³½u¤£¯à«½Æª± + +#define I_TIMEOUT (-2) /* Used for the getchar routine select call */ +#define I_OTHERDATA (-333) /* interface, (-3) will conflict with chinese */ + +#define CHE_O(c) ((c) >> 3) +#define CHE_P(c) ((c) & 7) +#define RTL(x) (((x) - 3) >> 1) +#define dim(x) (sizeof(x) / sizeof(x[0])) +#define LTR(x) ((x) * 2 + 3) +#define CHE(a, b) ((a) | ((b) << 3)) + +#define BRD_NOZAP 00001 /* ¤£¥izap */ +#define BRD_NOCOUNT 00002 /* ¤£¦C¤J²Îp */ +#define BRD_NOTRAN 00004 /* ¤£Âà«H */ +#define BRD_GROUPBOARD 00010 /* ¸s²ÕªO */ +#define BRD_HIDE 00020 /* ÁôÂêO (¬ÝªO¦n¤Í¤~¥i¬Ý) */ +#define BRD_POSTMASK 00040 /* ¨îµoªí©Î¾\Ū */ +#define BRD_ANONYMOUS 00100 /* °Î¦WªO */ +#define BRD_DEFAULTANONYMOUS 00200 /* ¹w³]°Î¦WªO */ +#define BRD_BAD 00400 /* ¹Hªk§ï¶i¤¤¬ÝªO */ +#define BRD_VOTEBOARD 01000 /* ³s¸p¾÷¬ÝªO */ + +#define MAX_MODES 80 + +#ifndef MIN +#define MIN(a,b) ((a<b)?a:b) +#endif +#ifndef MAX +#define MAX(a,b) ((a>b)?a:b) +#endif + +#define char_lower(c) ((c >= 'A' && c <= 'Z') ? c|32 : c) + +#define STR_CURSOR "¡´" +#define STR_UNCUR " " +#endif diff --git a/include/config.h b/include/config.h new file mode 100644 index 00000000..3eb6e64a --- /dev/null +++ b/include/config.h @@ -0,0 +1,197 @@ +/* $Id: config.h,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifndef INCLUDE_CONFIG_H +#define INCLUDE_CONFIG_H + +#include <syslog.h> +#include "../pttbbs.conf" + +#define BBSPROG BBSHOME "/bin/mbbsd" /* ¥Dµ{¦¡ */ +#define BAN_FILE "BAN" /* Ãö¯¸³q§iÀÉ */ +#define LOAD_FILE "/proc/loadavg" /* for Linux */ + +#ifndef RELAY_SERVER_IP /* ±H¯¸¥~«Hªº mail server */ +#define RELAY_SERVER_IP "127.0.0.1" +#endif + +#ifndef MAX_USERS /* ³Ì°ªµù¥U¤H¼Æ */ +#define MAX_USERS (150000) +#endif + +#ifndef MAX_ACTIVE +#define MAX_ACTIVE (1024) /* ³Ì¦h¦P®É¤W¯¸¤H¼Æ */ +#endif + +#ifndef MAX_CPULOAD +#define MAX_CPULOAD (70) /* CPU ³Ì°ªload */ +#endif + +#ifndef MAX_POST_MONEY /* µoªí¤å³¹½Z¶Oªº¤W */ +#define MAX_POST_MONEY 100 +#endif + +#ifndef MAX_CHICKEN_MONEY /* ¾iÂû³õì§Q¤W */ +#define MAX_CHICKEN_MONEY 100 +#endif + +#ifndef MAX_GUEST_LIFE /* ³Ìªø¥¼»{ÃҨϥΪ̫O¯d®É¶¡(¬í) */ +#define MAX_GUEST_LIFE (3 * 24 * 60 * 60) +#endif + +#ifndef MAX_LIFE /* ³Ìªø¨Ï¥ÎªÌ«O¯d®É¶¡(¬í) */ +#define MAX_LIFE (120 * 24 * 60 * 60) +#endif + +#ifndef MAX_FROM +#define MAX_FROM (300) /* ³Ì¦h¬G¶m¼Æ */ +#endif + +#ifndef HAVE_JCEE /* ¤j¾ÇÁp¦Ò¬dº]¨t²Î */ +#define HAVE_JCEE 1 +#endif + +#ifndef HAVE_FREECLOAK +#define HAVE_FREECLOAK 0 +#endif + +#ifndef FORCE_PROCESS_REGISTER_FORM +#define FORCE_PROCESS_REGISTER_FORM 0 +#endif + +#ifndef TITLE_COLOR +#define TITLE_COLOR "\033[0;1;37;46m" +#endif + +#ifndef SYSLOG_FACILITY +#define SYSLOG_FACILITY LOG_LOCAL0 +#endif + +#ifndef TAR_PATH +#define TAR_PATH "tar" +#endif + +#ifndef HBFLexpire +#define HBFLexpire (432000) /* 5 days */ +#endif + +/* ¥H¤UÁÙ¥¼¾ã²z */ +#define DIRCACHESIZE (40) /* cache ¤å³¹¦Cªí¤¤³Ì«á40½g */ +#define MAX_FRIEND (256) /* ¸ü¤J cache ¤§³Ì¦hªB¤Í¼Æ¥Ø */ +#define MAX_REJECT (32) /* ¸ü¤J cache ¤§³Ì¦hÃa¤H¼Æ¥Ø */ +#define MAX_MSGS (10) /* ¤ô²y(¼ö°T)§Ô@¤W */ +#define MAX_BOARD (8192) /* ³Ì¤j¶}ª©Ó¼Æ */ +#define MAX_MOVIE (999) /* ³Ì¦h°ÊºA¬Ýª©¼Æ */ +#define MAX_MOVIE_SECTION (10) /* ³Ì¦h°ÊºA¬ÝªOÃþ§O */ +#define MAX_ITEMS (1000) /* ¤@ӥؿý³Ì¦h¦³´X¶µ */ +#define MAX_HISTORY (12) /* °ÊºA¬ÝªO«O«ù 12 µ§¾ú¥v°O¿ý */ +#define MAX_CROSSNUM (9) /* ³Ì¦hcrosspost¦¸¼Æ */ +#define MAX_QUERYLINES (16) /* Åã¥Ü Query/Plan °T®§³Ì¤j¦æ¼Æ */ +#define MAX_LOGIN_INFO (128) /* ³Ì¦h¤W½u³qª¾¤H¼Æ */ +#define MAX_POST_INFO (32) /* ³Ì¦h·s¤å³¹³qª¾¤H¼Æ */ +#define MAX_NAMELIST (128) /* ³Ì¦h¨ä¥L¯S§O¦W³æ¤H¼Æ */ +#define MAX_PAGES (999) /* more.c ¤¤¤å³¹¶¼Æ¤W(lines/22) */ +#define MAX_KEEPMAIL (200) /* ³Ì¦h«O¯d´X«Ê MAIL¡H */ +#define MAX_EXKEEPMAIL (1000) /* ³Ì¦h«H½c¥[¤j¦h¤Ö«Ê */ +#define MAX_NOTE (20) /* ³Ì¦h«O¯d´X½g¯d¨¥¡H */ +#define MAX_SIGLINES (6) /* ñ¦WÀɤޤJ³Ì¤j¦æ¼Æ */ +#define MAX_CROSSNUM (9) /* ³Ì¦hcrosspost¦¸¼Æ */ +#define MAX_REVIEW (7) /* ³Ì¦h¤ô²y¦^ÅU */ +#define NUMVIEWFILE (14) /* ¶i¯¸µe±³Ì¦h¼Æ */ +#define MAX_SWAPUSED (0.7) /* SWAP³Ì°ª¨Ï¥Î²v */ +#define LOGINATTEMPTS (3) /* ³Ì¤j¶i¯¸¥¢»~¦¸¼Æ */ +#define WHERE /* ¬O§_¦³¬G¶m¥\¯à */ +#undef LOG_BOARD /* ¬Ýª©¬O§_log */ +#undef SUPPORT_GB /* ¬O§_¤ä´©gb */ + + +#define DEFAULTBOARD "SYSOP" /* ¹w³]¬ÝªO */ +#define LOGINASNEW /* ±Ä¥Î¤W¯¸¥Ó½Ð±b¸¹¨î«× */ +#define NO_WATER_POST /* ¨¾¤îBlahBlah¦¡Äé¤ô */ +#define USE_BSMTP /* ¨Ï¥ÎopusªºBSMTP ±H¦¬«H? */ +#define HAVE_ANONYMOUS /* ´£¨Ñ Anonymous ªO */ +#undef POSTNOTIFY /* ·s¤å³¹³qª¾¥\¯à */ +#define INTERNET_EMAIL /* ¤ä´© InterNet Email ¥\¯à(§t Forward) */ +#define HAVE_ORIGIN /* Åã¥Ü author ¨Ó¦Û¦ó³B */ +#undef HAVE_MAILCLEAN /* ²M²z©Ò¦³¨Ï¥ÎªÌÓ¤H«H½c */ +#undef HAVE_SUICIDE /* ´£¨Ñ¨Ï¥ÎªÌ¦Û±þ¥\¯à */ +#undef HAVE_REPORT /* ¨t²Î°lÂܳø§i */ +#undef HAVE_INFO /* Åã¥Üµ{¦¡ª©¥»»¡©ú */ +#undef HAVE_LICENSE /* Åã¥Ü GNU ª©Åvµe± */ +#undef HAVE_TIN /* ´£¨Ñ news reader */ +#undef HAVE_GOPHER /* ´£¨Ñ gopher */ +#undef HAVE_WWW /* ´£¨Ñ www browser */ +#define FAST_LOGIN /* Login ¤£Àˬd»·ºÝ¨Ï¥ÎªÌ */ +#define HAVE_CAL /* ´£¥\pºâ¾÷ */ +#undef HAVE_ARCHIE /* have arche */ +#undef POSTBUG /* board/mail post ¨S¦³ bug ¤F */ +#undef HAVE_REPORT /* ¨t²Î°lÂܳø§i */ +#undef EMAIL_JUSTIFY /* µo¥X InterNet Email ¨¥÷»{ÃÒ«H¨ç */ +#undef NEWUSER_LIMIT /* ·s¤â¤W¸ôªº¤T¤Ñ¨î */ +#undef HAVE_X_BOARDS + +#define USE_LYNX /* ¨Ï¥Î¥~³¡lynx dump ? */ +#undef USE_PROXY +#ifdef USE_PROXY +#define PROXYSERVER "140.112.28.165" +#define PROXYPORT 3128 +#endif +#define LOCAL_PROXY /* ¬O§_¶}±Òlocal ªºproxy */ +#ifdef LOCAL_PROXY +#define HPROXYDAY 1 /* localªºproxy refresh¤Ñ¼Æ */ +#endif + +#define SHOWMIND /* ¬Ý¨£¤ß±¡ */ +#define SHOWUID /* ¬Ý¨£¨Ï¥ÎªÌ UID */ +#define SHOWBOARD /* ¬Ý¨£¨Ï¥ÎªÌ¬ÝªO */ +#define SHOWPID /* ¬Ý¨£¨Ï¥ÎªÌ PID */ + +#define REALINFO /* ¯u¹ê©m¦W */ +#ifdef REALINFO +#undef ACTS_REALNAMES /* ¥D¥Ø¿ýªº (U)ser Åã¥Ü¯u¹ê©m¦W */ +#undef POST_REALNAMES /* ¶K¤å¥ó®Éªþ¤W¯u¹ê©m¦W */ +#undef MAIL_REALNAMES /* ±H¯¸¤º«H¥ó®Éªþ¤W¯u¹ê©m¦W */ +#endif + +#define DOTIMEOUT +#ifdef DOTIMEOUT +#define IDLE_TIMEOUT (30*60) /* ¤@¯ë±¡ªp¤§ timeout */ +#define MONITOR_TIMEOUT (20*60) /* monitor ®É¤§ timeout */ +#define SHOW_IDLE_TIME /* Åã¥Ü¶¢¸m®É¶¡ */ +#endif + +#define SEM_ENTER -1 /* enter semaphore */ +#define SEM_LEAVE 1 /* leave semaphore */ +#define SEM_RESET 0 /* reset semaphore */ + +#define MAGIC_KEY 1234 /* ¨¤À»{ÃÒ«H¨ç½s½X */ + +#define BRDSHM_KEY 1208 +#define UHASH_KEY 1218 /* userid->uid hash */ +#define UTMPSHM_KEY 2221 +#define PTTSHM_KEY 1220 /* °ÊºA¬Ýª© , ¸`¤é */ +#define FROMSHM_KEY 1223 /* whereis, ³Ì¦h¨Ï¥ÎªÌ */ + +#define BRDSEM_KEY 2005 /* semaphore key */ +#define PTTSEM_KEY 2000 /* semaphore key */ +#define FROMSEM_KEY 2003 /* semaphore key */ +#define PASSWDSEM_KEY 2010 + +#define NEW_CHATPORT 3838 +#define CHATPORT 5722 + +#define MAX_ROOM 16 /* ³Ì¦h¦³´X¶¡¥]´[¡H */ + +#define EXIT_LOGOUT 0 +#define EXIT_LOSTCONN -1 +#define EXIT_CLIERROR -2 +#define EXIT_TIMEDOUT -3 +#define EXIT_KICK -4 + +#define CHAT_LOGIN_OK "OK" +#define CHAT_LOGIN_EXISTS "EX" +#define CHAT_LOGIN_INVALID "IN" +#define CHAT_LOGIN_BOGUS "BG" +#define BADCIDCHARS " *" /* Chat Room ¤¤¸T¥Î©ó nick ªº¦r¤¸ */ + +#define ALLPOST "ALLPOST" + +#endif diff --git a/include/gomo.h b/include/gomo.h new file mode 100644 index 00000000..c51bb283 --- /dev/null +++ b/include/gomo.h @@ -0,0 +1,2156 @@ + +#define BBLANK (0) /* ªÅ¥Õ */ +#define BBLACK (1) /* ¶Â¤l, ¥ý¤â */ +#define BWHITE (2) /* ¥Õ¤l, «á¤â */ +#define MAX_TIME (300) /*³Ìªøidle¬í¼Æ*/ +#ifndef BRDSIZ +#define BRDSIZ (15) /* ´Ñ½L³æÃä¤j¤p */ +#endif + +#define BGOTO(x, y) move( 16 - y , x * 2 + 3) +#define BGOTOCUR(x, y) move(16 - y, x * 2 + 4) + +/* + 0 0 0 = #@# : len= 3 : NO 00 NO + 1 1 0 = #_@# : len= 4 : NO 00 NO + 2 1 1 = #_@_# : len= 5 : NO 00 NO + 3 2 0 = #O@# : len= 4 : NO 00 NO + 4 2 1 = #O@_# : len= 5 : NO 00 NO + 5 2 2 = #O@O# : len= 5 : NO 00 NO + 6 3 0 = #__@# : len= 5 : NO 00 NO + 7 3 1 = #__@_# : len= 6 : NO 00 NO + 8 3 2 = #__@O# : len= 6 : NO 00 NO + 9 3 3 = #__@__# : len= 7 : NO 00 NO + 10 4 0 = #_O@# : len= 5 : NO 00 NO + 11 4 1 = #_O@_# : len= 6 : NO 00 NO + 12 4 2 = #_O@O# : len= 6 : NO 00 NO + 13 4 3 = #_O@__# : len= 7 : NO 00 NO + 14 4 4 = #_O@O_# : len= 7 : NO 00 NO + 15 5 0 = #O_@# : len= 5 : NO 00 NO + 16 5 1 = #O_@_# : len= 6 : NO 00 NO + 17 5 2 = #O_@O# : len= 6 : NO 00 NO + 18 5 3 = #O_@__# : len= 7 : NO 00 NO + 19 5 4 = #O_@O_# : len= 7 : NO 00 NO + 20 5 5 = #O_@_O# : len= 7 : NO 00 NO + 21 6 0 = #OO@# : len= 5 : NO 00 NO + 22 6 1 = #OO@_# : len= 6 : NO 00 NO + 23 6 2 = #OO@O# : len= 6 : NO 00 NO + 24 6 3 = #OO@__# : len= 7 : NO 00 NO + 25 6 4 = #OO@O_# : len= 7 : S4 00 S4 + 26 6 5 = #OO@_O# : len= 7 : D4 00 D4 + 27 6 6 = #OO@OO# : len= 7 : L5 00 L5 + 28 7 0 = #___@# : len= 6 : NO 00 NO + 29 7 1 = #___@_# : len= 7 : NO 00 NO + 30 7 2 = #___@O# : len= 7 : NO 00 NO + 31 7 3 = #___@__# : len= 8 : NO 00 NO + 32 7 4 = #___@O_# : len= 8 : NO 00 NO + 33 7 5 = #___@_O# : len= 8 : NO 00 NO + 34 7 6 = #___@OO# : len= 8 : NO 00 NO + 35 7 7 = #___@___# : len= 9 : NO 00 NO + 36 8 0 = #__O@# : len= 6 : NO 00 NO + 37 8 1 = #__O@_# : len= 7 : NO 00 NO + 38 8 2 = #__O@O# : len= 7 : NO 00 NO + 39 8 3 = #__O@__# : len= 8 : NO 00 NO + 40 8 4 = #__O@O_# : len= 8 : H3 22 H3 + 41 8 5 = #__O@_O# : len= 8 : NO 00 NO + 42 8 6 = #__O@OO# : len= 8 : S4 00 S4 + 43 8 7 = #__O@___# : len= 9 : NO 00 NO + 44 8 8 = #__O@O__# : len= 9 : H3 22 H3 + 45 9 0 = #_O_@# : len= 6 : NO 00 NO + 46 9 1 = #_O_@_# : len= 7 : NO 00 NO + 47 9 2 = #_O_@O# : len= 7 : NO 00 NO + 48 9 3 = #_O_@__# : len= 8 : NO 00 NO + 49 9 4 = #_O_@O_# : len= 8 : D3 10 D3 + 50 9 5 = #_O_@_O# : len= 8 : NO 00 NO + 51 9 6 = #_O_@OO# : len= 8 : D4 00 D4 + 52 9 7 = #_O_@___# : len= 9 : NO 00 NO + 53 9 8 = #_O_@O__# : len= 9 : D3 10 D3 + 54 9 9 = #_O_@_O_# : len= 9 : NO 00 NO + 55 10 0 = #_OO@# : len= 6 : NO 00 NO + 56 10 1 = #_OO@_# : len= 7 : NO 00 NO + 57 10 2 = #_OO@O# : len= 7 : S4 00 S4 + 58 10 3 = #_OO@__# : len= 8 : H3 31 H3 + 59 10 4 = #_OO@O_# : len= 8 : H4 00 H4 + 60 10 5 = #_OO@_O# : len= 8 : D4 00 D4 + 61 10 6 = #_OO@OO# : len= 8 : L5 00 L5 + 62 10 7 = #_OO@___# : len= 9 : H3 31 H3 + 63 10 8 = #_OO@O__# : len= 9 : H4 00 H4 + 64 10 9 = #_OO@_O_# : len= 9 : D4 00 D4 + 65 10 10 = #_OO@OO_# : len= 9 : L5 00 L5 + 66 11 0 = #O__@# : len= 6 : NO 00 NO + 67 11 1 = #O__@_# : len= 7 : NO 00 NO + 68 11 2 = #O__@O# : len= 7 : NO 00 NO + 69 11 3 = #O__@__# : len= 8 : NO 00 NO + 70 11 4 = #O__@O_# : len= 8 : NO 00 NO + 71 11 5 = #O__@_O# : len= 8 : NO 00 NO + 72 11 6 = #O__@OO# : len= 8 : NO 00 NO + 73 11 7 = #O__@___# : len= 9 : NO 00 NO + 74 11 8 = #O__@O__# : len= 9 : NO 00 NO + 75 11 9 = #O__@_O_# : len= 9 : NO 00 NO + 76 11 10 = #O__@OO_# : len= 9 : NO 00 H3 + 77 11 11 = #O__@__O# : len= 9 : NO 00 NO + 78 12 0 = #O_O@# : len= 6 : NO 00 NO + 79 12 1 = #O_O@_# : len= 7 : NO 00 NO + 80 12 2 = #O_O@O# : len= 7 : D4 00 D4 + 81 12 3 = #O_O@__# : len= 8 : NO 00 NO + 82 12 4 = #O_O@O_# : len= 8 : D4 00 D4 + 83 12 5 = #O_O@_O# : len= 8 : NO 00 NO + 84 12 6 = #O_O@OO# : len= 8 : NO 00 D4 + 85 12 7 = #O_O@___# : len= 9 : NO 00 NO + 86 12 8 = #O_O@O__# : len= 9 : D4 00 D4 + 87 12 9 = #O_O@_O_# : len= 9 : NO 00 D3 + 88 12 10 = #O_O@OO_# : len= 9 : S4 00 H4 + 89 12 11 = #O_O@__O# : len= 9 : NO 00 NO + 90 12 12 = #O_O@O_O# : len= 9 : X4 00 X4 + 91 13 0 = #OO_@# : len= 6 : NO 00 NO + 92 13 1 = #OO_@_# : len= 7 : NO 00 NO + 93 13 2 = #OO_@O# : len= 7 : D4 00 D4 + 94 13 3 = #OO_@__# : len= 8 : NO 00 NO + 95 13 4 = #OO_@O_# : len= 8 : D4 00 D4 + 96 13 5 = #OO_@_O# : len= 8 : NO 00 NO + 97 13 6 = #OO_@OO# : len= 8 : NO 00 D4 + 98 13 7 = #OO_@___# : len= 9 : NO 00 NO + 99 13 8 = #OO_@O__# : len= 9 : D4 00 D4 + 100 13 9 = #OO_@_O_# : len= 9 : NO 00 NO + 101 13 10 = #OO_@OO_# : len= 9 : NO 00 D4 + 102 13 11 = #OO_@__O# : len= 9 : NO 00 NO + 103 13 12 = #OO_@O_O# : len= 9 : D4 00 D4 + 104 13 13 = #OO_@_OO# : len= 9 : NO 00 NO + 105 14 0 = #OOO@# : len= 6 : NO 00 NO + 106 14 1 = #OOO@_# : len= 7 : S4 00 S4 + 107 14 2 = #OOO@O# : len= 7 : L5 00 L5 + 108 14 3 = #OOO@__# : len= 8 : S4 00 S4 + 109 14 4 = #OOO@O_# : len= 8 : L5 00 L5 + 110 14 5 = #OOO@_O# : len= 8 : NO 00 D4 + 111 14 6 = #OOO@OO# : len= 8 : L6 00 L6 + 112 14 7 = #OOO@___# : len= 9 : S4 00 S4 + 113 14 8 = #OOO@O__# : len= 9 : L5 00 L5 + 114 14 9 = #OOO@_O_# : len= 9 : NO 00 D4 + 115 14 10 = #OOO@OO_# : len= 9 : L6 00 L6 + 116 14 11 = #OOO@__O# : len= 9 : S4 00 S4 + 117 14 12 = #OOO@O_O# : len= 9 : L5 00 L5 + 118 14 13 = #OOO@_OO# : len= 9 : NO 00 D4 + 119 14 14 = #OOO@OOO# : len= 9 : L6 00 L6 + 120 15 0 = #____@# : len= 7 : NO 00 NO + 121 15 1 = #____@_# : len= 8 : NO 00 NO + 122 15 2 = #____@O# : len= 8 : NO 00 NO + 123 15 3 = #____@__# : len= 9 : NO 00 NO + 124 15 4 = #____@O_# : len= 9 : NO 00 NO + 125 15 5 = #____@_O# : len= 9 : NO 00 NO + 126 15 6 = #____@OO# : len= 9 : NO 00 NO + 127 15 7 = #____@___# : len=10 : NO 00 NO + 128 15 8 = #____@O__# : len=10 : NO 00 NO + 129 15 9 = #____@_O_# : len=10 : NO 00 NO + 130 15 10 = #____@OO_# : len=10 : H3 13 H3 + 131 15 11 = #____@__O# : len=10 : NO 00 NO + 132 15 12 = #____@O_O# : len=10 : NO 00 NO + 133 15 13 = #____@_OO# : len=10 : NO 00 NO + 134 15 14 = #____@OOO# : len=10 : S4 00 S4 + 135 15 15 = #____@____# : len=11 : NO 00 NO + 136 16 0 = #___O@# : len= 7 : NO 00 NO + 137 16 1 = #___O@_# : len= 8 : NO 00 NO + 138 16 2 = #___O@O# : len= 8 : NO 00 NO + 139 16 3 = #___O@__# : len= 9 : NO 00 NO + 140 16 4 = #___O@O_# : len= 9 : H3 22 H3 + 141 16 5 = #___O@_O# : len= 9 : NO 00 NO + 142 16 6 = #___O@OO# : len= 9 : S4 00 S4 + 143 16 7 = #___O@___# : len=10 : NO 00 NO + 144 16 8 = #___O@O__# : len=10 : H3 22 H3 + 145 16 9 = #___O@_O_# : len=10 : D3 01 D3 + 146 16 10 = #___O@OO_# : len=10 : H4 00 H4 + 147 16 11 = #___O@__O# : len=10 : NO 00 NO + 148 16 12 = #___O@O_O# : len=10 : D4 00 D4 + 149 16 13 = #___O@_OO# : len=10 : D4 00 D4 + 150 16 14 = #___O@OOO# : len=10 : L5 00 L5 + 151 16 15 = #___O@____# : len=11 : NO 00 NO + 152 16 16 = #___O@O___# : len=11 : H3 22 H3 + 153 17 0 = #__O_@# : len= 7 : NO 00 NO + 154 17 1 = #__O_@_# : len= 8 : NO 00 NO + 155 17 2 = #__O_@O# : len= 8 : NO 00 NO + 156 17 3 = #__O_@__# : len= 9 : NO 00 NO + 157 17 4 = #__O_@O_# : len= 9 : D3 10 D3 + 158 17 5 = #__O_@_O# : len= 9 : NO 00 NO + 159 17 6 = #__O_@OO# : len= 9 : D4 00 D4 + 160 17 7 = #__O_@___# : len=10 : NO 00 NO + 161 17 8 = #__O_@O__# : len=10 : D3 10 D3 + 162 17 9 = #__O_@_O_# : len=10 : NO 00 NO + 163 17 10 = #__O_@OO_# : len=10 : D4 00 D4 + 164 17 11 = #__O_@__O# : len=10 : NO 00 NO + 165 17 12 = #__O_@O_O# : len=10 : NO 00 D3 + 166 17 13 = #__O_@_OO# : len=10 : NO 00 NO + 167 17 14 = #__O_@OOO# : len=10 : NO 00 D4 + 168 17 15 = #__O_@____# : len=11 : NO 00 NO + 169 17 16 = #__O_@O___# : len=11 : D3 10 D3 + 170 17 17 = #__O_@_O__# : len=11 : NO 00 NO + 171 18 0 = #__OO@# : len= 7 : NO 00 NO + 172 18 1 = #__OO@_# : len= 8 : H3 31 H3 + 173 18 2 = #__OO@O# : len= 8 : S4 00 S4 + 174 18 3 = #__OO@__# : len= 9 : H3 31 H3 + 175 18 4 = #__OO@O_# : len= 9 : H4 00 H4 + 176 18 5 = #__OO@_O# : len= 9 : D4 00 D4 + 177 18 6 = #__OO@OO# : len= 9 : L5 00 L5 + 178 18 7 = #__OO@___# : len=10 : H3 31 H3 + 179 18 8 = #__OO@O__# : len=10 : H4 00 H4 + 180 18 9 = #__OO@_O_# : len=10 : D4 00 D4 + 181 18 10 = #__OO@OO_# : len=10 : L5 00 L5 + 182 18 11 = #__OO@__O# : len=10 : H3 31 H3 + 183 18 12 = #__OO@O_O# : len=10 : S4 00 H4 + 184 18 13 = #__OO@_OO# : len=10 : NO 00 D4 + 185 18 14 = #__OO@OOO# : len=10 : L6 00 L6 + 186 18 15 = #__OO@____# : len=11 : H3 31 H3 + 187 18 16 = #__OO@O___# : len=11 : H4 00 H4 + 188 18 17 = #__OO@_O__# : len=11 : D4 00 D4 + 189 18 18 = #__OO@OO__# : len=11 : L5 00 L5 + 190 19 0 = #_O__@# : len= 7 : NO 00 NO + 191 19 1 = #_O__@_# : len= 8 : NO 00 NO + 192 19 2 = #_O__@O# : len= 8 : NO 00 NO + 193 19 3 = #_O__@__# : len= 9 : NO 00 NO + 194 19 4 = #_O__@O_# : len= 9 : NO 00 NO + 195 19 5 = #_O__@_O# : len= 9 : NO 00 NO + 196 19 6 = #_O__@OO# : len= 9 : NO 00 NO + 197 19 7 = #_O__@___# : len=10 : NO 00 NO + 198 19 8 = #_O__@O__# : len=10 : NO 00 NO + 199 19 9 = #_O__@_O_# : len=10 : NO 00 NO + 200 19 10 = #_O__@OO_# : len=10 : NO 00 H3 + 201 19 11 = #_O__@__O# : len=10 : NO 00 NO + 202 19 12 = #_O__@O_O# : len=10 : NO 00 NO + 203 19 13 = #_O__@_OO# : len=10 : NO 00 NO + 204 19 14 = #_O__@OOO# : len=10 : S4 00 S4 + 205 19 15 = #_O__@____# : len=11 : NO 00 NO + 206 19 16 = #_O__@O___# : len=11 : NO 00 NO + 207 19 17 = #_O__@_O__# : len=11 : NO 00 NO + 208 19 18 = #_O__@OO__# : len=11 : H3 13 H3 + 209 19 19 = #_O__@__O_# : len=11 : NO 00 NO + 210 20 0 = #_O_O@# : len= 7 : NO 00 NO + 211 20 1 = #_O_O@_# : len= 8 : D3 20 D3 + 212 20 2 = #_O_O@O# : len= 8 : D4 00 D4 + 213 20 3 = #_O_O@__# : len= 9 : D3 20 D3 + 214 20 4 = #_O_O@O_# : len= 9 : D4 00 D4 + 215 20 5 = #_O_O@_O# : len= 9 : NO 00 D3 + 216 20 6 = #_O_O@OO# : len= 9 : NO 00 D4 + 217 20 7 = #_O_O@___# : len=10 : D3 20 D3 + 218 20 8 = #_O_O@O__# : len=10 : D4 00 D4 + 219 20 9 = #_O_O@_O_# : len=10 : NO 00 D3 + 220 20 10 = #_O_O@OO_# : len=10 : S4 00 H4 + 221 20 11 = #_O_O@__O# : len=10 : D3 20 D3 + 222 20 12 = #_O_O@O_O# : len=10 : X4 00 X4 + 223 20 13 = #_O_O@_OO# : len=10 : D4 00 D4 + 224 20 14 = #_O_O@OOO# : len=10 : L5 00 L5 + 225 20 15 = #_O_O@____# : len=11 : D3 20 D3 + 226 20 16 = #_O_O@O___# : len=11 : D4 00 D4 + 227 20 17 = #_O_O@_O__# : len=11 : NO 00 D3 + 228 20 18 = #_O_O@OO__# : len=11 : S4 00 H4 + 229 20 19 = #_O_O@__O_# : len=11 : D3 20 D3 + 230 20 20 = #_O_O@O_O_# : len=11 : X4 00 X4 + 231 21 0 = #_OO_@# : len= 7 : NO 00 NO + 232 21 1 = #_OO_@_# : len= 8 : D3 10 D3 + 233 21 2 = #_OO_@O# : len= 8 : D4 00 D4 + 234 21 3 = #_OO_@__# : len= 9 : D3 10 D3 + 235 21 4 = #_OO_@O_# : len= 9 : D4 00 D4 + 236 21 5 = #_OO_@_O# : len= 9 : NO 00 D3 + 237 21 6 = #_OO_@OO# : len= 9 : NO 00 D4 + 238 21 7 = #_OO_@___# : len=10 : D3 10 D3 + 239 21 8 = #_OO_@O__# : len=10 : D4 00 D4 + 240 21 9 = #_OO_@_O_# : len=10 : NO 00 D3 + 241 21 10 = #_OO_@OO_# : len=10 : NO 00 D4 + 242 21 11 = #_OO_@__O# : len=10 : D3 10 D3 + 243 21 12 = #_OO_@O_O# : len=10 : D4 00 D4 + 244 21 13 = #_OO_@_OO# : len=10 : NO 00 D3 + 245 21 14 = #_OO_@OOO# : len=10 : NO 00 D4 + 246 21 15 = #_OO_@____# : len=11 : D3 10 D3 + 247 21 16 = #_OO_@O___# : len=11 : D4 00 D4 + 248 21 17 = #_OO_@_O__# : len=11 : NO 00 D3 + 249 21 18 = #_OO_@OO__# : len=11 : NO 00 D4 + 250 21 19 = #_OO_@__O_# : len=11 : D3 10 D3 + 251 21 20 = #_OO_@O_O_# : len=11 : D4 00 D4 + 252 21 21 = #_OO_@_OO_# : len=11 : NO 00 D3 + 253 22 0 = #_OOO@# : len= 7 : S4 00 S4 + 254 22 1 = #_OOO@_# : len= 8 : H4 00 H4 + 255 22 2 = #_OOO@O# : len= 8 : L5 00 L5 + 256 22 3 = #_OOO@__# : len= 9 : H4 00 H4 + 257 22 4 = #_OOO@O_# : len= 9 : L5 00 L5 + 258 22 5 = #_OOO@_O# : len= 9 : S4 00 H4 + 259 22 6 = #_OOO@OO# : len= 9 : L6 00 L6 + 260 22 7 = #_OOO@___# : len=10 : H4 00 H4 + 261 22 8 = #_OOO@O__# : len=10 : L5 00 L5 + 262 22 9 = #_OOO@_O_# : len=10 : S4 00 H4 + 263 22 10 = #_OOO@OO_# : len=10 : L6 00 L6 + 264 22 11 = #_OOO@__O# : len=10 : H4 00 H4 + 265 22 12 = #_OOO@O_O# : len=10 : L5 00 L5 + 266 22 13 = #_OOO@_OO# : len=10 : S4 00 H4 + 267 22 14 = #_OOO@OOO# : len=10 : L6 00 L6 + 268 22 15 = #_OOO@____# : len=11 : H4 00 H4 + 269 22 16 = #_OOO@O___# : len=11 : L5 00 L5 + 270 22 17 = #_OOO@_O__# : len=11 : S4 00 H4 + 271 22 18 = #_OOO@OO__# : len=11 : L6 00 L6 + 272 22 19 = #_OOO@__O_# : len=11 : H4 00 H4 + 273 22 20 = #_OOO@O_O_# : len=11 : L5 00 L5 + 274 22 21 = #_OOO@_OO_# : len=11 : S4 00 H4 + 275 22 22 = #_OOO@OOO_# : len=11 : L6 00 L6 + 276 23 0 = #O___@# : len= 7 : NO 00 NO + 277 23 1 = #O___@_# : len= 8 : NO 00 NO + 278 23 2 = #O___@O# : len= 8 : NO 00 NO + 279 23 3 = #O___@__# : len= 9 : NO 00 NO + 280 23 4 = #O___@O_# : len= 9 : NO 00 NO + 281 23 5 = #O___@_O# : len= 9 : NO 00 NO + 282 23 6 = #O___@OO# : len= 9 : NO 00 NO + 283 23 7 = #O___@___# : len=10 : NO 00 NO + 284 23 8 = #O___@O__# : len=10 : NO 00 NO + 285 23 9 = #O___@_O_# : len=10 : NO 00 NO + 286 23 10 = #O___@OO_# : len=10 : H3 13 H3 + 287 23 11 = #O___@__O# : len=10 : NO 00 NO + 288 23 12 = #O___@O_O# : len=10 : NO 00 NO + 289 23 13 = #O___@_OO# : len=10 : NO 00 NO + 290 23 14 = #O___@OOO# : len=10 : S4 00 S4 + 291 23 15 = #O___@____# : len=11 : NO 00 NO + 292 23 16 = #O___@O___# : len=11 : NO 00 NO + 293 23 17 = #O___@_O__# : len=11 : NO 00 NO + 294 23 18 = #O___@OO__# : len=11 : H3 13 H3 + 295 23 19 = #O___@__O_# : len=11 : NO 00 NO + 296 23 20 = #O___@O_O_# : len=11 : D3 02 D3 + 297 23 21 = #O___@_OO_# : len=11 : D3 01 D3 + 298 23 22 = #O___@OOO_# : len=11 : H4 00 H4 + 299 23 23 = #O___@___O# : len=11 : NO 00 NO + 300 24 0 = #O__O@# : len= 7 : NO 00 NO + 301 24 1 = #O__O@_# : len= 8 : NO 00 NO + 302 24 2 = #O__O@O# : len= 8 : NO 00 NO + 303 24 3 = #O__O@__# : len= 9 : NO 00 NO + 304 24 4 = #O__O@O_# : len= 9 : NO 00 H3 + 305 24 5 = #O__O@_O# : len= 9 : NO 00 NO + 306 24 6 = #O__O@OO# : len= 9 : S4 00 S4 + 307 24 7 = #O__O@___# : len=10 : NO 00 NO + 308 24 8 = #O__O@O__# : len=10 : H3 22 H3 + 309 24 9 = #O__O@_O_# : len=10 : D3 01 D3 + 310 24 10 = #O__O@OO_# : len=10 : H4 00 H4 + 311 24 11 = #O__O@__O# : len=10 : NO 00 NO + 312 24 12 = #O__O@O_O# : len=10 : D4 00 D4 + 313 24 13 = #O__O@_OO# : len=10 : D4 00 D4 + 314 24 14 = #O__O@OOO# : len=10 : L5 00 L5 + 315 24 15 = #O__O@____# : len=11 : NO 00 NO + 316 24 16 = #O__O@O___# : len=11 : H3 22 H3 + 317 24 17 = #O__O@_O__# : len=11 : D3 01 D3 + 318 24 18 = #O__O@OO__# : len=11 : H4 00 H4 + 319 24 19 = #O__O@__O_# : len=11 : NO 00 NO + 320 24 20 = #O__O@O_O_# : len=11 : D4 00 D4 + 321 24 21 = #O__O@_OO_# : len=11 : D4 00 D4 + 322 24 22 = #O__O@OOO_# : len=11 : L5 00 L5 + 323 24 23 = #O__O@___O# : len=11 : NO 00 NO + 324 24 24 = #O__O@O__O# : len=11 : NO 00 H3 + 325 25 0 = #O_O_@# : len= 7 : NO 00 NO + 326 25 1 = #O_O_@_# : len= 8 : NO 00 NO + 327 25 2 = #O_O_@O# : len= 8 : NO 00 NO + 328 25 3 = #O_O_@__# : len= 9 : NO 00 NO + 329 25 4 = #O_O_@O_# : len= 9 : NO 00 D3 + 330 25 5 = #O_O_@_O# : len= 9 : NO 00 NO + 331 25 6 = #O_O_@OO# : len= 9 : D4 00 D4 + 332 25 7 = #O_O_@___# : len=10 : NO 00 NO + 333 25 8 = #O_O_@O__# : len=10 : NO 00 D3 + 334 25 9 = #O_O_@_O_# : len=10 : NO 00 NO + 335 25 10 = #O_O_@OO_# : len=10 : D4 00 D4 + 336 25 11 = #O_O_@__O# : len=10 : NO 00 NO + 337 25 12 = #O_O_@O_O# : len=10 : NO 00 D3 + 338 25 13 = #O_O_@_OO# : len=10 : NO 00 NO + 339 25 14 = #O_O_@OOO# : len=10 : NO 00 D4 + 340 25 15 = #O_O_@____# : len=11 : NO 00 NO + 341 25 16 = #O_O_@O___# : len=11 : NO 00 D3 + 342 25 17 = #O_O_@_O__# : len=11 : NO 00 NO + 343 25 18 = #O_O_@OO__# : len=11 : D4 00 D4 + 344 25 19 = #O_O_@__O_# : len=11 : NO 00 NO + 345 25 20 = #O_O_@O_O_# : len=11 : NO 00 D3 + 346 25 21 = #O_O_@_OO_# : len=11 : NO 00 D3 + 347 25 22 = #O_O_@OOO_# : len=11 : S4 00 H4 + 348 25 23 = #O_O_@___O# : len=11 : NO 00 NO + 349 25 24 = #O_O_@O__O# : len=11 : NO 00 D3 + 350 25 25 = #O_O_@_O_O# : len=11 : NO 00 NO + 351 26 0 = #O_OO@# : len= 7 : D4 00 D4 + 352 26 1 = #O_OO@_# : len= 8 : D4 00 D4 + 353 26 2 = #O_OO@O# : len= 8 : NO 00 D4 + 354 26 3 = #O_OO@__# : len= 9 : D4 00 D4 + 355 26 4 = #O_OO@O_# : len= 9 : S4 00 H4 + 356 26 5 = #O_OO@_O# : len= 9 : X4 00 X4 + 357 26 6 = #O_OO@OO# : len= 9 : L5 00 L5 + 358 26 7 = #O_OO@___# : len=10 : D4 00 D4 + 359 26 8 = #O_OO@O__# : len=10 : S4 00 H4 + 360 26 9 = #O_OO@_O_# : len=10 : X4 00 X4 + 361 26 10 = #O_OO@OO_# : len=10 : L5 00 L5 + 362 26 11 = #O_OO@__O# : len=10 : D4 00 D4 + 363 26 12 = #O_OO@O_O# : len=10 : NO 00 H4 + 364 26 13 = #O_OO@_OO# : len=10 : D4 00 X4 + 365 26 14 = #O_OO@OOO# : len=10 : L6 00 L6 + 366 26 15 = #O_OO@____# : len=11 : D4 00 D4 + 367 26 16 = #O_OO@O___# : len=11 : S4 00 H4 + 368 26 17 = #O_OO@_O__# : len=11 : X4 00 X4 + 369 26 18 = #O_OO@OO__# : len=11 : L5 00 L5 + 370 26 19 = #O_OO@__O_# : len=11 : D4 00 D4 + 371 26 20 = #O_OO@O_O_# : len=11 : NO 00 H4 + 372 26 21 = #O_OO@_OO_# : len=11 : D4 00 X4 + 373 26 22 = #O_OO@OOO_# : len=11 : L6 00 L6 + 374 26 23 = #O_OO@___O# : len=11 : D4 00 D4 + 375 26 24 = #O_OO@O__O# : len=11 : S4 00 H4 + 376 26 25 = #O_OO@_O_O# : len=11 : X4 00 X4 + 377 26 26 = #O_OO@OO_O# : len=11 : L5 00 L5 + 378 27 0 = #OO__@# : len= 7 : NO 00 NO + 379 27 1 = #OO__@_# : len= 8 : NO 00 NO + 380 27 2 = #OO__@O# : len= 8 : NO 00 NO + 381 27 3 = #OO__@__# : len= 9 : NO 00 NO + 382 27 4 = #OO__@O_# : len= 9 : NO 00 NO + 383 27 5 = #OO__@_O# : len= 9 : NO 00 NO + 384 27 6 = #OO__@OO# : len= 9 : NO 00 NO + 385 27 7 = #OO__@___# : len=10 : NO 00 NO + 386 27 8 = #OO__@O__# : len=10 : NO 00 NO + 387 27 9 = #OO__@_O_# : len=10 : NO 00 NO + 388 27 10 = #OO__@OO_# : len=10 : NO 00 H3 + 389 27 11 = #OO__@__O# : len=10 : NO 00 NO + 390 27 12 = #OO__@O_O# : len=10 : NO 00 NO + 391 27 13 = #OO__@_OO# : len=10 : NO 00 NO + 392 27 14 = #OO__@OOO# : len=10 : S4 00 S4 + 393 27 15 = #OO__@____# : len=11 : NO 00 NO + 394 27 16 = #OO__@O___# : len=11 : NO 00 NO + 395 27 17 = #OO__@_O__# : len=11 : NO 00 NO + 396 27 18 = #OO__@OO__# : len=11 : H3 13 H3 + 397 27 19 = #OO__@__O_# : len=11 : NO 00 NO + 398 27 20 = #OO__@O_O_# : len=11 : D3 02 D3 + 399 27 21 = #OO__@_OO_# : len=11 : D3 01 D3 + 400 27 22 = #OO__@OOO_# : len=11 : H4 00 H4 + 401 27 23 = #OO__@___O# : len=11 : NO 00 NO + 402 27 24 = #OO__@O__O# : len=11 : NO 00 NO + 403 27 25 = #OO__@_O_O# : len=11 : NO 00 NO + 404 27 26 = #OO__@OO_O# : len=11 : D4 00 D4 + 405 27 27 = #OO__@__OO# : len=11 : NO 00 NO + 406 28 0 = #OO_O@# : len= 7 : D4 00 D4 + 407 28 1 = #OO_O@_# : len= 8 : D4 00 D4 + 408 28 2 = #OO_O@O# : len= 8 : NO 00 D4 + 409 28 3 = #OO_O@__# : len= 9 : D4 00 D4 + 410 28 4 = #OO_O@O_# : len= 9 : NO 00 D4 + 411 28 5 = #OO_O@_O# : len= 9 : D4 00 D4 + 412 28 6 = #OO_O@OO# : len= 9 : NO 00 D4 + 413 28 7 = #OO_O@___# : len=10 : D4 00 D4 + 414 28 8 = #OO_O@O__# : len=10 : NO 00 D4 + 415 28 9 = #OO_O@_O_# : len=10 : D4 00 D4 + 416 28 10 = #OO_O@OO_# : len=10 : S4 00 H4 + 417 28 11 = #OO_O@__O# : len=10 : D4 00 D4 + 418 28 12 = #OO_O@O_O# : len=10 : D4 00 X4 + 419 28 13 = #OO_O@_OO# : len=10 : X4 00 X4 + 420 28 14 = #OO_O@OOO# : len=10 : L5 00 L5 + 421 28 15 = #OO_O@____# : len=11 : D4 00 D4 + 422 28 16 = #OO_O@O___# : len=11 : NO 00 D4 + 423 28 17 = #OO_O@_O__# : len=11 : D4 00 D4 + 424 28 18 = #OO_O@OO__# : len=11 : S4 00 H4 + 425 28 19 = #OO_O@__O_# : len=11 : D4 00 D4 + 426 28 20 = #OO_O@O_O_# : len=11 : D4 00 X4 + 427 28 21 = #OO_O@_OO_# : len=11 : X4 00 X4 + 428 28 22 = #OO_O@OOO_# : len=11 : L5 00 L5 + 429 28 23 = #OO_O@___O# : len=11 : D4 00 D4 + 430 28 24 = #OO_O@O__O# : len=11 : NO 00 D4 + 431 28 25 = #OO_O@_O_O# : len=11 : D4 00 D4 + 432 28 26 = #OO_O@OO_O# : len=11 : NO 00 H4 + 433 28 27 = #OO_O@__OO# : len=11 : D4 00 D4 + 434 28 28 = #OO_O@O_OO# : len=11 : NO 00 X4 + 435 29 0 = #OOO_@# : len= 7 : D4 00 D4 + 436 29 1 = #OOO_@_# : len= 8 : D4 00 D4 + 437 29 2 = #OOO_@O# : len= 8 : NO 00 D4 + 438 29 3 = #OOO_@__# : len= 9 : D4 00 D4 + 439 29 4 = #OOO_@O_# : len= 9 : NO 00 D4 + 440 29 5 = #OOO_@_O# : len= 9 : D4 00 D4 + 441 29 6 = #OOO_@OO# : len= 9 : NO 00 D4 + 442 29 7 = #OOO_@___# : len=10 : D4 00 D4 + 443 29 8 = #OOO_@O__# : len=10 : NO 00 D4 + 444 29 9 = #OOO_@_O_# : len=10 : D4 00 D4 + 445 29 10 = #OOO_@OO_# : len=10 : NO 00 D4 + 446 29 11 = #OOO_@__O# : len=10 : D4 00 D4 + 447 29 12 = #OOO_@O_O# : len=10 : NO 00 D4 + 448 29 13 = #OOO_@_OO# : len=10 : D4 00 D4 + 449 29 14 = #OOO_@OOO# : len=10 : NO 00 D4 + 450 29 15 = #OOO_@____# : len=11 : D4 00 D4 + 451 29 16 = #OOO_@O___# : len=11 : NO 00 D4 + 452 29 17 = #OOO_@_O__# : len=11 : D4 00 D4 + 453 29 18 = #OOO_@OO__# : len=11 : NO 00 D4 + 454 29 19 = #OOO_@__O_# : len=11 : D4 00 D4 + 455 29 20 = #OOO_@O_O_# : len=11 : NO 00 D4 + 456 29 21 = #OOO_@_OO_# : len=11 : D4 00 D4 + 457 29 22 = #OOO_@OOO_# : len=11 : S4 00 H4 + 458 29 23 = #OOO_@___O# : len=11 : D4 00 D4 + 459 29 24 = #OOO_@O__O# : len=11 : NO 00 D4 + 460 29 25 = #OOO_@_O_O# : len=11 : D4 00 D4 + 461 29 26 = #OOO_@OO_O# : len=11 : D4 00 X4 + 462 29 27 = #OOO_@__OO# : len=11 : D4 00 D4 + 463 29 28 = #OOO_@O_OO# : len=11 : D4 00 X4 + 464 29 29 = #OOO_@_OOO# : len=11 : X4 00 X4 + 465 30 0 = #OOOO@# : len= 7 : L5 00 L5 + 466 30 1 = #OOOO@_# : len= 8 : L5 00 L5 + 467 30 2 = #OOOO@O# : len= 8 : L6 00 L6 + 468 30 3 = #OOOO@__# : len= 9 : L5 00 L5 + 469 30 4 = #OOOO@O_# : len= 9 : L6 00 L6 + 470 30 5 = #OOOO@_O# : len= 9 : L5 00 L5 + 471 30 6 = #OOOO@OO# : len= 9 : L6 00 L6 + 472 30 7 = #OOOO@___# : len=10 : L5 00 L5 + 473 30 8 = #OOOO@O__# : len=10 : L6 00 L6 + 474 30 9 = #OOOO@_O_# : len=10 : L5 00 L5 + 475 30 10 = #OOOO@OO_# : len=10 : L6 00 L6 + 476 30 11 = #OOOO@__O# : len=10 : L5 00 L5 + 477 30 12 = #OOOO@O_O# : len=10 : L6 00 L6 + 478 30 13 = #OOOO@_OO# : len=10 : L5 00 L5 + 479 30 14 = #OOOO@OOO# : len=10 : L6 00 L6 + 480 30 15 = #OOOO@____# : len=11 : L5 00 L5 + 481 30 16 = #OOOO@O___# : len=11 : L6 00 L6 + 482 30 17 = #OOOO@_O__# : len=11 : L5 00 L5 + 483 30 18 = #OOOO@OO__# : len=11 : L6 00 L6 + 484 30 19 = #OOOO@__O_# : len=11 : L5 00 L5 + 485 30 20 = #OOOO@O_O_# : len=11 : L6 00 L6 + 486 30 21 = #OOOO@_OO_# : len=11 : L5 00 L5 + 487 30 22 = #OOOO@OOO_# : len=11 : L6 00 L6 + 488 30 23 = #OOOO@___O# : len=11 : L5 00 L5 + 489 30 24 = #OOOO@O__O# : len=11 : L6 00 L6 + 490 30 25 = #OOOO@_O_O# : len=11 : L5 00 L5 + 491 30 26 = #OOOO@OO_O# : len=11 : L6 00 L6 + 492 30 27 = #OOOO@__OO# : len=11 : L5 00 L5 + 493 30 28 = #OOOO@O_OO# : len=11 : L6 00 L6 + 494 30 29 = #OOOO@_OOO# : len=11 : L5 00 L5 + 495 30 30 = #OOOO@OOOO# : len=11 : L6 00 L6 + 496 31 0 = _____@# : len= 7 : NO 00 NO + 497 31 1 = _____@_# : len= 8 : NO 00 NO + 498 31 2 = _____@O# : len= 8 : NO 00 NO + 499 31 3 = _____@__# : len= 9 : NO 00 NO + 500 31 4 = _____@O_# : len= 9 : NO 00 NO + 501 31 5 = _____@_O# : len= 9 : NO 00 NO + 502 31 6 = _____@OO# : len= 9 : NO 00 NO + 503 31 7 = _____@___# : len=10 : NO 00 NO + 504 31 8 = _____@O__# : len=10 : NO 00 NO + 505 31 9 = _____@_O_# : len=10 : NO 00 NO + 506 31 10 = _____@OO_# : len=10 : H3 13 H3 + 507 31 11 = _____@__O# : len=10 : NO 00 NO + 508 31 12 = _____@O_O# : len=10 : NO 00 NO + 509 31 13 = _____@_OO# : len=10 : NO 00 NO + 510 31 14 = _____@OOO# : len=10 : S4 00 S4 + 511 31 15 = _____@____# : len=11 : NO 00 NO + 512 31 16 = _____@O___# : len=11 : NO 00 NO + 513 31 17 = _____@_O__# : len=11 : NO 00 NO + 514 31 18 = _____@OO__# : len=11 : H3 13 H3 + 515 31 19 = _____@__O_# : len=11 : NO 00 NO + 516 31 20 = _____@O_O_# : len=11 : D3 02 D3 + 517 31 21 = _____@_OO_# : len=11 : D3 01 D3 + 518 31 22 = _____@OOO_# : len=11 : H4 00 H4 + 519 31 23 = _____@___O# : len=11 : NO 00 NO + 520 31 24 = _____@O__O# : len=11 : NO 00 NO + 521 31 25 = _____@_O_O# : len=11 : NO 00 NO + 522 31 26 = _____@OO_O# : len=11 : D4 00 D4 + 523 31 27 = _____@__OO# : len=11 : NO 00 NO + 524 31 28 = _____@O_OO# : len=11 : D4 00 D4 + 525 31 29 = _____@_OOO# : len=11 : D4 00 D4 + 526 31 30 = _____@OOOO# : len=11 : L5 00 L5 + 527 31 31 = _____@_____ : len=11 : NO 00 NO + 528 32 0 = ____O@# : len= 7 : NO 00 NO + 529 32 1 = ____O@_# : len= 8 : NO 00 NO + 530 32 2 = ____O@O# : len= 8 : NO 00 NO + 531 32 3 = ____O@__# : len= 9 : NO 00 NO + 532 32 4 = ____O@O_# : len= 9 : H3 22 H3 + 533 32 5 = ____O@_O# : len= 9 : NO 00 NO + 534 32 6 = ____O@OO# : len= 9 : S4 00 S4 + 535 32 7 = ____O@___# : len=10 : NO 00 NO + 536 32 8 = ____O@O__# : len=10 : H3 22 H3 + 537 32 9 = ____O@_O_# : len=10 : D3 01 D3 + 538 32 10 = ____O@OO_# : len=10 : H4 00 H4 + 539 32 11 = ____O@__O# : len=10 : NO 00 NO + 540 32 12 = ____O@O_O# : len=10 : D4 00 D4 + 541 32 13 = ____O@_OO# : len=10 : D4 00 D4 + 542 32 14 = ____O@OOO# : len=10 : L5 00 L5 + 543 32 15 = ____O@____# : len=11 : NO 00 NO + 544 32 16 = ____O@O___# : len=11 : H3 22 H3 + 545 32 17 = ____O@_O__# : len=11 : D3 01 D3 + 546 32 18 = ____O@OO__# : len=11 : H4 00 H4 + 547 32 19 = ____O@__O_# : len=11 : NO 00 NO + 548 32 20 = ____O@O_O_# : len=11 : D4 00 D4 + 549 32 21 = ____O@_OO_# : len=11 : D4 00 D4 + 550 32 22 = ____O@OOO_# : len=11 : L5 00 L5 + 551 32 23 = ____O@___O# : len=11 : NO 00 NO + 552 32 24 = ____O@O__O# : len=11 : H3 22 H3 + 553 32 25 = ____O@_O_O# : len=11 : NO 00 D3 + 554 32 26 = ____O@OO_O# : len=11 : S4 00 H4 + 555 32 27 = ____O@__OO# : len=11 : NO 00 NO + 556 32 28 = ____O@O_OO# : len=11 : NO 00 D4 + 557 32 29 = ____O@_OOO# : len=11 : NO 00 D4 + 558 32 30 = ____O@OOOO# : len=11 : L6 00 L6 + 559 32 31 = ____O@_____ : len=11 : NO 00 NO + 560 32 32 = ____O@O____ : len=11 : H3 22 H3 + 561 33 0 = ___O_@# : len= 7 : NO 00 NO + 562 33 1 = ___O_@_# : len= 8 : NO 00 NO + 563 33 2 = ___O_@O# : len= 8 : NO 00 NO + 564 33 3 = ___O_@__# : len= 9 : NO 00 NO + 565 33 4 = ___O_@O_# : len= 9 : D3 10 D3 + 566 33 5 = ___O_@_O# : len= 9 : NO 00 NO + 567 33 6 = ___O_@OO# : len= 9 : D4 00 D4 + 568 33 7 = ___O_@___# : len=10 : NO 00 NO + 569 33 8 = ___O_@O__# : len=10 : D3 10 D3 + 570 33 9 = ___O_@_O_# : len=10 : NO 00 NO + 571 33 10 = ___O_@OO_# : len=10 : D4 00 D4 + 572 33 11 = ___O_@__O# : len=10 : NO 00 NO + 573 33 12 = ___O_@O_O# : len=10 : NO 00 D3 + 574 33 13 = ___O_@_OO# : len=10 : NO 00 NO + 575 33 14 = ___O_@OOO# : len=10 : NO 00 D4 + 576 33 15 = ___O_@____# : len=11 : NO 00 NO + 577 33 16 = ___O_@O___# : len=11 : D3 10 D3 + 578 33 17 = ___O_@_O__# : len=11 : NO 00 NO + 579 33 18 = ___O_@OO__# : len=11 : D4 00 D4 + 580 33 19 = ___O_@__O_# : len=11 : NO 00 NO + 581 33 20 = ___O_@O_O_# : len=11 : NO 00 D3 + 582 33 21 = ___O_@_OO_# : len=11 : NO 00 D3 + 583 33 22 = ___O_@OOO_# : len=11 : S4 00 H4 + 584 33 23 = ___O_@___O# : len=11 : NO 00 NO + 585 33 24 = ___O_@O__O# : len=11 : D3 10 D3 + 586 33 25 = ___O_@_O_O# : len=11 : NO 00 NO + 587 33 26 = ___O_@OO_O# : len=11 : X4 00 X4 + 588 33 27 = ___O_@__OO# : len=11 : NO 00 NO + 589 33 28 = ___O_@O_OO# : len=11 : D4 00 D4 + 590 33 29 = ___O_@_OOO# : len=11 : D4 00 D4 + 591 33 30 = ___O_@OOOO# : len=11 : L5 00 L5 + 592 33 31 = ___O_@_____ : len=11 : NO 00 NO + 593 33 32 = ___O_@O____ : len=11 : D3 10 D3 + 594 33 33 = ___O_@_O___ : len=11 : NO 00 NO + 595 34 0 = ___OO@# : len= 7 : NO 00 NO + 596 34 1 = ___OO@_# : len= 8 : H3 31 H3 + 597 34 2 = ___OO@O# : len= 8 : S4 00 S4 + 598 34 3 = ___OO@__# : len= 9 : H3 31 H3 + 599 34 4 = ___OO@O_# : len= 9 : H4 00 H4 + 600 34 5 = ___OO@_O# : len= 9 : D4 00 D4 + 601 34 6 = ___OO@OO# : len= 9 : L5 00 L5 + 602 34 7 = ___OO@___# : len=10 : H3 31 H3 + 603 34 8 = ___OO@O__# : len=10 : H4 00 H4 + 604 34 9 = ___OO@_O_# : len=10 : D4 00 D4 + 605 34 10 = ___OO@OO_# : len=10 : L5 00 L5 + 606 34 11 = ___OO@__O# : len=10 : H3 31 H3 + 607 34 12 = ___OO@O_O# : len=10 : S4 00 H4 + 608 34 13 = ___OO@_OO# : len=10 : NO 00 D4 + 609 34 14 = ___OO@OOO# : len=10 : L6 00 L6 + 610 34 15 = ___OO@____# : len=11 : H3 31 H3 + 611 34 16 = ___OO@O___# : len=11 : H4 00 H4 + 612 34 17 = ___OO@_O__# : len=11 : D4 00 D4 + 613 34 18 = ___OO@OO__# : len=11 : L5 00 L5 + 614 34 19 = ___OO@__O_# : len=11 : H3 31 H3 + 615 34 20 = ___OO@O_O_# : len=11 : S4 00 H4 + 616 34 21 = ___OO@_OO_# : len=11 : NO 00 D4 + 617 34 22 = ___OO@OOO_# : len=11 : L6 00 L6 + 618 34 23 = ___OO@___O# : len=11 : H3 31 H3 + 619 34 24 = ___OO@O__O# : len=11 : H4 00 H4 + 620 34 25 = ___OO@_O_O# : len=11 : D4 00 D4 + 621 34 26 = ___OO@OO_O# : len=11 : L5 00 L5 + 622 34 27 = ___OO@__OO# : len=11 : H3 31 H3 + 623 34 28 = ___OO@O_OO# : len=11 : S4 00 H4 + 624 34 29 = ___OO@_OOO# : len=11 : NO 00 D4 + 625 34 30 = ___OO@OOOO# : len=11 : L6 00 L6 + 626 34 31 = ___OO@_____ : len=11 : H3 31 H3 + 627 34 32 = ___OO@O____ : len=11 : H4 00 H4 + 628 34 33 = ___OO@_O___ : len=11 : D4 00 D4 + 629 34 34 = ___OO@OO___ : len=11 : L5 00 L5 + 630 35 0 = __O__@# : len= 7 : NO 00 NO + 631 35 1 = __O__@_# : len= 8 : NO 00 NO + 632 35 2 = __O__@O# : len= 8 : NO 00 NO + 633 35 3 = __O__@__# : len= 9 : NO 00 NO + 634 35 4 = __O__@O_# : len= 9 : NO 00 NO + 635 35 5 = __O__@_O# : len= 9 : NO 00 NO + 636 35 6 = __O__@OO# : len= 9 : NO 00 NO + 637 35 7 = __O__@___# : len=10 : NO 00 NO + 638 35 8 = __O__@O__# : len=10 : NO 00 NO + 639 35 9 = __O__@_O_# : len=10 : NO 00 NO + 640 35 10 = __O__@OO_# : len=10 : NO 00 H3 + 641 35 11 = __O__@__O# : len=10 : NO 00 NO + 642 35 12 = __O__@O_O# : len=10 : NO 00 NO + 643 35 13 = __O__@_OO# : len=10 : NO 00 NO + 644 35 14 = __O__@OOO# : len=10 : S4 00 S4 + 645 35 15 = __O__@____# : len=11 : NO 00 NO + 646 35 16 = __O__@O___# : len=11 : NO 00 NO + 647 35 17 = __O__@_O__# : len=11 : NO 00 NO + 648 35 18 = __O__@OO__# : len=11 : H3 13 H3 + 649 35 19 = __O__@__O_# : len=11 : NO 00 NO + 650 35 20 = __O__@O_O_# : len=11 : D3 02 D3 + 651 35 21 = __O__@_OO_# : len=11 : D3 01 D3 + 652 35 22 = __O__@OOO_# : len=11 : H4 00 H4 + 653 35 23 = __O__@___O# : len=11 : NO 00 NO + 654 35 24 = __O__@O__O# : len=11 : NO 00 NO + 655 35 25 = __O__@_O_O# : len=11 : NO 00 NO + 656 35 26 = __O__@OO_O# : len=11 : D4 00 D4 + 657 35 27 = __O__@__OO# : len=11 : NO 00 NO + 658 35 28 = __O__@O_OO# : len=11 : D4 00 D4 + 659 35 29 = __O__@_OOO# : len=11 : D4 00 D4 + 660 35 30 = __O__@OOOO# : len=11 : L5 00 L5 + 661 35 31 = __O__@_____ : len=11 : NO 00 NO + 662 35 32 = __O__@O____ : len=11 : NO 00 NO + 663 35 33 = __O__@_O___ : len=11 : NO 00 NO + 664 35 34 = __O__@OO___ : len=11 : H3 13 H3 + 665 35 35 = __O__@__O__ : len=11 : NO 00 NO + 666 36 0 = __O_O@# : len= 7 : NO 00 NO + 667 36 1 = __O_O@_# : len= 8 : D3 20 D3 + 668 36 2 = __O_O@O# : len= 8 : D4 00 D4 + 669 36 3 = __O_O@__# : len= 9 : D3 20 D3 + 670 36 4 = __O_O@O_# : len= 9 : D4 00 D4 + 671 36 5 = __O_O@_O# : len= 9 : NO 00 D3 + 672 36 6 = __O_O@OO# : len= 9 : NO 00 D4 + 673 36 7 = __O_O@___# : len=10 : D3 20 D3 + 674 36 8 = __O_O@O__# : len=10 : D4 00 D4 + 675 36 9 = __O_O@_O_# : len=10 : NO 00 D3 + 676 36 10 = __O_O@OO_# : len=10 : S4 00 H4 + 677 36 11 = __O_O@__O# : len=10 : D3 20 D3 + 678 36 12 = __O_O@O_O# : len=10 : X4 00 X4 + 679 36 13 = __O_O@_OO# : len=10 : D4 00 D4 + 680 36 14 = __O_O@OOO# : len=10 : L5 00 L5 + 681 36 15 = __O_O@____# : len=11 : D3 20 D3 + 682 36 16 = __O_O@O___# : len=11 : D4 00 D4 + 683 36 17 = __O_O@_O__# : len=11 : NO 00 D3 + 684 36 18 = __O_O@OO__# : len=11 : S4 00 H4 + 685 36 19 = __O_O@__O_# : len=11 : D3 20 D3 + 686 36 20 = __O_O@O_O_# : len=11 : X4 00 X4 + 687 36 21 = __O_O@_OO_# : len=11 : D4 00 D4 + 688 36 22 = __O_O@OOO_# : len=11 : L5 00 L5 + 689 36 23 = __O_O@___O# : len=11 : D3 20 D3 + 690 36 24 = __O_O@O__O# : len=11 : D4 00 D4 + 691 36 25 = __O_O@_O_O# : len=11 : NO 00 D3 + 692 36 26 = __O_O@OO_O# : len=11 : NO 00 H4 + 693 36 27 = __O_O@__OO# : len=11 : D3 20 D3 + 694 36 28 = __O_O@O_OO# : len=11 : D4 00 X4 + 695 36 29 = __O_O@_OOO# : len=11 : NO 00 D4 + 696 36 30 = __O_O@OOOO# : len=11 : L6 00 L6 + 697 36 31 = __O_O@_____ : len=11 : D3 20 D3 + 698 36 32 = __O_O@O____ : len=11 : D4 00 D4 + 699 36 33 = __O_O@_O___ : len=11 : NO 00 D3 + 700 36 34 = __O_O@OO___ : len=11 : S4 00 H4 + 701 36 35 = __O_O@__O__ : len=11 : D3 20 D3 + 702 36 36 = __O_O@O_O__ : len=11 : X4 00 X4 + 703 37 0 = __OO_@# : len= 7 : NO 00 NO + 704 37 1 = __OO_@_# : len= 8 : D3 10 D3 + 705 37 2 = __OO_@O# : len= 8 : D4 00 D4 + 706 37 3 = __OO_@__# : len= 9 : D3 10 D3 + 707 37 4 = __OO_@O_# : len= 9 : D4 00 D4 + 708 37 5 = __OO_@_O# : len= 9 : NO 00 D3 + 709 37 6 = __OO_@OO# : len= 9 : NO 00 D4 + 710 37 7 = __OO_@___# : len=10 : D3 10 D3 + 711 37 8 = __OO_@O__# : len=10 : D4 00 D4 + 712 37 9 = __OO_@_O_# : len=10 : NO 00 D3 + 713 37 10 = __OO_@OO_# : len=10 : NO 00 D4 + 714 37 11 = __OO_@__O# : len=10 : D3 10 D3 + 715 37 12 = __OO_@O_O# : len=10 : D4 00 D4 + 716 37 13 = __OO_@_OO# : len=10 : NO 00 D3 + 717 37 14 = __OO_@OOO# : len=10 : NO 00 D4 + 718 37 15 = __OO_@____# : len=11 : D3 10 D3 + 719 37 16 = __OO_@O___# : len=11 : D4 00 D4 + 720 37 17 = __OO_@_O__# : len=11 : NO 00 D3 + 721 37 18 = __OO_@OO__# : len=11 : NO 00 D4 + 722 37 19 = __OO_@__O_# : len=11 : D3 10 D3 + 723 37 20 = __OO_@O_O_# : len=11 : D4 00 D4 + 724 37 21 = __OO_@_OO_# : len=11 : NO 00 D3 + 725 37 22 = __OO_@OOO_# : len=11 : S4 00 H4 + 726 37 23 = __OO_@___O# : len=11 : D3 10 D3 + 727 37 24 = __OO_@O__O# : len=11 : D4 00 D4 + 728 37 25 = __OO_@_O_O# : len=11 : NO 00 D3 + 729 37 26 = __OO_@OO_O# : len=11 : D4 00 X4 + 730 37 27 = __OO_@__OO# : len=11 : D3 10 D3 + 731 37 28 = __OO_@O_OO# : len=11 : X4 00 X4 + 732 37 29 = __OO_@_OOO# : len=11 : D4 00 D4 + 733 37 30 = __OO_@OOOO# : len=11 : L5 00 L5 + 734 37 31 = __OO_@_____ : len=11 : D3 10 D3 + 735 37 32 = __OO_@O____ : len=11 : D4 00 D4 + 736 37 33 = __OO_@_O___ : len=11 : NO 00 D3 + 737 37 34 = __OO_@OO___ : len=11 : NO 00 D4 + 738 37 35 = __OO_@__O__ : len=11 : D3 10 D3 + 739 37 36 = __OO_@O_O__ : len=11 : D4 00 D4 + 740 37 37 = __OO_@_OO__ : len=11 : NO 00 D3 + 741 38 0 = __OOO@# : len= 7 : S4 00 S4 + 742 38 1 = __OOO@_# : len= 8 : H4 00 H4 + 743 38 2 = __OOO@O# : len= 8 : L5 00 L5 + 744 38 3 = __OOO@__# : len= 9 : H4 00 H4 + 745 38 4 = __OOO@O_# : len= 9 : L5 00 L5 + 746 38 5 = __OOO@_O# : len= 9 : S4 00 H4 + 747 38 6 = __OOO@OO# : len= 9 : L6 00 L6 + 748 38 7 = __OOO@___# : len=10 : H4 00 H4 + 749 38 8 = __OOO@O__# : len=10 : L5 00 L5 + 750 38 9 = __OOO@_O_# : len=10 : S4 00 H4 + 751 38 10 = __OOO@OO_# : len=10 : L6 00 L6 + 752 38 11 = __OOO@__O# : len=10 : H4 00 H4 + 753 38 12 = __OOO@O_O# : len=10 : L5 00 L5 + 754 38 13 = __OOO@_OO# : len=10 : S4 00 H4 + 755 38 14 = __OOO@OOO# : len=10 : L6 00 L6 + 756 38 15 = __OOO@____# : len=11 : H4 00 H4 + 757 38 16 = __OOO@O___# : len=11 : L5 00 L5 + 758 38 17 = __OOO@_O__# : len=11 : S4 00 H4 + 759 38 18 = __OOO@OO__# : len=11 : L6 00 L6 + 760 38 19 = __OOO@__O_# : len=11 : H4 00 H4 + 761 38 20 = __OOO@O_O_# : len=11 : L5 00 L5 + 762 38 21 = __OOO@_OO_# : len=11 : S4 00 H4 + 763 38 22 = __OOO@OOO_# : len=11 : L6 00 L6 + 764 38 23 = __OOO@___O# : len=11 : H4 00 H4 + 765 38 24 = __OOO@O__O# : len=11 : L5 00 L5 + 766 38 25 = __OOO@_O_O# : len=11 : S4 00 H4 + 767 38 26 = __OOO@OO_O# : len=11 : L6 00 L6 + 768 38 27 = __OOO@__OO# : len=11 : H4 00 H4 + 769 38 28 = __OOO@O_OO# : len=11 : L5 00 L5 + 770 38 29 = __OOO@_OOO# : len=11 : S4 00 H4 + 771 38 30 = __OOO@OOOO# : len=11 : L6 00 L6 + 772 38 31 = __OOO@_____ : len=11 : H4 00 H4 + 773 38 32 = __OOO@O____ : len=11 : L5 00 L5 + 774 38 33 = __OOO@_O___ : len=11 : S4 00 H4 + 775 38 34 = __OOO@OO___ : len=11 : L6 00 L6 + 776 38 35 = __OOO@__O__ : len=11 : H4 00 H4 + 777 38 36 = __OOO@O_O__ : len=11 : L5 00 L5 + 778 38 37 = __OOO@_OO__ : len=11 : S4 00 H4 + 779 38 38 = __OOO@OOO__ : len=11 : L6 00 L6 + 780 39 0 = _O___@# : len= 7 : NO 00 NO + 781 39 1 = _O___@_# : len= 8 : NO 00 NO + 782 39 2 = _O___@O# : len= 8 : NO 00 NO + 783 39 3 = _O___@__# : len= 9 : NO 00 NO + 784 39 4 = _O___@O_# : len= 9 : NO 00 NO + 785 39 5 = _O___@_O# : len= 9 : NO 00 NO + 786 39 6 = _O___@OO# : len= 9 : NO 00 NO + 787 39 7 = _O___@___# : len=10 : NO 00 NO + 788 39 8 = _O___@O__# : len=10 : NO 00 NO + 789 39 9 = _O___@_O_# : len=10 : NO 00 NO + 790 39 10 = _O___@OO_# : len=10 : H3 13 H3 + 791 39 11 = _O___@__O# : len=10 : NO 00 NO + 792 39 12 = _O___@O_O# : len=10 : NO 00 NO + 793 39 13 = _O___@_OO# : len=10 : NO 00 NO + 794 39 14 = _O___@OOO# : len=10 : S4 00 S4 + 795 39 15 = _O___@____# : len=11 : NO 00 NO + 796 39 16 = _O___@O___# : len=11 : NO 00 NO + 797 39 17 = _O___@_O__# : len=11 : NO 00 NO + 798 39 18 = _O___@OO__# : len=11 : H3 13 H3 + 799 39 19 = _O___@__O_# : len=11 : NO 00 NO + 800 39 20 = _O___@O_O_# : len=11 : D3 02 D3 + 801 39 21 = _O___@_OO_# : len=11 : D3 01 D3 + 802 39 22 = _O___@OOO_# : len=11 : H4 00 H4 + 803 39 23 = _O___@___O# : len=11 : NO 00 NO + 804 39 24 = _O___@O__O# : len=11 : NO 00 NO + 805 39 25 = _O___@_O_O# : len=11 : NO 00 NO + 806 39 26 = _O___@OO_O# : len=11 : D4 00 D4 + 807 39 27 = _O___@__OO# : len=11 : NO 00 NO + 808 39 28 = _O___@O_OO# : len=11 : D4 00 D4 + 809 39 29 = _O___@_OOO# : len=11 : D4 00 D4 + 810 39 30 = _O___@OOOO# : len=11 : L5 00 L5 + 811 39 31 = _O___@_____ : len=11 : NO 00 NO + 812 39 32 = _O___@O____ : len=11 : NO 00 NO + 813 39 33 = _O___@_O___ : len=11 : NO 00 NO + 814 39 34 = _O___@OO___ : len=11 : H3 13 H3 + 815 39 35 = _O___@__O__ : len=11 : NO 00 NO + 816 39 36 = _O___@O_O__ : len=11 : D3 02 D3 + 817 39 37 = _O___@_OO__ : len=11 : D3 01 D3 + 818 39 38 = _O___@OOO__ : len=11 : H4 00 H4 + 819 39 39 = _O___@___O_ : len=11 : NO 00 NO + 820 40 0 = _O__O@# : len= 7 : NO 00 NO + 821 40 1 = _O__O@_# : len= 8 : NO 00 NO + 822 40 2 = _O__O@O# : len= 8 : NO 00 NO + 823 40 3 = _O__O@__# : len= 9 : NO 00 NO + 824 40 4 = _O__O@O_# : len= 9 : NO 00 H3 + 825 40 5 = _O__O@_O# : len= 9 : NO 00 NO + 826 40 6 = _O__O@OO# : len= 9 : S4 00 S4 + 827 40 7 = _O__O@___# : len=10 : NO 00 NO + 828 40 8 = _O__O@O__# : len=10 : H3 22 H3 + 829 40 9 = _O__O@_O_# : len=10 : D3 01 D3 + 830 40 10 = _O__O@OO_# : len=10 : H4 00 H4 + 831 40 11 = _O__O@__O# : len=10 : NO 00 NO + 832 40 12 = _O__O@O_O# : len=10 : D4 00 D4 + 833 40 13 = _O__O@_OO# : len=10 : D4 00 D4 + 834 40 14 = _O__O@OOO# : len=10 : L5 00 L5 + 835 40 15 = _O__O@____# : len=11 : NO 00 NO + 836 40 16 = _O__O@O___# : len=11 : H3 22 H3 + 837 40 17 = _O__O@_O__# : len=11 : D3 01 D3 + 838 40 18 = _O__O@OO__# : len=11 : H4 00 H4 + 839 40 19 = _O__O@__O_# : len=11 : NO 00 NO + 840 40 20 = _O__O@O_O_# : len=11 : D4 00 D4 + 841 40 21 = _O__O@_OO_# : len=11 : D4 00 D4 + 842 40 22 = _O__O@OOO_# : len=11 : L5 00 L5 + 843 40 23 = _O__O@___O# : len=11 : NO 00 NO + 844 40 24 = _O__O@O__O# : len=11 : NO 00 H3 + 845 40 25 = _O__O@_O_O# : len=11 : NO 00 D3 + 846 40 26 = _O__O@OO_O# : len=11 : S4 00 H4 + 847 40 27 = _O__O@__OO# : len=11 : NO 00 NO + 848 40 28 = _O__O@O_OO# : len=11 : NO 00 D4 + 849 40 29 = _O__O@_OOO# : len=11 : NO 00 D4 + 850 40 30 = _O__O@OOOO# : len=11 : L6 00 L6 + 851 40 31 = _O__O@_____ : len=11 : NO 00 NO + 852 40 32 = _O__O@O____ : len=11 : H3 22 H3 + 853 40 33 = _O__O@_O___ : len=11 : D3 01 D3 + 854 40 34 = _O__O@OO___ : len=11 : H4 00 H4 + 855 40 35 = _O__O@__O__ : len=11 : NO 00 NO + 856 40 36 = _O__O@O_O__ : len=11 : D4 00 D4 + 857 40 37 = _O__O@_OO__ : len=11 : D4 00 D4 + 858 40 38 = _O__O@OOO__ : len=11 : L5 00 L5 + 859 40 39 = _O__O@___O_ : len=11 : NO 00 NO + 860 40 40 = _O__O@O__O_ : len=11 : NO 00 H3 + 861 41 0 = _O_O_@# : len= 7 : NO 00 NO + 862 41 1 = _O_O_@_# : len= 8 : NO 00 NO + 863 41 2 = _O_O_@O# : len= 8 : NO 00 NO + 864 41 3 = _O_O_@__# : len= 9 : NO 00 NO + 865 41 4 = _O_O_@O_# : len= 9 : NO 00 D3 + 866 41 5 = _O_O_@_O# : len= 9 : NO 00 NO + 867 41 6 = _O_O_@OO# : len= 9 : D4 00 D4 + 868 41 7 = _O_O_@___# : len=10 : NO 00 NO + 869 41 8 = _O_O_@O__# : len=10 : NO 00 D3 + 870 41 9 = _O_O_@_O_# : len=10 : NO 00 NO + 871 41 10 = _O_O_@OO_# : len=10 : D4 00 D4 + 872 41 11 = _O_O_@__O# : len=10 : NO 00 NO + 873 41 12 = _O_O_@O_O# : len=10 : NO 00 D3 + 874 41 13 = _O_O_@_OO# : len=10 : NO 00 NO + 875 41 14 = _O_O_@OOO# : len=10 : NO 00 D4 + 876 41 15 = _O_O_@____# : len=11 : NO 00 NO + 877 41 16 = _O_O_@O___# : len=11 : NO 00 D3 + 878 41 17 = _O_O_@_O__# : len=11 : NO 00 NO + 879 41 18 = _O_O_@OO__# : len=11 : D4 00 D4 + 880 41 19 = _O_O_@__O_# : len=11 : NO 00 NO + 881 41 20 = _O_O_@O_O_# : len=11 : NO 00 D3 + 882 41 21 = _O_O_@_OO_# : len=11 : NO 00 D3 + 883 41 22 = _O_O_@OOO_# : len=11 : S4 00 H4 + 884 41 23 = _O_O_@___O# : len=11 : NO 00 NO + 885 41 24 = _O_O_@O__O# : len=11 : NO 00 D3 + 886 41 25 = _O_O_@_O_O# : len=11 : NO 00 NO + 887 41 26 = _O_O_@OO_O# : len=11 : X4 00 X4 + 888 41 27 = _O_O_@__OO# : len=11 : NO 00 NO + 889 41 28 = _O_O_@O_OO# : len=11 : D4 00 D4 + 890 41 29 = _O_O_@_OOO# : len=11 : D4 00 D4 + 891 41 30 = _O_O_@OOOO# : len=11 : L5 00 L5 + 892 41 31 = _O_O_@_____ : len=11 : NO 00 NO + 893 41 32 = _O_O_@O____ : len=11 : NO 00 D3 + 894 41 33 = _O_O_@_O___ : len=11 : NO 00 NO + 895 41 34 = _O_O_@OO___ : len=11 : D4 00 D4 + 896 41 35 = _O_O_@__O__ : len=11 : NO 00 NO + 897 41 36 = _O_O_@O_O__ : len=11 : NO 00 D3 + 898 41 37 = _O_O_@_OO__ : len=11 : NO 00 D3 + 899 41 38 = _O_O_@OOO__ : len=11 : S4 00 H4 + 900 41 39 = _O_O_@___O_ : len=11 : NO 00 NO + 901 41 40 = _O_O_@O__O_ : len=11 : NO 00 D3 + 902 41 41 = _O_O_@_O_O_ : len=11 : NO 00 NO + 903 42 0 = _O_OO@# : len= 7 : D4 00 D4 + 904 42 1 = _O_OO@_# : len= 8 : D4 00 D4 + 905 42 2 = _O_OO@O# : len= 8 : NO 00 D4 + 906 42 3 = _O_OO@__# : len= 9 : D4 00 D4 + 907 42 4 = _O_OO@O_# : len= 9 : S4 00 H4 + 908 42 5 = _O_OO@_O# : len= 9 : X4 00 X4 + 909 42 6 = _O_OO@OO# : len= 9 : L5 00 L5 + 910 42 7 = _O_OO@___# : len=10 : D4 00 D4 + 911 42 8 = _O_OO@O__# : len=10 : S4 00 H4 + 912 42 9 = _O_OO@_O_# : len=10 : X4 00 X4 + 913 42 10 = _O_OO@OO_# : len=10 : L5 00 L5 + 914 42 11 = _O_OO@__O# : len=10 : D4 00 D4 + 915 42 12 = _O_OO@O_O# : len=10 : NO 00 H4 + 916 42 13 = _O_OO@_OO# : len=10 : D4 00 X4 + 917 42 14 = _O_OO@OOO# : len=10 : L6 00 L6 + 918 42 15 = _O_OO@____# : len=11 : D4 00 D4 + 919 42 16 = _O_OO@O___# : len=11 : S4 00 H4 + 920 42 17 = _O_OO@_O__# : len=11 : X4 00 X4 + 921 42 18 = _O_OO@OO__# : len=11 : L5 00 L5 + 922 42 19 = _O_OO@__O_# : len=11 : D4 00 D4 + 923 42 20 = _O_OO@O_O_# : len=11 : NO 00 H4 + 924 42 21 = _O_OO@_OO_# : len=11 : D4 00 X4 + 925 42 22 = _O_OO@OOO_# : len=11 : L6 00 L6 + 926 42 23 = _O_OO@___O# : len=11 : D4 00 D4 + 927 42 24 = _O_OO@O__O# : len=11 : S4 00 H4 + 928 42 25 = _O_OO@_O_O# : len=11 : X4 00 X4 + 929 42 26 = _O_OO@OO_O# : len=11 : L5 00 L5 + 930 42 27 = _O_OO@__OO# : len=11 : D4 00 D4 + 931 42 28 = _O_OO@O_OO# : len=11 : NO 00 H4 + 932 42 29 = _O_OO@_OOO# : len=11 : D4 00 X4 + 933 42 30 = _O_OO@OOOO# : len=11 : L6 00 L6 + 934 42 31 = _O_OO@_____ : len=11 : D4 00 D4 + 935 42 32 = _O_OO@O____ : len=11 : S4 00 H4 + 936 42 33 = _O_OO@_O___ : len=11 : X4 00 X4 + 937 42 34 = _O_OO@OO___ : len=11 : L5 00 L5 + 938 42 35 = _O_OO@__O__ : len=11 : D4 00 D4 + 939 42 36 = _O_OO@O_O__ : len=11 : NO 00 H4 + 940 42 37 = _O_OO@_OO__ : len=11 : D4 00 X4 + 941 42 38 = _O_OO@OOO__ : len=11 : L6 00 L6 + 942 42 39 = _O_OO@___O_ : len=11 : D4 00 D4 + 943 42 40 = _O_OO@O__O_ : len=11 : S4 00 H4 + 944 42 41 = _O_OO@_O_O_ : len=11 : X4 00 X4 + 945 42 42 = _O_OO@OO_O_ : len=11 : L5 00 L5 + 946 43 0 = _OO__@# : len= 7 : NO 00 NO + 947 43 1 = _OO__@_# : len= 8 : NO 00 NO + 948 43 2 = _OO__@O# : len= 8 : NO 00 NO + 949 43 3 = _OO__@__# : len= 9 : NO 00 NO + 950 43 4 = _OO__@O_# : len= 9 : NO 00 NO + 951 43 5 = _OO__@_O# : len= 9 : NO 00 NO + 952 43 6 = _OO__@OO# : len= 9 : NO 00 NO + 953 43 7 = _OO__@___# : len=10 : NO 00 NO + 954 43 8 = _OO__@O__# : len=10 : NO 00 NO + 955 43 9 = _OO__@_O_# : len=10 : NO 00 NO + 956 43 10 = _OO__@OO_# : len=10 : NO 00 H3 + 957 43 11 = _OO__@__O# : len=10 : NO 00 NO + 958 43 12 = _OO__@O_O# : len=10 : NO 00 NO + 959 43 13 = _OO__@_OO# : len=10 : NO 00 NO + 960 43 14 = _OO__@OOO# : len=10 : S4 00 S4 + 961 43 15 = _OO__@____# : len=11 : NO 00 NO + 962 43 16 = _OO__@O___# : len=11 : NO 00 NO + 963 43 17 = _OO__@_O__# : len=11 : NO 00 NO + 964 43 18 = _OO__@OO__# : len=11 : H3 13 H3 + 965 43 19 = _OO__@__O_# : len=11 : NO 00 NO + 966 43 20 = _OO__@O_O_# : len=11 : D3 02 D3 + 967 43 21 = _OO__@_OO_# : len=11 : D3 01 D3 + 968 43 22 = _OO__@OOO_# : len=11 : H4 00 H4 + 969 43 23 = _OO__@___O# : len=11 : NO 00 NO + 970 43 24 = _OO__@O__O# : len=11 : NO 00 NO + 971 43 25 = _OO__@_O_O# : len=11 : NO 00 NO + 972 43 26 = _OO__@OO_O# : len=11 : D4 00 D4 + 973 43 27 = _OO__@__OO# : len=11 : NO 00 NO + 974 43 28 = _OO__@O_OO# : len=11 : D4 00 D4 + 975 43 29 = _OO__@_OOO# : len=11 : D4 00 D4 + 976 43 30 = _OO__@OOOO# : len=11 : L5 00 L5 + 977 43 31 = _OO__@_____ : len=11 : NO 00 NO + 978 43 32 = _OO__@O____ : len=11 : NO 00 NO + 979 43 33 = _OO__@_O___ : len=11 : NO 00 NO + 980 43 34 = _OO__@OO___ : len=11 : H3 13 H3 + 981 43 35 = _OO__@__O__ : len=11 : NO 00 NO + 982 43 36 = _OO__@O_O__ : len=11 : D3 02 D3 + 983 43 37 = _OO__@_OO__ : len=11 : D3 01 D3 + 984 43 38 = _OO__@OOO__ : len=11 : H4 00 H4 + 985 43 39 = _OO__@___O_ : len=11 : NO 00 NO + 986 43 40 = _OO__@O__O_ : len=11 : NO 00 NO + 987 43 41 = _OO__@_O_O_ : len=11 : NO 00 NO + 988 43 42 = _OO__@OO_O_ : len=11 : D4 00 D4 + 989 43 43 = _OO__@__OO_ : len=11 : NO 00 NO + 990 44 0 = _OO_O@# : len= 7 : D4 00 D4 + 991 44 1 = _OO_O@_# : len= 8 : D4 00 D4 + 992 44 2 = _OO_O@O# : len= 8 : NO 00 D4 + 993 44 3 = _OO_O@__# : len= 9 : D4 00 D4 + 994 44 4 = _OO_O@O_# : len= 9 : NO 00 D4 + 995 44 5 = _OO_O@_O# : len= 9 : D4 00 D4 + 996 44 6 = _OO_O@OO# : len= 9 : NO 00 D4 + 997 44 7 = _OO_O@___# : len=10 : D4 00 D4 + 998 44 8 = _OO_O@O__# : len=10 : NO 00 D4 + 999 44 9 = _OO_O@_O_# : len=10 : D4 00 D4 + 1000 44 10 = _OO_O@OO_# : len=10 : S4 00 H4 + 1001 44 11 = _OO_O@__O# : len=10 : D4 00 D4 + 1002 44 12 = _OO_O@O_O# : len=10 : D4 00 X4 + 1003 44 13 = _OO_O@_OO# : len=10 : X4 00 X4 + 1004 44 14 = _OO_O@OOO# : len=10 : L5 00 L5 + 1005 44 15 = _OO_O@____# : len=11 : D4 00 D4 + 1006 44 16 = _OO_O@O___# : len=11 : NO 00 D4 + 1007 44 17 = _OO_O@_O__# : len=11 : D4 00 D4 + 1008 44 18 = _OO_O@OO__# : len=11 : S4 00 H4 + 1009 44 19 = _OO_O@__O_# : len=11 : D4 00 D4 + 1010 44 20 = _OO_O@O_O_# : len=11 : D4 00 X4 + 1011 44 21 = _OO_O@_OO_# : len=11 : X4 00 X4 + 1012 44 22 = _OO_O@OOO_# : len=11 : L5 00 L5 + 1013 44 23 = _OO_O@___O# : len=11 : D4 00 D4 + 1014 44 24 = _OO_O@O__O# : len=11 : NO 00 D4 + 1015 44 25 = _OO_O@_O_O# : len=11 : D4 00 D4 + 1016 44 26 = _OO_O@OO_O# : len=11 : NO 00 H4 + 1017 44 27 = _OO_O@__OO# : len=11 : D4 00 D4 + 1018 44 28 = _OO_O@O_OO# : len=11 : NO 00 X4 + 1019 44 29 = _OO_O@_OOO# : len=11 : D4 00 X4 + 1020 44 30 = _OO_O@OOOO# : len=11 : L6 00 L6 + 1021 44 31 = _OO_O@_____ : len=11 : D4 00 D4 + 1022 44 32 = _OO_O@O____ : len=11 : NO 00 D4 + 1023 44 33 = _OO_O@_O___ : len=11 : D4 00 D4 + 1024 44 34 = _OO_O@OO___ : len=11 : S4 00 H4 + 1025 44 35 = _OO_O@__O__ : len=11 : D4 00 D4 + 1026 44 36 = _OO_O@O_O__ : len=11 : D4 00 X4 + 1027 44 37 = _OO_O@_OO__ : len=11 : X4 00 X4 + 1028 44 38 = _OO_O@OOO__ : len=11 : L5 00 L5 + 1029 44 39 = _OO_O@___O_ : len=11 : D4 00 D4 + 1030 44 40 = _OO_O@O__O_ : len=11 : NO 00 D4 + 1031 44 41 = _OO_O@_O_O_ : len=11 : D4 00 D4 + 1032 44 42 = _OO_O@OO_O_ : len=11 : NO 00 H4 + 1033 44 43 = _OO_O@__OO_ : len=11 : D4 00 D4 + 1034 44 44 = _OO_O@O_OO_ : len=11 : NO 00 X4 + 1035 45 0 = _OOO_@# : len= 7 : D4 00 D4 + 1036 45 1 = _OOO_@_# : len= 8 : D4 00 D4 + 1037 45 2 = _OOO_@O# : len= 8 : NO 00 D4 + 1038 45 3 = _OOO_@__# : len= 9 : D4 00 D4 + 1039 45 4 = _OOO_@O_# : len= 9 : NO 00 D4 + 1040 45 5 = _OOO_@_O# : len= 9 : D4 00 D4 + 1041 45 6 = _OOO_@OO# : len= 9 : NO 00 D4 + 1042 45 7 = _OOO_@___# : len=10 : D4 00 D4 + 1043 45 8 = _OOO_@O__# : len=10 : NO 00 D4 + 1044 45 9 = _OOO_@_O_# : len=10 : D4 00 D4 + 1045 45 10 = _OOO_@OO_# : len=10 : NO 00 D4 + 1046 45 11 = _OOO_@__O# : len=10 : D4 00 D4 + 1047 45 12 = _OOO_@O_O# : len=10 : NO 00 D4 + 1048 45 13 = _OOO_@_OO# : len=10 : D4 00 D4 + 1049 45 14 = _OOO_@OOO# : len=10 : NO 00 D4 + 1050 45 15 = _OOO_@____# : len=11 : D4 00 D4 + 1051 45 16 = _OOO_@O___# : len=11 : NO 00 D4 + 1052 45 17 = _OOO_@_O__# : len=11 : D4 00 D4 + 1053 45 18 = _OOO_@OO__# : len=11 : NO 00 D4 + 1054 45 19 = _OOO_@__O_# : len=11 : D4 00 D4 + 1055 45 20 = _OOO_@O_O_# : len=11 : NO 00 D4 + 1056 45 21 = _OOO_@_OO_# : len=11 : D4 00 D4 + 1057 45 22 = _OOO_@OOO_# : len=11 : S4 00 H4 + 1058 45 23 = _OOO_@___O# : len=11 : D4 00 D4 + 1059 45 24 = _OOO_@O__O# : len=11 : NO 00 D4 + 1060 45 25 = _OOO_@_O_O# : len=11 : D4 00 D4 + 1061 45 26 = _OOO_@OO_O# : len=11 : D4 00 X4 + 1062 45 27 = _OOO_@__OO# : len=11 : D4 00 D4 + 1063 45 28 = _OOO_@O_OO# : len=11 : D4 00 X4 + 1064 45 29 = _OOO_@_OOO# : len=11 : X4 00 X4 + 1065 45 30 = _OOO_@OOOO# : len=11 : L5 00 L5 + 1066 45 31 = _OOO_@_____ : len=11 : D4 00 D4 + 1067 45 32 = _OOO_@O____ : len=11 : NO 00 D4 + 1068 45 33 = _OOO_@_O___ : len=11 : D4 00 D4 + 1069 45 34 = _OOO_@OO___ : len=11 : NO 00 D4 + 1070 45 35 = _OOO_@__O__ : len=11 : D4 00 D4 + 1071 45 36 = _OOO_@O_O__ : len=11 : NO 00 D4 + 1072 45 37 = _OOO_@_OO__ : len=11 : D4 00 D4 + 1073 45 38 = _OOO_@OOO__ : len=11 : S4 00 H4 + 1074 45 39 = _OOO_@___O_ : len=11 : D4 00 D4 + 1075 45 40 = _OOO_@O__O_ : len=11 : NO 00 D4 + 1076 45 41 = _OOO_@_O_O_ : len=11 : D4 00 D4 + 1077 45 42 = _OOO_@OO_O_ : len=11 : D4 00 X4 + 1078 45 43 = _OOO_@__OO_ : len=11 : D4 00 D4 + 1079 45 44 = _OOO_@O_OO_ : len=11 : D4 00 X4 + 1080 45 45 = _OOO_@_OOO_ : len=11 : X4 00 X4 + 1081 46 0 = _OOOO@# : len= 7 : L5 00 L5 + 1082 46 1 = _OOOO@_# : len= 8 : L5 00 L5 + 1083 46 2 = _OOOO@O# : len= 8 : L6 00 L6 + 1084 46 3 = _OOOO@__# : len= 9 : L5 00 L5 + 1085 46 4 = _OOOO@O_# : len= 9 : L6 00 L6 + 1086 46 5 = _OOOO@_O# : len= 9 : L5 00 L5 + 1087 46 6 = _OOOO@OO# : len= 9 : L6 00 L6 + 1088 46 7 = _OOOO@___# : len=10 : L5 00 L5 + 1089 46 8 = _OOOO@O__# : len=10 : L6 00 L6 + 1090 46 9 = _OOOO@_O_# : len=10 : L5 00 L5 + 1091 46 10 = _OOOO@OO_# : len=10 : L6 00 L6 + 1092 46 11 = _OOOO@__O# : len=10 : L5 00 L5 + 1093 46 12 = _OOOO@O_O# : len=10 : L6 00 L6 + 1094 46 13 = _OOOO@_OO# : len=10 : L5 00 L5 + 1095 46 14 = _OOOO@OOO# : len=10 : L6 00 L6 + 1096 46 15 = _OOOO@____# : len=11 : L5 00 L5 + 1097 46 16 = _OOOO@O___# : len=11 : L6 00 L6 + 1098 46 17 = _OOOO@_O__# : len=11 : L5 00 L5 + 1099 46 18 = _OOOO@OO__# : len=11 : L6 00 L6 + 1100 46 19 = _OOOO@__O_# : len=11 : L5 00 L5 + 1101 46 20 = _OOOO@O_O_# : len=11 : L6 00 L6 + 1102 46 21 = _OOOO@_OO_# : len=11 : L5 00 L5 + 1103 46 22 = _OOOO@OOO_# : len=11 : L6 00 L6 + 1104 46 23 = _OOOO@___O# : len=11 : L5 00 L5 + 1105 46 24 = _OOOO@O__O# : len=11 : L6 00 L6 + 1106 46 25 = _OOOO@_O_O# : len=11 : L5 00 L5 + 1107 46 26 = _OOOO@OO_O# : len=11 : L6 00 L6 + 1108 46 27 = _OOOO@__OO# : len=11 : L5 00 L5 + 1109 46 28 = _OOOO@O_OO# : len=11 : L6 00 L6 + 1110 46 29 = _OOOO@_OOO# : len=11 : L5 00 L5 + 1111 46 30 = _OOOO@OOOO# : len=11 : L6 00 L6 + 1112 46 31 = _OOOO@_____ : len=11 : L5 00 L5 + 1113 46 32 = _OOOO@O____ : len=11 : L6 00 L6 + 1114 46 33 = _OOOO@_O___ : len=11 : L5 00 L5 + 1115 46 34 = _OOOO@OO___ : len=11 : L6 00 L6 + 1116 46 35 = _OOOO@__O__ : len=11 : L5 00 L5 + 1117 46 36 = _OOOO@O_O__ : len=11 : L6 00 L6 + 1118 46 37 = _OOOO@_OO__ : len=11 : L5 00 L5 + 1119 46 38 = _OOOO@OOO__ : len=11 : L6 00 L6 + 1120 46 39 = _OOOO@___O_ : len=11 : L5 00 L5 + 1121 46 40 = _OOOO@O__O_ : len=11 : L6 00 L6 + 1122 46 41 = _OOOO@_O_O_ : len=11 : L5 00 L5 + 1123 46 42 = _OOOO@OO_O_ : len=11 : L6 00 L6 + 1124 46 43 = _OOOO@__OO_ : len=11 : L5 00 L5 + 1125 46 44 = _OOOO@O_OO_ : len=11 : L6 00 L6 + 1126 46 45 = _OOOO@_OOO_ : len=11 : L5 00 L5 + 1127 46 46 = _OOOO@OOOO_ : len=11 : L6 00 L6 + 1128 47 0 = O____@# : len= 7 : NO 00 NO + 1129 47 1 = O____@_# : len= 8 : NO 00 NO + 1130 47 2 = O____@O# : len= 8 : NO 00 NO + 1131 47 3 = O____@__# : len= 9 : NO 00 NO + 1132 47 4 = O____@O_# : len= 9 : NO 00 NO + 1133 47 5 = O____@_O# : len= 9 : NO 00 NO + 1134 47 6 = O____@OO# : len= 9 : NO 00 NO + 1135 47 7 = O____@___# : len=10 : NO 00 NO + 1136 47 8 = O____@O__# : len=10 : NO 00 NO + 1137 47 9 = O____@_O_# : len=10 : NO 00 NO + 1138 47 10 = O____@OO_# : len=10 : H3 13 H3 + 1139 47 11 = O____@__O# : len=10 : NO 00 NO + 1140 47 12 = O____@O_O# : len=10 : NO 00 NO + 1141 47 13 = O____@_OO# : len=10 : NO 00 NO + 1142 47 14 = O____@OOO# : len=10 : S4 00 S4 + 1143 47 15 = O____@____# : len=11 : NO 00 NO + 1144 47 16 = O____@O___# : len=11 : NO 00 NO + 1145 47 17 = O____@_O__# : len=11 : NO 00 NO + 1146 47 18 = O____@OO__# : len=11 : H3 13 H3 + 1147 47 19 = O____@__O_# : len=11 : NO 00 NO + 1148 47 20 = O____@O_O_# : len=11 : D3 02 D3 + 1149 47 21 = O____@_OO_# : len=11 : D3 01 D3 + 1150 47 22 = O____@OOO_# : len=11 : H4 00 H4 + 1151 47 23 = O____@___O# : len=11 : NO 00 NO + 1152 47 24 = O____@O__O# : len=11 : NO 00 NO + 1153 47 25 = O____@_O_O# : len=11 : NO 00 NO + 1154 47 26 = O____@OO_O# : len=11 : D4 00 D4 + 1155 47 27 = O____@__OO# : len=11 : NO 00 NO + 1156 47 28 = O____@O_OO# : len=11 : D4 00 D4 + 1157 47 29 = O____@_OOO# : len=11 : D4 00 D4 + 1158 47 30 = O____@OOOO# : len=11 : L5 00 L5 + 1159 47 31 = O____@_____ : len=11 : NO 00 NO + 1160 47 32 = O____@O____ : len=11 : NO 00 NO + 1161 47 33 = O____@_O___ : len=11 : NO 00 NO + 1162 47 34 = O____@OO___ : len=11 : H3 13 H3 + 1163 47 35 = O____@__O__ : len=11 : NO 00 NO + 1164 47 36 = O____@O_O__ : len=11 : D3 02 D3 + 1165 47 37 = O____@_OO__ : len=11 : D3 01 D3 + 1166 47 38 = O____@OOO__ : len=11 : H4 00 H4 + 1167 47 39 = O____@___O_ : len=11 : NO 00 NO + 1168 47 40 = O____@O__O_ : len=11 : NO 00 NO + 1169 47 41 = O____@_O_O_ : len=11 : NO 00 NO + 1170 47 42 = O____@OO_O_ : len=11 : D4 00 D4 + 1171 47 43 = O____@__OO_ : len=11 : NO 00 NO + 1172 47 44 = O____@O_OO_ : len=11 : D4 00 D4 + 1173 47 45 = O____@_OOO_ : len=11 : D4 00 D4 + 1174 47 46 = O____@OOOO_ : len=11 : L5 00 L5 + 1175 47 47 = O____@____O : len=11 : NO 00 NO + 1176 48 0 = O___O@# : len= 7 : NO 00 NO + 1177 48 1 = O___O@_# : len= 8 : NO 00 NO + 1178 48 2 = O___O@O# : len= 8 : NO 00 NO + 1179 48 3 = O___O@__# : len= 9 : NO 00 NO + 1180 48 4 = O___O@O_# : len= 9 : H3 22 H3 + 1181 48 5 = O___O@_O# : len= 9 : NO 00 NO + 1182 48 6 = O___O@OO# : len= 9 : S4 00 S4 + 1183 48 7 = O___O@___# : len=10 : NO 00 NO + 1184 48 8 = O___O@O__# : len=10 : H3 22 H3 + 1185 48 9 = O___O@_O_# : len=10 : D3 01 D3 + 1186 48 10 = O___O@OO_# : len=10 : H4 00 H4 + 1187 48 11 = O___O@__O# : len=10 : NO 00 NO + 1188 48 12 = O___O@O_O# : len=10 : D4 00 D4 + 1189 48 13 = O___O@_OO# : len=10 : D4 00 D4 + 1190 48 14 = O___O@OOO# : len=10 : L5 00 L5 + 1191 48 15 = O___O@____# : len=11 : NO 00 NO + 1192 48 16 = O___O@O___# : len=11 : H3 22 H3 + 1193 48 17 = O___O@_O__# : len=11 : D3 01 D3 + 1194 48 18 = O___O@OO__# : len=11 : H4 00 H4 + 1195 48 19 = O___O@__O_# : len=11 : NO 00 NO + 1196 48 20 = O___O@O_O_# : len=11 : D4 00 D4 + 1197 48 21 = O___O@_OO_# : len=11 : D4 00 D4 + 1198 48 22 = O___O@OOO_# : len=11 : L5 00 L5 + 1199 48 23 = O___O@___O# : len=11 : NO 00 NO + 1200 48 24 = O___O@O__O# : len=11 : H3 22 H3 + 1201 48 25 = O___O@_O_O# : len=11 : NO 00 D3 + 1202 48 26 = O___O@OO_O# : len=11 : S4 00 H4 + 1203 48 27 = O___O@__OO# : len=11 : NO 00 NO + 1204 48 28 = O___O@O_OO# : len=11 : NO 00 D4 + 1205 48 29 = O___O@_OOO# : len=11 : NO 00 D4 + 1206 48 30 = O___O@OOOO# : len=11 : L6 00 L6 + 1207 48 31 = O___O@_____ : len=11 : NO 00 NO + 1208 48 32 = O___O@O____ : len=11 : H3 22 H3 + 1209 48 33 = O___O@_O___ : len=11 : D3 01 D3 + 1210 48 34 = O___O@OO___ : len=11 : H4 00 H4 + 1211 48 35 = O___O@__O__ : len=11 : NO 00 NO + 1212 48 36 = O___O@O_O__ : len=11 : D4 00 D4 + 1213 48 37 = O___O@_OO__ : len=11 : D4 00 D4 + 1214 48 38 = O___O@OOO__ : len=11 : L5 00 L5 + 1215 48 39 = O___O@___O_ : len=11 : NO 00 NO + 1216 48 40 = O___O@O__O_ : len=11 : H3 22 H3 + 1217 48 41 = O___O@_O_O_ : len=11 : NO 00 D3 + 1218 48 42 = O___O@OO_O_ : len=11 : S4 00 H4 + 1219 48 43 = O___O@__OO_ : len=11 : NO 00 NO + 1220 48 44 = O___O@O_OO_ : len=11 : NO 00 D4 + 1221 48 45 = O___O@_OOO_ : len=11 : NO 00 D4 + 1222 48 46 = O___O@OOOO_ : len=11 : L6 00 L6 + 1223 48 47 = O___O@____O : len=11 : NO 00 NO + 1224 48 48 = O___O@O___O : len=11 : H3 22 H3 + 1225 49 0 = O__O_@# : len= 7 : NO 00 NO + 1226 49 1 = O__O_@_# : len= 8 : NO 00 NO + 1227 49 2 = O__O_@O# : len= 8 : NO 00 NO + 1228 49 3 = O__O_@__# : len= 9 : NO 00 NO + 1229 49 4 = O__O_@O_# : len= 9 : D3 10 D3 + 1230 49 5 = O__O_@_O# : len= 9 : NO 00 NO + 1231 49 6 = O__O_@OO# : len= 9 : D4 00 D4 + 1232 49 7 = O__O_@___# : len=10 : NO 00 NO + 1233 49 8 = O__O_@O__# : len=10 : D3 10 D3 + 1234 49 9 = O__O_@_O_# : len=10 : NO 00 NO + 1235 49 10 = O__O_@OO_# : len=10 : D4 00 D4 + 1236 49 11 = O__O_@__O# : len=10 : NO 00 NO + 1237 49 12 = O__O_@O_O# : len=10 : NO 00 D3 + 1238 49 13 = O__O_@_OO# : len=10 : NO 00 NO + 1239 49 14 = O__O_@OOO# : len=10 : NO 00 D4 + 1240 49 15 = O__O_@____# : len=11 : NO 00 NO + 1241 49 16 = O__O_@O___# : len=11 : D3 10 D3 + 1242 49 17 = O__O_@_O__# : len=11 : NO 00 NO + 1243 49 18 = O__O_@OO__# : len=11 : D4 00 D4 + 1244 49 19 = O__O_@__O_# : len=11 : NO 00 NO + 1245 49 20 = O__O_@O_O_# : len=11 : NO 00 D3 + 1246 49 21 = O__O_@_OO_# : len=11 : NO 00 D3 + 1247 49 22 = O__O_@OOO_# : len=11 : S4 00 H4 + 1248 49 23 = O__O_@___O# : len=11 : NO 00 NO + 1249 49 24 = O__O_@O__O# : len=11 : D3 10 D3 + 1250 49 25 = O__O_@_O_O# : len=11 : NO 00 NO + 1251 49 26 = O__O_@OO_O# : len=11 : X4 00 X4 + 1252 49 27 = O__O_@__OO# : len=11 : NO 00 NO + 1253 49 28 = O__O_@O_OO# : len=11 : D4 00 D4 + 1254 49 29 = O__O_@_OOO# : len=11 : D4 00 D4 + 1255 49 30 = O__O_@OOOO# : len=11 : L5 00 L5 + 1256 49 31 = O__O_@_____ : len=11 : NO 00 NO + 1257 49 32 = O__O_@O____ : len=11 : D3 10 D3 + 1258 49 33 = O__O_@_O___ : len=11 : NO 00 NO + 1259 49 34 = O__O_@OO___ : len=11 : D4 00 D4 + 1260 49 35 = O__O_@__O__ : len=11 : NO 00 NO + 1261 49 36 = O__O_@O_O__ : len=11 : NO 00 D3 + 1262 49 37 = O__O_@_OO__ : len=11 : NO 00 D3 + 1263 49 38 = O__O_@OOO__ : len=11 : S4 00 H4 + 1264 49 39 = O__O_@___O_ : len=11 : NO 00 NO + 1265 49 40 = O__O_@O__O_ : len=11 : D3 10 D3 + 1266 49 41 = O__O_@_O_O_ : len=11 : NO 00 NO + 1267 49 42 = O__O_@OO_O_ : len=11 : X4 00 X4 + 1268 49 43 = O__O_@__OO_ : len=11 : NO 00 NO + 1269 49 44 = O__O_@O_OO_ : len=11 : D4 00 D4 + 1270 49 45 = O__O_@_OOO_ : len=11 : D4 00 D4 + 1271 49 46 = O__O_@OOOO_ : len=11 : L5 00 L5 + 1272 49 47 = O__O_@____O : len=11 : NO 00 NO + 1273 49 48 = O__O_@O___O : len=11 : D3 10 D3 + 1274 49 49 = O__O_@_O__O : len=11 : NO 00 NO + 1275 50 0 = O__OO@# : len= 7 : NO 00 NO + 1276 50 1 = O__OO@_# : len= 8 : NO 00 H3 + 1277 50 2 = O__OO@O# : len= 8 : S4 00 S4 + 1278 50 3 = O__OO@__# : len= 9 : H3 31 H3 + 1279 50 4 = O__OO@O_# : len= 9 : H4 00 H4 + 1280 50 5 = O__OO@_O# : len= 9 : D4 00 D4 + 1281 50 6 = O__OO@OO# : len= 9 : L5 00 L5 + 1282 50 7 = O__OO@___# : len=10 : H3 31 H3 + 1283 50 8 = O__OO@O__# : len=10 : H4 00 H4 + 1284 50 9 = O__OO@_O_# : len=10 : D4 00 D4 + 1285 50 10 = O__OO@OO_# : len=10 : L5 00 L5 + 1286 50 11 = O__OO@__O# : len=10 : NO 00 H3 + 1287 50 12 = O__OO@O_O# : len=10 : S4 00 H4 + 1288 50 13 = O__OO@_OO# : len=10 : NO 00 D4 + 1289 50 14 = O__OO@OOO# : len=10 : L6 00 L6 + 1290 50 15 = O__OO@____# : len=11 : H3 31 H3 + 1291 50 16 = O__OO@O___# : len=11 : H4 00 H4 + 1292 50 17 = O__OO@_O__# : len=11 : D4 00 D4 + 1293 50 18 = O__OO@OO__# : len=11 : L5 00 L5 + 1294 50 19 = O__OO@__O_# : len=11 : NO 00 H3 + 1295 50 20 = O__OO@O_O_# : len=11 : S4 00 H4 + 1296 50 21 = O__OO@_OO_# : len=11 : NO 00 D4 + 1297 50 22 = O__OO@OOO_# : len=11 : L6 00 L6 + 1298 50 23 = O__OO@___O# : len=11 : H3 31 H3 + 1299 50 24 = O__OO@O__O# : len=11 : H4 00 H4 + 1300 50 25 = O__OO@_O_O# : len=11 : D4 00 D4 + 1301 50 26 = O__OO@OO_O# : len=11 : L5 00 L5 + 1302 50 27 = O__OO@__OO# : len=11 : NO 00 H3 + 1303 50 28 = O__OO@O_OO# : len=11 : S4 00 H4 + 1304 50 29 = O__OO@_OOO# : len=11 : NO 00 D4 + 1305 50 30 = O__OO@OOOO# : len=11 : L6 00 L6 + 1306 50 31 = O__OO@_____ : len=11 : H3 31 H3 + 1307 50 32 = O__OO@O____ : len=11 : H4 00 H4 + 1308 50 33 = O__OO@_O___ : len=11 : D4 00 D4 + 1309 50 34 = O__OO@OO___ : len=11 : L5 00 L5 + 1310 50 35 = O__OO@__O__ : len=11 : NO 00 H3 + 1311 50 36 = O__OO@O_O__ : len=11 : S4 00 H4 + 1312 50 37 = O__OO@_OO__ : len=11 : NO 00 D4 + 1313 50 38 = O__OO@OOO__ : len=11 : L6 00 L6 + 1314 50 39 = O__OO@___O_ : len=11 : H3 31 H3 + 1315 50 40 = O__OO@O__O_ : len=11 : H4 00 H4 + 1316 50 41 = O__OO@_O_O_ : len=11 : D4 00 D4 + 1317 50 42 = O__OO@OO_O_ : len=11 : L5 00 L5 + 1318 50 43 = O__OO@__OO_ : len=11 : NO 00 H3 + 1319 50 44 = O__OO@O_OO_ : len=11 : S4 00 H4 + 1320 50 45 = O__OO@_OOO_ : len=11 : NO 00 D4 + 1321 50 46 = O__OO@OOOO_ : len=11 : L6 00 L6 + 1322 50 47 = O__OO@____O : len=11 : H3 31 H3 + 1323 50 48 = O__OO@O___O : len=11 : H4 00 H4 + 1324 50 49 = O__OO@_O__O : len=11 : D4 00 D4 + 1325 50 50 = O__OO@OO__O : len=11 : L5 00 L5 + 1326 51 0 = O_O__@# : len= 7 : NO 00 NO + 1327 51 1 = O_O__@_# : len= 8 : NO 00 NO + 1328 51 2 = O_O__@O# : len= 8 : NO 00 NO + 1329 51 3 = O_O__@__# : len= 9 : NO 00 NO + 1330 51 4 = O_O__@O_# : len= 9 : NO 00 NO + 1331 51 5 = O_O__@_O# : len= 9 : NO 00 NO + 1332 51 6 = O_O__@OO# : len= 9 : NO 00 NO + 1333 51 7 = O_O__@___# : len=10 : NO 00 NO + 1334 51 8 = O_O__@O__# : len=10 : NO 00 NO + 1335 51 9 = O_O__@_O_# : len=10 : NO 00 NO + 1336 51 10 = O_O__@OO_# : len=10 : NO 00 H3 + 1337 51 11 = O_O__@__O# : len=10 : NO 00 NO + 1338 51 12 = O_O__@O_O# : len=10 : NO 00 NO + 1339 51 13 = O_O__@_OO# : len=10 : NO 00 NO + 1340 51 14 = O_O__@OOO# : len=10 : S4 00 S4 + 1341 51 15 = O_O__@____# : len=11 : NO 00 NO + 1342 51 16 = O_O__@O___# : len=11 : NO 00 NO + 1343 51 17 = O_O__@_O__# : len=11 : NO 00 NO + 1344 51 18 = O_O__@OO__# : len=11 : H3 13 H3 + 1345 51 19 = O_O__@__O_# : len=11 : NO 00 NO + 1346 51 20 = O_O__@O_O_# : len=11 : D3 02 D3 + 1347 51 21 = O_O__@_OO_# : len=11 : D3 01 D3 + 1348 51 22 = O_O__@OOO_# : len=11 : H4 00 H4 + 1349 51 23 = O_O__@___O# : len=11 : NO 00 NO + 1350 51 24 = O_O__@O__O# : len=11 : NO 00 NO + 1351 51 25 = O_O__@_O_O# : len=11 : NO 00 NO + 1352 51 26 = O_O__@OO_O# : len=11 : D4 00 D4 + 1353 51 27 = O_O__@__OO# : len=11 : NO 00 NO + 1354 51 28 = O_O__@O_OO# : len=11 : D4 00 D4 + 1355 51 29 = O_O__@_OOO# : len=11 : D4 00 D4 + 1356 51 30 = O_O__@OOOO# : len=11 : L5 00 L5 + 1357 51 31 = O_O__@_____ : len=11 : NO 00 NO + 1358 51 32 = O_O__@O____ : len=11 : NO 00 NO + 1359 51 33 = O_O__@_O___ : len=11 : NO 00 NO + 1360 51 34 = O_O__@OO___ : len=11 : H3 13 H3 + 1361 51 35 = O_O__@__O__ : len=11 : NO 00 NO + 1362 51 36 = O_O__@O_O__ : len=11 : D3 02 D3 + 1363 51 37 = O_O__@_OO__ : len=11 : D3 01 D3 + 1364 51 38 = O_O__@OOO__ : len=11 : H4 00 H4 + 1365 51 39 = O_O__@___O_ : len=11 : NO 00 NO + 1366 51 40 = O_O__@O__O_ : len=11 : NO 00 NO + 1367 51 41 = O_O__@_O_O_ : len=11 : NO 00 NO + 1368 51 42 = O_O__@OO_O_ : len=11 : D4 00 D4 + 1369 51 43 = O_O__@__OO_ : len=11 : NO 00 NO + 1370 51 44 = O_O__@O_OO_ : len=11 : D4 00 D4 + 1371 51 45 = O_O__@_OOO_ : len=11 : D4 00 D4 + 1372 51 46 = O_O__@OOOO_ : len=11 : L5 00 L5 + 1373 51 47 = O_O__@____O : len=11 : NO 00 NO + 1374 51 48 = O_O__@O___O : len=11 : NO 00 NO + 1375 51 49 = O_O__@_O__O : len=11 : NO 00 NO + 1376 51 50 = O_O__@OO__O : len=11 : NO 00 H3 + 1377 51 51 = O_O__@__O_O : len=11 : NO 00 NO + 1378 52 0 = O_O_O@# : len= 7 : NO 00 NO + 1379 52 1 = O_O_O@_# : len= 8 : NO 00 D3 + 1380 52 2 = O_O_O@O# : len= 8 : D4 00 D4 + 1381 52 3 = O_O_O@__# : len= 9 : NO 00 D3 + 1382 52 4 = O_O_O@O_# : len= 9 : D4 00 D4 + 1383 52 5 = O_O_O@_O# : len= 9 : NO 00 D3 + 1384 52 6 = O_O_O@OO# : len= 9 : NO 00 D4 + 1385 52 7 = O_O_O@___# : len=10 : NO 00 D3 + 1386 52 8 = O_O_O@O__# : len=10 : D4 00 D4 + 1387 52 9 = O_O_O@_O_# : len=10 : NO 00 D3 + 1388 52 10 = O_O_O@OO_# : len=10 : S4 00 H4 + 1389 52 11 = O_O_O@__O# : len=10 : NO 00 D3 + 1390 52 12 = O_O_O@O_O# : len=10 : X4 00 X4 + 1391 52 13 = O_O_O@_OO# : len=10 : D4 00 D4 + 1392 52 14 = O_O_O@OOO# : len=10 : L5 00 L5 + 1393 52 15 = O_O_O@____# : len=11 : NO 00 D3 + 1394 52 16 = O_O_O@O___# : len=11 : D4 00 D4 + 1395 52 17 = O_O_O@_O__# : len=11 : NO 00 D3 + 1396 52 18 = O_O_O@OO__# : len=11 : S4 00 H4 + 1397 52 19 = O_O_O@__O_# : len=11 : NO 00 D3 + 1398 52 20 = O_O_O@O_O_# : len=11 : X4 00 X4 + 1399 52 21 = O_O_O@_OO_# : len=11 : D4 00 D4 + 1400 52 22 = O_O_O@OOO_# : len=11 : L5 00 L5 + 1401 52 23 = O_O_O@___O# : len=11 : NO 00 D3 + 1402 52 24 = O_O_O@O__O# : len=11 : D4 00 D4 + 1403 52 25 = O_O_O@_O_O# : len=11 : NO 00 D3 + 1404 52 26 = O_O_O@OO_O# : len=11 : NO 00 H4 + 1405 52 27 = O_O_O@__OO# : len=11 : NO 00 D3 + 1406 52 28 = O_O_O@O_OO# : len=11 : D4 00 X4 + 1407 52 29 = O_O_O@_OOO# : len=11 : NO 00 D4 + 1408 52 30 = O_O_O@OOOO# : len=11 : L6 00 L6 + 1409 52 31 = O_O_O@_____ : len=11 : NO 00 D3 + 1410 52 32 = O_O_O@O____ : len=11 : D4 00 D4 + 1411 52 33 = O_O_O@_O___ : len=11 : NO 00 D3 + 1412 52 34 = O_O_O@OO___ : len=11 : S4 00 H4 + 1413 52 35 = O_O_O@__O__ : len=11 : NO 00 D3 + 1414 52 36 = O_O_O@O_O__ : len=11 : X4 00 X4 + 1415 52 37 = O_O_O@_OO__ : len=11 : D4 00 D4 + 1416 52 38 = O_O_O@OOO__ : len=11 : L5 00 L5 + 1417 52 39 = O_O_O@___O_ : len=11 : NO 00 D3 + 1418 52 40 = O_O_O@O__O_ : len=11 : D4 00 D4 + 1419 52 41 = O_O_O@_O_O_ : len=11 : NO 00 D3 + 1420 52 42 = O_O_O@OO_O_ : len=11 : NO 00 H4 + 1421 52 43 = O_O_O@__OO_ : len=11 : NO 00 D3 + 1422 52 44 = O_O_O@O_OO_ : len=11 : D4 00 X4 + 1423 52 45 = O_O_O@_OOO_ : len=11 : NO 00 D4 + 1424 52 46 = O_O_O@OOOO_ : len=11 : L6 00 L6 + 1425 52 47 = O_O_O@____O : len=11 : NO 00 D3 + 1426 52 48 = O_O_O@O___O : len=11 : D4 00 D4 + 1427 52 49 = O_O_O@_O__O : len=11 : NO 00 D3 + 1428 52 50 = O_O_O@OO__O : len=11 : S4 00 H4 + 1429 52 51 = O_O_O@__O_O : len=11 : NO 00 D3 + 1430 52 52 = O_O_O@O_O_O : len=11 : X4 00 X4 + 1431 53 0 = O_OO_@# : len= 7 : NO 00 NO + 1432 53 1 = O_OO_@_# : len= 8 : NO 00 D3 + 1433 53 2 = O_OO_@O# : len= 8 : D4 00 D4 + 1434 53 3 = O_OO_@__# : len= 9 : NO 00 D3 + 1435 53 4 = O_OO_@O_# : len= 9 : D4 00 D4 + 1436 53 5 = O_OO_@_O# : len= 9 : NO 00 D3 + 1437 53 6 = O_OO_@OO# : len= 9 : NO 00 D4 + 1438 53 7 = O_OO_@___# : len=10 : NO 00 D3 + 1439 53 8 = O_OO_@O__# : len=10 : D4 00 D4 + 1440 53 9 = O_OO_@_O_# : len=10 : NO 00 D3 + 1441 53 10 = O_OO_@OO_# : len=10 : NO 00 D4 + 1442 53 11 = O_OO_@__O# : len=10 : NO 00 D3 + 1443 53 12 = O_OO_@O_O# : len=10 : D4 00 D4 + 1444 53 13 = O_OO_@_OO# : len=10 : NO 00 D3 + 1445 53 14 = O_OO_@OOO# : len=10 : NO 00 D4 + 1446 53 15 = O_OO_@____# : len=11 : NO 00 D3 + 1447 53 16 = O_OO_@O___# : len=11 : D4 00 D4 + 1448 53 17 = O_OO_@_O__# : len=11 : NO 00 D3 + 1449 53 18 = O_OO_@OO__# : len=11 : NO 00 D4 + 1450 53 19 = O_OO_@__O_# : len=11 : NO 00 D3 + 1451 53 20 = O_OO_@O_O_# : len=11 : D4 00 D4 + 1452 53 21 = O_OO_@_OO_# : len=11 : NO 00 D3 + 1453 53 22 = O_OO_@OOO_# : len=11 : S4 00 H4 + 1454 53 23 = O_OO_@___O# : len=11 : NO 00 D3 + 1455 53 24 = O_OO_@O__O# : len=11 : D4 00 D4 + 1456 53 25 = O_OO_@_O_O# : len=11 : NO 00 D3 + 1457 53 26 = O_OO_@OO_O# : len=11 : D4 00 X4 + 1458 53 27 = O_OO_@__OO# : len=11 : NO 00 D3 + 1459 53 28 = O_OO_@O_OO# : len=11 : X4 00 X4 + 1460 53 29 = O_OO_@_OOO# : len=11 : D4 00 D4 + 1461 53 30 = O_OO_@OOOO# : len=11 : L5 00 L5 + 1462 53 31 = O_OO_@_____ : len=11 : NO 00 D3 + 1463 53 32 = O_OO_@O____ : len=11 : D4 00 D4 + 1464 53 33 = O_OO_@_O___ : len=11 : NO 00 D3 + 1465 53 34 = O_OO_@OO___ : len=11 : NO 00 D4 + 1466 53 35 = O_OO_@__O__ : len=11 : NO 00 D3 + 1467 53 36 = O_OO_@O_O__ : len=11 : D4 00 D4 + 1468 53 37 = O_OO_@_OO__ : len=11 : NO 00 D3 + 1469 53 38 = O_OO_@OOO__ : len=11 : S4 00 H4 + 1470 53 39 = O_OO_@___O_ : len=11 : NO 00 D3 + 1471 53 40 = O_OO_@O__O_ : len=11 : D4 00 D4 + 1472 53 41 = O_OO_@_O_O_ : len=11 : NO 00 D3 + 1473 53 42 = O_OO_@OO_O_ : len=11 : D4 00 X4 + 1474 53 43 = O_OO_@__OO_ : len=11 : NO 00 D3 + 1475 53 44 = O_OO_@O_OO_ : len=11 : X4 00 X4 + 1476 53 45 = O_OO_@_OOO_ : len=11 : D4 00 D4 + 1477 53 46 = O_OO_@OOOO_ : len=11 : L5 00 L5 + 1478 53 47 = O_OO_@____O : len=11 : NO 00 D3 + 1479 53 48 = O_OO_@O___O : len=11 : D4 00 D4 + 1480 53 49 = O_OO_@_O__O : len=11 : NO 00 D3 + 1481 53 50 = O_OO_@OO__O : len=11 : NO 00 D4 + 1482 53 51 = O_OO_@__O_O : len=11 : NO 00 D3 + 1483 53 52 = O_OO_@O_O_O : len=11 : D4 00 D4 + 1484 53 53 = O_OO_@_OO_O : len=11 : NO 00 D3 + 1485 54 0 = O_OOO@# : len= 7 : NO 00 D4 + 1486 54 1 = O_OOO@_# : len= 8 : S4 00 H4 + 1487 54 2 = O_OOO@O# : len= 8 : L5 00 L5 + 1488 54 3 = O_OOO@__# : len= 9 : S4 00 H4 + 1489 54 4 = O_OOO@O_# : len= 9 : L5 00 L5 + 1490 54 5 = O_OOO@_O# : len= 9 : NO 00 H4 + 1491 54 6 = O_OOO@OO# : len= 9 : L6 00 L6 + 1492 54 7 = O_OOO@___# : len=10 : S4 00 H4 + 1493 54 8 = O_OOO@O__# : len=10 : L5 00 L5 + 1494 54 9 = O_OOO@_O_# : len=10 : NO 00 H4 + 1495 54 10 = O_OOO@OO_# : len=10 : L6 00 L6 + 1496 54 11 = O_OOO@__O# : len=10 : S4 00 H4 + 1497 54 12 = O_OOO@O_O# : len=10 : L5 00 L5 + 1498 54 13 = O_OOO@_OO# : len=10 : NO 00 H4 + 1499 54 14 = O_OOO@OOO# : len=10 : L6 00 L6 + 1500 54 15 = O_OOO@____# : len=11 : S4 00 H4 + 1501 54 16 = O_OOO@O___# : len=11 : L5 00 L5 + 1502 54 17 = O_OOO@_O__# : len=11 : NO 00 H4 + 1503 54 18 = O_OOO@OO__# : len=11 : L6 00 L6 + 1504 54 19 = O_OOO@__O_# : len=11 : S4 00 H4 + 1505 54 20 = O_OOO@O_O_# : len=11 : L5 00 L5 + 1506 54 21 = O_OOO@_OO_# : len=11 : NO 00 H4 + 1507 54 22 = O_OOO@OOO_# : len=11 : L6 00 L6 + 1508 54 23 = O_OOO@___O# : len=11 : S4 00 H4 + 1509 54 24 = O_OOO@O__O# : len=11 : L5 00 L5 + 1510 54 25 = O_OOO@_O_O# : len=11 : NO 00 H4 + 1511 54 26 = O_OOO@OO_O# : len=11 : L6 00 L6 + 1512 54 27 = O_OOO@__OO# : len=11 : S4 00 H4 + 1513 54 28 = O_OOO@O_OO# : len=11 : L5 00 L5 + 1514 54 29 = O_OOO@_OOO# : len=11 : NO 00 H4 + 1515 54 30 = O_OOO@OOOO# : len=11 : L6 00 L6 + 1516 54 31 = O_OOO@_____ : len=11 : S4 00 H4 + 1517 54 32 = O_OOO@O____ : len=11 : L5 00 L5 + 1518 54 33 = O_OOO@_O___ : len=11 : NO 00 H4 + 1519 54 34 = O_OOO@OO___ : len=11 : L6 00 L6 + 1520 54 35 = O_OOO@__O__ : len=11 : S4 00 H4 + 1521 54 36 = O_OOO@O_O__ : len=11 : L5 00 L5 + 1522 54 37 = O_OOO@_OO__ : len=11 : NO 00 H4 + 1523 54 38 = O_OOO@OOO__ : len=11 : L6 00 L6 + 1524 54 39 = O_OOO@___O_ : len=11 : S4 00 H4 + 1525 54 40 = O_OOO@O__O_ : len=11 : L5 00 L5 + 1526 54 41 = O_OOO@_O_O_ : len=11 : NO 00 H4 + 1527 54 42 = O_OOO@OO_O_ : len=11 : L6 00 L6 + 1528 54 43 = O_OOO@__OO_ : len=11 : S4 00 H4 + 1529 54 44 = O_OOO@O_OO_ : len=11 : L5 00 L5 + 1530 54 45 = O_OOO@_OOO_ : len=11 : NO 00 H4 + 1531 54 46 = O_OOO@OOOO_ : len=11 : L6 00 L6 + 1532 54 47 = O_OOO@____O : len=11 : S4 00 H4 + 1533 54 48 = O_OOO@O___O : len=11 : L5 00 L5 + 1534 54 49 = O_OOO@_O__O : len=11 : NO 00 H4 + 1535 54 50 = O_OOO@OO__O : len=11 : L6 00 L6 + 1536 54 51 = O_OOO@__O_O : len=11 : S4 00 H4 + 1537 54 52 = O_OOO@O_O_O : len=11 : L5 00 L5 + 1538 54 53 = O_OOO@_OO_O : len=11 : NO 00 H4 + 1539 54 54 = O_OOO@OOO_O : len=11 : L6 00 L6 + 1540 55 0 = OO___@# : len= 7 : NO 00 NO + 1541 55 1 = OO___@_# : len= 8 : NO 00 NO + 1542 55 2 = OO___@O# : len= 8 : NO 00 NO + 1543 55 3 = OO___@__# : len= 9 : NO 00 NO + 1544 55 4 = OO___@O_# : len= 9 : NO 00 NO + 1545 55 5 = OO___@_O# : len= 9 : NO 00 NO + 1546 55 6 = OO___@OO# : len= 9 : NO 00 NO + 1547 55 7 = OO___@___# : len=10 : NO 00 NO + 1548 55 8 = OO___@O__# : len=10 : NO 00 NO + 1549 55 9 = OO___@_O_# : len=10 : NO 00 NO + 1550 55 10 = OO___@OO_# : len=10 : H3 13 H3 + 1551 55 11 = OO___@__O# : len=10 : NO 00 NO + 1552 55 12 = OO___@O_O# : len=10 : NO 00 NO + 1553 55 13 = OO___@_OO# : len=10 : NO 00 NO + 1554 55 14 = OO___@OOO# : len=10 : S4 00 S4 + 1555 55 15 = OO___@____# : len=11 : NO 00 NO + 1556 55 16 = OO___@O___# : len=11 : NO 00 NO + 1557 55 17 = OO___@_O__# : len=11 : NO 00 NO + 1558 55 18 = OO___@OO__# : len=11 : H3 13 H3 + 1559 55 19 = OO___@__O_# : len=11 : NO 00 NO + 1560 55 20 = OO___@O_O_# : len=11 : D3 02 D3 + 1561 55 21 = OO___@_OO_# : len=11 : D3 01 D3 + 1562 55 22 = OO___@OOO_# : len=11 : H4 00 H4 + 1563 55 23 = OO___@___O# : len=11 : NO 00 NO + 1564 55 24 = OO___@O__O# : len=11 : NO 00 NO + 1565 55 25 = OO___@_O_O# : len=11 : NO 00 NO + 1566 55 26 = OO___@OO_O# : len=11 : D4 00 D4 + 1567 55 27 = OO___@__OO# : len=11 : NO 00 NO + 1568 55 28 = OO___@O_OO# : len=11 : D4 00 D4 + 1569 55 29 = OO___@_OOO# : len=11 : D4 00 D4 + 1570 55 30 = OO___@OOOO# : len=11 : L5 00 L5 + 1571 55 31 = OO___@_____ : len=11 : NO 00 NO + 1572 55 32 = OO___@O____ : len=11 : NO 00 NO + 1573 55 33 = OO___@_O___ : len=11 : NO 00 NO + 1574 55 34 = OO___@OO___ : len=11 : H3 13 H3 + 1575 55 35 = OO___@__O__ : len=11 : NO 00 NO + 1576 55 36 = OO___@O_O__ : len=11 : D3 02 D3 + 1577 55 37 = OO___@_OO__ : len=11 : D3 01 D3 + 1578 55 38 = OO___@OOO__ : len=11 : H4 00 H4 + 1579 55 39 = OO___@___O_ : len=11 : NO 00 NO + 1580 55 40 = OO___@O__O_ : len=11 : NO 00 NO + 1581 55 41 = OO___@_O_O_ : len=11 : NO 00 NO + 1582 55 42 = OO___@OO_O_ : len=11 : D4 00 D4 + 1583 55 43 = OO___@__OO_ : len=11 : NO 00 NO + 1584 55 44 = OO___@O_OO_ : len=11 : D4 00 D4 + 1585 55 45 = OO___@_OOO_ : len=11 : D4 00 D4 + 1586 55 46 = OO___@OOOO_ : len=11 : L5 00 L5 + 1587 55 47 = OO___@____O : len=11 : NO 00 NO + 1588 55 48 = OO___@O___O : len=11 : NO 00 NO + 1589 55 49 = OO___@_O__O : len=11 : NO 00 NO + 1590 55 50 = OO___@OO__O : len=11 : H3 13 H3 + 1591 55 51 = OO___@__O_O : len=11 : NO 00 NO + 1592 55 52 = OO___@O_O_O : len=11 : NO 00 D3 + 1593 55 53 = OO___@_OO_O : len=11 : NO 00 D3 + 1594 55 54 = OO___@OOO_O : len=11 : S4 00 H4 + 1595 55 55 = OO___@___OO : len=11 : NO 00 NO + 1596 56 0 = OO__O@# : len= 7 : NO 00 NO + 1597 56 1 = OO__O@_# : len= 8 : NO 00 NO + 1598 56 2 = OO__O@O# : len= 8 : NO 00 NO + 1599 56 3 = OO__O@__# : len= 9 : NO 00 NO + 1600 56 4 = OO__O@O_# : len= 9 : NO 00 H3 + 1601 56 5 = OO__O@_O# : len= 9 : NO 00 NO + 1602 56 6 = OO__O@OO# : len= 9 : S4 00 S4 + 1603 56 7 = OO__O@___# : len=10 : NO 00 NO + 1604 56 8 = OO__O@O__# : len=10 : H3 22 H3 + 1605 56 9 = OO__O@_O_# : len=10 : D3 01 D3 + 1606 56 10 = OO__O@OO_# : len=10 : H4 00 H4 + 1607 56 11 = OO__O@__O# : len=10 : NO 00 NO + 1608 56 12 = OO__O@O_O# : len=10 : D4 00 D4 + 1609 56 13 = OO__O@_OO# : len=10 : D4 00 D4 + 1610 56 14 = OO__O@OOO# : len=10 : L5 00 L5 + 1611 56 15 = OO__O@____# : len=11 : NO 00 NO + 1612 56 16 = OO__O@O___# : len=11 : H3 22 H3 + 1613 56 17 = OO__O@_O__# : len=11 : D3 01 D3 + 1614 56 18 = OO__O@OO__# : len=11 : H4 00 H4 + 1615 56 19 = OO__O@__O_# : len=11 : NO 00 NO + 1616 56 20 = OO__O@O_O_# : len=11 : D4 00 D4 + 1617 56 21 = OO__O@_OO_# : len=11 : D4 00 D4 + 1618 56 22 = OO__O@OOO_# : len=11 : L5 00 L5 + 1619 56 23 = OO__O@___O# : len=11 : NO 00 NO + 1620 56 24 = OO__O@O__O# : len=11 : NO 00 H3 + 1621 56 25 = OO__O@_O_O# : len=11 : NO 00 D3 + 1622 56 26 = OO__O@OO_O# : len=11 : S4 00 H4 + 1623 56 27 = OO__O@__OO# : len=11 : NO 00 NO + 1624 56 28 = OO__O@O_OO# : len=11 : NO 00 D4 + 1625 56 29 = OO__O@_OOO# : len=11 : NO 00 D4 + 1626 56 30 = OO__O@OOOO# : len=11 : L6 00 L6 + 1627 56 31 = OO__O@_____ : len=11 : NO 00 NO + 1628 56 32 = OO__O@O____ : len=11 : H3 22 H3 + 1629 56 33 = OO__O@_O___ : len=11 : D3 01 D3 + 1630 56 34 = OO__O@OO___ : len=11 : H4 00 H4 + 1631 56 35 = OO__O@__O__ : len=11 : NO 00 NO + 1632 56 36 = OO__O@O_O__ : len=11 : D4 00 D4 + 1633 56 37 = OO__O@_OO__ : len=11 : D4 00 D4 + 1634 56 38 = OO__O@OOO__ : len=11 : L5 00 L5 + 1635 56 39 = OO__O@___O_ : len=11 : NO 00 NO + 1636 56 40 = OO__O@O__O_ : len=11 : NO 00 H3 + 1637 56 41 = OO__O@_O_O_ : len=11 : NO 00 D3 + 1638 56 42 = OO__O@OO_O_ : len=11 : S4 00 H4 + 1639 56 43 = OO__O@__OO_ : len=11 : NO 00 NO + 1640 56 44 = OO__O@O_OO_ : len=11 : NO 00 D4 + 1641 56 45 = OO__O@_OOO_ : len=11 : NO 00 D4 + 1642 56 46 = OO__O@OOOO_ : len=11 : L6 00 L6 + 1643 56 47 = OO__O@____O : len=11 : NO 00 NO + 1644 56 48 = OO__O@O___O : len=11 : H3 22 H3 + 1645 56 49 = OO__O@_O__O : len=11 : D3 01 D3 + 1646 56 50 = OO__O@OO__O : len=11 : H4 00 H4 + 1647 56 51 = OO__O@__O_O : len=11 : NO 00 NO + 1648 56 52 = OO__O@O_O_O : len=11 : D4 00 D4 + 1649 56 53 = OO__O@_OO_O : len=11 : D4 00 D4 + 1650 56 54 = OO__O@OOO_O : len=11 : L5 00 L5 + 1651 56 55 = OO__O@___OO : len=11 : NO 00 NO + 1652 56 56 = OO__O@O__OO : len=11 : NO 00 H3 + 1653 57 0 = OO_O_@# : len= 7 : NO 00 NO + 1654 57 1 = OO_O_@_# : len= 8 : NO 00 NO + 1655 57 2 = OO_O_@O# : len= 8 : NO 00 NO + 1656 57 3 = OO_O_@__# : len= 9 : NO 00 NO + 1657 57 4 = OO_O_@O_# : len= 9 : NO 00 D3 + 1658 57 5 = OO_O_@_O# : len= 9 : NO 00 NO + 1659 57 6 = OO_O_@OO# : len= 9 : D4 00 D4 + 1660 57 7 = OO_O_@___# : len=10 : NO 00 NO + 1661 57 8 = OO_O_@O__# : len=10 : NO 00 D3 + 1662 57 9 = OO_O_@_O_# : len=10 : NO 00 NO + 1663 57 10 = OO_O_@OO_# : len=10 : D4 00 D4 + 1664 57 11 = OO_O_@__O# : len=10 : NO 00 NO + 1665 57 12 = OO_O_@O_O# : len=10 : NO 00 D3 + 1666 57 13 = OO_O_@_OO# : len=10 : NO 00 NO + 1667 57 14 = OO_O_@OOO# : len=10 : NO 00 D4 + 1668 57 15 = OO_O_@____# : len=11 : NO 00 NO + 1669 57 16 = OO_O_@O___# : len=11 : NO 00 D3 + 1670 57 17 = OO_O_@_O__# : len=11 : NO 00 NO + 1671 57 18 = OO_O_@OO__# : len=11 : D4 00 D4 + 1672 57 19 = OO_O_@__O_# : len=11 : NO 00 NO + 1673 57 20 = OO_O_@O_O_# : len=11 : NO 00 D3 + 1674 57 21 = OO_O_@_OO_# : len=11 : NO 00 D3 + 1675 57 22 = OO_O_@OOO_# : len=11 : S4 00 H4 + 1676 57 23 = OO_O_@___O# : len=11 : NO 00 NO + 1677 57 24 = OO_O_@O__O# : len=11 : NO 00 D3 + 1678 57 25 = OO_O_@_O_O# : len=11 : NO 00 NO + 1679 57 26 = OO_O_@OO_O# : len=11 : X4 00 X4 + 1680 57 27 = OO_O_@__OO# : len=11 : NO 00 NO + 1681 57 28 = OO_O_@O_OO# : len=11 : D4 00 D4 + 1682 57 29 = OO_O_@_OOO# : len=11 : D4 00 D4 + 1683 57 30 = OO_O_@OOOO# : len=11 : L5 00 L5 + 1684 57 31 = OO_O_@_____ : len=11 : NO 00 NO + 1685 57 32 = OO_O_@O____ : len=11 : NO 00 D3 + 1686 57 33 = OO_O_@_O___ : len=11 : NO 00 NO + 1687 57 34 = OO_O_@OO___ : len=11 : D4 00 D4 + 1688 57 35 = OO_O_@__O__ : len=11 : NO 00 NO + 1689 57 36 = OO_O_@O_O__ : len=11 : NO 00 D3 + 1690 57 37 = OO_O_@_OO__ : len=11 : NO 00 D3 + 1691 57 38 = OO_O_@OOO__ : len=11 : S4 00 H4 + 1692 57 39 = OO_O_@___O_ : len=11 : NO 00 NO + 1693 57 40 = OO_O_@O__O_ : len=11 : NO 00 D3 + 1694 57 41 = OO_O_@_O_O_ : len=11 : NO 00 NO + 1695 57 42 = OO_O_@OO_O_ : len=11 : X4 00 X4 + 1696 57 43 = OO_O_@__OO_ : len=11 : NO 00 NO + 1697 57 44 = OO_O_@O_OO_ : len=11 : D4 00 D4 + 1698 57 45 = OO_O_@_OOO_ : len=11 : D4 00 D4 + 1699 57 46 = OO_O_@OOOO_ : len=11 : L5 00 L5 + 1700 57 47 = OO_O_@____O : len=11 : NO 00 NO + 1701 57 48 = OO_O_@O___O : len=11 : NO 00 D3 + 1702 57 49 = OO_O_@_O__O : len=11 : NO 00 NO + 1703 57 50 = OO_O_@OO__O : len=11 : D4 00 D4 + 1704 57 51 = OO_O_@__O_O : len=11 : NO 00 NO + 1705 57 52 = OO_O_@O_O_O : len=11 : NO 00 D3 + 1706 57 53 = OO_O_@_OO_O : len=11 : NO 00 D3 + 1707 57 54 = OO_O_@OOO_O : len=11 : NO 00 H4 + 1708 57 55 = OO_O_@___OO : len=11 : NO 00 NO + 1709 57 56 = OO_O_@O__OO : len=11 : NO 00 D3 + 1710 57 57 = OO_O_@_O_OO : len=11 : NO 00 NO + 1711 58 0 = OO_OO@# : len= 7 : NO 00 D4 + 1712 58 1 = OO_OO@_# : len= 8 : NO 00 D4 + 1713 58 2 = OO_OO@O# : len= 8 : NO 00 D4 + 1714 58 3 = OO_OO@__# : len= 9 : NO 00 D4 + 1715 58 4 = OO_OO@O_# : len= 9 : S4 00 H4 + 1716 58 5 = OO_OO@_O# : len= 9 : D4 00 X4 + 1717 58 6 = OO_OO@OO# : len= 9 : L5 00 L5 + 1718 58 7 = OO_OO@___# : len=10 : NO 00 D4 + 1719 58 8 = OO_OO@O__# : len=10 : S4 00 H4 + 1720 58 9 = OO_OO@_O_# : len=10 : D4 00 X4 + 1721 58 10 = OO_OO@OO_# : len=10 : L5 00 L5 + 1722 58 11 = OO_OO@__O# : len=10 : NO 00 D4 + 1723 58 12 = OO_OO@O_O# : len=10 : NO 00 H4 + 1724 58 13 = OO_OO@_OO# : len=10 : NO 00 X4 + 1725 58 14 = OO_OO@OOO# : len=10 : L6 00 L6 + 1726 58 15 = OO_OO@____# : len=11 : NO 00 D4 + 1727 58 16 = OO_OO@O___# : len=11 : S4 00 H4 + 1728 58 17 = OO_OO@_O__# : len=11 : D4 00 X4 + 1729 58 18 = OO_OO@OO__# : len=11 : L5 00 L5 + 1730 58 19 = OO_OO@__O_# : len=11 : NO 00 D4 + 1731 58 20 = OO_OO@O_O_# : len=11 : NO 00 H4 + 1732 58 21 = OO_OO@_OO_# : len=11 : NO 00 X4 + 1733 58 22 = OO_OO@OOO_# : len=11 : L6 00 L6 + 1734 58 23 = OO_OO@___O# : len=11 : NO 00 D4 + 1735 58 24 = OO_OO@O__O# : len=11 : S4 00 H4 + 1736 58 25 = OO_OO@_O_O# : len=11 : D4 00 X4 + 1737 58 26 = OO_OO@OO_O# : len=11 : L5 00 L5 + 1738 58 27 = OO_OO@__OO# : len=11 : NO 00 D4 + 1739 58 28 = OO_OO@O_OO# : len=11 : NO 00 H4 + 1740 58 29 = OO_OO@_OOO# : len=11 : NO 00 X4 + 1741 58 30 = OO_OO@OOOO# : len=11 : L6 00 L6 + 1742 58 31 = OO_OO@_____ : len=11 : NO 00 D4 + 1743 58 32 = OO_OO@O____ : len=11 : S4 00 H4 + 1744 58 33 = OO_OO@_O___ : len=11 : D4 00 X4 + 1745 58 34 = OO_OO@OO___ : len=11 : L5 00 L5 + 1746 58 35 = OO_OO@__O__ : len=11 : NO 00 D4 + 1747 58 36 = OO_OO@O_O__ : len=11 : NO 00 H4 + 1748 58 37 = OO_OO@_OO__ : len=11 : NO 00 X4 + 1749 58 38 = OO_OO@OOO__ : len=11 : L6 00 L6 + 1750 58 39 = OO_OO@___O_ : len=11 : NO 00 D4 + 1751 58 40 = OO_OO@O__O_ : len=11 : S4 00 H4 + 1752 58 41 = OO_OO@_O_O_ : len=11 : D4 00 X4 + 1753 58 42 = OO_OO@OO_O_ : len=11 : L5 00 L5 + 1754 58 43 = OO_OO@__OO_ : len=11 : NO 00 D4 + 1755 58 44 = OO_OO@O_OO_ : len=11 : NO 00 H4 + 1756 58 45 = OO_OO@_OOO_ : len=11 : NO 00 X4 + 1757 58 46 = OO_OO@OOOO_ : len=11 : L6 00 L6 + 1758 58 47 = OO_OO@____O : len=11 : NO 00 D4 + 1759 58 48 = OO_OO@O___O : len=11 : S4 00 H4 + 1760 58 49 = OO_OO@_O__O : len=11 : D4 00 X4 + 1761 58 50 = OO_OO@OO__O : len=11 : L5 00 L5 + 1762 58 51 = OO_OO@__O_O : len=11 : NO 00 D4 + 1763 58 52 = OO_OO@O_O_O : len=11 : NO 00 H4 + 1764 58 53 = OO_OO@_OO_O : len=11 : NO 00 X4 + 1765 58 54 = OO_OO@OOO_O : len=11 : L6 00 L6 + 1766 58 55 = OO_OO@___OO : len=11 : NO 00 D4 + 1767 58 56 = OO_OO@O__OO : len=11 : S4 00 H4 + 1768 58 57 = OO_OO@_O_OO : len=11 : D4 00 X4 + 1769 58 58 = OO_OO@OO_OO : len=11 : L5 00 L5 + 1770 59 0 = OOO__@# : len= 7 : NO 00 NO + 1771 59 1 = OOO__@_# : len= 8 : NO 00 NO + 1772 59 2 = OOO__@O# : len= 8 : NO 00 NO + 1773 59 3 = OOO__@__# : len= 9 : NO 00 NO + 1774 59 4 = OOO__@O_# : len= 9 : NO 00 NO + 1775 59 5 = OOO__@_O# : len= 9 : NO 00 NO + 1776 59 6 = OOO__@OO# : len= 9 : NO 00 NO + 1777 59 7 = OOO__@___# : len=10 : NO 00 NO + 1778 59 8 = OOO__@O__# : len=10 : NO 00 NO + 1779 59 9 = OOO__@_O_# : len=10 : NO 00 NO + 1780 59 10 = OOO__@OO_# : len=10 : NO 00 H3 + 1781 59 11 = OOO__@__O# : len=10 : NO 00 NO + 1782 59 12 = OOO__@O_O# : len=10 : NO 00 NO + 1783 59 13 = OOO__@_OO# : len=10 : NO 00 NO + 1784 59 14 = OOO__@OOO# : len=10 : S4 00 S4 + 1785 59 15 = OOO__@____# : len=11 : NO 00 NO + 1786 59 16 = OOO__@O___# : len=11 : NO 00 NO + 1787 59 17 = OOO__@_O__# : len=11 : NO 00 NO + 1788 59 18 = OOO__@OO__# : len=11 : H3 13 H3 + 1789 59 19 = OOO__@__O_# : len=11 : NO 00 NO + 1790 59 20 = OOO__@O_O_# : len=11 : D3 02 D3 + 1791 59 21 = OOO__@_OO_# : len=11 : D3 01 D3 + 1792 59 22 = OOO__@OOO_# : len=11 : H4 00 H4 + 1793 59 23 = OOO__@___O# : len=11 : NO 00 NO + 1794 59 24 = OOO__@O__O# : len=11 : NO 00 NO + 1795 59 25 = OOO__@_O_O# : len=11 : NO 00 NO + 1796 59 26 = OOO__@OO_O# : len=11 : D4 00 D4 + 1797 59 27 = OOO__@__OO# : len=11 : NO 00 NO + 1798 59 28 = OOO__@O_OO# : len=11 : D4 00 D4 + 1799 59 29 = OOO__@_OOO# : len=11 : D4 00 D4 + 1800 59 30 = OOO__@OOOO# : len=11 : L5 00 L5 + 1801 59 31 = OOO__@_____ : len=11 : NO 00 NO + 1802 59 32 = OOO__@O____ : len=11 : NO 00 NO + 1803 59 33 = OOO__@_O___ : len=11 : NO 00 NO + 1804 59 34 = OOO__@OO___ : len=11 : H3 13 H3 + 1805 59 35 = OOO__@__O__ : len=11 : NO 00 NO + 1806 59 36 = OOO__@O_O__ : len=11 : D3 02 D3 + 1807 59 37 = OOO__@_OO__ : len=11 : D3 01 D3 + 1808 59 38 = OOO__@OOO__ : len=11 : H4 00 H4 + 1809 59 39 = OOO__@___O_ : len=11 : NO 00 NO + 1810 59 40 = OOO__@O__O_ : len=11 : NO 00 NO + 1811 59 41 = OOO__@_O_O_ : len=11 : NO 00 NO + 1812 59 42 = OOO__@OO_O_ : len=11 : D4 00 D4 + 1813 59 43 = OOO__@__OO_ : len=11 : NO 00 NO + 1814 59 44 = OOO__@O_OO_ : len=11 : D4 00 D4 + 1815 59 45 = OOO__@_OOO_ : len=11 : D4 00 D4 + 1816 59 46 = OOO__@OOOO_ : len=11 : L5 00 L5 + 1817 59 47 = OOO__@____O : len=11 : NO 00 NO + 1818 59 48 = OOO__@O___O : len=11 : NO 00 NO + 1819 59 49 = OOO__@_O__O : len=11 : NO 00 NO + 1820 59 50 = OOO__@OO__O : len=11 : NO 00 H3 + 1821 59 51 = OOO__@__O_O : len=11 : NO 00 NO + 1822 59 52 = OOO__@O_O_O : len=11 : NO 00 D3 + 1823 59 53 = OOO__@_OO_O : len=11 : NO 00 D3 + 1824 59 54 = OOO__@OOO_O : len=11 : S4 00 H4 + 1825 59 55 = OOO__@___OO : len=11 : NO 00 NO + 1826 59 56 = OOO__@O__OO : len=11 : NO 00 NO + 1827 59 57 = OOO__@_O_OO : len=11 : NO 00 NO + 1828 59 58 = OOO__@OO_OO : len=11 : NO 00 D4 + 1829 59 59 = OOO__@__OOO : len=11 : NO 00 NO + 1830 60 0 = OOO_O@# : len= 7 : NO 00 D4 + 1831 60 1 = OOO_O@_# : len= 8 : NO 00 D4 + 1832 60 2 = OOO_O@O# : len= 8 : NO 00 D4 + 1833 60 3 = OOO_O@__# : len= 9 : NO 00 D4 + 1834 60 4 = OOO_O@O_# : len= 9 : NO 00 D4 + 1835 60 5 = OOO_O@_O# : len= 9 : NO 00 D4 + 1836 60 6 = OOO_O@OO# : len= 9 : NO 00 D4 + 1837 60 7 = OOO_O@___# : len=10 : NO 00 D4 + 1838 60 8 = OOO_O@O__# : len=10 : NO 00 D4 + 1839 60 9 = OOO_O@_O_# : len=10 : NO 00 D4 + 1840 60 10 = OOO_O@OO_# : len=10 : S4 00 H4 + 1841 60 11 = OOO_O@__O# : len=10 : NO 00 D4 + 1842 60 12 = OOO_O@O_O# : len=10 : D4 00 X4 + 1843 60 13 = OOO_O@_OO# : len=10 : D4 00 X4 + 1844 60 14 = OOO_O@OOO# : len=10 : L5 00 L5 + 1845 60 15 = OOO_O@____# : len=11 : NO 00 D4 + 1846 60 16 = OOO_O@O___# : len=11 : NO 00 D4 + 1847 60 17 = OOO_O@_O__# : len=11 : NO 00 D4 + 1848 60 18 = OOO_O@OO__# : len=11 : S4 00 H4 + 1849 60 19 = OOO_O@__O_# : len=11 : NO 00 D4 + 1850 60 20 = OOO_O@O_O_# : len=11 : D4 00 X4 + 1851 60 21 = OOO_O@_OO_# : len=11 : D4 00 X4 + 1852 60 22 = OOO_O@OOO_# : len=11 : L5 00 L5 + 1853 60 23 = OOO_O@___O# : len=11 : NO 00 D4 + 1854 60 24 = OOO_O@O__O# : len=11 : NO 00 D4 + 1855 60 25 = OOO_O@_O_O# : len=11 : NO 00 D4 + 1856 60 26 = OOO_O@OO_O# : len=11 : NO 00 H4 + 1857 60 27 = OOO_O@__OO# : len=11 : NO 00 D4 + 1858 60 28 = OOO_O@O_OO# : len=11 : NO 00 X4 + 1859 60 29 = OOO_O@_OOO# : len=11 : NO 00 X4 + 1860 60 30 = OOO_O@OOOO# : len=11 : L6 00 L6 + 1861 60 31 = OOO_O@_____ : len=11 : NO 00 D4 + 1862 60 32 = OOO_O@O____ : len=11 : NO 00 D4 + 1863 60 33 = OOO_O@_O___ : len=11 : NO 00 D4 + 1864 60 34 = OOO_O@OO___ : len=11 : S4 00 H4 + 1865 60 35 = OOO_O@__O__ : len=11 : NO 00 D4 + 1866 60 36 = OOO_O@O_O__ : len=11 : D4 00 X4 + 1867 60 37 = OOO_O@_OO__ : len=11 : D4 00 X4 + 1868 60 38 = OOO_O@OOO__ : len=11 : L5 00 L5 + 1869 60 39 = OOO_O@___O_ : len=11 : NO 00 D4 + 1870 60 40 = OOO_O@O__O_ : len=11 : NO 00 D4 + 1871 60 41 = OOO_O@_O_O_ : len=11 : NO 00 D4 + 1872 60 42 = OOO_O@OO_O_ : len=11 : NO 00 H4 + 1873 60 43 = OOO_O@__OO_ : len=11 : NO 00 D4 + 1874 60 44 = OOO_O@O_OO_ : len=11 : NO 00 X4 + 1875 60 45 = OOO_O@_OOO_ : len=11 : NO 00 X4 + 1876 60 46 = OOO_O@OOOO_ : len=11 : L6 00 L6 + 1877 60 47 = OOO_O@____O : len=11 : NO 00 D4 + 1878 60 48 = OOO_O@O___O : len=11 : NO 00 D4 + 1879 60 49 = OOO_O@_O__O : len=11 : NO 00 D4 + 1880 60 50 = OOO_O@OO__O : len=11 : S4 00 H4 + 1881 60 51 = OOO_O@__O_O : len=11 : NO 00 D4 + 1882 60 52 = OOO_O@O_O_O : len=11 : D4 00 X4 + 1883 60 53 = OOO_O@_OO_O : len=11 : D4 00 X4 + 1884 60 54 = OOO_O@OOO_O : len=11 : L5 00 L5 + 1885 60 55 = OOO_O@___OO : len=11 : NO 00 D4 + 1886 60 56 = OOO_O@O__OO : len=11 : NO 00 D4 + 1887 60 57 = OOO_O@_O_OO : len=11 : NO 00 D4 + 1888 60 58 = OOO_O@OO_OO : len=11 : NO 00 H4 + 1889 60 59 = OOO_O@__OOO : len=11 : NO 00 D4 + 1890 60 60 = OOO_O@O_OOO : len=11 : NO 00 X4 + 1891 61 0 = OOOO_@# : len= 7 : NO 00 D4 + 1892 61 1 = OOOO_@_# : len= 8 : NO 00 D4 + 1893 61 2 = OOOO_@O# : len= 8 : NO 00 D4 + 1894 61 3 = OOOO_@__# : len= 9 : NO 00 D4 + 1895 61 4 = OOOO_@O_# : len= 9 : NO 00 D4 + 1896 61 5 = OOOO_@_O# : len= 9 : NO 00 D4 + 1897 61 6 = OOOO_@OO# : len= 9 : NO 00 D4 + 1898 61 7 = OOOO_@___# : len=10 : NO 00 D4 + 1899 61 8 = OOOO_@O__# : len=10 : NO 00 D4 + 1900 61 9 = OOOO_@_O_# : len=10 : NO 00 D4 + 1901 61 10 = OOOO_@OO_# : len=10 : NO 00 D4 + 1902 61 11 = OOOO_@__O# : len=10 : NO 00 D4 + 1903 61 12 = OOOO_@O_O# : len=10 : NO 00 D4 + 1904 61 13 = OOOO_@_OO# : len=10 : NO 00 D4 + 1905 61 14 = OOOO_@OOO# : len=10 : NO 00 D4 + 1906 61 15 = OOOO_@____# : len=11 : NO 00 D4 + 1907 61 16 = OOOO_@O___# : len=11 : NO 00 D4 + 1908 61 17 = OOOO_@_O__# : len=11 : NO 00 D4 + 1909 61 18 = OOOO_@OO__# : len=11 : NO 00 D4 + 1910 61 19 = OOOO_@__O_# : len=11 : NO 00 D4 + 1911 61 20 = OOOO_@O_O_# : len=11 : NO 00 D4 + 1912 61 21 = OOOO_@_OO_# : len=11 : NO 00 D4 + 1913 61 22 = OOOO_@OOO_# : len=11 : S4 00 H4 + 1914 61 23 = OOOO_@___O# : len=11 : NO 00 D4 + 1915 61 24 = OOOO_@O__O# : len=11 : NO 00 D4 + 1916 61 25 = OOOO_@_O_O# : len=11 : NO 00 D4 + 1917 61 26 = OOOO_@OO_O# : len=11 : D4 00 X4 + 1918 61 27 = OOOO_@__OO# : len=11 : NO 00 D4 + 1919 61 28 = OOOO_@O_OO# : len=11 : D4 00 X4 + 1920 61 29 = OOOO_@_OOO# : len=11 : D4 00 X4 + 1921 61 30 = OOOO_@OOOO# : len=11 : L5 00 L5 + 1922 61 31 = OOOO_@_____ : len=11 : NO 00 D4 + 1923 61 32 = OOOO_@O____ : len=11 : NO 00 D4 + 1924 61 33 = OOOO_@_O___ : len=11 : NO 00 D4 + 1925 61 34 = OOOO_@OO___ : len=11 : NO 00 D4 + 1926 61 35 = OOOO_@__O__ : len=11 : NO 00 D4 + 1927 61 36 = OOOO_@O_O__ : len=11 : NO 00 D4 + 1928 61 37 = OOOO_@_OO__ : len=11 : NO 00 D4 + 1929 61 38 = OOOO_@OOO__ : len=11 : S4 00 H4 + 1930 61 39 = OOOO_@___O_ : len=11 : NO 00 D4 + 1931 61 40 = OOOO_@O__O_ : len=11 : NO 00 D4 + 1932 61 41 = OOOO_@_O_O_ : len=11 : NO 00 D4 + 1933 61 42 = OOOO_@OO_O_ : len=11 : D4 00 X4 + 1934 61 43 = OOOO_@__OO_ : len=11 : NO 00 D4 + 1935 61 44 = OOOO_@O_OO_ : len=11 : D4 00 X4 + 1936 61 45 = OOOO_@_OOO_ : len=11 : D4 00 X4 + 1937 61 46 = OOOO_@OOOO_ : len=11 : L5 00 L5 + 1938 61 47 = OOOO_@____O : len=11 : NO 00 D4 + 1939 61 48 = OOOO_@O___O : len=11 : NO 00 D4 + 1940 61 49 = OOOO_@_O__O : len=11 : NO 00 D4 + 1941 61 50 = OOOO_@OO__O : len=11 : NO 00 D4 + 1942 61 51 = OOOO_@__O_O : len=11 : NO 00 D4 + 1943 61 52 = OOOO_@O_O_O : len=11 : NO 00 D4 + 1944 61 53 = OOOO_@_OO_O : len=11 : NO 00 D4 + 1945 61 54 = OOOO_@OOO_O : len=11 : NO 00 H4 + 1946 61 55 = OOOO_@___OO : len=11 : NO 00 D4 + 1947 61 56 = OOOO_@O__OO : len=11 : NO 00 D4 + 1948 61 57 = OOOO_@_O_OO : len=11 : NO 00 D4 + 1949 61 58 = OOOO_@OO_OO : len=11 : NO 00 X4 + 1950 61 59 = OOOO_@__OOO : len=11 : NO 00 D4 + 1951 61 60 = OOOO_@O_OOO : len=11 : NO 00 X4 + 1952 61 61 = OOOO_@_OOOO : len=11 : NO 00 X4 +*/ + +unsigned char *pat_gomoku /* [1954] */ = +/* 0 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 16 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x55\xcc\x00\x00\x00\x00" +/* 32 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00\x44\x00\x33\x00\x00\x00" +/* 48 */ "\x00\x22\x00\x55\x00\x22\x00\x00\x00\x44\x33\x66\x55\xcc\x33\x66" +/* 64 */ "\x55\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00" +/* 80 */ "\x55\x00\x55\x00\x05\x00\x55\x02\x46\x00\xaa\x00\x00\x55\x00\x55" +/* 96 */ "\x00\x05\x00\x55\x00\x05\x00\x55\x00\x00\x44\xcc\x44\xcc\x05\xbb" +/* 112 */ "\x44\xcc\x05\xbb\x44\xcc\x05\xbb\x00\x00\x00\x00\x00\x00\x00\x00" +/* 128 */ "\x00\x00\x33\x00\x00\x00\x44\x00\x00\x00\x00\x00\x33\x00\x44\x00" +/* 144 */ "\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x00\x00\x00\x00\x22\x00\x55" +/* 160 */ "\x00\x22\x00\x55\x00\x02\x00\x05\x00\x22\x00\x00\x33\x44\x33\x66" +/* 176 */ "\x55\xcc\x33\x66\x55\xcc\x33\x46\x05\xbb\x33\x66\x55\xcc\x00\x00" +/* 192 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00" +/* 208 */ "\x33\x00\x00\x22\x55\x22\x55\x02\x05\x22\x55\x02\x46\x22\xaa\x55" +/* 224 */ "\xcc\x22\x55\x02\x46\x22\xaa\x00\x22\x55\x22\x55\x02\x05\x22\x55" +/* 240 */ "\x02\x05\x22\x55\x02\x05\x22\x55\x02\x05\x22\x55\x02\x44\x66\xcc" +/* 256 */ "\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb" +/* 272 */ "\x66\xcc\x46\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00" +/* 288 */ "\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x00\x00" +/* 304 */ "\x03\x00\x44\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x22\x66\x00" +/* 320 */ "\x55\x55\xcc\x00\x03\x00\x00\x00\x00\x02\x00\x55\x00\x02\x00\x55" +/* 336 */ "\x00\x02\x00\x05\x00\x02\x00\x55\x00\x02\x02\x46\x00\x02\x00\x55" +/* 352 */ "\x55\x05\x55\x46\xaa\xcc\x55\x46\xaa\xcc\x55\x06\x5a\xbb\x55\x46" +/* 368 */ "\xaa\xcc\x55\x06\x5a\xbb\x55\x46\xaa\xcc\x00\x00\x00\x00\x00\x00" +/* 384 */ "\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22" +/* 400 */ "\x66\x00\x00\x00\x55\x00\x55\x55\x05\x55\x05\x55\x05\x55\x05\x55" +/* 416 */ "\x46\x55\x5a\xaa\xcc\x55\x05\x55\x46\x55\x5a\xaa\xcc\x55\x05\x55" +/* 432 */ "\x06\x55\x0a\x55\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05" +/* 448 */ "\x55\x05\x55\x05\x55\x05\x55\x05\x55\x46\x55\x05\x55\x5a\x55\x5a" +/* 464 */ "\xaa\xcc\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" +/* 480 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" +/* 496 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00\x00\x00\x44\x00" +/* 512 */ "\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00" +/* 528 */ "\x00\x00\x00\x00\x33\x00\x44\x00\x33\x22\x66\x00\x55\x55\xcc\x00" +/* 544 */ "\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x02\x46\x00\x05\x05\xbb\x00" +/* 560 */ "\x33\x00\x00\x00\x00\x22\x00\x55\x00\x22\x00\x55\x00\x02\x00\x05" +/* 576 */ "\x00\x22\x00\x55\x00\x02\x02\x46\x00\x22\x00\xaa\x00\x55\x55\xcc" +/* 592 */ "\x00\x22\x00\x00\x33\x44\x33\x66\x55\xcc\x33\x66\x55\xcc\x33\x46" +/* 608 */ "\x05\xbb\x33\x66\x55\xcc\x33\x46\x05\xbb\x33\x66\x55\xcc\x33\x46" +/* 624 */ "\x05\xbb\x33\x66\x55\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 640 */ "\x03\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00" +/* 656 */ "\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00\x00\x22\x55\x22\x55\x02" +/* 672 */ "\x05\x22\x55\x02\x46\x22\xaa\x55\xcc\x22\x55\x02\x46\x22\xaa\x55" +/* 688 */ "\xcc\x22\x55\x02\x06\x22\x5a\x05\xbb\x22\x55\x02\x46\x22\xaa\x00" +/* 704 */ "\x22\x55\x22\x55\x02\x05\x22\x55\x02\x05\x22\x55\x02\x05\x22\x55" +/* 720 */ "\x02\x05\x22\x55\x02\x46\x22\x55\x02\x5a\x22\xaa\x55\xcc\x22\x55" +/* 736 */ "\x02\x05\x22\x55\x02\x44\x66\xcc\x66\xcc\x46\xbb\x66\xcc\x46\xbb" +/* 752 */ "\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb" +/* 768 */ "\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x00\x00\x00\x00" +/* 784 */ "\x00\x00\x00\x00\x00\x00\x33\x00\x00\x00\x44\x00\x00\x00\x33\x00" +/* 800 */ "\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00" +/* 816 */ "\x22\x22\x66\x00\x00\x00\x00\x00\x03\x00\x44\x00\x33\x22\x66\x00" +/* 832 */ "\x55\x55\xcc\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x03\x02\x46\x00" +/* 848 */ "\x05\x05\xbb\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x03\x00\x00\x00" +/* 864 */ "\x00\x02\x00\x55\x00\x02\x00\x55\x00\x02\x00\x05\x00\x02\x00\x55" +/* 880 */ "\x00\x02\x02\x46\x00\x02\x00\xaa\x00\x55\x55\xcc\x00\x02\x00\x55" +/* 896 */ "\x00\x02\x02\x46\x00\x02\x00\x55\x55\x05\x55\x46\xaa\xcc\x55\x46" +/* 912 */ "\xaa\xcc\x55\x06\x5a\xbb\x55\x46\xaa\xcc\x55\x06\x5a\xbb\x55\x46" +/* 928 */ "\xaa\xcc\x55\x06\x5a\xbb\x55\x46\xaa\xcc\x55\x06\x5a\xbb\x55\x46" +/* 944 */ "\xaa\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00" +/* 960 */ "\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55" +/* 976 */ "\xcc\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55" +/* 992 */ "\x05\x55\x05\x55\x05\x55\x05\x55\x46\x55\x5a\xaa\xcc\x55\x05\x55" +/* 1008 */ "\x46\x55\x5a\xaa\xcc\x55\x05\x55\x06\x55\x0a\x5a\xbb\x55\x05\x55" +/* 1024 */ "\x46\x55\x5a\xaa\xcc\x55\x05\x55\x06\x55\x0a\x55\x55\x05\x55\x05" +/* 1040 */ "\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05" +/* 1056 */ "\x55\x46\x55\x05\x55\x5a\x55\x5a\xaa\xcc\x55\x05\x55\x05\x55\x05" +/* 1072 */ "\x55\x46\x55\x05\x55\x5a\x55\x5a\xaa\xcc\xcc\xbb\xcc\xbb\xcc\xbb" +/* 1088 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" +/* 1104 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" +/* 1120 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\x00\x00\x00\x00\x00\x00\x00\x00" +/* 1136 */ "\x00\x00\x33\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00" +/* 1152 */ "\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00\x22\x22\x66\x00" +/* 1168 */ "\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x00\x00\x33\x00\x44\x00" +/* 1184 */ "\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x22\x66\x00\x55\x55\xcc\x00" +/* 1200 */ "\x33\x02\x46\x00\x05\x05\xbb\x00\x33\x22\x66\x00\x55\x55\xcc\x00" +/* 1216 */ "\x33\x02\x46\x00\x05\x05\xbb\x00\x33\x00\x00\x00\x00\x22\x00\x55" +/* 1232 */ "\x00\x22\x00\x55\x00\x02\x00\x05\x00\x22\x00\x55\x00\x02\x02\x46" +/* 1248 */ "\x00\x22\x00\xaa\x00\x55\x55\xcc\x00\x22\x00\x55\x00\x02\x02\x46" +/* 1264 */ "\x00\x22\x00\xaa\x00\x55\x55\xcc\x00\x22\x00\x00\x03\x44\x33\x66" +/* 1280 */ "\x55\xcc\x33\x66\x55\xcc\x03\x46\x05\xbb\x33\x66\x55\xcc\x03\x46" +/* 1296 */ "\x05\xbb\x33\x66\x55\xcc\x03\x46\x05\xbb\x33\x66\x55\xcc\x03\x46" +/* 1312 */ "\x05\xbb\x33\x66\x55\xcc\x03\x46\x05\xbb\x33\x66\x55\xcc\x00\x00" +/* 1328 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00" +/* 1344 */ "\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00" +/* 1360 */ "\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00" +/* 1376 */ "\x03\x00\x00\x02\x55\x02\x55\x02\x05\x02\x55\x02\x46\x02\xaa\x55" +/* 1392 */ "\xcc\x02\x55\x02\x46\x02\xaa\x55\xcc\x02\x55\x02\x06\x02\x5a\x05" +/* 1408 */ "\xbb\x02\x55\x02\x46\x02\xaa\x55\xcc\x02\x55\x02\x06\x02\x5a\x05" +/* 1424 */ "\xbb\x02\x55\x02\x46\x02\xaa\x00\x02\x55\x02\x55\x02\x05\x02\x55" +/* 1440 */ "\x02\x05\x02\x55\x02\x05\x02\x55\x02\x05\x02\x55\x02\x46\x02\x55" +/* 1456 */ "\x02\x5a\x02\xaa\x55\xcc\x02\x55\x02\x05\x02\x55\x02\x46\x02\x55" +/* 1472 */ "\x02\x5a\x02\xaa\x55\xcc\x02\x55\x02\x05\x02\x55\x02\x05\x46\xcc" +/* 1488 */ "\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb" +/* 1504 */ "\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb" +/* 1520 */ "\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb" +/* 1536 */ "\x46\xcc\x06\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00" +/* 1552 */ "\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00" +/* 1568 */ "\x55\x55\xcc\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00" +/* 1584 */ "\x55\x55\xcc\x00\x00\x00\x33\x00\x02\x02\x46\x00\x00\x00\x00\x00" +/* 1600 */ "\x03\x00\x44\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x22\x66\x00" +/* 1616 */ "\x55\x55\xcc\x00\x03\x02\x46\x00\x05\x05\xbb\x00\x33\x22\x66\x00" +/* 1632 */ "\x55\x55\xcc\x00\x03\x02\x46\x00\x05\x05\xbb\x00\x33\x22\x66\x00" +/* 1648 */ "\x55\x55\xcc\x00\x03\x00\x00\x00\x00\x02\x00\x55\x00\x02\x00\x55" +/* 1664 */ "\x00\x02\x00\x05\x00\x02\x00\x55\x00\x02\x02\x46\x00\x02\x00\xaa" +/* 1680 */ "\x00\x55\x55\xcc\x00\x02\x00\x55\x00\x02\x02\x46\x00\x02\x00\xaa" +/* 1696 */ "\x00\x55\x55\xcc\x00\x02\x00\x55\x00\x02\x02\x06\x00\x02\x00\x05" +/* 1712 */ "\x05\x05\x05\x46\x5a\xcc\x05\x46\x5a\xcc\x05\x06\x0a\xbb\x05\x46" +/* 1728 */ "\x5a\xcc\x05\x06\x0a\xbb\x05\x46\x5a\xcc\x05\x06\x0a\xbb\x05\x46" +/* 1744 */ "\x5a\xcc\x05\x06\x0a\xbb\x05\x46\x5a\xcc\x05\x06\x0a\xbb\x05\x46" +/* 1760 */ "\x5a\xcc\x05\x06\x0a\xbb\x05\x46\x5a\xcc\x00\x00\x00\x00\x00\x00" +/* 1776 */ "\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22" +/* 1792 */ "\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00\x22\x22" +/* 1808 */ "\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x03\x00\x02\x02" +/* 1824 */ "\x46\x00\x00\x00\x05\x00\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +/* 1840 */ "\x46\x05\x5a\x5a\xcc\x05\x05\x05\x46\x05\x5a\x5a\xcc\x05\x05\x05" +/* 1856 */ "\x06\x05\x0a\x0a\xbb\x05\x05\x05\x46\x05\x5a\x5a\xcc\x05\x05\x05" +/* 1872 */ "\x06\x05\x0a\x0a\xbb\x05\x05\x05\x46\x05\x5a\x5a\xcc\x05\x05\x05" +/* 1888 */ "\x06\x05\x0a\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +/* 1904 */ "\x05\x05\x05\x05\x05\x05\x05\x05\x05\x46\x05\x05\x05\x5a\x05\x5a" +/* 1920 */ "\x5a\xcc\x05\x05\x05\x05\x05\x05\x05\x46\x05\x05\x05\x5a\x05\x5a" +/* 1936 */ "\x5a\xcc\x05\x05\x05\x05\x05\x05\x05\x06\x05\x05\x05\x0a\x05\x0a" +/* 1952 */ "\x0a"; + +unsigned char *adv_gomoku /* [978] */ = +/* 0 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 16 */ "\x00\x00\x00\x00\xa0\x00\xa0\x00\x04\x00\x04\x00\x00\xd0\x00\xd0" +/* 32 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 48 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 64 */ "\x00\x70\x00\x00\x00\x00\xa0\x00\xa1\x00\x00\x00\xa0\x00\x04\x00" +/* 80 */ "\x04\x00\x00\x00\x04\x00\xd0\xd0\x00\xd0\x00\xd0\x00\xd0\x00\x00" +/* 96 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x70\x08\x08\x00\x08\x00\x08\x00" +/* 112 */ "\x08\x00\x08\x00\x40\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x00" +/* 128 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70" +/* 144 */ "\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\xa1\x00\x00\x00\xa1\x00" +/* 160 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 176 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 192 */ "\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\x00" +/* 208 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 224 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 240 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00" +/* 256 */ "\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\xa0\x00\xa1\x00\x00\x00" +/* 272 */ "\xa1\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x04\x00\x04\x00\x00\x00" +/* 288 */ "\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\xd0\xd0\x00\xd0\x00\xd0" +/* 304 */ "\x00\xd0\x00\xd0\x00\xd0\x00\xd0\x00\xd0\x00\x00\x00\x00\x00\x00" +/* 320 */ "\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x70\x08\x08\x00" +/* 336 */ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" +/* 352 */ "\x40\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40" +/* 368 */ "\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 384 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x70" +/* 400 */ "\x21\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\xa1\x00" +/* 416 */ "\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\xa1\x00\x00\x00\x00\x00" +/* 432 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 448 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 464 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 480 */ "\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00" +/* 496 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 512 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 528 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 544 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 560 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x70\x21\x00" +/* 576 */ "\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\xa0\x00" +/* 592 */ "\xa1\x00\x00\x00\xa1\x00\x00\x00\xa0\x00\x00\x00\xa1\x00\x00\x00" +/* 608 */ "\xa0\x00\x00\x00\xa0\x00\x04\x00\x04\x00\x00\x00\x04\x00\x00\x00" +/* 624 */ "\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\xd0" +/* 640 */ "\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\xd0\x00\x00" +/* 656 */ "\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 672 */ "\x70\x21\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00" +/* 688 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 704 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 720 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 736 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 752 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 768 */ "\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x70\x21\x00\x00\x00" +/* 784 */ "\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x00" +/* 800 */ "\x00\x00\xa1\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\xa1\x00" +/* 816 */ "\x00\x00\x00\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 832 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 848 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 864 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 880 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x21" +/* 896 */ "\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\x00" +/* 912 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 928 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 944 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 960 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +/* 976 */ "\x00"; diff --git a/include/modes.h b/include/modes.h new file mode 100644 index 00000000..fe3a6b79 --- /dev/null +++ b/include/modes.h @@ -0,0 +1,152 @@ +/* $Id: modes.h,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifndef INCLUDE_MODES_H +#define INCLUDE_MODES_H + +#define DONOTHING 0 /* Read menu command return states */ +#define FULLUPDATE 1 /* Entire screen was destroyed in this oper */ +#define PARTUPDATE 2 /* Only the top three lines were destroyed */ +#define DOQUIT 3 /* Exit read menu was executed */ +#define NEWDIRECT 4 /* Directory has changed, re-read files */ +#define READ_NEXT 5 /* Direct read next file */ +#define READ_PREV 6 /* Direct read prev file */ +#define DIRCHANGED 8 /* Index file was changed */ +#define READ_REDRAW 9 +#define PART_REDRAW 10 +#define POS_NEXT 101 /* cursor_pos(locmem, locmem->crs_ln + 1, 1);*/ + +/* user ¾Þ§@ª¬ºA»P¼Ò¦¡ */ +#define IDLE 0 +#define MMENU 1 /* menu mode */ +#define ADMIN 2 +#define MAIL 3 +#define TMENU 4 +#define UMENU 5 +#define XMENU 6 +#define CLASS 7 +#define PMENU 8 +#define NMENU 9 +#define PSALE 10 +#define POSTING 11 /* boards & class */ +#define READBRD 12 +#define READING 13 +#define READNEW 14 +#define SELECT 15 +#define RMAIL 16 /* mail menu */ +#define SMAIL 17 +#define CHATING 18 /* talk menu */ +#define XMODE 19 +#define FRIEND 20 +#define LAUSERS 21 +#define LUSERS 22 +#define MONITOR 23 +#define PAGE 24 +#define TQUERY 25 +#define TALK 26 +#define EDITPLAN 27 /* user menu */ +#define EDITSIG 28 +#define VOTING 29 +#define XINFO 30 +#define MSYSOP 31 +#define WWW 32 +#define BIG2 33 +#define REPLY 34 +#define HIT 35 +#define DBACK 36 +#define NOTE 37 +#define EDITING 38 +#define MAILALL 39 +#define MJ 40 +#define P_FRIEND 41 +#define LOGIN 42 /* main menu */ +#define DICT 43 +#define BRIDGE 44 +#define ARCHIE 45 +#define GOPHER 46 +#define NEWS 47 +#define LOVE 48 +#define EDITEXP 49 +#define IPREG 50 +#define NADM 51 +#define DRINK 52 +#define CAL 53 +#define PROVERB 54 +#define ANNOUNCE 55 /* announce */ +#define EDNOTE 56 +#define CDICT 57 +#define LOBJ 58 +#define OSONG 59 +#define CHICKEN 60 +#define TICKET 61 +#define GUESSNUM 62 +#define AMUSE 63 +#define OTHELLO 64 +#define DICE 65 +#define VICE 66 +#define BBCALL 67 +#define VIOLATELAW 68 +#define M_FIVE 69 +#define JACK_CARD 70 +#define TENHALF 71 +#define CARD_99 72 +#define RAIL_WAY 73 +#define SREG 74 +#define CHC 75 /* Chinese chess */ +#define DARK 76 /* ¤¤°ê·tµX */ +#define TMPJACK 77 +#define JCEE 78 +#define REEDIT 79 + +/* menu.c ¤¤ªº¼Ò¦¡ */ +#define QUIT 0x666 /* Return value to abort recursive functions */ +#define XEASY 0x333 /* Return value to un-redraw screen */ + +/* for currmode */ +#define MODE_STARTED 1 /* ¬O§_¤w¸g¶i¤J¨t²Î */ +#define MODE_POST 2 /* ¬O§_¥i¥H¦b currboard µoªí¤å³¹ */ +#define MODE_BOARD 4 /* ¬O§_¥i¥H¦b currboard §R°£¡Bmark¤å³¹ */ +#define MODE_MENU 8 /* ¬O§_¥i¥H¦b MENU ¶}ªO */ +#define MODE_DIGEST 0x10 /* ¬O§_¬° digest mode */ +#define MODE_ETC 0x20 /* ¬O§_¬° etc mode */ +#define MODE_SELECT 0x40 /* ·j´M¨Ï¥ÎªÌ¼ÐÃD */ +#define MODE_DIRTY 0x80 /* ¬O§_§ó°Ê¹L userflag */ + +/* for curredit */ +#define EDIT_MAIL 1 /* ¥Ø«e¬O mail/board ? */ +#define EDIT_LIST 2 /* ¬O§_¬° mail list ? */ +#define EDIT_BOTH 4 /* both reply to author/board ? */ +#define EDIT_ITEM 8 /* ITEM ? */ + +/* read.c ¤¤ªº¼Ò¦¡ */ +#define TAG_NIN 0 /* ¤£ÄÝ©ó TagList */ +#define TAG_TOGGLE 1 /* ¤Á´« Taglist */ +#define TAG_INSERT 2 /* ¥[¤J TagList */ + + +#define RS_FORWARD 0x01 /* backward */ +#define RS_TITLE 0x02 /* author/title */ +#define RS_RELATED 0x04 +#define RS_FIRST 0x08 /* find first article */ +#define RS_CURRENT 0x10 /* match current read article */ +#define RS_THREAD 0x20 /* search the first article */ +#define RS_AUTHOR 0x40 /* search author's article */ +#define RS_NEWPOST 0x80 /* search new posts */ + +#define CURSOR_FIRST (RS_RELATED | RS_TITLE | RS_FIRST) +#define CURSOR_NEXT (RS_RELATED | RS_TITLE | RS_FORWARD) +#define CURSOR_PREV (RS_RELATED | RS_TITLE) +#define RELATE_FIRST (RS_RELATED | RS_TITLE | RS_FIRST | RS_CURRENT) +#define RELATE_NEXT (RS_RELATED | RS_TITLE | RS_FORWARD | RS_CURRENT) +#define RELATE_PREV (RS_RELATED | RS_TITLE | RS_CURRENT) +#define THREAD_NEXT (RS_THREAD | RS_FORWARD) +#define THREAD_PREV (RS_THREAD) + +enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; + +#define SIG_PK 0 +#define SIG_TALK 1 +#define SIG_BROADCAST 2 +#define SIG_GOMO 3 +#define SIG_CHC 4 +#define SIG_DARK 5 + +#endif diff --git a/include/perm.h b/include/perm.h new file mode 100644 index 00000000..eece624e --- /dev/null +++ b/include/perm.h @@ -0,0 +1,56 @@ +/* $Id: perm.h,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifndef INCLUDE_PERM_H +#define INCLUDE_PERM_H + +#define PERM_BASIC 000000000001 +#define PERM_CHAT 000000000002 +#define PERM_PAGE 000000000004 +#define PERM_POST 000000000010 +#define PERM_LOGINOK 000000000020 +#define PERM_MAILLIMIT 000000000040 +#define PERM_CLOAK 000000000100 +#define PERM_SEECLOAK 000000000200 +#define PERM_XEMPT 000000000400 +#define PERM_DENYPOST 000000001000 +#define PERM_BM 000000002000 +#define PERM_ACCOUNTS 000000004000 +#define PERM_CHATROOM 000000010000 +#define PERM_BOARD 000000020000 +#define PERM_SYSOP 000000040000 +#define PERM_BBSADM 000000100000 +#define PERM_NOTOP 000000200000 +#define PERM_VIOLATELAW 000000400000 +#define PERM_NOOUTMAIL 000001000000 +#define PERM_20 000002000000 +#define PERM_VIEWSYSOP 000004000000 +#define PERM_LOGUSER 000010000000 +#define PERM_ANNOUNCE 000020000000 +#define PERM_RELATION 000040000000 +#define PERM_SMG 000100000000 +#define PERM_PRG 000200000000 +#define PERM_ACTION 000400000000 +#define PERM_PAINT 001000000000 +#define PERM_LAW 002000000000 +#define PERM_SYSSUBOP 004000000000 +#define PERM_MSYSOP 010000000000 +#define PERM_PTT 020000000000 + +#define NUMPERMS 32 + +#define PERM_DEFAULT (PERM_BASIC | PERM_CHAT | PERM_PAGE ) +#define PERM_MANAGER (PERM_RELATION | PERM_SMG | PERM_ACTION | PERM_PAINT | PERM_LAW) +#define PERM_ADMIN (PERM_ACCOUNTS | PERM_SYSOP | PERM_SYSSUBOP | PERM_MANAGER | PERM_BM) +#define PERM_ALLBOARD (PERM_SYSOP | PERM_BOARD) +#define PERM_LOGINCLOAK (PERM_SYSOP | PERM_ACCOUNTS) +#define PERM_SEEULEVELS (PERM_SYSOP) +#define PERM_SEEBLEVELS (PERM_SYSOP | PERM_BM) +#define PERM_NOTIMEOUT (PERM_SYSOP) +#define PERM_READMAIL (PERM_BASIC) +#define PERM_FORWARD (PERM_BASIC) /* to do the forwarding */ +#define PERM_INTERNET (PERM_LOGINOK) /* ¨¥÷»{ÃÒ¹LÃöªº¤~¯à±H«H¨ì Internet */ + +#define HAS_PERM(x) ((x) ? cuser.userlevel & (x) : 1) +#define HAVE_PERM(x) (cuser.userlevel&(x)) +#define PERM_HIDE(u) ((u)->userlevel & PERM_SYSOP && \ + (u)->userlevel & PERM_DENYPOST) +#endif diff --git a/include/proto.h b/include/proto.h new file mode 100644 index 00000000..8122f5d5 --- /dev/null +++ b/include/proto.h @@ -0,0 +1,522 @@ +/* $Id: proto.h,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifndef INCLUDE_PROTO_H +#define INCLUDE_PROTO_H + +/* admin */ +int m_mod_board(char *bname); +int m_newbrd(int recover); +int scan_register_form(char *regfile, int automode, int neednum); +int m_user(); +int search_user_bypwd(); +int search_user_bybakpwd(); +int m_board(); +int m_register(); +int cat_register(); +unsigned int setperms(unsigned int pbits, char *pstring[]); +void setup_man(boardheader_t * board); + +/* announce */ +int a_menu(char *maintitle, char *path, int lastlevel); +void a_copyitem(char* fpath, char* title, char* owner, int mode); +int Announce(); +void gem(char* maintitle, item_t* path, int update); + +/* args */ +void initsetproctitle(int argc, char **argv, char **envp); +void setproctitle(const char* format, ...); + +/* bbcall */ +int main_bbcall(); + +/* bbs */ +void make_blist(); +int invalid_brdname(char *brd); +int del_range(int ent, fileheader_t *fhdr, char *direct); +int cmpfowner(fileheader_t *fhdr); +int b_note_edit_bname(int bid); +int Read(); +void anticrosspost(); +int Select(); +void do_reply_title(int row, char *title); +int cmpfmode(fileheader_t *fhdr); +int cmpfilename(fileheader_t *fhdr); +int getindex(char *fpath, char *fname, int size); +void outgo_post(fileheader_t *fh, char *board); +int edit_title(int ent, fileheader_t *fhdr, char *direct); +int whereami(int ent, fileheader_t *fhdr, char *direct); +void set_board(); +int do_post(); +void ReadSelect(); +int save_violatelaw(); +int board_select(); +int board_etc(); +int board_digest(); + +/* board */ +int brc_unread(char *fname, int bnum, int *blist); +int brc_initial(char *boardname); +void brc_update(); +int Ben_Perm(boardheader_t *bptr); +int New(); +int Boards(); +int root_board(); +void save_brdbuf(void); +void init_brdbuf(void); + +/* cache */ +int moneyof(int uid); +int getuser(char *userid); +void setuserid(int num, char *userid); +int searchuser(char *userid); +int getbnum(char *bname); +void reset_board(int bid); +void touch_boards(); +void addbrd_touchcache(); +void setapath(char *buf, char *boardname); +void setutmpmode(int mode); +void setadir(char *buf, char *path); +boardheader_t *getbcache(int bid); +int apply_boards(int (*func)(boardheader_t *)); +int haspostperm(char *bname); +void inbtotal(int bid, int add); +void brc_addlist(char *fname); +void setbtotal(int bid); +unsigned int safe_sleep(unsigned int seconds); +int apply_ulist(int (*fptr)(userinfo_t *)); +userinfo_t *search_ulistn(int uid, int unum); +void purge_utmp(userinfo_t *uentp); +userinfo_t *search_ulist(int uid); +int count_multi(); +void resolve_utmp(); +void attach_uhash(); +void getnewutmpent(userinfo_t *up); +void resolve_garbage(); +void resolve_boards(); +void resolve_fcache(); +void sem_init(int semkey,int *semid); +void sem_lock(int op,int semid); +int count_ulist(); +char *u_namearray(char buf[][IDLEN + 1], int *pnum, char *tag); +char *getuserid(int num); +int searchnewuser(int mode); +int count_logins(int uid, int show); +void remove_from_uhash(int n); +void add_to_uhash(int n, char *id); +int setumoney(int uid, int money); +int getbtotal(int bid); +userinfo_t *search_ulist_pid(int pid); +int moneyof(int uid); +void hbflreload(int bid); +int hbflcheck(int bid, int uid); + +/* cal */ +int vice(int money, char* item); +int inumoney(char *tuser, int money); +int cal(); +#define reload_money() cuser.money=moneyof(usernum) +int demoney(int money); +int deumoney(int uid, int money); +int lockutmpmode(int unmode, int state); +int unlockutmpmode(); +int p_touch_boards(); +int x_file(); +int give_money(); +int p_sysinfo(); +int p_give(); +int p_cloak(); +int p_from(); +int ordersong(); +int p_exmail(); +void mail_redenvelop(char* from, char* to, int money, char mode); + +/* card */ +int g_card_jack(); +int g_ten_helf(); +int card_99(); + +/* chat */ +int t_chat(); + +/* chc_draw */ +void chc_drawline(board_t board, int line); +void chc_movecur(int r, int c); +void chc_redraw(board_t board); + +/* chc_net */ +void chc_sendmove(int s); +int chc_recvmove(int s); + +/* chc_play */ +void chc(int s); + +/* chc_rule */ +void chc_movechess(board_t board); +int chc_canmove(board_t board, rc_t from, rc_t to); +int chc_iskfk(board_t board); +int chc_ischeck(board_t board, int turn); +void chc_init_board(board_t board); + +/* chicken */ +int show_file(char *filename, int y, int lines, int mode); +void ch_buyitem(int money, char *picture, int *item); +int chicken_main(); +int chickenpk(int fd); +void time_diff(chicken_t *thechicken); +int isdeadth(chicken_t *thechicken); +void show_chicken_data(chicken_t *thechicken, chicken_t *pkchicken); +int reload_chicken(); + +/* dark */ +int main_dark(int fd,userinfo_t *uin); + +/* dice */ +int IsSNum(char *a); +int dice_main(); +int IsNum(char *a, int n); + +/* edit */ +int vedit(char *fpath, int saveheader, int *islocal); +void write_header(FILE *fp); +void addsignature(FILE *fp, int ifuseanony); +void auto_backup(); +void restore_backup(); +char *ask_tmpbuf(int y); +char *strcasestr(const char* big, const char* little); + +/* friend */ +void friend_edit(int type); +void friend_load(); +int t_override(); +int t_reject(); +void friend_add(char *uident, int type); +void friend_delete(char *uident, int type); + +/* gamble */ +int ticket_main(); +int post_msg(char* bname, char* title, char *msg, char* author); +int openticket(int bid); +int ticket(int bid); + +/* gomo */ +int gomoku(int fd); + +/* gomo1 */ +int getstyle(int x, int y, int color, int limit); +int chkwin(int style, int limit); + +/* guess */ +int guess_main(); + +/* indict */ +int x_dict(); +int use_dict(); + +/* io */ +int getdata(int line, int col, char *prompt, char *buf, int len, int echo); +int igetch(); +int getdata_str(int line, int col, char *prompt, char *buf, int len, int echo, char *defaultstr); +int getdata_buf(int line, int col, char *prompt, char *buf, int len, int echo); +int i_get_key(); +void add_io(int fd, int timeout); +int igetkey(); +void oflush(); +int oldgetdata(int line, int col, char *prompt, char *buf, int len, int echo); +void output(char *s, int len); +void init_alarm(); +int num_in_buf(); +int ochar(int c); + +/* kaede */ +int Rename(char* src, char* dst); +int Link(char* src, char* dst); +char *Ptt_prints(char *str, int mode); +char *my_ctime(const time_t *t); + +/* lovepaper */ +int x_love(); + +/* mail */ +int load_mailalert(char *userid); +int mail_muser(userec_t muser, char *title, char *filename); +int mail_id(char* id, char *title, char *filename, char *owner); +int m_read(); +int doforward(char *direct, fileheader_t *fh, int mode); +int mail_reply(int ent, fileheader_t *fhdr, char *direct); +int bsmtp(char *fpath, char *title, char *rcpt, int method); +void hold_mail(char *fpath, char *receiver); +int chkmail(int rechk); +void m_init(); +int chkmailbox(); +int mail_man(); +int m_new(); +int m_send(); +int mail_list(); +int setforward(); +int m_internet(); +int mail_mbox(); +int built_mail_index(); +int mail_all(); +int invalidaddr(char *addr); +int do_send(char *userid, char *title); +void my_send(char *uident); + +/* mbbsd */ +void log_usies(char *mode, char *mesg); +void log_user(char *msg); +void abort_bbs(int sig); +void del_distinct(char *fname, char *line); +void add_distinct(char *fname, char *line); +void show_last_call_in(int save); +int dosearchuser(char *userid); +void u_exit(char *mode); + +/* menu */ +void showtitle(char *title, char *mid); +int egetch(); +void movie(int i); +void domenu(int cmdmode, char *cmdtitle, int cmd, commands_t cmdtable[]); + +/* more */ +int more(char *fpath, int promptend); + +/* name */ +void usercomplete(char *prompt, char *data); +void namecomplete(char *prompt, char *data); +void AddNameList(char *name); +void CreateNameList(); +int chkstr(char *otag, char *tag, char *name); +int InNameList(char *name); +void ShowNameList(int row, int column, char *prompt); +int RemoveNameList(char *name); +void ToggleNameList(int *reciper, char *listfile, char *msg); + +/* osdep */ +int cpuload(char *str); +double swapused(long *total, long *used); + +/* othello */ +int othello_main(); + +/* page */ +int main_railway(); + +/* read */ +void z_download(char *fpath); +void i_read(int cmdmode, char *direct, void (*dotitle)(), void (*doentry)(), onekey_t *rcmdlist, int bidcache); +void fixkeep(char *s, int first); +keeploc_t *getkeep(char *s, int def_topline, int def_cursline); +int Tagger(time_t chrono, int recno, int mode); + +/* record */ +int substitute_record(char *fpath, void *rptr, int size, int id); +int get_record(char *fpath, void *rptr, int size, int id); +void prints(char *fmt, ...); +int append_record(char *fpath, fileheader_t *record, int size); +int stampfile(char *fpath, fileheader_t *fh); +void stampdir(char *fpath, fileheader_t *fh); +int get_num_records(char *fpath, int size); +int get_records(char *fpath, void *rptr, int size, int id, int number); +void stamplink(char *fpath, fileheader_t *fh); +int delete_record(char fpath[], int size, int id); +int delete_files(char* dirname, int (*filecheck)(), int record); +int delete_file(char *dirname, int size, int ent, int (*filecheck)()); +int delete_range(char *fpath, int id1, int id2); +int apply_record(char *fpath, int (*fptr)(), int size); +int search_rec(char* dirname, int (*filecheck)()); +int do_append(char *fpath, fileheader_t *record, int size); +int get_sum_records(char* fpath, int size); + +/* register */ +int getnewuserid(); +int bad_user_id(char *userid); +void new_register(); +int checkpasswd(char *passwd, char *test); +void check_register(); +char *genpasswd(char *pw); + +/* screen */ +void move(int y, int x); +void outs(char *str); +void clrtoeol(); +void clear(); +void refresh(); +void clrtobot(); +void mprints(int y, int x, char *str); +void outmsg(char *msg); +void region_scroll_up(int top, int bottom); +void outc(unsigned char ch); +void redoscr(); +void clrtoline(int line); +void standout(); +void standend(); +int edit_outs(char *text); +void outch(unsigned char c); +void rscroll(); +void scroll(); +void getyx(int *y, int *x); +void initscr(); +void Jaky_outs(char *str, int line); + +/* stuff */ +void setcalfile(char *buf, char *userid); +void stand_title(char *title); +void pressanykey(); +int vmsg (const char *fmt,...); +void trim(char *buf); +void bell(); +void setbpath(char *buf, char *boardname); +int dashf(char *fname); +void sethomepath(char *buf, char *userid); +void sethomedir(char *buf, char *userid); +char *Cdate(time_t *clock); +void sethomefile(char *buf, char *userid, char *fname); +int log_file(char *filename,char *buf); +void str_lower(char *t, char *s); +int strstr_lower(char *str, char *tag); +int cursor_key(int row, int column); +int search_num(int ch, int max); +void setuserfile(char *buf, char *fname); +int is_BM(char *list); +long dasht(char *fname); +int dashd(char *fname); +int invalid_pname(char *str); +void setbdir(char *buf, char *boardname); +void setbfile(char *buf, char *boardname, char *fname); +int dashl(char *fname); +char *subject(char *title); +int not_alnum(char ch); +void setdirpath(char *buf, char *direct, char *fname); +int str_checksum(char *str); +void show_help(char *helptext[]); +int belong(char *filelist, char *key); +char *Cdatedate(time_t *clock); +int isprint2(char ch); +void sethomeman(char *buf, char *userid); +off_t dashs(char *fname); +void cursor_clear(int row, int column); +void cursor_show(int row, int column); +void printdash(char *mesg); +char *Cdatelite(time_t *clock); +int not_alpha(char ch); +int valid_ident(char *ident); +int userid_is_BM(char *userid, char *list); +int is_uBM(char *list, char *id); + +/* syspost */ +void post_newboard(char *bgroup, char *bname, char *bms); +void post_violatelaw(char *crime, char *police, char *reason, char *result); +void post_change_perm(int oldperm, int newperm, char *sysopid, char *userid); + +/* talk */ +int cmpwatermtime(const void *a, const void *b); +void water_scr(water_t **currwater, int which, char type); +void my_write2(void); +int t_idle(); +char *modestring(userinfo_t * uentp, int simple); +int isvisible(userinfo_t * me, userinfo_t * uentp); +int t_users(); +int cmpuids(int uid, userinfo_t * urec); +int my_write(pid_t pid, char *hint, char *id, int flag); +void t_display_new(); +void talkreply(); +int t_monitor(); +int t_pager(); +int t_query(); +int t_qchicken(); +int t_talk(); +int t_display(); +int my_query(char *uident); +int logout_friend_online(); +int login_friend_online(); +int isvisible_uid(int tuid); +int friend_stat(userinfo_t *me, userinfo_t * ui); + +/* tmpjack */ +int reg_barbq(); +int p_ticket_main(); +int j_ticket_main(); + +/* term */ +void init_tty(); +int term_init(); +void save_cursor(); +void restore_cursor(); +void do_move(int destcol, int destline); +void scroll_forward(); +void change_scroll_range(int top, int bottom); + +/* topsong */ +void sortsong(); +int topsong(); + +/* user */ +int u_editcalendar(); +void user_display(userec_t *u, int real); +void uinfo_query(userec_t *u, int real, int unum); +int showsignature(char *fname); +void mail_violatelaw(char* crime, char* police, char* reason, char* result); +void showplans(char *uid); +int u_info(); +int u_loginview(); +int u_ansi(); +int u_editplan(); +int u_editsig(); +int u_switchproverb(); +int u_editproverb(); +int u_cloak(); +int u_register(); +int u_list(); + +/* vote */ +int strip_ansi(char *buf, char *str, int mode); +void b_suckinfile(FILE *fp, char *fname); +int b_results(); +int b_vote(); +int b_vote_maintain(); +int b_closepolls(); + +/* vice */ +int vice_main(); + +/* voteboard */ +int do_voteboard(); +void do_voteboardreply(fileheader_t *fhdr); + +/* xyz */ +int m_sysop(); +int x_boardman(); +int x_note(); +int x_login(); +int x_week(); +int x_issue(); +int x_today(); +int x_yesterday(); +int x_user100(); +int x_birth(); +int x_90(); +int x_89(); +int x_88(); +int x_87(); +int x_86(); +int x_history(); +int x_weather(); +int x_stock(); +int note(); +int Goodbye(); + +/* toolkit */ +unsigned StringHash(unsigned char *s); + +/* passwd */ +int passwd_mmap(); +int passwd_update(int num, userec_t *buf); +int passwd_query(int num, userec_t *buf); +int passwd_apply(int (*fptr)(userec_t *)); +void passwd_lock(); +void passwd_unlock(); +int passwd_update_money(int num); + +/* calendar */ +int calendar(); + +#endif diff --git a/include/pttbbs.conf b/include/pttbbs.conf new file mode 100644 index 00000000..9bd4722d --- /dev/null +++ b/include/pttbbs.conf @@ -0,0 +1,17 @@ +/* ©w¸q BBS ¯¸¦W¦ì§} */ +#define BBSNAME "§å½ð½ð¹ê·~§{" /* ¤¤¤å¯¸¦W */ +#define MYHOSTNAME "ptt.csie.ntu.edu.tw" /* ºô¸ô¦ì§} */ +#define MYIP "140.112.30.142" /* IP¦ì§} */ +#define BBSUSER "bbs" +#define BBSUID 9999 +#define BBSGID 99 + +#define MAX_USERS 150000 +#define MAX_ACTIVE 4096 +#define MAX_CPULOAD 50 +#define MAX_FROM 512 +#define RELAY_SERVER_IP "140.112.30.143" +#define MAX_POST_MONEY 1000 +#define MAX_CHICKEN_MONEY 10000 +#define HAVE_JCEE 0 +#define TITLE_COLOR "\33[0;1;37;44m" diff --git a/include/pttstruct.h b/include/pttstruct.h new file mode 100644 index 00000000..76a196a9 --- /dev/null +++ b/include/pttstruct.h @@ -0,0 +1,390 @@ +/* $Id: pttstruct.h,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifndef INCLUDE_STRUCT_H +#define INCLUDE_STRUCT_H + +/* ¤pÂûªº¸ê®Æ */ +typedef struct chicken_t { + char name[20]; + char type; /* ª«ºØ */ + unsigned char tech[16]; /* §Þ¯à */ + time_t birthday; /* ¥Í¤é */ + time_t lastvisit; /* ¤W¦¸·ÓÅU®É¶¡ */ + int oo; /* ¸É«~ */ + int food; /* ¹ª« */ + int medicine; /* ÃÄ«~ */ + int weight; /* Åé« */ + int clean; /* °®²b */ + int run; /* ±Ó±¶«× */ + int attack; /* §ðÀ»¤O */ + int book; /* ª¾ÃÑ */ + int happy; /* §Ö¼Ö */ + int satis; /* º¡·N«× */ + int temperament; /* ®ð½è */ + int tiredstrong; /* ¯h³Ò«× */ + int sick; /* ¯f®ð«ü¼Æ */ + int hp; /* ¦å¶q */ + int hp_max; /* º¡¦å¶q */ + int mm; /* ªk¤O */ + int mm_max; /* º¡ªk¤O */ + time_t cbirth; /* ¹ê»Úpºâ¥Îªº¥Í¤é */ + int pad[2]; /* ¯dµÛ¥H«á¥Î */ +} chicken_t; + +#define IDLEN 12 /* Length of bid/uid */ +#define PASSLEN 14 /* Length of encrypted passwd field */ +#define REGLEN 38 /* Length of registration data */ + +typedef struct userec_t { + char userid[IDLEN + 1]; + char realname[20]; + char username[24]; + char passwd[PASSLEN]; + unsigned char uflag; + unsigned int userlevel; + unsigned short numlogins; + unsigned short numposts; + time_t firstlogin; + time_t lastlogin; + char lasthost[16]; + int money; + char remoteuser[3]; /* «O¯d ¥Ø«e¨S¥Î¨ìªº */ + char proverb; + char email[50]; + char address[50]; + char justify[REGLEN + 1]; + unsigned char month; + unsigned char day; + unsigned char year; + unsigned char sex; + unsigned char state; + unsigned char pager; + unsigned char invisible; + unsigned int exmailbox; + chicken_t mychicken; + time_t lastsong; + unsigned int loginview; + unsigned char channel; /* °ÊºA¬ÝªO */ + unsigned short vl_count; /* ViolateLaw counter */ + unsigned short five_win; + unsigned short five_lose; + unsigned short five_tie; + unsigned short chc_win; + unsigned short chc_lose; + unsigned short chc_tie; + int mobile; + int mind; + char ident[11]; + unsigned int uflag2; + char pad[72]; +} userec_t; +/* these are flags in userec_t.uflag */ +#define SIG_FLAG 0x3 /* signature number, 2 bits */ +#define PAGER_FLAG 0x4 /* true if pager was OFF last session */ +#define CLOAK_FLAG 0x8 /* true if cloak was ON last session */ +#define FRIEND_FLAG 0x10 /* true if show friends only */ +#define BRDSORT_FLAG 0x20 /* true if the boards sorted alphabetical */ +#define MOVIE_FLAG 0x40 /* true if show movie */ +#define COLOR_FLAG 0x80 /* true if the color mode open */ +#define MIND_FLAG 0x100 /* true if mind search mode open <-Heat*/ +/* these are flags in userec_t.uflag2 */ +#define WATER_MASK 000003 /* water mask */ +#define WATER_ORIG 0 +#define WATER_NEW 1 +#define WATER_OFO 2 +#define WATERMODE(mode) ((cuser.uflag2 & WATER_MASK) == mode) + + +#define BTLEN 48 /* Length of board title */ + +typedef struct boardheader_t { + char brdname[IDLEN + 1]; /* bid */ + char title[BTLEN + 1]; + char BM[IDLEN * 3 + 3]; /* BMs' uid, token '/' */ + unsigned int brdattr; /* boardªºÄÝ©Ê */ + char pad[3]; /* ¨S¥Î¨ìªº */ + time_t bupdate; /* note update time */ + char pad2[3]; /* ¨S¥Î¨ìªº */ + unsigned char bvote; /* Vote flags */ + time_t vtime; /* Vote close time */ + unsigned int level; /* ¥i¥H¬Ý¦¹ªOªºÅv */ + int unused; /* ÁÙ¨S¥Î¨ì */ + int gid; /* ¬ÝªO©ÒÄݪºÃþ§O ID */ + void *next[2]; /* ¦b¦P¤@Ógid¤U¤@ӬݪO °ÊºA²£¥Í*/ + void *firstchild[2]; /* ÄÝ©ó³oӬݪOªº²Ä¤@Ó¤l¬ÝªO */ + void *parent; + char pad3[100]; +} boardheader_t; + +#define BRD_NOZAP 00001 /* ¤£¥izap */ +#define BRD_NOCOUNT 00002 /* ¤£¦C¤J²Îp */ +#define BRD_NOTRAN 00004 /* ¤£Âà«H */ +#define BRD_GROUPBOARD 00010 /* ¸s²ÕªO */ +#define BRD_HIDE 00020 /* ÁôÂêO (¬ÝªO¦n¤Í¤~¥i¬Ý) */ +#define BRD_POSTMASK 00040 /* ¨îµoªí©Î¾\Ū */ +#define BRD_ANONYMOUS 00100 /* °Î¦WªO? */ +#define BRD_DEFAULTANONYMOUS 00200 /* ¹w³]°Î¦WªO */ +#define BRD_BAD 00400 /* ¹Hªk§ï¶i¤¤¬ÝªO */ +#define BRD_VOTEBOARD 01000 /* ³s¸p¾÷¬ÝªO */ +#define BRD_WARNDEL 02000 /* ¤wĵ§in¼o°£ªº¬ÝªO */ + +#define TTLEN 64 /* Length of title */ +#define FNLEN 33 /* Length of filename */ + +#define FHR_REFERENCE (1<<31) + +typedef struct fileheader_t { + char filename[FNLEN]; /* M.9876543210.A */ + char savemode; /* file save mode */ + char owner[IDLEN + 2]; /* uid[.] */ + char date[6]; /* [02/02] or space(5) */ + char title[TTLEN + 1]; + int money; /* rocker: if bit32 on ==> reference */ + unsigned char filemode; /* must be last field @ boards.c */ +} fileheader_t; + +#define FILE_LOCAL 0x1 /* local saved */ +#define FILE_READ 0x1 /* already read : mail only */ +#define FILE_MARKED 0x2 /* opus: 0x8 */ +#define FILE_DIGEST 0x4 /* digest */ +#define FILE_SOLVED 0x10 /* problem solved, sysop only */ +#define FILE_HIDE 0x20 /* hild */ +#define FILE_BM 0x40 /* BM only */ + +#define STRLEN 80 /* Length of most string data */ + + +/* uhash is a userid->uid hash table -- jochang */ + +#define HASH_BITS 16 +typedef struct uhash_t { + char userid[MAX_USERS][IDLEN + 1]; + int next_in_hash[MAX_USERS]; + int money[MAX_USERS]; + int hash_head[1 << HASH_BITS]; + int number; /* # of users total */ + int loaded; /* .PASSWD has been loaded? */ + int hbfl[MAX_BOARD][MAX_FRIEND + 1]; +} uhash_t; + +union xitem_t { + struct { /* bbs_item */ + char fdate[9]; /* [mm/dd/yy] */ + char editor[13]; /* user ID */ + char fname[31]; + } B; + struct { /* gopher_item */ + char path[81]; + char server[48]; + int port; + } G; +}; + +typedef struct { + char title[63]; + union xitem_t X; +} item_t; + +typedef struct { + item_t *item[MAX_ITEMS]; + char mtitle[STRLEN]; + char *path; + int num, page, now, level; +} gmenu_t; + +typedef struct msgque_t { + pid_t pid; + char userid[IDLEN + 1]; + char last_call_in[80]; +} msgque_t; + +typedef struct water_t { + pid_t pid; + char userid[IDLEN + 1]; + msgque_t msg[MAX_REVIEW]; + int top, count; +} water_t; + +#define FAVMAX 74 /* Max boards of Myfavorite */ +#define FAVGMAX 16 /* Max groups of Myfavorite */ +#define FAVGSLEN 8 /* Max Length of Description String */ + +typedef struct userinfo_t { + int uid; /* Used to find user name in passwd file */ + pid_t pid; /* kill() to notify user of talk request */ + int sockaddr; /* ... */ + int destuid; /* talk uses this to identify who called */ + int destuip; /* dest index in utmpshm->uinfo[] */ + unsigned char active; /* When allocated this field is true */ + unsigned char invisible; /* Used by cloaking function in Xyz menu */ + unsigned char sockactive; /* Used to coordinate talk requests */ + unsigned int userlevel; + unsigned char mode; /* UL/DL, Talk Mode, Chat Mode, ... */ + unsigned char pager; /* pager toggle, YEA, or NA */ + unsigned char in_chat; /* for in_chat commands */ + unsigned char sig; /* signal type */ + char userid[IDLEN + 1]; + char chatid[11]; /* chat id, if in chat mode */ + char realname[20]; + char username[24]; + char from[27]; /* machine name the user called in from */ + int from_alias; + char birth; /* ¬O§_¬O¥Í¤é Ptt*/ + char tty[11]; /* tty port */ + int friend[MAX_FRIEND]; + int friend_online[MAX_FRIEND]; /* point¨ì½u¤W¦n¤Í utmpshmªº¦ì¸m */ + /* ¦n¤Í¤ñ¸ûªºcache «e¨âÓbit¬Oª¬ºA */ + int reject[MAX_REJECT]; + int pad[3]; + int friendtotal; /* ¦n¤Í¤ñ¸ûªºcache ¤j¤p */ + unsigned char msgcount; + msgque_t msgs[MAX_MSGS]; + time_t uptime; + time_t lastact; /* ¤W¦¸¨Ï¥ÎªÌ°Êªº®É¶¡ */ + unsigned int brc_id; + unsigned char lockmode; /* ¤£ã multi_login ª±ªºªF¦è */ + char turn; /* for gomo */ + char mateid[IDLEN + 1]; /* for gomo */ + unsigned short int five_win; + unsigned short int five_lose; + unsigned short int five_tie; + int myfavorite[FAVMAX]; + char gfavorite[FAVGMAX][FAVGSLEN+1]; + int ninGroup[FAVGMAX]; + int nGroup; + int ninRoot; + int mailalert; + int sex; + char color; + int mind; +} userinfo_t; + +typedef struct { + fileheader_t *header; + char mtitle[STRLEN]; + char *path; + int num, page, now, level; +} menu_t; + +typedef struct onekey_t { /* Used to pass commands to the readmenu */ + int key; + int (*fptr)(); +} onekey_t; + +#define ANSILINELEN (511) /* Maximum Screen width in chars */ + +/* anti_crosspost */ +typedef struct crosspost_t { + int checksum[4]; /* 0 -> 'X' cross post 1-3 -> ²¬d¤å³¹¦æ */ + int times; /* ²Ä´X¦¸ */ +} crosspost_t; + +#define SORT_BY_ID 0 +#define SORT_BY_CLASS 1 +#define SORT_BY_STAT 1 +#define SORT_BY_IDLE 2 +#define SORT_BY_FROM 3 +#define SORT_BY_FIVE 4 +#define SORT_BY_SEX 5 + +typedef struct bcache_t { + boardheader_t bcache[MAX_BOARD]; + boardheader_t *sorted[2][MAX_BOARD]; /* 0: by name 1: by class */ + fileheader_t dircache[MAX_BOARD][DIRCACHESIZE]; + int cachetotal[MAX_BOARD]; + int total[MAX_BOARD]; + time_t lastposttime[MAX_BOARD]; + time_t uptime; + time_t touchtime; + int number; + int busystate; +} bcache_t; + +typedef struct keeploc_t { + char *key; + int top_ln; + int crs_ln; + struct keeploc_t *next; +} keeploc_t; + +#define USHM_SIZE (MAX_ACTIVE + 4) /* why+4? */ + +struct utmpfile_t { + userinfo_t uinfo[USHM_SIZE]; + userinfo_t *sorted[2][8][USHM_SIZE]; + /* ²Ä¤@ºûdouble buffer ¥Ñcurrsorted«ü¦V¥Ø«e¨Ï¥Îªº + ²Ä¤Gºûsort type */ + int currsorted; + time_t uptime; + int number; + int busystate; +}; + +struct pttcache_t { + char notes[MAX_MOVIE][200*11]; + char today_is[20]; + int n_notes[MAX_MOVIE_SECTION]; /* ¤@¸`¤¤¦³´XÓ ¬ÝªO */ + int next_refresh[MAX_MOVIE_SECTION]; /* ¤U¤@¦¸nrefreshªº ¬ÝªO */ + int max_film; + int max_history; + time_t uptime; + time_t touchtime; + int busystate; +}; + +typedef struct fromcache_t { + char domain[MAX_FROM][50]; + char replace[MAX_FROM][50]; + int top; + int max_user; + time_t max_time; + time_t uptime; + time_t touchtime; + int busystate; +} fromcache_t; + +typedef struct { + unsigned char oldlen; /* previous line length */ + unsigned char len; /* current length of line */ + unsigned char mode; /* status of line, as far as update */ + unsigned char smod; /* start of modified data */ + unsigned char emod; /* end of modified data */ + unsigned char sso; /* start stand out */ + unsigned char eso; /* end stand out */ + unsigned char data[ANSILINELEN + 1]; +} screenline_t; + +typedef struct { + int r, c; +} rc_t; + +#define BRD_ROW 10 +#define BRD_COL 9 + +typedef int board_t[BRD_ROW][BRD_COL]; + +/* name.c ¤¤¹B¥Îªº¸ê®Æµ²ºc */ +typedef struct word_t { + char *word; + struct word_t *next; +} word_t; + +typedef struct commands_t { + int (*cmdfunc)(); + int level; + char *desc; /* next/key/description */ +} commands_t; + +typedef struct MailQueue { + char filepath[FNLEN]; + char subject[STRLEN]; + time_t mailtime; + char sender[IDLEN + 1]; + char username[24]; + char rcpt[50]; + int method; + char * niamod; +} MailQueue; + +enum {MQ_TEXT, MQ_UUENCODE, MQ_JUSTIFY}; + +#endif diff --git a/include/pttstruct.h.save b/include/pttstruct.h.save new file mode 100644 index 00000000..f73f6413 --- /dev/null +++ b/include/pttstruct.h.save @@ -0,0 +1,363 @@ +/* $Id: pttstruct.h.save,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +~#ifndef INCLUDE_STRUCT_H +#define INCLUDE_STRUCT_H + +/* ¤pÂûªº¸ê®Æ */ +typedef struct chicken_t { + char name[20]; + char type; /* ª«ºØ */ + unsigned char tech[16]; /* §Þ¯à */ + time_t birthday; /* ¥Í¤é */ + time_t lastvisit; /* ¤W¦¸·ÓÅU®É¶¡ */ + int oo; /* ¸É«~ */ + int food; /* ¹ª« */ + int medicine; /* ÃÄ«~ */ + int weight; /* Åé« */ + int clean; /* °®²b */ + int run; /* ±Ó±¶«× */ + int attack; /* §ðÀ»¤O */ + int book; /* ª¾ÃÑ */ + int happy; /* §Ö¼Ö */ + int satis; /* º¡·N«× */ + int temperament; /* ®ð½è */ + int tiredstrong; /* ¯h³Ò«× */ + int sick; /* ¯f®ð«ü¼Æ */ + int hp; /* ¦å¶q */ + int hp_max; /* º¡¦å¶q */ + int mm; /* ªk¤O */ + int mm_max; /* º¡ªk¤O */ + time_t cbirth; /* ¹ê»Úpºâ¥Îªº¥Í¤é */ + int pad[2]; /* ¯dµÛ¥H«á¥Î */ +} chicken_t; + +#define IDLEN 12 /* Length of bid/uid */ +#define PASSLEN 14 /* Length of encrypted passwd field */ +#define REGLEN 38 /* Length of registration data */ + +typedef struct userec_t { + char userid[IDLEN + 1]; + char realname[20]; + char username[24]; + char passwd[PASSLEN]; + unsigned char uflag; + unsigned int userlevel; + unsigned short numlogins; + unsigned short numposts; + time_t firstlogin; + time_t lastlogin; + char lasthost[16]; + int money; + char remoteuser[3]; /* «O¯d ¥Ø«e¨S¥Î¨ìªº */ + char proverb; + char email[50]; + char address[50]; + char justify[REGLEN + 1]; + unsigned char month; + unsigned char day; + unsigned char year; + unsigned char sex; + unsigned char state; + unsigned char pager; + unsigned char invisible; + unsigned int exmailbox; + chicken_t mychicken; + time_t lastsong; + unsigned int loginview; + unsigned char channel; /* °ÊºA¬ÝªO */ + unsigned short vl_count; /* ViolateLaw counter */ + unsigned short five_win; + unsigned short five_lose; + unsigned short five_tie; + unsigned short chc_win; + unsigned short chc_lose; + unsigned short chc_tie; + char pad[95]; +} userec_t; +/* these are flags in userec_t.uflag */ +#define SIG_FLAG 0x3 /* signature number, 2 bits */ +#define PAGER_FLAG 0x4 /* true if pager was OFF last session */ +#define CLOAK_FLAG 0x8 /* true if cloak was ON last session */ +#define FRIEND_FLAG 0x10 /* true if show friends only */ +#define BRDSORT_FLAG 0x20 /* true if the boards sorted alphabetical */ +#define MOVIE_FLAG 0x40 /* true if show movie */ +#define COLOR_FLAG 0x80 /* true if the color mode open */ +#define MIND_FLAG 0x100 /* true if mind search mode open <-Heat*/ + +#define BTLEN 48 /* Length of board title */ + +typedef struct boardheader_t { + char brdname[IDLEN + 1]; /* bid */ + char title[BTLEN + 1]; + char BM[IDLEN * 3 + 3]; /* BMs' uid, token '/' */ + unsigned int brdattr; /* boardªºÄÝ©Ê */ + char pad[3]; /* ¨S¥Î¨ìªº */ + time_t bupdate; /* note update time */ + char pad2[3]; /* ¨S¥Î¨ìªº */ + unsigned char bvote; /* Vote flags */ + time_t vtime; /* Vote close time */ + unsigned int level; /* ¥i¥H¬Ý¦¹ªOªºÅv */ + int uid; /* ¬ÝªOªºÃþ§O ID */ + int gid; /* ¬ÝªO©ÒÄݪºÃþ§O ID */ + void *next[2]; /* ¦b¦P¤@Ógid¤U¤@ӬݪO °ÊºA²£¥Í*/ + void *firstchild[2]; /* ÄÝ©ó³oӬݪOªº²Ä¤@Ó¤l¬ÝªO */ + void *parent; + char pad3[100]; +} boardheader_t; + +#define BRD_NOZAP 00001 /* ¤£¥izap */ +#define BRD_NOCOUNT 00002 /* ¤£¦C¤J²Îp */ +#define BRD_NOTRAN 00004 /* ¤£Âà«H */ +#define BRD_GROUPBOARD 00010 /* ¸s²ÕªO */ +#define BRD_HIDE 00020 /* ÁôÂêO (¬ÝªO¦n¤Í¤~¥i¬Ý) */ +#define BRD_POSTMASK 00040 /* ¨îµoªí©Î¾\Ū */ +#define BRD_ANONYMOUS 00100 /* °Î¦WªO? */ +#define BRD_DEFAULTANONYMOUS 00200 /* ¹w³]°Î¦WªO */ +#define BRD_BAD 00400 /* ¹Hªk§ï¶i¤¤¬ÝªO */ +#define BRD_VOTEBOARD 01000 /* ³s¸p¾÷¬ÝªO */ + +#define TTLEN 64 /* Length of title */ +#define FNLEN 33 /* Length of filename */ + +#define FHR_REFERENCE (1<<31) + +typedef struct fileheader_t { + char filename[FNLEN]; /* M.9876543210.A */ + char savemode; /* file save mode */ + char owner[IDLEN + 2]; /* uid[.] */ + char date[6]; /* [02/02] or space(5) */ + char title[TTLEN + 1]; + int money; /* rocker: if bit32 on ==> reference */ + unsigned char filemode; /* must be last field @ boards.c */ +} fileheader_t; + +#define FILE_LOCAL 0x1 /* local saved */ +#define FILE_READ 0x1 /* already read : mail only */ +#define FILE_MARKED 0x2 /* opus: 0x8 */ +#define FILE_DIGEST 0x4 /* digest */ +#define FILE_TAGED 0x8 /* taged */ +#define FILE_SOLVED 0x10 /* problem solved, sysop only */ + +#define STRLEN 80 /* Length of most string data */ + + +/* uhash is a userid->uid hash table -- jochang */ + +#define HASH_BITS 16 +typedef struct uhash_t { + char userid[MAX_USERS][IDLEN + 1]; + int money[MAX_USERS]; + int next_in_hash[MAX_USERS]; + int hash_head[1 << HASH_BITS]; + int number; /* # of users total */ + int loaded; /* .PASSWD has been loaded? */ +} uhash_t; + +union xitem_t { + struct { /* bbs_item */ + char fdate[9]; /* [mm/dd/yy] */ + char editor[13]; /* user ID */ + char fname[31]; + } B; + struct { /* gopher_item */ + char path[81]; + char server[48]; + int port; + } G; +}; + +typedef struct { + char title[63]; + union xitem_t X; +} item_t; + +typedef struct { + item_t *item[MAX_ITEMS]; + char mtitle[STRLEN]; + char *path; + int num, page, now, level; +} gmenu_t; + +typedef struct msgque_t { + pid_t last_pid; + char last_userid[IDLEN + 1]; + char last_call_in[80]; +} msgque_t; + +#define FAVMAX 74 /* Max boards of Myfavorite */ +#define FAVGMAX 16 /* Max groups of Myfavorite */ +#define FAVGSLEN 8 /* Max Length of Description String */ + +typedef struct userinfo_t { + int uid; /* Used to find user name in passwd file */ + pid_t pid; /* kill() to notify user of talk request */ + int sockaddr; /* ... */ + int destuid; /* talk uses this to identify who called */ + int destuip; /* dest index in utmpshm->uinfo[] */ + unsigned char active; /* When allocated this field is true */ + unsigned char invisible; /* Used by cloaking function in Xyz menu */ + unsigned char sockactive; /* Used to coordinate talk requests */ + unsigned int userlevel; + unsigned char mode; /* UL/DL, Talk Mode, Chat Mode, ... */ + unsigned char pager; /* pager toggle, YEA, or NA */ + unsigned char in_chat; /* for in_chat commands */ + unsigned char sig; /* signal type */ + char userid[IDLEN + 1]; + char chatid[11]; /* chat id, if in chat mode */ + char realname[20]; + char username[24]; + char from[27]; /* machine name the user called in from */ + int from_alias; + char birth; /* ¬O§_¬O¥Í¤é Ptt*/ + char tty[11]; /* tty port */ + int friend[MAX_FRIEND]; + void *friend_online[MAX_FRIEND]; /* point¨ì½u¤W¦n¤Í */ + int friend_state[MAX_FRIEND]; /* ¹ïÀ³¨ìfriend_onlineªºª¬ºA */ + int reject[MAX_REJECT]; + unsigned char msgcount; + msgque_t msgs[MAX_MSGS]; + time_t uptime; + time_t lastact; /* ¤W¦¸¨Ï¥ÎªÌ°Êªº®É¶¡ */ + unsigned int brc_id; + unsigned char lockmode; /* ¤£ã multi_login ª±ªºªF¦è */ + char turn; /* for gomo */ + char mateid[IDLEN + 1]; /* for gomo */ + unsigned short int five_win; + unsigned short int five_lose; + unsigned short int five_tie; + int myfavorite[FAVMAX]; + char gfavorite[FAVGMAX][FAVGSLEN+1]; + int ninGroup[FAVGMAX]; + int nGroup; + int ninRoot; + int mailalert; + int sex; + char color; + int mind; +} userinfo_t; + +typedef struct { + fileheader_t *header; + char mtitle[STRLEN]; + char *path; + int num, page, now, level; +} menu_t; + +typedef struct onekey_t { /* Used to pass commands to the readmenu */ + int key; + int (*fptr)(); +} onekey_t; + +#define ANSILINELEN (511) /* Maximum Screen width in chars */ + +/* anti_crosspost */ +typedef struct crosspost_t { + int checksum[4]; /* 0 -> 'X' cross post 1-3 -> ²¬d¤å³¹¦æ */ + int times; /* ²Ä´X¦¸ */ +} crosspost_t; + +#define SORT_BY_ID 0 +#define SORT_BY_CLASS 1 +#define SORT_BY_STAT 1 +#define SORT_BY_IDLE 2 +#define SORT_BY_FROM 3 +#define SORT_BY_FIVE 4 +#define SORT_BY_SEX 5 + +typedef struct bcache_t { + boardheader_t bcache[MAX_BOARD]; + boardheader_t *sorted[2][MAX_BOARD]; /* 0: by name 1: by class */ + fileheader_t dircache[MAX_BOARD][DIRCACHESIZE]; + unsigned int total[MAX_BOARD]; + time_t lastposttime[MAX_BOARD]; + time_t uptime; + time_t touchtime; + int number; + int busystate; +} bcache_t; + +typedef struct keeploc_t { + char *key; + int top_ln; + int crs_ln; + struct keeploc_t *next; +} keeploc_t; + +#define USHM_SIZE (MAX_ACTIVE + 4) /* why+4? */ + +struct utmpfile_t { + userinfo_t uinfo[USHM_SIZE]; + userinfo_t *sorted[8][USHM_SIZE]; + time_t uptime; + int number; + int busystate; +}; + +struct pttcache_t { + char notes[MAX_MOVIE][200*11]; + char today_is[20]; + int n_notes[MAX_MOVIE_SECTION]; /* ¤@¸`¤¤¦³´XÓ ¬ÝªO */ + int next_refresh[MAX_MOVIE_SECTION]; /* ¤U¤@¦¸nrefreshªº ¬ÝªO */ + int max_film; + int max_history; + time_t uptime; + time_t touchtime; + int busystate; +}; + +typedef struct fromcache_t { + char domain[MAX_FROM][50]; + char replace[MAX_FROM][50]; + int top; + int max_user; + time_t max_time; + time_t uptime; + time_t touchtime; + int busystate; +} fromcache_t; + +typedef struct { + unsigned char oldlen; /* previous line length */ + unsigned char len; /* current length of line */ + unsigned char mode; /* status of line, as far as update */ + unsigned char smod; /* start of modified data */ + unsigned char emod; /* end of modified data */ + unsigned char sso; /* start stand out */ + unsigned char eso; /* end stand out */ + unsigned char data[ANSILINELEN + 1]; +} screenline_t; + +typedef struct { + int r, c; +} rc_t; + +#define BRD_ROW 10 +#define BRD_COL 9 + +typedef int board_t[BRD_ROW][BRD_COL]; + +/* name.c ¤¤¹B¥Îªº¸ê®Æµ²ºc */ +typedef struct word_t { + char *word; + struct word_t *next; +} word_t; + +typedef struct commands_t { + int (*cmdfunc)(); + int level; + char *desc; /* next/key/description */ +} commands_t; + +typedef struct MailQueue { + char filepath[FNLEN]; + char subject[STRLEN]; + time_t mailtime; + char sender[IDLEN + 1]; + char username[24]; + char rcpt[50]; + int method; + char * niamod; +} MailQueue; + +enum {MQ_TEXT, MQ_UUENCODE, MQ_JUSTIFY}; + +#endif diff --git a/innbbsd/.cvsignore b/innbbsd/.cvsignore new file mode 100644 index 00000000..91b3d99d --- /dev/null +++ b/innbbsd/.cvsignore @@ -0,0 +1,6 @@ +bbslink +bbsnnrp +ctlinnbbsd +innbbsd +mkhistory +*.o diff --git a/innbbsd/Makefile b/innbbsd/Makefile new file mode 100644 index 00000000..fb82be2a --- /dev/null +++ b/innbbsd/Makefile @@ -0,0 +1,206 @@ +# ------------------------------------------------------- # +# innbbsd/Makefile ( NTHU CS MapleBBS Ver 2.36 ) # +# ------------------------------------------------------- # +# target : Makefile for Âà«Hµ{¦¡ innbbsd by skhuang # +# create : 95/03/29 # +# update : 95/12/15 # +# ------------------------------------------------------- # + +#################################################### +# this is a bbs <--> news gateway +##################################################### +VERSION=0.50beta-4 +LASTVERSION=0.50beta-3 +ADMINUSER= root@your.domain.name +BBSHOME?=$(HOME) +BBS_SRC = .. +TARGET = $(INNBBSD) $(BBSNNRP) $(BBSLINK) +#################################################### +CC=gcc +INSTALL=cp +# +OPT= -O3 -s -pipe -fomit-frame-pointer -g + +BBS_DEP = MapleBBS +BBS_UTIL = $(BBS_SRC)/util +BBS_REC = $(BBS_UTIL)/util_record.o $(BBS_UTIL)/util_cache.o $(BBS_UTIL)/util_passwd.o + +######################### +# +############### +DEBUGOBJ = /usr/lib/debug/mallocmap.o +CFLAGS= -c -I. -I$(BBS_SRC)/include -I$(BBS_SRC)/mbbsd -D$(BBS_DEP) \ +$(EXTRAFLAGS) -DDBZDEBUG -DBBSHOME='"$(BBSHOME)"' \ +-D_PATH_BBSHOME=\"$(BBSHOME)\" \ +-DVERSION=\"$(VERSION)\" -DADMINUSER=\"$(ADMINUSER)\" +# +#################################################### + +OBJS = inndchannel.o innbbsd.o connectsock.o rfc931.o \ + daemon.o file.o pmain.o his.o dbz.o \ + closeonexec.o dbztool.o inntobbs.o receive_article.o \ + echobbslib.o $(BBS_REC) + # $(BBS_REC) +SRCS = inndchannel.c innbbsd.c connectsock.c rfc931.c \ + daemon.c file.c pmain.c parsdate.y his.c dbz.c \ + closeonexec.c dbztool.c inntobbs.c bbslib.c receive_article.c \ + port.c + +MOBJS = makedbz.o bbslib.o file.o dbz.o closeonexec.o +HOBJS = mkhistory.o bbslib.o file.o his.o dbz.o port.o closeonexec.o +DBZOBJS = dbzserver.o dbzinnbbsd.o pmain.o connectsock.o bbslib.o his.o \ + daemon.o file.o dbz.o dbztool.o rfc931.o port.o closeonexec.o \ + morelog.o +NNRPOBJS = bbsnnrp.o pmain.o bbslib.o connectsock.o file.o +LINKOBJS = bbslink.o pmain.o inntobbs.o echobbslib.o connectsock.o file.o port.o +LINKOBJS2 = bbslink2.o pmain.o inntobbs.o echobbslib.o connectsock.o file.o port.o +CTLOBJS = ctlinnbbsd.o pmain.o bbslib.o connectsock.o file.o +INNBBSD = innbbsd mkhistory bbsnnrp ctlinnbbsd $(BBSLINK) +BBSNNRP = bbsnnrp +BBSLINK = bbslink +BBSLINK2 = bbslink2 +EXES = $(TARGET) + +.c.o: + $(CC) $(OPT) $(CFLAGS) $*.c + + +all: $(OSTYPE) + +sun: + @$(MAKE) EXTRAFLAGS="-DMMAP -DGETRUSAGE -DMALLOCMAP" LDFLAGS="$(DEBUGOBJ)" target + + +aix: + @$(MAKE) CC=cc EXTRAFLAGS="-DMMAP -DGETRUSAGE -DAIX -DSYSV" target + +linux: + @$(MAKE) EXTRAFLAGS="-DLINUX -DGETRUSAGE" target + +hpux: + @$(MAKE) OPT= EXTRAFLAGS="-DMMAP -DHPUX -DSYSV" target + +irix: + @$(MAKE) EXTRAFLAGS="-DMMAP -DIRIX -DSYSV" target + +solaris: + @$(MAKE) EXTRAFLAGS="-DMMAP -DSOLARIS -DSYSV" LDFLAGS="-lsocket -lnsl" YACC="bison -y" target + +FreeBSD: + @$(MAKE) CC=cc EXTRAFLAGS="-DBSD44 -DMMAP -DGETRUSAGE" LIBCRYPT=-lcrypt target + +bsd: + @$(MAKE) CC=cc EXTRAFLAGS="-DMMAP -DGETRUSAGE" target + +alpha: + @$(MAKE) CC=cc EXTRAFLAGS="-DMMAP -DDEC_ALPHA -DGETRUSAGE" target + +sysv: + @$(MAKE) OPT= EXTRAFLAGS="-DMMAP -DSYSV" target + +target: $(EXES) + +r_port.o: r_port.c + $(CC) $(OPT) $(CFLAGS) -DWITH_RECORD_O r_port.c + +echobbslib.o: echobbslib.c + $(CC) $(OPT) $(CFLAGS) -DWITH_ECHOMAIL echobbslib.c + +tar: + test -d innbbsd-$(VERSION) || mkdir innbbsd-$(VERSION) + cp *.c *.h Makefile innbbsd-$(VERSION) + tar zcf innbbsd-$(VERSION).tar.gz innbbsd-$(VERSION) + cp innbbsd-$(VERSION).tar.gz /net/ftphome/CSIE/innbbsd + +patch: + rm -rf /tmp/innbbsd-$(LASTVERSION) + zcat /net/ftphome/ftp-data/bbs/misc/innbbsd/innbbsd-$(LASTVERSION).tar.gz | (cd /tmp; tar xf -) + (cd /tmp/innbbsd-$(VERSION); make clean; rm -f r_port.c dbzserver.c dbzinnbbsd.c echobbslib.c ) + (cd /tmp/innbbsd-$(LASTVERSION); make clean; rm -f r_port.c dbzserver.c dbzinnbbsd.c echobbslib.c ) + (cd /tmp; diff -rcs innbbsd-$(LASTVERSION) innbbsd-$(VERSION) > /tmp/innbbsd-patch.$(LASTVERSION)-$(VERSION); echo "diff -rcs") + (cd /tmp/innbbsd-$(VERSION); ln -s port.c r_port.c) + (cd /tmp/innbbsd-$(VERSION); ln -s inndchannel.c dbzserver.c) + (cd /tmp/innbbsd-$(VERSION); ln -s innbbsd.c dbzinnbbsd.c) + (cd /tmp/innbbsd-$(VERSION); ln -s bbslib.c echobbslib.c) + + +distribution: + rm -rf /tmp/innbbsd-$(VERSION) + test -d /tmp/innbbsd-$(VERSION) || mkdir /tmp/innbbsd-$(VERSION) + test -d /tmp/innbbsd-$(VERSION)/innd || mkdir /tmp/innbbsd-$(VERSION)/innd + rm -f r_port.c + rm -f dbzserver.c + rm -f dbzinnbbsd.c + rm -f echobbslib.c + cp -r doc hisconvert FEATURES CHANGES README* TODO *.c *.h *.y Makefile boards /tmp/innbbsd-$(VERSION) + (cd /tmp/innbbsd-$(VERSION); ln -s port.c r_port.c) + (cd /tmp/innbbsd-$(VERSION); ln -s inndchannel.c dbzserver.c) + (cd /tmp/innbbsd-$(VERSION); ln -s innbbsd.c dbzinnbbsd.c) + (cd /tmp/innbbsd-$(VERSION); ln -s bbslib.c echobbslib.c) + (cd innd ; cp -r Makefile README innbbs.conf in.bntpd mailpost *.pl bntplink bntplink.palmbbs *.active* *.c *.y *.bbs src /tmp/innbbsd-$(VERSION)/innd) + (cd /tmp/innbbsd-$(VERSION); make clean) + (cd /tmp; tar zcf innbbsd-$(VERSION).tar.gz innbbsd-$(VERSION) ) + ln -s port.c r_port.c + ln -s inndchannel.c dbzserver.c + ln -s innbbsd.c dbzinnbbsd.c + ln -s bbslib.c echobbslib.c + +remotetest: distribution + /usr/local/krb4/rcp /tmp/innbbsd-$(VERSION).tar.gz bbs_src.tar.gz skhuang:/tmp + /usr/local/krb4/rcp /tmp/innbbsd-$(VERSION).tar.gz bbs_src.tar.gz linux:/tmp + mv /u/staff/skhuang/.tcshrc /u/staff/skhuang/skhuang.tcshrc + rcp /tmp/innbbsd-$(VERSION).tar.gz bbs_src.tar.gz ccsun36:/tmp + rcp /tmp/innbbsd-$(VERSION).tar.gz bbs_src.tar.gz ccibm1:/tmp + mv /u/staff/skhuang/skhuang.tcshrc /u/staff/skhuang/.tcshrc + rcp /tmp/innbbsd-$(VERSION).tar.gz bbs_src.tar.gz cciris3:/tmp + +ftp: distribution patch + rsh ccsun42 mv /home8/ftp/pub/bbs/misc/innbbsd/innbbsd-$(VERSION).tar.gz /home8/ftp/pub/bbs/misc/innbbsd/.innbbsd-$(VERSION).tar.gz + rcp /tmp/innbbsd-$(VERSION).tar.gz ccsun42:/home8/ftp/pub/bbs/misc/innbbsd + rcp README* ccsun42:/home8/ftp/pub/bbs/misc/innbbsd + rcp /tmp/innbbsd-patch.$(LASTVERSION)-$(VERSION) ccsun42:/home8/ftp/pub/bbs/misc/innbbsd + +innbbspost.o: innbbspost.c + $(CC) $(CFLAGS) -I$(BBS_SRC) -c innbbspost.c + +makedbz: $(MOBJS) + $(CC) $(OPT) -o makedbz $(MOBJS) $(LDFLAGS) + +dbzserver.o: dbzserver.c + $(CC) $(CFLAGS) -DDBZSERVER -I$(BBS_SRC) -c dbzserver.c + +dbzinnbbsd.o: dbzinnbbsd.c + $(CC) $(CFLAGS) -DDBZSERVER -I$(BBS_SRC) -c dbzinnbbsd.c + +dbzserver: $(DBZOBJS) + $(CC) $(OPT) -o dbzserver $(DBZOBJS) $(LDFLAGS) + +bbsnnrp: $(NNRPOBJS) + $(CC) -o bbsnnrp $(NNRPOBJS) $(OPT) $(LDFLAGS) + +bbslink: $(LINKOBJS) + $(CC) -o bbslink $(LINKOBJS) $(OPT) $(LDFLAGS) + +bbslink2: $(LINKOBJS2) + $(CC) -o bbslink2 $(LINKOBJS2) $(OPT) $(LDFLAGS) + +ctlinnbbsd: $(CTLOBJS) + $(CC) $(OPT) -o ctlinnbbsd $(CTLOBJS) $(LDFLAGS) + +mkhistory: $(HOBJS) + $(CC) $(OPT) -o mkhistory $(HOBJS) $(LDFLAGS) + +dbz_query_sample: dbz_query_sample.o + $(CC) $(OPT) -o dbz_query_sample dbz_query_sample.o $(LDFLAGS) + + +innbbsd: $(OBJS) +# mv tnrpd.exe tnrpd.exe.old + $(CC) -o innbbsd $(OBJS) $(OPT) $(LDFLAGS) + +install: $(EXES) + install -d $(BBSHOME)/innd/ + install -c -m 755 $(EXES) $(BBSHOME)/innd/ + +clean: + rm -f *.o $(EXES) core innd/src/*.o diff --git a/innbbsd/antisplam.h b/innbbsd/antisplam.h new file mode 100644 index 00000000..30289da1 --- /dev/null +++ b/innbbsd/antisplam.h @@ -0,0 +1,37 @@ +#define char_lower(c) ((c >= 'A' && c <= 'Z') ? c|32 : c) + +/*void +str_lower(t, s) + char *t, *s;*/ +void str_lower(char *t, char *s) +{ + register char ch; + do + { + ch = *s++; + *t++ = char_lower(ch); + } while (ch); +} + +#if 0 /* string.h , libc */ +int +strcasestr(str, tag) + char *str, *tag; /* tag : lower-case string */ +{ + char buf[256]; + + str_lower(buf, str); + return (int) strstr(buf, tag); +} +#endif + +int +bad_subject(char *subject) +{ + char *badkey[] = {"µL½X","avcd","mp3",NULL}; + int i; + for(i=0; badkey[i]; i++) + if(strcasestr(subject, badkey[i])) return 1; + return 0; +} + diff --git a/innbbsd/bbslib.c b/innbbsd/bbslib.c new file mode 100644 index 00000000..0dc808c3 --- /dev/null +++ b/innbbsd/bbslib.c @@ -0,0 +1,712 @@ +#if defined( LINUX ) +# include "innbbsconf.h" +# include "bbslib.h" +# include <varargs.h> +#else +# include <varargs.h> +# include "innbbsconf.h" +# include "bbslib.h" +#endif + +char INNBBSCONF[MAXPATHLEN]; +char INNDHOME[MAXPATHLEN]; +char HISTORY[MAXPATHLEN]; +char LOGFILE[MAXPATHLEN]; +char MYBBSID[MAXPATHLEN]; +char ECHOMAIL[MAXPATHLEN]; +char BBSFEEDS[MAXPATHLEN]; +char LOCALDAEMON[MAXPATHLEN]; + +int His_Maint_Min= HIS_MAINT_MIN; +int His_Maint_Hour= HIS_MAINT_HOUR; +int Expiredays = EXPIREDAYS; + +nodelist_t *NODELIST=NULL, **NODELIST_BYNODE=NULL; +newsfeeds_t *NEWSFEEDS=NULL, **NEWSFEEDS_BYBOARD=NULL; +static char *NODELIST_BUF, *NEWSFEEDS_BUF; +int NFCOUNT, NLCOUNT; +int LOCALNODELIST=0, NONENEWSFEEDS=0; + +#ifndef _PATH_BBSHOME +# define _PATH_BBSHOME "/u/staff/bbsroot/csie_util/bntpd/home" +#endif + +static FILE *bbslogfp; + +static int +verboseFlag=0; + +static char* +verboseFilename=NULL; +static char verbosename[MAXPATHLEN]; + +verboseon(filename) +char *filename; +{ + verboseFlag = 1; + if ( filename != NULL ) { + if (strchr(filename,'/') == NULL) { + sprintf(verbosename,"%s/innd/%s",BBSHOME,filename); + filename = verbosename; + } + } + verboseFilename = filename; +} +verboseoff() +{ + verboseFlag = 0; +} + +setverboseon() +{ + verboseFlag = 1; +} + +isverboselog() +{ + return verboseFlag; +} + +setverboseoff() +{ + verboseoff(); + if (bbslogfp != NULL) { + fclose(bbslogfp); + bbslogfp = NULL; + } +} + +verboselog(va_alist) +va_dcl +{ + va_list ap; + register char* fmt; + char datebuf[40]; + time_t now; + + if (verboseFlag == 0) return; + + va_start(ap); + + time(&now); + strftime(datebuf, sizeof(datebuf), "%b %d %X ", localtime(&now)); + + if (bbslogfp == NULL) { + if (verboseFilename != NULL) + bbslogfp = fopen(verboseFilename, "a"); + else + bbslogfp = fdopen(1, "a"); + } + if (bbslogfp == NULL) { va_end(ap); return; } + fmt = va_arg(ap, char *) ; + fprintf(bbslogfp,"%s[%d] ",datebuf, getpid()); + vfprintf(bbslogfp, fmt, ap); + fflush(bbslogfp); + va_end(ap); +} + +#ifdef PalmBBS +xbbslog(va_alist) +#else +bbslog(va_alist) +#endif +va_dcl +{ + va_list ap; + register char* fmt; + char datebuf[40]; + time_t now; + + va_start(ap); + + time(&now); + strftime(datebuf, sizeof(datebuf), "%b %d %X ", localtime(&now)); + + if (bbslogfp == NULL) { + bbslogfp = fopen(LOGFILE, "a"); + } + if (bbslogfp == NULL) { va_end(ap); return; } + fmt = va_arg(ap, char *) ; + fprintf(bbslogfp,"%s[%d] ",datebuf,getpid()); + vfprintf(bbslogfp, fmt, ap); + fflush(bbslogfp); + va_end(ap); +} + +initial_bbs(outgoing) +char *outgoing; +{ + FILE* FN; + struct stat st; + int fd, i; + char *bbsnameptr=NULL; + +/* reopen bbslog */ + if (bbslogfp != NULL) { + fclose(bbslogfp); + bbslogfp = NULL; + } + +#ifdef WITH_ECHOMAIL + init_echomailfp(); + init_bbsfeedsfp(); +#endif + + LOCALNODELIST=0, NONENEWSFEEDS =0; + sprintf(INNDHOME,"%s/innd",BBSHOME); + sprintf(HISTORY, "%s/history",INNDHOME); + sprintf(LOGFILE, "%s/bbslog",INNDHOME); + sprintf(ECHOMAIL,"%s/echomail.log",BBSHOME); + sprintf(LOCALDAEMON,"%s/.innbbsd",INNDHOME); + sprintf(INNBBSCONF,"%s/innbbs.conf",INNDHOME); + sprintf(BBSFEEDS,"%s/bbsfeeds.log",INNDHOME); + + if (isfile(INNBBSCONF)) { + FILE *conf; + char buffer[MAXPATHLEN]; + conf = fopen(INNBBSCONF,"r"); + if (conf != NULL) { + while (fgets( buffer, sizeof buffer, conf) != NULL) { + char *ptr, *front=NULL, *value=NULL, *value2=NULL, *value3=NULL; + if ( buffer[0] == '#' || buffer[0] == '\n') continue; + for ( front = buffer; *front && isspace(*front); front++); + for ( ptr = front; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr == '\0') continue; + *ptr++ = '\0'; + for ( ; *ptr && isspace(*ptr) ; ptr++) ; + if (*ptr == '\0') continue; + value = ptr++; + for ( ; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr) { + *ptr++ = '\0'; + for ( ; *ptr && isspace(*ptr) ; ptr++) ; + value2 = ptr++; + for ( ; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr) { + *ptr++ = '\0'; + for ( ; *ptr && isspace(*ptr) ; ptr++) ; + value3 = ptr++; + for ( ; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr) { + *ptr++ = '\0'; + } + } + } + if ( strcasecmp(front,"expiredays") == 0) { + Expiredays = atoi(value); + if (Expiredays < 0) { + Expiredays = EXPIREDAYS; + } + } else if ( strcasecmp(front,"expiretime") == 0) { + ptr = strchr(value,':'); + if (ptr == NULL) { + fprintf(stderr, "Syntax error in innbbs.conf\n"); + } else { + *ptr++ = '\0'; + His_Maint_Hour = atoi(value); + His_Maint_Min = atoi(ptr); + if (His_Maint_Hour < 0) + His_Maint_Hour = HIS_MAINT_HOUR; + if (His_Maint_Min < 0) + His_Maint_Min = HIS_MAINT_MIN; + } + } else if ( strcasecmp(front,"newsfeeds") == 0) { + if (strcmp(value,"none")==0) + NONENEWSFEEDS = 1; + } else if ( strcasecmp(front,"nodelist") == 0) { + if (strcmp(value,"local")==0) + LOCALNODELIST = 1; + } /*else if ( strcasecmp(front,"newsfeeds") == 0) { + printf("newsfeeds %s\n", value); + } else if ( strcasecmp(front,"nodelist") == 0) { + printf("nodelist %s\n", value); + } else if ( strcasecmp(front,"bbsname") == 0) { + printf("bbsname %s\n", value); + } */ + } + fclose(conf); + } + } + +#ifdef WITH_ECHOMAIL + bbsnameptr = (char*) fileglue("%s/bbsname.bbs",INNDHOME); + if ((FN = fopen( bbsnameptr ,"r" ))==NULL) { + fprintf(stderr,"can't open file %s\n", bbsnameptr); + return 0; + } + while ( fscanf(FN,"%s", MYBBSID) != EOF); + fclose(FN); + if( ! isdir(fileglue("%s/out.going",BBSHOME)) ) { + mkdir( (char*)fileglue("%s/out.going",BBSHOME), 0750 ); + } + if (NONENEWSFEEDS == 0) + readnffile(INNDHOME); + if (LOCALNODELIST == 0) { + if (readnlfile(INNDHOME, outgoing) != 0) return 0; + } + +#endif + return 1; +} + +static int +nf_byboardcmp(a,b) +newsfeeds_t **a, **b; +{ +/* + if (!a || !*a || !(*a)->board) return -1; + if (!b || !*b || !(*b)->board) return 1; +*/ + return strcasecmp((*a)->board, (*b)->board); +} + +static int +nfcmp(a,b) +newsfeeds_t *a, *b; +{ +/* + if (!a || !a->newsgroups) return -1; + if (!b || !b->newsgroups) return 1; +*/ + return strcasecmp(a->newsgroups, b->newsgroups); +} + +static int +nlcmp(a,b) +nodelist_t *a, *b; +{ +/* + if (!a || !a->host) return -1; + if (!b || !b->host) return 1; +*/ + return strcasecmp(a->host, b->host); +} + +static int +nl_bynodecmp(a,b) +nodelist_t **a, **b; +{ +/* + if (!a || !*a || !(*a)->node) return -1; + if (!b || !*b || !(*b)->node) return 1; +*/ + return strcasecmp((*a)->node, (*b)->node); +} + +/* read in newsfeeds.bbs and nodelist.bbs */ +readnlfile(inndhome, outgoing) +char *inndhome; +char *outgoing; +{ + FILE *fp; + char buff[1024]; + struct stat st; + int i, count, j; + char *ptr, *nodelistptr; + static lastcount=0; + + sprintf(buff,"%s/nodelist.bbs", inndhome); + fp = fopen(buff,"r"); + if (fp == NULL) { + fprintf(stderr,"open fail %s",buff); + return -1; + } + if (fstat(fileno(fp),&st) != 0) { + fprintf(stderr,"stat fail %s", buff); + return -1; + } + if (NODELIST_BUF == NULL) { + NODELIST_BUF = (char*) mymalloc( st.st_size +1); + } else { + NODELIST_BUF = (char*) myrealloc( NODELIST_BUF, st.st_size +1); + } + i = 0, count =0; + while (fgets(buff, sizeof buff, fp) != NULL) { + if (buff[0] == '#') continue; + if (buff[0] == '\n') continue; + strcpy(NODELIST_BUF+i, buff); + i += strlen(buff); + count ++; + } + fclose(fp); + if (NODELIST == NULL) { + NODELIST = (nodelist_t*) mymalloc(sizeof(nodelist_t) * (count+1)); + NODELIST_BYNODE = (nodelist_t**) mymalloc(sizeof(nodelist_t*) * (count+1)); + } else { + NODELIST = (nodelist_t*) myrealloc(NODELIST, sizeof(nodelist_t) * (count+1)); + NODELIST_BYNODE = (nodelist_t**) myrealloc(NODELIST_BYNODE, sizeof(nodelist_t*) * (count+1)); + } + for (i=lastcount; i< count; i++) { + NODELIST[i].feedfp = NULL; + } + lastcount = count; + NLCOUNT = 0; + for (ptr = NODELIST_BUF; (nodelistptr = (char*)strchr(ptr,'\n')) != NULL; ptr = nodelistptr +1, NLCOUNT++) { + char *nptr , *bptr, *pptr, *tptr; + *nodelistptr = '\0'; + NODELIST[NLCOUNT].host = ""; + NODELIST[NLCOUNT].exclusion = ""; + NODELIST[NLCOUNT].node = ""; + NODELIST[NLCOUNT].protocol = "IHAVE(119)"; + NODELIST[NLCOUNT].comments = ""; + NODELIST_BYNODE[NLCOUNT] = NODELIST+NLCOUNT; + for (nptr= ptr ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') { + bbslog("nodelist.bbs %d entry read error\n", NLCOUNT); + return -1; + } + /*NODELIST[NLCOUNT].id = nptr;*/ + NODELIST[NLCOUNT].node = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') { + bbslog("nodelist.bbs node %d entry read error\n", NLCOUNT); + return -1; + } + *nptr = '\0'; + if ((tptr = strchr(NODELIST[NLCOUNT].node,'/'))) { + *tptr = '\0'; + NODELIST[NLCOUNT].exclusion = tptr + 1; + } else { + NODELIST[NLCOUNT].exclusion = ""; + } + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + if (*nptr=='+' || *nptr=='-') { + NODELIST[NLCOUNT].feedtype = *nptr; + if (NODELIST[NLCOUNT].feedfp != NULL) { + fclose(NODELIST[NLCOUNT].feedfp); + } + if ( NODELIST[NLCOUNT].feedtype == '+') + if (outgoing != NULL) { + NODELIST[NLCOUNT].feedfp = fopen((char*)fileglue("%s/out.going/%s.%s",BBSHOME, NODELIST[NLCOUNT].node, outgoing),"a"); + } + nptr++; + } else { + NODELIST[NLCOUNT].feedtype = ' '; + } + NODELIST[NLCOUNT].host = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') { + continue; + } + *nptr = '\0'; + for (nptr++;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NODELIST[NLCOUNT].protocol = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + *nptr = '\0'; + for (nptr++;*nptr && strchr(" \t\r\n",*nptr); ) nptr++; + if (*nptr == '\0') continue; + NODELIST[NLCOUNT].comments = nptr; + } + qsort(NODELIST, NLCOUNT, sizeof(nodelist_t), nlcmp); + qsort(NODELIST_BYNODE, NLCOUNT, sizeof(nodelist_t*), nl_bynodecmp); + return 0; +} + +readnffile(inndhome) +char *inndhome; +{ + FILE *fp; + char buff[1024]; + struct stat st; + int i, count; + char *ptr, *newsfeedsptr; + + sprintf(buff,"%s/newsfeeds.bbs", inndhome); + fp = fopen(buff,"r"); + if (fp == NULL) { + fprintf(stderr,"open fail %s",buff); + return -1; + } + if (fstat(fileno(fp),&st) != 0) { + fprintf(stderr,"stat fail %s", buff); + return -1; + } + if (NEWSFEEDS_BUF == NULL) { + NEWSFEEDS_BUF = (char*) mymalloc( st.st_size +1); + } else { + NEWSFEEDS_BUF = (char*) myrealloc( NEWSFEEDS_BUF, st.st_size +1); + } + i = 0, count =0; + while (fgets(buff, sizeof buff, fp) != NULL) { + if (buff[0] == '#') continue; + if (buff[0] == '\n') continue; + strcpy(NEWSFEEDS_BUF+i, buff); + i += strlen(buff); + count ++; + } + fclose(fp); + if (NEWSFEEDS == NULL) { + NEWSFEEDS = (newsfeeds_t*) mymalloc(sizeof(newsfeeds_t) * (count+1)); + NEWSFEEDS_BYBOARD = (newsfeeds_t**) mymalloc(sizeof(newsfeeds_t*) * (count+1)); + } else { + NEWSFEEDS = (newsfeeds_t*) myrealloc(NEWSFEEDS, sizeof(newsfeeds_t) * (count+1)); + NEWSFEEDS_BYBOARD = (newsfeeds_t**) myrealloc(NEWSFEEDS_BYBOARD, sizeof(newsfeeds_t*) * (count+1)); + } + NFCOUNT = 0; + for (ptr = NEWSFEEDS_BUF; (newsfeedsptr = (char*)strchr(ptr,'\n')) != NULL; ptr = newsfeedsptr +1, NFCOUNT++) { + char *nptr , *bptr, *pptr; + *newsfeedsptr = '\0'; + NEWSFEEDS[NFCOUNT].newsgroups = ""; + NEWSFEEDS[NFCOUNT].board = ""; + NEWSFEEDS[NFCOUNT].path = NULL; + NEWSFEEDS_BYBOARD[NFCOUNT] = NEWSFEEDS+NFCOUNT; + for (nptr= ptr ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NEWSFEEDS[NFCOUNT].newsgroups = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + *nptr = '\0'; + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NEWSFEEDS[NFCOUNT].board = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + *nptr = '\0'; + for (nptr++;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NEWSFEEDS[NFCOUNT].path = nptr; + for (nptr++; *nptr && !strchr("\r\n",*nptr); ) nptr++; + *nptr = '\0'; + } + qsort(NEWSFEEDS, NFCOUNT, sizeof(newsfeeds_t), nfcmp); + qsort(NEWSFEEDS_BYBOARD, NFCOUNT, sizeof(newsfeeds_t*), nf_byboardcmp); +} + +newsfeeds_t *search_board(board) +char *board; +{ + newsfeeds_t nft, *nftptr, **find; + if (NONENEWSFEEDS) return NULL; + nft.board = board; + nftptr = &nft; + find = (newsfeeds_t**)bsearch((char*)&nftptr, NEWSFEEDS_BYBOARD, NFCOUNT, sizeof(newsfeeds_t*), nf_byboardcmp); + if (find != NULL) return *find; + return NULL; +} + +nodelist_t *search_nodelist_bynode(node) +char *node; +{ + nodelist_t nlt, *nltptr, **find; + if (LOCALNODELIST) return NULL; + nlt.node = node; + nltptr = ≮ + find = (nodelist_t**)bsearch((char*)&nltptr, NODELIST_BYNODE, NLCOUNT, sizeof(nodelist_t*), nl_bynodecmp); + if (find != NULL) return *find; + return NULL; +} + + +nodelist_t *search_nodelist(site, identuser) +char *site; +char *identuser; +{ + nodelist_t nlt, *find; + char buffer[1024]; + if (LOCALNODELIST) return NULL; + nlt.host = site; + find = (nodelist_t*)bsearch((char*)&nlt, NODELIST, NLCOUNT, sizeof(nodelist_t), nlcmp); + if (find == NULL && identuser != NULL) { + sprintf(buffer,"%s@%s", identuser, site); + nlt.host = buffer; + find = (nodelist_t*)bsearch((char*)&nlt, NODELIST, NLCOUNT, sizeof(nodelist_t), nlcmp); + } + return find; +} + +newsfeeds_t *search_group(newsgroup) +char *newsgroup; +{ + newsfeeds_t nft, *find; + if (NONENEWSFEEDS) return NULL; + nft.newsgroups = newsgroup; + find = (newsfeeds_t*)bsearch((char*)&nft, NEWSFEEDS, NFCOUNT, sizeof(newsfeeds_t), nfcmp); + return find; +} + +char *ascii_date(now) +time_t now; +{ + static char datebuf[40]; + /*time_t now; + time(&now);*/ + strftime(datebuf, sizeof(datebuf), "%d %b %Y %X GMT", gmtime(&now)); + return datebuf; +} + +char * +restrdup(ptr, string) +char *ptr; +char *string; +{ + int len ; + if (string == NULL) { + if (ptr != NULL) *ptr = '\0'; + return ptr; + } + len = strlen(string) + 1; + if (ptr != NULL) { + ptr = (char*)myrealloc(ptr, len); + } else + ptr = (char*)mymalloc(len); + strcpy(ptr, string); + return ptr; +} + + + +void * +mymalloc(size) +int size; +{ + char *ptr = (char*)malloc(size); + if (ptr == NULL) { + fprintf(stderr, "cant allocate memory\n"); + syslog(LOG_ERR, "cant allocate memory %m"); + exit(1); + } + return ptr; +} + +void * +myrealloc(optr, size) +void *optr; +int size; +{ + char *ptr = (char*)realloc(optr, size); + if (ptr == NULL) { + fprintf(stderr, "cant allocate memory\n"); + syslog(LOG_ERR, "cant allocate memory %m"); + exit(1); + } + return ptr; +} + +testandmkdir(dir) +char *dir; +{ + if (!isdir(dir)) { + char path[MAXPATHLEN+12]; + sprintf(path,"mkdir -p %s",dir); + system(path); + } +} + +static char splitbuf[2048]; +static char joinbuf[1024]; +#define MAXTOK 50 +static char* Splitptr[MAXTOK]; +char **split(line,pat) +char *line,*pat; +{ + char *p; + int i; + + for (i=0;i<MAXTOK;++i) Splitptr[i] = NULL; + strncpy(splitbuf,line,sizeof splitbuf - 1 ); + /*printf("%d %d\n",strlen(line),strlen(splitbuf));*/ + splitbuf[sizeof splitbuf - 1] = '\0'; + for (i=0,p=splitbuf;*p && i< MAXTOK -1 ;){ + for (Splitptr[i++]=p;*p && !strchr(pat,*p);p++); + if (*p=='\0') break; + for (*p++='\0'; *p && strchr(pat,*p);p++); + } + return Splitptr; +} + +char **BNGsplit(line) +char *line; +{ + char **ptr = split(line,","); + newsfeeds_t *nf1, *nf2; + char *n11, *n12, *n21, *n22; + int i,j; + for (i=0; ptr[i] != NULL; i++) { + nf1 = (newsfeeds_t*)search_group(ptr[i]); + for (j=i+1; ptr[j] != NULL; j++) { + if (strcmp(ptr[i],ptr[j])==0) { + *ptr[j] = '\0'; + continue; + } + nf2 = (newsfeeds_t*)search_group(ptr[j]); + if (nf1 && nf2) { + if (strcmp(nf1->board,nf2->board)==0) { + *ptr[j] = '\0'; + continue; + } + for (n11 = nf1->board, n12 = (char*)strchr(n11,','); + n11 && *n11 ; n12 = (char*) strchr(n11,',')) { + if (n12) *n12 = '\0'; + for (n21 = nf2->board, n22 = (char*)strchr(n21,','); + n21 && *n21 ; n22 = (char*) strchr(n21,',')) { + if (n22) *n22 = '\0'; + if (strcmp(n11,n21)==0) { + *n21 = '\t'; + } + if (n22) { + *n22 = ','; + n21 = n22 + 1; + } else + break; + } + if (n12) { + *n12 = ','; + n11 = n12 +1; + } else + break; + } + } + } + } + return ptr; +} + +char **ssplit(line,pat) +char *line,*pat; +{ + char *p; + int i; + for (i=0;i<MAXTOK;++i) Splitptr[i] = NULL; + strncpy(splitbuf,line,1024); + for (i=0,p=splitbuf;*p && i< MAXTOK;){ + for (Splitptr[i++]=p;*p && !strchr(pat,*p);p++); + if (*p=='\0') break; + *p=0;p++; +/* for (*p='\0'; strchr(pat,*p);p++);*/ + } + return Splitptr; +} + +char *join(lineptr,pat,num) +char **lineptr,*pat; +int num; +{ + int i; + joinbuf[0] = '\0'; + if (lineptr[0] != NULL) + strncpy(joinbuf,lineptr[0],1024); + else { + joinbuf[0]='\0'; + return joinbuf; + } + for (i=1;i<num;i++) { + strcat(joinbuf,pat); + if (lineptr[i] != NULL) + strcat(joinbuf,lineptr[i]); + else + break; + } + return joinbuf; +} + +#ifdef BBSLIB +main() +{ + initial_bbs("feed"); + printf("%s\n",ascii_date()); +} +#endif + diff --git a/innbbsd/bbslib.h b/innbbsd/bbslib.h new file mode 100644 index 00000000..190672b7 --- /dev/null +++ b/innbbsd/bbslib.h @@ -0,0 +1,62 @@ +#ifndef BBSLIB_H +#define BBSLIB_H + +typedef struct nodelist_t { + char *node; + char *exclusion; + char *host; + char *protocol; + char *comments; + int feedtype; + FILE *feedfp; +} nodelist_t; + +typedef struct newsfeeds_t { + char *newsgroups; + char *board; + char *path; +} newsfeeds_t; + +typedef struct overview_t { + char *board, *filename, *group; + time_t mtime; + char *from, *subject; +} overview_t; + +extern char MYBBSID[]; +extern char ECHOMAIL[]; +extern char BBSFEEDS[]; +extern char LOCALDAEMON[]; +extern char INNDHOME[]; +extern char HISTORY[]; +extern char LOGFILE[]; +extern char INNBBSCONF[]; +extern nodelist_t *NODELIST; +extern nodelist_t **NODELIST_BYNODE; +extern newsfeeds_t *NEWSFEEDS, **NEWSFEEDS_BYBOARD; +extern int NFCOUNT, NLCOUNT; +extern int Expiredays, His_Maint_Min, His_Maint_Hour; +extern int LOCALNODELIST, NONENEWSFEEDS; +extern int Maxclient; + +# ifndef ARG +# ifdef __STDC__ +# define ARG(x) x +# else +# define ARG(x) () +# endif +# endif + +int initial_bbs ARG((char* )); +char *restrdup ARG((char *, char *)); +nodelist_t *search_nodelist ARG((char *, char *)); +newsfeeds_t *search_group ARG((char *)); +int bbslog ARG(()); +void *mymalloc ARG((int)); +void *myrealloc ARG((void *, int)); + +#ifdef PalmBBS +#define bbslog xbbslog +#endif + +#endif diff --git a/innbbsd/bbslink.c b/innbbsd/bbslink.c new file mode 100644 index 00000000..2b0b6f37 --- /dev/null +++ b/innbbsd/bbslink.c @@ -0,0 +1,2021 @@ +#if defined( LINUX ) +# include "innbbsconf.h" +# include "bbslib.h" +# include <varargs.h> +#else +# include <varargs.h> +# include "innbbsconf.h" +# include "bbslib.h" +#endif +#include "antisplam.h" + +#include <sys/mman.h> + +#ifndef AIX +# include <sys/fcntl.h> +#endif + +#if defined(PalmBBS) +#include <utime.h> +#endif + + +#include "daemon.h" +#include "nntp.h" +#include "externs.h" + +/* + * TODO 1. read newsfeeds.bbs, read nodelist.bbs, read bbsname.bbs 2. scan + * new posts and append to .link 3. rename .link to .send (must lock) 4. + * start to send .send out and append not sent to .link + * + * 5. node.LOCK (with pid) 6. log articles sent + */ + + +#ifndef MAXBUFLEN +#define MAXBUFLEN 256 +#endif + +#define MAX_OUTGO_POST 100 /* bbslink ¤@¦¸³B²zªºÂà¥X³Ì¤j¤å³¹¼Æ¶q */ + +typedef struct my_out_bntp +{ + char *board, *filename, *userid, *nickname, *subject; +} my_out_bntp; +struct my_out_bntp out_bntp[MAX_OUTGO_POST]; + +int outgo_post=0; + +typedef struct Over_t +{ + time_t mtime; + char date[MAXBUFLEN]; + char nickname[MAXBUFLEN]; + char subject[MAXBUFLEN]; + char from[MAXBUFLEN]; + char msgid[MAXBUFLEN]; + char site[MAXBUFLEN]; + char board[MAXBUFLEN]; +} linkoverview_t; + +typedef struct SendOver_t +{ + char *board, *filename, *group, *from, *subject; + char *outgoingtype, *msgid, *path; + char *date, *control; + time_t mtime; +} soverview_t; + +typedef struct Stat_t +{ + int localsendout; + int localfailed; + int remotesendout; + int remotefailed; +} stat_t; + +static stat_t *BBSLINK_STAT; + +static int NoAction = 0; +static int Verbose = 0; +static int VisitOnly = 0; +static int NoVisit = 0; +static char *DefaultFeedSite = ""; +static int KillFormerBBSLINK = 0; + +extern char *SITE; +extern char *GROUPS; + +char NICKNAME[MAXBUFLEN]; + +char DATE_BUF[MAXBUFLEN]; +extern char *DATE; + +char FROM_BUF[MAXBUFLEN]; +extern char *FROM; + +#ifndef MapleBBS +char POSTER_BUF[MAXBUFLEN]; +char *POSTER; +#endif + +char MYADDR[MAXBUFLEN]; +char MYSITE[MAXBUFLEN]; + +char SUBJECT_BUF[MAXBUFLEN]; +extern char *SUBJECT; + +char MSGID_BUF[MAXBUFLEN]; +extern char *MSGID; + +char LINKPROTOCOL[MAXBUFLEN]; +int LINKPORT; +char ORGANIZATION[MAXBUFLEN]; +char NEWSCONTROL[MAXBUFLEN]; +char NEWSAPPROVED[MAXBUFLEN]; +char NNTPHOST_BUF[MAXBUFLEN]; +extern char *NNTPHOST; +char PATH_BUF[MAXBUFLEN]; +extern char *PATH; + +char CONTROL_BUF[MAXBUFLEN]; +extern char *CONTROL; + +char *BODY, *HEAD; + +int USEIHAVE = 1; +int USEPOST = 0; +int USEDATA = 0; +int FEEDTYPE = ' '; + +int NNTP = -1; +FILE *NNTPrfp = NULL; +FILE *NNTPwfp = NULL; +char NNTPbuffer[1024]; +static char *NEWSFEED; +static char *REMOTE = "REMOTE"; +static char *LOCAL = "LOCAL"; + +static int FD, FD_SIZE; +static char *FD_BUF; +static char *FD_END; + +static char *COMMENT = "\n"; +/*"[Ptt °e¥X]\n";*/ + +char *fileglue(); +int +is_outgo_post(board, filename, userid, nickname, subject) + char *board, *filename, *userid, *nickname, *subject; +{ + int mypost; + + for (mypost = 0; mypost < outgo_post; mypost++) + { + if (!strcmp(out_bntp[mypost].filename, filename)) + if (!strcmp(out_bntp[mypost].userid, userid)) + if (!strcmp(out_bntp[mypost].board, board)) + if (!strcmp(out_bntp[mypost].nickname, nickname)) + if (!strcmp(out_bntp[mypost].subject, subject)){ + if (Verbose) + printf("bad_cancel: %s, %s(%s), %s, %s\n", + board, userid, nickname, subject, filename); + bbslog("bad_cancel: %s, %s(%s), %s, %s\n", + board, userid, nickname, subject, filename); + return 1; + } + } + return 0; +} +/* +woju +Cross-fs rename() +*/ + +Rename(char* src, char* dst) +{ + char cmd[200]; + + if (rename(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/mv %s %s", src, dst); + return system(cmd); + +} + + +bbslink_un_lock(file) + char *file; +{ + char *lockfile = fileglue("%s.LOCK", file); + + if (isfile(lockfile)) + unlink(lockfile); +} + +bbslink_get_lock(file) + char *file; +{ + int lockfd; + char LockFile[MAXPATHLEN]; + + strncpy(LockFile, (char *) fileglue("%s.LOCK", file), sizeof LockFile); + if ((lockfd = open(LockFile, O_RDONLY)) >= 0) + { + char buf[10]; + int pid; + + if (read(lockfd, buf, sizeof buf) > 0 && + (pid = atoi(buf)) > 0 && kill(pid, 0) == 0) + { + if (KillFormerBBSLINK) + { + kill(pid, SIGTERM); + unlink(LockFile); + } + else + { + fprintf(stderr, "another process [%d] running\n", pid); + return 0; + } + } + else + { + fprintf(stderr, "no process [%d] running, but lock file existed, unlinked\n", pid); + unlink(LockFile); + } + close(lockfd); + } + + if ((lockfd = open(LockFile, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0) + { + fprintf(stderr, "lock %s error: another bbslink process running\n", LockFile); + return 0; + } + else + { + char buf[10]; + int pid; + + sprintf(buf, "%-.8d\n", getpid()); + write(lockfd, buf, strlen(buf)); + close(lockfd); + return 1; + } +} + + +int +tcpcommand(va_alist) +va_dcl +{ + va_list ap; + register char *fmt; + char *ptr; + + va_start(ap); + fmt = va_arg(ap, char *); + vfprintf(NNTPwfp, fmt, ap); + fprintf(NNTPwfp, "\r\n"); + fflush(NNTPwfp); + + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + ptr = strchr(NNTPbuffer, '\r'); + if (ptr) + *ptr = '\0'; + ptr = strchr(NNTPbuffer, '\n'); + if (ptr) + *ptr = '\0'; + va_end(ap); + return atoi(NNTPbuffer); +} + +char * +tcpmessage() +{ + char *ptr; + + ptr = strchr(NNTPbuffer, ' '); + if (ptr) + return ptr; + return NNTPbuffer; +} + +read_article(lover, filename, userid) + linkoverview_t *lover; + char *filename, *userid; +{ + FILE *fp; + int fd; + struct stat st; + time_t mtime; + char *buffer; + char *artptr, *artend, *artback; + + if (stat(filename, &st) != 0) + return 0; + lover->mtime = st.st_mtime; + fd = open(filename, O_RDONLY); + if (fd < 0) + { + bbslog("<bbslink> Err: can't open %s\n", filename); + return 0; + } + + if (FD_BUF == NULL) + { + FD_BUF = mymalloc(st.st_size + 1 + strlen(COMMENT)); + } + else + { + FD_BUF = myrealloc(FD_BUF, st.st_size + 1 + strlen(COMMENT)); + } + FD_BUF[st.st_size] = '\0'; + read(fd, FD_BUF, st.st_size); + sprintf(FD_BUF + st.st_size, "%s", COMMENT); + st.st_size += strlen(COMMENT); + FD_SIZE = st.st_size; + for (buffer = FD_BUF, artend = FD_BUF + st.st_size, + artback = strchr(buffer, '\n'); + buffer && buffer < artend && *buffer; + artback = strchr(buffer, '\n') + ) + { + /* while( fgets(buffer, sizeof buffer, fp) != NULL) { */ + char *m, *n; + char *ptr; + + if (artback != NULL) + *artback = '\0'; + if (*buffer == '\0') + break; + +#ifndef MapleBBS + if (strstr(buffer, userid) != NULL) + { + m = strchr(buffer, '('); + n = strrchr(buffer, ')'); + if (m != NULL && n != NULL) + { + strncpy(lover->nickname, m + 1, n - m - 1); + lover->nickname[n - m - 1] = '\0'; + } + else + { + *lover->nickname = '\0'; + } + } + else if (strncmp(buffer, "Date: ", 11) == 0) + { + strcpy(lover->date, buffer + 11); + } + else if (strncmp(buffer, "µo«H¯¸: ", 8) == 0) + { + m = strchr(buffer, '('); + n = strrchr(buffer, ')'); + strncpy(lover->date, m + 1, n - m - 1); + lover->date[n - m - 1] = '\0'; + } +#endif + + if (artback != NULL) + { + *artback = '\n'; + buffer = artback + 1; + } + else + { + break; + } + } + if (artback != NULL) + BODY = artback + 1; + else + BODY = ""; + close(fd); + return 1; +} + +save_outgoing(sover, filename, userid, poster, mtime) + soverview_t *sover, *filename, *userid, *poster; + time_t mtime; +{ + newsfeeds_t *nf; + char *group, *server, *serveraddr; + char *subject, *path; + char *board; + char *ptr1, *ptr2; + + board = sover->board; + + PATH = MYBBSID; + nf = (newsfeeds_t *) search_board(board); + if (nf == NULL) + { + bbslog("<bbslink> save_outgoing: No such board %s\n", board); + return; + } + else + { + group = nf->newsgroups; + server = nf->path; + } + if (!server || !*server) + { + sprintf(PATH_BUF, "%.*s (local)", sizeof PATH_BUF - 9, MYBBSID); + PATH = PATH_BUF; + serveraddr = ""; + sover->path = PATH; + } + for (ptr1 = server; ptr1 && *ptr1;) + { + nodelist_t *nl; + char savech; + + for (; *ptr1 && isspace(*ptr1); ptr1++); + if (!*ptr1) + break; + for (ptr2 = ptr1; *ptr2 && !isspace(*ptr2); ptr2++); + savech = *ptr2; + *ptr2 = '\0'; + nl = (nodelist_t *) search_nodelist_bynode(ptr1); + *ptr2 = savech; + ptr1 = ptr2++; + if (nl == NULL) + continue; + /* if (nl->feedfp == NULL) continue; */ + + if (nl->host && *nl->host) + { + if (nl->feedfp == NULL) + { + nl->feedfp = fopen(fileglue("%s/%s.link", INNDHOME, nl->node), "a"); + if (nl->feedfp == NULL) + { + bbslog("<save outgoing> append failed for %s/%s.link", INNDHOME, nl->node); + } + } + if (nl->feedfp != NULL) + { + flock(fileno(nl->feedfp), LOCK_EX); + fprintf(nl->feedfp, "%s\t%s\t%s\t%ld\t%s\t%s\n", sover->board, filename, group, mtime, FROM, sover->subject); + fflush(nl->feedfp); + flock(fileno(nl->feedfp), LOCK_UN); + } + } + if (savech == '\0') + break; + } +} + + +#ifndef MapleBBS +save_article(board, filename, sover) + char *board, *filename; + soverview_t *sover; +{ + FILE *FN; + + if (Verbose) + printf("<save_article> %s %s\n", board, filename); + FN = fopen(fileglue("%s/boards/%s/%s", BBSHOME, board, filename), "w"); + if (FN == NULL) + { + bbslog("<save_article> err: %s %s\n", board, filename); + if (Verbose) + printf("<save_article> err: %s %s\n", board, filename); + return 0; + } + flock(fileno(FN), LOCK_EX); + fprintf(FN, "µo«H¤H: %s, «H°Ï: %s\n", POSTER, sover->board); + fprintf(FN, "¼Ð ÃD: %s\n", sover->subject); + fprintf(FN, "µo«H¯¸: %s (%s)\n", MYSITE, sover->date); + fprintf(FN, "Âà«H¯¸: %s\n", sover->path); + fprintf(FN, "\n"); + fputs(BODY, FN); + flock(fileno(FN), LOCK_UN); + fclose(FN); + +#if defined(PalmBBS) + { + struct utimbuf times; + + times.actime = sover->mtime; + times.modtime = sover->mtime; + utime(fileglue("%s/boards/%s/%s", BBSHOME, board, filename), ×); + utime(fileglue("%s/.bcache/%s", BBSHOME, board), NULL); + } +#endif +} +#endif + +/* process_article() read_article() save_outgoing() save_article() */ + +process_article(board, filename, userid, nickname, subject) + char *board, *filename, *userid, *nickname, *subject; +{ + char *n, *filepath; + char poster[MAXBUFLEN]; + soverview_t sover; + + if (!*userid) + { + return; + } + else if (!subject || !*subject) + { + subject = "µLÃD"; + } + filepath = fileglue("%s/boards/%s/%s", BBSHOME, board, filename); + if (isfile(filepath)) + { + linkoverview_t lover; + + if (read_article(&lover, filepath, userid)) + { + +#ifndef MapleBBS + strncpy(POSTER_BUF, fileglue("%s@%s (%s)", userid, MYBBSID, nickname), sizeof POSTER_BUF); + POSTER = POSTER_BUF; +#endif + + strncpy(FROM_BUF, fileglue("%s.bbs@%s (%s)", userid, MYADDR, nickname), sizeof FROM_BUF); + FROM = FROM_BUF; + sover.from = FROM; + sover.board = board; + sover.subject = subject; + PATH = MYBBSID; + sover.path = MYBBSID; + sover.date = lover.date; + sover.mtime = lover.mtime; + if (!VisitOnly) + { + save_outgoing(&sover, filename, userid, poster, lover.mtime); + +#ifndef MapleBBS + save_article(board, filename, &sover); +#endif + } + } + } +} + + +char * +baseN(val, base, len) + int val, base, len; +{ + int n, ans; + static char str[MAXBUFLEN]; + char *pstr = str; + int index; + + for (index = len - 1; index >= 0; index--) + { + n = val % base; + val /= base; + if (n < 10) + { + n += '0'; + } + else if (n < 36) + { + n += 'A' - 10; + } + else if (n < 62) + { + n += 'a' - 36; + } + else + { + n = '_'; + } + str[index] = n; + } + str[len] = '\0'; + return str; +} + +char * +hash_value(str) + char *str; +{ + int val, n; + char *ptr; + + if (*str) + ptr = str + strlen(str) - 1; + else + ptr = str; + val = 0; + while (ptr >= str) + { + n = *ptr; + val = (val + n * 0x100) ^ n; + ptr--; + } + return baseN(val, 64, 3); +} + +/* process_cancel() save_outgoing() hash_value(); baseN(); ascii_date(); */ + + +read_outgoing(sover) + soverview_t *sover; +{ + char *board, *filename, *group, *from, *subject, *outgoingtype, *msgid, *path; + char *buffer, *bufferp; + FILE *ECHOMAIL, *FN; + char *hash; + char times[MAXBUFLEN]; + time_t mtime; + + board = sover->board; + filename = sover->filename; + group = sover->group; + mtime = sover->mtime; + from = sover->from; + subject = sover->subject; + outgoingtype = sover->outgoingtype; + msgid = sover->msgid; + path = sover->path; + if (Verbose) + { + printf("<read_outgoing> %s:%s:%s\n", board, filename, group); + printf(" => %ld:%s\n", mtime, from); + printf(" => %s\n", subject); + printf(" => %s:%s\n", outgoingtype, msgid); + printf(" => %s\n", path); + } + if (NEWSFEED == LOCAL) + { + char *end = strrchr(filename, '.'); + + if (end) + *end = '\0'; + strncpy(times, baseN(atol(filename + 2), 48, 6), sizeof times); + if (end) + *end = '.'; + hash = hash_value(fileglue("%s.%s", filename, board)); + sprintf(MSGID_BUF, "%s$%s@%s", times, hash, MYADDR); + } + else + { + strncpy(MSGID_BUF, msgid, sizeof MSGID_BUF); + } + sover->msgid = MSGID; + if (mtime == -1) + { + static char BODY_BUF[MAXBUFLEN]; + + strncpy(BODY_BUF, fileglue("%s\r\n", subject), sizeof BODY_BUF); + BODY = BODY_BUF; + sprintf(SUBJECT_BUF, "cmsg cancel <%s>", MSGID); + SUBJECT = SUBJECT_BUF; + sprintf(CONTROL_BUF, "cancel <%s>", MSGID); + CONTROL = CONTROL_BUF; + strncpy(MSGID_BUF, fileglue("%d.%s", getpid(), MSGID_BUF), sizeof MSGID_BUF); + sprintf(DATE_BUF, "%s", ascii_date(time(NULL))); + DATE = DATE_BUF; + sover->subject = SUBJECT; + sover->control = CONTROL; + sover->msgid = MSGID; + sover->date = DATE; + } + else + { + sover->control = CONTROL; + sover->date = DATE_BUF; + DATE = DATE_BUF; + *CONTROL = '\0'; + sprintf(DATE, "%s", ascii_date((mtime))); + if (NEWSFEED == LOCAL && !NoAction) + { + SITE = MYSITE; + PATH = MYBBSID; + GROUPS = group; + +#ifndef MapleBBS + echomaillog(); +#endif + } + BODY = ""; + FD = open(fileglue("%s/boards/%s/%s", BBSHOME, board, filename), O_RDONLY); + if (FD < 0) + { + if (Verbose) + printf(" !! can't open %s/boards/%s/%s\n", BBSHOME, board, filename); + else + fprintf(stderr, "can't open %s/boards/%s/%s\n", BBSHOME, board, filename); + return -1; + } + + FD_SIZE = filesize(fileglue("%s/boards/%s/%s", BBSHOME, board, filename)); + if (FD_BUF == NULL) + { + FD_BUF = (char *) mymalloc(FD_SIZE + 1 + strlen(COMMENT)); + } + else + { + FD_BUF = (char *) myrealloc(FD_BUF, FD_SIZE + 1 + strlen(COMMENT)); + } + FD_END = FD_BUF + FD_SIZE; + *FD_END = '\0'; + read(FD, FD_BUF, FD_SIZE); + sprintf(FD_END, "%s", COMMENT); + FD_SIZE += strlen(COMMENT); + FD_END += strlen(COMMENT); + if (Verbose) + { + printf("<read in> %s/boards/%s/%s\n", BBSHOME, board, filename); + } + + *ORGANIZATION = '\0'; + *NEWSCONTROL = '\0'; + *NEWSAPPROVED = '\0'; + *NNTPHOST_BUF = '\0'; + NNTPHOST = NULL; + + for (buffer = FD_BUF, bufferp = strchr(buffer, '\n'); + buffer && *buffer; bufferp = strchr(buffer, '\n')) + { + if (bufferp) + *bufferp = '\0'; + if (*buffer == '\0') + { + break; + } + /* printf("get buffer %s\n", buffer); */ + if (NEWSFEED == REMOTE) + { + if (strncmp(buffer, "Date: ", 11) == 0) + { + strcpy(DATE_BUF, buffer + 11); + DATE = DATE_BUF; + } + else if (strncmp(buffer, "µo«H¯¸: ", 8) == 0) + { + char *m, *n; + + m = strchr(buffer, '('); + n = strrchr(buffer, ')'); + if (m && n) + { + strncpy(DATE_BUF, m + 1, n - m - 1); + DATE_BUF[n - m - 1] = '\0'; + DATE = DATE_BUF; + strncpy(ORGANIZATION, buffer + 8, m - 8 - buffer - 1); + ORGANIZATION[m - 8 - buffer - 1] = '\0'; + } + } + else if (strncmp(buffer, "Control: ", 9) == 0) + { + strcpy(NEWSCONTROL, buffer + 9); + } + else if (strncmp(buffer, "Approved: ", 10) == 0) + { + strcpy(NEWSAPPROVED, buffer + 10); + } + else if (strncmp(buffer, "Origin: ", 8) == 0) + { + strcpy(NNTPHOST_BUF, buffer + 8); + NNTPHOST = NNTPHOST_BUF; + } + } + if (bufferp) + { + *bufferp = '\n'; + buffer = bufferp + 1; + } + else + { + break; + } + } + if (bufferp) + { + BODY = bufferp + 1; + } + else + BODY = ""; + if (bufferp) + for (buffer = bufferp + 1, bufferp = strchr(buffer, '\n'); + buffer && *buffer; bufferp = strchr(buffer, '\n')) + { + if (bufferp) + *bufferp = '\0'; + /* printf("get line (%s)\n", buffer); */ + /* if( strcmp(buffer,".")==0 ) { buffer[1]='.'; buffer[2]='\0'; } */ + if (NEWSFEED == REMOTE && + strncmp(NEWSCONTROL, "cancel", 5) == 0 && + strncmp(buffer, "------------------", 18) == 0) + { + break; + } + else if (strncmp(buffer, "¡» From: ", 9) == 0) + { + strcpy(NNTPHOST_BUF, buffer + 9); + NNTPHOST = NNTPHOST_BUF; + } + /* $BODY[ @BODY ] = "$_\r\n"; */ + if (bufferp) + { + *bufferp = '\n'; + buffer = bufferp + 1; + } + else + { + break; + } + } + /* # fprintf("BODY @BODY\n"; */ + close(FD); + } + return 0; +} + +#ifdef TEST +#endif + +openfeed(node) + nodelist_t *node; +{ + if (node->feedfp == NULL) + { + node->feedfp = fopen(fileglue("%s/%s.link", INNDHOME, node->node), "a"); + } +} + +queuefeed(node, textline) + nodelist_t *node; + char *textline; +{ + openfeed(node); + if (node->feedfp != NULL) + { + flock(fileno(node->feedfp), LOCK_EX); + fprintf(node->feedfp, "%s", textline); + fflush(node->feedfp); + flock(fileno(node->feedfp), LOCK_UN); + } +} + +post_article(node, site, sover, textline) + nodelist_t *node; + char *site; + soverview_t *sover; + char *textline; +{ + int status; + char *filename = sover->filename; + char *msgid = sover->msgid; + char *board = sover->board; + char *bodyp, *body; + + if (Verbose) + fprintf(stdout, "<post_article> %s %s %s\n", site, filename, msgid); + if (NoAction && Verbose) + { + printf(" ==>%s\n", sover->path); + printf(" ==>%s:%s\n", sover->from, sover->group); + printf(" ==>%s:%s\n", sover->subject, sover->date); + body = BODY; + bodyp = strchr(body, '\n'); + if (bodyp) + *bodyp = '\0'; + printf(" ==>%s\n", body); + if (bodyp) + *bodyp = '\n'; + if (bodyp) + { + body = bodyp + 1; + bodyp = strchr(body, '\n'); + if (bodyp) + *bodyp = '\0'; + printf(" ==>%s\n", body); + if (bodyp) + *bodyp = '\n'; + } + } + if (NoAction) + return 1; + if (NEWSFEED == REMOTE) + { + fprintf(NNTPwfp, "Path: %s\r\n", sover->path); + fprintf(NNTPwfp, "From: %s\r\n", sover->from); + fprintf(NNTPwfp, "Newsgroups: %s\r\n", sover->group); + fprintf(NNTPwfp, "Subject: %s\r\n", sover->subject); + /* # fprintf( NNTPwfp,"Post with subject ($subject)\n"); */ + fprintf(NNTPwfp, "Date: %s\r\n", sover->date); + if (*ORGANIZATION) + fprintf(NNTPwfp, "Organization: %s\r\n", ORGANIZATION); + fprintf(NNTPwfp, "Message-ID: <%s>\r\n", sover->msgid); + if (*NEWSCONTROL) + fprintf(NNTPwfp, "Control: %s\r\n", NEWSCONTROL); + if (*NEWSAPPROVED) + fprintf(NNTPwfp, "Approved: %s\r\n", NEWSAPPROVED); + } + else + { + fprintf(NNTPwfp, "Path: %s\r\n", MYBBSID); + fprintf(NNTPwfp, "From: %s\r\n", sover->from); + fprintf(NNTPwfp, "Newsgroups: %s\r\n", sover->group); + fprintf(NNTPwfp, "Subject: %s\r\n", sover->subject); + fprintf(NNTPwfp, "Date: %s\r\n", sover->date); + fprintf(NNTPwfp, "Organization: %s\r\n", MYSITE); + fprintf(NNTPwfp, "Message-ID: <%s>\r\n", sover->msgid); + fprintf(NNTPwfp, "X-Filename: %s/%s\r\n", sover->board, sover->filename); + } + if (NNTPHOST && *NNTPHOST && USEIHAVE) + fprintf(NNTPwfp, "NNTP-Posting-Host: %s\r\n", NNTPHOST); + else if (NNTPHOST && *NNTPHOST) + fprintf(NNTPwfp, "X-Auth-From: %s\r\n", NNTPHOST); + if (*CONTROL) + { + fprintf(NNTPwfp, "Control: %s\r\n", CONTROL); + } + fputs("\r\n", NNTPwfp); + for (body = BODY, bodyp = strchr(body, '\n'); + body && *body; bodyp = strchr(body, '\n')) + { + if (bodyp) + *bodyp = '\0'; + + fputs(body, NNTPwfp); + if (body[0] == '.' && body[1] == '\0') + fputs(".", NNTPwfp); + fputs("\r\n", NNTPwfp); + if (bodyp) + { + *bodyp = '\n'; + body = bodyp + 1; + } + else + { + break; + } + } + /* print "send out @BODY\n"; */ + status = tcpcommand("."); + /* 435 duplicated article 437 invalid header */ + + if (USEIHAVE) + { + if (status == 235) + { + if (NEWSFEED == LOCAL) + { + bbslog("Sendout <%s> from %s/%s\n", msgid, board, filename); + } + } + else if (status == 437 || status == 435) + { + bbslog("<bbslink> :Warn: %d %s <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s <%s>\n", status, (char *) tcpmessage(), msgid); + return 0; + } + else + { + bbslog("<bbslink> :Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (!strstr(tcpmessage(), "Article not posted")) + queuefeed(node, textline); + return 0; + } + } + else if (USEPOST) + { + if (status == 240) + { + bbslog("Sendout <%s> from %s/%s\n", msgid, board, filename); + } + else if (status == 437 || status == 435) + { + bbslog("<bbslink> :Warn: %d %s <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s <%s>\n", status, (char *) tcpmessage(), msgid); + return 0; + } + else + { + bbslog("<bbslink> :Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (!strstr(tcpmessage(), "Article not posted")) + queuefeed(node, textline); + return 0; + } + } + else + { + if (status == 250) + { + bbslog("<bbslink> DATA Sendout <%s> from %s/%s\n", msgid, board, filename); + if (Verbose) + printf("<DATA Sendout> <%s> from %s/%s\n", msgid, board, filename); + } + else + { + bbslog("<bbslink> :Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (!strstr(tcpmessage(), "Article not posted")) + queuefeed(node, textline); + return 0; + } + } + return 1; +} + +process_cancel(board, filename, userid, nickname, subject) + char *board, *filename, *userid, *nickname, *subject; +{ + time_t mtime; + soverview_t sover; + + if (!userid || !*userid) + { + return; + } + mtime = -1; + strncpy(FROM_BUF, fileglue("%s.bbs@%s (%s)", userid, MYADDR, nickname), sizeof FROM_BUF); + FROM = FROM_BUF; + sover.from = FROM; + sover.board = board; + sover.subject = subject; + PATH = MYBBSID; + sover.path = MYBBSID; + /* save_outgoing(&sover, filename, userid, poster, -1); */ + save_outgoing(&sover, filename, userid, userid, -1); +} + +open_link(hostname, hostprot, hostport) + char *hostname, *hostprot, *hostport; +{ + USEIHAVE = 1; + USEPOST = 0; + USEDATA = 0; + FEEDTYPE = ' '; + if (Verbose) + printf("<OPEN_link> %s %s %s\n", hostname, hostprot, hostport); + if (strncasecmp(hostprot, "IHAVE", 5) != 0) + { + USEIHAVE = 0; + USEPOST = 1; + if (strncasecmp(hostprot, "POST", 4) == 0) + { + USEPOST = 1; + } + else if (strncasecmp(hostprot, "DATA", 4) == 0) + { + USEPOST = 0; + USEDATA = 1; + } + } + + FEEDTYPE = hostname[0]; + if (!USEDATA) + { + char *atsign; + + if (FEEDTYPE == '-' || FEEDTYPE == '+') + { + hostname = hostname + 1; + } + atsign = strchr(hostname, '@'); + if (atsign != NULL) + { + hostname = atsign + 1; + } + if (!NoAction) + { + if (Verbose) + printf("<inetclient> %s %s\n", hostname, hostport); + if ((NNTP = inetclient(hostname, hostport, "tcp")) < 0) + { + bbslog("<bbslink> :Err: server %s %s error: cant connect\n", hostname, hostport); + if (Verbose) + printf(":Err: server %s %s error: cant connect\n", hostname, hostport); + return 0; + /* exit( 0 ); */ + /* return; */ + } + NNTPrfp = fdopen(NNTP, "r"); + NNTPwfp = fdopen(NNTP, "w"); + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + if (atoi(NNTPbuffer) != 200) + { + bbslog("<bbslink> :Err: server error: %s", NNTPbuffer); + if (Verbose) + printf(":Err: server error: %s", NNTPbuffer); + return 0; + /* exit( 0 ); */ + } + } + else + { + if (Verbose) + printf("<inetclient> %s %s\n", hostname, hostport); + } + } + else + { + if (!NoAction) + { + if (Verbose) + printf("<inetclient> localhost %s\n", hostport); + if ((NNTP = inetclient("localhost", hostport, "tcp")) < 0) + { + bbslog("<bbslink> :Err: server %s port %s error: cant connect\n", hostname, hostport); + if (Verbose) + printf(":Err: server error: cant connect"); + return 0; + /* exit( 0 ); */ + /* return; */ + } + NNTPrfp = fdopen(NNTP, "r"); + NNTPwfp = fdopen(NNTP, "w"); + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + if (strncmp(NNTPbuffer, "220", 3) != 0) + { + bbslog("<bbslink> :Err: server error: %s", NNTPbuffer); + if (Verbose) + printf(":Err: server error: %s", NNTPbuffer); + return 0; + /* exit( 0 ); */ + } + if (strncmp(NNTPbuffer, "220-", 4) == 0) + { + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + } + } + else + { + if (Verbose) + printf("<inetclient> %s %s\n", hostname, hostport); + } + } + return 1; +} + +send_outgoing(node, site, hostname, sover, textline) + nodelist_t *node; + soverview_t *sover; + char *hostname, *site; + char *textline; +{ + int status; + char *board, *filepath, *msgid; + int returnstatus = 0; + + board = sover->board; + filepath = sover->filename; + msgid = sover->msgid; + + if (Verbose) + printf("<send_outgoing> %s:%s:%s:%s\n", site, board, filepath, msgid); + if (BODY != NULL && !NoAction) + { + if (USEIHAVE) + { +/* status = tcpcommand("IHAVE <%s>", msgid);*/ + char buf[80]; + sprintf(buf, "IHAVE <%s>", msgid); + status = tcpcommand(buf); + if (status == 335) + { + returnstatus = post_article(node, site, sover, textline); + } + else if (status == 435) + { + bbslog("<bbslink> :Warn: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + returnstatus = 0; + } + else + { + bbslog("<bbslink> :Err: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + if (!strstr(tcpmessage(), "Article not posted")) + queuefeed(node, textline); + returnstatus = 0; + } + } + else if (USEPOST) + { + tcpcommand("MODE READER"); + status = tcpcommand("POST"); + if (status == 340) + { + returnstatus = post_article(node, site, sover, textline); + } + else if (status == 441) + { + bbslog("<bbslink> :Warn: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + returnstatus = 0; + } + else + { + bbslog("<bbslink> :Err: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + if (!strstr(tcpmessage(), "Article not posted")) + queuefeed(node, textline); + returnstatus = 0; + } + } + else + { + tcpcommand("HELO"); + tcpcommand("MAIL FROM: bbs"); + tcpcommand("RCPT TO: %s", hostname); + status = tcpcommand("DATA"); + if (status == 354) + { + returnstatus = post_article(node, site, sover, textline); + } + else + { + bbslog("<bbslink> :Err: %d %s, DATA <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s, DATA <%s>\n", status, (char *) tcpmessage(), msgid); + if (!strstr(tcpmessage(), "Article not posted")) + queuefeed(node, textline); + returnstatus = 0; + } + } + } + else if (NoAction) + { + returnstatus = post_article(node, site, sover, textline); + } + return returnstatus; +} + +save_nntplink(node, overview) + nodelist_t *node; + char *overview; +{ + FILE *POSTS; + char buffer[1024]; + + openfeed(node); + POSTS = fopen(overview, "r"); + if (POSTS == NULL) + return 0; + openfeed(node); + /* if (node->feedfp == NULL) return 0; */ + flock(fileno(node->feedfp), LOCK_EX); + while (fgets(buffer, sizeof buffer, POSTS) != NULL) + { + fputs(buffer, node->feedfp); + fflush(node->feedfp); + } + flock(fileno(node->feedfp), LOCK_UN); + fclose(POSTS); + if (Verbose) + printf("<Unlinking> %s\n", overview); + if (!NoAction) + unlink(overview); + return 1; +} + + +char * +get_tmpfile(tmpfile) + char *tmpfile; +{ + FILE *FN; + static char result[256]; + + FN = fopen(tmpfile, "r"); + fgets(result, sizeof result, FN); + fclose(FN); + unlink(tmpfile); + return (result); +} + +/* cancel moderating posts */ + +cancel_outgoing(board, filename, from, subject) + char *board, *filename, *from, *subject; +{ + char *base, filepath[MAXPATHLEN]; + FILE *FN; + char *result; + char TMPFILE[MAXPATHLEN]; + + if (Verbose) + { + printf("<cancel_outgoing> %s %s %s %s\n", board, filename, from, subject); + } + + sprintf(TMPFILE, "/tmp/cancel_outgoing.%d.%d", getuid(), getpid()); + + bbslog("<cancel_outgoing> Try to move moderated post from %s to deleted\n", board); + if (Verbose) + printf("Try to move moderated post from %s to deleted\n", board); + FN = popen(fileglue("%s/bbspost post %s/boards/deleted > %s", + INNDHOME, BBSHOME, TMPFILE), "w"); + if (FN == NULL) + { + bbslog("<cancel_outgoing> can't run %s/bbspost\n", INNDHOME); + if (Verbose) + printf("<cancel_outgoing> can't run %s/bbspost\n", INNDHOME); + return 0; + } + fprintf(FN, "%s\n", from); + fprintf(FN, "%s\n", subject); + fprintf(FN, "µo«H¤H: %s, «H°Ï: %s\n", from, board); + fprintf(FN, "¼Ð ÃD: %s\n", subject); + fprintf(FN, "µo«H¯¸: %s (%s)\n", MYSITE, DATE); + fprintf(FN, "Âà«H¯¸: %s\n", MYBBSID); + fputs("\n", FN); + fputs(BODY, FN); + pclose(FN); + result = (char *) get_tmpfile(TMPFILE); + if (strncmp(result, "post to ", 8) == 0) + { + /* try to remove it */ + strncpy(filepath, fileglue("%s/boards/%s/%s", BBSHOME, board, filename), sizeof filepath); + if (isfile(filepath)) + { + Rename(filepath, fileglue("%s.cancel", filepath)); + } + FN = fopen(filepath, "w"); + + fprintf(FN, "µo«H¤H: %s, «H°Ï: %s\n", from, board); + fprintf(FN, "¼Ð ÃD: <article cancelled and mailed to the moderator\n"); + fprintf(FN, "µo«H¯¸: %s (%s)\n", MYSITE, DATE); + fprintf(FN, "Âà«H¯¸: %s\n", MYBBSID); + fprintf(FN, "\n"); + fputs("\n", FN); + fprintf(FN, "§Aªº¤å³¹ \"%s\" ¤w¸g°e©¹¼f®Ö¤¤. ½Ðµ¥«Ý¦^ÂÐ.\n", subject); + fputs("\n", FN); + fputs("Your post has been sent to the moderator and move\n", FN); + fputs("into the deleted board. If the post accepted by the moderator,\n", FN); + fputs("it will be posted in this board again. Please wait.\n", FN); + + } + else + { + bbslog("%s", result); + } + + bbslog("%s/bbspost cancel %s %s %s moderate\n", INNDHOME, BBSHOME, board, filename); + if (Verbose) + printf("%s/bbspost cancel %s %s %s moderate\n", INNDHOME, BBSHOME, board, filename); + system(fileglue("%s/bbspost cancel %s %s %s moderate", + INNDHOME, BBSHOME, board, filename)); + return 1; +} + +/* + * send_nntplink open_link read_outgoing send_outgoing post_article + * cancel_outgoing + */ +send_nntplink(node, site, hostname, hostprot, hostport, overview, nlcount) + nodelist_t *node; + char *site, *hostname, *hostprot, *hostport, *overview; + int nlcount; +{ + FILE *POSTS; + char textline[1024]; + char baktextline[1024]; + char *filepath; + int status; + + if (Verbose) + { + printf("<send nntplink> %s %s %s %s\n", site, hostname, hostprot, hostport); + printf(" ==> %s\n", overview); + } + if (!open_link(hostname, hostprot, hostport)) + { + save_nntplink(node, overview); + return 0; + } + POSTS = fopen(overview, "r"); + if (POSTS == NULL) + { + if (Verbose) + printf("open %s failed\n", overview); + return 0; + } + while (fgets(textline, sizeof textline, POSTS) != NULL) + { + char *linebreak = strchr(textline, '\n'); + char *ptr; + char *board, *filename, *subject, *group, *mtime, *from; + char *outgoingtype; + char *msgid, *path; + soverview_t soverview; + + strcpy(baktextline, textline); + if (linebreak) + *linebreak = '\0'; + + board = "", filename = "", mtime = "", group = "", from = "", subject = ""; + outgoingtype = "", msgid = "", path = ""; + /* get board field */ + board = textline; + ptr = strchr(textline, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* filename field */ + filename = ptr; + + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + + *ptr++ = '\0'; + + /* group field */ + group = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* mtime field */ + mtime = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* from field */ + from = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* subject */ + subject = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + *ptr++ = '\0'; + + /* outgoing type field */ + outgoingtype = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + *ptr++ = '\0'; + + /* msgid */ + msgid = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + *ptr++ = '\0'; + + /* path */ + path = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + +try_read_outgoing: + + NEWSFEED = LOCAL; + if (outgoingtype && msgid && path && *outgoingtype && *msgid && *path) + { + char *left, *right; + + NEWSFEED = REMOTE; + left = strchr(msgid, '<'); + right = strrchr(msgid, '>'); + if (left) + msgid = left + 1; + if (right) + *right = '\0'; + } + soverview.board = board; + soverview.filename = filename; + soverview.group = group; + soverview.mtime = atol(mtime); + soverview.from = from; + soverview.subject = subject; + soverview.outgoingtype = outgoingtype; + soverview.msgid = msgid; + soverview.path = path; + if (read_outgoing(&soverview) == 0) + { + int sendresult = send_outgoing(node, site, hostname, &soverview, baktextline); + int sendfailed = 1 - sendresult; + + if (NEWSFEED == REMOTE) + { + BBSLINK_STAT[nlcount].remotesendout += sendresult; + BBSLINK_STAT[nlcount].remotefailed += sendfailed; + } + else + { + BBSLINK_STAT[nlcount].localsendout += sendresult; + BBSLINK_STAT[nlcount].localfailed += sendfailed; + } + if (node->feedtype == '-') + { + if (!NoAction && sendresult) + cancel_outgoing(board, filename, from, subject); + } + } + } + fclose(POSTS); + close_link(); + if (Verbose) + printf("<Unlinking> %s\n", overview); + if (!NoAction) + unlink(overview); +} + +close_link() +{ + int status; + + if (Verbose) + printf("<close_link>\n"); + if (NoAction) + return; + status = tcpcommand("QUIT"); + if (status != 205 && status != 221) + { + bbslog("<bbslink> :Err: Cannot quit message '%d %s'\n", status, (char *) tcpmessage()); + if (Verbose) + printf(":Err: Cannot quit message '%d %s'\n", status, (char *) tcpmessage()); + } + fclose(NNTPwfp); + fclose(NNTPrfp); + close(NNTP); +} + + +/* + * send_article() send_nntplink() read_outgoing() + * + */ + +send_article() +{ + char *site, *addr, *protocol, *port, *op; + char *nntphost; + int nlcount; + + chdir(INNDHOME); + + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + nodelist_t *node; + char linkfile[MAXPATHLEN]; + char sendfile[MAXPATHLEN]; + char feedfile[MAXPATHLEN]; + char feedingfile[MAXPATHLEN]; + char protocol[MAXBUFLEN], port[MAXBUFLEN]; + + node = NODELIST + nlcount; + site = node->node; + nntphost = node->host; + op = node->protocol; + + if (DefaultFeedSite && *DefaultFeedSite) + { + if (strcmp(node->node, DefaultFeedSite) != 0) + continue; + } + + if (op && (strncasecmp(op, "ihave", 5) == 0 || + strncasecmp(op, "post", 4) == 0 || + strncasecmp(op, "data", 4) == 0)) + { + char *left, *right; + + left = strchr(op, '('), right = strrchr(op, ')'); + if (left && right) + { + *left = '\0'; + *right = '\0'; + strncpy(protocol, op, sizeof protocol); + strncpy(port, left + 1, sizeof port); + *left = '('; + *right = ')'; + } + else + { + strncpy(protocol, op, sizeof protocol); + strncpy(port, "nntp", sizeof port); + } + } + else + { + strcpy(protocol, "IHAVE"); + strcpy(port, "nntp"); + } + sprintf(linkfile, "%s.link", site); + sprintf(sendfile, "%s.sending", site); + sprintf(feedfile, "%s.feed", site); + sprintf(feedingfile, "%s.feeding", site); + if (isfile(sendfile) && !iszerofile(sendfile)) + { + if (bbslink_get_lock(sendfile)) + { + send_nntplink(node, site, nntphost, protocol, port, sendfile, nlcount); + bbslink_un_lock(sendfile); + } + } + if (isfile(linkfile) && !iszerofile(linkfile)) + { + if (!NoAction) + { + if (bbslink_get_lock(sendfile) && bbslink_get_lock(linkfile) && + bbslink_get_lock(feedingfile)) + { + if (isfile(sendfile) && !iszerofile(sendfile)) + { + save_nntplink(node, sendfile); + } + if (node->feedfp) + { + fclose(node->feedfp); + node->feedfp = NULL; + } + Rename(linkfile, sendfile); + send_nntplink(node, site, nntphost, protocol, port, sendfile, nlcount); + bbslink_un_lock(linkfile); + bbslink_un_lock(sendfile); + bbslink_un_lock(feedingfile); + } + } + else + { + send_nntplink(node, site, nntphost, protocol, port, linkfile, nlcount); + } + } + if (isfile(feedingfile) && !iszerofile(feedingfile)) + { + if (bbslink_get_lock(feedingfile)) + { + send_nntplink(node, site, nntphost, protocol, port, feedingfile, nlcount); + bbslink_un_lock(feedingfile); + } + } + if (isfile(feedfile) && !iszerofile(feedfile)) + { + if (!NoAction) + { + if (bbslink_get_lock(feedfile) && bbslink_get_lock(feedingfile)) + { + if (isfile(feedingfile) && !iszerofile(feedingfile)) + { + save_nntplink(node, feedingfile); + if (node->feedfp) + { + fclose(node->feedfp); + node->feedfp = NULL; + } + } + Rename(feedfile, feedingfile); + system(fileglue("%s/ctlinnbbsd reload > /dev/null", INNDHOME)); + send_nntplink(node, site, nntphost, protocol, port, feedingfile, nlcount); + bbslink_un_lock(feedfile); + bbslink_un_lock(feedingfile); + } + } + else + { + send_nntplink(node, site, nntphost, protocol, port, feedfile, nlcount); + } + } + } +} + +/* bntplink() bbspost() process_article() process_cancel() send_article() */ + + +show_usage(argv) + char *argv; +{ + fprintf(stderr, "%s initialization failed or improper options !!\n", argv); + fprintf(stderr, "Usage: %s [options] bbs_home\n", argv); + fprintf(stderr, " -v (show transmission status)\n"); + fprintf(stderr, " -n (dont send out articles and leave queue untouched)\n"); + fprintf(stderr, " -s site (only process articles sent to site)\n"); + fprintf(stderr, " -V (visit only: bbspost visit)\n"); + fprintf(stderr, " -N (no visit, and only process batch queue)\n"); + fprintf(stderr, " -k (kill the former bbslink process before started)\n\n"); + fprintf(stderr, "¥»µ{¦¡n¥¿±`°õ¦æ¥²¶·±N¥H¤UÀɮ׸m©ó %s/innd ¤U:\n", BBSHOME); + fprintf(stderr, "bbsname.bbs ³]©w¶Q¯¸ªº BBS ID (½Ð¾¨¶q²µu)\n"); + fprintf(stderr, "nodelist.bbs ³]©wºô¸ô¦U BBS ¯¸ªº ID, Address ©M fullname\n"); + fprintf(stderr, "newsfeeds.bbs ³]©wºô¸ô«H¥óªº newsgroup board nodelist ...\n"); +} + + +bntplink(argc, argv) + int argc; + char **argv; +{ + static char *OUTING = ".outing"; + nodelist_t *nl; + int linkport; + char result[4096]; + char cancelfile[MAXPATHLEN], cancelpost[MAXPATHLEN]; + char bbslink_lockfile[MAXPATHLEN]; + FILE *NEWPOST; + char *left, *right; + int nlcount; + +// strcpy(BBSHOME, argv[0]); + if (initial_bbs("link") == 0) + { + return -1; + } + + BBSLINK_STAT = (stat_t *) malloc(sizeof(stat_t) * (NLCOUNT + 1)); + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + BBSLINK_STAT[nlcount].localsendout = 0; + BBSLINK_STAT[nlcount].remotesendout = 0; + BBSLINK_STAT[nlcount].localfailed = 0; + BBSLINK_STAT[nlcount].remotefailed = 0; + } + + nl = (nodelist_t *) search_nodelist_bynode(MYBBSID); + if (nl == NULL) + { + *MYADDR = '\0'; + *MYSITE = '\0'; + *LINKPROTOCOL = '\0'; + } + else + { + strncpy(MYADDR, nl->host, sizeof MYADDR); + strncpy(LINKPROTOCOL, nl->protocol, sizeof LINKPROTOCOL); + strncpy(MYSITE, nl->comments, sizeof MYSITE); + } + if (Verbose) + { + printf("MYADDR: %s\n", MYADDR); + printf("MYSITE: %s\n", MYSITE); + } + left = strchr(nl->protocol, '('); + right = strrchr(nl->protocol, ')'); + if (left && right) + { + *right = '\0'; + strncpy(LINKPROTOCOL, nl->protocol, sizeof LINKPROTOCOL); + LINKPORT = atoi(left + 1); + *right = ')'; + } + + if (!NoVisit) + { + sprintf(bbslink_lockfile, "%s/.bbslink.visit", INNDHOME); + if (!Rename(fileglue("%s/out.bntp", INNDHOME), OUTING) && bbslink_get_lock(bbslink_lockfile)) + { + /* When try to visit new post, try to lock it */ + NEWPOST = fopen(OUTING, "r"); + if (NEWPOST == NULL) + { + bbslog("<bbslink> Err: can't open %s\n", OUTING); + bbslink_un_lock(bbslink_lockfile); + return -1; + } + while (fgets(result, sizeof result, NEWPOST)) + { + /* chop( $_ ); */ + char *board, *filename, *userid, *nickname, *subject; + char *ptr; + + ptr = strchr(result, '\n'); + if (ptr) + *ptr = '\0'; + + board = filename = userid = nickname = subject = NULL; + /* board field */ + board = result; + ptr = strchr(result, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* filename field */ + filename = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* userid field */ + userid = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* nickname field */ + nickname = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* subject field */ + subject = ptr; + /* ptr = strchr(ptr, '\t'); if (ptr == NULL) continue; ptr++ = '\0'; */ + + if(bad_subject(subject)) continue; + + if(outgo_post < MAX_OUTGO_POST){ + out_bntp[outgo_post].board = board; + out_bntp[outgo_post].filename = filename; + out_bntp[outgo_post].userid = userid; + out_bntp[outgo_post].nickname = nickname; + out_bntp[outgo_post].subject = subject; + outgo_post++; + } + + process_article(board, filename, userid, nickname, subject); + } + fclose(NEWPOST); + unlink(OUTING); + bbslink_un_lock(bbslink_lockfile); + } /* getlock */ + } /* if NoVisit is false */ + + sprintf(cancelpost, "%s/cancel.bntp", INNDHOME); + if (isfile(cancelpost)) + { + FILE *CANCELFILE; + + if (bbslink_get_lock(cancelpost) && bbslink_get_lock(cancelfile)) + { + sprintf(cancelfile, "%s.%d", cancelpost, getpid()); + Rename(cancelpost, cancelfile); + CANCELFILE = fopen(cancelfile, "r"); + while (fgets(result, sizeof result, CANCELFILE) != NULL) + { + /* chop( $_ ); */ + char *board, *filename, *userid, *nickname, *subject; + char *ptr, **sptr; + + ptr = strchr(result, '\n'); + if (ptr) + *ptr = '\0'; + board = filename = userid = nickname = subject = NULL; + + /* board field */ + board = result; + ptr = strchr(result, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* filename field */ + filename = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* userid field */ + userid = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* nickname field */ + nickname = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* subject field */ + subject = ptr; + /* ptr = strchr(ptr, '\t'); if (ptr == NULL) continue; ptr++ = '\0'; */ + if(!is_outgo_post(board, filename, userid, nickname, subject)) + process_cancel(board, filename, userid, nickname, subject); + } + fclose(CANCELFILE); + if (Verbose) + printf("Unlinking %s\n", cancelfile); + if (!NoAction) + unlink(cancelfile); + bbslink_un_lock(cancelfile); + bbslink_un_lock(cancelpost); + } + } + + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + if (NODELIST[nlcount].feedfp != NULL) + { + fclose(NODELIST[nlcount].feedfp); + NODELIST[nlcount].feedfp = NULL; + } + } + + send_article(); + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + int localsendout, remotesendout, localfailed, remotefailed; + + localsendout = BBSLINK_STAT[nlcount].localsendout; + remotesendout = BBSLINK_STAT[nlcount].remotesendout; + localfailed = BBSLINK_STAT[nlcount].localfailed; + remotefailed = BBSLINK_STAT[nlcount].remotefailed; + if (localsendout || remotesendout || localfailed || remotefailed) + bbslog("<bbslink> [%s]%s lsend:%d rsend:%d lfail:%d rfail:%d\n", + NODELIST[nlcount].node, NoAction ? "NoAction" : "", localsendout, remotesendout, + localfailed, remotefailed); + if (NODELIST[nlcount].feedfp != NULL) + { + fclose(NODELIST[nlcount].feedfp); + NODELIST[nlcount].feedfp = NULL; + } + } + if (BBSLINK_STAT); + free(BBSLINK_STAT); + return 0; +} +/* +termbbslink(sig) + int sig; +{ + bbslog("kill signal received %d, terminated\n", sig); + if (Verbose) + printf("kill signal received %d, terminated\n", sig); + exit(0); +} +*/ +void +termbbslink() +{ + bbslog("kill signal received ??, terminated\n"); + if (Verbose) + printf("kill signal received ??, terminated\n"); + exit(0); +} + +char *REMOTEUSERNAME = ""; +char *REMOTEHOSTNAME = ""; + +extern char *optarg; +extern int opterr, optind; + +main(argc, argv) + int argc; + char **argv; +{ + int c, errflag = 0; + + CONTROL = CONTROL_BUF; + MSGID = MSGID_BUF; + + /* For debug Only */ +#define DEBUGBBSLINK + +#ifdef DEBUGBBSLINK + NoAction = 0; + Verbose = 0; + VisitOnly = 0; + NoVisit = 0; + DefaultFeedSite = ""; +#endif + + while ((c = getopt(argc, argv, "s:hnvVNk")) != -1) + switch (c) + { + case 's': + DefaultFeedSite = optarg; + break; + case 'n': + NoAction = 1; + break; + case 'v': + Verbose = 1; + break; + case 'V': + VisitOnly = 1; + break; + case 'N': + NoVisit = 1; + break; + case 'k': + KillFormerBBSLINK = 1; + break; + case 'h': + default: + errflag++; + break; + } + if (errflag > 0) + { + show_usage(argv[0]); + return (1); + } + if (argc - optind < 1) + { + show_usage(argv[0]); + exit(1); + } + signal(SIGTERM, termbbslink); + if (bntplink(argc - optind, argv + optind) != 0) + { + show_usage(argv[0]); + exit(1); + } + return 0; +} diff --git a/innbbsd/bbslink2.c b/innbbsd/bbslink2.c new file mode 100644 index 00000000..d79c23a9 --- /dev/null +++ b/innbbsd/bbslink2.c @@ -0,0 +1,2017 @@ +#if defined( LINUX ) +# include "innbbsconf.h" +# include "bbslib.h" +# include <varargs.h> +#else +# include <varargs.h> +# include "innbbsconf.h" +# include "bbslib.h" +#endif + +#include <sys/mman.h> + +#ifndef AIX +# include <sys/fcntl.h> +#endif + +#if defined(PalmBBS) +#include <utime.h> +#endif + + +#include "daemon.h" +#include "nntp.h" +#include "externs.h" + +/* + * TODO 1. read newsfeeds.bbs, read nodelist.bbs, read bbsname.bbs 2. scan + * new posts and append to .link 3. rename .link to .send (must lock) 4. + * start to send .send out and append not sent to .link + * + * 5. node.LOCK (with pid) 6. log articles sent + */ + + +#ifndef MAXBUFLEN +#define MAXBUFLEN 256 +#endif + +typedef struct Over_t +{ + time_t mtime; + char date[MAXBUFLEN]; + char nickname[MAXBUFLEN]; + char subject[MAXBUFLEN]; + char from[MAXBUFLEN]; + char msgid[MAXBUFLEN]; + char site[MAXBUFLEN]; + char board[MAXBUFLEN]; +} linkoverview_t; + +typedef struct SendOver_t +{ + char *board, *filename, *group, *from, *subject; + char *outgoingtype, *msgid, *path; + char *date, *control; + time_t mtime; +} soverview_t; + +typedef struct Stat_t +{ + int localsendout; + int localfailed; + int remotesendout; + int remotefailed; +} stat_t; + +static stat_t *BBSLINK_STAT; + +static int NoAction = 0; +static int Verbose = 0; +static int VisitOnly = 0; +static int NoVisit = 0; +static char *DefaultFeedSite = ""; +static int KillFormerBBSLINK = 0; + +extern char *SITE; +extern char *GROUPS; + +char NICKNAME[MAXBUFLEN]; + +char DATE_BUF[MAXBUFLEN]; +extern char *DATE; + +char FROM_BUF[MAXBUFLEN]; +extern char *FROM; + +#ifndef MapleBBS +char POSTER_BUF[MAXBUFLEN]; +char *POSTER; +#endif + +char MYADDR[MAXBUFLEN]; +char MYSITE[MAXBUFLEN]; + +char SUBJECT_BUF[MAXBUFLEN]; +extern char *SUBJECT; + +char MSGID_BUF[MAXBUFLEN]; +extern char *MSGID; + +char LINKPROTOCOL[MAXBUFLEN]; +int LINKPORT; +char ORGANIZATION[MAXBUFLEN]; +char NEWSCONTROL[MAXBUFLEN]; +char NEWSAPPROVED[MAXBUFLEN]; +char NNTPHOST_BUF[MAXBUFLEN]; +extern char *NNTPHOST; +char PATH_BUF[MAXBUFLEN]; +extern char *PATH; + +char CONTROL_BUF[MAXBUFLEN]; +extern char *CONTROL; + +char *BODY, *HEAD; + +int USEIHAVE = 1; +int USEPOST = 0; +int USEDATA = 0; +int FEEDTYPE = ' '; + +int NNTP = -1; +FILE *NNTPrfp = NULL; +FILE *NNTPwfp = NULL; +char NNTPbuffer[1024]; +static char *NEWSFEED; +static char *REMOTE = "REMOTE"; +static char *LOCAL = "LOCAL"; + +static int FD, FD_SIZE; +static char *FD_BUF; +static char *FD_END; + +static char *COMMENT = +"[Ptt °e¥X]\n"; + +char *fileglue(); + +/* +woju +Cross-fs rename() +*/ + +Rename(char* src, char* dst) +{ + char cmd[200]; + + if (rename(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/mv %s %s", src, dst); + return system(cmd); + +} + + +bbslink_un_lock(file) + char *file; +{ + char *lockfile = fileglue("%s.LOCK", file); + + if (isfile(lockfile)) + unlink(lockfile); +} + +bbslink_get_lock(file) + char *file; +{ + int lockfd; + char LockFile[MAXPATHLEN]; + + strncpy(LockFile, (char *) fileglue("%s.LOCK", file), sizeof LockFile); + if ((lockfd = open(LockFile, O_RDONLY)) >= 0) + { + char buf[10]; + int pid; + + if (read(lockfd, buf, sizeof buf) > 0 && + (pid = atoi(buf)) > 0 && kill(pid, 0) == 0) + { + if (KillFormerBBSLINK) + { + kill(pid, SIGTERM); + unlink(LockFile); + } + else + { + fprintf(stderr, "another process [%d] running\n", pid); + return 0; + } + } + else + { + fprintf(stderr, "no process [%d] running, but lock file existed, unlinked\n", pid); + unlink(LockFile); + } + close(lockfd); + } + + if ((lockfd = open(LockFile, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0) + { + fprintf(stderr, "lock %s error: another bbslink process running\n", LockFile); + return 0; + } + else + { + char buf[10]; + int pid; + + sprintf(buf, "%-.8d\n", getpid()); + write(lockfd, buf, strlen(buf)); + close(lockfd); + return 1; + } +} + + +int +tcpcommand(va_alist) +va_dcl +{ + va_list ap; + register char *fmt; + char *ptr; + + va_start(ap); + fmt = va_arg(ap, char *); + vfprintf(NNTPwfp, fmt, ap); + fprintf(NNTPwfp, "\r\n"); + fflush(NNTPwfp); + + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + ptr = strchr(NNTPbuffer, '\r'); + if (ptr) + *ptr = '\0'; + ptr = strchr(NNTPbuffer, '\n'); + if (ptr) + *ptr = '\0'; + va_end(ap); + return atoi(NNTPbuffer); +} + +char * +tcpmessage() +{ + char *ptr; + + ptr = strchr(NNTPbuffer, ' '); + if (ptr) + return ptr; + return NNTPbuffer; +} + +read_article(lover, filename, userid) + linkoverview_t *lover; + char *filename, *userid; +{ + FILE *fp; + int fd; + struct stat st; + time_t mtime; + char *buffer; + char *artptr, *artend, *artback; + + if (stat(filename, &st) != 0) + return 0; + lover->mtime = st.st_mtime; + fd = open(filename, O_RDONLY); + if (fd < 0) + { + bbslog("<bbslink> Err: can't open %s\n", filename); + return 0; + } + + if (FD_BUF == NULL) + { + FD_BUF = mymalloc(st.st_size + 1 + strlen(COMMENT)); + } + else + { + FD_BUF = myrealloc(FD_BUF, st.st_size + 1 + strlen(COMMENT)); + } + FD_BUF[st.st_size] = '\0'; + read(fd, FD_BUF, st.st_size); + sprintf(FD_BUF + st.st_size, "%s", COMMENT); + st.st_size += strlen(COMMENT); + FD_SIZE = st.st_size; + for (buffer = FD_BUF, artend = FD_BUF + st.st_size, + artback = strchr(buffer, '\n'); + buffer && buffer < artend && *buffer; + artback = strchr(buffer, '\n') + ) + { + /* while( fgets(buffer, sizeof buffer, fp) != NULL) { */ + char *m, *n; + char *ptr; + + if (artback != NULL) + *artback = '\0'; + if (*buffer == '\0') + break; + +#ifndef MapleBBS + if (strstr(buffer, userid) != NULL) + { + m = strchr(buffer, '('); + n = strrchr(buffer, ')'); + if (m != NULL && n != NULL) + { + strncpy(lover->nickname, m + 1, n - m - 1); + lover->nickname[n - m - 1] = '\0'; + } + else + { + *lover->nickname = '\0'; + } + } + else if (strncmp(buffer, "Date: ", 11) == 0) + { + strcpy(lover->date, buffer + 11); + } + else if (strncmp(buffer, "µo«H¯¸: ", 8) == 0) + { + m = strchr(buffer, '('); + n = strrchr(buffer, ')'); + strncpy(lover->date, m + 1, n - m - 1); + lover->date[n - m - 1] = '\0'; + } +#endif + + if (artback != NULL) + { + *artback = '\n'; + buffer = artback + 1; + } + else + { + break; + } + } + if (artback != NULL) + BODY = artback + 1; + else + BODY = ""; + close(fd); + return 1; +} + +save_outgoing(sover, filename, userid, poster, mtime) + soverview_t *sover, *filename, *userid, *poster; + time_t mtime; +{ + newsfeeds_t *nf; + char *group, *server, *serveraddr; + char *subject, *path; + char *board; + char *ptr1, *ptr2; + + board = sover->board; + + PATH = MYBBSID; + nf = (newsfeeds_t *) search_board(board); + if (nf == NULL) + { + bbslog("<bbslink> save_outgoing: No such board %s\n", board); + return; + } + else + { + group = nf->newsgroups; + server = nf->path; + } + if (!server || !*server) + { + sprintf(PATH_BUF, "%.*s (local)", sizeof PATH_BUF - 9, MYBBSID); + PATH = PATH_BUF; + serveraddr = ""; + sover->path = PATH; + } + for (ptr1 = server; ptr1 && *ptr1;) + { + nodelist_t *nl; + char savech; + + for (; *ptr1 && isspace(*ptr1); ptr1++); + if (!*ptr1) + break; + for (ptr2 = ptr1; *ptr2 && !isspace(*ptr2); ptr2++); + savech = *ptr2; + *ptr2 = '\0'; + nl = (nodelist_t *) search_nodelist_bynode(ptr1); + *ptr2 = savech; + ptr1 = ptr2++; + if (nl == NULL) + continue; + /* if (nl->feedfp == NULL) continue; */ + + if (nl->host && *nl->host) + { + if (nl->feedfp == NULL) + { + nl->feedfp = fopen(fileglue("%s/%s.link", INNDHOME, nl->node), "a"); + if (nl->feedfp == NULL) + { + bbslog("<save outgoing> append failed for %s/%s.link", INNDHOME, nl->node); + } + } + if (nl->feedfp != NULL) + { + flock(fileno(nl->feedfp), LOCK_EX); + fprintf(nl->feedfp, "%s\t%s\t%s\t%ld\t%s\t%s\n", sover->board, filename, group, mtime, FROM, sover->subject); + fflush(nl->feedfp); + flock(fileno(nl->feedfp), LOCK_UN); + } + } + if (savech == '\0') + break; + } +} + + +#ifndef MapleBBS +save_article(board, filename, sover) + char *board, *filename; + soverview_t *sover; +{ + FILE *FN; + + if (Verbose) + printf("<save_article> %s %s\n", board, filename); + FN = fopen(fileglue("%s/boards/%s/%s", BBSHOME, board, filename), "w"); + if (FN == NULL) + { + bbslog("<save_article> err: %s %s\n", board, filename); + if (Verbose) + printf("<save_article> err: %s %s\n", board, filename); + return 0; + } + flock(fileno(FN), LOCK_EX); + fprintf(FN, "µo«H¤H: %s, «H°Ï: %s\n", POSTER, sover->board); + fprintf(FN, "¼Ð ÃD: %s\n", sover->subject); + fprintf(FN, "µo«H¯¸: %s (%s)\n", MYSITE, sover->date); + fprintf(FN, "Âà«H¯¸: %s\n", sover->path); + fprintf(FN, "\n"); + fputs(BODY, FN); + flock(fileno(FN), LOCK_UN); + fclose(FN); + +#if defined(PalmBBS) + { + struct utimbuf times; + + times.actime = sover->mtime; + times.modtime = sover->mtime; + utime(fileglue("%s/boards/%s/%s", BBSHOME, board, filename), ×); + utime(fileglue("%s/.bcache/%s", BBSHOME, board), NULL); + } +#endif +} +#endif + +/* process_article() read_article() save_outgoing() save_article() */ + +process_article(board, filename, userid, nickname, subject) + char *board, *filename, *userid, *nickname, *subject; +{ + char *n, *filepath; + char poster[MAXBUFLEN]; + soverview_t sover; + + if (!*userid) + { + return; + } + else if (!subject || !*subject) + { + subject = "µLÃD"; + } + filepath = fileglue("%s/boards/%s/%s", BBSHOME, board, filename); + if (isfile(filepath)) + { + linkoverview_t lover; + + if (read_article(&lover, filepath, userid)) + { + +#ifndef MapleBBS + strncpy(POSTER_BUF, fileglue("%s@%s (%s)", userid, MYBBSID, nickname), sizeof POSTER_BUF); + POSTER = POSTER_BUF; +#endif + + strncpy(FROM_BUF, fileglue("%s.bbs@%s (%s)", userid, MYADDR, nickname), sizeof FROM_BUF); + FROM = FROM_BUF; + sover.from = FROM; + sover.board = board; + sover.subject = subject; + PATH = MYBBSID; + sover.path = MYBBSID; + sover.date = lover.date; + sover.mtime = lover.mtime; + if (!VisitOnly) + { + save_outgoing(&sover, filename, userid, poster, lover.mtime); + +#ifndef MapleBBS + save_article(board, filename, &sover); +#endif + } + } + } +} + + +char * +baseN(val, base, len) + int val, base, len; +{ + int n, ans; + static char str[MAXBUFLEN]; + char *pstr = str; + int index; + + for (index = len - 1; index >= 0; index--) + { + n = val % base; + val /= base; + if (n < 10) + { + n += '0'; + } + else if (n < 36) + { + n += 'A' - 10; + } + else if (n < 62) + { + n += 'a' - 36; + } + else + { + n = '_'; + } + str[index] = n; + } + str[len] = '\0'; + return str; +} + +char * +hash_value(str) + char *str; +{ + int val, n; + char *ptr; + + if (*str) + ptr = str + strlen(str) - 1; + else + ptr = str; + val = 0; + while (ptr >= str) + { + n = *ptr; + val = (val + n * 0x100) ^ n; + ptr--; + } + return baseN(val, 64, 3); +} + +/* process_cancel() save_outgoing() hash_value(); baseN(); ascii_date(); */ + + +read_outgoing(sover) + soverview_t *sover; +{ + char *board, *filename, *group, *from, *subject, *outgoingtype, *msgid, *path; + char *buffer, *bufferp; + FILE *ECHOMAIL, *FN; + char *hash; + char times[MAXBUFLEN]; + time_t mtime; + + board = sover->board; + filename = sover->filename; + group = sover->group; + mtime = sover->mtime; + from = sover->from; + subject = sover->subject; + outgoingtype = sover->outgoingtype; + msgid = sover->msgid; + path = sover->path; + if (Verbose) + { + printf("<read_outgoing> %s:%s:%s\n", board, filename, group); + printf(" => %ld:%s\n", mtime, from); + printf(" => %s\n", subject); + printf(" => %s:%s\n", outgoingtype, msgid); + printf(" => %s\n", path); + } + if (NEWSFEED == LOCAL) + { + char *end = strrchr(filename, '.'); + + if (end) + *end = '\0'; + strncpy(times, baseN(atol(filename + 2), 48, 6), sizeof times); + if (end) + *end = '.'; + hash = hash_value(fileglue("%s.%s", filename, board)); + sprintf(MSGID_BUF, "%s$%s@%s", times, hash, MYADDR); + } + else + { + strncpy(MSGID_BUF, msgid, sizeof MSGID_BUF); + } + sover->msgid = MSGID; + if (mtime == -1) + { + static char BODY_BUF[MAXBUFLEN]; + + strncpy(BODY_BUF, fileglue("%s\r\n", subject), sizeof BODY_BUF); + BODY = BODY_BUF; + sprintf(SUBJECT_BUF, "cmsg cancel <%s>", MSGID); + SUBJECT = SUBJECT_BUF; + sprintf(CONTROL_BUF, "cancel <%s>", MSGID); + CONTROL = CONTROL_BUF; + strncpy(MSGID_BUF, fileglue("%d.%s", getpid(), MSGID_BUF), sizeof MSGID_BUF); + sprintf(DATE_BUF, "%s", ascii_date(time(NULL))); + DATE = DATE_BUF; + sover->subject = SUBJECT; + sover->control = CONTROL; + sover->msgid = MSGID; + sover->date = DATE; + } + else + { + sover->control = CONTROL; + sover->date = DATE_BUF; + DATE = DATE_BUF; + *CONTROL = '\0'; + sprintf(DATE, "%s", ascii_date((mtime))); + if (NEWSFEED == LOCAL && !NoAction) + { + SITE = MYSITE; + PATH = MYBBSID; + GROUPS = group; + +#ifndef MapleBBS + echomaillog(); +#endif + } + BODY = ""; + FD = open(fileglue("%s/boards/%s/%s", BBSHOME, board, filename), O_RDONLY); + if (FD < 0) + { + if (Verbose) + printf(" !! can't open %s/boards/%s/%s\n", BBSHOME, board, filename); + else + fprintf(stderr, "can't open %s/boards/%s/%s\n", BBSHOME, board, filename); + return -1; + } + + FD_SIZE = filesize(fileglue("%s/boards/%s/%s", BBSHOME, board, filename)); + if (FD_BUF == NULL) + { + FD_BUF = (char *) mymalloc(FD_SIZE + 1 + strlen(COMMENT)); + } + else + { + FD_BUF = (char *) myrealloc(FD_BUF, FD_SIZE + 1 + strlen(COMMENT)); + } + FD_END = FD_BUF + FD_SIZE; + *FD_END = '\0'; + read(FD, FD_BUF, FD_SIZE); + sprintf(FD_END, "%s", COMMENT); + FD_SIZE += strlen(COMMENT); + FD_END += strlen(COMMENT); + if (Verbose) + { + printf("<read in> %s/boards/%s/%s\n", BBSHOME, board, filename); + } + + *ORGANIZATION = '\0'; + *NEWSCONTROL = '\0'; + *NEWSAPPROVED = '\0'; + *NNTPHOST_BUF = '\0'; + NNTPHOST = NULL; + + for (buffer = FD_BUF, bufferp = strchr(buffer, '\n'); + buffer && *buffer; bufferp = strchr(buffer, '\n')) + { + if (bufferp) + *bufferp = '\0'; + if (*buffer == '\0') + { + break; + } + /* printf("get buffer %s\n", buffer); */ + if (NEWSFEED == REMOTE) + { + if (strncmp(buffer, "Date: ", 11) == 0) + { + strcpy(DATE_BUF, buffer + 11); + DATE = DATE_BUF; + } + else if (strncmp(buffer, "µo«H¯¸: ", 8) == 0) + { + char *m, *n; + + m = strchr(buffer, '('); + n = strrchr(buffer, ')'); + if (m && n) + { + strncpy(DATE_BUF, m + 1, n - m - 1); + DATE_BUF[n - m - 1] = '\0'; + DATE = DATE_BUF; + strncpy(ORGANIZATION, buffer + 8, m - 8 - buffer - 1); + ORGANIZATION[m - 8 - buffer - 1] = '\0'; + } + } + else if (strncmp(buffer, "Control: ", 9) == 0) + { + strcpy(NEWSCONTROL, buffer + 9); + } + else if (strncmp(buffer, "Approved: ", 10) == 0) + { + strcpy(NEWSAPPROVED, buffer + 10); + } + else if (strncmp(buffer, "Origin: ", 8) == 0) + { + strcpy(NNTPHOST_BUF, buffer + 8); + NNTPHOST = NNTPHOST_BUF; + } + } + if (bufferp) + { + *bufferp = '\n'; + buffer = bufferp + 1; + } + else + { + break; + } + } + if (bufferp) + { + BODY = bufferp + 1; + } + else + BODY = ""; + if (bufferp) + for (buffer = bufferp + 1, bufferp = strchr(buffer, '\n'); + buffer && *buffer; bufferp = strchr(buffer, '\n')) + { + if (bufferp) + *bufferp = '\0'; + /* printf("get line (%s)\n", buffer); */ + /* if( strcmp(buffer,".")==0 ) { buffer[1]='.'; buffer[2]='\0'; } */ + if (NEWSFEED == REMOTE && + strncmp(NEWSCONTROL, "cancel", 5) == 0 && + strncmp(buffer, "------------------", 18) == 0) + { + break; + } + /* $BODY[ @BODY ] = "$_\r\n"; */ + if (bufferp) + { + *bufferp = '\n'; + buffer = bufferp + 1; + } + else + { + break; + } + } + /* # fprintf("BODY @BODY\n"; */ + close(FD); + } + return 0; +} + +#ifdef TEST +#endif + +openfeed(node) + nodelist_t *node; +{ + if (node->feedfp == NULL) + { + node->feedfp = fopen(fileglue("%s/%s.link", INNDHOME, node->node), "a"); + } +} + +queuefeed(node, textline) + nodelist_t *node; + char *textline; +{ + openfeed(node); + if (node->feedfp != NULL) + { + flock(fileno(node->feedfp), LOCK_EX); + fprintf(node->feedfp, "%s", textline); + fflush(node->feedfp); + flock(fileno(node->feedfp), LOCK_UN); + } +} + +post_article(node, site, sover, textline) + nodelist_t *node; + char *site; + soverview_t *sover; + char *textline; +{ + int status; + char *filename = sover->filename; + char *msgid = sover->msgid; + char *board = sover->board; + char *bodyp, *body; + + if (Verbose) + fprintf(stdout, "<post_article> %s %s %s\n", site, filename, msgid); + if (NoAction && Verbose) + { + printf(" ==>%s\n", sover->path); + printf(" ==>%s:%s\n", sover->from, sover->group); + printf(" ==>%s:%s\n", sover->subject, sover->date); + body = BODY; + bodyp = strchr(body, '\n'); + if (bodyp) + *bodyp = '\0'; + printf(" ==>%s\n", body); + if (bodyp) + *bodyp = '\n'; + if (bodyp) + { + body = bodyp + 1; + bodyp = strchr(body, '\n'); + if (bodyp) + *bodyp = '\0'; + printf(" ==>%s\n", body); + if (bodyp) + *bodyp = '\n'; + } + } + if (NoAction) + return 1; + if (NEWSFEED == REMOTE) + { + fprintf(NNTPwfp, "Path: %s\r\n", sover->path); + fprintf(NNTPwfp, "From: %s\r\n", sover->from); + fprintf(NNTPwfp, "Newsgroups: %s\r\n", sover->group); + fprintf(NNTPwfp, "Subject: %s\r\n", sover->subject); + /* # fprintf( NNTPwfp,"Post with subject ($subject)\n"); */ + fprintf(NNTPwfp, "Date: %s\r\n", sover->date); + if (*ORGANIZATION) + fprintf(NNTPwfp, "Organization: %s\r\n", ORGANIZATION); + fprintf(NNTPwfp, "Message-ID: <%s>\r\n", sover->msgid); + if (*NEWSCONTROL) + fprintf(NNTPwfp, "Control: %s\r\n", NEWSCONTROL); + if (*NEWSAPPROVED) + fprintf(NNTPwfp, "Approved: %s\r\n", NEWSAPPROVED); + } + else + { + fprintf(NNTPwfp, "Path: %s\r\n", MYBBSID); + fprintf(NNTPwfp, "From: %s\r\n", sover->from); + fprintf(NNTPwfp, "Newsgroups: %s\r\n", sover->group); + fprintf(NNTPwfp, "Subject: %s\r\n", sover->subject); + fprintf(NNTPwfp, "Date: %s\r\n", sover->date); + fprintf(NNTPwfp, "Organization: %s\r\n", MYSITE); + fprintf(NNTPwfp, "Message-ID: <%s>\r\n", sover->msgid); + fprintf(NNTPwfp, "X-Filename: %s/%s\r\n", sover->board, sover->filename); + } + if (NNTPHOST && *NNTPHOST && USEIHAVE) + fprintf(NNTPwfp, "NNTP-Posting-Host: %s\r\n", NNTPHOST); + else if (NNTPHOST && *NNTPHOST) + fprintf(NNTPwfp, "X-Auth-From: %s\r\n", NNTPHOST); + if (*CONTROL) + { + fprintf(NNTPwfp, "Control: %s\r\n", CONTROL); + } + fputs("\r\n", NNTPwfp); + for (body = BODY, bodyp = strchr(body, '\n'); + body && *body; bodyp = strchr(body, '\n')) + { + if (bodyp) + *bodyp = '\0'; + + fputs(body, NNTPwfp); + if (body[0] == '.' && body[1] == '\0') + fputs(".", NNTPwfp); + fputs("\r\n", NNTPwfp); + if (bodyp) + { + *bodyp = '\n'; + body = bodyp + 1; + } + else + { + break; + } + } + /* print "send out @BODY\n"; */ + status = tcpcommand("."); + /* 435 duplicated article 437 invalid header */ + + if (USEIHAVE) + { + if (status == 235) + { + if (NEWSFEED == LOCAL) + { + bbslog("Sendout <%s> from %s/%s\n", msgid, board, filename); + } + } + else if (status == 437 || status == 435) + { + bbslog("<bbslink> :Warn: %d %s <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s <%s>\n", status, (char *) tcpmessage(), msgid); + return 0; + } + else + { + bbslog("<bbslink> :Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + queuefeed(node, textline); + return 0; + } + } + else if (USEPOST) + { + if (status == 240) + { + bbslog("Sendout <%s> from %s/%s\n", msgid, board, filename); + } + else + { + bbslog("<bbslink> :Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + queuefeed(node, textline); + return 0; + } + } + else + { + if (status == 250) + { + bbslog("<bbslink> DATA Sendout <%s> from %s/%s\n", msgid, board, filename); + if (Verbose) + printf("<DATA Sendout> <%s> from %s/%s\n", msgid, board, filename); + } + else + { + bbslog("<bbslink> :Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s of <%s>\n", status, (char *) tcpmessage(), msgid); + queuefeed(node, textline); + return 0; + } + } + return 1; +} + +process_cancel(board, filename, userid, nickname, subject) + char *board, *filename, *userid, *nickname, *subject; +{ + time_t mtime; + soverview_t sover; + + if (!userid || !*userid) + { + return; + } + mtime = -1; + strncpy(FROM_BUF, fileglue("%s.bbs@%s (%s)", userid, MYADDR, nickname), sizeof FROM_BUF); + FROM = FROM_BUF; + sover.from = FROM; + sover.board = board; + sover.subject = subject; + PATH = MYBBSID; + sover.path = MYBBSID; + /* save_outgoing(&sover, filename, userid, poster, -1); */ + save_outgoing(&sover, filename, userid, userid, -1); +} + +open_link(hostname, hostprot, hostport) + char *hostname, *hostprot, *hostport; +{ + USEIHAVE = 1; + USEPOST = 0; + USEDATA = 0; + FEEDTYPE = ' '; + if (Verbose) + printf("<OPEN_link> %s %s %s\n", hostname, hostprot, hostport); + if (strncasecmp(hostprot, "IHAVE", 5) != 0) + { + USEIHAVE = 0; + USEPOST = 1; + if (strncasecmp(hostprot, "POST", 4) == 0) + { + USEPOST = 1; + } + else if (strncasecmp(hostprot, "DATA", 4) == 0) + { + USEPOST = 0; + USEDATA = 1; + } + } + + FEEDTYPE = hostname[0]; + if (!USEDATA) + { + char *atsign; + + if (FEEDTYPE == '-' || FEEDTYPE == '+') + { + hostname = hostname + 1; + } + atsign = strchr(hostname, '@'); + if (atsign != NULL) + { + hostname = atsign + 1; + } + if (!NoAction) + { + if (Verbose) + printf("<inetclient> %s %s\n", hostname, hostport); + if ((NNTP = inetclient(hostname, hostport, "tcp")) < 0) + { + bbslog("<bbslink> :Err: server %s %s error: cant connect\n", hostname, hostport); + if (Verbose) + printf(":Err: server %s %s error: cant connect\n", hostname, hostport); + return 0; + /* exit( 0 ); */ + /* return; */ + } + NNTPrfp = fdopen(NNTP, "r"); + NNTPwfp = fdopen(NNTP, "w"); + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + if (atoi(NNTPbuffer) != 200) + { + bbslog("<bbslink> :Err: server error: %s", NNTPbuffer); + if (Verbose) + printf(":Err: server error: %s", NNTPbuffer); + return 0; + /* exit( 0 ); */ + } + } + else + { + if (Verbose) + printf("<inetclient> %s %s\n", hostname, hostport); + } + } + else + { + if (!NoAction) + { + if (Verbose) + printf("<inetclient> localhost %s\n", hostport); + if ((NNTP = inetclient("localhost", hostport, "tcp")) < 0) + { + bbslog("<bbslink> :Err: server %s port %s error: cant connect\n", hostname, hostport); + if (Verbose) + printf(":Err: server error: cant connect"); + return 0; + /* exit( 0 ); */ + /* return; */ + } + NNTPrfp = fdopen(NNTP, "r"); + NNTPwfp = fdopen(NNTP, "w"); + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + if (strncmp(NNTPbuffer, "220", 3) != 0) + { + bbslog("<bbslink> :Err: server error: %s", NNTPbuffer); + if (Verbose) + printf(":Err: server error: %s", NNTPbuffer); + return 0; + /* exit( 0 ); */ + } + if (strncmp(NNTPbuffer, "220-", 4) == 0) + { + fgets(NNTPbuffer, sizeof NNTPbuffer, NNTPrfp); + } + } + else + { + if (Verbose) + printf("<inetclient> %s %s\n", hostname, hostport); + } + } + return 1; +} + +send_outgoing(node, site, hostname, sover, textline) + nodelist_t *node; + soverview_t *sover; + char *hostname, *site; + char *textline; +{ + int status; + char *board, *filepath, *msgid; + int returnstatus = 0; + + board = sover->board; + filepath = sover->filename; + msgid = sover->msgid; + + if (Verbose) + printf("<send_outgoing> %s:%s:%s:%s\n", site, board, filepath, msgid); + if (BODY != NULL && !NoAction) + { + if (USEIHAVE) + { + status = tcpcommand("IHAVE <%s>", msgid); + if (status == 335) + { + returnstatus = post_article(node, site, sover, textline); + } + else if (status == 435) + { + bbslog("<bbslink> :Warn: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + returnstatus = 0; + } + else + { + bbslog("<bbslink> :Err: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s, IHAVE <%s>\n", status, (char *) tcpmessage(), msgid); + queuefeed(node, textline); + returnstatus = 0; + } + } + else if (USEPOST) + { + tcpcommand("MODE READER"); + status = tcpcommand("POST"); + if (status == 340) + { + returnstatus = post_article(node, site, sover, textline); + } + else if (status == 441) + { + bbslog("<bbslink> :Warn: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Warn: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + returnstatus = 0; + } + else + { + bbslog("<bbslink> :Err: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s, POST <%s>\n", status, (char *) tcpmessage(), msgid); + queuefeed(node, textline); + returnstatus = 0; + } + } + else + { + tcpcommand("HELO"); + tcpcommand("MAIL FROM: bbs"); + tcpcommand("RCPT TO: %s", hostname); + status = tcpcommand("DATA"); + if (status == 354) + { + returnstatus = post_article(node, site, sover, textline); + } + else + { + bbslog("<bbslink> :Err: %d %s, DATA <%s>\n", status, (char *) tcpmessage(), msgid); + if (Verbose) + printf(":Err: %d %s, DATA <%s>\n", status, (char *) tcpmessage(), msgid); + + queuefeed(node, textline); + returnstatus = 0; + } + } + } + else if (NoAction) + { + returnstatus = post_article(node, site, sover, textline); + } + return returnstatus; +} + +save_nntplink(node, overview) + nodelist_t *node; + char *overview; +{ + FILE *POSTS; + char buffer[1024]; + + openfeed(node); + POSTS = fopen(overview, "r"); + if (POSTS == NULL) + return 0; + openfeed(node); + /* if (node->feedfp == NULL) return 0; */ + flock(fileno(node->feedfp), LOCK_EX); + while (fgets(buffer, sizeof buffer, POSTS) != NULL) + { + fputs(buffer, node->feedfp); + fflush(node->feedfp); + } + flock(fileno(node->feedfp), LOCK_UN); + fclose(POSTS); + if (Verbose) + printf("<Unlinking> %s\n", overview); + if (!NoAction) + unlink(overview); + return 1; +} + + +char * +get_tmpfile(tmpfile) + char *tmpfile; +{ + FILE *FN; + static char result[256]; + + FN = fopen(tmpfile, "r"); + fgets(result, sizeof result, FN); + fclose(FN); + unlink(tmpfile); + return (result); +} + +/* cancel moderating posts */ + +cancel_outgoing(board, filename, from, subject) + char *board, *filename, *from, *subject; +{ + char *base, filepath[MAXPATHLEN]; + FILE *FN; + char *result; + char TMPFILE[MAXPATHLEN]; + + if (Verbose) + { + printf("<cancel_outgoing> %s %s %s %s\n", board, filename, from, subject); + } + + sprintf(TMPFILE, "/tmp/cancel_outgoing.%d.%d", getuid(), getpid()); + + bbslog("<cancel_outgoing> Try to move moderated post from %s to deleted\n", board); + if (Verbose) + printf("Try to move moderated post from %s to deleted\n", board); + FN = popen(fileglue("%s/bbspost post %s/boards/deleted > %s", + INNDHOME, BBSHOME, TMPFILE), "w"); + if (FN == NULL) + { + bbslog("<cancel_outgoing> can't run %s/bbspost\n", INNDHOME); + if (Verbose) + printf("<cancel_outgoing> can't run %s/bbspost\n", INNDHOME); + return 0; + } + fprintf(FN, "%s\n", from); + fprintf(FN, "%s\n", subject); + fprintf(FN, "µo«H¤H: %s, «H°Ï: %s\n", from, board); + fprintf(FN, "¼Ð ÃD: %s\n", subject); + fprintf(FN, "µo«H¯¸: %s (%s)\n", MYSITE, DATE); + fprintf(FN, "Âà«H¯¸: %s\n", MYBBSID); + fputs("\n", FN); + fputs(BODY, FN); + pclose(FN); + result = (char *) get_tmpfile(TMPFILE); + if (strncmp(result, "post to ", 8) == 0) + { + /* try to remove it */ + strncpy(filepath, fileglue("%s/boards/%s/%s", BBSHOME, board, filename), sizeof filepath); + if (isfile(filepath)) + { + Rename(filepath, fileglue("%s.cancel", filepath)); + } + FN = fopen(filepath, "w"); + + fprintf(FN, "µo«H¤H: %s, «H°Ï: %s\n", from, board); + fprintf(FN, "¼Ð ÃD: <article cancelled and mailed to the moderator\n"); + fprintf(FN, "µo«H¯¸: %s (%s)\n", MYSITE, DATE); + fprintf(FN, "Âà«H¯¸: %s\n", MYBBSID); + fprintf(FN, "\n"); + fputs("\n", FN); + fprintf(FN, "§Aªº¤å³¹ \"%s\" ¤w¸g°e©¹¼f®Ö¤¤. ½Ðµ¥«Ý¦^ÂÐ.\n", subject); + fputs("\n", FN); + fputs("Your post has been sent to the moderator and move\n", FN); + fputs("into the deleted board. If the post accepted by the moderator,\n", FN); + fputs("it will be posted in this board again. Please wait.\n", FN); + + } + else + { + bbslog("%s", result); + } + + bbslog("%s/bbspost cancel %s %s %s moderate\n", INNDHOME, BBSHOME, board, filename); + if (Verbose) + printf("%s/bbspost cancel %s %s %s moderate\n", INNDHOME, BBSHOME, board, filename); + system(fileglue("%s/bbspost cancel %s %s %s moderate", + INNDHOME, BBSHOME, board, filename)); + return 1; +} + +/* + * send_nntplink open_link read_outgoing send_outgoing post_article + * cancel_outgoing + */ +send_nntplink(node, site, hostname, hostprot, hostport, overview, nlcount) + nodelist_t *node; + char *site, *hostname, *hostprot, *hostport, *overview; + int nlcount; +{ + FILE *POSTS; + char textline[1024]; + char baktextline[1024]; + char *filepath; + int status; + + if (Verbose) + { + printf("<send nntplink> %s %s %s %s\n", site, hostname, hostprot, hostport); + printf(" ==> %s\n", overview); + } + if (!open_link(hostname, hostprot, hostport)) + { + save_nntplink(node, overview); + return 0; + } + POSTS = fopen(overview, "r"); + if (POSTS == NULL) + { + if (Verbose) + printf("open %s failed\n", overview); + return 0; + } + while (fgets(textline, sizeof textline, POSTS) != NULL) + { + char *linebreak = strchr(textline, '\n'); + char *ptr; + char *board, *filename, *subject, *group, *mtime, *from; + char *outgoingtype; + char *msgid, *path; + soverview_t soverview; + + strcpy(baktextline, textline); + if (linebreak) + *linebreak = '\0'; + + board = "", filename = "", mtime = "", group = "", from = "", subject = ""; + outgoingtype = "", msgid = "", path = ""; + /* get board field */ + board = textline; + ptr = strchr(textline, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* filename field */ + filename = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* group field */ + group = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* mtime field */ + mtime = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* from field */ + from = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* subject */ + subject = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + *ptr++ = '\0'; + + /* outgoing type field */ + outgoingtype = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + *ptr++ = '\0'; + + /* msgid */ + msgid = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + *ptr++ = '\0'; + + /* path */ + path = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + goto try_read_outgoing; + +try_read_outgoing: + + NEWSFEED = LOCAL; + if (outgoingtype && msgid && path && *outgoingtype && *msgid && *path) + { + char *left, *right; + + NEWSFEED = REMOTE; + left = strchr(msgid, '<'); + right = strrchr(msgid, '>'); + if (left) + msgid = left + 1; + if (right) + *right = '\0'; + } + soverview.board = board; + soverview.filename = filename; + soverview.group = group; + soverview.mtime = atol(mtime); + soverview.from = from; + soverview.subject = subject; + soverview.outgoingtype = outgoingtype; + soverview.msgid = msgid; + soverview.path = path; + if (read_outgoing(&soverview) == 0) + { + int sendresult = send_outgoing(node, site, hostname, &soverview, baktextline); + int sendfailed = 1 - sendresult; + + if (NEWSFEED == REMOTE) + { + BBSLINK_STAT[nlcount].remotesendout += sendresult; + BBSLINK_STAT[nlcount].remotefailed += sendfailed; + } + else + { + BBSLINK_STAT[nlcount].localsendout += sendresult; + BBSLINK_STAT[nlcount].localfailed += sendfailed; + } + if (node->feedtype == '-') + { + if (!NoAction && sendresult) + cancel_outgoing(board, filename, from, subject); + } + } + } + fclose(POSTS); + close_link(); + if (Verbose) + printf("<Unlinking> %s\n", overview); + if (!NoAction) + unlink(overview); +} + +close_link() +{ + int status; + + if (Verbose) + printf("<close_link>\n"); + if (NoAction) + return; + status = tcpcommand("QUIT"); + if (status != 205 && status != 221) + { + bbslog("<bbslink> :Err: Cannot quit message '%d %s'\n", status, (char *) tcpmessage()); + if (Verbose) + printf(":Err: Cannot quit message '%d %s'\n", status, (char *) tcpmessage()); + } + fclose(NNTPwfp); + fclose(NNTPrfp); + close(NNTP); +} + + +/* + * send_article() send_nntplink() read_outgoing() + * + */ + +send_article() +{ + char *site, *addr, *protocol, *port, *op; + char *nntphost; + int nlcount; + + chdir(INNDHOME); + + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + nodelist_t *node; + char linkfile[MAXPATHLEN]; + char sendfile[MAXPATHLEN]; + char feedfile[MAXPATHLEN]; + char feedingfile[MAXPATHLEN]; + char protocol[MAXBUFLEN], port[MAXBUFLEN]; + + node = NODELIST + nlcount; + site = node->node; + nntphost = node->host; + op = node->protocol; + + if (DefaultFeedSite && *DefaultFeedSite) + { + if (strcmp(node->node, DefaultFeedSite) != 0) + continue; + } + + if (op && (strncasecmp(op, "ihave", 5) == 0 || + strncasecmp(op, "post", 4) == 0 || + strncasecmp(op, "data", 4) == 0)) + { + char *left, *right; + + left = strchr(op, '('), right = strrchr(op, ')'); + if (left && right) + { + *left = '\0'; + *right = '\0'; + strncpy(protocol, op, sizeof protocol); + strncpy(port, left + 1, sizeof port); + *left = '('; + *right = ')'; + } + else + { + strncpy(protocol, op, sizeof protocol); + strncpy(port, "nntp", sizeof port); + } + } + else + { + strcpy(protocol, "IHAVE"); + strcpy(port, "nntp"); + } + sprintf(linkfile, "%s.link", site); + sprintf(sendfile, "%s.sending", site); + sprintf(feedfile, "%s.feed", site); + sprintf(feedingfile, "%s.feeding", site); + if (isfile(sendfile) && !iszerofile(sendfile)) + { + if (bbslink_get_lock(sendfile)) + { + send_nntplink(node, site, nntphost, protocol, port, sendfile, nlcount); + bbslink_un_lock(sendfile); + } + } + if (isfile(linkfile) && !iszerofile(linkfile)) + { + if (!NoAction) + { + if (bbslink_get_lock(sendfile) && bbslink_get_lock(linkfile) && + bbslink_get_lock(feedingfile)) + { + if (isfile(sendfile) && !iszerofile(sendfile)) + { + save_nntplink(node, sendfile); + } + if (node->feedfp) + { + fclose(node->feedfp); + node->feedfp = NULL; + } + Rename(linkfile, sendfile); + send_nntplink(node, site, nntphost, protocol, port, sendfile, nlcount); + bbslink_un_lock(linkfile); + bbslink_un_lock(sendfile); + bbslink_un_lock(feedingfile); + } + } + else + { + send_nntplink(node, site, nntphost, protocol, port, linkfile, nlcount); + } + } + if (isfile(feedingfile) && !iszerofile(feedingfile)) + { + if (bbslink_get_lock(feedingfile)) + { + send_nntplink(node, site, nntphost, protocol, port, feedingfile, nlcount); + bbslink_un_lock(feedingfile); + } + } + if (isfile(feedfile) && !iszerofile(feedfile)) + { + if (!NoAction) + { + if (bbslink_get_lock(feedfile) && bbslink_get_lock(feedingfile)) + { + if (isfile(feedingfile) && !iszerofile(feedingfile)) + { + save_nntplink(node, feedingfile); + if (node->feedfp) + { + fclose(node->feedfp); + node->feedfp = NULL; + } + } + Rename(feedfile, feedingfile); + system(fileglue("%s/ctlinnbbsd reload > /dev/null", INNDHOME)); + send_nntplink(node, site, nntphost, protocol, port, feedingfile, nlcount); + bbslink_un_lock(feedfile); + bbslink_un_lock(feedingfile); + } + } + else + { + send_nntplink(node, site, nntphost, protocol, port, feedfile, nlcount); + } + } + } +} + +/* bntplink() bbspost() process_article() process_cancel() send_article() */ + + +show_usage(argv) + char *argv; +{ + fprintf(stderr, "%s initialization failed or improper options !!\n", argv); +/* +woju +*/ + fprintf(stderr, "Usage: %s [options] bbs_home board\n", argv); + fprintf(stderr, " -v (show transmission status)\n"); + fprintf(stderr, " -n (dont send out articles and leave queue untouched)\n"); + fprintf(stderr, " -s site (only process articles sent to site)\n"); + fprintf(stderr, " -V (visit only: bbspost visit)\n"); + fprintf(stderr, " -N (no visit, and only process batch queue)\n"); + fprintf(stderr, " -k (kill the former bbslink process before started)\n\n"); + fprintf(stderr, "¥»µ{¦¡n¥¿±`°õ¦æ¥²¶·±N¥H¤UÀɮ׸m©ó %s/innd ¤U:\n", BBSHOME); + fprintf(stderr, "bbsname.bbs ³]©w¶Q¯¸ªº BBS ID (½Ð¾¨¶q²µu)\n"); + fprintf(stderr, "nodelist.bbs ³]©wºô¸ô¦U BBS ¯¸ªº ID, Address ©M fullname\n"); + fprintf(stderr, "newsfeeds.bbs ³]©wºô¸ô«H¥óªº newsgroup board nodelist ...\n"); +} + + +/* +woju +*/ +struct fileheader +{ + char filename[33]; /* M.9876543210.A */ + char savemode; /* file save mode */ + char owner[12 + 2]; /* uid[.] */ + char date[6]; /* [02/02] or space(5) */ + char title[72+ 1]; + unsigned char filemode; /* must be last field @ boards.c */ +}; +typedef struct fileheader fileheader; + + +bntplink(argc, argv) + int argc; + char **argv; +{ +/* +woju + static char *OUTING = ".outing"; +*/ + static char OUTING[MAXPATHLEN]; + fileheader fhdr; + char *fname, *s1, *s2; + char nick[100]; + FILE* fp; + + nodelist_t *nl; + int linkport; + char result[4096]; + char cancelfile[MAXPATHLEN], cancelpost[MAXPATHLEN]; + char bbslink_lockfile[MAXPATHLEN]; + FILE *NEWPOST; + char *left, *right; + int nlcount; + + strcpy(BBSHOME, argv[0]); +/* +woju +*/ + sprintf(OUTING, "%s/boards/%s/", BBSHOME, argv[1]); + fname = OUTING + strlen(OUTING); + + if (initial_bbs("link") == 0) + { + return -1; + } + + BBSLINK_STAT = (stat_t *) malloc(sizeof(stat_t) * (NLCOUNT + 1)); + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + BBSLINK_STAT[nlcount].localsendout = 0; + BBSLINK_STAT[nlcount].remotesendout = 0; + BBSLINK_STAT[nlcount].localfailed = 0; + BBSLINK_STAT[nlcount].remotefailed = 0; + } + + nl = (nodelist_t *) search_nodelist_bynode(MYBBSID); + if (nl == NULL) + { + *MYADDR = '\0'; + *MYSITE = '\0'; + *LINKPROTOCOL = '\0'; + } + else + { + strncpy(MYADDR, nl->host, sizeof MYADDR); + strncpy(LINKPROTOCOL, nl->protocol, sizeof LINKPROTOCOL); + strncpy(MYSITE, nl->comments, sizeof MYSITE); + } + if (Verbose) + { + printf("MYADDR: %s\n", MYADDR); + printf("MYSITE: %s\n", MYSITE); + } + left = strchr(nl->protocol, '('); + right = strrchr(nl->protocol, ')'); + if (left && right) + { + *right = '\0'; + strncpy(LINKPROTOCOL, nl->protocol, sizeof LINKPROTOCOL); + LINKPORT = atoi(left + 1); + *right = ')'; + } + + if (!NoVisit) + { + sprintf(bbslink_lockfile, "%s/.bbslink.visit", INNDHOME); +/* +woju + if (!Rename(fileglue("%s/out.bntp", INNDHOME), OUTING) && bbslink_get_lock(bbslink_lockfile)) +*/ + if (strcpy(fname, ".DIR")) + { + /* When try to visit new post, try to lock it */ + NEWPOST = fopen(OUTING, "r"); + if (NEWPOST == NULL) + { + bbslog("<bbslink> Err: can't open %s\n", OUTING); +/* +woju + bbslink_un_lock(bbslink_lockfile); +*/ + return -1; + } +#ifdef 0 +woju + while (fgets(result, sizeof result, NEWPOST)) + { + /* chop( $_ ); */ + char *board, *filename, *userid, *nickname, *subject; + char *ptr; + + ptr = strchr(result, '\n'); + if (ptr) + *ptr = '\0'; + + board = filename = userid = nickname = subject = NULL; + /* board field */ + board = result; + ptr = strchr(result, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* filename field */ + filename = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* userid field */ + userid = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* nickname field */ + nickname = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* subject field */ + subject = ptr; + /* ptr = strchr(ptr, '\t'); if (ptr == NULL) continue; ptr++ = '\0'; */ + + process_article(board, filename, userid, nickname, subject); + } +#endif + while (fread(&fhdr, sizeof(fhdr), 1, NEWPOST) == 1) { + nick[1] = 0; + strcpy(fname, fhdr.filename); + if (fp = fopen(OUTING, "r")) { + fgets(nick, 100, fp); + if ((s1 = strchr(nick, '(')) && (s2 = strrchr(nick, ')'))) + *s2 = 0; + else + s1 = nick; + fclose(fp); + } + printf("%s\n", fhdr.title); + process_article(argv[1], fhdr.filename, fhdr.owner, s1 + 1, fhdr.title); + } + fclose(NEWPOST); +/* +woju + unlink(OUTING); + bbslink_un_lock(bbslink_lockfile); +*/ + } /* getlock */ + } /* if NoVisit is false */ + +#if 0 +woju + sprintf(cancelpost, "%s/cancel.bntp", INNDHOME); + if (isfile(cancelpost)) + { + FILE *CANCELFILE; + + if (bbslink_get_lock(cancelpost) && bbslink_get_lock(cancelfile)) + { + sprintf(cancelfile, "%s.%d", cancelpost, getpid()); + Rename(cancelpost, cancelfile); + CANCELFILE = fopen(cancelfile, "r"); + while (fgets(result, sizeof result, CANCELFILE) != NULL) + { + /* chop( $_ ); */ + char *board, *filename, *userid, *nickname, *subject; + char *ptr, **sptr; + + ptr = strchr(result, '\n'); + if (ptr) + *ptr = '\0'; + board = filename = userid = nickname = subject = NULL; + + /* board field */ + board = result; + ptr = strchr(result, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* filename field */ + filename = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* userid field */ + userid = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* nickname field */ + nickname = ptr; + ptr = strchr(ptr, '\t'); + if (ptr == NULL) + continue; + *ptr++ = '\0'; + + /* subject field */ + subject = ptr; + /* ptr = strchr(ptr, '\t'); if (ptr == NULL) continue; ptr++ = '\0'; */ + process_cancel(board, filename, userid, nickname, subject); + } + fclose(CANCELFILE); + if (Verbose) + printf("Unlinking %s\n", cancelfile); + if (!NoAction) + unlink(cancelfile); + bbslink_un_lock(cancelfile); + bbslink_un_lock(cancelpost); + } + } +#endif + + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + if (NODELIST[nlcount].feedfp != NULL) + { + fclose(NODELIST[nlcount].feedfp); + NODELIST[nlcount].feedfp = NULL; + } + } + + send_article(); + for (nlcount = 0; nlcount < NLCOUNT; nlcount++) + { + int localsendout, remotesendout, localfailed, remotefailed; + + localsendout = BBSLINK_STAT[nlcount].localsendout; + remotesendout = BBSLINK_STAT[nlcount].remotesendout; + localfailed = BBSLINK_STAT[nlcount].localfailed; + remotefailed = BBSLINK_STAT[nlcount].remotefailed; + if (localsendout || remotesendout || localfailed || remotefailed) + bbslog("<bbslink> [%s]%s lsend:%d rsend:%d lfail:%d rfail:%d\n", + NODELIST[nlcount].node, NoAction ? "NoAction" : "", localsendout, remotesendout, + localfailed, remotefailed); + if (NODELIST[nlcount].feedfp != NULL) + { + fclose(NODELIST[nlcount].feedfp); + NODELIST[nlcount].feedfp = NULL; + } + } + if (BBSLINK_STAT); + free(BBSLINK_STAT); + return 0; +} +/* +termbbslink(sig) + int sig; +{ + bbslog("kill signal received %d, terminated\n", sig); + if (Verbose) + printf("kill signal received %d, terminated\n", sig); + exit(0); +} +*/ +void +termbbslink() +{ + bbslog("kill signal received ??, terminated\n"); + if (Verbose) + printf("kill signal received ??, terminated\n"); + exit(0); +} + +char *REMOTEUSERNAME = ""; +char *REMOTEHOSTNAME = ""; + +extern char *optarg; +extern int opterr, optind; + +main(argc, argv) + int argc; + char **argv; +{ + int c, errflag = 0; + + CONTROL = CONTROL_BUF; + MSGID = MSGID_BUF; + + /* For debug Only */ +#define DEBUGBBSLINK + +#ifdef DEBUGBBSLINK + NoAction = 0; + Verbose = 0; + VisitOnly = 0; + NoVisit = 0; + DefaultFeedSite = ""; +#endif + + while ((c = getopt(argc, argv, "s:hnvVNk")) != -1) + switch (c) + { + case 's': + DefaultFeedSite = optarg; + break; + case 'n': + NoAction = 1; + break; + case 'v': + Verbose = 1; + break; + case 'V': + VisitOnly = 1; + break; + case 'N': + NoVisit = 1; + break; + case 'k': + KillFormerBBSLINK = 1; + break; + case 'h': + default: + errflag++; + break; + } + if (errflag > 0) + { + show_usage(argv[0]); + return (1); + } + if (argc - optind < 2) + { + show_usage(argv[0]); + exit(1); + } + signal(SIGTERM, termbbslink); + if (bntplink(argc - optind, argv + optind) != 0) + { + show_usage(argv[0]); + exit(1); + } + return 0; +} diff --git a/innbbsd/bbsnnrp.c b/innbbsd/bbsnnrp.c new file mode 100644 index 00000000..11993629 --- /dev/null +++ b/innbbsd/bbsnnrp.c @@ -0,0 +1,1187 @@ +/* + Usage: bbsnnrp [options] nntpserver activefile + -h|? (help) + -v (verbose protocol transactions) + -c (reset active files only; don't receive articles) + -r remotehost(send articles to remotehost, default=local) + -p port|(send articles to remotehost at port, default=7777) + path(send articles to local at path, default=~bbs/innd/.innbbsd) + -n (don't ask innbbsd server and stat articles) + -w seconds (wait for seconds and run infinitely, default=once) + -a max_art (maximum number of articles received for a group each time) + -s max_stat(maximum number of articles stated for a group each time) + -t stdin|nntp (default=nntp) +*/ + +#include "innbbsconf.h" +#include <sys/mman.h> +#ifndef AIX +# include <sys/fcntl.h> +#endif +#include "bbslib.h" +#include "daemon.h" +#include "nntp.h" + +#ifndef MAX_ARTS +# define MAX_ARTS 100 +#endif +#ifndef MAX_STATS +# define MAX_STATS 1000 +#endif + +#if defined(__linux) +#define NO_USE_MMAP +#else +#define USE_MMAP +#endif + +int Max_Arts= MAX_ARTS; +int Max_Stats = MAX_STATS; + +typedef struct NEWSRC_T { + char *nameptr, *lowptr, *highptr, *modeptr; + int namelen, lowlen, highlen; + ULONG low, high; + int mode, subscribe; +} newsrc_t; + +typedef struct NNRP_T { + int nnrpfd; + int innbbsfd; + FILE *nnrpin, *nnrpout; + FILE *innbbsin, *innbbsout; + char activefile[MAXPATHLEN]; + char rcfile[MAXPATHLEN]; + newsrc_t *newsrc; + char *actpointer, *actend; + int actsize, actfd, actdirty; +} nnrp_t; + +typedef struct XHDR_T { + char *header; + ULONG artno; +} xhdr_t; + +xhdr_t XHDR[MAX_ARTS]; +char LockFile[1024]; + +#define NNRPGroupOK NNTP_GROUPOK_VAL +#define NNRPXhdrOK NNTP_HEAD_FOLLOWS_VAL +#define NNRParticleOK NNTP_ARTICLE_FOLLOWS_VAL +#define INNBBSstatOK NNTP_NOTHING_FOLLOWS_VAL +#define INNBBSihaveOK NNTP_SENDIT_VAL +#define NNRPconnectOK NNTP_POSTOK_VAL +#define NNRPstatOK NNTP_NOTHING_FOLLOWS_VAL +#define INNBBSconnectOK NNTP_POSTOK_VAL + +nnrp_t BBSNNRP; + +void doterm(s) +int s; +{ + printf("bbsnnrp terminated. Signal %d\n", s); + writerc(&BBSNNRP); + if (isfile(LockFile)) + unlink(LockFile); + exit(1); +} + +extern char *optarg; +extern int opterr, optind; + +#ifndef MIN_WAIT +# define MIN_WAIT 60 +#endif + +int ResetActive = 0; +int StatHistory = 1; +int AskLocal = 1; +int RunOnce = 1; + +int DefaultWait = MIN_WAIT; + +char *DefaultPort = DefaultINNBBSPort; +char *DefaultPath = LOCALDAEMON; +char *DefaultRemoteHost; + +#ifndef MAXBUFLEN +#define MAXBUFLEN 256 +#endif +char DefaultNewsgroups[MAXBUFLEN]; +char DefaultOrganization[MAXBUFLEN]; +char DefaultModerator[MAXBUFLEN]; +char DefaultTrustfrom[MAXBUFLEN]; +char DefaultTrustFrom[MAXBUFLEN]; + +usage(arg) +char *arg; +{ +fprintf(stderr,"Usage: %s [options] nntpserver activefile\n", arg); +fprintf(stderr," -h|? (help) \n"); +fprintf(stderr," -v (verbose protocol transactions)\n"); +fprintf(stderr," -c (reset active files only; don't receive articles)\n"); +fprintf(stderr," -r [proto:]remotehost\n"); +fprintf(stderr," (send articles to remotehost, default=ihave:local)\n"); +fprintf(stderr," -p port|(send articles to remotehost at port, default=%s)\n",DefaultINNBBSPort); +fprintf(stderr," path(send articles to local at path, default=~bbs/innd/.innbbsd)\n"); +fprintf(stderr," -w seconds ( > 1 wait for seconds and run infinitely, default=once)\n"); +fprintf(stderr," -n (don't ask innbbsd server and stat articles)\n"); +fprintf(stderr," -a max_art(maximum number of articles received for a group each time)\n"); +fprintf(stderr," default=%d\n", MAX_ARTS); +fprintf(stderr," -s max_stat(maximum number of articles stated for a group each time)\n"); +fprintf(stderr," default=%d\n", MAX_STATS); +fprintf(stderr," -t stdin|nntp (default=nntp)\n"); +fprintf(stderr," -g newsgroups\n"); +fprintf(stderr," -m moderator\n"); +fprintf(stderr," -o organization\n"); +fprintf(stderr," -f trust_user (From: trust_user)\n"); +fprintf(stderr," -F trust_user (From trust_user)\n"); +fprintf(stderr," Please E-mail bug to skhuang@csie.nctu.edu.tw or\n"); +fprintf(stderr," post to tw.bbs.admin.installbbs\n"); +} + +static char *StdinInputType="stdin"; +static char *NntpInputType="nntp"; +static char *NntpIhaveProtocol="ihave"; +static char *NntpPostProtocol="post"; +static char *DefaultNntpProtocol ; +main(argc, argv) +int argc; +char **argv; +{ + char *ptr, *server, *active; + int c, errflag=0; + int lockfd; + char *inputtype; + + DefaultNntpProtocol = NntpIhaveProtocol; + *DefaultNewsgroups = '\0'; + *DefaultModerator = '\0'; + *DefaultOrganization = '\0'; + *DefaultTrustFrom = '\0'; + *DefaultTrustfrom = '\0'; + inputtype = NntpInputType; + while ((c = getopt(argc,argv,"f:F:m:o:g:w:r:p:a:s:t:h?ncv"))!= -1) + switch (c) { + case 'v': + verboseon("bbsnnrp.log"); + break; + case 'c': + ResetActive = 1; + break; + case 'g': + strncpy(DefaultNewsgroups, optarg, sizeof DefaultNewsgroups); + break; + case 'm': + strncpy(DefaultModerator, optarg, sizeof DefaultModerator); + break; + case 'o': + strncpy(DefaultOrganization, optarg, sizeof DefaultOrganization); + break; + case 'f': + strncpy(DefaultTrustfrom, optarg, sizeof DefaultTrustfrom); + break; + case 'F': + strncpy(DefaultTrustFrom, optarg, sizeof DefaultTrustFrom); + break; + case 'r': { + char *hostptr; + AskLocal = 0; + DefaultRemoteHost = optarg; + if ((hostptr = strchr(optarg,':')) != NULL) { + *hostptr = '\0'; + DefaultRemoteHost = hostptr+1; + if (strcasecmp( optarg, "post" ) == 0) + DefaultNntpProtocol = NntpPostProtocol; + *hostptr = ':'; + } + break; + } + case 'w': + RunOnce = 0; + DefaultWait = atoi(optarg); + if (DefaultWait < MIN_WAIT) + DefaultWait = MIN_WAIT; + break; + case 'p': + if (AskLocal == 0) { + DefaultPort = optarg; + } else { + DefaultPath = optarg; + } + break; + case 'n': + StatHistory = 0; + break; + case 'a': + Max_Arts = atol(optarg); + if (Max_Arts < 0) Max_Arts = 0; + break; + case 's': + Max_Stats = atol(optarg); + if (Max_Stats < 0) Max_Stats = 0; + break; + case 't': + if ( strcasecmp(optarg,StdinInputType) == 0) { + inputtype = StdinInputType; + } + break; + case 'h': + case '?': + default: + errflag ++; + } + if (errflag > 0) { + usage(argv[0]); + return(1); + } + if (inputtype == NntpInputType && argc - optind < 2) { + usage(argv[0]); + exit(1); + } + if (inputtype == NntpInputType) { + server = argv[optind]; + active = argv[optind+1]; + if ( isfile(active) ) { + strncpy(BBSNNRP.activefile, active, sizeof BBSNNRP.activefile); + } else if ( strchr(active,'/') == NULL) { + sprintf(BBSNNRP.activefile, "%s/innd/%.*s",BBSHOME, sizeof BBSNNRP.activefile - 7 - strlen(BBSHOME), active); + } else { + strncpy(BBSNNRP.activefile, active, sizeof BBSNNRP.activefile); + } + + strncpy(LockFile , (char*)fileglue("%s.lock",active), sizeof LockFile); + if ((lockfd = open(LockFile, O_RDONLY)) >= 0) { + char buf[10]; + int pid; + + if (read(lockfd, buf, sizeof buf) > 0 && (pid = atoi(buf))>0 && kill(pid,0)==0) { + fprintf(stderr, "another process [%d] running\n", pid); + exit(1); + } else { + fprintf(stderr, "no process [%d] running, but lock file existed, unlinked\n", pid); + unlink(LockFile); + } + close(lockfd); + } + if ((lockfd = open(LockFile, O_RDWR|O_CREAT|O_EXCL,0644)) < 0) { + fprintf( stderr, "maybe another %s process running\n",argv[0]); + exit(1); + } else { + char buf[10]; + int pid; + sprintf(buf,"%-.8d\n",getpid()); + write(lockfd, buf, strlen(buf)); + close(lockfd); + } + for (;;) { + if (!initial_bbs(NULL)) { + fprintf(stderr, "Initial BBS failed\n"); + exit(1); + } + initsockets(server, &BBSNNRP, inputtype); + ptr = (char*)strrchr(active,'/'); + if (ptr != NULL) + ptr++; + else + ptr = active; + sprintf(BBSNNRP.rcfile,"%s/.newsrc.%s.%s",INNDHOME, server, ptr); + initrcfiles(&BBSNNRP); + + signal(SIGTERM, doterm); + signal(SIGKILL, doterm); + signal(SIGHUP, doterm); + signal(SIGPIPE, doterm); + + readnews(&BBSNNRP); + writerc(&BBSNNRP); + closesockets(); + + if (RunOnce) break; + sleep(DefaultWait); + } + unlink(LockFile); + } /* NntpInputType */ + else { + if (!initial_bbs(NULL)) { + fprintf(stderr, "Initial BBS failed\n"); + exit(1); + } + initsockets(server, &BBSNNRP, inputtype); + signal(SIGTERM, doterm); + signal(SIGKILL, doterm); + signal(SIGHUP, doterm); + signal(SIGPIPE, doterm); + + stdinreadnews(&BBSNNRP); + closesockets(); + } /* stdin input type */ + return 0; +} + +headbegin(buffer) +char *buffer; +{ + if (strncmp(buffer,"Path: ",6)==0 ) { + if (strchr(buffer+6,'!') != NULL) + return 1; + } + if (strncmp(buffer,"From ",5)== 0 ) { + if (strchr(buffer+5,':') != NULL) + return 1; + } + return 0; +} + +stdinreadnews(bbsnnrp) +nnrp_t *bbsnnrp; +{ + int i; + char buffer[4096]; + ULONG low, high; + char tmpfilename[MAXPATHLEN]; + FILE *tmpfp = NULL; + char mid[1024]; + int pathagain; + int ngmet, submet, midmet, pathmet, orgmet, approvedmet; + int discard; + char sending_path[MAXPATHLEN]; + int sending_path_len=0; + + strncpy(tmpfilename,(char*)fileglue("/tmp/bbsnnrp-stdin-%d-%d",getuid(),getpid()),sizeof tmpfilename); + fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s", buffer); + if (atoi(buffer) != INNBBSconnectOK) { + fprintf(stderr, "INNBBS server not OK\n"); + return; + } + + if ( DefaultNntpProtocol == NntpPostProtocol ) { + fputs("MODE READER\r\n", bbsnnrp->innbbsout); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: MODE READER\n"); + fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s",buffer); + } + + if (StatHistory == 0) { + fputs("MIDCHECK OFF\r\n", bbsnnrp->innbbsout); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: MIDCHECK OFF\n"); + fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s",buffer); + } + tmpfp = fopen(tmpfilename,"w"); + if (tmpfp == NULL) return; + *mid = '\0'; + for (;;) { + fprintf(stderr,"Try to read from stdin ...\n"); + ngmet = 0, submet = 0, midmet = 0, pathmet = 0, orgmet = 0, approvedmet=0; + discard = 0; + while (fgets(buffer, sizeof buffer, stdin) != NULL) { + char *tmpptr; + tmpptr = strchr(buffer,'\n'); + if (tmpptr != NULL) *tmpptr = '\0'; + if (strncasecmp(buffer,"Message-ID: ",12)==0) { + strncpy(mid, buffer+12,sizeof mid); + midmet = 1; + } else if (strncmp(buffer,"Subject: ",9)==0) { + submet = 1; + } else if (strncmp(buffer,"Path: ",6)==0) { + pathmet = 1; + } else if (strncmp(buffer,"Organization: ",14)==0) { + orgmet = 1; + } else if (strncmp(buffer,"Approved: ",10) == 0) { + approvedmet = 1; + } else if (strncmp(buffer,"From: ",6)==0 && *DefaultTrustfrom ) { + if (strstr(buffer+6, DefaultTrustfrom)==NULL) { + discard = 1; + verboselog("Discard: %s for %s",buffer, DefaultTrustfrom); + } + } else if (strncmp(buffer,"From ",5)==0 && *DefaultTrustFrom ) { + if (strstr(buffer+5, DefaultTrustFrom)==NULL) { + discard = 1; + verboselog("Discard: %s for %s",buffer, DefaultTrustFrom); + } + } else if (strncmp(buffer,"Received: ",10)==0) { + char *rptr=buffer+10, *rrptr; + int savech, len; + if (strncmp(buffer+10,"from ",5)==0) { + rptr +=5; + rrptr = strchr(rptr,'('); + if (rrptr != NULL) rptr = rrptr + 1; + rrptr = strchr(rptr,' '); + savech = *rrptr; + if (rrptr != NULL) *rrptr = '\0'; + } else if (strncmp(buffer+10,"(from ",6)==0) { + rptr +=6; + rrptr = strchr(rptr,')'); + savech = *rrptr; + if (rrptr != NULL) *rrptr = '\0'; + } + len = strlen(rptr) +1; + if (*rptr && sending_path_len + len < sizeof(sending_path)) { + if (*sending_path) + strcat(sending_path, "!"); + strcat(sending_path, rptr); + sending_path_len += len ; + } + if (rrptr != NULL) *rrptr = savech; + } + + if (strncmp(buffer,"Newsgroups: ",12)==0) { + if (*DefaultNewsgroups){ + fprintf(tmpfp,"Newsgroups: %s\r\n",DefaultNewsgroups); + } else { + fprintf(tmpfp,"%s\r\n",buffer); + } + ngmet = 1; + } else { + if (buffer[0] == '\0') { + if (!ngmet && *DefaultNewsgroups) { + fprintf(tmpfp,"Newsgroups: %s\r\n",DefaultNewsgroups); + } + if (!submet) { + fprintf(tmpfp,"Subject: (no subject)\r\n"); + } + if (!pathmet) { + fprintf(tmpfp,"Path: from-mail\r\n"); + } + if (!midmet) { + static int seed; + time_t now; + time(&now); + fprintf(tmpfp,"Message-ID: <%d@%d.%d.%d>\r\n",now,getpid(), getuid(), seed); + sprintf(mid, "<%d@%d.%d.%d>", now, getpid(), getuid(), seed); + seed++; + } + if (!orgmet && *DefaultOrganization) { + fprintf(tmpfp,"Organization: %s\r\n", DefaultOrganization); + } + if (!approvedmet && *DefaultModerator) { + fprintf(tmpfp,"Approved: %s\r\n", DefaultModerator); + } + } + if (strncmp(buffer,"From ",5) != 0 && strncmp(buffer,"To: ",4) !=0) { + if (buffer[0] == '\0') { + if (*sending_path) { + fprintf(tmpfp,"X-Sending-Path: %s\r\n",sending_path); + } + } + fprintf(tmpfp,"%s\r\n",buffer); + } + } + if (buffer[0]=='\0') break; + } + fprintf(stderr,"Article Body begin ...\n"); + pathagain = 0; + while (fgets(buffer, sizeof buffer, stdin) != NULL) { + char *tmpptr; + tmpptr = strchr(buffer,'\n'); + if (tmpptr != NULL) *tmpptr = '\0'; + if ( headbegin(buffer) ) { + FILE *oldfp = bbsnnrp->nnrpin; + pathagain = 1; + fputs(".\r\n",tmpfp); + fclose(tmpfp); + fprintf(stderr,"Try to post ...\n"); + tmpfp = fopen(tmpfilename,"r"); + bbsnnrp->nnrpin = tmpfp; + if (!discard) + if (INNBBSihave(bbsnnrp, -1, mid)== -1) { + fprintf(stderr,"post failed\n"); + } + bbsnnrp->nnrpin = oldfp; + fclose(tmpfp); + *mid = '\0'; + tmpfp = fopen(tmpfilename,"w"); + fprintf(tmpfp,"%s\r\n",buffer); + break; + } else { + fprintf(tmpfp,"%s\r\n",buffer); + } + } + if (!pathagain) break; + } + if (!pathagain && tmpfp) { + FILE *oldfp = bbsnnrp->nnrpin; + fputs(".\r\n",tmpfp); + fclose(tmpfp); + fprintf(stderr,"Try to post ...\n"); + tmpfp = fopen(tmpfilename,"r"); + bbsnnrp->nnrpin = tmpfp; + if (!discard) + if (INNBBSihave(bbsnnrp, -1, mid)== -1) { + fprintf(stderr,"post failed\n"); + } + bbsnnrp->nnrpin = oldfp; + fclose(tmpfp); + } + if (isfile(tmpfilename)) { + unlink(tmpfilename); + } +} + +static char *ACT_BUF, *RC_BUF; +int ACT_COUNT; + +initrcfiles(bbsnnrp) +nnrp_t *bbsnnrp; +{ + FILE *actfp, *rcfp; + char buff[1024]; + int actfd, i, count, actcount=0, rcount=0, maxcount; + struct stat st; + char *actlistptr, *ptr; + + actfd = open(bbsnnrp->activefile, O_RDWR); + if (actfd < 0) { + fprintf( stderr, "can't read/write %s\n", bbsnnrp->activefile ); + exit(1); + } + if (fstat(actfd, &st) != 0) { + fprintf( stderr, "can't stat %s\n", bbsnnrp->activefile ); + exit(1); + } + + bbsnnrp->actfd = actfd; + bbsnnrp->actsize = st.st_size; +#ifdef USE_MMAP + bbsnnrp->actpointer = mmap(0, st.st_size, PROT_WRITE | PROT_READ, + MAP_SHARED, actfd, 0); + if (bbsnnrp->actpointer == (char*)-1) { + fprintf( stderr, "mmap error \n"); + exit(1); + } +#else + if (bbsnnrp->actpointer == NULL) { + bbsnnrp->actpointer = (char*)mymalloc(st.st_size); + } else { + bbsnnrp->actpointer = (char*)myrealloc(bbsnnrp->actpointer,st.st_size); + } + if (bbsnnrp->actpointer == NULL || read(actfd, bbsnnrp->actpointer, st.st_size) <= 0) { + fprintf( stderr, "read act error \n"); + exit(1); + } +#endif + bbsnnrp->actend = bbsnnrp->actpointer + st.st_size; + i = 0, count = 0; + for (ptr = bbsnnrp->actpointer; ptr < bbsnnrp->actend && (actlistptr = (char*)strchr(ptr,'\n')) != NULL; ptr = actlistptr +1, ACT_COUNT++) { + if (*ptr == '\n') continue; + if (*ptr == '#') continue; + count ++; + } + bbsnnrp->newsrc = (newsrc_t*) mymalloc( sizeof(newsrc_t) * count); + ACT_COUNT = 0; + for (ptr = bbsnnrp->actpointer; ptr < bbsnnrp->actend && (actlistptr = (char*)strchr(ptr,'\n')) != NULL; ptr = actlistptr +1 ) { + register newsrc_t *rcptr; + char *nptr; + /**actlistptr = '\0';*/ + if (*ptr == '\n') continue; + if (*ptr == '#') continue; + rcptr = &bbsnnrp->newsrc[ACT_COUNT]; + rcptr->nameptr = NULL; + rcptr->namelen = 0; + rcptr->lowptr = NULL; + rcptr->lowlen = 0; + rcptr->highptr = NULL; + rcptr->highlen = 0; + rcptr->modeptr = NULL; + rcptr->low = 0; + rcptr->high = 0; + rcptr->mode = 'y'; + for (nptr= ptr ;*nptr && isspace(*nptr); ) nptr++; + if ( nptr == actlistptr ) continue; + rcptr->nameptr = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + rcptr->namelen = (int)(nptr - rcptr->nameptr); + if ( nptr == actlistptr) continue; + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if ( nptr == actlistptr) continue; + rcptr->highptr = nptr; + rcptr->high = atol(nptr); + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + rcptr->highlen = (int)(nptr - rcptr->highptr); + if ( nptr == actlistptr) continue; + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if ( nptr == actlistptr) continue; + rcptr->lowptr = nptr; + rcptr->low = atol(nptr); + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + rcptr->lowlen = (int)(nptr - rcptr->lowptr); + if ( nptr == actlistptr) continue; + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if ( nptr == actlistptr) continue; + rcptr->mode = *nptr; + rcptr->modeptr = nptr; + ACT_COUNT ++; + } +} + +initsockets(server, bbsnnrp, type) +char *server; +nnrp_t *bbsnnrp; +char *type; +{ + int nnrpfd ; + int innbbsfd; + if (AskLocal) { + innbbsfd = unixclient(DefaultPath,"tcp"); + if (innbbsfd < 0) { + fprintf(stderr, "Connect to %s error. You may not run innbbsd\n", LOCALDAEMON); + /* unix connect fail, may run by inetd, try to connect to local once */ + innbbsfd = inetclient("localhost",DefaultPort,"tcp"); + if (innbbsfd < 0) { + exit(2); + } + close(innbbsfd); + /* try again */ + innbbsfd = unixclient(DefaultPath,"tcp"); + if (innbbsfd < 0) { + exit(3); + } + } + verboselog("INNBBS connect to %s\n",DefaultPath); + } else { + innbbsfd = inetclient(DefaultRemoteHost,DefaultPort,"tcp"); + if (innbbsfd < 0) { + fprintf(stderr, "Connect to %s at %s error. Remote Server not Ready\n", DefaultRemoteHost, DefaultPort); + exit(2); + } + verboselog("INNBBS connect to %s\n",DefaultRemoteHost); + } + if (type == StdinInputType) { + bbsnnrp->nnrpfd = 0; + bbsnnrp->innbbsfd = innbbsfd; + if ((bbsnnrp->nnrpin = fdopen(0,"r")) == NULL || + (bbsnnrp->nnrpout= fdopen(1,"w")) == NULL || + (bbsnnrp->innbbsin= fdopen(innbbsfd,"r")) == NULL || + (bbsnnrp->innbbsout= fdopen(innbbsfd,"w"))== NULL ) { + fprintf( stderr, "fdopen error\n"); + exit(3); + } + return; + } + nnrpfd = inetclient(server, "nntp","tcp"); + if (nnrpfd < 0) { + fprintf(stderr, " connect to %s error \n", server); + exit(2); + } + verboselog("NNRP connect to %s\n", server); + bbsnnrp->nnrpfd = nnrpfd; + bbsnnrp->innbbsfd = innbbsfd; + if ((bbsnnrp->nnrpin = fdopen(nnrpfd,"r")) == NULL || + (bbsnnrp->nnrpout= fdopen(nnrpfd,"w")) == NULL || + (bbsnnrp->innbbsin= fdopen(innbbsfd,"r")) == NULL || + (bbsnnrp->innbbsout= fdopen(innbbsfd,"w"))== NULL ) { + fprintf( stderr, "fdopen error\n"); + exit(3); + } +} + +closesockets() +{ + fclose(BBSNNRP.nnrpin); + fclose(BBSNNRP.nnrpout); + fclose(BBSNNRP.innbbsin); + fclose(BBSNNRP.innbbsout); + close(BBSNNRP.nnrpfd); + close(BBSNNRP.innbbsfd); +} + +updaterc(actptr, len, value) +char *actptr; +int len; +ULONG value; +{ + for (actptr += len -1; len -- >0; ) { + *actptr-- = value % 10 + '0'; + value /= 10; + } +} + +/* + if old file is empty, don't need to update + prevent from disk full +*/ +int +myrename(old,new) +char *old, *new; +{ + struct stat st; + if (stat(old,&st) != 0) return -1; + if (st.st_size <= 0) return -1; + return rename(old,new); +} + +flushrc(bbsnnrp) +nnrp_t *bbsnnrp; +{ + int backfd; + char *bak1; + if (bbsnnrp->actdirty == 0) return; + bak1 = (char*)strdup((char*)fileglue("%s.BAK",bbsnnrp->activefile)); + if (isfile(bak1)) { + myrename(bak1, (char*)fileglue("%s.BAK.OLD",bbsnnrp->activefile)); + } +#ifdef USE_MMAP + if ((backfd=open((char*)fileglue("%s.BAK",bbsnnrp->activefile),O_WRONLY | O_TRUNC | O_CREAT, 0664)) < 0 || write(backfd, bbsnnrp->actpointer, bbsnnrp->actsize) < bbsnnrp->actsize) +#else + myrename(bbsnnrp->activefile, bak1); + if ((backfd=open(bbsnnrp->activefile,O_WRONLY | O_TRUNC | O_CREAT, 0664)) < 0 || write(backfd, bbsnnrp->actpointer, bbsnnrp->actsize) < bbsnnrp->actsize) +#endif + { + char emergent[128]; + sprintf(emergent,"/tmp/bbsnnrp.%d.active",getpid()); + fprintf(stderr, "write to backup active fail. Maybe disk full\n"); + fprintf(stderr, "try to write in %s\n",emergent); + if ((backfd = open(emergent,O_WRONLY | O_TRUNC | O_CREAT, 0644))<0 || write(backfd, bbsnnrp->actpointer, bbsnnrp->actsize) < bbsnnrp->actsize) + { + fprintf(stderr, "write to %sfail.\n", emergent); + } else { + close(backfd); + } + /* if write fail, should leave */ + /*exit(1);*/ + } else { + close(backfd); + } + free(bak1); + bbsnnrp->actdirty = 0; +} + +writerc(bbsnnrp) +nnrp_t *bbsnnrp; +{ + if (bbsnnrp->actpointer) { + flushrc(bbsnnrp); +#ifdef USE_MMAP + if (munmap(bbsnnrp->actpointer, bbsnnrp->actsize) < 0) + fprintf(stderr, "can't unmap\n"); + /*free(bbsnnrp->actpointer);*/ + bbsnnrp->actpointer = NULL; +#endif + if (close(bbsnnrp->actfd) < 0) + fprintf(stderr, "can't close actfd\n"); + } +} + +static FILE* Xhdrfp; +static char NNRPbuffer[4096]; +static char INNBBSbuffer[4096]; + +char * +NNRPgets(string, len, fp) +char *string; +int len; +FILE *fp; +{ + char* re = fgets(string, len, fp); + char *ptr; + if (re != NULL) { + if ((ptr = (char*)strchr(string,'\r'))!=NULL) + *ptr = '\0'; + if ((ptr = (char*)strchr(string,'\n'))!=NULL) + *ptr = '\0'; + } + return re; +} + +int NNRPstat(bbsnnrp, artno, mid) +nnrp_t *bbsnnrp; + ULONG artno; +char **mid; +{ + char *ptr; + int code; + + *mid = NULL; + fprintf(bbsnnrp->nnrpout,"STAT %d\r\n",artno); + fflush(bbsnnrp->nnrpout); + verboselog("nnrpPut: STAT %d\n",artno); + NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); + verboselog("nnrpGet: %s\n",NNRPbuffer); + + ptr = (char*) strchr(NNRPbuffer, ' '); + if (ptr != NULL) *ptr++ = '\0'; + code = atoi(NNRPbuffer); + ptr = (char*) strchr(ptr, ' '); + if (ptr != NULL) *ptr++ = '\0'; + *mid = ptr; + ptr = (char*) strchr(ptr, ' '); + if (ptr != NULL) *ptr++ = '\0'; + return code; +} + +int +NNRPxhdr(pattern, bbsnnrp, i, low, high) +char *pattern; +nnrp_t *bbsnnrp; +int i; +ULONG low, high; +{ + newsrc_t *rcptr = &bbsnnrp->newsrc[i]; + int size, code; + + Xhdrfp = bbsnnrp->nnrpin; + fprintf(bbsnnrp->nnrpout,"XHDR %s %d-%d\r\n",pattern,low, high ); +#ifdef BBSNNRPDEBUG + printf("XHDR %s %d-%d\r\n",pattern,low, high ); +#endif + fflush(bbsnnrp->nnrpout); + verboselog("nnrpPut: XHDR %s %d-%d\n",pattern,low, high ); + NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); + verboselog("nnrpGet: %s\n", NNRPbuffer); + code = atoi(NNRPbuffer); + return code; +} + +int NNRPxhdrget(artno, mid, iscontrol) +int *artno; +char **mid; +int iscontrol; +{ + *mid = NULL; + *artno = 0; + if (NNRPgets(NNRPbuffer, sizeof NNRPbuffer, Xhdrfp) == NULL) + return 0; + else { + char *ptr, *s; + if (strcmp(NNRPbuffer,".")==0) return 0; + ptr = (char*)strchr(NNRPbuffer,' '); + if (!ptr) return 1; + *ptr++ = '\0'; + *artno = atol(NNRPbuffer); + if (iscontrol) { + ptr = (char*)strchr(s=ptr,' '); + if (!ptr) return 1; + *ptr++ = '\0'; + if (strcmp(s,"cancel") != 0) return 1; + } + *mid = ptr; + return 1; + } +} + +int INNBBSstat(bbsnnrp, i, mid) +nnrp_t *bbsnnrp; +int i; +char *mid; +{ + newsrc_t *rcptr = &bbsnnrp->newsrc[i]; + int size, code; + + fprintf(bbsnnrp->innbbsout,"STAT %s\r\n", mid); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: STAT %s\n", mid); + NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s\n", INNBBSbuffer); + return atol(INNBBSbuffer); +} + +int INNBBSihave(bbsnnrp, artno, mid) +nnrp_t *bbsnnrp; +ULONG artno; +char *mid; +{ + int size, code; + int header=1; + + if (DefaultNntpProtocol == NntpPostProtocol) { + fprintf(bbsnnrp->innbbsout,"POST\r\n"); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: POST %s\n", mid); + } else { + fprintf(bbsnnrp->innbbsout,"IHAVE %s\r\n", mid); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: IHAVE %s\n", mid); + } + if (NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin)==NULL){ + return -1; + } + verboselog("innbbsGet: %s\n", INNBBSbuffer); +#ifdef BBSNNRPDEBUG + printf("ihave got %s\n", INNBBSbuffer); +#endif + + if (DefaultNntpProtocol == NntpPostProtocol) { + if ((code=atol(INNBBSbuffer)) != NNTP_START_POST_VAL) { + if (code == NNTP_POSTFAIL_VAL) + return 0; + else + return -1; + } + } else { + if ((code=atol(INNBBSbuffer)) != INNBBSihaveOK) { + if (code == 435 || code == 437) + return 0; + else + return -1; + } + } + if (artno != -1) { + fprintf(bbsnnrp->nnrpout,"ARTICLE %d\r\n", artno); + verboselog("nnrpPut: ARTICLE %d\n", artno); +#ifdef BBSNNRPDEBUG + printf("ARTICLE %d\r\n", artno); +#endif + fflush(bbsnnrp->nnrpout); + if (NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin)==NULL) { + return -1; + } + verboselog("nnrpGet: %s\n", NNRPbuffer); +#ifdef BBSNNRPDEBUG + printf("article got %s\n", NNRPbuffer); +#endif + if (atol(NNRPbuffer) != NNRParticleOK) { + fputs(".\r\n",bbsnnrp->innbbsout); + fflush(bbsnnrp->innbbsout); + NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s\n",INNBBSbuffer); + return 0; + } + } + header = 1; + while ( fgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin) != NULL) + { + if (strcmp(NNRPbuffer,"\r\n") == 0) + header = 0; + if (strcmp(NNRPbuffer,".\r\n")==0) { + verboselog("nnrpGet: .\n"); + fputs(NNRPbuffer,bbsnnrp->innbbsout); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: .\n"); + if (NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin)==NULL) + return -1; + verboselog("innbbsGet: %s\n",INNBBSbuffer); +#ifdef BBSNNRPDEBUG + printf("end ihave got %s\n", INNBBSbuffer); +#endif + code = atol(INNBBSbuffer); + if (DefaultNntpProtocol == NntpPostProtocol) { + if (code == NNTP_POSTEDOK_VAL) + return 1; + if (code == NNTP_POSTFAIL_VAL) + return 0; + } else { + if (code == 235) + return 1; + if (code == 437 || code == 435) + return 0; + } + break; + } + if ( DefaultNntpProtocol == NntpPostProtocol && + header && strncasecmp(NNRPbuffer,"NNTP-Posting-Host: ",19)==0) { + fprintf(bbsnnrp->innbbsout,"X-%s",NNRPbuffer); + } else { + fputs(NNRPbuffer,bbsnnrp->innbbsout); + } + } + fflush(bbsnnrp->innbbsout); + return -1; +} + +int +NNRPgroup(bbsnnrp, i, low, high) +nnrp_t *bbsnnrp; +int i; +ULONG *low, *high; +{ + newsrc_t *rcptr = &bbsnnrp->newsrc[i]; + int size, code; + ULONG tmp; + + fprintf(bbsnnrp->nnrpout,"GROUP %-.*s\r\n", + rcptr->namelen, rcptr->nameptr ); + printf("GROUP %-.*s\r\n", rcptr->namelen, rcptr->nameptr ); + verboselog("nnrpPut: GROUP %-.*s\n", rcptr->namelen, rcptr->nameptr ); + fflush(bbsnnrp->nnrpout); + NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); + verboselog("nnrpGet: %s\n",NNRPbuffer); + printf("%s\n",NNRPbuffer); + sscanf(NNRPbuffer, "%d %d %ld %ld", &code, &size, low, high); + if (*low > *high) { + tmp = *low; + *low = *high; + *high = tmp; + } + return code; +} + + +readnews(bbsnnrp) +nnrp_t *bbsnnrp; +{ + int i; + char buffer[4096]; + ULONG low, high; + + fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s", buffer); + if (atoi(buffer) != INNBBSconnectOK) { + fprintf(stderr, "INNBBS server not OK\n"); + return; + } +#ifdef BBSNNRPDEBUG + printf("%s",buffer); +#endif + fgets(buffer, sizeof buffer, bbsnnrp->nnrpin); + verboselog("nnrpGet: %s", buffer); + if (buffer[0] != '2') { + /*if (atoi(buffer) != NNRPconnectOK && atoi(buffer) != NNTP_NOPOSTOK_VAL) {*/ + fprintf(stderr, "NNRP server not OK\n"); + return; + } +#ifdef BBSNNRPDEBUG + printf("%s",buffer); +#endif + fputs("MODE READER\r\n", bbsnnrp->nnrpout); + fflush(bbsnnrp->nnrpout); + verboselog("nnrpPut: MODE READER\n"); + fgets(buffer, sizeof buffer, bbsnnrp->nnrpin); + verboselog("nnrpGet: %s",buffer); + + if ( DefaultNntpProtocol == NntpPostProtocol ) { + fputs("MODE READER\r\n", bbsnnrp->innbbsout); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: MODE READER\n"); + fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s",buffer); + } + +#ifdef BBSNNRPDEBUG + printf("%s",buffer); +#endif + + if (StatHistory == 0) { + fputs("MIDCHECK OFF\r\n", bbsnnrp->innbbsout); + fflush(bbsnnrp->innbbsout); + verboselog("innbbsPut: MIDCHECK OFF\n"); + fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); + verboselog("innbbsGet: %s",buffer); + } + bbsnnrp->actdirty = 0; + for (i =0; i< ACT_COUNT; i++) { + int code = NNRPgroup(bbsnnrp, i, &low, &high); + newsrc_t *rcptr = &bbsnnrp->newsrc[i]; + int j; + ULONG artno; + char *mid; + int artcount; + +#ifdef BBSNNRPDEBUG + printf("got reply %d %ld %ld\n",code, low, high); +#endif + artcount = 0; + if (code == NNRPGroupOK) { + int xcount; + ULONG maxartno= rcptr->high; + int isCancelControl = (strncmp(rcptr->nameptr,"control",rcptr->namelen)==0) + || + (strncmp(rcptr->nameptr,"control.cancel",rcptr->namelen)==0) ; + +/* less than or equal to high, for server renumber */ + if (rcptr->low != low) { + bbsnnrp->actdirty = 1; + rcptr->low = low; + updaterc(rcptr->lowptr, rcptr->lowlen, rcptr->low); + } + if (ResetActive) { + if (rcptr->high != high) { + bbsnnrp->actdirty = 1; + rcptr->high = high; + updaterc(rcptr->highptr, rcptr->highlen, rcptr->high); + } + } else if (rcptr->high < high) { + int xhdrcode; + ULONG maxget=high; + int exception=0; + if (rcptr->high < low) { + bbsnnrp->actdirty = 1; + rcptr->high = low; + updaterc(rcptr->highptr, rcptr->highlen, low); + } + if (high > rcptr->high + Max_Stats) { + maxget = rcptr->high + Max_Stats; + } + if ( isCancelControl ) + xhdrcode = NNRPxhdr("Control",bbsnnrp, i, rcptr->high+1, maxget); + else + xhdrcode = NNRPxhdr("Message-ID",bbsnnrp, i, rcptr->high+1, maxget); + + maxartno = maxget; + if ( xhdrcode == NNRPXhdrOK) { + while (NNRPxhdrget(&artno, &mid, isCancelControl)) { +/*#define DEBUG*/ +#ifdef DEBUG + printf("no %d id %s\n",artno, mid); +#endif + if (artcount < Max_Arts) { + if (mid != NULL && !isCancelControl) { + if (!StatHistory || INNBBSstat(bbsnnrp,i,mid) != INNBBSstatOK) { + printf("** %d ** %d need it %s\n", artcount, artno,mid); + XHDR[artcount].artno = artno; + XHDR[artcount].header = restrdup(XHDR[artcount].header,mid); + /*INNBBSihave(bbsnnrp,i,artno,mid);*/ + /* to get it */ + artcount++; + } + } else if (mid != NULL) { + if (INNBBSstat(bbsnnrp,i,mid) == INNBBSstatOK) { + printf("** %d ** %d need cancel %s\n", artcount, artno,mid); + XHDR[artcount].artno = artno; + XHDR[artcount].header = restrdup(XHDR[artcount].header,mid); + artcount++; + } + } + maxartno = artno; + } + } + }/* while xhdr OK */ + exception = 0; + for (xcount = 0; xcount < artcount; xcount++) { + ULONG artno; + char *mid; + artno = XHDR[xcount].artno; + mid = XHDR[xcount].header; + if (isCancelControl) { + if (NNRPstat(bbsnnrp,artno,&mid) == NNRPstatOK) { + } + } + printf("** %d ** %d i have it %s\n", xcount, artno, mid); + if (!ResetActive && mid != NULL) + exception = INNBBSihave(bbsnnrp,artno,mid); + if (exception == -1) break; + if (rcptr->high != artno) { + rcptr->high = artno; + updaterc(rcptr->highptr, rcptr->highlen, rcptr->high); + } + } + if (rcptr->high != maxartno && exception != -1) { + bbsnnrp->actdirty = 1; + rcptr->high = maxartno; + updaterc(rcptr->highptr, rcptr->highlen, maxartno); + } + } + } + /* + flushrc(bbsnnrp); + */ + } + fprintf(bbsnnrp->innbbsout,"quit\r\n"); + fprintf(bbsnnrp->nnrpout,"quit\r\n"); + fflush(bbsnnrp->innbbsout); + fflush(bbsnnrp->nnrpout); + fgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); + fgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin); + +/* bbsnnrp->newsrc[0].high = 1900; + updaterc(bbsnnrp->newsrc[0].highptr, bbsnnrp->newsrc[0].highlen, + bbsnnrp->newsrc[0].high); +*/ +} + +INNBBSDhalt() +{ +} diff --git a/innbbsd/clibrary.h b/innbbsd/clibrary.h new file mode 100644 index 00000000..92ec82e0 --- /dev/null +++ b/innbbsd/clibrary.h @@ -0,0 +1,131 @@ +/* $Revision: 1.1 $ +** +** Here be declarations of routines and variables in the C library. +** You must #include <sys/types.h> and <stdio.h> before this file. +*/ + +#if defined(DO_HAVE_UNISTD) +#include <unistd.h> +#endif /* defined(DO_HAVE_UNISTD) */ + +#if defined(DO_HAVE_VFORK) +#include <vfork.h> +#endif /* defined(DO_HAVE_VFORK) */ + + /* Generic pointer, used by memcpy, malloc, etc. */ + /* =()<typedef @<POINTER>@ *POINTER;>()= */ +typedef char *POINTER; + /* What is a file offset? Will not work unless long! */ + /* =()<typedef @<OFFSET_T>@ OFFSET_T;>()= */ +typedef long OFFSET_T; + /* What is the type of an object size? */ + /* =()<typedef @<SIZE_T>@ SIZE_T;>()= */ +typedef int SIZE_T; + /* What is the type of a passwd uid and gid, for use in chown(2)? */ + /* =()<typedef @<UID_T>@ UID_T;>()= */ +typedef int UID_T; + /* =()<typedef @<GID_T>@ GID_T;>()= */ +typedef int GID_T; + /* =()<typedef @<PID_T>@ PID_T;>()= */ +typedef int PID_T; + /* What should a signal handler return? */ + /* =()<#define SIGHANDLER @<SIGHANDLER>@>()= */ +#define SIGHANDLER void + +#if defined(SIG_DFL) + /* What types of variables can be modified in a signal handler? */ + /* =()<typedef @<SIGVAR>@ SIGVAR;>()= */ +typedef int SIGVAR; +#endif /* defined(SIG_DFL) */ + +/* =()<#include @<STR_HEADER>@>()= */ +#include <string.h> +/* =()<#include @<MEM_HEADER>@>()= */ +#include <memory.h> + + +/* +** It's a pity we have to go through these contortions, for broken +** systems that have fd_set but not the FD_SET. +*/ +#if defined(FD_SETSIZE) +#define FDSET fd_set +#else +#include <sys/param.h> +#if !defined(NOFILE) + error -- #define NOFILE to the number of files allowed on your machine! +#endif /* !defined(NOFILE) */ +#if !defined(howmany) +#define howmany(x, y) (((x) + ((y) - 1)) / (y)) +#endif /* !defined(howmany) */ +#define FD_SETSIZE NOFILE +#define NFDBITS (sizeof (long) * 8) +typedef struct _FDSET { + long fds_bits[howmany(FD_SETSIZE, NFDBITS)]; +} FDSET; +#define FD_SET(n, p) (p)->fds_bits[(n) / NFDBITS] |= (1 << ((n) % NFDBITS)) +#define FD_CLR(n, p) (p)->fds_bits[(n) / NFDBITS] &= ~(1 << ((n) % NFDBITS)) +#define FD_ISSET(n, p) ((p)->fds_bits[(n) / NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) (void)memset((POINTER)(p), 0, sizeof *(p)) +#endif /* defined(FD_SETSIZE) */ + + +#if !defined(SEEK_SET) +#define SEEK_SET 0 +#endif /* !defined(SEEK_SET) */ +#if !defined(SEEK_END) +#define SEEK_END 2 +#endif /* !defined(SEEK_END) */ + +/* +** We must use #define to set FREEVAL, since "typedef void FREEVAL;" doesn't +** work on some broken compilers, sigh. +*/ +/* =()<#define FREEVAL @<FREEVAL>@>()= */ +#define FREEVAL int + +extern int optind; +extern char *optarg; +#if !defined(__STDC__) +extern int errno; +#endif /* !defined(__STDC__) */ + +extern char *getenv(); +extern char *inet_ntoa(); +extern char *mktemp(); +#if !defined(strerror) +extern char *strerror(); +#endif /* !defined(strerror) */ +extern long atol(); +extern time_t time(); +extern unsigned long inet_addr(); +extern FREEVAL free(); +extern POINTER malloc(); +extern POINTER realloc(); +#if defined(ACT_MMAP) +extern char *mmap(); +#endif /* defined(ACT_MMAP) */ + +/* Some backward systems need this. */ +extern FILE *popen(); + +/* This is in <mystring.h>, but not in some system string headers, + * so we put it here just in case. */ +extern int strncasecmp(); + +/* =()<extern @<ABORTVAL>@ abort();>()= */ +extern int abort(); +/* =()<extern @<ALARMVAL>@ alarm();>()= */ +extern int alarm(); +/* =()<extern @<EXITVAL>@ exit();>()= */ +extern void exit(); +/* =()<extern @<GETPIDVAL>@ getpid();>()= */ +extern int getpid(); +/* =()<extern @<LSEEKVAL>@ lseek();>()= */ +extern off_t lseek(); +/* =()<extern @<QSORTVAL>@ qsort();>()= */ +extern int qsort(); +/* =()<extern @<SLEEPVAL>@ sleep();>()= */ +extern int sleep(); +/* =()<extern @<_EXITVAL>@ _exit();>()= */ +extern int _exit(); diff --git a/innbbsd/closeonexec.c b/innbbsd/closeonexec.c new file mode 100644 index 00000000..e005e51b --- /dev/null +++ b/innbbsd/closeonexec.c @@ -0,0 +1,66 @@ +/* $Revision: 1.1 $ +** +*/ +/*#include "configdata.h"*/ +#include <stdio.h> +#include <sys/types.h> +#include <errno.h> +#include <sys/ioctl.h> +#include "clibrary.h" + +#ifndef CLX_IOCTL +# define CLX_IOCTL +#endif +#ifndef CLX_FCNTL +# define CLX_FCNTL +#endif + + + +#if defined(CLX_IOCTL) && !defined(IRIX) +#ifdef __linux +# include <termios.h> +#else +# include <sgtty.h> +#endif + + +/* +** Mark a file close-on-exec so that it doesn't get shared with our +** children. Ignore any error codes. +*/ +void +closeOnExec(fd, flag) + int fd; + int flag; +{ + int oerrno; + + oerrno = errno; + (void)ioctl(fd, flag ? FIOCLEX : FIONCLEX, (char *)NULL); + errno = oerrno; +} +#endif /* defined(CLX_IOCTL) */ + + + +#if defined(CLX_FCNTL) +#include <fcntl.h> + + +/* +** Mark a file close-on-exec so that it doesn't get shared with our +** children. Ignore any error codes. +*/ +void +CloseOnExec(fd, flag) + int fd; + int flag; +{ + int oerrno; + + oerrno = errno; + (void)fcntl(fd, F_SETFD, flag ? 1 : 0); + errno = oerrno; +} +#endif /* defined(CLX_FCNTL) */ diff --git a/innbbsd/connectsock.c b/innbbsd/connectsock.c new file mode 100644 index 00000000..71203cfe --- /dev/null +++ b/innbbsd/connectsock.c @@ -0,0 +1,452 @@ +#include "innbbsconf.h" +#include "daemon.h" +#include <signal.h> +#include <setjmp.h> + +static jmp_buf timebuf; + +static void +timeout(sig) + int sig; +{ + longjmp(timebuf, sig); +} + +extern int errno; +static void reapchild (s) +int s; +{ + int state; + while (waitpid(-1,&state,WNOHANG|WUNTRACED)>0) { + /* printf("reaping child\n");*/ + } +} + +void dokill(s) +int s; +{ + kill(0,SIGKILL); +} + +static INETDstart = 0; +int startfrominetd(flag) +{ + INETDstart = flag ; +} + + +int standalonesetup(fd) +int fd; +{ + int on =1; + struct linger foobar; + if (setsockopt(fd,SOL_SOCKET, SO_REUSEADDR,(char *)&on,sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); + foobar.l_onoff = 0; + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&foobar, sizeof (foobar))<0) + syslog(LOG_ERR, "setsockopt (SO_LINGER): %m"); +} + +static char *UNIX_SERVER_PATH; +static int (*halt)(); + +sethaltfunction(haltfunc) +int (*haltfunc)(); +{ + halt = haltfunc; +} + +void docompletehalt(s) +int s; +{ + /*printf("try to remove %s\n", UNIX_SERVER_PATH); + unlink(UNIX_SERVER_PATH);*/ + exit(0); + /*dokill();*/ +} + +void doremove(s) +int s; +{ + if (halt != NULL) + (*halt)(s); + else + docompletehalt(s); +} + + +initunixserver(path, protocol) +char *path; +char *protocol; +{ + struct sockaddr_un s_un; + /* unix endpoint address */ + struct protoent *pe; /*protocol information entry*/ + int s; + char *ptr; + + bzero((char*)&s_un,sizeof(s_un)); + s_un.sun_family= AF_UNIX; + strcpy(s_un.sun_path, path); + if (protocol==NULL) + protocol="tcp"; + /* map protocol name to protocol number */ + pe=getprotobyname(protocol); + if (pe==NULL) { + fprintf(stderr,"%s: Unknown protocol.\n",protocol); + return (-1); + } + + /* Allocate a socket */ + s = socket(PF_UNIX,strcmp(protocol,"tcp")?SOCK_DGRAM:SOCK_STREAM,0); + if (s<0) { + printf("protocol %d\n", pe->p_proto); + perror("socket"); + return -1; + } + /*standalonesetup(s);*/ + signal(SIGHUP, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGCHLD,reapchild); + UNIX_SERVER_PATH = path; + signal(SIGINT,doremove); + signal(SIGTERM,doremove); + + chdir("/"); + if (bind(s,(struct sockaddr*)&s_un,sizeof (struct sockaddr_un))<0){ + perror("bind"); + perror(path); + return -1; + } + listen(s,10); + return s; +} + +initinetserver(service,protocol) +char *service; +char *protocol; +{ + struct servent *se; /*service information entry*/ + struct hostent *he; /*host information entry*/ + struct protoent *pe; /*protocol information entry*/ + struct sockaddr_in sin;/*Internet endpoint address*/ + int port,s; + int randomport=0; + + bzero((char*)&sin,sizeof(sin)); + sin.sin_family= AF_INET; + if (!strcmp("0",service)) { + randomport = 1; + sin.sin_addr.s_addr = INADDR_ANY; + } + + if (service==NULL) + service=DEFAULTPORT; + if (protocol==NULL) + protocol="tcp"; + /* map service name to port number */ + /* service ---> port */ + se = getservbyname(service,protocol); + if (se==NULL) { + port = htons((u_short)atoi(service)); + if (port==0 && !randomport) { + fprintf (stderr, "%s/%s: Unknown service.\n",service,protocol); + return (-1); + } + } else + port=se->s_port; + sin.sin_port = port; + + /* map protocol name to protocol number */ + pe=getprotobyname(protocol); + if (pe==NULL) { + fprintf(stderr,"%s: Unknown protocol.\n",protocol); + return (-1); + } + + /* Allocate a socket */ + s = socket(PF_INET,strcmp(protocol,"tcp")?SOCK_DGRAM:SOCK_STREAM,pe->p_proto); + if (s<0) { + perror("socket"); + return -1; + } + standalonesetup(s); + signal(SIGHUP, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGCHLD,reapchild); + signal(SIGINT,dokill); + signal(SIGTERM,dokill); + + chdir("/"); + if (bind(s,(struct sockaddr*)&sin,sizeof (struct sockaddr_in))<0){ + perror("bind"); + return -1; + } + listen(s,10); +#ifdef DEBUG + { int length=sizeof(sin); + getsockname(s,&sin,&length); + printf("portnum alocalted %d\n",sin.sin_port); + } +#endif + return s; +} + +int open_unix_listen(path,protocol,initfunc) +char *path; +char *protocol; +int (*initfunc) ARG((int)); +{ + int s; + s = initunixserver(path,protocol); + if (s<0) { + return -1; + } + if (initfunc != NULL) { + printf("in inetsingleserver before initfunc s %d\n",s); + if ((*initfunc)(s)<0) { + perror("initfunc error"); + return -1; + } + printf("end inetsingleserver before initfunc \n"); + } + return s; +} + +int open_listen(service,protocol,initfunc) +char *service; +char *protocol; +int (*initfunc) ARG((int)); +{ + int s; + if (! INETDstart) + s = initinetserver(service,protocol); + else + s = 0; + if (s<0) { + return -1; + } + if (initfunc != NULL) { + printf("in inetsingleserver before initfunc s %d\n",s); + if ((*initfunc)(s)<0) { + perror("initfunc error"); + return -1; + } + printf("end inetsingleserver before initfunc \n"); + } + return s; +} + +int inetsingleserver(service,protocol,serverfunc,initfunc) +char *service; +char *protocol; +int (*initfunc) ARG((int)); +int (*serverfunc) ARG((int)); +{ + int s; + if (!INETDstart) + s = initinetserver(service,protocol); + else + s = 0; + if (s<0) { + return -1; + } + if (initfunc != NULL) { + printf("in inetsingleserver before initfunc s %d\n",s); + if ((*initfunc)(s)<0) { + perror("initfunc error"); + return -1; + } + printf("end inetsingleserver before initfunc \n"); + } + { + int ns=tryaccept(s); + int result=0; + if (ns < 0 && errno != EINTR){ +#ifdef DEBUGSERVER + perror("accept"); +#endif + } + close(s); + if (serverfunc != NULL) + result = (*serverfunc)(ns); + close(ns); + return(result); + } +} + + +int tryaccept(s) +int s; +{ + int ns,fromlen; + struct sockaddr sockaddr;/*Internet endpoint address*/ + fromlen=sizeof (struct sockaddr_in); + +#ifdef DEBUGSERVER + fputs("Listening again\n",stdout); +#endif + do { + ns = accept(s,&sockaddr,&fromlen); + errno = 0; + } while ( ns < 0 && errno == EINTR ); + return ns; +} + +int inetserver(service,protocol,serverfunc) +char *service; +char *protocol; +int (*serverfunc) ARG((int)); +{ + int port,s; + + if (!INETDstart) + s = initinetserver(service,protocol); + else + s = 0; + if (s<0) { + return -1; + } + for (;;) { + int ns=tryaccept(s); + int result=0; + int pid; + if (ns < 0 && errno != EINTR){ +#ifdef DEBUGSERVER + perror("accept"); +#endif + continue; + } +#ifdef DEBUGSERVER + fputs("Accept OK\n",stdout); +#endif + pid = fork(); + if (pid==0) { + close(s); + if (serverfunc != NULL) + result = (*serverfunc)(ns); + close(ns); + exit(result); + } else if (pid < 0) { + perror("fork"); + return -1; + } + close(ns); + } + return 0; +} + +int inetclient(server,service,protocol) +char *server; +char *protocol; +char *service; +{ + struct servent *se; /*service information entry*/ + struct hostent *he; /*host information entry*/ + struct protoent *pe; /*protocol information entry*/ + struct sockaddr_in sin;/*Internet endpoint address*/ + int port,s; + + bzero((char*)&sin,sizeof(sin)); + sin.sin_family= AF_INET; + + if (service==NULL) + service=DEFAULTPORT; + if (protocol==NULL) + protocol="tcp"; + if (server==NULL) + server=DEFAULTSERVER; + /* map service name to port number */ + /* service ---> port */ + se = getservbyname(service,protocol); + if (se==NULL) { + port = htons((u_short)atoi(service)); + if (port==0) { + fprintf (stderr, "%s/%s: Unknown service.\n",service,protocol); + return (-1); + } + } else + port=se->s_port; + sin.sin_port = port; + + /* map server hostname to IP address, allowing for dotted decimal */ + he=gethostbyname(server); + if (he==NULL) { + sin.sin_addr.s_addr = inet_addr(server); + if (sin.sin_addr.s_addr==INADDR_NONE) { + fprintf (stderr, "%s: Unknown host.\n",server); + return (-1); + } + } else + bcopy(he->h_addr,(char*)&sin.sin_addr,he->h_length); + + /* map protocol name to protocol number */ + pe=getprotobyname(protocol); + if (pe==NULL) { + fprintf(stderr,"%s: Unknown protocol.\n",protocol); + return (-1); + } + + /* Allocate a socket */ + s = socket(PF_INET,strcmp(protocol,"tcp")?SOCK_DGRAM:SOCK_STREAM,pe->p_proto); + if (s<0) { + perror("socket"); + return -1; + } + + if (setjmp(timebuf) == 0) + { + signal(SIGALRM, timeout); + alarm(5); + if (connect(s,(struct sockaddr*)&sin,sizeof(sin))<0) + { + alarm(0); + return -1; + } + } + else + { + alarm(0); + return -1; + } + alarm(0); + + return s; +} + +int unixclient(path,protocol) +char *path; +char *protocol; +{ + struct protoent *pe; /*protocol information entry*/ + struct sockaddr_un s_un;/*unix endpoint address*/ + int s; + + bzero((char*)&s_un,sizeof(s_un)); + s_un.sun_family= AF_UNIX; + + if (path==NULL) + path=DEFAULTPATH; + if (protocol==NULL) + protocol="tcp"; + strcpy(s_un.sun_path , path); + + /* map protocol name to protocol number */ + pe=getprotobyname(protocol); + if (pe==NULL) { + fprintf(stderr,"%s: Unknown protocol.\n",protocol); + return (-1); + } + /* Allocate a socket */ + s = socket(PF_UNIX,strcmp(protocol,"tcp")?SOCK_DGRAM:SOCK_STREAM,0); + if (s<0) { + perror("socket"); + return -1; + } + /* Connect the socket to the server */ + if (connect(s,(struct sockaddr*)&s_un,sizeof(s_un))<0) { + /*perror("connect");*/ + return -1; + } + return s; +} diff --git a/innbbsd/ctlinnbbsd.c b/innbbsd/ctlinnbbsd.c new file mode 100644 index 00000000..4ba77b52 --- /dev/null +++ b/innbbsd/ctlinnbbsd.c @@ -0,0 +1,160 @@ +#include "innbbsconf.h" +#include "bbslib.h" + +extern char *optarg; +extern int opterr, optind; + +usage(name) +char *name; +{ + fprintf(stderr, "Usage: %s [-p path] commands\n",name); + fprintf(stderr, " where available commands:\n"); + fprintf(stderr," ctlinnbbsd reload : reload datafiles for innbbsd\n"); + fprintf(stderr," ctlinnbbsd shutdown : shutdown innbbsd gracefully\n"); + fprintf(stderr," ctlinnbbsd mode : examine mode of innbbsd\n"); + fprintf(stderr," ctlinnbbsd addhist <mid> path: add history\n"); + fprintf(stderr," ctlinnbbsd grephist <mid>: query history\n"); + fprintf(stderr," ctlinnbbsd verboselog on|off : verboselog on/off\n"); + fprintf(stderr," ctlinnbbsd hismaint : maintain history\n"); + fprintf(stderr," ctlinnbbsd listnodelist : list nodelist.bbs\n"); + fprintf(stderr," ctlinnbbsd listnewsfeeds : list newsfeeds.bbs\n"); +#ifdef GETRUSAGE + fprintf(stderr," ctlinnbbsd getrusage: get resource usage\n"); +#endif +#ifdef MALLOCMAP + fprintf(stderr," ctlinnbbsd mallocmap: get malloc map\n"); +#endif +} + + +char *DefaultPath = LOCALDAEMON; +char INNBBSbuffer[4096]; + +FILE *innbbsin, *innbbsout; +int innbbsfd; + +ctlinnbbsd(argc, argv) +int argc; +char **argv; +{ + fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin); + printf("%s",INNBBSbuffer); + if (strcasecmp(argv[0], "shutdown")==0 || + strcasecmp(argv[0], "reload")==0 || + strcasecmp(argv[0], "hismaint")==0 || +#ifdef GETRUSAGE + strcasecmp(argv[0], "getrusage")==0 || +#endif +#ifdef MALLOCMAP + strcasecmp(argv[0], "mallocmap")==0 || +#endif + strcasecmp(argv[0], "mode")==0 || + strcasecmp(argv[0], "listnodelist")==0 || + strcasecmp(argv[0], "listnewsfeeds")==0 + ) { + fprintf( innbbsout, "%s\r\n", argv[0]); + fflush( innbbsout); + fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin); + printf("%s",INNBBSbuffer); + if (strcasecmp(argv[0], "mode") ==0 +#ifdef GETRUSAGE + || + strcasecmp(argv[0], "getrusage") ==0 + || + strcasecmp(argv[0], "mallocmap") ==0 +#endif + || + strcasecmp(argv[0], "listnodelist")==0 + || + strcasecmp(argv[0], "listnewsfeeds")==0 + ) { + while (fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin) != NULL) { + if (strcmp(INNBBSbuffer,".\r\n")==0) { + break; + } + printf("%s",INNBBSbuffer); + } + } + } else if (strcasecmp(argv[0], "grephist")==0 || + strcasecmp(argv[0], "verboselog")==0 ) { + if (argc < 2) { + usage("ctlinnbbsd"); + } else { + fprintf( innbbsout, "%s %s\r\n", argv[0], argv[1]); + fflush( innbbsout); + fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin); + printf("%s\n",INNBBSbuffer); + } + } else if (strcasecmp(argv[0], "addhist")==0) { + if (argc < 3) { + usage("ctlinnbbsd"); + } else { + fprintf( innbbsout, "%s %s %s\r\n", argv[0], argv[1], argv[2]); + fflush( innbbsout); + fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin); + printf("%s",INNBBSbuffer); + } + } else { + fprintf(stderr, "invalid command %s\n", argv[0]); + } + if (strcasecmp(argv[0],"shutdown") != 0) { + fprintf( innbbsout, "QUIT\r\n"); + fflush(innbbsout); + fgets(INNBBSbuffer, sizeof INNBBSbuffer, innbbsin); + } +} + +initsocket() +{ + innbbsfd = unixclient(DefaultPath,"tcp"); + if (innbbsfd < 0) { + fprintf(stderr, "Connect to %s error. You may not run innbbsd\n", DefaultPath); + exit(2); + } + if ( (innbbsin= fdopen(innbbsfd,"r")) == NULL || + (innbbsout= fdopen(innbbsfd,"w"))== NULL ) { + fprintf( stderr, "fdopen error\n"); + exit(3); + } +} + +closesocket() +{ + if (innbbsin != NULL) + fclose(innbbsin); + if (innbbsout != NULL) + fclose(innbbsout); + if (innbbsfd >= 0) + close(innbbsfd); +} + +main(argc, argv) +int argc; +char **argv; +{ + int c, errflag=0; + + while ((c = getopt(argc,argv,"p:h?"))!= -1) + switch (c) { + case 'p': + DefaultPath = optarg; + break; + case 'h': + case '?': + default: + errflag ++; + break; + } + if (errflag > 0) { + usage(argv[0]); + return(1); + } + if (argc - optind < 1) { + usage(argv[0]); + exit(1); + } + initial_bbs(NULL); + initsocket(); + ctlinnbbsd(argc-optind, argv+optind); + closesocket(); +} diff --git a/innbbsd/daemon.c b/innbbsd/daemon.c new file mode 100644 index 00000000..973a96c8 --- /dev/null +++ b/innbbsd/daemon.c @@ -0,0 +1,173 @@ +#include "daemon.h" +/* +typedef struct daemoncmd { + char *cmdname; + char *usage; + int argc; + int (*main) ARG((FILE*,FILE*,int,char**,char*)); +} daemoncmd_t; + +*/ + +void deargify ARG((char ***)); +static daemoncmd_t *dcmdp=NULL; +static char *startupmessage=NULL; +static int startupcode=100; +static FILE *DIN,*DOUT,*DIO; +typedef int (*F)(); + +void installdaemon(cmds,code,startupmsg) +daemoncmd_t *cmds; +int code; +char *startupmsg; +{ + dcmdp = cmds; + startupcode = code; + startupmessage = startupmsg; +} + +daemoncmd_t *searchcmd(cmd) +char *cmd; +{ + daemoncmd_t *p; + for (p=dcmdp;p->name != NULL ; p++) { +#ifdef DEBUGCMD + printf("searching name %s for cmd %s\n",p->name,cmd); +#endif + if (!strncasecmp(p->name,cmd,1024)) + return p; + } + return NULL; +} + +#if 0 +int daemon(dfd) +int dfd; +{ + static char BUF[1024]; + /*hash_init();*/ + if (dfd > 0) { + DIO = fdopen(dfd,"rw"); + DIN = fdopen(dfd,"r"); + DOUT = fdopen(dfd,"w"); + if (DIO == NULL || DIN == NULL || DOUT == NULL) { + perror("fdopen"); + return -1; + } + } + if (startupmessage) { + fprintf(DOUT,"%d %s\n",startupcode,startupmessage); + fflush(DOUT); + } + while (fgets(BUF,1024,DIN) != NULL) { + int i; + int (*Main)(); + daemoncmd_t *dp; + argv_t Argv; + + char *p=(char*)strchr(BUF,'\r'); + if (p == NULL) p=(char*)strchr(BUF,'\n'); + if (p == NULL) continue; + *p='\0'; + if (p==BUF) continue; + + Argv.argc = 0, Argv.argv = NULL, Argv.inputline=BUF; + Argv.in = DIN, Argv.out = DOUT; + printf("command entered: %s\n",BUF); +#ifdef DEBUGSERVER + fprintf(DOUT,"BUF in client %s\n",BUF); + fprintf(stdout,"BUF in server %s\n",BUF); + fflush(DOUT); +#endif + Argv.argc = argify(BUF,&Argv.argv); +#ifdef DEBUGSERVER + fprintf(stdout,"argc %d argv ",Argv.argc); + for (i=0;i<Argv.argc;++i) + fprintf(stdout,"%s ",Argv.argv[i]); + fprintf(stdout,"\n"); +#endif + dp = searchcmd(Argv.argv[0]); + Argv.dc = dp; + if (dp) { +#ifdef DEBUGSERVER + printf("find cmd %s by %s\n",dp->name,dp->usage); +#endif + if (Argv.argc < dp->argc) { + fprintf(DOUT,"%d Usage: %s\n",dp->errorcode,dp->usage); + fflush(DOUT); + goto cont; + } + if (dp->argno != 0 && Argv.argc > dp->argno) { + fprintf(DOUT,"%d Usage: %s\n",dp->errorcode,dp->usage); + fflush(DOUT); + goto cont; + } + Main=dp->main; + if (Main) { + fflush(stdout); + (*Main)(&Argv); + } + } + else { + fprintf(DOUT,"99 command %s not available\n",Argv.argv[0]); + fflush(DOUT); + } +cont: + deargify(&Argv.argv); + } + /*hash_reclaim();*/ +} +#endif + +#define MAX_ARG 32 +#define MAX_ARG_SIZE 16384 + +int argify(line, argvp) +char *line, ***argvp; +{ + static char *argvbuffer[MAX_ARG+2]; + char **argv = argvbuffer; + int i; + static char argifybuffer[MAX_ARG_SIZE]; + char *p; + while (strchr("\t\n\r ",*line)) line++; + i=strlen(line); + /*p=(char*) mymalloc(i+1);*/ + p = argifybuffer; + strncpy(p,line, sizeof argifybuffer); + for (*argvp = argv, i=0 ;*p && i < MAX_ARG;){ + for (*argv++=p;*p && !strchr("\t\r\n ",*p);p++); + if (*p=='\0') break; + for (*p++='\0'; strchr("\t\r\n ",*p) && *p;p++); + } + *argv = NULL; + return argv - *argvp; +} + +void deargify (argv) +char ***argv; +{ + return; + /*if (*argv != NULL) { + if (*argv[0] != NULL){ + free(*argv[0]); + *argv[0] = NULL; + } + free(*argv); + *argv = NULL; + }*/ +} + +int daemonprintf(format) +char *format; +{ + fprintf(DOUT,format); + fflush(DOUT); +} + +int daemonputs(output) +char* output; +{ + fputs(output, DOUT); + fflush(DOUT); +} diff --git a/innbbsd/daemon.h b/innbbsd/daemon.h new file mode 100644 index 00000000..d056051f --- /dev/null +++ b/innbbsd/daemon.h @@ -0,0 +1,54 @@ +#ifndef DAEMON_H +#define DAEMON_H + +#include <stdio.h> +#include <time.h> + +#ifndef ARG +# ifdef __STDC__ +# define ARG(x) x +# else +# define ARG(x) () +# endif +#endif + + +struct Argv_t { + FILE *in,*out; + int argc; + char **argv; + char *inputline; + struct Daemoncmd *dc; +}; + +typedef struct Argv_t argv_t; + +typedef struct Buffer_t { + char *data; + int used, left, lastread; +} buffer_t; + +typedef struct ClientType { + char hostname[1024]; + char username[32]; + char buffer[4096]; + int mode; + argv_t Argv; + int fd, access, lastread, midcheck; + buffer_t in,out; + int ihavecount, ihavesize, ihaveduplicate, ihavefail; + int statcount, statfail; + time_t begin; +} ClientType; + +typedef struct Daemoncmd { + char *name; + char *usage; + int argc, argno, errorcode, normalcode; + int (*main) ARG(( ClientType*)); +} daemoncmd_t; + +extern void installdaemon ARG((daemoncmd_t *,int,char*)); +extern ClientType *Channel; + +#endif diff --git a/innbbsd/dbz.c b/innbbsd/dbz.c new file mode 100644 index 00000000..6fd15df8 --- /dev/null +++ b/innbbsd/dbz.c @@ -0,0 +1,1918 @@ +/* + +dbz.c V3.2 + +Copyright 1988 Jon Zeeff (zeeff@b-tech.ann-arbor.mi.us) +You can use this code in any manner, as long as you leave my name on it +and don't hold me responsible for any problems with it. + +Hacked on by gdb@ninja.UUCP (David Butler); Sun Jun 5 00:27:08 CDT 1988 + +Various improvments + INCORE by moraes@ai.toronto.edu (Mark Moraes) + +Major reworking by Henry Spencer as part of the C News project. + +Minor lint and CodeCenter (Saber) fluff removal by Rich $alz (March, 1991). +Non-portable CloseOnExec() calls added by Rich $alz (September, 1991). +Added "writethrough" and tagmask calculation code from +<rob@violet.berkeley.edu> and <leres@ee.lbl.gov> by Rich $alz (December, 1992). +Merged in MMAP code by David Robinson, formerly <david@elroy.jpl.nasa.gov> +now <david.robinson@sun.com> (January, 1993). + +These routines replace dbm as used by the usenet news software +(it's not a full dbm replacement by any means). It's fast and +simple. It contains no AT&T code. + +In general, dbz's files are 1/20 the size of dbm's. Lookup performance +is somewhat better, while file creation is spectacularly faster, especially +if the incore facility is used. + +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <ctype.h> +#include <errno.h> +#ifndef __STDC__ +extern int errno; +#endif +#include <dbz.h> +#include "clibrary.h" + +/* + * #ifdef index. "LIA" = "leave it alone unless you know what you're doing". + * + * FUNNYSEEKS SEEK_SET is not 0, get it from <unistd.h> + * INDEX_SIZE backward compatibility with old dbz; avoid using this + * NMEMORY number of days of memory for use in sizing new table (LIA) + * INCORE backward compatibility with old dbz; use dbzincore() instead + * DBZDEBUG enable debugging + * DEFSIZE default table size (not as critical as in old dbz) + * OLDBNEWS default case mapping as in old B News; set NOBUFFER + * BNEWS default case mapping as in current B News; set NOBUFFER + * DEFCASE default case-map algorithm selector + * NOTAGS fseek offsets are strange, do not do tagging (see below) + * NPAGBUF size of .pag buffer, in longs (LIA) + * SHISTBUF size of ASCII-file buffer, in bytes (LIA) + * MAXRUN length of run which shifts to next table (see below) (LIA) + * OVERFLOW long-int arithmetic overflow must be avoided, will trap + * NOBUFFER do not buffer hash-table i/o, B News locking is defective + * MMAP Use SunOS style mmap() for efficient incore + */ +/* SUPPRESS 530 *//* Empty body for statement */ +/* SUPPRESS 701 on free *//* Conflicting declaration */ + +#ifdef FUNNYSEEKS +#include <unistd.h> +#else +#define SEEK_SET 0 +#endif +#ifdef OVERFLOW +#include <limits.h> +#endif + +static int dbzversion = 3; /* for validating .dir file format */ + +/* + * The dbz database exploits the fact that when news stores a <key,value> + * tuple, the `value' part is a seek offset into a text file, pointing to + * a copy of the `key' part. This avoids the need to store a copy of + * the key in the dbz files. However, the text file *must* exist and be + * consistent with the dbz files, or things will fail. + * + * The basic format of the database is a simple hash table containing the + * values. A value is stored by indexing into the table using a hash value + * computed from the key; collisions are resolved by linear probing (just + * search forward for an empty slot, wrapping around to the beginning of + * the table if necessary). Linear probing is a performance disaster when + * the table starts to get full, so a complication is introduced. The + * database is actually one *or more* tables, stored sequentially in the + * .pag file, and the length of linear-probe sequences is limited. The + * search (for an existing item or an empty slot) always starts in the + * first table, and whenever MAXRUN probes have been done in table N, + * probing continues in table N+1. This behaves reasonably well even in + * cases of massive overflow. There are some other small complications + * added, see comments below. + * + * The table size is fixed for any particular database, but is determined + * dynamically when a database is rebuilt. The strategy is to try to pick + * the size so the first table will be no more than 2/3 full, that being + * slightly before the point where performance starts to degrade. (It is + * desirable to be a bit conservative because the overflow strategy tends + * to produce files with holes in them, which is a nuisance.) + */ + +/* + * The following is for backward compatibility. + */ +#ifdef INDEX_SIZE +#define DEFSIZE INDEX_SIZE +#endif + +/* + * ANSI C says an offset into a file is a long, not an off_t, for some + * reason. This actually does simplify life a bit, but it's still nice + * to have a distinctive name for it. Beware, this is just for readability, + * don't try to change this. + */ +#define of_t long +#define SOF (sizeof(of_t)) + +/* + * We assume that unused areas of a binary file are zeros, and that the + * bit pattern of `(of_t)0' is all zeros. The alternative is rather + * painful file initialization. Note that okayvalue(), if OVERFLOW is + * defined, knows what value of an offset would cause overflow. + */ +#define VACANT ((of_t)0) +#define BIAS(o) ((o)+1) /* make any valid of_t non-VACANT */ +#define UNBIAS(o) ((o)-1) /* reverse BIAS() effect */ + +/* + * In a Unix implementation, or indeed any in which an of_t is a byte + * count, there are a bunch of high bits free in an of_t. There is a + * use for them. Checking a possible hit by looking it up in the base + * file is relatively expensive, and the cost can be dramatically reduced + * by using some of those high bits to tag the value with a few more bits + * of the key's hash. This detects most false hits without the overhead of + * seek+read+strcmp. We use the top bit to indicate whether the value is + * tagged or not, and don't tag a value which is using the tag bits itself. + * We're in trouble if the of_t representation wants to use the top bit. + * The actual bitmasks and offset come from the configuration stuff, + * which permits fiddling with them as necessary, and also suppressing + * them completely (by defining the masks to 0). We build pre-shifted + * versions of the masks for efficiency. + */ +static of_t tagbits; /* pre-shifted tag mask */ +static of_t taghere; /* pre-shifted tag-enable bit */ +static of_t tagboth; /* tagbits|taghere */ +#define HASTAG(o) ((o)&taghere) +#define TAG(o) ((o)&tagbits) +#define NOTAG(o) ((o)&~tagboth) +#define CANTAG(o) (((o)&tagboth) == 0) +#define MKTAG(v) (((v)<<conf.tagshift)&tagbits) + +/* + * A new, from-scratch database, not built as a rebuild of an old one, + * needs to know table size, casemap algorithm, and tagging. Normally + * the user supplies this info, but there have to be defaults. + */ +#ifndef DEFSIZE +#define DEFSIZE 120011 /* 300007 might be better */ +#endif +#ifdef OLDBNEWS +#define DEFCASE '0' /* B2.10 -- no mapping */ +#define NOBUFFER /* B News locking is defective */ +#endif +#ifdef BNEWS +#define DEFCASE '=' /* B2.11 -- all mapped */ +#define NOBUFFER /* B News locking is defective */ +#endif +#ifndef DEFCASE /* C News compatibility is the default */ +#define DEFCASE 'C' /* C News -- RFC822 mapping */ +#endif +#ifndef NOTAGS +#define TAGENB 0x80 /* tag enable is top bit, tag is next 7 */ +#define TAGMASK 0x7f +#define TAGSHIFT 24 +#else +#define TAGENB 0 /* no tags */ +#define TAGMASK 0 +#define TAGSHIFT 0 +#endif + +/* + * We read configuration info from the .dir file into this structure, + * so we can avoid wired-in assumptions for an existing database. + * + * Among the info is a record of recent peak usages, so that a new table + * size can be chosen intelligently when rebuilding. 10 is a good + * number of usages to keep, since news displays marked fluctuations + * in volume on a 7-day cycle. + */ +struct dbzconfig { + int olddbz; /* .dir file empty but .pag not? */ + of_t tsize; /* table size */ +# ifndef NMEMORY +# define NMEMORY 10 /* # days of use info to remember */ +# endif +# define NUSEDS (1+NMEMORY) + of_t used[NUSEDS]; /* entries used today, yesterday, ... */ + int valuesize; /* size of table values, == SOF */ + int bytemap[SOF]; /* byte-order map */ + char casemap; /* case-mapping algorithm (see cipoint()) */ + char fieldsep; /* field separator in base file, if any */ + of_t tagenb; /* unshifted tag-enable bit */ + of_t tagmask; /* unshifted tag mask */ + int tagshift; /* shift count for tagmask and tagenb */ +}; +static struct dbzconfig conf; +static int getconf(); +static long getno(); +static int putconf(); +static void mybytemap(); +static of_t bytemap(); + +/* + * Using mmap() is a more efficent way of keeping the .pag file incore. On + * average, it cuts the number of system calls and buffer copies in half. + * It also allows one copy to be shared among many processes without + * consuming any extra resources. + */ +#ifdef MMAP +#include <sys/mman.h> +#ifdef MAP_FILE +#define MAP__ARG (MAP_FILE | MAP_SHARED) +#else +#define MAP__ARG (MAP_SHARED) +#endif +#ifndef INCORE +#define INCORE +#endif +#endif + +/* + * For a program that makes many, many references to the database, it + * is a large performance win to keep the table in core, if it will fit. + * Note that this does hurt robustness in the event of crashes, and + * dbmclose() *must* be called to flush the in-core database to disk. + * The code is prepared to deal with the possibility that there isn't + * enough memory. There *is* an assumption that a size_t is big enough + * to hold the size (in bytes) of one table, so dbminit() tries to figure + * out whether this is possible first. + * + * The preferred way to ask for an in-core table is to do dbzincore(1) + * before dbminit(). The default is not to do it, although -DINCORE + * overrides this for backward compatibility with old dbz. + * + * We keep only the first table in core. This greatly simplifies the + * code, and bounds memory demand. Furthermore, doing this is a large + * performance win even in the event of massive overflow. + */ +#ifdef INCORE +static int incore = 1; +#else +static int incore = 0; +#endif + +/* + * Write to filesystem even if incore? This replaces a single multi- + * megabyte write when doing a dbzsync with a multi-byte write each + * time an article is added. On most systems, this will give an overall + * performance boost. + */ +static int writethrough = 0; + +/* + * Stdio buffer for .pag reads. Buffering more than about 16 does not help + * significantly at the densities we try to maintain, and the much larger + * buffers that most stdios default to are much more expensive to fill. + * With small buffers, stdio is performance-competitive with raw read(), + * and it's much more portable. + */ +#ifndef NPAGBUF +#define NPAGBUF 16 +#endif +#ifndef NOBUFFER +#ifdef _IOFBF +static of_t pagbuf[NPAGBUF]; /* only needed if !NOBUFFER && _IOFBF */ +#endif +#endif + +/* + * Stdio buffer for base-file reads. Message-IDs (all news ever needs to + * read) are essentially never longer than 64 bytes, and the typical stdio + * buffer is so much larger that it is much more expensive to fill. + */ +#ifndef SHISTBUF +#define SHISTBUF 64 +#endif +#ifdef _IOFBF +static char basebuf[SHISTBUF]; /* only needed if _IOFBF exists */ +#endif + +/* + * Data structure for recording info about searches. + */ +struct searcher { + of_t place; /* current location in file */ + int tabno; /* which table we're in */ + int run; /* how long we'll stay in this table */ +# ifndef MAXRUN +# define MAXRUN 100 +# endif + long hash; /* the key's hash code (for optimization) */ + of_t tag; /* tag we are looking for */ + int seen; /* have we examined current location? */ + int aborted; /* has i/o error aborted search? */ +}; +static void start(); +#define FRESH ((struct searcher *)NULL) +static of_t search(); +#define NOTFOUND ((of_t)-1) +static int okayvalue(); +static int set(); + +/* + * Arguably the searcher struct for a given routine ought to be local to + * it, but a fetch() is very often immediately followed by a store(), and + * in some circumstances it is a useful performance win to remember where + * the fetch() completed. So we use a global struct and remember whether + * it is current. + */ +static struct searcher srch; +static struct searcher *prevp; /* &srch or FRESH */ + +/* byte-ordering stuff */ +static int mybmap[SOF]; /* my byte order (see mybytemap()) */ +static int bytesame; /* is database order same as mine? */ +#define MAPIN(o) ((bytesame) ? (o) : bytemap((o), conf.bytemap, mybmap)) +#define MAPOUT(o) ((bytesame) ? (o) : bytemap((o), mybmap, conf.bytemap)) + +/* + * The double parentheses needed to make this work are ugly, but the + * alternative (under most compilers) is to pack around 2K of unused + * strings -- there's just no way to get rid of them. + */ +#ifdef DBZDEBUG +static int debug; /* controlled by dbzdebug() */ +#define DEBUG(args) if (debug) { (void) printf args ; } else +#else +#define DEBUG(args) ; +#endif + +/* externals used */ +#if 0 +extern char *memcpy(); +extern char *memchr(); +extern char *malloc(); +extern char *calloc(); +extern void free(); /* ANSI C; some old implementations say int */ +#endif /* 0 */ +extern int atoi(); +extern long atol(); +extern void CloseOnExec(); + +/* misc. forwards */ +static long hash(); +static void crcinit(); +static char *cipoint(); +static char *mapcase(); +static int isprime(); +static FILE *latebase(); + +/* file-naming stuff */ +static char dir[] = ".dir"; +static char pag[] = ".pag"; +static char *enstring(); + +/* central data structures */ +static FILE *basef; /* descriptor for base file */ +static char *basefname; /* name for not-yet-opened base file */ +static FILE *dirf; /* descriptor for .dir file */ +static int dirronly; /* dirf open read-only? */ +static FILE *pagf = NULL; /* descriptor for .pag file */ +static of_t pagpos; /* posn in pagf; only search may set != -1 */ +static int pagronly; /* pagf open read-only? */ +static of_t *corepag; /* incore version of .pag file, if any */ +static FILE *bufpagf; /* well-buffered pagf, for incore rewrite */ +static of_t *getcore(); +#ifndef MMAP +static int putcore(); +#endif +static int written; /* has a store() been done? */ + +/* + - dbzfresh - set up a new database, no historical info + */ +int /* 0 success, -1 failure */ +dbzfresh(name, size, fs, cmap, tagmask) +char *name; /* base name; .dir and .pag must exist */ +long size; /* table size (0 means default) */ +int fs; /* field-separator character in base file */ +int cmap; /* case-map algorithm (0 means default) */ +of_t tagmask; /* 0 default, 1 no tags */ +{ + register char *fn; + struct dbzconfig c; + register of_t m; + register FILE *f; + + if (pagf != NULL) { + DEBUG(("dbzfresh: database already open\n")); + return(-1); + } + if (size != 0 && size < 2) { + DEBUG(("dbzfresh: preposterous size (%ld)\n", size)); + return(-1); + } + + /* get default configuration */ + if (getconf((FILE *)NULL, (FILE *)NULL, &c) < 0) + return(-1); /* "can't happen" */ + + /* and mess with it as specified */ + if (size != 0) + c.tsize = size; + c.fieldsep = fs; + switch (cmap) { + case 0: + case '0': + case 'B': /* 2.10 compat */ + c.casemap = '0'; /* '\0' nicer, but '0' printable! */ + break; + case '=': + case 'b': /* 2.11 compat */ + c.casemap = '='; + break; + case 'C': + c.casemap = 'C'; + break; + case '?': + c.casemap = DEFCASE; + break; + default: + DEBUG(("dbzfresh case map `%c' unknown\n", cmap)); + return(-1); + } + switch ((int)tagmask) { + case 0: /* default */ + break; + case 1: /* no tags */ + c.tagshift = 0; + c.tagmask = 0; + c.tagenb = 0; + break; + default: + m = tagmask; + c.tagshift = 0; + while (!(m&01)) { + m >>= 1; + c.tagshift++; + } + c.tagmask = m; + c.tagenb = (m << 1) & ~m; + break; + } + + /* write it out */ + fn = enstring(name, dir); + if (fn == NULL) + return(-1); + f = fopen(fn, "w"); + free((POINTER)fn); + if (f == NULL) { + DEBUG(("dbzfresh: unable to write config\n")); + return(-1); + } + if (putconf(f, &c) < 0) { + (void) fclose(f); + return(-1); + } + if (fclose(f) == EOF) { + DEBUG(("dbzfresh: fclose failure\n")); + return(-1); + } + + /* create/truncate .pag */ + fn = enstring(name, pag); + if (fn == NULL) + return(-1); + f = fopen(fn, "w"); + free((POINTER)fn); + if (f == NULL) { + DEBUG(("dbzfresh: unable to create/truncate .pag file\n")); + return(-1); + } else + (void) fclose(f); + + /* and punt to dbminit for the hard work */ + return(dbminit(name)); +} + +/* + - dbzsize - what's a good table size to hold this many entries? + */ +long +dbzsize(contents) +long contents; /* 0 means what's the default */ +{ + register long n; + + if (contents <= 0) { /* foulup or default inquiry */ + DEBUG(("dbzsize: preposterous input (%ld)\n", contents)); + return(DEFSIZE); + } + n = (contents/2)*3; /* try to keep table at most 2/3 full */ + if (!(n&01)) /* make it odd */ + n++; + DEBUG(("dbzsize: tentative size %ld\n", n)); + while (!isprime(n)) /* and look for a prime */ + n += 2; + DEBUG(("dbzsize: final size %ld\n", n)); + + return(n); +} + +/* + - isprime - is a number prime? + * + * This is not a terribly efficient approach. + */ +static int /* predicate */ +isprime(x) +register long x; +{ + static int quick[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 0 }; + register int *ip; + register long div; + register long stop; + + /* hit the first few primes quickly to eliminate easy ones */ + /* this incidentally prevents ridiculously small tables */ + for (ip = quick; (div = *ip) != 0; ip++) + if (x%div == 0) { + DEBUG(("isprime: quick result on %ld\n", (long)x)); + return(0); + } + + /* approximate square root of x */ + for (stop = x; x/stop < stop; stop >>= 1) + continue; + stop <<= 1; + + /* try odd numbers up to stop */ + for (div = *--ip; div < stop; div += 2) + if (x%div == 0) + return(0); + + return(1); +} + +/* + - dbzagain - set up a new database to be a rebuild of an old one + */ +int /* 0 success, -1 failure */ +dbzagain(name, oldname) +char *name; /* base name; .dir and .pag must exist */ +char *oldname; /* base name; all must exist */ +{ + register char *fn; + struct dbzconfig c; + register int i; + register long top; + register FILE *f; + register int newtable; + register of_t newsize; + struct stat sb; + register of_t m; + + if (pagf != NULL) { + DEBUG(("dbzagain: database already open\n")); + return(-1); + } + + /* pick up the old configuration */ + fn = enstring(oldname, dir); + if (fn == NULL) + return(-1); + f = fopen(fn, "r"); + free((POINTER)fn); + if (f == NULL) { + DEBUG(("dbzagain: cannot open old .dir file\n")); + return(-1); + } + i = getconf(f, (FILE *)NULL, &c); + (void) fclose(f); + if (i < 0) { + DEBUG(("dbzagain: getconf failed\n")); + return(-1); + } + + /* calculate tagging from old file */ + if (stat(oldname, &sb) != -1) { + for (m = 1, i = 0; m < sb.st_size; i++, m <<= 1) + continue; + + /* if we had more tags than the default, use the new data */ + if ((c.tagmask | c.tagenb) && m > (1 << TAGSHIFT)) { + c.tagshift = i; + c.tagmask = (~(unsigned long)0) >> (i + 1); + c.tagenb = (c.tagmask << 1) & ~c.tagmask; + } + } + + /* tinker with it */ + top = 0; + newtable = 0; + for (i = 0; i < NUSEDS; i++) { + if (top < c.used[i]) + top = c.used[i]; + if (c.used[i] == 0) + newtable = 1; /* hasn't got full usage history yet */ + } + if (top == 0) { + DEBUG(("dbzagain: old table has no contents!\n")); + newtable = 1; + } + for (i = NUSEDS-1; i > 0; i--) + c.used[i] = c.used[i-1]; + c.used[0] = 0; + newsize = dbzsize(top); + if (!newtable || newsize > c.tsize) /* don't shrink new table */ + c.tsize = newsize; + + /* write it out */ + fn = enstring(name, dir); + if (fn == NULL) + return(-1); + f = fopen(fn, "w"); + free((POINTER)fn); + if (f == NULL) { + DEBUG(("dbzagain: unable to write new .dir\n")); + return(-1); + } + i = putconf(f, &c); + (void) fclose(f); + if (i < 0) { + DEBUG(("dbzagain: putconf failed\n")); + return(-1); + } + + /* create/truncate .pag */ + fn = enstring(name, pag); + if (fn == NULL) + return(-1); + f = fopen(fn, "w"); + free((POINTER)fn); + if (f == NULL) { + DEBUG(("dbzagain: unable to create/truncate .pag file\n")); + return(-1); + } else + (void) fclose(f); + + /* and let dbminit do the work */ + return(dbminit(name)); +} + +/* + - dbminit - open a database, creating it (using defaults) if necessary + * + * We try to leave errno set plausibly, to the extent that underlying + * functions permit this, since many people consult it if dbminit() fails. + */ +int /* 0 success, -1 failure */ +dbminit(name) +char *name; +{ + register int i; + register size_t s; + register char *dirfname; + register char *pagfname; + + if (pagf != NULL) { + DEBUG(("dbminit: dbminit already called once\n")); + errno = 0; + return(-1); + } + + /* open the .dir file */ + dirfname = enstring(name, dir); + if (dirfname == NULL) + return(-1); + dirf = fopen(dirfname, "r+"); + if (dirf == NULL) { + dirf = fopen(dirfname, "r"); + dirronly = 1; + } else + dirronly = 0; + free((POINTER)dirfname); + if (dirf == NULL) { + DEBUG(("dbminit: can't open .dir file\n")); + return(-1); + } + CloseOnExec((int)fileno(dirf), 1); + + /* open the .pag file */ + pagfname = enstring(name, pag); + if (pagfname == NULL) { + (void) fclose(dirf); + return(-1); + } + pagf = fopen(pagfname, "r+b"); + if (pagf == NULL) { + pagf = fopen(pagfname, "rb"); + if (pagf == NULL) { + DEBUG(("dbminit: .pag open failed\n")); + (void) fclose(dirf); + free((POINTER)pagfname); + return(-1); + } + pagronly = 1; + } else if (dirronly) + pagronly = 1; + else + pagronly = 0; + if (pagf != NULL) + CloseOnExec((int)fileno(pagf), 1); +#ifdef NOBUFFER + /* + * B News does not do adequate locking on its database accesses. + * Why it doesn't get into trouble using dbm is a mystery. In any + * case, doing unbuffered i/o does not cure the problem, but does + * enormously reduce its incidence. + */ + (void) setbuf(pagf, (char *)NULL); +#else +#ifdef _IOFBF + (void) setvbuf(pagf, (char *)pagbuf, _IOFBF, sizeof(pagbuf)); +#endif +#endif + pagpos = -1; + /* don't free pagfname, need it below */ + + /* open the base file */ + basef = fopen(name, "r"); + if (basef == NULL) { + DEBUG(("dbminit: basefile open failed\n")); + basefname = enstring(name, ""); + if (basefname == NULL) { + (void) fclose(pagf); + (void) fclose(dirf); + free((POINTER)pagfname); + pagf = NULL; + return(-1); + } + } else + basefname = NULL; + if (basef != NULL) + CloseOnExec((int)fileno(basef), 1); +#ifdef _IOFBF + if (basef != NULL) + (void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf)); +#endif + + /* pick up configuration */ + if (getconf(dirf, pagf, &conf) < 0) { + DEBUG(("dbminit: getconf failure\n")); + (void) fclose(basef); + (void) fclose(pagf); + (void) fclose(dirf); + free((POINTER)pagfname); + pagf = NULL; + errno = EDOM; /* kind of a kludge, but very portable */ + return(-1); + } + tagbits = conf.tagmask << conf.tagshift; + taghere = conf.tagenb << conf.tagshift; + tagboth = tagbits | taghere; + mybytemap(mybmap); + bytesame = 1; + for (i = 0; i < SOF; i++) + if (mybmap[i] != conf.bytemap[i]) + bytesame = 0; + + /* get first table into core, if it looks desirable and feasible */ + s = (size_t)conf.tsize * SOF; + if (incore && (of_t)(s/SOF) == conf.tsize) { + bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b"); + if (bufpagf != NULL) { + corepag = getcore(bufpagf); + CloseOnExec((int)fileno(bufpagf), 1); + } + } else { + bufpagf = NULL; + corepag = NULL; + } + free((POINTER)pagfname); + + /* misc. setup */ + crcinit(); + written = 0; + prevp = FRESH; + DEBUG(("dbminit: succeeded\n")); + return(0); +} + +/* + - enstring - concatenate two strings into a malloced area + */ +static char * /* NULL if malloc fails */ +enstring(s1, s2) +char *s1; +char *s2; +{ + register char *p; + + p = malloc((size_t)strlen(s1) + (size_t)strlen(s2) + 1); + if (p != NULL) { + (void) strcpy(p, s1); + (void) strcat(p, s2); + } else { + DEBUG(("enstring(%s, %s) out of memory\n", s1, s2)); + } + return(p); +} + +/* + - dbmclose - close a database + */ +int +dbmclose() +{ + register int ret = 0; + + if (pagf == NULL) { + DEBUG(("dbmclose: not opened!\n")); + return(-1); + } + + if (fclose(pagf) == EOF) { + DEBUG(("dbmclose: fclose(pagf) failed\n")); + ret = -1; + } + pagf = basef; /* ensure valid pointer; dbzsync checks it */ + if (dbzsync() < 0) + ret = -1; + if (bufpagf != NULL && fclose(bufpagf) == EOF) { + DEBUG(("dbmclose: fclose(bufpagf) failed\n")); + ret = -1; + } + if (corepag != NULL) +#ifdef MMAP + if (munmap((caddr_t)corepag, (int)conf.tsize * SOF) == -1) { + DEBUG(("dbmclose: munmap failed\n")); + ret = -1; + } +#else + free((POINTER)corepag); +#endif + corepag = NULL; + if (basef) { + if (fclose(basef) == EOF) { + DEBUG(("dbmclose: fclose(basef) failed\n")); + ret = -1; + } + } + if (basefname != NULL) + free((POINTER)basefname); + basef = NULL; + pagf = NULL; + if (fclose(dirf) == EOF) { + DEBUG(("dbmclose: fclose(dirf) failed\n")); + ret = -1; + } + + DEBUG(("dbmclose: %s\n", (ret == 0) ? "succeeded" : "failed")); + return(ret); +} + +/* + - dbzsync - push all in-core data out to disk + */ +int +dbzsync() +{ + register int ret = 0; + + if (pagf == NULL) { + DEBUG(("dbzsync: not opened!\n")); + return(-1); + } + if (!written) + return(0); + +#ifndef MMAP + if (corepag != NULL && !writethrough) { + if (putcore(corepag, bufpagf) < 0) { + DEBUG(("dbzsync: putcore failed\n")); + ret = -1; + } + } +#endif + if (!conf.olddbz) + if (putconf(dirf, &conf) < 0) + ret = -1; + + DEBUG(("dbzsync: %s\n", (ret == 0) ? "succeeded" : "failed")); + return(ret); +} + +/* + - dbzcancel - cancel writing of in-core data + * Mostly for use from child processes. + * Note that we don't need to futz around with stdio buffers, because we + * always fflush them immediately anyway and so they never have stale data. + */ +int +dbzcancel() +{ + if (pagf == NULL) { + DEBUG(("dbzcancel: not opened!\n")); + return(-1); + } + + written = 0; + return(0); +} + +/* + - dbzfetch - fetch() with case mapping built in + */ +datum +dbzfetch(key) +datum key; +{ + char buffer[DBZMAXKEY + 1]; + datum mappedkey; + register size_t keysize; + + DEBUG(("dbzfetch: (%s)\n", key.dptr)); + + /* Key is supposed to be less than DBZMAXKEY */ + keysize = key.dsize; + if (keysize >= DBZMAXKEY) { + keysize = DBZMAXKEY; + DEBUG(("keysize is %d - truncated to %d\n", key.dsize, DBZMAXKEY)); + } + + mappedkey.dptr = mapcase(buffer, key.dptr, keysize); + buffer[keysize] = '\0'; /* just a debug aid */ + mappedkey.dsize = keysize; + + return(fetch(mappedkey)); +} + +/* + - fetch - get an entry from the database + * + * Disgusting fine point, in the name of backward compatibility: if the + * last character of "key" is a NUL, that character is (effectively) not + * part of the comparison against the stored keys. + */ +datum /* dptr NULL, dsize 0 means failure */ +fetch(key) +datum key; +{ + char buffer[DBZMAXKEY + 1]; + static of_t key_ptr; /* return value points here */ + datum output; + register size_t keysize; + register size_t cmplen; + register char *sepp; + + DEBUG(("fetch: (%s)\n", key.dptr)); + output.dptr = NULL; + output.dsize = 0; + prevp = FRESH; + + /* Key is supposed to be less than DBZMAXKEY */ + keysize = key.dsize; + if (keysize >= DBZMAXKEY) { + keysize = DBZMAXKEY; + DEBUG(("keysize is %d - truncated to %d\n", key.dsize, DBZMAXKEY)); + } + + if (pagf == NULL) { + DEBUG(("fetch: database not open!\n")); + return(output); + } else if (basef == NULL) { /* basef didn't exist yet */ + basef = latebase(); + if (basef == NULL) + return(output); + } + + cmplen = keysize; + sepp = &conf.fieldsep; + if (key.dptr[keysize-1] == '\0') { + cmplen--; + sepp = &buffer[keysize-1]; + } + start(&srch, &key, FRESH); + while ((key_ptr = search(&srch)) != NOTFOUND) { + DEBUG(("got 0x%lx\n", key_ptr)); + + /* fetch the key */ + if (fseek(basef, key_ptr, SEEK_SET) != 0) { + DEBUG(("fetch: seek failed\n")); + return(output); + } + if (fread((POINTER)buffer, 1, keysize, basef) != keysize) { + DEBUG(("fetch: read failed\n")); + return(output); + } + + /* try it */ + buffer[keysize] = '\0'; /* terminated for DEBUG */ + (void) mapcase(buffer, buffer, keysize); + DEBUG(("fetch: buffer (%s) looking for (%s) size = %d\n", + buffer, key.dptr, keysize)); + if (memcmp((POINTER)key.dptr, (POINTER)buffer, cmplen) == 0 && + (*sepp == conf.fieldsep || *sepp == '\0')) { + /* we found it */ + output.dptr = (char *)&key_ptr; + output.dsize = SOF; + DEBUG(("fetch: successful\n")); + return(output); + } + } + + /* we didn't find it */ + DEBUG(("fetch: failed\n")); + prevp = &srch; /* remember where we stopped */ + return(output); +} + +/* + - latebase - try to open a base file that wasn't there at the start + */ +static FILE * +latebase() +{ + register FILE *it; + + if (basefname == NULL) { + DEBUG(("latebase: name foulup\n")); + return(NULL); + } + it = fopen(basefname, "r"); + if (it == NULL) { + DEBUG(("latebase: still can't open base\n")); + } else { + DEBUG(("latebase: late open succeeded\n")); + free((POINTER)basefname); + basefname = NULL; +#ifdef _IOFBF + (void) setvbuf(it, basebuf, _IOFBF, sizeof(basebuf)); +#endif + } + if (it != NULL) + CloseOnExec((int)fileno(it), 1); + return(it); +} + +/* + - dbzstore - store() with case mapping built in + */ +int +dbzstore(key, data) +datum key; +datum data; +{ + char buffer[DBZMAXKEY + 1]; + datum mappedkey; + register size_t keysize; + + DEBUG(("dbzstore: (%s)\n", key.dptr)); + + /* Key is supposed to be less than DBZMAXKEY */ + keysize = key.dsize; + if (keysize >= DBZMAXKEY) { + DEBUG(("dbzstore: key size too big (%d)\n", key.dsize)); + return(-1); + } + + mappedkey.dptr = mapcase(buffer, key.dptr, keysize); + buffer[keysize] = '\0'; /* just a debug aid */ + mappedkey.dsize = keysize; + + return(store(mappedkey, data)); +} + +/* + - store - add an entry to the database + */ +int /* 0 success, -1 failure */ +store(key, data) +datum key; +datum data; +{ + of_t value; + + if (pagf == NULL) { + DEBUG(("store: database not open!\n")); + return(-1); + } else if (basef == NULL) { /* basef didn't exist yet */ + basef = latebase(); + if (basef == NULL) + return(-1); + } + if (pagronly) { + DEBUG(("store: database open read-only\n")); + return(-1); + } + if (data.dsize != SOF) { + DEBUG(("store: value size wrong (%d)\n", data.dsize)); + return(-1); + } + if (key.dsize >= DBZMAXKEY) { + DEBUG(("store: key size too big (%d)\n", key.dsize)); + return(-1); + } + + /* copy the value in to ensure alignment */ + (void) memcpy((POINTER)&value, (POINTER)data.dptr, SOF); + DEBUG(("store: (%s, %ld)\n", key.dptr, (long)value)); + if (!okayvalue(value)) { + DEBUG(("store: reserved bit or overflow in 0x%lx\n", value)); + return(-1); + } + + /* find the place, exploiting previous search if possible */ + start(&srch, &key, prevp); + while (search(&srch) != NOTFOUND) + continue; + + prevp = FRESH; + conf.used[0]++; + DEBUG(("store: used count %ld\n", conf.used[0])); + written = 1; + return(set(&srch, value)); +} + +/* + - dbzincore - control attempts to keep .pag file in core + */ +int /* old setting */ +dbzincore(value) +int value; +{ + register int old = incore; + +#ifndef MMAP + incore = value; +#endif + return(old); +} + +/* + - dbzwritethrough - write through the pag file in core + */ +int /* old setting */ +dbzwritethrough(value) +int value; +{ + register int old = writethrough; + + writethrough = value; + return(old); +} + +/* + - dbztagmask - calculate the correct tagmask for the given base file size + */ +long +dbztagmask(size) +register long size; +{ + register long m; + register long tagmask; + register int i; + + if (size <= 0) + return(0L); /* silly size */ + + for (m = 1, i = 0; m < size; i++, m <<= 1) + continue; + + if (m < (1 << TAGSHIFT)) + return(0L); /* not worth tagging */ + + tagmask = (~(unsigned long)0) >> (i + 1); + tagmask = tagmask << i; + return(tagmask); +} + +/* + - getconf - get configuration from .dir file + */ +static int /* 0 success, -1 failure */ +getconf(df, pf, cp) +register FILE *df; /* NULL means just give me the default */ +register FILE *pf; /* NULL means don't care about .pag */ +register struct dbzconfig *cp; +{ + register int c; + register int i; + int err = 0; + + c = (df != NULL) ? getc(df) : EOF; + if (c == EOF) { /* empty file, no configuration known */ + cp->olddbz = 0; + if (df != NULL && pf != NULL && getc(pf) != EOF) + cp->olddbz = 1; + cp->tsize = DEFSIZE; + cp->fieldsep = '\t'; + for (i = 0; i < NUSEDS; i++) + cp->used[i] = 0; + cp->valuesize = SOF; + mybytemap(cp->bytemap); + cp->casemap = DEFCASE; + cp->tagenb = TAGENB; + cp->tagmask = TAGMASK; + cp->tagshift = TAGSHIFT; + DEBUG(("getconf: defaults (%ld, %c, (0x%lx/0x%lx<<%d))\n", + cp->tsize, cp->casemap, cp->tagenb, + cp->tagmask, cp->tagshift)); + return(0); + } + (void) ungetc(c, df); + + /* first line, the vital stuff */ + if (getc(df) != 'd' || getc(df) != 'b' || getc(df) != 'z') + err = -1; + if (getno(df, &err) != dbzversion) + err = -1; + cp->tsize = getno(df, &err); + cp->fieldsep = (int)getno(df, &err); + while ((c = getc(df)) == ' ') + continue; + cp->casemap = c; + cp->tagenb = getno(df, &err); + cp->tagmask = getno(df, &err); + cp->tagshift = getno(df, &err); + cp->valuesize = getno(df, &err); + if (cp->valuesize != SOF) { + DEBUG(("getconf: wrong of_t size (%d)\n", cp->valuesize)); + err = -1; + cp->valuesize = SOF; /* to protect the loops below */ + } + for (i = 0; i < cp->valuesize; i++) + cp->bytemap[i] = getno(df, &err); + if (getc(df) != '\n') + err = -1; +#ifdef DBZDEBUG + DEBUG(("size %ld, sep %d, cmap %c, tags 0x%lx/0x%lx<<%d, ", cp->tsize, + cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask, + cp->tagshift)); + DEBUG(("bytemap (%d)", cp->valuesize)); + for (i = 0; i < cp->valuesize; i++) { + DEBUG((" %d", cp->bytemap[i])); + } + DEBUG(("\n")); +#endif + + /* second line, the usages */ + for (i = 0; i < NUSEDS; i++) + cp->used[i] = getno(df, &err); + if (getc(df) != '\n') + err = -1; + DEBUG(("used %ld %ld %ld...\n", cp->used[0], cp->used[1], cp->used[2])); + + if (err < 0) { + DEBUG(("getconf error\n")); + return(-1); + } + return(0); +} + +/* + - getno - get a long + */ +static long +getno(f, ep) +FILE *f; +int *ep; +{ + register char *p; +# define MAXN 50 + char getbuf[MAXN]; + register int c; + + while ((c = getc(f)) == ' ') + continue; + if (c == EOF || c == '\n') { + DEBUG(("getno: missing number\n")); + *ep = -1; + return(0); + } + p = getbuf; + *p++ = c; + while ((c = getc(f)) != EOF && c != '\n' && c != ' ') + if (p < &getbuf[MAXN-1]) + *p++ = c; + if (c == EOF) { + DEBUG(("getno: EOF\n")); + *ep = -1; + } else + (void) ungetc(c, f); + *p = '\0'; + + if (strspn(getbuf, "-1234567890") != strlen(getbuf)) { + DEBUG(("getno: `%s' non-numeric\n", getbuf)); + *ep = -1; + } + return(atol(getbuf)); +} + +/* + - putconf - write configuration to .dir file + */ +static int /* 0 success, -1 failure */ +putconf(f, cp) +register FILE *f; +register struct dbzconfig *cp; +{ + register int i; + register int ret = 0; + + if (fseek(f, (of_t)0, SEEK_SET) != 0) { + DEBUG(("fseek failure in putconf\n")); + ret = -1; + } + (void) fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, cp->tsize, + cp->fieldsep, cp->casemap, cp->tagenb, + cp->tagmask, cp->tagshift, cp->valuesize); + for (i = 0; i < cp->valuesize; i++) + (void) fprintf(f, " %d", cp->bytemap[i]); + (void) fprintf(f, "\n"); + for (i = 0; i < NUSEDS; i++) + (void) fprintf(f, "%ld%c", cp->used[i], (i < NUSEDS-1) ? ' ' : '\n'); + + (void) fflush(f); + if (ferror(f)) + ret = -1; + + DEBUG(("putconf status %d\n", ret)); + return(ret); +} + +/* + - getcore - try to set up an in-core copy of .pag file + */ +static of_t * /* pointer to copy, or NULL */ +getcore(f) +FILE *f; +{ + register of_t *p; + register size_t i; + register size_t nread; + register char *it; +#ifdef MMAP + struct stat st; + + if (fstat(fileno(f), &st) == -1) { + DEBUG(("getcore: fstat failed\n")); + return(NULL); + } + if (((size_t)conf.tsize * SOF) > st.st_size) { + /* file too small; extend it */ + if (ftruncate((int)fileno(f), conf.tsize * SOF) == -1) { + DEBUG(("getcore: ftruncate failed\n")); + return(NULL); + } + } + it = mmap((caddr_t)0, (size_t)conf.tsize * SOF, + pagronly ? PROT_READ : PROT_WRITE | PROT_READ, MAP__ARG, + (int)fileno(f), (off_t)0); + if (it == (char *)-1) { + DEBUG(("getcore: mmap failed\n")); + return(NULL); + } +#ifdef MC_ADVISE + /* not present in all versions of mmap() */ + madvise(it, (size_t)conf.tsize * SOF, MADV_RANDOM); +#endif +#else + it = malloc((size_t)conf.tsize * SOF); + if (it == NULL) { + DEBUG(("getcore: malloc failed\n")); + return(NULL); + } + + nread = fread((POINTER)it, SOF, (size_t)conf.tsize, f); + if (ferror(f)) { + DEBUG(("getcore: read failed\n")); + free((POINTER)it); + return(NULL); + } + + /* NOSTRICT *//* Possible pointer alignment problem */ + p = (of_t *)it + nread; + i = (size_t)conf.tsize - nread; + while (i-- > 0) + *p++ = VACANT; +#endif + /* NOSTRICT *//* Possible pointer alignment problem */ + return((of_t *)it); +} + +#ifndef MMAP +/* + - putcore - try to rewrite an in-core table + */ +static int /* 0 okay, -1 fail */ +putcore(tab, f) +of_t *tab; +FILE *f; +{ + if (fseek(f, (of_t)0, SEEK_SET) != 0) { + DEBUG(("fseek failure in putcore\n")); + return(-1); + } + (void) fwrite((POINTER)tab, SOF, (size_t)conf.tsize, f); + (void) fflush(f); + return((ferror(f)) ? -1 : 0); +} +#endif + +/* + - start - set up to start or restart a search + */ +static void +start(sp, kp, osp) +register struct searcher *sp; +register datum *kp; +register struct searcher *osp; /* may be FRESH, i.e. NULL */ +{ + register long h; + + h = hash(kp->dptr, kp->dsize); + if (osp != FRESH && osp->hash == h) { + if (sp != osp) + *sp = *osp; + DEBUG(("search restarted\n")); + } else { + sp->hash = h; + sp->tag = MKTAG(h / conf.tsize); + DEBUG(("tag 0x%lx\n", sp->tag)); + sp->place = h % conf.tsize; + sp->tabno = 0; + sp->run = (conf.olddbz) ? conf.tsize : MAXRUN; + sp->aborted = 0; + } + sp->seen = 0; +} + +/* + - search - conduct part of a search + */ +static of_t /* NOTFOUND if we hit VACANT or error */ +search(sp) +register struct searcher *sp; +{ + register of_t dest; + register of_t value; + of_t val; /* buffer for value (can't fread register) */ + register of_t place; + + if (sp->aborted) + return(NOTFOUND); + + for (;;) { + /* determine location to be examined */ + place = sp->place; + if (sp->seen) { + /* go to next location */ + if (--sp->run <= 0) { + sp->tabno++; + sp->run = MAXRUN; + } + place = (place+1)%conf.tsize + sp->tabno*conf.tsize; + sp->place = place; + } else + sp->seen = 1; /* now looking at current location */ + DEBUG(("search @ %ld\n", place)); + + /* get the tagged value */ + if (corepag != NULL && place < conf.tsize) { + DEBUG(("search: in core\n")); + value = MAPIN(corepag[place]); + } else { + /* seek, if necessary */ + dest = place * SOF; + if (pagpos != dest) { + if (fseek(pagf, dest, SEEK_SET) != 0) { + DEBUG(("search: seek failed\n")); + pagpos = -1; + sp->aborted = 1; + return(NOTFOUND); + } + pagpos = dest; + } + + /* read it */ + if (fread((POINTER)&val, sizeof(val), 1, pagf) == 1) + value = MAPIN(val); + else if (ferror(pagf)) { + DEBUG(("search: read failed\n")); + pagpos = -1; + sp->aborted = 1; + return(NOTFOUND); + } else + value = VACANT; + + /* and finish up */ + pagpos += sizeof(val); + } + + /* vacant slot is always cause to return */ + if (value == VACANT) { + DEBUG(("search: empty slot\n")); + return(NOTFOUND); + }; + + /* check the tag */ + value = UNBIAS(value); + DEBUG(("got 0x%lx\n", value)); + if (!HASTAG(value)) { + DEBUG(("tagless\n")); + return(value); + } else if (TAG(value) == sp->tag) { + DEBUG(("match\n")); + return(NOTAG(value)); + } else { + DEBUG(("mismatch 0x%lx\n", TAG(value))); + } + } + /* NOTREACHED */ +} + +/* + - okayvalue - check that a value can be stored + */ +static int /* predicate */ +okayvalue(value) +of_t value; +{ + if (HASTAG(value)) + return(0); +#ifdef OVERFLOW + if (value == LONG_MAX) /* BIAS() and UNBIAS() will overflow */ + return(0); +#endif + return(1); +} + +/* + - set - store a value into a location previously found by search + */ +static int /* 0 success, -1 failure */ +set(sp, value) +register struct searcher *sp; +of_t value; +{ + register of_t place = sp->place; + register of_t v = value; + + if (sp->aborted) + return(-1); + + if (CANTAG(v) && !conf.olddbz) { + v |= sp->tag | taghere; + if (v != UNBIAS(VACANT)) /* BIAS(v) won't look VACANT */ +#ifdef OVERFLOW + if (v != LONG_MAX) /* and it won't overflow */ +#endif + value = v; + } + DEBUG(("tagged value is 0x%lx\n", value)); + value = BIAS(value); + value = MAPOUT(value); + + /* If we have the index file in memory, use it */ + if (corepag != NULL && place < conf.tsize) { + corepag[place] = value; + DEBUG(("set: incore\n")); +#ifdef MMAP + return(0); +#else + if (!writethrough) + return(0); +#endif + } + + /* seek to spot */ + pagpos = -1; /* invalidate position memory */ + if (fseek(pagf, (of_t)(place * SOF), SEEK_SET) != 0) { + DEBUG(("set: seek failed\n")); + sp->aborted = 1; + return(-1); + } + + /* write in data */ + if (fwrite((POINTER)&value, SOF, 1, pagf) != 1) { + DEBUG(("set: write failed\n")); + sp->aborted = 1; + return(-1); + } + /* fflush improves robustness, and buffer re-use is rare anyway */ + if (fflush(pagf) == EOF) { + DEBUG(("set: fflush failed\n")); + sp->aborted = 1; + return(-1); + } + + DEBUG(("set: succeeded\n")); + return(0); +} + +/* + - mybytemap - determine this machine's byte map + * + * A byte map is an array of ints, sizeof(of_t) of them. The 0th int + * is the byte number of the high-order byte in my of_t, and so forth. + */ +static void +mybytemap(map) +int map[]; /* -> int[SOF] */ +{ + union { + of_t o; + char c[SOF]; + } u; + register int *mp = &map[SOF]; + register int ntodo; + register int i; + + u.o = 1; + for (ntodo = (int)SOF; ntodo > 0; ntodo--) { + for (i = 0; i < SOF; i++) + /* SUPPRESS 112 *//* Retrieving char where long is stored */ + if (u.c[i] != 0) + break; + if (i == SOF) { + /* trouble -- set it to *something* consistent */ + DEBUG(("mybytemap: nonexistent byte %d!!!\n", ntodo)); + for (i = 0; i < SOF; i++) + map[i] = i; + return; + } + DEBUG(("mybytemap: byte %d\n", i)); + *--mp = i; + /* SUPPRESS 112 *//* Retrieving char where long is stored */ + while (u.c[i] != 0) + u.o <<= 1; + } +} + +/* + - bytemap - transform an of_t from byte ordering map1 to map2 + */ +static of_t /* transformed result */ +bytemap(ino, map1, map2) +of_t ino; +int *map1; +int *map2; +{ + union oc { + of_t o; + char c[SOF]; + }; + union oc in; + union oc out; + register int i; + + in.o = ino; + for (i = 0; i < SOF; i++) + out.c[map2[i]] = in.c[map1[i]]; + return(out.o); +} + +/* + * This is a simplified version of the pathalias hashing function. + * Thanks to Steve Belovin and Peter Honeyman + * + * hash a string into a long int. 31 bit crc (from andrew appel). + * the crc table is computed at run time by crcinit() -- we could + * precompute, but it takes 1 clock tick on a 750. + * + * This fast table calculation works only if POLY is a prime polynomial + * in the field of integers modulo 2. Since the coefficients of a + * 32-bit polynomial won't fit in a 32-bit word, the high-order bit is + * implicit. IT MUST ALSO BE THE CASE that the coefficients of orders + * 31 down to 25 are zero. Happily, we have candidates, from + * E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962): + * x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0 + * x^31 + x^3 + x^0 + * + * We reverse the bits to get: + * 111101010000000000000000000000001 but drop the last 1 + * f 5 0 0 0 0 0 0 + * 010010000000000000000000000000001 ditto, for 31-bit crc + * 4 8 0 0 0 0 0 0 + */ + +#define POLY 0x48000000L /* 31-bit polynomial (avoids sign problems) */ + +static long CrcTable[128]; + +/* + - crcinit - initialize tables for hash function + */ +static void +crcinit() +{ + register int i, j; + register long sum; + + for (i = 0; i < 128; ++i) { + sum = 0L; + for (j = 7 - 1; j >= 0; --j) + if (i & (1 << j)) + sum ^= POLY >> j; + CrcTable[i] = sum; + } + DEBUG(("crcinit: done\n")); +} + +/* + - hash - Honeyman's nice hashing function + */ +static long +hash(name, size) +register char *name; +register int size; +{ + register long sum = 0L; + + while (size--) { + sum = (sum >> 7) ^ CrcTable[(sum ^ (*name++)) & 0x7f]; + } + DEBUG(("hash: returns (%ld)\n", sum)); + return(sum); +} + +/* + * case-mapping stuff + * + * Borrowed from C News, by permission of the authors. Somewhat modified. + * + * We exploit the fact that we are dealing only with headers here, and + * headers are limited to the ASCII characters by RFC822. It is barely + * possible that we might be dealing with a translation into another + * character set, but in particular it's very unlikely for a header + * character to be outside -128..255. + * + * Life would be a whole lot simpler if tolower() could safely and portably + * be applied to any char. + */ + +#define OFFSET 128 /* avoid trouble with negative chars */ + +/* must call casencmp before invoking TOLOW... */ +#define TOLOW(c) (cmap[(c)+OFFSET]) + +/* ...but the use of it in CISTREQN is safe without the preliminary call (!) */ +/* CISTREQN is an optimised case-insensitive strncmp(a,b,n)==0; n > 0 */ +#define CISTREQN(a, b, n) \ + (TOLOW((a)[0]) == TOLOW((b)[0]) && casencmp(a, b, n) == 0) + +#define MAPSIZE (256+OFFSET) +static char cmap[MAPSIZE]; /* relies on init to '\0' */ +static int mprimed = 0; /* has cmap been set up? */ + +/* + - mapprime - set up case-mapping stuff + */ +static void +mapprime() +{ + register char *lp; + register char *up; + register int c; + register int i; + static char lower[] = "abcdefghijklmnopqrstuvwxyz"; + static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + for (lp = lower, up = upper; *lp != '\0'; lp++, up++) { + c = *lp; + cmap[c+OFFSET] = c; + cmap[*up+OFFSET] = c; + } + for (i = 0; i < MAPSIZE; i++) + if (cmap[i] == '\0') + cmap[i] = (char)(i-OFFSET); + mprimed = 1; +} + +/* + - casencmp - case-independent strncmp + */ +static int /* < == > 0 */ +casencmp(s1, s2, len) +char *s1; +char *s2; +int len; +{ + register char *p1; + register char *p2; + register int n; + + if (!mprimed) + mapprime(); + + p1 = s1; + p2 = s2; + n = len; + while (--n >= 0 && *p1 != '\0' && TOLOW(*p1) == TOLOW(*p2)) { + p1++; + p2++; + } + if (n < 0) + return(0); + + /* + * The following case analysis is necessary so that characters + * which look negative collate low against normal characters but + * high against the end-of-string NUL. + */ + if (*p1 == '\0' && *p2 == '\0') + return(0); + else if (*p1 == '\0') + return(-1); + else if (*p2 == '\0') + return(1); + else + return(TOLOW(*p1) - TOLOW(*p2)); +} + +/* + - mapcase - do case-mapped copy + */ +static char * /* returns src or dst */ +mapcase(dst, src, siz) +char *dst; /* destination, used only if mapping needed */ +char *src; /* source; src == dst is legal */ +size_t siz; +{ + register char *s; + register char *d; + register char *c; /* case break */ + register char *e; /* end of source */ + + + c = cipoint(src, siz); + if (c == NULL) + return(src); + + if (!mprimed) + mapprime(); + s = src; + e = s + siz; + d = dst; + + while (s < c) + *d++ = *s++; + while (s < e) + *d++ = TOLOW(*s++); + + return(dst); +} + +/* + - cipoint - where in this message-ID does it become case-insensitive? + * + * The RFC822 code is not quite complete. Absolute, total, full RFC822 + * compliance requires a horrible parsing job, because of the arcane + * quoting conventions -- abc"def"ghi is not equivalent to abc"DEF"ghi, + * for example. There are three or four things that might occur in the + * domain part of a message-id that are case-sensitive. They don't seem + * to ever occur in real news, thank Cthulhu. (What? You were expecting + * a merciful and forgiving deity to be invoked in connection with RFC822? + * Forget it; none of them would come near it.) + */ +static char * /* pointer into s, or NULL for "nowhere" */ +cipoint(s, siz) +char *s; +size_t siz; +{ + register char *p; + static char post[] = "postmaster"; + static int plen = sizeof(post)-1; + + switch (conf.casemap) { + case '0': /* unmapped, sensible */ + return(NULL); + case 'C': /* C News, RFC 822 conformant (approx.) */ + p = memchr((POINTER)s, '@', siz); + if (p == NULL) /* no local/domain split */ + return(NULL); /* assume all local */ + if (p - (s+1) == plen && CISTREQN(s+1, post, plen)) { + /* crazy -- "postmaster" is case-insensitive */ + return(s); + } + return(p); + case '=': /* 2.11, neither sensible nor conformant */ + return(s); /* all case-insensitive */ + } + + DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap)); + return(NULL); /* just leave it alone */ +} + +/* + - dbzdebug - control dbz debugging at run time + */ +#ifdef DBZDEBUG +int /* old value */ +dbzdebug(value) +int value; +{ + register int old = debug; + + debug = value; + return(old); +} +#endif diff --git a/innbbsd/dbz.h b/innbbsd/dbz.h new file mode 100644 index 00000000..3d7e8ed7 --- /dev/null +++ b/innbbsd/dbz.h @@ -0,0 +1,32 @@ +/* for dbm and dbz */ +typedef struct { + char *dptr; + int dsize; +} datum; + +/* standard dbm functions */ +extern int dbminit(); +extern datum fetch(); +extern int store(); +extern int delete(); /* not in dbz */ +extern datum firstkey(); /* not in dbz */ +extern datum nextkey(); /* not in dbz */ +extern int dbmclose(); /* in dbz, but not in old dbm */ + +/* new stuff for dbz */ +extern int dbzfresh(); +extern int dbzagain(); +extern datum dbzfetch(); +extern int dbzstore(); +extern int dbzsync(); +extern long dbzsize(); +extern int dbzincore(); +extern int dbzcancel(); +extern int dbzdebug(); + +/* + * In principle we could handle unlimited-length keys by operating a chunk + * at a time, but it's not worth it in practice. Setting a nice large + * bound on them simplifies the code and doesn't hurt anything. + */ +#define DBZMAXKEY 255 diff --git a/innbbsd/dbztool.c b/innbbsd/dbztool.c new file mode 100644 index 00000000..5318721b --- /dev/null +++ b/innbbsd/dbztool.c @@ -0,0 +1,88 @@ +#include <sys/file.h> +#include "his.h" + +#define DEBUG 1 +#undef DEBUG + +static datum content, inputkey, inputvalue; +static char dboutput[1025]; +static char dbinput[1025]; +static char valueinput[100]; + +enum {SUBJECT, FROM, NAME}; +char *DBfetch(key) +char *key; +{ + int i; + char *tail, *ptr; + if (key == NULL) return NULL; + sprintf(dbinput,"%.510s",key); + inputkey.dptr = dbinput; + inputkey.dsize = strlen(dbinput); + content.dptr = dboutput; + ptr = (char*)HISfilesfor(&inputkey,&content); + if (ptr == NULL) { + return NULL; + } + return ptr; +} + +DBstore(key,paths) +char *key; +char *paths; +{ + int i; + char *tail; + time_t now; + time(&now); + if (key == NULL) return -1; + sprintf(dbinput,"%.510s",key); + inputkey.dptr = dbinput; + inputkey.dsize = strlen(dbinput); + if (HISwrite(&inputkey, now, paths ) == FALSE) { + return -1; + } else { + return 0; + } +} + +int storeDB(mid,paths) +char *mid; +char *paths; +{ + char *key,*ptr; + int rel; + ptr = DBfetch(mid); + if (ptr != NULL) { + return 0; + } else { + return DBstore(mid , paths); + } +} + +my_mkdir (idir,mode) +char *idir; +int mode; +{ + char buffer[LEN]; + char *ptr, *dir = buffer; + struct stat st; + strncpy(dir, idir, LEN - 1); + for (;dir!=NULL && *dir;) { + ptr = (char*)strchr(dir,'/'); + if (ptr != NULL) { + *ptr = '\0'; + } + if (stat(dir,&st) != 0) { + if (mkdir(dir,mode) != 0 ) + return -1; + } + chdir(dir); + if (ptr != NULL) + dir = ptr +1; + else + dir = ptr; + } + return 0; +} + diff --git a/innbbsd/echobbslib.c b/innbbsd/echobbslib.c new file mode 100644 index 00000000..84d77de6 --- /dev/null +++ b/innbbsd/echobbslib.c @@ -0,0 +1,713 @@ +#if defined( LINUX ) +# include "innbbsconf.h" +# include "bbslib.h" +# include <varargs.h> +#else +# include <varargs.h> +# include "innbbsconf.h" +# include "bbslib.h" +#endif + +char INNBBSCONF[MAXPATHLEN]; +char INNDHOME[MAXPATHLEN]; +char HISTORY[MAXPATHLEN]; +char LOGFILE[MAXPATHLEN]; +char MYBBSID[MAXPATHLEN]; +char ECHOMAIL[MAXPATHLEN]; +char BBSFEEDS[MAXPATHLEN]; +char LOCALDAEMON[MAXPATHLEN]; + +int His_Maint_Min= HIS_MAINT_MIN; +int His_Maint_Hour= HIS_MAINT_HOUR; +int Expiredays = EXPIREDAYS; + +nodelist_t *NODELIST=NULL, **NODELIST_BYNODE=NULL; +newsfeeds_t *NEWSFEEDS=NULL, **NEWSFEEDS_BYBOARD=NULL; +static char *NODELIST_BUF, *NEWSFEEDS_BUF; +int NFCOUNT, NLCOUNT; +int LOCALNODELIST=0, NONENEWSFEEDS=0; + +#ifndef _PATH_BBSHOME +# define _PATH_BBSHOME "/u/staff/bbsroot/csie_util/bntpd/home" +#endif + +static FILE *bbslogfp; + +static int +verboseFlag=0; + +static char* +verboseFilename=NULL; +static char verbosename[MAXPATHLEN]; + +verboseon(filename) +char *filename; +{ + verboseFlag = 1; + if ( filename != NULL ) { + if (strchr(filename,'/') == NULL) { + sprintf(verbosename,"%s/innd/%s",BBSHOME,filename); + filename = verbosename; + } + } + verboseFilename = filename; +} +verboseoff() +{ + verboseFlag = 0; +} + +setverboseon() +{ + verboseFlag = 1; +} + +isverboselog() +{ + return verboseFlag; +} + +setverboseoff() +{ + verboseoff(); + if (bbslogfp != NULL) { + fclose(bbslogfp); + bbslogfp = NULL; + } +} + +verboselog(va_alist) +va_dcl +{ + va_list ap; + register char* fmt; + char datebuf[40]; + time_t now; + + if (verboseFlag == 0) return; + + va_start(ap); + + time(&now); + strftime(datebuf, sizeof(datebuf), "%b %d %X ", localtime(&now)); + + if (bbslogfp == NULL) { + if (verboseFilename != NULL) + bbslogfp = fopen(verboseFilename, "a"); + else + bbslogfp = fdopen(1, "a"); + } + if (bbslogfp == NULL) { va_end(ap); return; } + fmt = va_arg(ap, char *) ; + fprintf(bbslogfp,"%s[%d] ",datebuf, getpid()); + vfprintf(bbslogfp, fmt, ap); + fflush(bbslogfp); + va_end(ap); +} + +#ifdef PalmBBS +xbbslog(va_alist) +#else +bbslog(va_alist) +#endif +va_dcl +{ + va_list ap; + register char* fmt; + char datebuf[40]; + time_t now; + + va_start(ap); + + time(&now); + strftime(datebuf, sizeof(datebuf), "%b %d %X ", localtime(&now)); + + if (bbslogfp == NULL) { + bbslogfp = fopen(LOGFILE, "a"); + } + if (bbslogfp == NULL) { va_end(ap); return; } + fmt = va_arg(ap, char *) ; + fprintf(bbslogfp,"%s[%d] ",datebuf,getpid()); + vfprintf(bbslogfp, fmt, ap); + fflush(bbslogfp); + va_end(ap); +} + +initial_bbs(outgoing) +char *outgoing; +{ + FILE* FN; + struct stat st; + int fd, i; + char *bbsnameptr=NULL; + +/* reopen bbslog */ + if (bbslogfp != NULL) { + fclose(bbslogfp); + bbslogfp = NULL; + } + +#ifdef WITH_ECHOMAIL + init_echomailfp(); + init_bbsfeedsfp(); +#endif + + LOCALNODELIST=0, NONENEWSFEEDS =0; + sprintf(INNDHOME,"%s/innd",BBSHOME); + sprintf(HISTORY, "%s/history",INNDHOME); + sprintf(LOGFILE, "%s/bbslog",INNDHOME); + sprintf(ECHOMAIL,"%s/echomail.log",BBSHOME); + sprintf(LOCALDAEMON,"%s/.innbbsd",INNDHOME); + sprintf(INNBBSCONF,"%s/innbbs.conf",INNDHOME); + sprintf(BBSFEEDS,"%s/bbsfeeds.log",INNDHOME); + + if (isfile(INNBBSCONF)) { + FILE *conf; + char buffer[MAXPATHLEN]; + conf = fopen(INNBBSCONF,"r"); + if (conf != NULL) { + while (fgets( buffer, sizeof buffer, conf) != NULL) { + char *ptr, *front=NULL, *value=NULL, *value2=NULL, *value3=NULL; + if ( buffer[0] == '#' || buffer[0] == '\n') continue; + for ( front = buffer; *front && isspace(*front); front++); + for ( ptr = front; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr == '\0') continue; + *ptr++ = '\0'; + for ( ; *ptr && isspace(*ptr) ; ptr++) ; + if (*ptr == '\0') continue; + value = ptr++; + for ( ; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr) { + *ptr++ = '\0'; + for ( ; *ptr && isspace(*ptr) ; ptr++) ; + value2 = ptr++; + for ( ; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr) { + *ptr++ = '\0'; + for ( ; *ptr && isspace(*ptr) ; ptr++) ; + value3 = ptr++; + for ( ; *ptr && !isspace(*ptr) ; ptr++) ; + if (*ptr) { + *ptr++ = '\0'; + } + } + } + if ( strcasecmp(front,"expiredays") == 0) { + Expiredays = atoi(value); + if (Expiredays < 0) { + Expiredays = EXPIREDAYS; + } + } else if ( strcasecmp(front,"expiretime") == 0) { + ptr = strchr(value,':'); + if (ptr == NULL) { + fprintf(stderr, "Syntax error in innbbs.conf\n"); + } else { + *ptr++ = '\0'; + His_Maint_Hour = atoi(value); + His_Maint_Min = atoi(ptr); + if (His_Maint_Hour < 0) + His_Maint_Hour = HIS_MAINT_HOUR; + if (His_Maint_Min < 0) + His_Maint_Min = HIS_MAINT_MIN; + } + } else if ( strcasecmp(front,"newsfeeds") == 0) { + if (strcmp(value,"none")==0) + NONENEWSFEEDS = 1; + } else if ( strcasecmp(front,"nodelist") == 0) { + if (strcmp(value,"local")==0) + LOCALNODELIST = 1; + } /*else if ( strcasecmp(front,"newsfeeds") == 0) { + printf("newsfeeds %s\n", value); + } else if ( strcasecmp(front,"nodelist") == 0) { + printf("nodelist %s\n", value); + } else if ( strcasecmp(front,"bbsname") == 0) { + printf("bbsname %s\n", value); + } */ + } + fclose(conf); + } + } + +#ifdef WITH_ECHOMAIL + bbsnameptr = (char*) fileglue("%s/bbsname.bbs",INNDHOME); + if ((FN = fopen( bbsnameptr ,"r" ))==NULL) { + fprintf(stderr,"can't open file %s\n", bbsnameptr); + return 0; + } + while ( fscanf(FN,"%s", MYBBSID) != EOF); + fclose(FN); + if( ! isdir(fileglue("%s/out.going",BBSHOME)) ) { + mkdir( (char*)fileglue("%s/out.going",BBSHOME), 0750 ); + } + if (NONENEWSFEEDS == 0) + readnffile(INNDHOME); + if (LOCALNODELIST == 0) { + if (readnlfile(INNDHOME, outgoing) != 0) return 0; + } + +#endif + return 1; +} + +static int +nf_byboardcmp(a,b) +newsfeeds_t **a, **b; +{ +/* + if (!a || !*a || !(*a)->board) return -1; + if (!b || !*b || !(*b)->board) return 1; +*/ + return strcasecmp((*a)->board, (*b)->board); +} + +static int +nfcmp(a,b) +newsfeeds_t *a, *b; +{ +/* + if (!a || !a->newsgroups) return -1; + if (!b || !b->newsgroups) return 1; +*/ + return strcasecmp(a->newsgroups, b->newsgroups); +} + +static int +nlcmp(a,b) +nodelist_t *a, *b; +{ +/* + if (!a || !a->host) return -1; + if (!b || !b->host) return 1; +*/ + return strcasecmp(a->host, b->host); +} + +static int +nl_bynodecmp(a,b) +nodelist_t **a, **b; +{ +/* + if (!a || !*a || !(*a)->node) return -1; + if (!b || !*b || !(*b)->node) return 1; +*/ + return strcasecmp((*a)->node, (*b)->node); +} + +/* read in newsfeeds.bbs and nodelist.bbs */ +readnlfile(inndhome, outgoing) +char *inndhome; +char *outgoing; +{ + FILE *fp; + char buff[1024]; + struct stat st; + int i, count, j; + char *ptr, *nodelistptr; + static lastcount=0; + + sprintf(buff,"%s/nodelist.bbs", inndhome); + fp = fopen(buff,"r"); + if (fp == NULL) { + fprintf(stderr,"open fail %s",buff); + return -1; + } + if (fstat(fileno(fp),&st) != 0) { + fprintf(stderr,"stat fail %s", buff); + return -1; + } + if (NODELIST_BUF == NULL) { + NODELIST_BUF = (char*) mymalloc( st.st_size +1); + } else { + NODELIST_BUF = (char*) myrealloc( NODELIST_BUF, st.st_size +1); + } + i = 0, count =0; + while (fgets(buff, sizeof buff, fp) != NULL) { + if (buff[0] == '#') continue; + if (buff[0] == '\n') continue; + strcpy(NODELIST_BUF+i, buff); + i += strlen(buff); + count ++; + } + fclose(fp); + if (NODELIST == NULL) { + NODELIST = (nodelist_t*) mymalloc(sizeof(nodelist_t) * (count+1)); + NODELIST_BYNODE = (nodelist_t**) mymalloc(sizeof(nodelist_t*) * (count+1)); + } else { + NODELIST = (nodelist_t*) myrealloc(NODELIST, sizeof(nodelist_t) * (count+1)); + NODELIST_BYNODE = (nodelist_t**) myrealloc(NODELIST_BYNODE, sizeof(nodelist_t*) * (count+1)); + } + for (i=lastcount; i< count; i++) { + NODELIST[i].feedfp = NULL; + } + lastcount = count; + NLCOUNT = 0; + for (ptr = NODELIST_BUF; (nodelistptr = (char*)strchr(ptr,'\n')) != NULL; ptr = nodelistptr +1, NLCOUNT++) { + char *nptr , *bptr, *pptr, *tptr; + *nodelistptr = '\0'; + NODELIST[NLCOUNT].host = ""; + NODELIST[NLCOUNT].exclusion = ""; + NODELIST[NLCOUNT].node = ""; + NODELIST[NLCOUNT].protocol = "IHAVE(119)"; + NODELIST[NLCOUNT].comments = ""; + NODELIST_BYNODE[NLCOUNT] = NODELIST+NLCOUNT; + for (nptr= ptr ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') { + bbslog("nodelist.bbs %d entry read error\n", NLCOUNT); + return -1; + } + /*NODELIST[NLCOUNT].id = nptr;*/ + NODELIST[NLCOUNT].node = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') { + bbslog("nodelist.bbs node %d entry read error\n", NLCOUNT); + return -1; + } + *nptr = '\0'; + if ((tptr = strchr(NODELIST[NLCOUNT].node,'/'))) { + *tptr = '\0'; + NODELIST[NLCOUNT].exclusion = tptr + 1; + } else { + NODELIST[NLCOUNT].exclusion = ""; + } + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + if (*nptr=='+' || *nptr=='-') { + NODELIST[NLCOUNT].feedtype = *nptr; + if (NODELIST[NLCOUNT].feedfp != NULL) { + fclose(NODELIST[NLCOUNT].feedfp); + } + if ( NODELIST[NLCOUNT].feedtype == '+') + if (outgoing != NULL) { + NODELIST[NLCOUNT].feedfp = fopen((char*)fileglue("%s/out.going/%s.%s",BBSHOME, NODELIST[NLCOUNT].node, outgoing),"a"); + } + nptr++; + } else { + NODELIST[NLCOUNT].feedtype = ' '; + } + NODELIST[NLCOUNT].host = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') { + continue; + } + *nptr = '\0'; + for (nptr++;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NODELIST[NLCOUNT].protocol = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + *nptr = '\0'; + for (nptr++;*nptr && strchr(" \t\r\n",*nptr); ) nptr++; + if (*nptr == '\0') continue; + NODELIST[NLCOUNT].comments = nptr; + } + qsort(NODELIST, NLCOUNT, sizeof(nodelist_t), nlcmp); + qsort(NODELIST_BYNODE, NLCOUNT, sizeof(nodelist_t*), nl_bynodecmp); + return 0; +} + +readnffile(inndhome) +char *inndhome; +{ + FILE *fp; + char buff[1024]; + struct stat st; + int i, count; + char *ptr, *newsfeedsptr; + + sprintf(buff,"%s/newsfeeds.bbs", inndhome); + fp = fopen(buff,"r"); + if (fp == NULL) { + fprintf(stderr,"open fail %s",buff); + return -1; + } + if (fstat(fileno(fp),&st) != 0) { + fprintf(stderr,"stat fail %s", buff); + return -1; + } + if (NEWSFEEDS_BUF == NULL) { + NEWSFEEDS_BUF = (char*) mymalloc( st.st_size +1); + } else { + NEWSFEEDS_BUF = (char*) myrealloc( NEWSFEEDS_BUF, st.st_size +1); + } + i = 0, count =0; + while (fgets(buff, sizeof buff, fp) != NULL) { + if (buff[0] == '#') continue; + if (buff[0] == '\n') continue; + strcpy(NEWSFEEDS_BUF+i, buff); + i += strlen(buff); + count ++; + } + fclose(fp); + if (NEWSFEEDS == NULL) { + NEWSFEEDS = (newsfeeds_t*) mymalloc(sizeof(newsfeeds_t) * (count+1)); + NEWSFEEDS_BYBOARD = (newsfeeds_t**) mymalloc(sizeof(newsfeeds_t*) * (count+1)); + } else { + NEWSFEEDS = (newsfeeds_t*) myrealloc(NEWSFEEDS, sizeof(newsfeeds_t) * (count+1)); + NEWSFEEDS_BYBOARD = (newsfeeds_t**) myrealloc(NEWSFEEDS_BYBOARD, sizeof(newsfeeds_t*) * (count+1)); + } + NFCOUNT = 0; + for (ptr = NEWSFEEDS_BUF; (newsfeedsptr = (char*)strchr(ptr,'\n')) != NULL; ptr = newsfeedsptr +1, NFCOUNT++) { + char *nptr , *bptr, *pptr; + *newsfeedsptr = '\0'; + NEWSFEEDS[NFCOUNT].newsgroups = ""; + NEWSFEEDS[NFCOUNT].board = ""; + NEWSFEEDS[NFCOUNT].path = NULL; + NEWSFEEDS_BYBOARD[NFCOUNT] = NEWSFEEDS+NFCOUNT; + for (nptr= ptr ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NEWSFEEDS[NFCOUNT].newsgroups = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + *nptr = '\0'; + for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NEWSFEEDS[NFCOUNT].board = nptr; + for (nptr++; *nptr && !isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + *nptr = '\0'; + for (nptr++;*nptr && isspace(*nptr); ) nptr++; + if (*nptr == '\0') continue; + NEWSFEEDS[NFCOUNT].path = nptr; + for (nptr++; *nptr && !strchr("\r\n",*nptr); ) nptr++; + /*if (*nptr == '\0') continue;*/ + *nptr = '\0'; + } + qsort(NEWSFEEDS, NFCOUNT, sizeof(newsfeeds_t), nfcmp); + qsort(NEWSFEEDS_BYBOARD, NFCOUNT, sizeof(newsfeeds_t*), nf_byboardcmp); +} + +newsfeeds_t *search_board(board) +char *board; +{ + newsfeeds_t nft, *nftptr, **find; + if (NONENEWSFEEDS) return NULL; + nft.board = board; + nftptr = &nft; + find = (newsfeeds_t**)bsearch((char*)&nftptr, NEWSFEEDS_BYBOARD, NFCOUNT, sizeof(newsfeeds_t*), nf_byboardcmp); + if (find != NULL) return *find; + return NULL; +} + +nodelist_t *search_nodelist_bynode(node) +char *node; +{ + nodelist_t nlt, *nltptr, **find; + if (LOCALNODELIST) return NULL; + nlt.node = node; + nltptr = ≮ + find = (nodelist_t**)bsearch((char*)&nltptr, NODELIST_BYNODE, NLCOUNT, sizeof(nodelist_t*), nl_bynodecmp); + if (find != NULL) return *find; + return NULL; +} + + +nodelist_t *search_nodelist(site, identuser) +char *site; +char *identuser; +{ + nodelist_t nlt, *find; + char buffer[1024]; + if (LOCALNODELIST) return NULL; + nlt.host = site; + find = (nodelist_t*)bsearch((char*)&nlt, NODELIST, NLCOUNT, sizeof(nodelist_t), nlcmp); + if (find == NULL && identuser != NULL) { + sprintf(buffer,"%s@%s", identuser, site); + nlt.host = buffer; + find = (nodelist_t*)bsearch((char*)&nlt, NODELIST, NLCOUNT, sizeof(nodelist_t), nlcmp); + } + return find; +} + +newsfeeds_t *search_group(newsgroup) +char *newsgroup; +{ + newsfeeds_t nft, *find; + if (NONENEWSFEEDS) return NULL; + nft.newsgroups = newsgroup; + find = (newsfeeds_t*)bsearch((char*)&nft, NEWSFEEDS, NFCOUNT, sizeof(newsfeeds_t), nfcmp); + return find; +} + +char *ascii_date(now) +time_t now; +{ + static char datebuf[40]; + /*time_t now; + time(&now);*/ + strftime(datebuf, sizeof(datebuf), "%d %b %Y %X GMT", gmtime(&now)); + return datebuf; +} + +char * +restrdup(ptr, string) +char *ptr; +char *string; +{ + int len ; + if (string == NULL) { + if (ptr != NULL) *ptr = '\0'; + return ptr; + } + len = strlen(string) + 1; + if (ptr != NULL) { + ptr = (char*)myrealloc(ptr, len); + } else + ptr = (char*)mymalloc(len); + strcpy(ptr, string); + return ptr; +} + + + +void * +mymalloc(size) +int size; +{ + char *ptr = (char*)malloc(size); + if (ptr == NULL) { + fprintf(stderr, "cant allocate memory\n"); + syslog(LOG_ERR, "cant allocate memory %m"); + exit(1); + } + return ptr; +} + +void * +myrealloc(optr, size) +void *optr; +int size; +{ + char *ptr = (char*)realloc(optr, size); + if (ptr == NULL) { + fprintf(stderr, "cant allocate memory\n"); + syslog(LOG_ERR, "cant allocate memory %m"); + exit(1); + } + return ptr; +} + +testandmkdir(dir) +char *dir; +{ + if (!isdir(dir)) { + char path[MAXPATHLEN+12]; + sprintf(path,"mkdir -p %s",dir); + system(path); + } +} + +static char splitbuf[2048]; +static char joinbuf[1024]; +#define MAXTOK 50 +static char* Splitptr[MAXTOK]; +char **split(line,pat) +char *line,*pat; +{ + char *p; + int i; + + for (i=0;i<MAXTOK;++i) Splitptr[i] = NULL; + strncpy(splitbuf,line,sizeof splitbuf - 1 ); + /*printf("%d %d\n",strlen(line),strlen(splitbuf));*/ + splitbuf[sizeof splitbuf - 1] = '\0'; + for (i=0,p=splitbuf;*p && i< MAXTOK -1 ;){ + for (Splitptr[i++]=p;*p && !strchr(pat,*p);p++); + if (*p=='\0') break; + for (*p++='\0'; *p && strchr(pat,*p);p++); + } + return Splitptr; +} + +char **BNGsplit(line) +char *line; +{ + char **ptr = split(line,","); + newsfeeds_t *nf1, *nf2; + char *n11, *n12, *n21, *n22; + int i,j; + for (i=0; ptr[i] != NULL; i++) { + nf1 = (newsfeeds_t*)search_group(ptr[i]); + for (j=i+1; ptr[j] != NULL; j++) { + if (strcmp(ptr[i],ptr[j])==0) { + *ptr[j] = '\0'; + continue; + } + nf2 = (newsfeeds_t*)search_group(ptr[j]); + if (nf1 && nf2) { + if (strcmp(nf1->board,nf2->board)==0) { + *ptr[j] = '\0'; + continue; + } + for (n11 = nf1->board, n12 = (char*)strchr(n11,','); + n11 && *n11 ; n12 = (char*) strchr(n11,',')) { + if (n12) *n12 = '\0'; + for (n21 = nf2->board, n22 = (char*)strchr(n21,','); + n21 && *n21 ; n22 = (char*) strchr(n21,',')) { + if (n22) *n22 = '\0'; + if (strcmp(n11,n21)==0) { + *n21 = '\t'; + } + if (n22) { + *n22 = ','; + n21 = n22 + 1; + } else + break; + } + if (n12) { + *n12 = ','; + n11 = n12 +1; + } else + break; + } + } + } + } + return ptr; +} + +char **ssplit(line,pat) +char *line,*pat; +{ + char *p; + int i; + for (i=0;i<MAXTOK;++i) Splitptr[i] = NULL; + strncpy(splitbuf,line,1024); + for (i=0,p=splitbuf;*p && i< MAXTOK;){ + for (Splitptr[i++]=p;*p && !strchr(pat,*p);p++); + if (*p=='\0') break; + *p=0;p++; +/* for (*p='\0'; strchr(pat,*p);p++);*/ + } + return Splitptr; +} + +char *join(lineptr,pat,num) +char **lineptr,*pat; +int num; +{ + int i; + joinbuf[0] = '\0'; + if (lineptr[0] != NULL) + strncpy(joinbuf,lineptr[0],1024); + else { + joinbuf[0]='\0'; + return joinbuf; + } + for (i=1;i<num;i++) { + strcat(joinbuf,pat); + if (lineptr[i] != NULL) + strcat(joinbuf,lineptr[i]); + else + break; + } + return joinbuf; +} + +#ifdef BBSLIB +main() +{ + initial_bbs("feed"); + printf("%s\n",ascii_date()); +} +#endif + diff --git a/innbbsd/externs.h b/innbbsd/externs.h new file mode 100644 index 00000000..2cde1141 --- /dev/null +++ b/innbbsd/externs.h @@ -0,0 +1,16 @@ +#ifndef EXTERNS_H +#define EXTERNS_H + +# ifndef ARG +# ifdef __STDC__ +# define ARG(x) x +# else +# define ARG(x) () +# endif +# endif + +char *fileglue ARG((char *, ...)); +char *ascii_date ARG(()); +char **split ARG((char *, char *)); + +#endif diff --git a/innbbsd/file.c b/innbbsd/file.c new file mode 100644 index 00000000..d4df15b2 --- /dev/null +++ b/innbbsd/file.c @@ -0,0 +1,185 @@ +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <varargs.h> +#define MAXARGS 100 + +/* isfile is called by + * isfile(filenamecomp1, filecomp2, filecomp3, ..., (char *)0); + * extern "C" int isfile(const char *, const char *[]) ; +*/ + + +char FILEBUF[4096]; + + +static char DOLLAR_[8192]; +char *getstream(fp) +FILE *fp; +{ + return fgets(DOLLAR_, sizeof(DOLLAR_) -1 , fp); +} + +/* + The same as sprintf, but return the new string + fileglue("%s/%s",home,".newsrc"); +*/ + +char *fileglue(va_alist) +va_dcl +{ + va_list ap; + register char* fmt; + static char *newstring; + static char gluebuffer[8192]; + + va_start(ap); + fmt = va_arg(ap, char *) ; + vsprintf(gluebuffer, fmt, ap); + newstring = gluebuffer; + va_end(ap); + return newstring; +} + +long +filesize(filename) +char* filename; +{ + struct stat st; + + if (stat(filename,&st)) return 0; + return st.st_size; +} + +int iszerofile(filename) +char* filename; +{ + struct stat st; + + if (stat(filename,&st)) return 0; + if (st.st_size == 0) return 1; + return 0; +} + +int isfile(filename) +char* filename; +{ + struct stat st; + + if (stat(filename,&st)) return 0; + if (!S_ISREG(st.st_mode)) return 0; + return 1; +} + +int isfilev(va_alist) +va_dcl +{ + va_list ap; + struct stat st; + char *p; + va_start(ap); + + FILEBUF[0]='\0'; + while ((p = va_arg(ap, char *)) != (char *)0) { + strcat(FILEBUF,p); + } + printf("file %s\n",FILEBUF); + + va_end(ap); + return isfile(FILEBUF); +} + + +int isdir(filename) +char* filename; +{ + struct stat st; + + if (stat(filename,&st)) return 0; + if (!S_ISDIR(st.st_mode)) return 0; + return 1; +} + +int isdirv(va_alist) +va_dcl +{ + va_list ap; + struct stat st; + char *p; + va_start(ap); + + FILEBUF[0]='\0'; + while ((p = va_arg(ap, char *)) != (char *)0) { + strcat(FILEBUF,p); + } + + va_end(ap); + return isdir(FILEBUF); +} + +unsigned long mtime(filename) +char* filename; +{ + struct stat st; + if (stat(filename,&st)) return 0; + return st.st_mtime; +} + +unsigned long mtimev(va_alist) +va_dcl +{ + va_list ap; + struct stat st; + char *p; + va_start(ap); + + FILEBUF[0]='\0'; + while ((p = va_arg(ap, char *)) != (char *)0) { + strcat(FILEBUF,p); + } + + va_end(ap); + return mtime(FILEBUF); +} + +unsigned long atime(filename) +char *filename; +{ + struct stat st; + if (stat(filename,&st)) return 0; + return st.st_atime; +} + +unsigned long atimev(va_alist) +va_dcl +{ + va_list ap; + struct stat st; + char *p; + va_start(ap); + + FILEBUF[0]='\0'; + while ((p = va_arg(ap, char *)) != (char *)0) { + strcat(FILEBUF,p); + } + + va_end(ap); + return atime(FILEBUF); +} + +/*#undef TEST*/ +#ifdef TEST +main(argc,argv) +int argc; +char **argv; +{ + int i; + if (argc > 3) { + if (isfilev(argv[1],argv[2],(char*)0)) printf("%s %s %s is file\n",argv[1],argv[2],argv[3]); + if (isdirv(argv[1],argv[2],(char*)0)) printf("%s %s %s is dir\n",argv[1],argv[2],argv[3]); + printf("mtime %d\n",mtimev(argv[1],argv[2],(char*)0)); + printf("atime %d\n",atimev(argv[1],argv[2],(char*)0)); + } + printf("fileglue %s\n", fileglue("%s/%s","home",".test")); +} +#endif diff --git a/innbbsd/his.c b/innbbsd/his.c new file mode 100644 index 00000000..7fe48dc3 --- /dev/null +++ b/innbbsd/his.c @@ -0,0 +1,474 @@ +/* $Revision: 1.1 $ +** +** History file routines. +*/ +#include "innbbsconf.h" +#include "bbslib.h" +#include "his.h" + +#define STATIC static +/*STATIC char HIShistpath[] = _PATH_HISTORY;*/ +STATIC FILE *HISwritefp; +STATIC int HISreadfd; +STATIC int HISdirty; +STATIC int HISincore = XINDEX_DBZINCORE; +STATIC char *LogName = "xindexchan"; + +#ifndef EXPIREDAYS +# define EXPIREDAYS 4 +#endif + +#ifndef DEFAULT_HIST_SIZE +# define DEFAULT_HIST_SIZE 100000 +#endif + +hisincore(flag) +int flag; +{ + HISincore = flag; +} + +makedbz(histpath, entry) +char *histpath; +long entry; +{ + long size; + size = dbzsize(entry); + dbzfresh(histpath,size,'\t',0, 1); + dbmclose(); +} + +void HISsetup(); +void HISclose(); + +void +mkhistory(srchist) +char *srchist; +{ + FILE *hismaint ; + time_t lasthist, now; + char maintbuff[256]; + char *ptr; + hismaint= fopen(srchist, "r"); + if (hismaint == NULL) { + return; + } + { + char newhistpath[1024]; + char newhistdirpath[1024]; + char newhistpagpath[1024]; + sprintf(newhistpath,"%s.n",srchist); + sprintf(newhistdirpath,"%s.n.dir",srchist); + sprintf(newhistpagpath,"%s.n.pag",srchist); + if (!isfile(newhistdirpath) || !isfile(newhistpagpath)) { + makedbz(newhistpath, DEFAULT_HIST_SIZE); + } + myHISsetup(newhistpath); + while ( fgets(maintbuff, sizeof(maintbuff), hismaint) != NULL) { + datum key; + ptr = (char*) strchr(maintbuff,'\t'); + if (ptr != NULL) { *ptr = '\0'; ptr++;} + key.dptr = maintbuff; + key.dsize = strlen(maintbuff); + myHISwrite(&key, ptr); + } + (void) HISclose(); + /*rename(newhistpath, srchist); + rename(newhistdirpath, fileglue("%s.dir", srchist)); + rename(newhistpagpath, fileglue("%s.pag", srchist));*/ + } + fclose(hismaint); +} + +time_t +gethisinfo() +{ + FILE *hismaint ; + time_t lasthist, now; + char maintbuff[4096]; + char *ptr; + hismaint= fopen(HISTORY, "r"); + if (hismaint == NULL) { + return 0; + } + fgets(maintbuff,sizeof(maintbuff), hismaint); + fclose(hismaint); + ptr = (char*)strchr(maintbuff,'\t'); + if (ptr != NULL) { + ptr++; + lasthist = atol(ptr); + return lasthist; + } + return 0; +} + +void +HISmaint() +{ + FILE *hismaint ; + time_t lasthist, now; + char maintbuff[4096]; + char *ptr; + + if (!isfile(HISTORY)) { + makedbz(HISTORY, DEFAULT_HIST_SIZE); + } + hismaint= fopen(HISTORY, "r"); + if (hismaint == NULL) { + return; + } + fgets(maintbuff,sizeof(maintbuff), hismaint); + ptr = (char*)strchr(maintbuff,'\t'); + if (ptr != NULL) { + ptr++; + lasthist = atol(ptr); + time(&now); + if ( lasthist + 86400 * Expiredays * 2 < now ) { + char newhistpath[1024]; + char newhistdirpath[1024]; + char newhistpagpath[1024]; + (void) HISclose(); + sprintf(newhistpath,"%s.n",HISTORY); + sprintf(newhistdirpath,"%s.n.dir",HISTORY); + sprintf(newhistpagpath,"%s.n.pag",HISTORY); + if (!isfile(newhistdirpath)) { + makedbz(newhistpath, DEFAULT_HIST_SIZE); + } + myHISsetup(newhistpath); + while ( fgets(maintbuff, sizeof(maintbuff), hismaint) != NULL) { + datum key; + ptr = (char*) strchr(maintbuff,'\t'); + if (ptr != NULL) { + *ptr = '\0'; ptr++; + lasthist = atol(ptr); + } else { + continue ; + } + if ( lasthist + 99600 * Expiredays < now ) continue; + key.dptr = maintbuff; + key.dsize = strlen(maintbuff); + myHISwrite(&key, ptr); + } + (void) HISclose(); + rename(HISTORY, (char*)fileglue("%s.o",HISTORY)); + rename(newhistpath, HISTORY); + rename(newhistdirpath, (char*)fileglue("%s.dir", HISTORY)); + rename(newhistpagpath, (char*)fileglue("%s.pag", HISTORY)); + (void) HISsetup(); + } + } + fclose(hismaint); +} + + +/* +** Set up the history files. +*/ +void +HISsetup() +{ + myHISsetup(HISTORY); +} + +int +myHISsetup(histpath) +char *histpath; +{ + if (HISwritefp == NULL) { + /* Open the history file for appending formatted I/O. */ + if ((HISwritefp = fopen(histpath, "a")) == NULL) { + syslog(LOG_CRIT, "%s cant fopen %s %m", LogName, histpath); + exit(1); + } + CloseOnExec((int)fileno(HISwritefp), TRUE); + + /* Open the history file for reading. */ + if ((HISreadfd = open(histpath, O_RDONLY)) < 0) { + syslog(LOG_CRIT, "%s cant open %s %m", LogName, histpath); + exit(1); + } + CloseOnExec(HISreadfd, TRUE); + + /* Open the DBZ file. */ + /*(void)dbzincore(HISincore);*/ + (void)dbzincore(HISincore); + (void)dbzwritethrough(1); + if (dbminit(histpath) < 0) { + syslog(LOG_CRIT, "%s cant dbminit %s %m", histpath, LogName); + exit(1); + } + } +} + + +/* +** Synchronize the in-core history file (flush it). +*/ +void +HISsync() +{ + if (HISdirty) { + if (dbzsync()) { + syslog(LOG_CRIT, "%s cant dbzsync %m", LogName); + exit(1); + } + HISdirty = 0; + } +} + + +/* +** Close the history files. +*/ +void +HISclose() +{ + if (HISwritefp != NULL) { + /* Since dbmclose calls dbzsync we could replace this line with + * "HISdirty = 0;". Oh well, it keeps the abstraction clean. */ + HISsync(); + if (dbmclose() < 0) + syslog(LOG_ERR, "%s cant dbmclose %m", LogName); + if (fclose(HISwritefp) == EOF) + syslog(LOG_ERR, "%s cant fclose history %m", LogName); + HISwritefp = NULL; + if (close(HISreadfd) < 0) + syslog(LOG_ERR, "%s cant close history %m", LogName); + HISreadfd = -1; + } +} + + +#ifdef HISset +/* +** File in the DBZ datum for a Message-ID, making sure not to copy any +** illegal characters. +*/ +STATIC void +HISsetkey(p, keyp) + register char *p; + datum *keyp; +{ + static BUFFER MessageID; + register char *dest; + register int i; + + /* Get space to hold the ID. */ + i = strlen(p); + if (MessageID.Data == NULL) { + MessageID.Data = NEW(char, i + 1); + MessageID.Size = i; + } + else if (MessageID.Size < i) { + RENEW(MessageID.Data, char, i + 1); + MessageID.Size = i; + } + + for (keyp->dptr = dest = MessageID.Data; *p; p++) + if (*p == HIS_FIELDSEP || *p == '\n') + *dest++ = HIS_BADCHAR; + else + *dest++ = *p; + *dest = '\0'; + + keyp->dsize = dest - MessageID.Data + 1; +} + +#endif +/* +** Get the list of files under which a Message-ID is stored. +*/ +char * +HISfilesfor(key,output) + datum *key; + datum *output; +{ + char *dest; + datum val; + long offset; + register char *p; + register int i; + int Used; + + /* Get the seek value into the history file. */ + val = dbzfetch(*key); + if (val.dptr == NULL || val.dsize != sizeof offset){ + /*printf("fail here val.dptr %d\n",val.dptr);*/ + return NULL; + } + + /* Get space. */ + if (output->dptr == NULL) { + printf("fail here output->dptr null\n"); + return NULL; + } + + /* Copy the value to an aligned spot. */ + for (p = val.dptr, dest = (char *)&offset, i = sizeof offset; --i >= 0; ) + *dest++ = *p++; + if (lseek(HISreadfd, offset, SEEK_SET) == -1) { + printf("fail here lseek %d\n",offset); + return NULL; + } + + /* Read the text until \n or EOF. */ + for (output->dsize = 0,Used=0; ; ) { + i = read(HISreadfd, + &output->dptr[output->dsize], LEN - 1); + if (i <= 0) { + printf("fail here i %d\n",i); + return NULL; + } + Used += i; + output->dptr[Used] = '\0'; + if ((p = (char*)strchr(output->dptr, '\n')) != NULL) { + *p = '\0'; + break; + } + } + + /* Move past the first two fields -- Message-ID and date info. */ + if ((p = (char*)strchr(output->dptr, HIS_FIELDSEP)) == NULL) { + printf("fail here no HIS_FILE\n"); + return NULL; + } + return p+1; + /*if ((p = (char*)strchr(p + 1, HIS_FIELDSEP)) == NULL) + return NULL;*/ + + /* Translate newsgroup separators to slashes, return the fieldstart. */ +} + +/* +** Have we already seen an article? +*/ +#ifdef HISh +BOOL +HIShavearticle(MessageID) + char *MessageID; +{ + datum key; + datum val; + + HISsetkey(MessageID, &key); + val = dbzfetch(key); + return val.dptr != NULL; +} +#endif + + +/* +** Turn a history filename entry from slashes to dots. It's a pity +** we have to do this. +*/ +STATIC void +HISslashify(p) + register char *p; +{ + register char *last; + + for (last = NULL; *p; p++) { + if (*p == '/') { + *p = '.'; + last = p; + } + else if (*p == ' ' && last != NULL) + *last = '/'; + } + if (last) + *last = '/'; +} + + +IOError(error) +char *error; +{ + fprintf(stderr,"%s\n",error); +} + +/*BOOL*/ +myHISwrite(key, remain) + datum *key; + char *remain; +{ + static char NOPATHS[] = ""; + long offset; + datum val; + int i; + + val = dbzfetch(*key); + if (val.dptr != NULL){ + return FALSE; + } + + flock(fileno(HISwritefp),LOCK_EX); + offset = ftell(HISwritefp); + i = fprintf(HISwritefp, "%s%c%s", + key->dptr, HIS_FIELDSEP, remain); + if (i == EOF || fflush(HISwritefp) == EOF) { + /* The history line is now an orphan... */ + IOError("history"); + syslog(LOG_ERR, "%s cant write history %m", LogName); + flock(fileno(HISwritefp),LOCK_UN); + return FALSE; + } + + /* Set up the database values and write them. */ + val.dptr = (char *)&offset; + val.dsize = sizeof offset; + if (dbzstore(*key, val) < 0) { + IOError("my history database"); + syslog(LOG_ERR, "%s cant dbzstore %m", LogName); + flock(fileno(HISwritefp),LOCK_UN); + return FALSE; + } + + if (++HISdirty >= ICD_SYNC_COUNT) + HISsync(); + flock(fileno(HISwritefp),LOCK_UN); + return TRUE; +} + + +/* +** Write a history entry. +*/ +BOOL +HISwrite(key, date, paths) + datum *key; + char *paths; + long date; +{ + static char NOPATHS[] = ""; + long offset; + datum val; + int i; + + flock(fileno(HISwritefp),LOCK_EX); + offset = ftell(HISwritefp); + i = fprintf(HISwritefp, "%s%c%ld%c%s\n", + key->dptr, HIS_FIELDSEP, (long)date, HIS_FIELDSEP, + paths); + if (i == EOF || fflush(HISwritefp) == EOF) { + /* The history line is now an orphan... */ + IOError("history"); + syslog(LOG_ERR, "%s cant write history %m", LogName); + flock(fileno(HISwritefp),LOCK_UN); + return FALSE; + } + + /* Set up the database values and write them. */ + val.dptr = (char *)&offset; + val.dsize = sizeof offset; + if (dbzstore(*key, val) < 0) { + IOError("history database"); + syslog(LOG_ERR, "%s cant dbzstore %m", LogName); + flock(fileno(HISwritefp),LOCK_UN); + return FALSE; + } + + if (++HISdirty >= ICD_SYNC_COUNT) + HISsync(); + flock(fileno(HISwritefp),LOCK_UN); + return TRUE; +} diff --git a/innbbsd/his.h b/innbbsd/his.h new file mode 100644 index 00000000..f54efc01 --- /dev/null +++ b/innbbsd/his.h @@ -0,0 +1,80 @@ +#ifndef HIS_H +#define HIS_H +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/param.h> +#ifndef SEEK_SET +#include <unistd.h> +#endif +#include "dbz.h" + +#ifndef XINDEXDIR +# define XINDEXDIR "/homec/xindex" +#endif +#ifndef _PATH_HISTORY +# define _PATH_HISTORY "/u/staff/bbsroot/csie_util/bntpd/history" +#endif + +#ifndef _PATH_COVERVIEW +# define _PATH_COVERVIEW ".coverview" +#endif + +#ifndef _PATH_COVERVIEWDIR +# define _PATH_COVERVIEWDIR "/homec/xindex" +#endif + +#ifndef XINDEX_DBZINCORE +# define XINDEX_DBZINCORE 1 +#endif +#ifndef XINDEXNAME +# define XINDEXNAME ".index" +#endif +#ifndef XINDEXDBM +# define XINDEXDBM ".dbm" +#endif +#ifndef XINDEXINFO +# define XINDEXINFO ".info" +#endif + +#define LEN 1024 +struct t_article { + long artnum; + char subject[LEN]; /* Subject: line from mail header */ + char from[LEN]; /* From: line from mail header (address) + */ + char name[LEN]; /* From: line from mail header (full nam +e) */ + long date; /* Date: line from header in seconds */ + char xref[LEN]; /* Xref: cross posted article reference +line */ + int lines; /* Lines: number of lines in article */ + char *archive; /* Archive-name: line from mail header */ + char *part; /* part no. of archive */ + char *patch; /* patch no. of archive */ +}; + +typedef struct t_article art_t; + +#define HIS_BADCHAR '_' +#define HIS_FIELDSEP '\t' +#define HIS_NOEXP "-" +#define HIS_SUBFIELDSEP '~' +/*#define HIS_FIELDSEP2 '\034'*/ +#define HIS_FIELDSEP2 'I' + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +#ifndef BOOL +typedef unsigned char BOOL; +#endif + +#ifndef ICD_SYNC_COUNT +# define ICD_SYNC_COUNT 1 +#endif + +#endif diff --git a/innbbsd/innbbsconf.h b/innbbsd/innbbsconf.h new file mode 100644 index 00000000..6521dde6 --- /dev/null +++ b/innbbsd/innbbsconf.h @@ -0,0 +1,192 @@ +#ifndef INNBBSCONF_H +#define INNBBSCONF_H +#include <stdio.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/un.h> +#include <sys/param.h> +#include <sys/wait.h> + +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> +#ifndef BSD44 +# include <malloc.h> +#endif +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/file.h> + +/*#include "bbs.h"*/ +#if defined(AIX) +# include <sys/select.h> +#endif + +/* + BBS home directory + It has been overridden in Makefile +*/ +#ifndef _PATH_BBSHOME +# define _PATH_BBSHOME "/u/staff/bbsroot/csie_util/bntpd/home" +/*# define _PATH_BBSHOME "/home/bbs"*/ +#endif + +#ifndef EXPIREDAYS +# define EXPIREDAYS 7 +#endif + +#ifndef DEFAULT_HIST_SIZE +# define DEFAULT_HIST_SIZE 100000 +#endif + +/* + Maximum number of connections accepted by innbbsd +*/ +#ifndef MAXCLIENT +# define MAXCLIENT 500 +#endif + +/* + Maximum number of articles received for a newsgroup by bbsnnrp each time +*/ +#ifndef MAX_ARTS +# define MAX_ARTS 100 +#endif + +/* + Maximum size of articles received +*/ +#ifndef MAX_ART_SIZE +# define MAX_ART_SIZE 1000000L +#endif + + +/* + Maximum number of articles stated for a newsgroup by bbsnnrp each time +*/ +#ifndef MAX_STATS +# define MAX_STATS 1000 +#endif + +/* + Mininum wait interval for bbsnnrp +*/ +#ifndef MIN_WAIT +# define MIN_WAIT 60 +#endif + + +#ifndef DefaultINNBBSPort +# define DefaultINNBBSPort "7777" +#endif + +/* + time to maintain history database +*/ +#ifndef HIS_MAINT +# define HIS_MAINT +# define HIS_MAINT_HOUR 4 +# define HIS_MAINT_MIN 30 +#endif + +#ifndef ChannelSize +# define ChannelSize 4096 +#endif + +#ifndef ReadSize +# define ReadSize 1024 +#endif + +#ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +#endif + +#ifndef CLX_IOCTL +# define CLX_IOCTL +#endif + +#define DEFAULTSERVER "your.favorite.news.server" +#define DEFAULTPORT "nntp" +#define DEFAULTPROTOCOL "tcp" +#define DEFAULTPATH ".innbbsd" + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +/* +# ifndef ARG +# ifdef __STDC__ +# define ARG(x) (x) +# else +# define ARG(x) () +# endif +# endif +*/ +/* machine dependend */ +#if defined(__linux) +# ifndef LINUX +# define LINUX +# endif +#endif + +#if !defined(__svr4__) || defined(sun) +# define WITH_TM_GMTOFF +#endif +#if (defined(__svr4__) && defined(sun)) || defined(SOLARIS) +# ifndef SOLARIS +# define SOLARIS +# endif +# define NO_getdtablesize +# define NO_bcopy +# define NO_bzero +# define NO_flock +# define WITH_lockf +#endif + +#if defined(AIX) +# define NO_flock +# define WITH_lockf +#endif + +#if defined(HPUX) +# define NO_getdtablesize +# define NO_flock +# define WITH_lockf +#endif + +#ifdef NO_bcopy +# ifndef bcopy +# define bcopy(a,b,c) memcpy(b,a,c) +# endif +#endif + +#ifdef NO_bzero +# ifndef bzero +# define bzero(mem, size) memset(mem,'\0',size) +# endif +#endif + +#ifndef LOCK_EX +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_UN 8 /* unlock */ +#endif + +#ifdef DEC_ALPHA +# define ULONG unsigned int +#else +# define ULONG unsigned long +#endif + +#ifdef PalmBBS +#undef WITH_RECORD_O +#endif + +#endif diff --git a/innbbsd/innbbsd.c b/innbbsd/innbbsd.c new file mode 100644 index 00000000..f35c1cfb --- /dev/null +++ b/innbbsd/innbbsd.c @@ -0,0 +1,775 @@ +#include "innbbsconf.h" +#include "daemon.h" +#include "innbbsd.h" +#include <dirent.h> +#include "bbslib.h" +#include "inntobbs.h" +#include "nntp.h" + +#ifdef GETRUSAGE +#include <sys/time.h> +#include <sys/resource.h> +#endif + +#ifdef STDC +# ifndef ARG +# define ARG(x) (x) +# else +# define ARG(x) () +# endif +#endif + +/*< add <mid> <recno> ... +> 200 OK +< quit + 500 BYE + +> 300 DBZ Server ... +< query <mid> +> 250 <recno> ... +> 450 NOT FOUND! +*/ + +static int CMDhelp ARG((ClientType*)); +static int CMDquit ARG((ClientType*)); +static int CMDihave ARG((ClientType*)); +static int CMDstat ARG((ClientType*)); +static int CMDaddhist ARG((ClientType*)); +static int CMDgrephist ARG((ClientType*)); +static int CMDmidcheck ARG((ClientType*)); +static int CMDshutdown ARG((ClientType*)); +static int CMDmode ARG((ClientType*)); +static int CMDreload ARG((ClientType*)); +static int CMDhismaint ARG((ClientType*)); +static int CMDverboselog ARG((ClientType*)); +static int CMDlistnodelist ARG((ClientType*)); +static int CMDlistnewsfeeds ARG((ClientType*)); + +#ifdef GETRUSAGE +static int CMDgetrusage ARG((ClientType*)); +static int CMDmallocmap ARG((ClientType*)); +#endif + +static daemoncmd_t cmds[]= +/* cmd-name, cmd-usage, min-argc, max-argc, errorcode, normalcode, cmd-func */ +{ {"help","help [cmd]",1,2,99,100,CMDhelp}, + {"quit","quit",1,0,99,100,CMDquit}, +#ifndef DBZSERVER + {"ihave","ihave mid",2,2,435,335,CMDihave}, +#endif + {"stat","stat mid",2,2,223,430,CMDstat}, + {"addhist","addhist <mid> <path>",3,3, NNTP_ADDHIST_BAD, NNTP_ADDHIST_OK,CMDaddhist}, + {"grephist","grephist <mid>",2,2, NNTP_GREPHIST_BAD, NNTP_GREPHIST_OK, CMDgrephist}, + {"midcheck","midcheck [on|off]",1,2, NNTP_MIDCHECK_BAD, NNTP_MIDCHECK_OK, CMDmidcheck}, + {"shutdown","shutdown (local)",1,1, NNTP_SHUTDOWN_BAD, NNTP_SHUTDOWN_OK, CMDshutdown}, + {"mode","mode (local)",1,1, NNTP_MODE_BAD, NNTP_MODE_OK, CMDmode}, + {"listnodelist","listnodelist (local)",1,1, NNTP_MODE_BAD, NNTP_MODE_OK, CMDlistnodelist}, + {"listnewsfeeds","listnewsfeeds (local)",1,1, NNTP_MODE_BAD, NNTP_MODE_OK, CMDlistnewsfeeds}, + {"reload","reload (local)",1,1, NNTP_RELOAD_BAD, NNTP_RELOAD_OK, CMDreload}, + {"hismaint","hismaint (local)",1,1, NNTP_RELOAD_BAD, NNTP_RELOAD_OK, CMDhismaint}, + {"verboselog","verboselog [on|off](local)",1,2, NNTP_VERBOSELOG_BAD, NNTP_VERBOSELOG_OK, CMDverboselog}, +#ifdef GETRUSAGE + {"getrusage","getrusage (local)",1,1, NNTP_MODE_BAD, NNTP_MODE_OK, CMDgetrusage}, +#endif +#ifdef MALLOCMAP + {"mallocmap","mallocmap (local)",1,1, NNTP_MODE_BAD, NNTP_MODE_OK, CMDmallocmap}, +#endif + {NULL,NULL,0,0,99,100,NULL} +}; + +installinnbbsd() +{ + installdaemon(cmds,100,NULL); +} + +#ifdef OLDLIBINBBSINND +testandmkdir(dir) +char *dir; +{ + if (!isdir(dir)) { + char path[MAXPATHLEN+12]; + sprintf(path,"mkdir -p %s",dir); + system(path); + } +} + +static char splitbuf[2048]; +static char joinbuf[1024]; +#define MAXTOK 50 +static char* Splitptr[MAXTOK]; +char **split(line,pat) +char *line,*pat; +{ + char *p; + int i; + + for (i=0;i<MAXTOK;++i) Splitptr[i] = NULL; + strncpy(splitbuf,line,sizeof splitbuf - 1 ); + /*printf("%d %d\n",strlen(line),strlen(splitbuf));*/ + splitbuf[sizeof splitbuf - 1] = '\0'; + for (i=0,p=splitbuf;*p && i< MAXTOK -1 ;){ + for (Splitptr[i++]=p;*p && !strchr(pat,*p);p++); + if (*p=='\0') break; + for (*p++='\0'; *p && strchr(pat,*p);p++); + } + return Splitptr; +} + +char **BNGsplit(line) +char *line; +{ + char **ptr = split(line,","); + newsfeeds_t *nf1, *nf2; + char *n11, *n12, *n21, *n22; + int i,j; + for (i=0; ptr[i] != NULL; i++) { + nf1 = (newsfeeds_t*)search_group(ptr[i]); + for (j=i+1; ptr[j] != NULL; j++) { + if (strcmp(ptr[i],ptr[j])==0) { + *ptr[j] = '\0'; + continue; + } + nf2 = (newsfeeds_t*)search_group(ptr[j]); + if (nf1 && nf2) { + if (strcmp(nf1->board,nf2->board)==0) { + *ptr[j] = '\0'; + continue; + } + for (n11 = nf1->board, n12 = (char*)strchr(n11,','); + n11 && *n11 ; n12 = (char*) strchr(n11,',')) { + if (n12) *n12 = '\0'; + for (n21 = nf2->board, n22 = (char*)strchr(n21,','); + n21 && *n21 ; n22 = (char*) strchr(n21,',')) { + if (n22) *n22 = '\0'; + if (strcmp(n11,n21)==0) { + *n21 = '\t'; + } + if (n22) { + *n22 = ','; + n21 = n22 + 1; + } else + break; + } + if (n12) { + *n12 = ','; + n11 = n12 +1; + } else + break; + } + } + } + } + return ptr; +} + +char **ssplit(line,pat) +char *line,*pat; +{ + char *p; + int i; + for (i=0;i<MAXTOK;++i) Splitptr[i] = NULL; + strncpy(splitbuf,line,1024); + for (i=0,p=splitbuf;*p && i< MAXTOK;){ + for (Splitptr[i++]=p;*p && !strchr(pat,*p);p++); + if (*p=='\0') break; + *p=0;p++; +/* for (*p='\0'; strchr(pat,*p);p++);*/ + } + return Splitptr; +} + +char *join(lineptr,pat,num) +char **lineptr,*pat; +int num; +{ + int i; + joinbuf[0] = '\0'; + if (lineptr[0] != NULL) + strncpy(joinbuf,lineptr[0],1024); + else { + joinbuf[0]='\0'; + return joinbuf; + } + for (i=1;i<num;i++) { + strcat(joinbuf,pat); + if (lineptr[i] != NULL) + strcat(joinbuf,lineptr[i]); + else + break; + } + return joinbuf; +} + +#endif + +static int CMDtnrpd(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + fprintf(argv->out,"%d %s\n",argv->dc->usage); + return 0; +} + +islocalconnect(client) +ClientType *client; +{ + if (strcmp(client->username,"localuser") != 0 || + strcmp(client->hostname,"localhost") != 0) + return 0; + return 1; +} + +static shutdownflag = 0; +INNBBSDhalt() +{ + shutdownflag = 1; +} + +int INNBBSDshutdown() +{ + return shutdownflag; +} + +static int CMDshutdown(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d shutdown access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Shutdown Put: %d shutdown access denied\n", p->errorcode); + return 1; + } + shutdownflag = 1; + fprintf(argv->out,"%d shutdown starting\r\n", p->normalcode); + fflush(argv->out); + verboselog("Shutdown Put: %d shutdown starting\n", p->normalcode); + return 1; +} + +static int CMDmode(client) +ClientType *client; +{ + /*char cwdpath[MAXPATHLEN+1];*/ + argv_t *argv = &client->Argv; + extern ClientType INNBBSD_STAT; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + time_t uptime, now; + int i,j; + time_t lasthist; + ClientType *client1 = &INNBBSD_STAT; + + if (!islocalconnect(client)) { + fprintf(argv->out,"%d mode access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Mode Put: %d mode access denied\n", p->errorcode); + return 1; + } + fprintf(argv->out,"%d mode\r\n", p->normalcode); + fflush(argv->out); + verboselog("Mode Put: %d mode\n", p->normalcode); + uptime = innbbsdstartup(); + time(&now); + fprintf(argv->out,"up since %salive %.2f days\r\n", ctime(&uptime), (double)(now - innbbsdstartup())/86400); + fprintf(argv->out,"BBSHOME %s\r\n", BBSHOME); + fprintf(argv->out,"MYBBSID %s\r\n", MYBBSID); + fprintf(argv->out,"ECHOMAIL %s\r\n", ECHOMAIL); + fprintf(argv->out,"INNDHOME %s\r\n", INNDHOME); + fprintf(argv->out,"HISTORY %s\r\n", HISTORY); + fprintf(argv->out,"LOGFILE %s\r\n", LOGFILE); + fprintf(argv->out,"INNBBSCONF %s\r\n", INNBBSCONF); + fprintf(argv->out,"BBSFEEDS %s\r\n", BBSFEEDS); + fprintf(argv->out,"Verbose log: %s\r\n", isverboselog() ?"ON":"OFF"); + fprintf(argv->out,"History Expire Days %d\r\n", Expiredays); + fprintf(argv->out,"History Expire Time %d:%d\r\n", His_Maint_Hour, His_Maint_Min); + lasthist = gethisinfo(); + if (lasthist > 0) { + time_t keep = lasthist, keep1; + time(&now); + fprintf(argv->out,"Oldest history entry created: %s",(char*)ctime(&keep)); + keep = Expiredays * 86400 * 2 + lasthist; + keep1 = keep - now ; + fprintf(argv->out,"Next time to maintain history: (%.2f days later) %s",(double)keep1/86400, (char*)ctime(&keep)); + } + fprintf(argv->out,"PID is %d\r\n", getpid()); + fprintf(argv->out,"LOCAL ONLY %d\r\n", LOCALNODELIST); + fprintf(argv->out,"NONE NEWSFEEDS %d\r\n", NONENEWSFEEDS); + fprintf(argv->out,"Max connections %d\r\n", Maxclient); +#ifdef DEBUGCWD + getwd(cwdpath); + fprintf(argv->out,"Working directory %s\r\n", cwdpath); +#endif + if (Channel) + for (i=0, j=0; i< Maxclient; ++i) { + if (Channel[i].fd == -1) continue; + if (Channel+i == client) continue; + j++; + fprintf(argv->out," %d) in->used %d, in->left %d %s@%s\r\n",i, + Channel[i].in.used, Channel[i].in.left, + Channel[i].username,Channel[i].hostname); + } + fprintf(argv->out,"Total connections %d\r\n", j); + fprintf(argv->out,"Total rec: %d dup: %d fail: %d size: %d, stat rec: %d fail: %d\n", client1->ihavecount, client1->ihaveduplicate, client1->ihavefail, client1->ihavesize, client1->statcount, client1->statfail); + fprintf(argv->out,".\r\n"); + fflush(argv->out); + return 1; +} + +static int +CMDlistnodelist(client) +ClientType *client; +{ + int nlcount; + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d listnodelist access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Mallocmap Put: %d listnodelist access denied\n", p->errorcode); + return 1; + } + fprintf(argv->out,"%d listnodelist\r\n", p->normalcode); + for (nlcount =0; nlcount < NLCOUNT; nlcount++) { + nodelist_t *nl = NODELIST+nlcount; + fprintf(argv->out,"%2d %s /\\/\\ %s\r\n", nlcount+1, nl->node==NULL?"":nl->node, nl->exclusion==NULL?"":nl->exclusion); + fprintf(argv->out," %s:%s:%s\r\n",nl->host==NULL?"":nl->host, nl->protocol==NULL?"":nl->protocol, nl->comments == NULL ? "": nl->comments); + } + fprintf(argv->out,".\r\n"); + fflush(argv->out); + verboselog("Listnodelist Put: %d listnodelist complete\n", p->normalcode); + return 1; +} + +static int +CMDlistnewsfeeds(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + int nfcount; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d listnewsfeeds access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Mallocmap Put: %d listnewsfeeds access denied\n", p->errorcode); + return 1; + } + fprintf(argv->out,"%d listnewsfeeds\r\n", p->normalcode); + for (nfcount =0; nfcount < NFCOUNT; nfcount++) { + newsfeeds_t *nf = NEWSFEEDS + nfcount; + fprintf(argv->out,"%3d %s<=>%s\r\n",nfcount+1, nf->newsgroups, nf->board); + fprintf(argv->out," %s\r\n",nf->path==NULL?"(Null)":nf->path); + } + fprintf(argv->out,".\r\n"); + fflush(argv->out); + verboselog("Listnewsfeeds Put: %d listnewsfeeds complete\n", p->normalcode); + return 1; +} + +#ifdef MALLOCMAP +static int CMDmallocmap(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + struct rusage ru; + int savefd ; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d mallocmap access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Mallocmap Put: %d mallocmap access denied\n", p->errorcode); + return 1; + } + fprintf(argv->out,"%d mallocmap\r\n", p->normalcode); + savefd = dup(1); + dup2(client->fd, 1); + mallocmap(); + dup2(savefd, 1); + close(savefd); + fprintf(argv->out,".\r\n"); + fflush(argv->out); + verboselog("Mallocmap Put: %d mallocmap complete\n", p->normalcode); + return 1; +} +#endif + +#ifdef GETRUSAGE +static int CMDgetrusage(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + struct rusage ru; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d getrusage access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Getrusage Put: %d getrusage access denied\n", p->errorcode); + return 1; + } + fprintf(argv->out,"%d getrusage\r\n", p->normalcode); + if (getrusage(RUSAGE_SELF,&ru) == 0) { + fprintf(argv->out,"user time used: %.6f\r\n",(double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec/1000000.0); + fprintf(argv->out,"system time used: %.6f\r\n",(double)ru.ru_stime.tv_sec + (double)ru.ru_stime.tv_usec/1000000.0); + fprintf(argv->out,"maximum resident set size: %lu\r\n",ru.ru_maxrss * getpagesize()); + fprintf(argv->out,"integral resident set size: %lu\r\n",ru.ru_idrss * getpagesize()); + fprintf(argv->out,"page faults not requiring physical I/O: %d\r\n",ru.ru_minflt); + fprintf(argv->out,"page faults requiring physical I/O: %d\r\n",ru.ru_majflt); + fprintf(argv->out,"swaps: %d\r\n",ru.ru_nswap); + fprintf(argv->out,"block input operations: %d\r\n",ru.ru_inblock); + fprintf(argv->out,"block output operations: %d\r\n",ru.ru_oublock); + fprintf(argv->out,"messages sent: %d\r\n",ru.ru_msgsnd); + fprintf(argv->out,"messages received: %d\r\n",ru.ru_msgrcv); + fprintf(argv->out,"signals received: %d\r\n",ru.ru_nsignals); + fprintf(argv->out,"voluntary context switches: %d\r\n",ru.ru_nvcsw); + fprintf(argv->out,"involuntary context switches: %d\r\n",ru.ru_nivcsw); + } + fprintf(argv->out,".\r\n"); + fflush(argv->out); + verboselog("Getrusage Put: %d getrusage complete\n", p->normalcode); + return 1; +} + +#endif + +static int CMDhismaint(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d hismaint access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Hismaint Put: %d hismaint access denied\n", p->errorcode); + return 1; + } + verboselog("Hismaint Put: %d hismaint start\n", p->normalcode); + HISmaint(); + fprintf(argv->out,"%d hismaint complete\r\n", p->normalcode); + fflush(argv->out); + verboselog("Hismaint Put: %d hismaint complete\n", p->normalcode); + return 1; +} + +static int CMDreload(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d reload access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Reload Put: %d reload access denied\n", p->errorcode); + return 1; + } + initial_bbs("feed"); + fprintf(argv->out,"%d reload complete\r\n", p->normalcode); + fflush(argv->out); + verboselog("Reload Put: %d reload complete\n", p->normalcode); + return 1; +} + +static int CMDverboselog(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (!islocalconnect(client)) { + fprintf(argv->out,"%d verboselog access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Reload Put: %d verboselog access denied\n", p->errorcode); + return 1; + } + if (client->mode == 0) { + if (argv->argc > 1) { + if (strcasecmp(argv->argv[1],"off")==0) { + setverboseoff(); + } else { + setverboseon(); + } + } + } + fprintf(argv->out,"%d verboselog %s\r\n",p->normalcode, + isverboselog() ?"ON":"OFF"); + fflush(argv->out); + verboselog("%d verboselog %s\r\n",p->normalcode, + isverboselog()?"ON":"OFF"); +} + +static int CMDmidcheck(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (client->mode == 0) { + if (argv->argc > 1) { + if (strcasecmp(argv->argv[1],"off")==0) { + client->midcheck = 0; + } else { + client->midcheck = 1; + } + } + } + fprintf(argv->out,"%d mid check %s\r\n",p->normalcode, + client->midcheck == 1?"ON":"OFF"); + fflush(argv->out); + verboselog("%d mid check %s\r\n",p->normalcode, + client->midcheck == 1?"ON":"OFF"); +} + +static int CMDgrephist(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + if (client->mode == 0) { + if (argv->argc > 1) { + char *ptr; + ptr = (char*)DBfetch(argv->argv[1]); + if (ptr != NULL) { + fprintf(argv->out,"%d %s OK\r\n", p->normalcode, ptr); + fflush(argv->out); + verboselog("Addhist Put: %d %s OK\n", p->normalcode, ptr); + return 0; + } else { + fprintf(argv->out,"%d %s not found\r\n", p->errorcode,argv->argv[1]); + fflush(argv->out); + verboselog("Addhist Put: %d %s not found\n", p->errorcode, argv->argv[1]); + return 1; + } + } + } + fprintf(argv->out,"%d grephist error\r\n", p->errorcode); + fflush(argv->out); + verboselog("Addhist Put: %d grephist error\n", p->errorcode); + return 1; +} + + +static int CMDaddhist(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + buffer_t *in = &client->in; + daemoncmd_t *p = argv->dc; + /* + if (strcmp(client->username,"localuser") != 0 || + strcmp(client->hostname,"localhost") != 0) { + fprintf(argv->out,"%d add hist access denied\r\n", p->errorcode); + fflush(argv->out); + verboselog("Addhist Put: %d add hist access denied\n", p->errorcode); + return 1; + } + */ + if (client->mode == 0) { + if (argv->argc > 2) { + char *ptr; + ptr = (char*)DBfetch(argv->argv[1]); + if (ptr == NULL) { + if (storeDB(argv->argv[1], argv->argv[2]) < 0) { + fprintf(argv->out,"%d add hist store DB error\r\n", p->errorcode); + fflush(argv->out); + verboselog("Addhist Put: %d add hist store DB error\n", p->errorcode); + return 1; + } else { + fprintf(argv->out,"%d add hist OK\r\n", p->normalcode); + fflush(argv->out); + verboselog("Addhist Put: %d add hist OK\n", p->normalcode); + return 0; + } + } else { + fprintf(argv->out,"%d add hist duplicate error\r\n", p->errorcode); + fflush(argv->out); + verboselog("Addhist Put: %d add hist duplicate error\n", p->errorcode); + return 1; + } + } + } + fprintf(argv->out,"%d add hist error\r\n", p->errorcode); + fflush(argv->out); + verboselog("Addhist Put: %d add hist error\n", p->errorcode); + return 1; +} + +static int CMDstat(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + char *ptr, *frontptr; + buffer_t *in = &client->in; + daemoncmd_t *p; + if (client->mode == 0) { + client->statcount++; + if (argv->argc > 1) { + if (argv->argv[1][0] != '<') { + fprintf(argv->out,"430 No such article\r\n"); + fflush(argv->out); + verboselog("Stat Put: 430 No such article\n"); + client->statfail++; + return 0; + } + ptr = (char*)DBfetch(argv->argv[1]); + if (ptr != NULL) { + fprintf(argv->out,"223 0 status %s\r\n",argv->argv[1]); + fflush(argv->out); + client->mode = 0; + verboselog("Stat Put: 223 0 status %s\n",argv->argv[1]); + return 1; + } else { + fprintf(argv->out,"430 No such article\r\n"); + fflush(argv->out); + verboselog("Stat Put: 430 No such article\n"); + client->mode = 0; + client->statfail++; + } + } + } +} + +#ifndef DBZSERVER +static int CMDihave(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + char *ptr=NULL, *frontptr; + buffer_t *in = &client->in; + daemoncmd_t *p; + if (client->mode == 0) { + client->ihavecount++; + if (argv->argc > 1) { + if (argv->argv[1][0] != '<') { + fprintf(argv->out,"435 Bad Message-ID\r\n"); + fflush(argv->out); + verboselog("Ihave Put: 435 Bad Message-ID\n"); + client->ihavefail++; + return 0; + } + if (client->midcheck == 1) + ptr = (char*)DBfetch(argv->argv[1]); + if (ptr != NULL && client->midcheck == 1) { + fprintf(argv->out,"435 Duplicate\r\n"); + fflush(argv->out); + client->mode = 0; + verboselog("Ihave Put: 435 Duplicate\n"); + client->ihaveduplicate++; + client->ihavefail++; + return 1; + } else { + fprintf(argv->out,"335\r\n"); + fflush(argv->out); + client->mode = 1; + verboselog("Ihave Put: 335\n"); + } + } + } else { + client->mode = 0; + readlines(client); + if (HEADER[SUBJECT_H] && HEADER[FROM_H] && HEADER[DATE_H] && + HEADER[MID_H] && HEADER[NEWSGROUPS_H] ) { + char *path1, *path2; + int rel ; + rel = 0; + path1 = (char*)mymalloc(strlen(HEADER[PATH_H]) + 3); + path2 = (char*)mymalloc(strlen(MYBBSID) + 3); + sprintf(path1, "!%s!",HEADER[PATH_H]); + sprintf(path2, "!%s!",MYBBSID); + if (HEADER[CONTROL_H]) { + bbslog( "Control: %s\n", HEADER[CONTROL_H] ); + if (strncasecmp(HEADER[CONTROL_H],"cancel ",7)==0) { + rel = cancel_article_front(HEADER[CONTROL_H]+7); + } else { + rel = receive_control(); + } + } else if ( (char*)strstr(path1, path2) != NULL) { + bbslog( ":Warn: Loop back article: %s!%s\n",MYBBSID,HEADER[PATH_H] ); + } else { + rel = receive_article(); + } + free(path1); + free(path2); + if (rel == -1) { + fprintf(argv->out,"400 server side failed\r\n"); + fflush(argv->out); + verboselog("Ihave Put: 400\n"); + clearfdset(client->fd); + fclose(client->Argv.in); + fclose(client->Argv.out); + close(client->fd); + client->fd = -1; + client->mode = 0; + client->ihavefail++; + return; + } else { + fprintf(argv->out,"235\r\n"); + verboselog("Ihave Put: 235\n"); + } + fflush(argv->out); + } else if (!HEADER[PATH_H]) { + fprintf(argv->out,"437 No Path in \"ihave %s\" header\r\n",HEADER[MID_H]); + fflush(argv->out); + verboselog("Put: 437 No Path in \"ihave %s\" header\n",HEADER[MID_H]); + client->ihavefail++; + } else { + fprintf(argv->out,"437 No colon-space in \"ihave %s\" header\r\n",HEADER[MID_H]); + fflush(argv->out); + verboselog("Ihave Put: 437 No colon-space in \"ihave %s\" header\n",HEADER[MID_H]); + client->ihavefail++; + } +#ifdef DEBUG + printf("subject is %s\n",HEADER[SUBJECT_H]); + printf("from is %s\n",HEADER[FROM_H]); + printf("Date is %s\n",HEADER[DATE_H]); + printf("Newsgroups is %s\n",HEADER[NEWSGROUPS_H]); + printf("mid is %s\n",HEADER[MID_H]); + printf("path is %s\n",HEADER[PATH_H]); +#endif + } + fflush(argv->out); + return 0; +} +#endif + +static int CMDhelp(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + daemoncmd_t *p; + if (argv->argc>=1) { + fprintf(argv->out,"%d Available Commands\r\n",argv->dc->normalcode); + for (p=cmds;p->name !=NULL;p++) { + fprintf(argv->out," %s\r\n",p->usage); + } + fprintf(argv->out,"Report problems to %s\r\n",ADMINUSER); + } + fputs(".\r\n",argv->out); + fflush(argv->out); + client->mode = 0; + return 0; +} + +static int CMDquit(client) +ClientType *client; +{ + argv_t *argv = &client->Argv; + fprintf(argv->out,"205 quit\r\n"); + fflush(argv->out); + verboselog("Quit Put: 205 quit\n"); + clearfdset(client->fd); + fclose(client->Argv.in); + fclose(client->Argv.out); + close(client->fd); + client->fd = -1; + client->mode = 0; + channeldestroy(client); + /*exit(0);*/ +} diff --git a/innbbsd/innbbsd.h b/innbbsd/innbbsd.h new file mode 100644 index 00000000..ba667ee6 --- /dev/null +++ b/innbbsd/innbbsd.h @@ -0,0 +1,9 @@ +#ifndef INNBBSD_H +#define INNBBSD_H +#include "daemon.h" + +#ifndef ADMINUSER +# define ADMINUSER "usenet@csie.nctu.edu.tw" +#endif + +#endif diff --git a/innbbsd/inndchannel.c b/innbbsd/inndchannel.c new file mode 100644 index 00000000..439b2af0 --- /dev/null +++ b/innbbsd/inndchannel.c @@ -0,0 +1,657 @@ +#include "innbbsconf.h" +#include "daemon.h" +#include "bbslib.h" +#include "config.h" + +#define DEBUG +#undef DEBUG + +#ifndef MAXCLIENT +#define MAXCLIENT 500 +#endif + +#ifndef ChannelSize +#define ChannelSize 4096 +#endif + +#ifndef ReadSize +#define ReadSize 1024 +#endif + +#ifndef DefaultINNBBSPort +# define DefaultINNBBSPort "7777" +#endif + +#ifndef HIS_MAINT +# define HIS_MAINT +# define HIS_MAINT_HOUR 5 +# define HIS_MAINT_MIN 30 +#endif + +int Maxclient=MAXCLIENT; +ClientType *Channel=NULL; +ClientType INNBBSD_STAT; + +int Max_Art_Size = MAX_ART_SIZE; + +int inetdstart = 0; + +int Junkhistory = 0; + +char *REMOTEUSERNAME, *REMOTEHOSTNAME; + +static fd_set rfd,wfd,efd,orfd,owfd,oefd; + +clearfdset(fd) +int fd; +{ + FD_CLR(fd,&rfd); +} + +static +channelcreate(client) +ClientType *client; +{ + buffer_t *in, *out; + in = &client->in; + out = &client->out; + if (in->data != NULL) + free(in->data); + in->data = (char*)mymalloc( ChannelSize ); + in->left = ChannelSize; + in->used = 0; + if (out->data != NULL) + free(out->data); + out->data = (char*)mymalloc( ChannelSize ); + out->used = 0; + out->left = ChannelSize; + client->ihavecount = 0; + client->ihaveduplicate = 0; + client->ihavefail = 0; + client->ihavesize = 0; + client->statcount = 0; + client->statfail = 0; + client->begin = time(NULL); +} + +channeldestroy(client) +ClientType *client; +{ + if (client->in.data != NULL) { + free(client->in.data); + client->in.data = NULL; + } + if (client->out.data != NULL) { + free(client->out.data); + client->out.data = NULL; + } +#if !defined(PowerBBS) && !defined(DBZSERVER) + if (client->ihavecount >0 || client->statcount >0) { + bbslog("%s@%s rec: %d dup: %d fail: %d size: %d, stat rec: %d fail: %d, time sec: %d\n", + client->username, client->hostname, client->ihavecount, + client->ihaveduplicate, client->ihavefail, client->ihavesize, + client->statcount, client->statfail, time(NULL) - client->begin); + INNBBSD_STAT.ihavecount += client->ihavecount; + INNBBSD_STAT.ihaveduplicate += client->ihaveduplicate; + INNBBSD_STAT.ihavefail += client->ihavefail; + INNBBSD_STAT.ihavesize += client->ihavesize; + INNBBSD_STAT.statcount += client->statcount; + INNBBSD_STAT.statfail += client->statfail; + } +#endif +} + +inndchannel(port, path) +char *port, *path; +{ + time_t tvec; + int i; + int bbsinnd ; + int localbbsinnd; + char obuf[4096]; + struct timeval tout; + ClientType *client = (ClientType *)mymalloc( sizeof(ClientType) * Maxclient); + int localdaemonready = 0; + Channel = client; + + bbsinnd = pmain(port); + if (bbsinnd < 0) { + perror("pmain, existing"); + docompletehalt(); + return(-1); + } + + FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&efd); + + localbbsinnd = p_unix_main(path); + if (localbbsinnd < 0) { + perror("local pmain, existing"); +/* Kaede + if (!inetdstart) + fprintf(stderr, "if no other innbbsd running, try to remove %s\n",path); +*/ + close(bbsinnd); + return(-1); + } else { + FD_SET(localbbsinnd,&rfd); + localdaemonready = 1; + } + + FD_SET(bbsinnd,&rfd); + tvec = time((time_t *)0); + for (i=0;i< Maxclient ;++i) { + client[i].fd = -1; + client[i].access=0; + client[i].buffer[0] = '\0'; + client[i].mode = 0; + client[i].in.left = 0; + client[i].in.used = 0; + client[i].in.data = NULL; + client[i].out.left = 0; + client[i].out.used = 0; + client[i].out.data = NULL; + client[i].midcheck = 1; + } + for (;;) { + int nsel,i; + +/* + When to maintain history files. +*/ + time_t now; + static int maint = 0; + struct tm *local; + + if (INNBBSDshutdown()) { + HISclose(); + bbslog(" Shutdown Complete \n"); + docompletehalt(); + exit(0); + } + + time(&now); + local = localtime(&now); + if (local != NULL & local->tm_hour == His_Maint_Hour && + local->tm_min >= His_Maint_Min ) { + if (!maint) { + bbslog(":Maint: start (%d:%d).\n",local->tm_hour,local->tm_min); + HISmaint(); + time(&now); + local = localtime(&now); + if (local != NULL) + bbslog(":Maint: end (%d:%d).\n",local->tm_hour,local->tm_min); + maint = 1; + } + } else { + maint = 0; + } +/* +*/ +/* + in order to maintain history, timeout every 60 seconds in case + no connections +*/ + tout.tv_sec = 60; + tout.tv_usec = 0; + orfd = rfd; + if ((nsel=select(FD_SETSIZE,&orfd, NULL , NULL , &tout))<0){ + continue; + } + if (localdaemonready && FD_ISSET(localbbsinnd,&orfd)) { + int ns,length; + int cc; + ns=tryaccept(localbbsinnd); + if (ns < 0) continue; + for (i=0;i< Maxclient ;++i) { + if (client[i].fd==-1) break; + } + if (i== Maxclient) { + static char msg[]="502 no free descriptors\r\n"; + printf("%s",msg); + write(ns, msg, sizeof(msg)); + close(ns); + continue; + } + client[i].fd=ns; + client[i].buffer[0] = '\0'; + client[i].mode = 0; + client[i].midcheck = 1; + channelcreate(&client[i]); + FD_SET(ns,&rfd); /*FD_SET(ns,&wfd);*/ + { + strncpy(client[i].username,"localuser",20); + strncpy(client[i].hostname,"localhost",128); + client[i].Argv.in = fdopen( ns,"r"); + client[i].Argv.out = fdopen( ns,"w"); +#if !defined(PowerBBS) && !defined(DBZSERVER) + bbslog("connected from (%s@%s).\n",client[i].username, client[i].hostname); +#endif +#ifdef INNBBSDEBUG + printf("connected from (%s@%s).\n",client[i].username, client[i].hostname); +#endif +#ifdef DBZSERVER + fprintf(client[i].Argv.out,"200 %s InterNetNews DBZSERVER server %s (%s@%s).\r\n",MYBBSID, VERSION, client[i].username, client[i].hostname); +#else + fprintf(client[i].Argv.out,"200 %s InterNetNews INNBBSD server %s (%s@%s).\r\n", MYBBSID, VERSION, client[i].username, client[i].hostname ); +#endif + fflush(client[i].Argv.out); + verboselog("UNIX Connect from %s@%s\n",client[i].username, client[i].hostname); + } + } + + if (FD_ISSET(bbsinnd,&orfd)) { + int ns=tryaccept(bbsinnd), length; + struct sockaddr_in there; + char *name; + struct hostent *hp; + int cc; + if (ns < 0) continue; + for (i=0;i< Maxclient ;++i) { + if (client[i].fd==-1) break; + } + if (i== Maxclient) { + static char msg[]="502 no free descriptors\r\n"; + printf("%s",msg); + write(ns, msg, sizeof(msg)); + close(ns); + continue; + } + client[i].fd=ns; + client[i].buffer[0] = '\0'; + client[i].mode = 0; + client[i].midcheck = 1; + channelcreate(&client[i]); + FD_SET(ns,&rfd); /*FD_SET(ns,&wfd);*/ + length = sizeof(there); + if (getpeername(ns,(struct sockaddr *)&there,&length)>=0){ + time_t now=time((time_t *)0); + name=(char*)my_rfc931_name(ns,&there); + strncpy(client[i].username,name,20); + hp = (struct hostent*)gethostbyaddr((char*)&there.sin_addr, sizeof (struct in_addr), there.sin_family); + if (hp) + strncpy(client[i].hostname,hp->h_name,128); + else + strncpy(client[i].hostname,(char*)inet_ntoa(there.sin_addr),128); + + client[i].Argv.in = fdopen( ns,"r"); + client[i].Argv.out = fdopen( ns,"w"); + if ((char*)search_nodelist(client[i].hostname,client[i].username) == NULL) { + bbslog(":Err: invalid connection (%s@%s).\n",client[i].username, client[i].hostname); + fprintf(client[i].Argv.out,"502 You are not in my access file. (%s@%s)\r\n", client[i].username, client[i].hostname); + fflush(client[i].Argv.out); + fclose(client[i].Argv.in); + fclose(client[i].Argv.out); + close(client[i].fd); + FD_CLR(client[i].fd,&rfd); + client[i].fd = -1; + continue; + } + bbslog("connected from (%s@%s).\n",client[i].username, client[i].hostname); +#ifdef INNBBSDEBUG + printf("connected from (%s@%s).\n",client[i].username, client[i].hostname); +#endif +#ifdef DBZSERVER + fprintf(client[i].Argv.out,"200 %s InterNetNews DBZSERVER server %s (%s@%s).\r\n",MYBBSID, VERSION, client[i].username, client[i].hostname ); +#else + fprintf(client[i].Argv.out,"200 %s InterNetNews INNBBSD server %s (%s@%s).\r\n",MYBBSID, VERSION, client[i].username, client[i].hostname ); +#endif + fflush(client[i].Argv.out); + verboselog("INET Connect from %s@%s\n",client[i].username, client[i].hostname); + } else { + } + + } + for (i=0;i< Maxclient ;++i) { + int fd=client[i].fd; + if (fd < 0) { + continue; + } + if (FD_ISSET(fd,&orfd)) { + int nr; +#ifdef DEBUG + printf("before read i %d in.used %d in.left %d\n",i,client[i].in.used, client[i].in.left); +#endif + nr=channelreader(client+i); +#ifdef DEBUG + printf("after read i %d in.used %d in.left %d\n",i,client[i].in.used, client[i].in.left); +#endif + /*int nr=read(fd,client[i].buffer,1024);*/ + if (nr <= 0) { + FD_CLR(fd,&rfd); + fclose(client[i].Argv.in); + fclose(client[i].Argv.out); + close(fd); + client[i].fd = -1; + channeldestroy(client+i); + continue; + } +#ifdef DEBUG + printf("nr %d %.*s", nr, nr, client[i].buffer); +#endif + if (client[i].access==0) { + continue; + } + } + } + } +} + +int channelreader(client) +ClientType *client; +{ + int len, clientlen; + char buffer1[8192], buffer2[4096]; + char *ptr; + buffer_t *in = &client->in; + + if (in->left < ReadSize+3) { + int need = in->used + in->left + ReadSize + 3; + need += need/5 ; + in->data = (char*)myrealloc(in->data, need); + in->left = need - in->used; + verboselog("channelreader realloc %d\n",need); + } + len = read(client->fd, in->data+in->used, ReadSize); + + if (len <=0) return len; + + in->data[len+in->used] = '\0'; + in->lastread = len; +#ifdef DEBUG + printf("after read lastread %d\n", in->lastread); + printf("len %d client %d\n", len, strlen(in->data+in->used)); +#endif + + REMOTEHOSTNAME = client->hostname; + REMOTEUSERNAME = client->username; + if (client->mode == 0) { + if ( (ptr=(char*)strchr(in->data,'\n')) != NULL) { + if (in->data[0] != '\r') + commandparse(client); + } + } else { + commandparse(client); + } + return len; +} + +commandparse(client) +ClientType *client; +{ + char *ptr, *lastend; + argv_t *Argv = &client->Argv; + int (*Main)(); + char *buffer = client->in.data; + int fd = client->fd; + buffer_t *in = &client->in; + int dataused; + int dataleft; + +#ifdef DEBUG + printf("%s %s buffer %s",client->username, client->hostname, buffer); +#endif + ptr= (char*) strchr(in->data+in->used,'\n'); + if (client->mode == 0) { + if (ptr == NULL) { + in->used += in->lastread; + in->left -= in->lastread; + return; + } else { + dataused = ptr - (in->data + in->used) + 1; + dataleft = in->lastread - dataused; + lastend = ptr + 1; + } + } else { + if (in->used >= 5) { + ptr = (char*) strstr(in->data+in->used-5,"\r\n.\r\n"); + } else if (strncmp(in->data,".\r\n",3)==0) { + ptr = in->data; + } else { + ptr = (char*) strstr(in->data+in->used,"\r\n.\r\n"); + } + if (ptr == NULL) { + in->used += in->lastread; + in->left -= in->lastread; + return; + } else { + ptr[2]='\0'; + if ( strncmp(in->data,".\r\n",3)==0) + dataused = 3; + else + dataused = ptr - (in->data + in->used) + 5; + dataleft = in->lastread - dataused; + lastend = ptr + 5; + verboselog("Get: %s@%s end of data . size %d\n", client->username, client->hostname, in->used + dataused); + client->ihavesize += in->used + dataused; + } + } + if (client->mode == 0) { + struct Daemoncmd * dp; + Argv->argc = 0, Argv->argv = NULL, + Argv->inputline= buffer; + if ( ptr != NULL) *ptr = '\0'; + verboselog("Get: %s\n",Argv->inputline); + Argv->argc = argify( in->data + in->used,&Argv->argv); + if ( ptr != NULL) *ptr = '\n'; + dp = (struct Daemoncmd *) searchcmd(Argv->argv[0]); + Argv->dc = dp; + if (Argv->dc) { +#ifdef DEBUG + printf("enter command %s\n",Argv->argv[0]); +#endif + if (Argv->argc < dp->argc) { + fprintf(Argv->out,"%d Usage: %s\r\n",dp->errorcode,dp->usage); + fflush(Argv->out); + verboselog("Put: %d Usage: %s\n",dp->errorcode,dp->usage); + } else if (dp->argno != 0 && Argv->argc > dp->argno) { + fprintf(Argv->out,"%d Usage: %s\r\n",dp->errorcode,dp->usage); + fflush(Argv->out); + verboselog("Put: %d Usage: %s\n",dp->errorcode,dp->usage); + } else { + Main=Argv->dc->main; + if (Main) { + fflush(stdout); + (*Main)(client); + } + } + } else { + fprintf(Argv->out,"500 Syntax error or bad command\r\n"); + fflush(Argv->out); + verboselog("Put: 500 Syntax error or bad command\r\n"); + } + deargify(&Argv->argv); + } else { + if (Argv->dc) { +#ifdef DEBUG + printf("enter data mode\n"); +#endif + Main=Argv->dc->main; + if (Main) { + fflush(stdout); + (*Main)(client); + } + } + } + if (client->mode == 0) { + if (dataleft > 0) { + strncpy(in->data, lastend, dataleft); +#ifdef INNBBSDEBUG + printf("***** try to copy %x %x %d bytes\n",in->data, lastend, dataleft); +#endif + } else { + dataleft = 0; + } + in->left += in->used - dataleft; + in->used = dataleft; + } +} + +do_command() +{ +} + +void dopipesig(s) +int s; +{ + printf("catch sigpipe\n"); + signal(SIGPIPE, dopipesig); +} + +int standaloneinit(port) +char *port ; +{ + int ndescriptors; + FILE *pf; + char pidfile[24]; + ndescriptors = getdtablesize(); +/*#ifndef NOFORK*/ + if (!inetdstart) + if (fork()) + exit(0); +/*#endif*/ + + sprintf(pidfile,"/tmp/innbbsd-%s.pid",port); +/* Kaede + if (!inetdstart) + fprintf(stderr, "PID file is in %s\n", pidfile); +*/ + { int s; + for (s = 3; s < ndescriptors; s++) + (void) close(s); + } + pf=fopen(pidfile,"w"); + if (pf != NULL) { + fprintf(pf,"%d\n",getpid()); + fclose(pf); + } +} + +extern char *optarg; +extern int opterr, optind; + +innbbsusage(name) +char *name; +{ + fprintf(stderr,"Usage: %s [options] [port [path]]\n",name); + fprintf(stderr," -v (verbose log)\n"); + fprintf(stderr," -h|? (help)\n"); + fprintf(stderr," -n (not to use in core dbz)\n"); + fprintf(stderr," -i (start from inetd with wait option)\n"); + fprintf(stderr," -c connections (maximum number of connections accepted)\n"); + fprintf(stderr," default=%d\n",Maxclient); + fprintf(stderr," -j (keep history of junk article, default=none)\n"); +} + + +#ifdef DEBUGNGSPLIT +main() +{ + char **ngptr ; + char buf[1024]; + gets(buf); + ngptr = (char**)BNGsplit(buf); + printf("line %s\n",buf); + while ( *ngptr != NULL) { + printf("%s\n",*ngptr); + ngptr++; + } +} +#endif + +static time_t INNBBSDstartup; +innbbsdstartup() +{ + return INNBBSDstartup; +} + +main(argc,argv) +int argc; +char **argv; +{ + + char *port, *path; + int c, errflag=0; + extern INNBBSDhalt(); +/* +woju +*/ + setgid(BBSGID); + setuid(BBSUID); + chdir(BBSHOME); + resolve_boards(); + + port = DefaultINNBBSPort; + path = LOCALDAEMON; + Junkhistory = 0; + + time(&INNBBSDstartup); + openlog("innbbsd", LOG_PID | LOG_ODELAY, LOG_DAEMON); + while ((c = getopt(argc,argv,"c:f:s:vhidn?j"))!= -1) + switch (c) { + case 'j': + Junkhistory = 1; + break; + case 'v': + verboseon("innbbsd.log"); + break; + case 'n': + hisincore(0); + break; + case 'c': + Maxclient = atoi(optarg); + if (Maxclient < 0) Maxclient = 0; + break; + case 'i': { + struct sockaddr_in there; + int len = sizeof(there); + int rel; + if ((rel=getsockname(0,(struct sockaddr *)&there,&len))< 0){ + fprintf(stdout,"You must run -i from inetd with inetd.conf line: \n"); + fprintf(stdout,"service-port stream tcp wait bbs /home/bbs/innbbsd innbbsd -i port\n"); + fflush(stdout); + exit(5); + } + inetdstart = 1; + startfrominetd(1); + } + break; + case 'd': + dbzdebug(1); + break; + case 's': + Max_Art_Size = atol(optarg); + if (Max_Art_Size < 0) Max_Art_Size = 0; + break; + case 'h': + case '?': + default: + errflag ++; + } + if (errflag > 0) { + innbbsusage(argv[0]); + return(1); + } + if (argc - optind >= 1) { + port = argv[optind]; + } + if (argc - optind >= 2) { + path = argv[optind+1]; + } + + standaloneinit(port); + + initial_bbs("feed"); + +/* Kaede + if (!inetdstart) + fprintf(stderr, "Try to listen in port %s and path %s\n", port, path); +*/ + HISmaint(); + HISsetup(); + installinnbbsd(); + sethaltfunction(INNBBSDhalt); + + signal(SIGPIPE, dopipesig); + inndchannel(port, path); + HISclose(); +} diff --git a/innbbsd/inntobbs.c b/innbbsd/inntobbs.c new file mode 100644 index 00000000..b57d8bb1 --- /dev/null +++ b/innbbsd/inntobbs.c @@ -0,0 +1,323 @@ +#include <stdio.h> +#include "daemon.h" +#include "bbslib.h" +#include <time.h> + +#define INNTOBBS +#include "inntobbs.h" + +typedef struct Header { + char *name; + int id; +} header_t; + +/*enum HeaderValue { +SUBJECT_H, FROM_H, DATE_H, MID_H, NEWSGROUPS_H, +NNTPPOSTINGHOST_H, NNTPHOST_H, CONTROL_H, PATH_H, +ORGANIZATION_H, LASTHEADER, +}; +*/ + +char *strchr ARG((char*,int)); +char *strrchr ARG((char*,int)); +char *strstr ARG((char*,char*)); + +header_t headertable[] = { +"Subject" ,SUBJECT_H, +"From" ,FROM_H, +"Date" ,DATE_H, +"Message-ID",MID_H, +"Newsgroups",NEWSGROUPS_H, +"NNTP-Posting-Host",NNTPPOSTINGHOST_H, +"NNTP-Host", NNTPHOST_H, +"Control", CONTROL_H, +"Path", PATH_H, +"Organization", ORGANIZATION_H, +"X-Auth-From", X_Auth_From_H, +"Approved", APPROVED_H, +"Distribution", DISTRIBUTION_H, +"Keywords", KEYWORDS_H, +"Summary", SUMMARY_H, +"References",REFERENCES_H, +}; + +char *HEADER[LASTHEADER]; +char *BODY; +char *FROM, *SUBJECT, *SITE, *DATE, *POSTHOST, + *NNTPHOST, *PATH, *GROUPS, *MSGID, *CONTROL; + +#ifdef PalmBBS +char **XHEADER; +char *XPATH; +#endif + + +int +isexcluded(path1, nl) +char *path1; +nodelist_t *nl; +{ + char path2[1024]; + /*path2 = (char*)mymalloc(strlen(nl->node) + 3);*/ + sprintf(path2, "!%.*s!",sizeof path2 - 3, nl->node); + if (strstr(path1, path2) != NULL) return 1; + if (nl->exclusion && *nl->exclusion) { + char *exclude, *ptr; + for (exclude = nl->exclusion, ptr = strchr(exclude,','); + exclude && *exclude; ptr = strchr(exclude,',')) { + if (ptr) *ptr = '\0'; + sprintf(path2, "!%.*s!",sizeof path2 - 3, exclude); + if (strstr(path1, path2) != NULL) return 1; + if (ptr) { + *ptr = ','; + exclude = ptr+1; + } else { + break; + } + } + } + return 0; +} + +feedfplog(nf, filepath, type) +newsfeeds_t *nf; +char *filepath; +int type; +{ + char *path1, *path2, *hostptr; + nodelist_t *nl; + if (nf == NULL) return; + if( nf->path != NULL ) { + char *ptr1, *ptr2; + char savech; + path1 = (char*)mymalloc(strlen(HEADER[PATH_H]) + 3); + sprintf(path1, "!%s!",HEADER[PATH_H]); + for (ptr1 = nf->path; ptr1 && *ptr1;) { + for (; *ptr1 && isspace(*ptr1); ptr1++); + if (!*ptr1) break; + for (ptr2 = ptr1; *ptr2 && !isspace(*ptr2); ptr2++); + savech = *ptr2; + *ptr2 = '\0'; + /* + bbslog("search node %s\n",ptr1); + */ + nl = (nodelist_t*) search_nodelist_bynode(ptr1); + /* + bbslog("search node node %s, host %s fp %d\n",nl->node, nl->host, nl->feedfp); + */ + *ptr2 = savech; + ptr1 = ptr2++; + if (nl == NULL) continue; + if (nl->feedfp == NULL) continue; + if (isexcluded(path1,nl)) continue; + /*path2 = (char*)mymalloc(strlen(nl->node) + 3); + sprintf(path2, "!%s!",nl->node); + free(path2); + */ + /* + bbslog("path1 %s path2 %s\n",path1, path2); + */ + /*if (strstr(path1, path2) != NULL) return;*/ + /* to conform to the bntplink batch file */ + { + char *slash = strrchr(filepath,'/'); + if (slash != NULL) *slash = '\t'; + fprintf(nl->feedfp,"%s\t%s\t\t%s\t%s\t%c\t%s\t%s!%s\n", + filepath == NULL ? "": filepath, + GROUPS, FROM, SUBJECT, type, MSGID, MYBBSID, HEADER[PATH_H]); + if (slash != NULL) *slash = '/'; + } + fflush(nl->feedfp); + if (savech == '\0') break; + } + free(path1); + } +} + +static FILE* bbsfeedsfp = NULL; +static bbsfeedson = -1; + +init_bbsfeedsfp() +{ + if (bbsfeedsfp != NULL) { + fclose(bbsfeedsfp); + bbsfeedsfp = NULL; + } + bbsfeedson = -1; +} + +bbsfeedslog(filepath, type) +char *filepath; +int type; +{ + + char datebuf[40]; + time_t now; + + if (bbsfeedson ==0) return; + if (bbsfeedson == -1) { + if (!isfile(BBSFEEDS)) { + bbsfeedson = 0; + return; + } + bbsfeedson = 1; + } + + if (bbsfeedsfp == NULL) { + bbsfeedsfp = fopen(BBSFEEDS,"a"); + } + time(&now); + strftime(datebuf, sizeof(datebuf), "%b %d %X ", localtime(&now)); + + if( bbsfeedsfp != NULL ) { + fprintf(bbsfeedsfp,"%s %c %s %s %s %s!%s %s\n", datebuf, type, + REMOTEHOSTNAME, GROUPS, MSGID, MYBBSID, HEADER[PATH_H], filepath==NULL? "": filepath); + fflush(bbsfeedsfp); + } +} + +static FILE* echomailfp = NULL; +static echomaillogon = -1; + +init_echomailfp() +{ + if (echomailfp != NULL) { + fclose(echomailfp); + echomailfp = NULL; + } + echomaillogon = -1; +} + +echomaillog() +{ + + if (echomaillogon ==0) return; + if (echomaillogon == -1) { + if (!isfile(ECHOMAIL)) { + echomaillogon = 0; + return; + } + echomaillogon = 1; + } + + if (echomailfp == NULL) { + echomailfp = fopen(ECHOMAIL,"a"); + } + + if( echomailfp != NULL ) { + fprintf(echomailfp,"\n"); + fprintf(echomailfp,"µo«H¤H: %s, «H°Ï: %s\n", FROM, GROUPS); + fprintf(echomailfp,"¼Ð ÃD: %s\n", SUBJECT); + fprintf(echomailfp,"µo«H¯¸: %s (%s)\n", SITE, DATE); + fprintf(echomailfp,"Âà«H¯¸: %s (%s)\n", PATH, REMOTEHOSTNAME); + fflush(echomailfp); + } +} + +int headercmp(a,b) +header_t *a, *b; +{ + return strcasecmp(a->name, b->name); +} + +int readlines(client) +ClientType *client; +{ + int fd = client->fd; + char *buffer = client->buffer; + buffer_t *in = &client->in; + char *front = in->data, *ptr, *hptr; + int i; + + for (i=0; i < LASTHEADER; i++ ) + HEADER[i] = NULL; + for (ptr = (char*)strchr(in->data,'\n'); ptr != NULL && *ptr != '\0' ; front = ptr+1, ptr = (char*)strchr(front,'\n')) { + *ptr = '\0'; + if (front[0] == '\r' || front[1] == '\n') { + BODY = front+2; + break; + } + hptr = (char*)strchr(front,':'); + if (hptr != NULL && hptr[1] == ' ') { + int value; + *hptr = '\0'; + value = headervalue(front); + if (value != -1) { + char *tp; + HEADER[value] = hptr + 2; + if ((tp = (char*)strchr(HEADER[value],'\r'))!=NULL) + *tp = '\0'; + } + *hptr = ':'; + } + /**ptr = '\n';*/ + } + NNTPHOST = HEADER[NNTPHOST_H]; + PATH = HEADER[PATH_H]; + FROM = HEADER[FROM_H]; + GROUPS = HEADER[NEWSGROUPS_H]; + SUBJECT = HEADER[SUBJECT_H]; + DATE = HEADER[DATE_H]; + SITE = HEADER[ORGANIZATION_H]; + MSGID = HEADER[MID_H]; + CONTROL = HEADER[CONTROL_H]; + POSTHOST = HEADER[NNTPPOSTINGHOST_H]; + if (POSTHOST == NULL) { + if (HEADER[X_Auth_From_H] != NULL) { + POSTHOST = HEADER[X_Auth_From_H]; + HEADER[NNTPPOSTINGHOST_H] = POSTHOST; + } + } +#ifdef PalmBBS + XPATH = PATH; + XHEADER = HEADER; +#endif +} + +int headervalue(inputheader) +char *inputheader; +{ + header_t key, *findkey; + static int hasinit=0; + + if (hasinit == 0) { + article_init(); + hasinit = 1; + } + + key.name = inputheader; + findkey = ( header_t *)bsearch ( + (char *) &key, (char *) headertable, + sizeof(headertable)/ sizeof(header_t), sizeof (key), + headercmp); + if (findkey != NULL) return findkey->id; + return -1; +} + +article_init() +{ + int i; + static int article_inited = 0; + + if (article_inited) return; + article_inited = 1; + + qsort(headertable, sizeof(headertable)/ sizeof(header_t), sizeof(header_t), + headercmp); + for (i=0; i < LASTHEADER; i++ ) + HEADER[i] = NULL; +} + +#ifdef INNTOBBS_MAIN +main() +{ + int i,j,k,l,m,n,o,p,q; + article_init(); + i = headervalue("Subject"); + j = headervalue("From"); + k = headervalue("Date"); + l = headervalue("NNTP-Posting-Host"); + m = headervalue("Newsgroups"); + n = headervalue("Message-ID"); +} +#endif diff --git a/innbbsd/inntobbs.h b/innbbsd/inntobbs.h new file mode 100644 index 00000000..1026e6d7 --- /dev/null +++ b/innbbsd/inntobbs.h @@ -0,0 +1,39 @@ +#ifndef INNTOBBS_H +#define INNTOBBS_H + +enum HeaderValue { +SUBJECT_H, FROM_H, DATE_H, MID_H, NEWSGROUPS_H, +NNTPPOSTINGHOST_H, NNTPHOST_H, CONTROL_H, PATH_H, +ORGANIZATION_H, X_Auth_From_H, APPROVED_H, DISTRIBUTION_H, +REFERENCES_H, KEYWORDS_H, SUMMARY_H, +LASTHEADER, +}; + +#if !defined(PalmBBS) +extern char *HEADER[]; +extern char *BODY; +extern char *FROM, *SUBJECT, *SITE, *DATE, *POSTHOST, + *NNTPHOST, *PATH, *GROUPS, *MSGID, *CONTROL; +extern char *REMOTEHOSTNAME, *REMOTEUSERNAME; +#else +extern char **XHEADER; +extern char *BODY; +extern char *FROM, *SUBJECT, *SITE, *DATE, *POSTHOST, + *NNTPHOST, *XPATH, *GROUPS, *MSGID, *CONTROL; +extern char *REMOTEHOSTNAME, *REMOTEUSERNAME; +#endif + +int receive_article(); + +#if defined(PalmBBS) +#ifndef INNTOBBS +#ifndef PATH +# define PATH XPATH +#endif +#ifndef HEADER +# define HEADER XHEADER +#endif +#endif +#endif + +#endif diff --git a/innbbsd/mkhistory.c b/innbbsd/mkhistory.c new file mode 100644 index 00000000..4be980ea --- /dev/null +++ b/innbbsd/mkhistory.c @@ -0,0 +1,14 @@ +#include "innbbsconf.h" +#include "bbslib.h" + +main(argc,argv) +int argc; +char *argv[]; +{ + if (argc < 2) { + fprintf(stderr,"Usage: %s history-file\n",argv[0]); + exit(1); + } + initial_bbs(NULL); + mkhistory(argv[1]); +} diff --git a/innbbsd/nntp.h b/innbbsd/nntp.h new file mode 100644 index 00000000..489f3502 --- /dev/null +++ b/innbbsd/nntp.h @@ -0,0 +1,145 @@ +/* $Revision: 1.1 $ +** +** Here be a set of NNTP response codes as defined in RFC977 and elsewhere. +** The reponse codes are three digits, RFI, defined like this: +** R, Response: +** 1xx Informative message +** 2xx Command ok +** 3xx Command ok so far, send the rest of it. +** 4xx Command was correct, but couldn't be performed for +** some reason. +** 5xx Command unimplemented, or incorrect, or a serious +** program error occurred. +** F, Function: +** x0x Connection, setup, and miscellaneous messages +** x1x Newsgroup selection +** x2x Article selection +** x3x Distribution functions +** x4x Posting +** x8x Nonstandard extensions (AUTHINFO, XGTITLE) +** x9x Debugging output +** I, Information: +** No defined semantics +*/ +#define NNTP_HELPOK_VAL 100 +#define NNTP_BAD_COMMAND_VAL 500 +#define NNTP_BAD_COMMAND "500 Syntax error or bad command" +#define NNTP_TEMPERR_VAL 503 +#define NNTP_ACCESS "502 Permission denied" +#define NNTP_ACCESS_VAL 502 +#define NNTP_GOODBYE_ACK "205" +#define NNTP_GOODBYE_ACK_VAL 205 +#define NNTP_GOODBYE "400" +#define NNTP_GOODBYE_VAL 400 +#define NNTP_HAVEIT "435 Duplicate" +#define NNTP_HAVEIT_BADID "435 Bad Message-ID" +#define NNTP_HAVEIT_VAL 435 +#define NNTP_LIST_FOLLOWS "215" +#define NNTP_LIST_FOLLOWS_VAL 215 +#define NNTP_HELP_FOLLOWS "100 Legal commands" +#define NNTP_HELP_FOLLOWS_VAL 100 +#define NNTP_NOTHING_FOLLOWS_VAL 223 +#define NNTP_ARTICLE_FOLLOWS "220" +#define NNTP_ARTICLE_FOLLOWS_VAL 220 +#define NNTP_NEWGROUPS_FOLLOWS_VAL 231 +#define NNTP_HEAD_FOLLOWS "221" +#define NNTP_HEAD_FOLLOWS_VAL 221 +#define NNTP_BODY_FOLLOWS_VAL 222 +#define NNTP_OVERVIEW_FOLLOWS_VAL 224 +#define NNTP_DATE_FOLLOWS_VAL 111 +#define NNTP_POSTOK "200" +#define NNTP_POSTOK_VAL 200 +#define NNTP_START_POST_VAL 340 +#define NNTP_NOPOSTOK_VAL 201 +#define NNTP_SLAVEOK_VAL 202 +#define NNTP_REJECTIT_VAL 437 +#define NNTP_REJECTIT_EMPTY "437 Empty article" +#define NNTP_DONTHAVEIT "430" +#define NNTP_DONTHAVEIT_VAL 430 +#define NNTP_RESENDIT_NOHIST "436 Can't write history" +#define NNTP_RESENDIT_NOSPACE "436 No space" +#define NNTP_RESENDIT_VAL 436 +#define NNTP_POSTEDOK "240 Article posted" +#define NNTP_POSTEDOK_VAL 240 +#define NNTP_POSTFAIL_VAL 441 +#define NNTP_GROUPOK_VAL 211 +#define NNTP_SENDIT "335" +#define NNTP_SENDIT_VAL 335 +#define NNTP_SYNTAX_USE "501 Bad command use" +#define NNTP_SYNTAX_VAL 501 +#define NNTP_TOOKIT "235" +#define NNTP_TOOKIT_VAL 235 +#define NNTP_NOTINGROUP "412 Not in a newsgroup" +#define NNTP_NOTINGROUP_VAL 412 +#define NNTP_NOSUCHGROUP "411 No such group" +#define NNTP_NOSUCHGROUP_VAL 411 +#define NNTP_NEWNEWSOK "230 New news follows" +#define NNTP_NOARTINGRP "423 Bad article number" +#define NNTP_NOARTINGRP_VAL 423 +#define NNTP_NOCURRART "420 No current article" +#define NNTP_NOCURRART_VAL 420 +#define NNTP_NONEXT_VAL 421 +#define NNTP_NOPREV_VAL 422 +#define NNTP_CANTPOST "440 Posting not allowed" +#define NNTP_CANTPOST_VAL 440 + + +/* +** The first character of an NNTP reply can be used as a category class. +*/ +#define NNTP_CLASS_OK '2' +#define NNTP_CLASS_ERROR '4' +#define NNTP_CLASS_FATAL '5' + + +/* +** The NNTP protocol currently has no way to say "offer me this article +** later, but don't close the connection." That will be fixed in NNTP2. +#define NNTP_RESENDIT_LATER "?" +#define NNTP_RESENDIT_LATER_VAL ? +*/ + + +/* +** Authentication commands from the RFC update (not official). +*/ +#define NNTP_AUTH_NEEDED "480" +#define NNTP_AUTH_NEEDED_VAL 480 +#define NNTP_AUTH_BAD "481" +#define NNTP_AUTH_NEXT "381" +#define NNTP_AUTH_NEXT_VAL 381 +#define NNTP_AUTH_OK "281" +#define NNTP_AUTH_OK_VAL 281 +#define NNTP_AUTH_REJECT_VAL 482 + +/* +** XGTITLE, from ANU news. +*/ +#define NNTP_XGTITLE_BAD 481 /* Yes, 481. */ +#define NNTP_XGTITLE_OK 282 + +#define NNTP_STRLEN 512 + +/* +** For tin newsreader +*/ +#define OK_XINDEX 218 /* Tin style group index file follows */ +#define OK_XMOTD 217 /* Motd (message of the day) file follows */ +#define ERR_XINDEX 418 /* No tin style index file for newsgroup */ +#define ERR_XMOTD 417 /* No motd (message of the day) file */ + +/* For DBZ server */ +#define NNTP_ADDHIST_OK 283 /* addhist OK */ +#define NNTP_GREPHIST_OK 284 /* grephist OK */ +#define NNTP_MIDCHECK_OK 285 /* grephist OK */ +#define NNTP_SHUTDOWN_OK 286 /* grephist OK */ +#define NNTP_RELOAD_OK 287 /* grephist OK */ +#define NNTP_MODE_OK 101 /* grephist OK */ +#define NNTP_VERBOSELOG_OK 289 /* grephist OK */ +#define NNTP_ADDHIST_BAD 483 /* addhist fail */ +#define NNTP_GREPHIST_BAD 484 /* grephist fail */ +#define NNTP_MIDCHECK_BAD 485 /* grephist fail */ +#define NNTP_SHUTDOWN_BAD 486 /* grephist fail */ +#define NNTP_RELOAD_BAD 487 /* grephist fail */ +#define NNTP_MODE_BAD 488 /* grephist fail */ +#define NNTP_VERBOSELOG_BAD 489 /* grephist fail */ diff --git a/innbbsd/pmain.c b/innbbsd/pmain.c new file mode 100644 index 00000000..39ddba22 --- /dev/null +++ b/innbbsd/pmain.c @@ -0,0 +1,62 @@ +#include "innbbsconf.h" +#include "daemon.h" + +/*char *AccessFile=ACCESSFILE;*/ +#define INNBBSDPORT1 "1904" +#define INNBBSDPORT2 "1234" +#define INNBBSDPATH1 ".innbbsd1" +#define INNBBSDPATH2 ".innbbsd2" + +pmain(port) +char *port; +{ + if (port == NULL) { + int rel; +/* installbbstalkd(); */ + fprintf(stderr,"Trying to listen in port %s\n",INNBBSDPORT1); + rel = open_listen(INNBBSDPORT1,"tcp",NULL); +#ifdef DEBUG + printf("port fd %d allocated\n",rel); +#endif + if (rel<0) { + fprintf(stderr,"Trying to listen in port %s\n",INNBBSDPORT2); + return open_listen(INNBBSDPORT2,"tcp",NULL); + } + return rel; + } else { +#ifdef DEBUG + printf("start to allocate port\n"); +#endif + return open_listen(port,"tcp",NULL); + } +} + +p_unix_main(path) +char *path; +{ + if (path == NULL) { + int rel; +/* installbbstalkd(); */ + fprintf(stderr,"Trying to listen in port %s\n",INNBBSDPATH1); + rel = open_unix_listen(INNBBSDPATH1,"tcp",NULL); +#ifdef DEBUG + printf("port fd %d allocated\n",rel); +#endif + if (rel<0) { + fprintf(stderr,"Trying to listen in port %s\n",INNBBSDPATH2); + return open_listen(INNBBSDPATH2,"tcp",NULL); + } + return rel; + } else { +#ifdef DEBUG + printf("start to allocate path %s\n", path); +#endif + int fd = unixclient(path,"tcp"); + if (fd < 0) + unlink(path); + else + close(fd); + return open_unix_listen(path,"tcp",NULL); + } +} + diff --git a/innbbsd/port.c b/innbbsd/port.c new file mode 100644 index 00000000..65e91fa4 --- /dev/null +++ b/innbbsd/port.c @@ -0,0 +1,28 @@ +#include "innbbsconf.h" + +#ifdef NO_getdtablesize +#include <sys/time.h> +#include <sys/resource.h> +getdtablesize() +{ + struct rlimit limit; + if (getrlimit(RLIMIT_NOFILE, &limit) >= 0){ + return limit.rlim_cur; + } + return -1; +} +#endif + +#if defined(SYSV) && !defined(WITH_RECORD_O) +#include <fcntl.h> +flock(fd, op) +int fd,op; +{ + switch (op) { + case LOCK_EX: op = F_LOCK; break; + case LOCK_UN: op = F_ULOCK; break; + default: return -1; + } + return lockf(fd, op, 0L); +} +#endif diff --git a/innbbsd/receive_article.c b/innbbsd/receive_article.c new file mode 100644 index 00000000..40f2609c --- /dev/null +++ b/innbbsd/receive_article.c @@ -0,0 +1,1204 @@ +/* + * BBS implementation dependendent part + * + * The only two interfaces you must provide + * + * #include "inntobbs.h" int receive_article(); 0 success not 0 fail + * + * if (storeDB(HEADER[MID_H], hispaths) < 0) { .... fail } + * + * int cancel_article_front( char *msgid ); 0 success not 0 fail + * + * char *ptr = (char*)DBfetch(msgid); + * + * ¦¬¨ì¤§¤å³¹¤º®e (body)¦b char *BODY, ÀÉÀY (header)¦b char *HEADER[] SUBJECT_H, + * FROM_H, DATE_H, MID_H, NEWSGROUPS_H, NNTPPOSTINGHOST_H, NNTPHOST_H, + * CONTROL_H, PATH_H, ORGANIZATION_H + */ + +/* + * Sample Implementation + * + * receive_article() --> post_article() --> bbspost_write_post(); + * cacnel_article_front(mid) --> cancel_article() --> bbspost_write_cancel(); + */ + + +#ifndef PowerBBS +#include "innbbsconf.h" +#include "daemon.h" +#include "bbslib.h" +#include "inntobbs.h" +#include "antisplam.h" + +extern int Junkhistory; + +char *post_article ARG((char *, char *, char *, int (*) (), char *, char *)); +int cancel_article ARG((char *, char *, char *)); + + +#ifdef MapleBBS +#include "config.h" +#include "pttstruct.h" +#define _BBS_UTIL_C_ +#else +report() +{ + /* Function called from record.o */ + /* Please leave this function empty */ +} +#endif + + +#if defined(PalmBBS) + +#ifndef PATH +# define PATH XPATH +#endif + +#ifndef HEADER +# define HEADER XHEADER +#endif + +#endif + +/* process post write */ +bbspost_write_post(fh, board, filename) + int fh; + char *board; + char *filename; +{ + char *fptr, *ptr; + FILE *fhfd = fdopen(fh, "w"); + + if (fhfd == NULL) + { + bbslog("can't fdopen, maybe disk full\n"); + return -1; + } + + fprintf(fhfd, "µo«H¤H: %.60s, ¬ÝªO: %s\n", FROM, board); + fprintf(fhfd, "¼Ð ÃD: %.70s\n", SUBJECT); + fprintf(fhfd, "µo«H¯¸: %.43s (%s)\n", SITE, DATE); + fprintf(fhfd, "Âà«H¯¸: %.70s\n", PATH); + +#ifndef MapleBBS + if (POSTHOST != NULL) + { + fprintf(fhfd, "Origin: %.70s\n", POSTHOST); + } +#endif + + fprintf(fhfd, "\n"); + for (fptr = BODY, ptr = strchr(fptr, '\r'); ptr != NULL && *ptr != '\0'; fptr = ptr + 1, ptr = strchr(fptr, '\r')) + { + int ch = *ptr; + *ptr = '\0'; + fputs(fptr, fhfd); + *ptr = ch; + } + fputs(fptr, fhfd); + + fflush(fhfd); + fclose(fhfd); + return 0; +} + +#ifdef KEEP_NETWORK_CANCEL +/* process cancel write */ +bbspost_write_cancel(fh, board, filename) + int fh; + char *board, *filename; +{ + char *fptr, *ptr; + FILE *fhfd = fdopen(fh, "w"), *fp; + char buffer[256]; + + if (fhfd == NULL) + { + bbslog("can't fdopen, maybe disk full\n"); + return -1; + } + + fprintf(fhfd, "µo«H¤H: %s, «H°Ï: %s\n", FROM, board); + fprintf(fhfd, "¼Ð ÃD: %s\n", SUBJECT); + fprintf(fhfd, "µo«H¯¸: %.43s (%s)\n", SITE, DATE); + fprintf(fhfd, "Âà«H¯¸: %.70s\n", PATH); + if (HEADER[CONTROL_H] != NULL) + { + fprintf(fhfd, "Control: %s\n", HEADER[CONTROL_H]); + } + if (POSTHOST != NULL) + { + fprintf(fhfd, "Origin: %s\n", POSTHOST); + } + fprintf(fhfd, "\n"); + for (fptr = BODY, ptr = strchr(fptr, '\r'); ptr != NULL && *ptr != '\0'; fptr = ptr + 1, ptr = strchr(fptr, '\r')) + { + int ch = *ptr; + *ptr = '\0'; + fputs(fptr, fhfd); + *ptr = ch; + } + fputs(fptr, fhfd); + if (POSTHOST != NULL) + { + fprintf(fhfd, "\n * Origin: ¡´ %.26s ¡´ From: %.40s\n", SITE, POSTHOST); + } + fprintf(fhfd, "\n---------------------\n"); + fp = fopen(filename, "r"); + if (fp == NULL) + { + bbslog("can't open %s\n", filename); + return -1; + } + while (fgets(buffer, sizeof buffer, fp) != NULL) + { + fputs(buffer, fhfd); + } + fclose(fp); + fflush(fhfd); + fclose(fhfd); + + { + fp = fopen(filename, "w"); + if (fp == NULL) + { + bbslog("can't write %s\n", filename); + return -1; + } + fprintf(fp, "µo«H¤H: %s, «H°Ï: %s\n", FROM, board); + fprintf(fp, "¼Ð ÃD: %.70s\n", SUBJECT); + fprintf(fp, "µo«H¯¸: %.43s (%s)\n", SITE, DATE); + fprintf(fp, "Âà«H¯¸: %.70s\n", PATH); + if (POSTHOST != NULL) + { + fprintf(fhfd, "Origin: %s\n", POSTHOST); + } + if (HEADER[CONTROL_H] != NULL) + { + fprintf(fhfd, "Control: %s\n", HEADER[CONTROL_H]); + } + fprintf(fp, "\n"); + for (fptr = BODY, ptr = strchr(fptr, '\r'); ptr != NULL && *ptr != '\0'; fptr = ptr + 1, ptr = strchr(fptr, '\r')) + { + *ptr = '\0'; + fputs(fptr, fp); + } + fputs(fptr, fp); + if (POSTHOST != NULL) + { + fprintf(fp, "\n * Origin: ¡´ %.26s ¡´ From: %.40s\n", SITE, POSTHOST); + } + fclose(fp); + } + return 0; +} +#endif + + +bbspost_write_control(fh, board, filename) + int fh; + char *board; + char *filename; +{ + char *fptr, *ptr; + FILE *fhfd = fdopen(fh, "w"); + + if (fhfd == NULL) + { + bbslog("can't fdopen, maybe disk full\n"); + return -1; + } + + fprintf(fhfd, "Path: %s!%s\n", MYBBSID, HEADER[PATH_H]); + fprintf(fhfd, "From: %s\n", FROM); + fprintf(fhfd, "Newsgroups: %s\n", GROUPS); + fprintf(fhfd, "Subject: %s\n", SUBJECT); + fprintf(fhfd, "Date: %s\n", DATE); + fprintf(fhfd, "Organization: %s\n", SITE); + if (POSTHOST != NULL) + { + fprintf(fhfd, "NNTP-Posting-Host: %.70s\n", POSTHOST); + } + if (HEADER[CONTROL_H] != NULL) + { + fprintf(fhfd, "Control: %s\n", HEADER[CONTROL_H]); + } + if (HEADER[APPROVED_H] != NULL) + { + fprintf(fhfd, "Approved: %s\n", HEADER[APPROVED_H]); + } + if (HEADER[DISTRIBUTION_H] != NULL) + { + fprintf(fhfd, "Distribution: %s\n", HEADER[DISTRIBUTION_H]); + } + fprintf(fhfd, "\n"); + for (fptr = BODY, ptr = strchr(fptr, '\r'); ptr != NULL && *ptr != '\0'; fptr = ptr + 1, ptr = strchr(fptr, '\r')) + { + int ch = *ptr; + *ptr = '\0'; + fputs(fptr, fhfd); + *ptr = ch; + } + fputs(fptr, fhfd); + + + fflush(fhfd); + fclose(fhfd); + return 0; +} + + +time_t datevalue; + + +/* process cancel write */ +receive_article() +{ + int i; + char *user, *userptr; + char *ngptr, *nngptr, *pathptr; + char **splitptr; + static char userid[32]; + static char xdate[32]; + static char xpath[180]; + newsfeeds_t *nf; + char *boardhome; + char hispaths[4096]; + char firstpath[MAXPATHLEN], *firstpathbase; + char *lesssym, *nameptrleft, *nameptrright; + static char sitebuf[80]; + +#ifdef HMM_USE_ANTI_SPAM + char *notitle[] = + {"¦æ¾P", "·~°È¥Nªí", "¼x", "¸ê°T", "§K¶O", "¤jÃØ°e", "¶Ç¾P", "¥¼º¡", + "¦~¶O", "¶Ç©I", "»ù", "¾Þ§A¶ý", "¥¼¦¨¦~", "°¨ÁɧJ", "«H¥Î", "ÁÈ¿ú", + "=?", "!!!", + "¾Þ§A", "¾Þ§A", "·F©p", "¾Þ©p","**","¡¹¡¹","¡¯¡¯","¢C¢C","ªwÄÑ", NULL}, + *nofrom[] = + {"TaipeiNet.Net", "hotmail.com", "mt.touc.edu.tw", "ms11.hinet.net", NULL}, + *nocont[] = + {"¦WÃB¦³", "Àu´f»ù", "°Ê§@n§Ö", "qÁÊ", "¯S»ù", "±M½æ", "BBC", + "·F§A", "¾Þ§A", "·F©p", "¾Þ©p","¨C¤ù","³Ì·s¥Ø¿ý", "http://", "¦¬¿ú", + "³Ð·~", "¥I´Ú", "¼s§i«H", "¥u½æ", "¥«»ù", "NCg", "ICAg", NULL}; +#endif + + if (FROM == NULL) + { + bbslog(":Err: article without usrid %s\n", MSGID); + return 0; + } + else + { +#ifdef HMM_USE_ANTI_SPAM + for(i=0; nofrom[i]; i++) + if(strstr(FROM, nofrom[i])) + { + morelog_to(INNBBSD_SPAM, "spam from [%s]: %s\n", nofrom[i], FROM); + morelog_to(INNBBSD_SPAM, " %s %s %s %s\n", FROM, PATH, GROUPS, SUBJECT); + bbslog(":Ptt: spam from [%s]: %s\n", nofrom[i], FROM); + return 0; + } +#endif + } + + if(!BODY) + { + bbslog(":Err: article without body %s\n", MSGID); + return 0; + } + else + { +#ifdef HMM_USE_ANTI_SPAM + for(i=0; nocont[i]; i++) + if(strstr(BODY, nocont[i])) + { + morelog_to(INNBBSD_SPAM, "spam body [%s]: %s\n", nocont[i]); + morelog_to(INNBBSD_SPAM, " %s %s %s %s\n", FROM, PATH, GROUPS, SUBJECT); + bbslog(":Ptt: spam body [%s]: %s\n", nocont[i]); + return 0; + } +#endif + } + + if(!SUBJECT) + { + bbslog(":Err: article without subject %s\n", MSGID); + return 0; + } + else + { +#ifdef HMM_USE_ANTI_SPAM + for(i=0; notitle[i]; i++) + if(strstr(SUBJECT, notitle[i])) + { + morelog_to(INNBBSD_SPAM, "spam title [%s]: %s\n", notitle[i], SUBJECT); + morelog_to(INNBBSD_SPAM, " %s %s %s %s\n", FROM, PATH, GROUPS, SUBJECT); + bbslog(":Ptt: spam title [%s]: %s\n", notitle[i], SUBJECT); + return 0; + } +#endif + } + + + user = (char *) strchr(FROM, '@'); + lesssym = (char *) strchr(FROM, '<'); + nameptrleft = NULL, nameptrright = NULL; + if (lesssym == NULL || lesssym >= user) + { + lesssym = FROM; + nameptrleft = strchr(FROM, '('); + if (nameptrleft != NULL) + nameptrleft++; + nameptrright = strrchr(FROM, ')'); + } + else + { + nameptrleft = FROM; + nameptrright = strrchr(FROM, '<'); + lesssym++; + } + if (user != NULL) + { + *user = '\0'; + userptr = (char *) strchr(FROM, '.'); + if (userptr != NULL) + { + *userptr = '\0'; + strncpy(userid, lesssym, sizeof userid); + *userptr = '.'; + } + else + { + strncpy(userid, lesssym, sizeof userid); + } + *user = '@'; + } + else + { + strncpy(userid, lesssym, sizeof userid); + } + strcat(userid, "."); + + { + struct tm tmbuf; + + strptime(DATE, "%d %b %Y %X GMT", &tmbuf); + datevalue = timegm(&tmbuf); + } + + if (datevalue > 0) + { + char *p; + strncpy(xdate, ctime(&datevalue), sizeof(xdate)); + p = (char *) strchr(xdate, '\n'); + if (p != NULL) + *p = '\0'; + DATE = xdate; + } + +#ifndef MapleBBS + if (SITE == NULL || *SITE == '\0') + { + if (nameptrleft != NULL && nameptrright != NULL) + { + char savech = *nameptrright; + *nameptrright = '\0'; + strncpy(sitebuf, nameptrleft, sizeof sitebuf); + *nameptrright = savech; + SITE = sitebuf; + } + else + /* SITE = "(Unknown)"; */ + SITE = ""; + } + if (strlen(MYBBSID) > 70) + { + bbslog(" :Err: your bbsid %s too long\n", MYBBSID); + return 0; + } +#endif + + sprintf(xpath, "%s!%.*s", MYBBSID, sizeof(xpath) - strlen(MYBBSID) - 2, PATH); + PATH = xpath; + for (pathptr = PATH; pathptr != NULL && (pathptr = strstr(pathptr, ".edu.tw")) != NULL;) + { + if (pathptr != NULL) + { + strcpy(pathptr, pathptr + 7); + } + } + xpath[71] = '\0'; + +#ifndef MapleBBS + echomaillog(); +#endif + + *hispaths = '\0'; + splitptr = (char **) BNGsplit(GROUPS); + firstpath[0] = '\0'; + firstpathbase = firstpath; + + for (ngptr = *splitptr; ngptr != NULL; ngptr = *(++splitptr)) + { + char *boardptr, *nboardptr; + + if (*ngptr == '\0') + continue; + nf = (newsfeeds_t *) search_group(ngptr); + if (nf == NULL) + { + bbslog("unwanted \'%s\'\n", ngptr); + continue; + } + if (nf->board == NULL || !*nf->board) + continue; + if (nf->path == NULL || !*nf->path) + continue; + for (boardptr = nf->board, nboardptr = (char *) strchr(boardptr, ','); boardptr != NULL && *boardptr != '\0'; nboardptr = (char *) strchr(boardptr, ',')) + { + if (nboardptr != NULL) + { + *nboardptr = '\0'; + } + if (*boardptr == '\t') + { + goto boardcont; + } + boardhome = (char *) fileglue("%s/boards/%s", BBSHOME, boardptr); + if (!isdir(boardhome)) + { + bbslog(":Err: unable to write %s\n", boardhome); + } + else + { + char *fname; + /* + * if ( !isdir( boardhome )) { bbslog( ":Err: unable to write + * %s\n",boardhome); testandmkdir(boardhome); } + */ + fname = (char *) post_article(boardhome, userid, boardptr, + bbspost_write_post, NULL, firstpath); + if (fname != NULL) + { + fname = (char *) fileglue("%s/%s", boardptr, fname); + if (firstpath[0] == '\0') + { + sprintf(firstpath, "%s/boards/%s", BBSHOME, fname); + firstpathbase = firstpath + strlen(BBSHOME) + strlen("/boards/"); + } + if (strlen(fname) + strlen(hispaths) + 1 < sizeof(hispaths)) + { + strcat(hispaths, fname); + strcat(hispaths, " "); + } + } + else + { + bbslog("fname is null %s\n", boardhome); + return -1; + } + } + + boardcont: + if (nboardptr != NULL) + { + *nboardptr = ','; + boardptr = nboardptr + 1; + } + else + break; + + } /* for board1,board2,... */ + /* + * if (nngptr != NULL) ngptr = nngptr + 1; else break; + */ + if (*firstpathbase) + feedfplog(nf, firstpathbase, 'P'); + } + if (*hispaths) + bbsfeedslog(hispaths, 'P'); + + if (Junkhistory || *hispaths) + { + if (storeDB(HEADER[MID_H], hispaths) < 0) + { + bbslog("store DB fail\n"); + /* I suspect here will introduce duplicated articles */ + /* return -1; */ + } + } + return 0; +} + +receive_control() +{ + char *boardhome, *fname; + char firstpath[MAXPATHLEN], *firstpathbase; + char **splitptr, *ngptr; + newsfeeds_t *nf; + + bbslog("control post %s\n", HEADER[CONTROL_H]); + boardhome = (char *) fileglue("%s/boards/control", BBSHOME); + testandmkdir(boardhome); + *firstpath = '\0'; + if (isdir(boardhome)) + { + fname = (char *) post_article(boardhome, FROM, "control", bbspost_write_control, NULL, firstpath); + if (fname != NULL) + { + if (firstpath[0] == '\0') + sprintf(firstpath, "%s/boards/control/%s", BBSHOME, fname); + if (storeDB(HEADER[MID_H], (char *) fileglue("control/%s", fname)) < 0) + { + } + bbsfeedslog(fileglue("control/%s", fname), 'C'); + firstpathbase = firstpath + strlen(BBSHOME) + strlen("/boards/"); + splitptr = (char **) BNGsplit(GROUPS); + for (ngptr = *splitptr; ngptr != NULL; ngptr = *(++splitptr)) + { + if (*ngptr == '\0') + continue; + nf = (newsfeeds_t *) search_group(ngptr); + if (nf == NULL) + continue; + if (nf->board == NULL) + continue; + if (nf->path == NULL) + continue; + feedfplog(nf, firstpathbase, 'C'); + } + } + } + return 0; +} + +cancel_article_front(msgid) + char *msgid; +{ + char *ptr = (char *) DBfetch(msgid); + char *filelist, filename[2048]; + char histent[4096]; + char firstpath[MAXPATHLEN], *firstpathbase; + if (ptr == NULL) + { + bbslog("cancel failed(DBfetch): %s\n", msgid); + return 0; + } + strncpy(histent, ptr, sizeof histent); + ptr = histent; + +#ifdef DEBUG + printf("**** try to cancel %s *****\n", ptr); +#endif + + filelist = strchr(ptr, '\t'); + if (filelist != NULL) + { + filelist++; + } + *firstpath = '\0'; + for (ptr = filelist; ptr && *ptr;) + { + char *file; + for (; *ptr && isspace(*ptr); ptr++); + if (*ptr == '\0') + break; + file = ptr; + for (ptr++; *ptr && !isspace(*ptr); ptr++); + if (*ptr != '\0') + { + *ptr++ = '\0'; + } + sprintf(filename, "%s/boards/%s", BBSHOME, file); + bbslog("cancel post %s\n", filename); + if (isfile(filename)) + { + FILE *fp = fopen(filename, "r"); + char buffer[1024]; + char xfrom0[100], xfrom[100], xpath[1024], *boardhome; + + if (fp == NULL) + continue; + strncpy(xfrom0, HEADER[FROM_H], 99); + xfrom0[99] = 0; + strtok(xfrom0, ", "); + while (fgets(buffer, sizeof buffer, fp) != NULL) + { + char *hptr; + if (buffer[0] == '\n') + break; + hptr = strchr(buffer, '\n'); + if (hptr != NULL) + *hptr = '\0'; + if (strncmp(buffer, "µo«H¤H: ", 8) == 0) + { + strncpy(xfrom, buffer + 8, 99); + xfrom[99] = 0; + strtok(xfrom, ", "); + } + else if (strncmp(buffer, "Âà«H¯¸: ", 8) == 0) + { + strcpy(xpath, buffer + 8); + } + } + fclose(fp); + if (strcmp(xfrom0, xfrom)) + { + bbslog("Invalid cancel %s, path: %s!%s, [`%s` != `%s`]\n", + FROM, MYBBSID, PATH, xfrom0, xfrom); + return 0; + } + +#ifdef KEEP_NETWORK_CANCEL + bbslog("cancel post %s\n", filename); + boardhome = (char *) fileglue("%s/boards/deleted", BBSHOME); + testandmkdir(boardhome); + if (isdir(boardhome)) + { + char subject[1024]; + char *fname; + if (POSTHOST) + { + sprintf(subject, "cancel by: %.1000s", POSTHOST); + } + else + { + char *body, *body2; + body = strchr(BODY, '\r'); + if (body != NULL) + *body = '\0'; + body2 = strchr(BODY, '\n'); + if (body2 != NULL) + *body = '\0'; + sprintf(subject, "%.1000s", BODY); + if (body != NULL) + *body = '\r'; + if (body2 != NULL) + *body = '\n'; + } + if (*subject) + SUBJECT = subject; + fname = (char *) post_article(boardhome, FROM, "deleted", bbspost_write_cancel, filename, firstpath); + if (fname != NULL) + { + if (firstpath[0] == '\0') + { + sprintf(firstpath, "%s/boards/deleted/%s", BBSHOME, fname); + firstpathbase = firstpath + strlen(BBSHOME) + strlen("/boards/"); + } + if (storeDB(HEADER[MID_H], (char *) fileglue("deleted/%s", fname)) < 0) + { + /* should do something */ + bbslog("store DB fail\n"); + /* return -1; */ + } + bbsfeedslog(fileglue("deleted/%s", fname), 'D'); + +#ifdef OLDDISPATCH + { + char board[256]; + newsfeeds_t *nf; + char *filebase = filename + strlen(BBSHOME) + strlen("/boards/"); + char *filetail = strrchr(filename, '/'); + if (filetail != NULL) + { + strncpy(board, filebase, filetail - filebase); + nf = (newsfeeds_t *) search_board(board); + if (nf != NULL && nf->board && nf->path) + { + feedfplog(nf, firstpathbase, 'D'); + } + } + } +#endif + } + else + { + bbslog(" fname is null %s %s\n", boardhome, filename); + return -1; + } + } +#else + /* bbslog("**** %s should be removed\n", filename); */ +/* + unlink(filename); +*/ +#endif + + { + char *fp = strrchr(file, '/'); + if (fp != NULL) + { + *fp = '\0'; + cancel_article(BBSHOME, file, fp + 1); + *fp = '/'; + } + } + } + } + if (*firstpath) + { + char **splitptr, *ngptr; + newsfeeds_t *nf; + splitptr = (char **) BNGsplit(GROUPS); + for (ngptr = *splitptr; ngptr != NULL; ngptr = *(++splitptr)) + { + if (*ngptr == '\0') + continue; + nf = (newsfeeds_t *) search_group(ngptr); + if (nf == NULL) + continue; + if (nf->board == NULL) + continue; + if (nf->path == NULL) + continue; + feedfplog(nf, firstpathbase, 'D'); + } + } + return 0; +} + + +#if defined(PhoenixBBS) || defined(SecretBBS) || defined(PivotBBS) || defined(MapleBBS) +/* for PhoenixBBS's post article and cancel article */ +#include "config.h" + + +char * +post_article(homepath, userid, board, writebody, pathname, firstpath) + char *homepath; + char *userid, *board; + int (*writebody) (); +char *pathname, *firstpath; +{ + struct userec_t record; + struct fileheader_t header; + char *subject = SUBJECT; + char index[MAXPATHLEN]; + static char name[MAXPATHLEN]; + char article[MAXPATHLEN]; + char buf[MAXPATHLEN], *ptr; + FILE *fidx; + int fh, bid; + time_t now; + int linkflag; +/* Ptt + if(bad_subject(subject)) return NULL; +*/ + sprintf(index, "%s/.DIR", homepath); + if ((fidx = fopen(index, "r")) == NULL) + { + if ((fidx = fopen(index, "w")) == NULL) + { + bbslog(":Err: Unable to post in %s.\n", homepath); + return NULL; + } + } + fclose(fidx); + + now = time(NULL); + while (1) + { + sprintf(name, "M.%d.A", ++now); + sprintf(article, "%s/%s", homepath, name); + fh = open(article, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fh >= 0) + break; + if (errno != EEXIST) + { + bbslog(" Err: can't writable or other errors\n"); + return NULL; + } + } + +#ifdef DEBUG + printf("post to %s\n", article); +#endif + + linkflag = 1; + if (firstpath && *firstpath) + { + close(fh); + unlink(article); + +#ifdef DEBUGLINK + bbslog("try to link %s to %s", firstpath, article); +#endif + + linkflag = link(firstpath, article); + if (linkflag) + { + fh = open(article, O_CREAT | O_EXCL | O_WRONLY, 0644); + } + } + if (linkflag) + { + if (writebody) + { + if ((*writebody) (fh, board, pathname) < 0) + return NULL; + } + else + { + if (bbspost_write_post(fh, board, pathname) < 0) + return NULL; + } + close(fh); + } + + bzero((void *) &header, sizeof(header)); + +#ifndef MapleBBS + strcpy(header.filename, name); + strncpy(header.owner, userid, IDLEN); + strncpy(header.title, subject, STRLEN); + header.filename[STRLEN - 1] = 'M'; +#else + + strcpy(header.filename, name); + if (userid[IDLEN]) + strcpy(&userid[IDLEN], "."); + strcpy(header.owner, userid); + strncpy(header.title, subject, TTLEN); + header.savemode = 'M'; + { + struct tm *ptime; + ptime = localtime(&datevalue); + sprintf(header.date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); + } +#endif + + append_record(index, &header, sizeof(header)); + + if((bid = getbnum(board)) > 0) + touchbtotal(bid); + return name; +} + +/* +woju +Cross-fs rename() +*/ + +Rename(char* src, char* dst) +{ + char cmd[200]; + + bbslog("Rename: %s -> %s\n", src, dst); + if (rename(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/mv %s %s", src, dst); + return system(cmd); +} + + +cancelpost(fileheader_t *fhdr, char* boardname) +{ + int fd; + char fpath[MAXPATHLEN]; + + sprintf(fpath, BBSHOME "/boards/%s/%s", boardname, fhdr->filename); + if ((fd = open(fpath, O_RDONLY)) >= 0) { + fileheader_t postfile; + char fn2[MAXPATHLEN] = BBSHOME "/boards/deleted", *junkdir; + + stampfile(fn2, &postfile); + memcpy(postfile.owner, fhdr->owner, IDLEN + TTLEN + 10); + postfile.savemode = 'D'; + close(fd); + Rename(fpath, fn2); + strcpy(strrchr(fn2, '/') + 1, ".DIR"); + append_record(fn2, &postfile, sizeof(postfile)); + } + else + bbslog("cancelpost: %s opened error\n", fpath); +} + + +/* ---------------------------- */ +/* new/old/lock file processing */ +/* ---------------------------- */ + +typedef struct +{ + char newfn[MAXPATHLEN]; + char oldfn[MAXPATHLEN]; + char lockfn[MAXPATHLEN]; +} nol; + + +static void +nolfilename(n, fpath) + nol *n; + char *fpath; +{ + sprintf(n->newfn, "%s.new", fpath); + sprintf(n->oldfn, "%s.old", fpath); + sprintf(n->lockfn, "%s.lock", fpath); +} + + + +int +delete_record(char *fpath, int size, int id) +{ + nol my; + char abuf[512]; + int fdr, fdw, fd; + int count; + fileheader_t fhdr; + + nolfilename(&my, fpath); + + if ((fd = open(my.lockfn, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1) + return -1; + flock(fd, LOCK_EX); + + if ((fdr = open(fpath, O_RDONLY, 0)) == -1) + { + +#ifdef HAVE_REPORT + report("delete_record failed!!! (open)"); +#endif + + flock(fd, LOCK_UN); + close(fd); + return -1; + } + if ((fdw = open(my.newfn, O_WRONLY | O_CREAT | O_EXCL, 0644)) == -1) + { + flock(fd, LOCK_UN); + +#ifdef HAVE_REPORT + report("delete_record failed!!! (open tmpfile)"); +#endif + + close(fd); + close(fdr); + return -1; + } + count = 1; + while (read(fdr, abuf, size) == size) + { + if (id == count) { + memcpy(&fhdr, abuf, sizeof(fhdr)); + bbslog("delete_record: %d, %s, %s\n", count, fhdr.owner, fhdr.title); + } + if (id != count++ && (write(fdw, abuf, size) == -1)) + { + + bbslog("delete_record: %s failed!!! (write)\n", fpath); +#ifdef HAVE_REPORT + report("delete_record failed!!! (write)"); +#endif + + unlink(my.newfn); + close(fdr); + close(fdw); + flock(fd, LOCK_UN); + close(fd); + return -1; + } + } + close(fdr); + close(fdw); + if (Rename(fpath, my.oldfn) == -1 || Rename(my.newfn, fpath) == -1) + { + +#ifdef HAVE_REPORT + report("delete_record failed!!! (Rename)"); +#endif + + flock(fd, LOCK_UN); + close(fd); + return -1; + } + flock(fd, LOCK_UN); + close(fd); + return 0; +} + +cancel_article(homepath, board, file) + char *homepath; + char *board, *file; +{ + struct fileheader_t header; + struct stat state; + char dirname[MAXPATHLEN]; + char buf[MAXPATHLEN]; + long numents, size, time, now; + int fd, lower, ent; + + + if (file == NULL || file[0] != 'M' || file[1] != '.' || + (time = atoi(file + 2)) <= 0) { + bbslog("cancel_article: invalid filename `%s`\n", file); + return 0; + } + size = sizeof(header); + sprintf(dirname, "%s/boards/%s/.DIR", homepath, board); + if ((fd = open(dirname, O_RDONLY)) == -1) { + bbslog("cancel_article: open `%s` error\n", dirname); + return 0; + } + fstat(fd, &state); + ent = ((long) state.st_size) / size; + lower = 0; + while (1) + { + ent -= 8; + if (ent <= 0 || lower >= 2) + break; + lseek(fd, size * ent, SEEK_SET); + if (read(fd, &header, size) != size) + { + ent = 0; + break; + } + now = atoi(header.filename + 2); + lower = (now < time) ? lower + 1 : 0; + } + if (ent < 0) + ent = 0; + while (read(fd, &header, size) == size) + { + if (strcmp(file, header.filename) == 0) + { + if ((header.filemode & FILE_MARKED) + || (header.filemode & FILE_DIGEST) || (header.owner[0] == '-')) + break; + delete_record(dirname, sizeof(fileheader_t), lseek(fd, 0, SEEK_CUR) / size); + cancelpost(&header, board); + break; + } + now = atoi(header.filename + 2); + if (now > time) + break; + } + close(fd); + return 0; +} + +#elif defined(PalmBBS) +# undef PATH XPATH +# undef HEADER XHEADER +#include "server.h" + +char * +post_article(homepath, userid, board, writebody, pathname, firstpath) + char *homepath; + char *userid, *board; + int (*writebody) (); +char *pathname, *firstpath; +{ + PATH msgdir, msgfile; + static PATH name; + + READINFO readinfo; + SHORT fileid; + char buf[MAXPATHLEN]; + struct stat stbuf; + int fh; + + strcpy(msgdir, homepath); + if (stat(msgdir, &stbuf) == -1 || !S_ISDIR(stbuf.st_mode)) + { + /* A directory is missing! */ + bbslog(":Err: Unable to post in %s.\n", msgdir); + return NULL; + } + get_filelist_ids(msgdir, &readinfo); + + for (fileid = 1; fileid <= BBS_MAX_FILES; fileid++) + { + int oumask; + if (test_readbit(&readinfo, fileid)) + continue; + fileid_to_fname(msgdir, fileid, msgfile); + sprintf(name, "%04x", fileid); + +#ifdef DEBUG + printf("post to %s\n", msgfile); +#endif + + if (firstpath && *firstpath) + { + +#ifdef DEBUGLINK + bbslog("try to link %s to %s", firstpath, msgfile); +#endif + + if (link(firstpath, msgfile) == 0) + break; + } + oumask = umask(0); + fh = open(msgfile, O_CREAT | O_EXCL | O_WRONLY, 0664); + umask(oumask); + if (writebody) + { + if ((*writebody) (fh, board, pathname) < 0) + return NULL; + } + else + { + if (bbspost_write_post(fh, board, pathname) < 0) + return NULL; + } + close(fh); + break; + } + +#ifdef CACHED_OPENBOARD + { + char *bname; + bname = strrchr(msgdir, '/'); + if (bname) + notify_new_post(++bname, 1, fileid, stbuf.st_mtime); + } +#endif + + return name; +} + +cancel_article(homepath, board, file) + char *homepath; + char *board, *file; +{ + PATH fname; + +#ifdef CACHED_OPENBOARD + PATH bdir; + struct stat stbuf; + + sprintf(bdir, "%s/boards/%s", homepath, board); + stat(bdir, &stbuf); +#endif + + sprintf(fname, "%s/boards/%s/%s", homepath, board, file); + unlink(fname); + /* kill it now! the function is far small then original.. :) */ + /* because it won't make system load heavy like before */ + +#ifdef CACHED_OPENBOARD + notify_new_post(board, -1, hex2SHORT(file), stbuf.st_mtime); +#endif +} + +#else +error("You should choose one of the systems: PhoenixBBS, PowerBBS, or PalmBBS") +#endif + +#else + +receive_article() +{ +} + +cancel_article_front(msgid) + char *msgid; +{ +} +#endif diff --git a/innbbsd/rfc931.c b/innbbsd/rfc931.c new file mode 100644 index 00000000..0d59d771 --- /dev/null +++ b/innbbsd/rfc931.c @@ -0,0 +1,144 @@ + /* + * rfc931_user() speaks a common subset of the RFC 931, AUTH, TAP and IDENT + * protocols. It consults an RFC 931 etc. compatible daemon on the client + * host to look up the remote user name. The information should not be used + * for authentication purposes. + * + * Diagnostics are reported through syslog(3). + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + * + * Inspired by the authutil package (comp.sources.unix volume 22) by Dan + * Bernstein (brnstnd@kramden.acf.nyu.edu). + */ + +#ifndef lint +static char sccsid[] = "@(#) rfc931.c 1.4 93/03/07 22:47:52"; +#endif + +#include <stdio.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <setjmp.h> +#include <signal.h> + +/*#include "log_tcp.h"*/ + +#define RFC931_PORT 113 /* Semi-well-known port */ + +#ifndef RFC931_TIMEOUT +#define RFC931_TIMEOUT 30 /* wait for at most 30 seconds */ +#endif + +extern char *strchr(); +extern char *inet_ntoa(); + +static jmp_buf timebuf; + +/* timeout - handle timeouts */ + +static void timeout(sig) +int sig; +{ + longjmp(timebuf, sig); +} + +/* rfc931_name - return remote user name */ + +char *my_rfc931_name(herefd,there) +int herefd; +struct sockaddr_in *there; /* remote link information */ +{ + struct sockaddr_in here; /* local link information */ + struct sockaddr_in sin; /* for talking to RFC931 daemon */ + int length; + int s; + unsigned remote; + unsigned local; + static char user[256]; /* XXX */ + char buffer[512]; /* YYY */ + FILE *fp; + char *cp; + char *result = "unknown"; + + /* Find out local address and port number of stdin. */ + + length = sizeof(here); + if (getsockname(herefd, (struct sockaddr *) & here, &length) == -1) { + syslog(LOG_ERR, "getsockname: %m"); + return (result); + } + + /* + * The socket that will be used for user name lookups should be bound to + * the same local IP address as stdin. This will automagically happen on + * hosts that have only one IP network address. When the local host has + * more than one IP network address, we must do an explicit bind() call. + */ + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) + return (result); + + sin = here; + sin.sin_port = 0; + if (bind(s, (struct sockaddr *) & sin, sizeof sin) < 0) { + syslog(LOG_ERR, "bind: %s: %m", inet_ntoa(here.sin_addr)); + return (result); + } + /* Set up timer so we won't get stuck. */ + + signal(SIGALRM, timeout); + if (setjmp(timebuf)) { + close(s); /* not: fclose(fp) */ + return (result); + } + alarm(RFC931_TIMEOUT); + + /* Connect to the RFC931 daemon. */ + + sin = *there; + sin.sin_port = htons(RFC931_PORT); + if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1 + || (fp = fdopen(s, "w+")) == 0) { + close(s); + alarm(0); + return (result); + } + + /* + * Use unbuffered I/O or we may read back our own query. setbuf() must be + * called before doing any I/O on the stream. Thanks for the reminder, + * Paul Kranenburg <pk@cs.few.eur.nl>! + */ + + setbuf(fp, (char *) 0); + + /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */ + + fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port)); + fflush(fp); + + /* + * Read response from server. Use fgets()/sscanf() instead of fscanf() + * because there is no buffer for pushback. Thanks, Chris Turbeville + * <turbo@cse.uta.edu>. + */ + + if (fgets(buffer, sizeof(buffer), fp) != 0 + && ferror(fp) == 0 && feof(fp) == 0 + && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s", + &remote, &local, user) == 3 + && ntohs(there->sin_port) == remote + && ntohs(here.sin_port) == local) { + /* Strip trailing carriage return. */ + + if (cp = strchr(user, '\r')) + *cp = 0; + result = user; + } + alarm(0); + fclose(fp); + return (result); +} diff --git a/mbbsd/.cvsignore b/mbbsd/.cvsignore new file mode 100644 index 00000000..35f9f2d1 --- /dev/null +++ b/mbbsd/.cvsignore @@ -0,0 +1,2 @@ +*.o +mbbsd diff --git a/mbbsd/Makefile b/mbbsd/Makefile new file mode 100644 index 00000000..886944f3 --- /dev/null +++ b/mbbsd/Makefile @@ -0,0 +1,45 @@ +# $Id: Makefile,v 1.1 2002/03/07 15:13:48 in2 Exp $ + +BBSHOME?=$(HOME) +OSTYPE=FreeBSD + +# FreeBSD +CFLAGS_FreeBSD= -pipe -Wall -g -O3 -DHAVE_SETPROCTITLE -DBBSHOME='"$(BBSHOME)"' -DFreeBSD -I../include +LDFLAGS_FreeBSD=-pipe -Wall -g -O3 +LIBS_FreeBSD= -lutil -lkvm + +# Linux +CFLAGS_linux= -pipe -Wall -g -O3 -DHAVE_DES_CRYPT -DBBSHOME='"$(BBSHOME)"' -DLinux -I../include -s +LDFLAGS_linux= -pipe -Wall -g -O3 +LIBS_linux= -lcrypt + +CFLAGS= $(CFLAGS_$(OSTYPE)) +LDFLAGS=$(LDFLAGS_$(OSTYPE)) +LIBS= $(LIBS_$(OSTYPE)) + +CC= gcc +PROG= mbbsd +OBJS= admin.o announce.o args.o bbcall.o bbs.o board.o cache.o cal.o card.o\ + chat.o chc_draw.o chc_net.o chc_play.o chc_rule.o chicken.o dark.o\ + dice.o edit.o friend.o gamble.o gomo.o gomo1.o guess.o indict.o io.o\ + kaede.o lovepaper.o mail.o mbbsd.o menu.o more.o name.o osdep.o\ + othello.o page.o read.o record.o register.o screen.o stuff.o\ + talk.o term.o topsong.o user.o vice.o vote.o xyz.o\ + voteboard.o syspost.o var.o descrypt.o toolkit.o passwd.o\ + calendar.o + +.SUFFIXES: .c .o +.c.o: + $(CC) $(CFLAGS) -c $*.c + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +install: $(PROG) + install -d $(BBSHOME)/bin/ + install -c -m 755 $(PROG) $(BBSHOME)/bin/ + +clean: + rm -f $(OBJS) $(PROG) diff --git a/mbbsd/admin.c b/mbbsd/admin.c new file mode 100644 index 00000000..14bc9721 --- /dev/null +++ b/mbbsd/admin.c @@ -0,0 +1,1105 @@ +/* $Id: admin.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +extern char *msg_uid; +extern userec_t xuser; +extern char *err_uid; +extern boardheader_t *bcache; + +/* ¨Ï¥ÎªÌºÞ²z */ +int m_user() { + userec_t muser; + int id; + char genbuf[200]; + + stand_title("¨Ï¥ÎªÌ³]©w"); + usercomplete(msg_uid, genbuf); + if(*genbuf) { + move(2, 0); + if((id = getuser(genbuf))) { + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } else { + outs(err_uid); + clrtoeol(); + pressanykey(); + } + } + return 0; +} + +extern int b_lines; + +static int search_key_user(char *passwdfile, int mode) { + userec_t user; + int ch; + int coun = 0; + FILE *fp1 = fopen(passwdfile, "r"); + char buf[128], key[22], genbuf[8]; + + clear(); + getdata(0, 0, mode ? "½Ð¿é¤J¨Ï¥ÎªÌÃöÁä¦r[¹q¸Ü|¦a§}|©m¦W|¤W¯¸¦aÂI|" + "email|¤pÂûid] :" : "½Ð¿é¤Jid :", key, 21, DOECHO); + while((fread(&user, sizeof(user), 1, fp1)) > 0 && coun < MAX_USERS) { + if(!(++coun & 15)) { + move(1, 0); + sprintf(buf, "²Ä [%d] µ§¸ê®Æ\n", coun); + outs(buf); + refresh(); + } + if(!strcasecmp(user.userid, key) || + (mode && ( + strstr(user.realname, key) || strstr(user.username, key) || + strstr(user.lasthost, key) || strstr(user.email, key) || + strstr(user.address, key) || strstr(user.justify, key) || + strstr(user.mychicken.name, key)))) { + move(1, 0); + sprintf(buf, "²Ä [%d] µ§¸ê®Æ\n", coun); + outs(buf); + refresh(); + + user_display(&user, 1); + uinfo_query(&user, 1, coun); + outs("\033[44m ªÅ¥ÕÁä\033[37m:·j´M¤U¤@Ó" + " \033[33m Q\033[37m: Â÷¶}"); + outs(mode ? " \033[m " : + " S: ¨ú¥Î³Æ¥÷¸ê®Æ \033[m "); + while(1) { + while((ch = igetch()) == 0); + if(ch == ' ') + break; + if(ch == 'q' || ch == 'Q') + return 0; + if(ch == 's' && !mode) { + if((ch = searchuser(user.userid))) { + setumoney(ch,user.money); + passwd_update(ch, &user); + return 0; + } else { + move(b_lines - 1, 0); + genbuf[0] = 'n'; + getdata(0, 0, + "¥Ø«eªº PASSWD ÀɨS¦³¦¹ ID¡A·s¼W¶Ü¡H[y/N]", + genbuf, 3, LCECHO); + if(genbuf[0] == 'n') { + outs("¥Ø«eªºPASSWDSÀɨS¦³¦¹id " + "½Ð¥ýnew¤@Ó³oÓidªº±b¸¹"); + } else { + int allocid = getnewuserid(); + + if(allocid > MAX_USERS || allocid <= 0) { + fprintf(stderr, "¥»¯¸¤H¤f¤w¹F¹¡©M¡I\n"); + exit(1); + } + + if(passwd_update(allocid, &user) == -1) { + fprintf(stderr, "«Èº¡¤F¡A¦A¨£¡I\n"); + exit(1); + } + setuserid(allocid, user.userid); + if(!searchuser(user.userid)) { + fprintf(stderr, "µLªk«Ø¥ß±b¸¹\n"); + exit(1); + } + return 0; + } + } + } + } + } + } + + fclose(fp1); + return 0; +} + +/* ¥H¥ô·N key ´M§ä¨Ï¥ÎªÌ */ +int search_user_bypwd() { + search_key_user(FN_PASSWD, 1); + return 0; +} + +/* ´M§ä³Æ¥÷ªº¨Ï¥ÎªÌ¸ê®Æ */ +int search_user_bybakpwd() { + char *choice[] = { + "PASSWDS.NEW1", "PASSWDS.NEW2", "PASSWDS.NEW3", + "PASSWDS.NEW4", "PASSWDS.NEW5", "PASSWDS.NEW6", + "PASSWDS.BAK" + }; + int ch; + + clear(); + move(1, 1); + outs("½Ð¿é¤J§An¥Î¨Ó´M§ä³Æ¥÷ªºÀÉ®× ©Î«ö 'q' Â÷¶}\n"); + outs(" [\033[1;31m1\033[m]¤@¤Ñ«e, [\033[1;31m2\033[m]¨â¤Ñ«e, " + "[\033[1;31m3\033[m]¤T¤Ñ«e\n"); + outs(" [\033[1;31m4\033[m]¥|¤Ñ«e, [\033[1;31m5\033[m]¤¤Ñ«e, " + "[\033[1;31m6\033[m]¤»¤Ñ«e\n"); + outs(" [7]³Æ¥÷ªº\n"); + do { + move(5, 1); + outs("¿ï¾Ü => "); + ch = igetch(); + if(ch == 'q' || ch == 'Q') + return 0; + } while (ch < '1' || ch > '8'); + ch -= '1'; + search_key_user(choice[ch], 0); + return 0; +} + +static void bperm_msg(boardheader_t *board) { + prints("\n³]©w [%s] ¬ÝªO¤§(%s)Åv¡G", board->brdname, + board->brdattr & BRD_POSTMASK ? "µoªí" : "¾\\Ū"); +} + +extern char* str_permboard[]; + +unsigned int setperms(unsigned int pbits, char *pstring[]) { + register int i; + char choice[4]; + + move(4, 0); + for(i = 0; i < NUMPERMS / 2; i++) { + prints("%c. %-20s %-15s %c. %-20s %s\n", + 'A' + i, pstring[i], + ((pbits >> i) & 1 ? "£¾" : "¢æ"), + i < 10 ? 'Q' + i : '0' + i - 10, + pstring[i + 16], + ((pbits >> (i + 16)) & 1 ? "£¾" : "¢æ")); + } + clrtobot(); + while(getdata(b_lines - 1, 0, "½Ð«ö [A-5] ¤Á´«³]©w¡A«ö [Return] µ²§ô¡G", + choice, 3, LCECHO)) { + i = choice[0] - 'a'; + if(i < 0) + i = choice[0] - '0' + 26; + if(i >= NUMPERMS) + bell(); + else { + pbits ^= (1 << i); + move(i % 16 + 4, i <= 15 ? 24 : 64); + prints((pbits >> i) & 1 ? "£¾" : "¢æ"); + } + } + return pbits; +} + +/* ¦Û°Ê³]¥ßºëµØ°Ï */ +void setup_man(boardheader_t * board) { + char genbuf[200]; + + setapath(genbuf, board->brdname); + mkdir(genbuf, 0755); +} + +extern char *fn_board; +extern char *err_bid; +extern userec_t cuser; +extern char *msg_sure_ny; +extern char* str_permid[]; + +int m_mod_board(char *bname) { + boardheader_t bh, newbh; + int bid; + char genbuf[256], ans[4]; + + bid = getbnum(bname); + if(!bid || !bname[0] || get_record(fn_board, &bh, sizeof(bh), bid) == -1) { + outs(err_bid); + pressanykey(); + return -1; + } + + prints("¬ÝªO¦WºÙ¡G%s\n¬ÝªO»¡©ú¡G%s\n¬ÝªObid¡G%d\n¬ÝªOGID¡G%d\n" + "ªO¥D¦W³æ¡G%s", bh.brdname, bh.title, bid, bh.gid, bh.BM); + bperm_msg(&bh); + + /* Ptt ³oÃäÂ_¦æ·|Àɨì¤U± */ + move(9, 0); + sprintf(genbuf, "¬ÝªO (E)³]©w (V)¹Hªk/¸Ñ°£ %s (D)§R°£ [Q]¨ú®ø¡H", + HAS_PERM(PERM_SYSOP) ? + " (B)BVote (S)±Ï¦^¤å³¹" : ""); + getdata(10, 0, genbuf, ans, 3, LCECHO); + + switch(*ans) { + case 's': + if(HAS_PERM(PERM_SYSOP) ) { + char actionbuf[512]; + + sprintf(actionbuf, BBSHOME "/bin/buildir boards/%s &", + bh.brdname); + system(actionbuf); + } + break; + case 'b': + if(HAS_PERM(PERM_SYSOP)) { + char bvotebuf[10]; + + memcpy(&newbh, &bh, sizeof(bh)); + sprintf(bvotebuf, "%d", newbh.bvote); + move(20, 0); + prints("¬Ýª© %s ì¨Óªº BVote¡G%d", bh.brdname, bh.bvote); + getdata_str(21, 0, "·sªº Bvote¡G", genbuf, 5, LCECHO, bvotebuf); + newbh.bvote = atoi(genbuf); + substitute_record(fn_board, &newbh, sizeof(newbh), bid); + reset_board(bid); + log_usies("SetBoardBvote", newbh.brdname); + break; + } else + break; + case 'v': + memcpy(&newbh, &bh, sizeof(bh)); + outs("¬Ýª©¥Ø«e¬°"); + outs((bh.brdattr & BRD_BAD) ? "¹Hªk" : "¥¿±`"); + getdata(21, 0, "½T©w§ó§ï¡H", genbuf, 5, LCECHO); + if(genbuf[0] == 'y') { + if(newbh.brdattr & BRD_BAD) + newbh.brdattr = newbh.brdattr & (!BRD_BAD); + else + newbh.brdattr = newbh.brdattr | BRD_BAD; + substitute_record(fn_board, &newbh, sizeof(newbh), bid); + reset_board(bid); + log_usies("ViolateLawSet", newbh.brdname); + } + break; + case 'd': + getdata_str(9, 0, msg_sure_ny, genbuf, 3, LCECHO, "N"); + if(genbuf[0] != 'y' || !bname[0]) + outs(MSG_DEL_CANCEL); + else { + strcpy(bname, bh.brdname); + sprintf(genbuf, + "/bin/tar zcvf tmp/board_%s.tgz boards/%s man/%s >/dev/null 2>&1;" + "/bin/rm -fr boards/%s man/%s", + bname, bname, bname, bname, bname); + system(genbuf); + memset(&bh, 0, sizeof(bh)); + sprintf(bh.title, "%s ¬ÝªO %s §R°£", bname, cuser.userid); + post_msg("Security", bh.title,"½Ðª`·N§R°£ªº¦Xªk©Ê","[¨t²Î¦w¥þ§½]"); + substitute_record(fn_board, &bh, sizeof(bh), bid); + reset_board(bid); + log_usies("DelBoard", bh.title); + outs("§RªO§¹²¦"); + } + break; + case 'e': + move(8, 0); + outs("ª½±µ«ö [Return] ¤£×§ï¸Ó¶µ³]©w"); + memcpy(&newbh, &bh, sizeof(bh)); + + while(getdata(9, 0, "·s¬ÝªO¦WºÙ¡G", genbuf, IDLEN + 1, DOECHO)) { + if(getbnum(genbuf)) { + move(3, 0); + outs("¿ù»~! ªO¦W¹p¦P"); + } else if(!invalid_brdname(genbuf)) { + strcpy(newbh.brdname, genbuf); + break; + } + } + + do { + getdata_str(12, 0, "¬ÝªOÃþ§O¡G", genbuf, 5, DOECHO, bh.title); + if(strlen(genbuf) == 4) + break; + } while (1); + + if(strlen(genbuf) >= 4) + strncpy(newbh.title, genbuf, 4); + + newbh.title[4] = ' '; + + getdata_str(14, 0, "¬ÝªO¥DÃD¡G", genbuf, BTLEN + 1, DOECHO, + bh.title + 7); + if(genbuf[0]) + strcpy(newbh.title + 7, genbuf); + if(getdata_str(15, 0, "·sªO¥D¦W³æ¡G", genbuf, IDLEN * 3 + 3, DOECHO, + bh.BM)) { + trim(genbuf); + strcpy(newbh.BM, genbuf); + } + + if(HAS_PERM(PERM_SYSOP)) { + move(1, 0); + clrtobot(); + newbh.brdattr = setperms(newbh.brdattr, str_permboard); + move(1, 0); + clrtobot(); + } + + if(newbh.brdattr & BRD_GROUPBOARD) + strncpy(newbh.title + 5, "£U", 2); + else if(newbh.brdattr & BRD_NOTRAN) + strncpy(newbh.title + 5, "¡·", 2); + else + strncpy(newbh.title + 5, "¡´", 2); + + if(HAS_PERM(PERM_SYSOP) && !(newbh.brdattr & BRD_HIDE)) { + getdata_str(14, 0, "³]©wŪ¼gÅv(Y/N)¡H", ans, 4, LCECHO, "N"); + if(*ans == 'y') { + getdata_str(15, 0, "¨î [R]¾\\Ū (P)µoªí¡H", ans, 4, LCECHO, + "R"); + if(*ans == 'p') + newbh.brdattr |= BRD_POSTMASK; + else + newbh.brdattr &= ~BRD_POSTMASK; + + move(1, 0); + clrtobot(); + bperm_msg(&newbh); + newbh.level = setperms(newbh.level, str_permid); + clear(); + } + } + + getdata_str(b_lines - 1, 0, msg_sure_ny, genbuf, 4, LCECHO, "Y"); + + if((*genbuf == 'y') && memcmp(&newbh, &bh, sizeof(bh))) { + if(strcmp(bh.brdname, newbh.brdname)) { + char src[60], tar[60]; + + setbpath(src, bh.brdname); + setbpath(tar, newbh.brdname); + Rename(src, tar); + + setapath(src, bh.brdname); + setapath(tar, newbh.brdname); + Rename(src, tar); + } + setup_man(&newbh); + substitute_record(fn_board, &newbh, sizeof(newbh), bid); + reset_board(bid); + log_usies("SetBoard", newbh.brdname); + } + } + return 0; +} + +extern char *msg_bid; + +/* ³]©w¬Ýª© */ +int m_board() { + char bname[32]; + + stand_title("¬ÝªO³]©w"); + make_blist(); + namecomplete(msg_bid, bname); + if(!*bname) + return 0; + m_mod_board(bname); + return 0; +} + +/* ³]©w¨t²ÎÀÉ®× */ +int x_file() { + int aborted; + char ans[4], *fpath; + + move(b_lines - 4, 0); + /* Ptt */ + outs("³]©w (1)¨¥÷½T»{«H (4)postª`·N¨Æ¶µ (5)¿ù»~µn¤J°T®§ (6)µù¥U½d¨Ò (7)³q¹L½T»{³qª¾\n"); + outs(" (8)email post³qª¾ (9)¨t²Î¥\\¯àºëÆF (A)¯ù¼Ó (B)¯¸ªø¦W³æ (C)email³q¹L½T»{\n"); + outs(" (D)·s¨Ï¥ÎªÌ»Ýª¾ (E)¨¥÷½T»{¤èªk (F)Åwªïµe± (G)¶i¯¸µe± " +#ifdef MULTI_WELCOME_LOGIN +"(X)§R°£¶i¯¸µe±" +#endif +"\n"); + getdata(b_lines - 1, 0, " (H)¬ÝªO´Á (I)¬G¶m (J)¥X¯¸µe± (K)¥Í¤é¥d (L)¸`¤é [Q]¨ú®ø¡H", ans, 3, LCECHO); + + switch(ans[0]) { + case '1': + fpath = "etc/confirm"; + break; + case '4': + fpath = "etc/post.note"; + break; + case '5': + fpath = "etc/goodbye"; + break; + case '6': + fpath = "etc/register"; + break; + case '7': + fpath = "etc/registered"; + break; + case '8': + fpath = "etc/emailpost"; + break; + case '9': + fpath = "etc/hint"; + break; + case 'a': + fpath = "etc/teashop"; + break; + case 'b': + fpath = "etc/sysop"; + break; + case 'c': + fpath = "etc/bademail"; + break; + case 'd': + fpath = "etc/newuser"; + break; + case 'e': + fpath = "etc/justify"; + break; + case 'f': + fpath = "etc/Welcome"; + break; + case 'g': +#ifdef MULTI_WELCOME_LOGIN + getdata(b_lines - 1, 0, "²Ä´XÓ¶i¯¸µe±[0-4]", ans, 3, LCECHO); + if( ans[0] == '1' ) { fpath = "etc/Welcome_login.1"; } + else if( ans[0] == '2' ){ fpath = "etc/Welcome_login.2"; } + else if( ans[0] == '3' ){ fpath = "etc/Welcome_login.3"; } + else if( ans[0] == '4' ){ fpath = "etc/Welcome_login.4"; } + else { fpath = "etc/Welcome_login.0"; } +#else + fpath = "etc/Welcome_login"; +#endif + break; + +#ifdef MULTI_WELCOME_LOGIN + case 'x': + getdata(b_lines - 1, 0, "²Ä´XÓ¶i¯¸µe±[1-4]", ans, 3, LCECHO); + if( ans[0] == '1' ) { unlink("etc/Welcome_login.1"); outs("ok"); } + else if( ans[0] == '2' ){ unlink("etc/Welcome_login.2"); outs("ok"); } + else if( ans[0] == '3' ){ unlink("etc/Welcome_login.3"); outs("ok"); } + else if( ans[0] == '4' ){ unlink("etc/Welcome_login.4"); outs("ok"); } + else {outs("©Ò«ü©wªº¶i¯¸µe±µLªk§R°£"); } + pressanykey(); + return FULLUPDATE; + +#endif + + case 'h': + fpath = "etc/expire.conf"; + break; + case 'i': + fpath = "etc/domain_name_query"; + break; + case 'j': + fpath = "etc/Logout"; + break; + case 'k': + fpath = "etc/Welcome_birth"; + break; + case 'l': + fpath = "etc/feast"; + break; + default: + return FULLUPDATE; + } + aborted = vedit(fpath, NA, NULL); + prints("\n\n¨t²ÎÀÉ®×[%s]¡G%s", fpath, + (aborted == -1) ? "¥¼§ïÅÜ" : "§ó·s§¹²¦"); + pressanykey(); + return FULLUPDATE; +} + +extern int numboards; +extern int class_bid; + +int m_newbrd(int recover) { + boardheader_t newboard; + char ans[4]; + int bid; + char genbuf[200]; + + stand_title("«Ø¥ß·sªO"); + memset(&newboard, 0, sizeof(newboard)); + + newboard.gid = class_bid; + if (newboard.gid == 0) { + move(6, 0); + outs("½Ð¥ý¿ï¾Ü¤@ÓÃþ§O¦A¶}ªO!"); + pressanykey(); + return -1; + } + + do { + if(!getdata(3, 0, msg_bid, newboard.brdname, IDLEN + 1, DOECHO)) + return -1; + } while(invalid_brdname(newboard.brdname)); + + do { + getdata(6, 0, "¬ÝªOÃþ§O¡G", genbuf, 5, DOECHO); + if(strlen(genbuf) == 4) + break; + } while (1); + + if(strlen(genbuf) >= 4) + strncpy(newboard.title, genbuf, 4); + + newboard.title[4] = ' '; + + getdata(8, 0, "¬ÝªO¥DÃD¡G", genbuf, BTLEN + 1, DOECHO); + if(genbuf[0]) + strcpy(newboard.title + 7, genbuf); + setbpath(genbuf, newboard.brdname); + + if(recover) { + struct stat sb; + + if(stat(genbuf, &sb) == -1 || !(sb.st_mode & S_IFDIR)) { + outs("¦¹¬ÝªO¤w¸g¦s¦b! ½Ð¨ú¤£¦P^¤åªO¦W"); + pressanykey(); + return -1; + } + } else if(getbnum(newboard.brdname) > 0 || mkdir(genbuf, 0755) == -1) { + outs("¦¹¬ÝªO¤w¸g¦s¦b! ½Ð¨ú¤£¦P^¤åªO¦W"); + pressanykey(); + return -1; + } + + newboard.brdattr = BRD_NOTRAN; + + if(HAS_PERM(PERM_SYSOP)) { + move(1, 0); + clrtobot(); + newboard.brdattr = setperms(newboard.brdattr, str_permboard); + move(1, 0); + clrtobot(); + } + getdata(9, 0, "¬O¬ÝªO? (N:¥Ø¿ý) (Y/n)¡G", genbuf, 3, LCECHO); + if(genbuf[0]=='n') + newboard.brdattr |= BRD_GROUPBOARD; + + if(newboard.brdattr & BRD_GROUPBOARD) + strncpy(newboard.title + 5, "£U", 2); + else if(newboard.brdattr & BRD_NOTRAN) + strncpy(newboard.title + 5, "¡·", 2); + else + strncpy(newboard.title + 5, "¡´", 2); + + newboard.level = 0; + getdata(11, 0, "ªO¥D¦W³æ¡G", newboard.BM, IDLEN * 3 + 3, DOECHO); + + if(HAS_PERM(PERM_SYSOP) && !(newboard.brdattr & BRD_HIDE)) { + getdata_str(14, 0, "³]©wŪ¼gÅv(Y/N)¡H", ans, 3, LCECHO, "N"); + if(*ans == 'y') { + getdata_str(15, 0, "¨î [R]¾\\Ū (P)µoªí¡H", ans, 4, LCECHO, "R"); + if(*ans == 'p') + newboard.brdattr |= BRD_POSTMASK; + else + newboard.brdattr &= (~BRD_POSTMASK); + + move(1, 0); + clrtobot(); + bperm_msg(&newboard); + newboard.level = setperms(newboard.level, str_permid); + clear(); + } + } + + if((bid = getbnum("")) > 0) + { + substitute_record(fn_board, &newboard, sizeof(newboard), bid); + reset_board(bid); + } + else if(append_record(fn_board, (fileheader_t *) & newboard, + sizeof(newboard)) == -1) { + pressanykey(); + return -1; + } + else + { + addbrd_touchcache(); + } + setup_man(&newboard); + + outs("\n·sªO¦¨¥ß"); + post_newboard(newboard.title, newboard.brdname, newboard.BM); + log_usies("NewBoard", newboard.title); + pressanykey(); + return 0; +} + +static int auto_scan(char fdata[][STRLEN], char ans[]) { + int good = 0; + int count = 0; + int i; + char temp[10]; + + if(!strncmp(fdata[2], "¤p", 2) || strstr(fdata[2], "¤X") + || strstr(fdata[2], "½Ö") || strstr(fdata[2], "¤£")) { + ans[0] = '0'; + return 1; + } + + strncpy(temp, fdata[2], 2); + temp[2] = '\0'; + + /* Å|¦r */ + if(!strncmp(temp, &(fdata[2][2]), 2)) { + ans[0] = '0'; + return 1; + } + + if(strlen(fdata[2]) >= 6) { + if(strstr(fdata[2], "³¯¤ô«ó")) { + ans[0] = '0'; + return 1; + } + + if(strstr("»¯¿ú®]§õ©P§d¾G¤ý", temp)) + good++; + else if(strstr("§ùÃC¶ÀªL³¯©x§E¨¯¼B", temp)) + good++; + else if(strstr("Ĭ¤è§d§f§õªò±i¹ùÀ³Ä¬", temp)) + good++; + else if(strstr("®}ÁÂ¥Û¿c¬IÀ¹¯Îð", temp)) + good++; + } + + if(!good) + return 0; + + if(!strcmp(fdata[3], fdata[4]) || + !strcmp(fdata[3], fdata[5]) || + !strcmp(fdata[4], fdata[5])) { + ans[0] = '4'; + return 5; + } + + if(strstr(fdata[3], "¤j")) { + if (strstr(fdata[3], "¥x") || strstr(fdata[3], "²H") || + strstr(fdata[3], "¥æ") || strstr(fdata[3], "¬F") || + strstr(fdata[3], "²M") || strstr(fdata[3], "ĵ") || + strstr(fdata[3], "®v") || strstr(fdata[3], "»Ê¶Ç") || + strstr(fdata[3], "¤¤¥¡") || strstr(fdata[3], "¦¨") || + strstr(fdata[3], "»²") || strstr(fdata[3], "ªF§d")) + good++; + } else if(strstr(fdata[3], "¤k¤¤")) + good++; + + if(strstr(fdata[4], "¦a²y") || strstr(fdata[4], "¦t©z") || + strstr(fdata[4], "«H½c")) { + ans[0] = '2'; + return 3; + } + + if(strstr(fdata[4], "¥«") || strstr(fdata[4], "¿¤")) { + if(strstr(fdata[4], "¸ô") || strstr(fdata[4], "µó")) { + if(strstr(fdata[4], "¸¹")) + good++; + } + } + + for(i = 0; fdata[5][i]; i++) { + if(isdigit(fdata[5][i])) + count++; + } + + if(count <= 4) { + ans[0] = '3'; + return 4; + } else if(count >= 7) + good++; + + if(good >= 3) { + ans[0] = 'y'; + return -1; + } else + return 0; +} + +/* ³B²z Register Form */ +int scan_register_form(char *regfile, int automode, int neednum) { + char genbuf[200]; + static char *logfile = "register.log"; + static char *field[] = { + "uid", "ident", "name", "career", "addr", "phone", "email", NULL + }; + static char *finfo[] = { + "±b¸¹", "¨¤ÀÃÒ¸¹", "¯u¹ê©m¦W", "ªA°È³æ¦ì", "¥Ø«e¦í§}", + "³sµ¸¹q¸Ü", "¹q¤l¶l¥ó«H½c", NULL + }; + static char *reason[] = { + "¿é¤J¯u¹ê©m¦W", "¸Ô¶ñ¾Ç®Õ¬ì¨t»P¦~¯Å", "¶ñ¼g§¹¾ãªº¦í§}¸ê®Æ", + "¸Ô¶ñ³sµ¸¹q¸Ü", "½T¹ê¶ñ¼gµù¥U¥Ó½Ðªí", "¥Î¤¤¤å¶ñ¼g¥Ó½Ð³æ", NULL + }; + static char *autoid = "AutoScan"; + userec_t muser; + FILE *fn, *fout, *freg; + char fdata[7][STRLEN]; + char fname[STRLEN], buf[STRLEN]; + char ans[4], *ptr, *uid; + int n, unum; + int nSelf = 0, nAuto = 0; + + uid = cuser.userid; + sprintf(fname, "%s.tmp", regfile); + move(2, 0); + if(dashf(fname)) { + if(neednum == 0) { /* ¦Û¤v¶i Admin ¨Ó¼fªº */ + outs("¨ä¥L SYSOP ¤]¦b¼f®Öµù¥U¥Ó½Ð³æ"); + pressanykey(); + } + return -1; + } + Rename(regfile, fname); + if((fn = fopen(fname, "r")) == NULL) { + prints("¨t²Î¿ù»~¡AµLªkŪ¨úµù¥U¸ê®ÆÀÉ: %s", fname); + pressanykey(); + return -1; + } + if(neednum) { /* ³Q±j¢¼fªº */ + move(1, 0); + clrtobot(); + prints("¦U¦ì¨ã¦³¯¸ªøÅvªº¤H¡Aµù¥U³æ²Ö¿n¶W¹L¤@¦Ê¥÷¤F¡A³Â·Ð±zÀ°¦£¼f %d ¥÷\n", neednum); + prints("¤]´N¬O¤j·§¤G¤Q¤À¤§¤@ªº¼Æ¶q¡A·íµM¡A±z¤]¥i¥H¦h¼f\n¨S¼f§¹¤§«e¡A¨t²Î¤£·|Åý§A¸õ¥X³é¡IÁÂÁÂ"); + pressanykey(); + } + memset(fdata, 0, sizeof(fdata)); + while(fgets(genbuf, STRLEN, fn)) { + if ((ptr = (char *) strstr(genbuf, ": "))) { + *ptr = '\0'; + for(n = 0; field[n]; n++) { + if(strcmp(genbuf, field[n]) == 0) { + strcpy(fdata[n], ptr + 2); + if((ptr = (char *) strchr(fdata[n], '\n'))) + *ptr = '\0'; + } + } + } else if ((unum = getuser(fdata[0])) == 0) { + move(2, 0); + clrtobot(); + outs("¨t²Î¿ù»~¡A¬dµL¦¹¤H\n\n"); + for (n = 0; field[n]; n++) + prints("%s : %s\n", finfo[n], fdata[n]); + pressanykey(); + neednum--; + } else { + neednum--; + memcpy(&muser, &xuser, sizeof(muser)); + if(automode) + uid = autoid; + + if(!automode || !auto_scan(fdata, ans)) { + uid = cuser.userid; + + move(1, 0); + prints("±b¸¹¦ì¸m ¡G%d\n", unum); + user_display(&muser, 1); + move(14, 0); + prints("\033[1;32m------------- ½Ð¯¸ªøÄY®æ¼f®Ö¨Ï¥ÎªÌ¸ê®Æ¡A±zÁÙ¦³ %d ¥÷---------------\033[m\n", neednum); + for(n = 0; field[n]; n++) { + if(n >= 2 && n <= 5) + prints("%d.", n - 2); + else + prints(" "); + prints("%-12s¡G%s\n", finfo[n], fdata[n]); + } + if(muser.userlevel & PERM_LOGINOK) { + getdata(b_lines - 1, 0, "\033[1;32m¦¹±b¸¹¤w¸g§¹¦¨µù¥U, " + "§ó·s(Y/N/Skip)¡H\033[m[N] ", ans, 3, LCECHO); + if(ans[0] != 'y' && ans[0] != 's') + ans[0] = 'd'; + } else { + getdata(b_lines - 1, 0, + "¬O§_±µ¨ü¦¹¸ê®Æ(Y/N/Q/Del/Skip)¡H[Y] ", + ans, 3, LCECHO); + } + nSelf++; + } else + nAuto++; + if(neednum > 0 && ans[0] == 'q') { + move(2, 0); + clrtobot(); + prints("¨S¼f§¹¤£¯à°h¥X"); + pressanykey(); + ans[0] = 's'; + } + + switch(ans[0]) { + case 'q': + if((freg = fopen(regfile, "a"))) { + for(n = 0; field[n]; n++) + fprintf(freg, "%s: %s\n", field[n], fdata[n]); + fprintf(freg, "----\n"); + while(fgets(genbuf, STRLEN, fn)) + fputs(genbuf, freg); + fclose(freg); + } + case 'd': + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case 'n': + if(ans[0] == 'n') { + for(n = 0; field[n]; n++) + prints("%s: %s\n", finfo[n], fdata[n]); + move(9, 0); + prints("½Ð´£¥X°h¦^¥Ó½Ðªíì¦]¡A«ö <enter> ¨ú®ø\n"); + for (n = 0; reason[n]; n++) + prints("%d) ½Ð%s\n", n, reason[n]); + } else + buf[0] = ans[0]; + if(ans[0] != 'n' || + getdata(10 + n, 0, "°h¦^ì¦]¡G", buf, 60, DOECHO)) + if((buf[0] - '0') >= 0 && (buf[0] - '0') < n) { + int i; + fileheader_t mhdr; + char title[128], buf1[80]; + FILE *fp; + + i = buf[0] - '0'; + strcpy(buf, reason[i]); + sprintf(genbuf, "[°h¦^ì¦]] ½Ð%s", buf); + + sethomepath(buf1, muser.userid); + stampfile(buf1, &mhdr); + strcpy(mhdr.owner, cuser.userid); + strncpy(mhdr.title, "[µù¥U¥¢±Ñ]", TTLEN); + mhdr.savemode = 0; + mhdr.filemode = 0; + sethomedir(title, muser.userid); + if(append_record(title, &mhdr, sizeof(mhdr)) != -1) { + fp = fopen(buf1, "w"); + fprintf(fp, "%s\n", genbuf); + fclose(fp); + } + if((fout = fopen(logfile, "a"))) { + for(n = 0; field[n]; n++) + fprintf(fout, "%s: %s\n", field[n], fdata[n]); + n = time(NULL); + fprintf(fout, "Date: %s\n", Cdate((time_t *) & n)); + fprintf(fout, "Rejected: %s [%s]\n----\n", + uid, buf); + fclose(fout); + } + break; + } + move(10, 0); + clrtobot(); + prints("¨ú®ø°h¦^¦¹µù¥U¥Ó½Ðªí"); + case 's': + if((freg = fopen(regfile, "a"))) { + for(n = 0; field[n]; n++) + fprintf(freg, "%s: %s\n", field[n], fdata[n]); + fprintf(freg, "----\n"); + fclose(freg); + } + break; + default: + prints("¥H¤U¨Ï¥ÎªÌ¸ê®Æ¤w¸g§ó·s:\n"); + mail_muser(muser, "[µù¥U¦¨¥\\Åo]", "etc/registered"); + muser.userlevel |= (PERM_LOGINOK | PERM_POST); + strcpy(muser.realname, fdata[2]); + strcpy(muser.address, fdata[4]); + strcpy(muser.email, fdata[6]); + sprintf(genbuf, "%s:%s:%s", fdata[5], fdata[3], uid); + strncpy(muser.justify, genbuf, REGLEN); + sethomefile(buf, muser.userid, "justify"); + log_file(buf, genbuf); + passwd_update(unum, &muser); + + if((fout = fopen(logfile, "a"))) { + for(n = 0; field[n]; n++) + fprintf(fout, "%s: %s\n", field[n], fdata[n]); + n = time(NULL); + fprintf(fout, "Date: %s\n", Cdate((time_t *) & n)); + fprintf(fout, "Approved: %s\n", uid); + fprintf(fout, "----\n"); + fclose(fout); + } + break; + } + } + } + fclose(fn); + unlink(fname); + + move(0, 0); + clrtobot(); + + move(5, 0); + prints("±z¼f¤F %d ¥÷µù¥U³æ¡AAutoScan ¼f¤F %d ¥÷", nSelf, nAuto); + +/** DickG: ±N¼f¤F´X¥÷ªº¬ÛÃö¸ê®Æ post ¨ì Security ªO¤W ***********/ +/* DickG: ¦]À³·sªº¯¸ªø¤W¯¸»Ý¼f®Ö¤è®×¡A¬O¬G¨S¦³¥²n¯d¤U record ¦ÓÃö±¼ + strftime(buf, 200, "%Y/%m/%d/%H:%M", pt); + + strcpy(xboard, "Security"); + setbpath(xfpath, xboard); + stampfile(xfpath, &xfile); + strcpy(xfile.owner, "¨t²Î"); + strcpy(xfile.title, "[³ø§i] ¼f®Ö°O¿ý"); + xfile.savemode = 'S'; + xptr = fopen(xfpath, "w"); + fprintf(xptr, "\n®É¶¡¡G%s + %s ¼f¤F %d ¥÷µù¥U³æ\n + AutoScan ¼f¤F %d ¥÷µù¥U³æ\n + ¦@p %d ¥÷¡C", + buf, cuser.userid, nSelf, nAuto, nSelf+nAuto); + fclose(xptr); + setbdir(fname, xboard); + append_record(fname, &xfile, sizeof(xfile)); + outgo_post(&xfile, xboard); + touchbtotal(getbnum(xboard)); + cuser.numposts++; +*/ +/*********************************************/ + pressanykey(); + return (0); +} + +extern char* fn_register; +extern int t_lines; + +int m_register() { + FILE *fn; + int x, y, wid, len; + char ans[4]; + char genbuf[200]; + + if((fn = fopen(fn_register, "r")) == NULL) { + outs("¥Ø«e¨ÃµL·sµù¥U¸ê®Æ"); + return XEASY; + } + + stand_title("¼f®Ö¨Ï¥ÎªÌµù¥U¸ê®Æ"); + y = 2; + x = wid = 0; + + while(fgets(genbuf, STRLEN, fn) && x < 65) { + if(strncmp(genbuf, "uid: ", 5) == 0) { + move(y++, x); + outs(genbuf + 5); + len = strlen(genbuf + 5); + if(len > wid) + wid = len; + if(y >= t_lines - 3) { + y = 2; + x += wid + 2; + } + } + } + fclose(fn); + getdata(b_lines - 1, 0, "¶}©l¼f®Ö¶Ü(Auto/Yes/No)¡H[N] ", ans, 3, LCECHO); + if(ans[0] == 'a') + scan_register_form(fn_register, 1, 0); + else if(ans[0] == 'y') + scan_register_form(fn_register, 0, 0); + + return 0; +} + +int cat_register() { + if(system("cat register.new.tmp >> register.new") == 0 && + system("rm -f register.new.tmp") == 0) + mprints(22, 0, "OK ÂP~~ Ä~Äò¥h¾Ä°«§a!! "); + else + mprints(22, 0, "¨S¿ìªkCAT¹L¥h©O ¥hÀˬd¤@¤U¨t²Î§a!! "); + pressanykey(); + return 0; +} + +static void give_id_money(char *user_id, int money, FILE *log_fp, char *mail_title, time_t t) { + char tt[TTLEN + 1] = {0}; + + if(deumoney(searchuser(user_id), money) < 0) { + move(12, 0); + clrtoeol(); + prints("id:%s money:%d ¤£¹ï§a!!", user_id, money); + pressanykey(); + } else { + fprintf(log_fp, "%ld %s %d", t, user_id, money); + sprintf(tt, "%s : %d ptt ¹ô", mail_title, money); + mail_id(user_id, tt, "~bbs/etc/givemoney.why", "[PTT »È¦æ]"); + } +} + +int give_money() { + FILE *fp, *fp2; + char *ptr, *id, *mn; + char buf[200] = {0}, tt[TTLEN + 1] = {0}; + time_t t = time(NULL); + struct tm *pt = localtime(&t); + int to_all = 0, money = 0; + + getdata(0, 0, "«ü©w¨Ï¥ÎªÌ(S) ¥þ¯¸¨Ï¥ÎªÌ(A) ¨ú®ø(Q)¡H[S]", buf, 3, LCECHO); + if(buf[0] == 'q') + return 1; + else if( buf[0] == 'a') { + to_all = 1; + getdata(1, 0, "µo¦h¤Ö¿ú©O?", buf, 20, DOECHO); + money = atoi(buf); + if(money <= 0) { + move(2, 0); + prints("¿é¤J¿ù»~!!"); + pressanykey(); + return 1; + } + } else { + if(vedit("etc/givemoney.txt", NA, NULL) < 0) + return 1; + } + + clear(); + getdata(0, 0, "nµo¿ú¤F¶Ü(Y/N)[N]", buf, 3, LCECHO); + if(buf[0] != 'y') + return 1; + + if(!(fp2 = fopen("etc/givemoney.log", "a"))) + return 1; + strftime(buf, 200, "%Y/%m/%d/%H:%M", pt); + fprintf(fp2, "%s\n", buf); + + getdata(1, 0, "¬õ¥]³U¼ÐÃD ¡G", tt, TTLEN, DOECHO); + move(2, 0); + + prints("½s¬õ¥]³U¤º®e"); + pressanykey(); + if(vedit("etc/givemoney.why", NA, NULL) < 0) + return 1; + + stand_title("µo¿ú¤¤..."); + if(to_all) { + extern struct uhash_t *uhash; + int i, unum; + for(unum = uhash->number, i=0; i<unum; i++) { + if(bad_user_id(uhash->userid[i])) + continue; + id = uhash->userid[i]; + give_id_money(id, money, fp2, tt, t); + } + } else { + if(!(fp = fopen("etc/givemoney.txt", "r+"))) { + fclose(fp2); + return 1; + } + while(fgets(buf, 255, fp)) { +// clear(); + if (!(ptr = strchr(buf, ':'))) + continue; + *ptr = '\0'; + id = buf; + mn = ptr + 1; + give_id_money(id, atoi(mn), fp2, tt, t); + } + fclose(fp); + } + + fclose(fp2); + pressanykey(); + return FULLUPDATE; +} diff --git a/mbbsd/announce.c b/mbbsd/announce.c new file mode 100644 index 00000000..960a45aa --- /dev/null +++ b/mbbsd/announce.c @@ -0,0 +1,1590 @@ +/* $Id: announce.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <netdb.h> +#include <unistd.h> +#include <setjmp.h> +#include <signal.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern int b_lines; +extern int p_lines; +extern int TagNum; +extern int currbid; +static void g_showmenu(gmenu_t *pm) { + static char *mytype = "½s ¿ï µ·¸ô¤§®È"; + char *title, ch; + int n, max; + item_t *item; + + showtitle("ºëµØ¤å³¹", pm->mtitle); + prints(" \033[1;36m½s¸¹ ¼Ð ÃD%56s\033[m", mytype); + + if(pm->num) { + n = pm->page; + max = n + p_lines; + if(max > pm->num) + max = pm->num; + while(n < max) { + item = pm->item[n++]; + title = item->title; + ch = title[1]; + prints("\n%5d. %-72.71s", n, title); + } + } else + outs("\n ¡mºëµØ°Ï¡n©|¦b§l¨ú¤Ñ¦a¶¡ªº¤éºë¤ëµØ :)"); + + move(b_lines, 1); + outs(pm->level ? + "\033[34;46m ¡iªO ¥D¡j \033[31;47m (h)\033[30m»¡©ú " + "\033[31m(q/¡ö)\033[30mÂ÷¶} \033[31m(n)\033[30m·s¼W¤å³¹ " + "\033[31m(g)\033[30m·s¼W¥Ø¿ý \033[31m(e)\033[30m½s¿èÀÉ®× \033[m" : + "\033[34;46m ¡i¥\\¯àÁä¡j \033[31;47m (h)\033[30m»¡©ú " + "\033[31m(q/¡ö)\033[30mÂ÷¶} \033[31m(k¡ôj¡õ)\033[30m²¾°Ê´å¼Ð " + "\033[31m(enter/¡÷)\033[30mŪ¨ú¸ê®Æ \033[m"); +} + +static FILE *go_cmd(item_t *node, int *sock) { + struct sockaddr_in sin; + struct hostent *host; + char *site; + FILE *fp; + + *sock = socket(AF_INET, SOCK_STREAM, 0); + + if(*sock < 0) { + syslog(LOG_ERR, "socket(): %m"); + return NULL; + } + memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(node->X.G.port); + + host = gethostbyname(site = node->X.G.server); + if(host == NULL) + sin.sin_addr.s_addr = inet_addr(site); + else + memcpy(&sin.sin_addr.s_addr, host->h_addr, host->h_length); + + if(connect(*sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + syslog(LOG_ERR, "connect(): %m"); + return NULL; + } + fp = fdopen(*sock, "r+"); + if(fp != NULL) { + setbuf(fp, (char *) 0); + fprintf(fp, "%s\r\n", node->X.G.path); + fflush(fp); + } else + close(*sock); + return fp; +} + +static char *nextfield(char *data, char *field) { + register int ch; + + while((ch = *data)) { + data++; + if((ch == '\t') || (ch == '\r' && *data == '\n')) + break; + *field++ = ch; + } + *field = '\0'; + return data; +} + +extern char *str_author1; + +static FILE* my_open(char* path) { + FILE* ans = 0; + char buf[80]; + struct stat st; + time_t now = time(0); + + if(stat(path, &st) == 0 && st.st_mtime < now - 3600 * 24 * 7) { + return fopen(path, "w"); + } + + if((ans = fopen(path, "r+"))) { + fclose(ans); + return 0; + /* + return directly due to currutmp->pager > 1 mode (real copy) + */ + fgets(buf, 80, ans); + if(!strncmp(buf, str_author1, strlen(str_author1)) || + *buf == '0' || *buf == '1') { + fclose(ans); + return 0; + } + + rewind(ans); + } else + ans = fopen(path, "w"); + return ans; +} + +static jmp_buf jbuf; + +static void isig(int sig) { + longjmp(jbuf, 1); +} + +#define PROXY_HOME "proxy/" +extern userec_t cuser; +extern userinfo_t *currutmp; + +static void go_proxy(char* fpath, item_t *node, int update) { + char *ptr, *str, *server; + int ch; + static FILE *fo; + + strcpy(fpath, PROXY_HOME); + ptr = fpath + sizeof(PROXY_HOME) - 1; + str = server = node->X.G.server; + while((ch = *str)) { + str++; + if(ch == '.') { + if(!strcmp(str, "edu.tw")) + break; + } else if(ch >= 'A' && ch <= 'Z') { + ch |= 0x20; + } + *ptr++ = ch; + } + *ptr = '\0'; + mkdir(fpath, 0755); + + *ptr++ = '/'; + str = node->X.G.path; + while((ch = *str)) { + str++; + if(ch == '/') { + ch = '.'; + } + *ptr++ = ch; + } + *ptr = '\0'; + + /* expire proxy data */ + + if((fo = update ? fopen(fpath, "w") : my_open(fpath))) { + FILE *fp; + char buf[512]; + int sock; + + if(fo == NULL) + return; + + outmsg("¡¹ «Ø¥ß proxy ¸ê®Æ³s½u¤¤ ... "); + refresh(); + + sock = -1; + if(setjmp(jbuf)) { + if(sock != -1) + close(sock); + fseek(fo, 0, SEEK_SET); + fwrite("", 0, 0, fo); + fclose(fo); + alarm(0); + return; + } + + signal(SIGALRM, isig); + alarm(5); + fp = go_cmd(node, &sock); + alarm(0); + + str = node->title; + ch = str[1]; + if(ch == (char) 0xbc && + !(HAS_PERM(PERM_SYSOP) && currutmp->pager > 1)) { + time_t now; + + time(&now); + fprintf(fo, "§@ªÌ: %s (³s½uºëµØ°Ï)\n¼ÐÃD: %s\n®É¶¡: %s\n", + server, str + 3, ctime(&now) + ); + } + + while(fgets(buf, 511, fp)) { + if(!strcmp(buf, ".\r\n")) + break; + if((ptr = strstr(buf, "\r\n"))) + strcpy(ptr, "\n"); + fputs(buf, fo); + } + fclose(fo); + fclose(fp); + } +} + +static void g_additem(gmenu_t *pm, item_t *myitem) { + if(pm->num < MAX_ITEMS) { + item_t *newitem = (item_t *)malloc(sizeof(item_t)); + + memcpy(newitem, myitem, sizeof(item_t)); + pm->item[(pm->num)++] = newitem; + } +} + +static void go_menu(gmenu_t *pm, item_t *node, int update) { + FILE *fp; + char buf[512], *ptr, *title; + item_t item; + int ch; + + go_proxy(buf, node, update); + pm->num = 0; + if((fp = fopen(buf, "r"))) { + title = item.title; + while(fgets(buf, 511, fp)) { + ptr = buf; + ch = *ptr++; + if(ch != '0' && ch != '1') + continue; + + strcpy(title, "¡¼ "); + if(ch == '1') + title[1] = (char) 0xbd; + + ptr = nextfield(ptr, title + 3); + if(!*ptr) + continue; + title[sizeof(item.title) - 1] = '\0'; + + ptr = nextfield(ptr, item.X.G.path); + if(!*ptr) + continue; + + ptr = nextfield(ptr, item.X.G.server); + if(!*ptr) + continue; + + nextfield(ptr, buf); + item.X.G.port = atoi(buf); + + g_additem(pm, &item); + } + fclose(fp); + } +} + +static int g_searchtitle(gmenu_t* pm, int rev) { + static char search_str[30] = ""; + int pos; + + if(getdata(b_lines - 1, 1,"[·j´M]ÃöÁä¦r:", search_str, 40, DOECHO)) + if(!*search_str) + return pm->now; + + str_lower(search_str, search_str); + + rev = rev ? -1 : 1; + pos = pm->now; + do { + pos += rev; + if(pos == pm->num) + pos = 0; + else if(pos < 0) + pos = pm->num - 1; + if(strstr_lower(pm->item[pos]->title, search_str)) + return pos; + } while(pos != pm->now); + return pm->now; +} + +static void g_showhelp() { + clear(); + outs("\033[36m¡i " BBSNAME "³s½uºëµØ°Ï¨Ï¥Î»¡©ú ¡j\033[m\n\n" + "[¡ö][q] Â÷¶}¨ì¤W¤@¼h¥Ø¿ý\n" + "[¡ô][k] ¤W¤@ӿﶵ\n" + "[¡õ][j] ¤U¤@ӿﶵ\n" + "[¡÷][r][enter] ¶i¤J¥Ø¿ý¡þŪ¨ú¤å³¹\n" + "[b][PgUp] ¤W¶¿ï³æ\n" + "[^F][PgDn][Spc] ¤U¶¿ï³æ\n" + "[##] ²¾¨ì¸Ó¿ï¶µ\n" + "[^S] ±N¤å³¹¦s¨ì«H½c\n" + "[R] §ó·s¸ê®Æ\n" + "[N] ¬d¸ßÀɦW\n" + "[c][C][^C] «þ¨©¤å³¹/¨Ã¸õ¦Ü¤W¦¸¶K¤å³¹ªº¦a¤è/" + "ª½±µ¶K¨ì¤W¦¸¶Kªº¦a¤è\n"); + pressanykey(); +} + +#define PATHLEN 256 + +static char paste_fname[200]; +extern time_t paste_time; +extern char paste_path[]; +extern char paste_title[]; +extern int paste_level; + +static void load_paste() { + struct stat st; + FILE *fp; + + if(!*paste_fname) + setuserfile(paste_fname, "paste_path"); + if(stat(paste_fname, &st) == 0 && st.st_mtime > paste_time && + (fp = fopen(paste_fname, "r"))) { + int i; + fgets(paste_path, PATHLEN, fp); + i = strlen(paste_path) - 1; + if(paste_path[i] == '\n') + paste_path[i] = 0; + fgets(paste_title, STRLEN, fp); + i = strlen(paste_title) - 1; + if(paste_title[i] == '\n') + paste_title[i] = 0; + fscanf(fp, "%d", &paste_level); + paste_time = st.st_mtime; + fclose(fp); + } +} + +static char copyfile[PATHLEN]; +static char copytitle[TTLEN+1]; +static char copyowner[IDLEN + 2]; + +void a_copyitem(char* fpath, char* title, char* owner, int mode) { + strcpy(copyfile, fpath); + strcpy(copytitle, title); + if(owner) + strcpy(copyowner, owner); + else + *copyowner = 0; + if(mode) { + outmsg("Àɮ׼аO§¹¦¨¡C[ª`·N] «þ¨©«á¤~¯à§R°£ì¤å!"); + igetch(); + } +} + +#define FHSZ sizeof(fileheader_t) + +static void a_loadname(menu_t *pm) { + char buf[PATHLEN]; + int len; + + setadir(buf, pm->path); + len = get_records(buf, pm->header, FHSZ, pm->page+1, p_lines); + if(len < p_lines) + bzero(&pm->header[len], FHSZ*(p_lines-len)); +} + +static void a_timestamp(char *buf, time_t *time) { + struct tm *pt = localtime(time); + + sprintf(buf, "%02d/%02d/%02d", pt->tm_mon + 1, pt->tm_mday, (pt->tm_year + 1900) % 100); +} + +static void a_showmenu(menu_t *pm) { + char *title, *editor; + int n; + fileheader_t *item; + char buf[PATHLEN]; + time_t dtime; + + showtitle("ºëµØ¤å³¹", pm->mtitle); + prints(" \033[1;36m½s¸¹ ¼Ð ÃD%56s\033[0m", + "½s ¿ï ¤é ´Á"); + + if(pm->num) { + setadir(buf, pm->path); + a_loadname(pm); + for(n = 0; n < p_lines && pm->page + n < pm->num; n++) { + item = &pm->header[n]; + title = item->title; + editor = item->owner; + /* Ptt §â®É¶¡§ï¬°¨úÀɮ׮ɶ¡ + dtime = atoi(&item->filename[2]); + */ + sprintf(buf,"%s/%s",pm->path,item->filename); + dtime = dasht(buf); + a_timestamp(buf, &dtime); + prints("\n%6d%c %-47.46s%-13s[%s]", pm->page+n+1, + (item->filemode & FILE_BM) ?'X': + (item->filemode & FILE_HIDE) ?')':'.', + title, editor, + buf); + } + } else + outs("\n ¡mºëµØ°Ï¡n©|¦b§l¨ú¤Ñ¦a¶¡ªº¤é¤ëºëµØ¤¤... :)"); + + move(b_lines, 1); + outs(pm->level ? + "\033[34;46m ¡iªO ¥D¡j \033[31;47m (h)\033[30m»¡©ú " + "\033[31m(q/¡ö)\033[30mÂ÷¶} \033[31m(n)\033[30m·s¼W¤å³¹ " + "\033[31m(g)\033[30m·s¼W¥Ø¿ý \033[31m(e)\033[30m½s¿èÀÉ®× \033[m" : + "\033[34;46m ¡i¥\\¯àÁä¡j \033[31;47m (h)\033[30m»¡©ú " + "\033[31m(q/¡ö)\033[30mÂ÷¶} \033[31m(k¡ôj¡õ)\033[30m²¾°Ê´å¼Ð " + "\033[31m(enter/¡÷)\033[30mŪ¨ú¸ê®Æ \033[m"); +} + +static int a_searchtitle(menu_t *pm, int rev) { + static char search_str[40] = ""; + int pos; + + getdata(b_lines - 1, 1, "[·j´M]ÃöÁä¦r:", search_str, 40, DOECHO); + + if(!*search_str) + return pm->now; + + str_lower(search_str, search_str); + + rev = rev ? -1 : 1; + pos = pm->now; + do { + pos += rev; + if(pos == pm->num) + pos = 0; + else if(pos < 0) + pos = pm->num - 1; + if(pos < pm->page || pos >= pm->page + p_lines) { + pm->page = pos - pos % p_lines; + a_loadname(pm); + } + if(strstr_lower(pm->header[pos - pm->page].title, search_str)) + return pos; + } while(pos != pm->now); + return pm->now; +} + +enum {NOBODY, MANAGER, SYSOP}; + +static void a_showhelp(int level) { + clear(); + outs("\033[36m¡i " BBSNAME "¤½§GÄæ¨Ï¥Î»¡©ú ¡j\033[m\n\n" + "[¡ö][q] Â÷¶}¨ì¤W¤@¼h¥Ø¿ý\n" + "[¡ô][k] ¤W¤@ӿﶵ\n" + "[¡õ][j] ¤U¤@ӿﶵ\n" + "[¡÷][r][enter] ¶i¤J¥Ø¿ý¡þŪ¨ú¤å³¹\n" + "[^B][PgUp] ¤W¶¿ï³æ\n" + "[^F][PgDn][Spc] ¤U¶¿ï³æ\n" + "[##] ²¾¨ì¸Ó¿ï¶µ\n" + "[F][U] ±N¤å³¹±H¦^ Internet ¶l½c/" + "±N¤å³¹ uuencode «á±H¦^¶l½c\n"); + if(level >= MANAGER) { + outs("\n\033[36m¡i ªO¥D±M¥ÎÁä ¡j\033[m\n" + "[H] ¤Á´«¬° ¤½¶}/·|û/ª©¥D ¤~¯à¾\\Ū\n" + "[n/g/G] ¦¬¿ýºëµØ¤å³¹/¶}ÅP¥Ø¿ý/«Ø¥ß³s½u\n" + "[m/d/D] ²¾°Ê/§R°£¤å³¹/§R°£¤@Ó½d³òªº¤å³¹\n" + "[f/T/e] ½s¿è¼ÐÃD²Å¸¹/קï¤å³¹¼ÐÃD/¤º®e\n" + "[c/p/a] «þ¨©/Ö߶K/ªþ¥[¤å³¹\n" + "[^P/^A] Ö߶K/ªþ¥[¤w¥Î't'¼Ð°O¤å³¹\n"); + } + + if(level >= SYSOP) { + outs("\n\033[36m¡i ¯¸ªø±M¥ÎÁä ¡j\033[m\n" + "[l] «Ø symbolic link\n" + "[N] ¬d¸ßÀɦW\n"); + } + pressanykey(); +} + +static int AnnounceSelect() { + static char xboard[20]; + char buf[20]; + char fpath[256]; + boardheader_t *bp; + + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + make_blist(); + namecomplete("¿ï¾ÜºëµØ°Ï¬ÝªO¡G", buf); + if(*buf) + strcpy(xboard, buf); + if(*xboard && (bp = getbcache(getbnum(xboard)))) { + setapath(fpath, xboard); + setutmpmode(ANNOUNCE); + a_menu(xboard, fpath, + (HAS_PERM(PERM_ALLBOARD) || + (HAS_PERM(PERM_BM) && is_BM(bp->BM))) ? 1 : 0); + } + return FULLUPDATE; +} + +extern char vetitle[]; + +void gem(char* maintitle, item_t* path, int update) { + gmenu_t me; + int ch; + char fname[PATHLEN]; + + strncpy(me.mtitle, maintitle, 40); + me.mtitle[40] = 0; + go_menu(&me, path, update); + + /* ºëµØ°Ï-tree ¤¤³¡¥÷µ²ºcÄÝ©ó cuser ==> BM */ + + me.level = 0; + me.page = 9999; + me.now = 0; + for(;;) { + if(me.now >= me.num && me.num > 0) + me.now = me.num - 1; + else if(me.now < 0) + me.now = 0; + + if(me.now < me.page || me.now >= me.page + p_lines) { + me.page = me.now - (me.now % p_lines); + g_showmenu(&me); + } + ch = cursor_key(2 + me.now - me.page, 0); + if(ch == 'q' || ch == 'Q' || ch == KEY_LEFT) + break; + + if(ch >= '0' && ch <= '9') { + if((ch = search_num(ch, me.num)) != -1) + me.now = ch; + me.page = 9999; + continue; + } + + switch(ch) { + case KEY_UP: + case 'k': + if(--me.now < 0) + me.now = me.num - 1; + break; + case KEY_DOWN: + case 'j': + if(++me.now >= me.num) + me.now = 0; + break; + case KEY_PGUP: + case 'b': + if(me.now >= p_lines) + me.now -= p_lines; + else if(me.now > 0) + me.now = 0; + else + me.now = me.num - 1; + break; + case ' ': + case KEY_PGDN: + case Ctrl('F'): + if(me.now < me.num - p_lines) + me.now += p_lines; + else if(me.now < me.num - 1) + me.now = me.num - 1; + else + me.now = 0; + break; + case 'h': + g_showhelp(); + me.page = 9999; + break; + case '?': + case '/': + me.now = g_searchtitle(&me, ch == '?'); + me.page = 9999; + break; + case 'N': + if(HAS_PERM(PERM_SYSOP)) { + go_proxy(fname, me.item[me.now], 0); + move(b_lines - 1, 0); + outs(fname); + pressanykey(); + me.page = 9999; + } + break; + case 'c': + case 'C': + case Ctrl('C'): + if(me.now < me.num) { + item_t *node = me.item[me.now]; + char *title = node->title; + int mode = title[1]; + + load_paste(); + if(mode == (char) 0xbc || ch == Ctrl('C')) { + if(mode == (char) 0xbc) + go_proxy(fname, node, 0); + if(ch == Ctrl('C') && *paste_path && paste_level) { + char newpath[PATHLEN]; + fileheader_t item; + + strcpy(newpath, paste_path); + if(mode == (char) 0xbc) { + stampfile(newpath, &item); + unlink(newpath); + Link(fname, newpath); + } else + stampdir(newpath, &item); + strcpy(item.owner, cuser.userid); + sprintf(item.title, "%s%.72s", + (currutmp->pager > 1) ? "" : + (mode == (char) 0xbc) ? "¡º " : "¡» ", + title + 3); + strcpy(strrchr(newpath, '/') + 1, ".DIR"); + append_record(newpath, &item, FHSZ); + if(++me.now >= me.num) + me.now = 0; + break; + } + if(mode == (char) 0xbc) { + a_copyitem(fname, + title + ((currutmp->pager > 1) ? 3 : 0), + 0, 1); + if(ch == 'C' && *paste_path) { + setutmpmode(ANNOUNCE); + a_menu(paste_title, paste_path, paste_level); + } + me.page = 9999; + } else + bell(); + } + } + break; + case Ctrl('B'): + m_read(); + me.page = 9999; + break; + case Ctrl('I'): + t_idle(); + me.page = 9999; + break; + case 's': + AnnounceSelect(); + me.page = 9999; + break; + case '\n': + case '\r': + case KEY_RIGHT: + case 'r': + case 'R': + if(me.now < me.num) { + item_t *node = me.item[me.now]; + char *title = node->title; + int mode = title[1]; + int update = (ch == 'R') ? 1 : 0; + + title += 3; + + if(mode == (char) 0xbc) { + int more_result; + + go_proxy(fname, node, update); + strcpy(vetitle, title); + while((more_result = more(fname, YEA))) { + if(more_result == 1) { + if(--me.now < 0) { + me.now = 0; + break; + } + } else if(more_result == 3) { + if(++me.now >= me.num) { + me.now = me.num - 1; + break; + } + } else + break; + node = me.item[me.now]; + if(node->title[1] != (char) 0xbc) + break; + go_proxy(fname, node, update); + strcpy(vetitle, title); + } + } else if(mode == (char) 0xbd) { + gem(title, node, update); + } + me.page = 9999; + } + break; + } + } + for(ch = 0; ch < me.num; ch++) + free(me.item[ch]); +} + +extern char *msg_fwd_ok; +extern char *msg_fwd_err1; +extern char *msg_fwd_err2; + +static void a_forward(char *path, fileheader_t *pitem, int mode) { + fileheader_t fhdr; + + strcpy(fhdr.filename, pitem->filename); + strcpy(fhdr.title, pitem->title); + switch(doforward(path, &fhdr, mode)) { + case 0: + outmsg(msg_fwd_ok); + break; + case -1: + outmsg(msg_fwd_err1); + break; + case -2: + outmsg(msg_fwd_err2); + break; + } +} + +static void a_additem(menu_t *pm, fileheader_t *myheader) { + char buf[PATHLEN]; + + setadir(buf, pm->path); + if(append_record(buf, myheader, FHSZ) == -1) + return; + pm->now = pm->num++; + + if(pm->now >= pm->page + p_lines) { + pm->page = pm->now - ((pm->page == 10000 && pm->now > p_lines / 2) ? + (p_lines / 2) : (pm->now % p_lines)); + } + + /*Ptt*/ + strcpy(pm->header[pm->now - pm->page].filename, myheader->filename); +} + +#define ADDITEM 0 +#define ADDGROUP 1 +#define ADDGOPHER 2 +#define ADDLINK 3 +extern char currboard[]; + +static void a_newitem(menu_t *pm, int mode) { + static char *mesg[4] = { + "[·s¼W¤å³¹] ½Ð¿é¤J¼ÐÃD¡G", /* ADDITEM */ + "[·s¼W¥Ø¿ý] ½Ð¿é¤J¼ÐÃD¡G", /* ADDGROUP */ + "[·s¼W³s½u] ½Ð¿é¤J¼ÐÃD¡G", /* ADDGOPHER */ + "½Ð¿é¤J¼ÐÃD¡G" /* ADDLINK */ + }; + + char fpath[PATHLEN], buf[PATHLEN], lpath[PATHLEN]; + fileheader_t item; + int d; + + strcpy(fpath, pm->path); + + switch(mode) { + case ADDITEM: + stampfile(fpath, &item); + strcpy(item.title, "¡º "); /* A1BA */ + break; + + case ADDGROUP: + stampdir(fpath, &item); + strcpy(item.title, "¡» "); /* A1BB */ + break; + case ADDGOPHER: + bzero(&item, sizeof(item)); + strcpy(item.title, "¡ó "); /* A1BB */ + if(!getdata(b_lines - 2, 1, "¿é¤JURL¦ì§}¡G", + item.filename+2,61, DOECHO)) + return; + break; + case ADDLINK: + stamplink(fpath, &item); + if (!getdata(b_lines - 2, 1, "·s¼W³s½u¡G", buf, 61, DOECHO)) + return; + if(invalid_pname(buf)) { + unlink(fpath); + outs("¥Øªº¦a¸ô®|¤£¦Xªk¡I"); + igetch(); + return; + } + + item.title[0] = 0; + for(d = 0; d <= 3; d++) { + switch(d) { + case 0: + sprintf(lpath, "%s%s%s/%s", + BBSHOME, "/man/boards/",currboard , buf); + break; + case 1: + sprintf(lpath, "%s%s%s", + BBSHOME, "/man/boards/" , buf); + break; + case 2: + sprintf(lpath, "%s%s%s", + BBSHOME, "/" , buf); + break; + case 3: + sprintf(lpath, "%s%s%s", + BBSHOME, "/etc/" , buf); + break; + } + if(dashf(lpath)) { + strcpy(item.title, "¡¸ "); /* A1B3 */ + break; + } else if (dashd(lpath)) { + strcpy(item.title, "¡¹ "); /* A1B4 */ + break; + } + if(!HAS_PERM(PERM_BBSADM) && d==1) + break; + } + + if(!item.title[0]) { + unlink(fpath); + outs("¥Øªº¦a¸ô®|¤£¦Xªk¡I"); + igetch(); + return; + } + } + + if(!getdata(b_lines - 1, 1, mesg[mode], &item.title[3], 55, DOECHO)) { + if(mode == ADDGROUP) + rmdir(fpath); + else if(mode != ADDGOPHER) + unlink(fpath); + return; + } + + switch(mode) { + case ADDITEM: + if(vedit(fpath, 0, NULL) == -1) { + unlink(fpath); + pressanykey(); + return; + } + break; + case ADDLINK: + unlink(fpath); + if(symlink(lpath, fpath) == -1) { + outs("µLªk«Ø¥ß symbolic link"); + igetch(); + return; + } + break; + case ADDGOPHER: + strcpy(item.date, "70"); + strncpy(item.filename, "H.",2); + break; + } + + strcpy(item.owner, cuser.userid); + a_additem(pm, &item); +} + +static void a_pasteitem(menu_t *pm, int mode) { + char newpath[PATHLEN]; + char buf[PATHLEN]; + char ans[2]; + int i; + fileheader_t item; + + move(b_lines - 1, 1); + if(copyfile[0]) { + if(dashd(copyfile)) { + for(i = 0; copyfile[i] && copyfile[i] == pm->path[i]; i++); + if(!copyfile[i]) { + outs("±N¥Ø¿ý«þ¶i¦Û¤vªº¤l¥Ø¿ý¤¤¡A·|³y¦¨µL½a°j°é¡I"); + igetch(); + return; + } + } + if(mode) { + sprintf(buf, "½T©wn«þ¨©[%s]¶Ü(Y/N)¡H[N] ", copytitle); + getdata(b_lines - 1, 1, buf, ans, 3, LCECHO); + } else + ans[0]='y'; + if(ans[0] == 'y') { + strcpy(newpath, pm->path); + + if(*copyowner) { + char* fname = strrchr(copyfile, '/'); + + if(fname) + strcat(newpath, fname); + else + return; + if(access(pm->path, X_OK | R_OK | W_OK)) + mkdir(pm->path, 0755); + memset(&item, 0, sizeof(fileheader_t)); + strcpy(item.filename, fname + 1); + memcpy(copytitle, "¡·", 2); + if(HAS_PERM(PERM_BBSADM)) + Link(copyfile, newpath); + else { + sprintf(buf, "/bin/cp %s %s", copyfile, newpath); + system(buf); + } + } else if(dashf(copyfile)) { + stampfile(newpath, &item); + memcpy(copytitle, "¡º", 2); + sprintf(buf, "/bin/cp %s %s", copyfile, newpath); + } else if(dashd(copyfile)) { + stampdir(newpath, &item); + memcpy(copytitle, "¡»", 2); + sprintf(buf, "/bin/cp -r %s/* %s/.D* %s", copyfile, copyfile, + newpath); + } else { + outs("µLªk«þ¨©¡I"); + igetch(); + return; + } + strcpy(item.owner, *copyowner ? copyowner : cuser.userid); + strcpy(item.title, copytitle); + if(!*copyowner) + system(buf); + a_additem(pm, &item); + copyfile[0] = '\0'; + } + } else { + outs("½Ð¥ý°õ¦æ copy ©R¥O«á¦A paste"); + igetch(); + } +} + +static void a_appenditem(menu_t *pm, int isask) { + char fname[PATHLEN]; + char buf[ANSILINELEN]; + char ans[2] = "y"; + FILE *fp, *fin; + + move(b_lines - 1, 1); + if(copyfile[0]) { + if(dashf(copyfile)) { + sprintf(fname, "%s/%s", pm->path, + pm->header[pm->now-pm->page].filename); + if(dashf(fname)) { + if(isask) { + sprintf(buf, "½T©wn±N[%s]ªþ¥[©ó¦¹¶Ü(Y/N)¡H[N] ", + copytitle); + getdata(b_lines - 2, 1, buf, ans, 3, LCECHO); + } + if(ans[0] == 'y') { + if((fp = fopen(fname, "a+"))) { + if((fin = fopen(copyfile, "r"))) { + memset(buf, '-', 74); + buf[74] = '\0'; + fprintf(fp, "\n> %s <\n\n", buf); + if(isask) + getdata(b_lines - 1, 1, + "¬O§_¦¬¿ýñ¦WÀɳ¡¥÷(Y/N)¡H[Y] ", + ans, 3, LCECHO); + while(fgets(buf, sizeof(buf), fin)) { + if((ans[0] == 'n' ) && + !strcmp(buf, "--\n")) + break; + fputs(buf, fp); + } + fclose(fin); + copyfile[0] = '\0'; + } + fclose(fp); + } + } + } else { + outs("Àɮפ£±oªþ¥[©ó¦¹¡I"); + igetch(); + } + } else { + outs("¤£±oªþ¥[¾ãӥؿý©óÀɮ׫á¡I"); + igetch(); + } + } else { + outs("½Ð¥ý°õ¦æ copy ©R¥O«á¦A append"); + igetch(); + } +} + +static int a_pastetagpost(menu_t *pm, int mode) { + extern int TagNum; + extern void EnumTagFhdr(); + extern void UnTagger(int locus); + fileheader_t fhdr; + int ans = 0, ent=0, tagnum; + char title[TTLEN + 1]= "¡º "; + char dirname[200],buf[200]; + + setbdir(dirname, currboard); + tagnum = TagNum; + + if (!tagnum) return ans; + + while (tagnum--) + { + EnumTagFhdr (&fhdr, dirname, ent++); + setbfile (buf, currboard, fhdr.filename); + + if (dashf (buf)) + { + strncpy(title+3, fhdr.title, TTLEN-3); + title[TTLEN] = '\0'; + a_copyitem(buf, title, 0, 0); + if(mode) + { + mode--; + a_pasteitem(pm,0); + } + else a_appenditem(pm, 0); + ++ans; + UnTagger (tagnum); + } + + }; + + return ans; +} + +static void a_moveitem(menu_t *pm) { + fileheader_t *tmp; + char newnum[4]; + int num, max, min; + char buf[PATHLEN]; + int fail; + + sprintf(buf, "½Ð¿é¤J²Ä %d ¿ï¶µªº·s¦¸§Ç¡G", pm->now + 1); + if(!getdata(b_lines - 1, 1, buf, newnum, 6, DOECHO)) + return; + num = (newnum[0] == '$') ? 9999 : atoi(newnum) - 1; + if(num >= pm->num) + num = pm->num - 1; + else if(num < 0) + num = 0; + setadir(buf, pm->path); + min = num < pm->now ? num : pm->now; + max = num > pm->now ? num : pm->now; + tmp = (fileheader_t *) calloc(max + 1, FHSZ); + + fail = 0; + if(get_records(buf, tmp, FHSZ, 1, min) != min) + fail = 1; + if(num > pm->now) { + if(get_records(buf, &tmp[min], FHSZ, pm->now+2, max-min) != max-min) + fail = 1; + if(get_records(buf, &tmp[max], FHSZ, pm->now+1, 1) != 1) + fail = 1; + } else { + if(get_records(buf, &tmp[min], FHSZ, pm->now+1, 1) != 1) + fail = 1; + if(get_records(buf, &tmp[min+1], FHSZ, num+1, max-min) != max-min) + fail = 1; + } + if(!fail) + substitute_record(buf, tmp, FHSZ * (max + 1), 1); + pm->now = num; + free(tmp); +} + +static void a_delrange(menu_t *pm) { + char fname[256]; + + sprintf(fname,"%s/.DIR",pm->path); + del_range(0, NULL, fname); + pm->num = get_num_records(fname, FHSZ); +} + +static void a_delete(menu_t *pm) { + char fpath[PATHLEN], buf[PATHLEN], cmd[PATHLEN]; + char ans[4]; + fileheader_t backup; + + sprintf(fpath, "%s/%s", pm->path, pm->header[pm->now - pm->page].filename); + setadir(buf, pm->path); + + if(pm->header[pm->now - pm->page].filename[0] == 'H' && + pm->header[pm->now - pm->page].filename[1] == '.') { + getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹ºëµØ°Ï³s½u¶Ü(Y/N)¡H[N] ", + ans, 3, LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + } else if (dashl(fpath)) { + getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹ symbolic link ¶Ü(Y/N)¡H[N] ", + ans, 3, LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + unlink(fpath); + } else if(dashf(fpath)) { + getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹Àɮ׶Ü(Y/N)¡H[N] ", ans, 3, + LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + + setbpath(buf, "deleted"); + stampfile(buf, &backup); + strcpy(backup.owner, cuser.userid); + strcpy(backup.title,pm->header[pm->now - pm->page].title + 2); + backup.savemode = 'D'; + + sprintf(cmd, "mv -f %s %s", fpath,buf); + system(cmd); + setbdir(buf, "deleted"); + append_record(buf, &backup, sizeof(backup)); + } else if (dashd(fpath)) { + getdata(b_lines - 1, 1, "±z½T©wn§R°£¾ãӥؿý¶Ü(Y/N)¡H[N] ", ans, 3, + LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + + setapath(buf, "deleted"); + stampdir(buf, &backup); + + sprintf(cmd, "rm -rf %s;/bin/mv -f %s %s",buf,fpath,buf); + system(cmd); + + strcpy(backup.owner, cuser.userid); + strcpy(backup.title,pm->header[pm->now - pm->page].title +2); + setapath(buf, "deleted"); + setadir(buf,buf); + append_record(buf, &backup, sizeof(backup)); + } else { /* Ptt ·l·´ªº¶µ¥Ø */ + getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹·l·´ªº¶µ¥Ø¶Ü(Y/N)¡H[N] ", + ans, 3, LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + } + pm->num--; +} + +static void a_newtitle(menu_t *pm) { + char buf[PATHLEN]; + fileheader_t item; + + memcpy(&item, &pm->header[pm->now - pm->page], FHSZ); + strcpy(buf,item.title + 3); + if(getdata_buf(b_lines - 1, 1, "·s¼ÐÃD¡G", buf, 60, DOECHO)) { + strcpy(item.title + 3, buf); + setadir(buf, pm->path); + substitute_record(buf, &item, FHSZ, pm->now + 1); + } +} +static void a_hideitem(menu_t *pm) { + fileheader_t *item=&pm->header[pm->now - pm->page]; + char buf[PATHLEN]; + if(item->filemode&FILE_BM) + { + item->filemode &= ~FILE_BM; + item->filemode &= ~FILE_HIDE; + } + else if(item->filemode&FILE_HIDE) + item->filemode |= FILE_BM; + else item->filemode |= FILE_HIDE; + setadir(buf, pm->path); + substitute_record(buf, item, FHSZ, pm->now + 1); +} +static void a_editsign(menu_t *pm) { + char buf[PATHLEN]; + fileheader_t item; + + memcpy(&item, &pm->header[pm->now - pm->page], FHSZ); + sprintf(buf, "%c%c", item.title[0], item.title[1]); + if(getdata_buf(b_lines - 1, 1, "²Å¸¹", buf, 5, DOECHO)) { + item.title[0] = buf[0] ? buf[0] : ' '; + item.title[1] = buf[1] ? buf[1] : ' '; + item.title[2] = buf[2] ? buf[2] : ' '; + setadir(buf, pm->path); + substitute_record(buf, &item, FHSZ, pm->now + 1); + } +} + +static void a_showname(menu_t *pm) { + char buf[PATHLEN]; + int len; + int i; + int sym; + + move(b_lines - 1, 1); + sprintf(buf, "%s/%s", pm->path, pm->header[pm->now - pm->page].filename); + if(dashl(buf)) { + prints("¦¹ symbolic link ¦WºÙ¬° %s\n", + pm->header[pm->now - pm->page].filename); + if((len = readlink(buf, buf, PATHLEN-1)) >= 0) { + buf[len] = '\0'; + for(i = 0; BBSHOME[i] && buf[i] == BBSHOME[i]; i++); + if(!BBSHOME[i] && buf[i] == '/') { + if(HAS_PERM(PERM_BBSADM)) + sym = 1; + else { + sym = 0; + for(i++; BBSHOME "/man"[i] && buf[i] == BBSHOME "/man"[i]; + i++); + if(!BBSHOME "/man"[i] && buf[i] == '/') + sym = 1; + } + if(sym) { + pressanykey(); + move(b_lines - 1, 1); + prints("¦¹ symbolic link «ü¦V %s\n", &buf[i+1]); + } + } + } + } else if(dashf(buf)) + prints("¦¹¤å³¹¦WºÙ¬° %s", pm->header[pm->now - pm->page].filename); + else if(dashd(buf)) + prints("¦¹¥Ø¿ý¦WºÙ¬° %s", pm->header[pm->now - pm->page].filename); + else + outs("¦¹¶µ¥Ø¤w·l·´, «Øij±N¨ä§R°£¡I"); + pressanykey(); +} + +static char *a_title; + +static void atitle() { + showtitle("ºëµØ¤å³¹", a_title); + outs("[¡ö]Â÷¶} [¡÷]¾\\Ū [^P]µoªí¤å³¹ [b]³Æ§Ñ¿ý [d]§R°£ [q]ºëµØ°Ï " + "[TAB]¤åºK [h]elp\n\033[7m ½s¸¹ ¤é ´Á §@ ªÌ " + "¤å ³¹ ¼Ð ÃD\033[m"); +} + +extern char currtitle[]; + +char trans_buffer[256]; +extern char quote_file[]; +extern unsigned int currstat; + +static int isvisible_man(menu_t *me) +{ + fileheader_t *fhdr = &me->header[me->now-me->page]; + if( me->level<MANAGER && ((fhdr->filemode & FILE_BM) || + ((fhdr->filemode & FILE_HIDE) && + hbflcheck(currbid, currutmp->uid)))) + return 0; + return 1; +} +int a_menu(char *maintitle, char *path, int lastlevel) { + static char Fexit; + menu_t me; + char fname[PATHLEN]; + int ch, returnvalue = FULLUPDATE; + + trans_buffer[0] = 0; + + Fexit = 0; + me.header = (fileheader_t *)calloc(p_lines, FHSZ); + me.path = path; + strcpy(me.mtitle, maintitle); + setadir(fname, me.path); + me.num = get_num_records(fname, FHSZ); + + /* ºëµØ°Ï-tree ¤¤³¡¥÷µ²ºcÄÝ©ó cuser ==> BM */ + + if(!(me.level = lastlevel)) { + char *ptr; + + if((ptr = strrchr(me.mtitle, '['))) + me.level = is_BM(ptr + 1); + } + + me.page = 9999; + me.now = 0; + for(;;) { + if(me.now >= me.num) + me.now = me.num - 1; + if(me.now < 0) + me.now = 0; + + if(me.now < me.page || me.now >= me.page + p_lines) { + me.page = me.now - ((me.page == 10000 && me.now > p_lines / 2) ? + (p_lines / 2) : (me.now % p_lines)); + a_showmenu(&me); + } + + ch = cursor_key(2 + me.now - me.page, 0); + + if(ch == 'q' || ch == 'Q' || ch == KEY_LEFT) + break; + + if(ch >= '1' && ch <= '9') { + if((ch = search_num(ch, me.num)) != -1) + me.now = ch; + me.page = 10000; + continue; + } + + switch(ch) { + case KEY_UP: + case 'k': + if(--me.now < 0) + me.now = me.num - 1; + break; + + case KEY_DOWN: + case 'j': + if(++me.now >= me.num) + me.now = 0; + break; + + case KEY_PGUP: + case Ctrl('B'): + if(me.now >= p_lines) + me.now -= p_lines; + else if (me.now > 0) + me.now = 0; + else + me.now = me.num - 1; + break; + + case ' ': + case KEY_PGDN: + case Ctrl('F'): + if(me.now < me.num - p_lines) + me.now += p_lines; + else if(me.now < me.num - 1) + me.now = me.num - 1; + else + me.now = 0; + break; + + case '0': + me.now = 0; + break; + case '?': + case '/': + me.now = a_searchtitle(&me, ch == '?'); + me.page = 9999; + break; + case '$': + me.now = me.num -1; + break; + case 'h': + a_showhelp(me.level); + me.page = 9999; + break; + case Ctrl('C'): + cal(); + me.page = 9999; + break; + + case Ctrl('I'): + t_idle(); + me.page = 9999; + break; + + case 's': + AnnounceSelect(); + me.page = 9999; + break; + + case 'e': + case 'E': + sprintf(fname, "%s/%s", path, me.header[me.now-me.page].filename); + if(dashf(fname) && me.level >= MANAGER) { + *quote_file = 0; + if(vedit(fname, NA, NULL) != -1) { + char fpath[200]; + fileheader_t fhdr; + + strcpy(fpath, path); + stampfile(fpath, &fhdr); + unlink(fpath); + Rename(fname, fpath); + strcpy(me.header[me.now-me.page].filename, fhdr.filename); + strcpy(me.header[me.now-me.page].owner, cuser.userid); + setadir(fpath, path); + substitute_record(fpath, me.header+me.now-me.page, + sizeof(fhdr), me.now + 1); + } + me.page = 9999; + } + break; + + case 'c': + if(me.now < me.num) { + if(!isvisible_man(&me)) break; + sprintf(fname, "%s/%s", path, + me.header[me.now-me.page].filename); + a_copyitem(fname, me.header[me.now-me.page].title, 0, 1); + me.page = 9999; + break; + } + + case '\n': + case '\r': + case KEY_RIGHT: + case 'r': + if(me.now < me.num) { + fileheader_t *fhdr = &me.header[me.now-me.page]; + if(!isvisible_man(&me)) break; + sprintf(fname, "%s/%s", path, fhdr->filename); + if(*fhdr->filename == 'H' && fhdr->filename[1] == '.') { + item_t item; + strcpy(item.X.G.server, fhdr->filename + 2); + strcpy(item.X.G.path, "1/"); + item.X.G.port = 70; + gem(fhdr->title, &item, (ch == 'R') ? 1 : 0); + } else if (dashf(fname)) { + int more_result; + + while((more_result = more(fname, YEA))) { + /* Ptt ½d¥»ºëÆF plugin */ + if(currstat == EDITEXP || currstat == OSONG) { + char ans[4]; + + move(22, 0); + clrtoeol(); + getdata(22, 1, + currstat == EDITEXP ? + "n§â½d¨Ò Plugin ¨ì¤å³¹¶Ü?[y/N]": + "½T©wnÂI³oººq¶Ü?[y/N]", + ans, 3, LCECHO); + if(ans[0]=='y') { + strcpy(trans_buffer,fname); + Fexit = 1; + free(me.header); + if(currstat == OSONG){ + log_file(FN_USSONG,fhdr->title); + } + return FULLUPDATE; + } + } + if(more_result == 1) { + if(--me.now < 0) { + me.now = 0; + break; + } + } else if(more_result == 3) { + if(++me.now >= me.num) { + me.now = me.num - 1; + break; + } + } else + break; + if(!isvisible_man(&me)) break; + sprintf(fname, "%s/%s", path, + me.header[me.now-me.page].filename); + if(!dashf(fname)) + break; + } + } else if(dashd(fname)) { + a_menu(me.header[me.now-me.page].title, fname, me.level); + /* Ptt ±j¤O¸õ¥Xrecursive */ + if(Fexit) { + free(me.header); + return FULLUPDATE; + } + } + me.page = 9999; + } + break; + + case 'F': + case 'U': + sprintf(fname, "%s/%s", path, me.header[me.now-me.page].filename); + if(me.now < me.num && HAS_PERM(PERM_BASIC) && dashf(fname)) { + a_forward(path, &me.header[me.now-me.page], ch /*== 'U'*/); + /*By CharlieL*/ + } else + outmsg("µLªkÂà±H¦¹¶µ¥Ø"); + + me.page = 9999; + refresh(); + sleep(1); + break; + } + + if(me.level >= MANAGER) { + int page0 = me.page; + + switch(ch) { + case 'n': + a_newitem(&me, ADDITEM); + me.page = 9999; + break; + case 'g': + a_newitem(&me, ADDGROUP); + me.page = 9999; + break; + case 'G': + a_newitem(&me, ADDGOPHER); + me.page = 9999; + break; + case 'p': + a_pasteitem(&me,1); + me.page = 9999; + break; + case 'f': + a_editsign(&me); + me.page = 9999; + break; + case Ctrl('P'): + a_pastetagpost(&me, -1); + returnvalue = DIRCHANGED; + me.page = 9999; + break; + case Ctrl('A'): + a_pastetagpost(&me, 1); + returnvalue = DIRCHANGED; + me.page = 9999; + break; + case 'a': + a_appenditem(&me, 1); + me.page = 9999; + break; + default: + me.page = page0; + break; + } + + if(me.num) + switch(ch) { + case 'm': + a_moveitem(&me); + me.page = 9999; + break; + + case 'D': + /* Ptt me.page = -1;*/ + a_delrange(&me); + me.page = 9999; + break; + case 'd': + a_delete(&me); + me.page = 9999; + break; + case 'H': + a_hideitem(&me); + me.page = 9999; + break; + case 'T': + a_newtitle(&me); + me.page = 9999; + break; + } + } + + if(me.level == SYSOP) { + switch(ch) { + case 'l': + a_newitem(&me, ADDLINK); + me.page = 9999; + break; + case 'N': + a_showname(&me); + me.page = 9999; + break; + } + } + } + free(me.header); + return returnvalue; +} + +static char *mytitle = BBSNAME "§G§iÄæ"; + +int Announce() { + setutmpmode(ANNOUNCE); + a_menu(mytitle, "man", + ((HAS_PERM(PERM_SYSOP) || HAS_PERM(PERM_ANNOUNCE)) ? SYSOP : + NOBODY)); + return 0; +} diff --git a/mbbsd/args.c b/mbbsd/args.c new file mode 100644 index 00000000..4d1d6ceb --- /dev/null +++ b/mbbsd/args.c @@ -0,0 +1,62 @@ +/* $Id: args.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifdef HAVE_SETPROCTITLE + +void initsetproctitle(int argc, char **argv, char **envp) { +} + +#else + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ +extern char **environ; + +void initsetproctitle(int argc, char **argv, char **envp) { + register int i; + + /* Move the environment so setproctitle can use the space at + the top of memory. */ + for(i = 0; envp[i]; i++); + environ = malloc(sizeof(char *) * (i + 1)); + for(i = 0; envp[i]; i++) + environ[i] = strdup(envp[i]); + environ[i] = NULL; + + /* Save start and extent of argv for setproctitle. */ + Argv = argv; + if(i > 0) + LastArgv = envp[i - 1] + strlen(envp[i - 1]); + else + LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); +} + +static void do_setproctitle(const char *cmdline) { + char buf[256], *p; + int i; + + strncpy(buf, cmdline, 256); + buf[255] = '\0'; + i = strlen(buf); + if(i > LastArgv - Argv[0] - 2) { + i = LastArgv - Argv[0] - 2; + } + strcpy(Argv[0], buf); + p = &Argv[0][i]; + while(p < LastArgv) + *p++='\0'; + Argv[1] = NULL; +} + +void setproctitle(const char* format, ...) { + char buf[256]; + va_list args; + va_start(args, format); + vsprintf(buf, format,args); + do_setproctitle(buf); + va_end(args); +} +#endif diff --git a/mbbsd/bbcall.c b/mbbsd/bbcall.c new file mode 100644 index 00000000..d7b2d33b --- /dev/null +++ b/mbbsd/bbcall.c @@ -0,0 +1,268 @@ +/* $Id: bbcall.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define SERVER_0941 "www.chips.com.tw" +#define SERVER_0943 "www.pager.com.tw" +#define SERVER_0948 "www.fitel.net.tw" +#define SERVER_0947 "www.hoyard.com.tw" +#define SERVER_0945 "203.73.181.254" + +#define CGI_0948 "/cgi-bin/Webpage.dll" +#define CGI_0941 "/cgi-bin/paging1.pl" +#define CGI_0947 "/scripts/fp_page1.dll" +#define CGI_0945 "/Scripts/fiss/PageForm.exe" +#define CGI_0943 "/tpn/tpnasp/dowebcall.asp" + +#define CGI_RAILWAY "http://www.railway.gov.tw/cgi-bin/timetk.cgi" + +#define REFER_0943 "http://www.pager.com.tw/tpn/webcall/webcall.asp" +#define REFER_0948 "http://www.fitel.net.tw/html/svc03.htm" +#define REFER_0941 "http://www.chips.com.tw:9100/WEB2P/page_1.htm" +#define REFER_0947 "http://web1.hoyard.com.tw/freeway/freewayi.html" +#define REFER_0945 "http://203.73.181.254/call.HTM" + +static void pager_msg_encode(char *field, char *buf) { + char *cc = field; + unsigned char *p; + + for(p = (unsigned char *)buf; *p; p++) { + if((*p >= '0' && *p <= '9') || + (*p >= 'A' && *p <= 'Z') || + (*p >= 'a' && *p <= 'z') || + *p == ' ') + *cc++ = *p == ' ' ? '+' : (char)*p; + else { + sprintf(cc, "%%%02X", (int)*p); + cc += 3; + } + } + *cc = 0; +} + +static void gettime(int flag, int *Year, int *Month, int *Day, int *Hour, + int *Minute) { + char ans[5]; + + do { + getdata(10, 0, "¦~[20-]:", ans, 3, LCECHO); + *Year = atoi(ans); + } while(*Year < 00 || *Year > 02); + do { + getdata(10, 15, "¤ë[1-12]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Month = atoi(ans)) > 12 || *Month < 1); + do { + getdata(10,30, "¤é[1-31]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Day = atoi(ans)) > 31 || *Day < 1); + do { + getdata(10,45, "®É[0-23]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Hour = atoi(ans)) > 23 || *Hour < 0); + do { + getdata(10,60, "¤À[0-59]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Minute=atoi(ans))>59 || *Minute<0); + if(flag == 1) + *Year-=11; +} + +#define hpressanykey(a) {move(22, 0); prints(a); pressanykey();} + +static int Connect(char *s, char *server) { + FILE *fp = fopen(BBSHOME "/log/bbcall.log", "a"); + int sockfd; + char result[2048]; + struct sockaddr_in serv_addr; + struct hostent *hp; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0) + return 0; + + memset((char *)&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + + if((hp = gethostbyname(server)) == NULL) + return 0; + + memcpy(&serv_addr.sin_addr, hp->h_addr, hp->h_length); + + if(!strcmp(server, SERVER_0941)) + serv_addr.sin_port = htons(9100); + else + serv_addr.sin_port = htons(80); + + if(connect(sockfd, (struct sockaddr *) &serv_addr, sizeof serv_addr)) { + hpressanykey("µLªk»P¦øªA¾¹¨ú±o³sµ²¡A¶Ç©I¥¢±Ñ"); + return 0; + } else { + mprints(20, 0, "\033[1;33m¦øªA¾¹¤w¸g³s±µ¤W¡A½Ðµy«á" + ".....................\033[m"); + refresh(); + } + + write(sockfd, s, strlen(s)); + shutdown(sockfd, 1); + + while(read(sockfd, result, sizeof(result)) > 0) { + fprintf(fp, "%s\n", result); + fflush(fp); + if(strstr(result, "¥¿½T") || + strstr(result,"µ¥«Ý") || + strstr(result,"¦A«×") || + strstr(result,"§¹ ¦¨ ¦^ À³") || + strstr(result, "¹w¬ù¤¤") || + strstr(result,"¶Ç°e¤¤")) { + close(sockfd); + hpressanykey("¶¶§Q°e¥X¶Ç©I"); + return 0; + } + memset(result, 0, sizeof(result)); + } + fclose(fp); + close(sockfd); + hpressanykey("µLªk¶¶§Q°e¥X¶Ç©I"); + return 0; +} + +#define PARA \ +"Connection: Keep-Alive\r\n"\ +"User-Agent: Lynx/2.6 libwww-FM/2.14\r\n"\ +"Content-type: application/x-www-form-urlencoded\r\n"\ +"Accept: text/html, text/plain, application/x-wais-source, "\ +"application/html, */*;q=0.001\r\n"\ +"Accept-Encoding: gzip\r\n"\ +"Accept-Language: en\r\n"\ +"Accept-Charset: iso-8859-1,*,utf-8\r\n" + +static void halpha0943(char* CoId) { + char tmpbuf[64],ans[2]; + char ID[8]; + char Msg[64], atrn[512], sendform[1024]; + int Year = 99, Month = 1, Day = 15, Hour = 13, Minute = 8; + + sprintf(tmpbuf, "\033[1;37m½Ð¿é¤J±zn¶Ç©Iªº¸¹½X\033[m : %s-", CoId); + if(!getdata(7,0, tmpbuf, ID, 7, LCECHO) || + !getdata(8,0, "\033[1;37m½Ð¿é¤J¶Ç©I°T®§\033[m¡G", tmpbuf, 63, LCECHO)) { + hpressanykey("©ñ±ó¶Ç©I"); + return; + } + pager_msg_encode(Msg,tmpbuf); + getdata(9, 0, "\033[1;37m¦pªG§An°¨¤W°e½Ð«ö '1' " + "¦pªGn©w®É°e½Ð«ö '2': \033[m", ans, 2, LCECHO); + + if(ans[0] != '1') + gettime(0, &Year, &Month, &Day, &Hour, &Minute); + + sprintf(atrn, "CoId=%s&ID=%s&Year=19%02d&Month=%02d&Day=%02d" + "&Hour=%02d&Minute=%02d&Msg=%s", + CoId, ID,Year,Month,Day,Hour,Minute,Msg); + sprintf(sendform, "POST %s HTTP/1.0\nReferer: " + "%s\n%sContent-length:%d\n\n%s", + CGI_0943, REFER_0943, PARA, strlen(atrn), atrn); + Connect(sendform, SERVER_0943); + return ; +} + +static void hcall0941() { + char ans[2]; + char PAGER_NO[8], TRAN_MSG[18], TIME[8]; + char trn[512], sendform[512]; + int year = 98, month = 12, day = 4, hour = 13, min = 8; + + if(!getdata(7, 0, "\033[1;37 ½Ð±z¿é¤J±zn¶Ç©Iªº¸¹½X : 0941- \033[m", + PAGER_NO, 7, LCECHO) || + !getdata(8, 0, "\033[1;37m½Ð¿é¤J¶Ç©I°T®§\033[m¡G", trn, 17, LCECHO)) { + hpressanykey("©ñ±ó¶Ç©I"); + return; + } + pager_msg_encode(TRAN_MSG,trn); + getdata(9,0, "\033[1;37m¦pªG§An°¨¤W°e½Ð«ö '1' " + "¦pªGn©w®É°e½Ð«ö '2': \033[m", ans, 2, LCECHO); + if(ans[0] != '1') { + strcpy(TIME,"DELAY"); + gettime(0, &year, &month, &day, &hour, &min); + } else + strcpy(TIME,"NOW"); + sprintf(trn,"PAGER_NO=%s&TRAN_MSG=%s&MSG_TYPE=NUMERIC&%s=1" + "&year=19%02d&month=%02d&day=%02d&hour=%02d&min=%02d", + PAGER_NO, TRAN_MSG, TIME,year,month,day,hour,min); + + sprintf(sendform, "POST %s HTTP/1.0\nReferer: %s\n%s" + "Content-length:%d\n\n%s", + CGI_0941, REFER_0941, PARA, strlen(trn), trn); + + Connect(sendform, SERVER_0941); + return ; +} + +static void hcall0948() { + int year = 87, month = 12, day = 19, hour = 12, min = 0, ya = 0; + char svc_no[8], message[64], trn[256], sendform[512], ans[3]; + + move(7,0); + clrtoeol(); + + if(!getdata(7, 0, "\033[1;37m½Ð¿é¤J±zn¶Ç©Iªº¸¹½X\033[m¡G0948-", + svc_no, 7, LCECHO) || + !getdata(8, 0, "\033[1;37m½Ð¿é¤J¶Ç©I°T®§\033[m¡G", trn, 61, LCECHO)) { + hpressanykey("©ñ±ó¶Ç©I"); + return; + } + pager_msg_encode(message, trn); + getdata(9, 0, "\033[1;37m¦pªG§An°¨¤W°e½Ð«ö '1' " + "¦pªGn©w®É°e½Ð«ö '2'\033[m: ", ans, 2, LCECHO); + if(ans[0] != '1') { + gettime(1, &year, &month, &day, &hour, &min); + ya = 1; + } + + sprintf(trn, "MfcISAPICommand=SinglePage&svc_no=%s&reminder=%d" + "&year=%02d&month=%02d&day=%02d&hour=%02d&min=%02d&message=%s", + svc_no, ya, year, month, day, hour, min, message); + + sprintf(sendform, "GET %s?%s Http/1.0\n\n", CGI_0948, trn); + + Connect(sendform, SERVER_0948); + return; +} + +int main_bbcall() { + char ch[2]; + + clear(); + move(0, 30); + prints("\033[1;37;45m ¹G¹Gáà¾÷ \033[m"); + move(3, 0); + prints("\033[1;31m ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{\033[m\n"); + prints("\033[1;33m (1)0941 (2)0943 (3)0946 " + " (4)0948 \033[m\n"); + prints("\033[1;31m ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}\033[m\n"); + getdata(7, 8, "\033[1;37m§Aªº¿ï¾Ü? [1-4]\033[m", ch, 2, LCECHO); + + switch(ch[0]) { + case '1': + hcall0941(); + break; + case '2': + halpha0943("0943"); + break; + case '3': + halpha0943("0946"); + break; + case '4': + hcall0948(); + break; + } + return 0; +} diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c new file mode 100644 index 00000000..15db1c91 --- /dev/null +++ b/mbbsd/bbs.c @@ -0,0 +1,1904 @@ +/* $Id: bbs.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +static int g_board_names(boardheader_t *fhdr) { + AddNameList(fhdr->brdname); + return 0; +} + +extern userec_t cuser; +extern void touchdircache(int bid); +extern int TagNum; + +static void mail_by_link(char* owner, char* title, char* path) { + char genbuf[200]; + fileheader_t mymail; + + sprintf(genbuf,BBSHOME"/home/%c/%s", cuser.userid[0], cuser.userid); + stampfile(genbuf, &mymail); + strcpy(mymail.owner, owner); + sprintf(mymail.title, title); + mymail.savemode = 0; + unlink(genbuf); + Link(path, genbuf); + sprintf(genbuf,BBSHOME"/home/%c/%s/.DIR",cuser.userid[0],cuser.userid); + + append_record(genbuf, &mymail, sizeof(mymail)); +} + +extern int usernum; + +void anticrosspost() { + char buf[200]; + time_t now = time(NULL); + + sprintf(buf, + "\033[1;33;46m%s \033[37;45mcross post ¤å³¹ \033[37m %s\033[m", + cuser.userid, ctime(&now)); + log_file("etc/illegal_money", buf); + + post_violatelaw(cuser.userid, "Ptt¨t²Îĵ¹î", "Cross-post", "»@³æ³B¥÷"); + cuser.userlevel |= PERM_VIOLATELAW; + cuser.vl_count ++; + mail_by_link("Pttĵ¹î³¡¶¤", "Cross-Post»@³æ", + BBSHOME "/etc/crosspost.txt"); + passwd_update(usernum, &cuser); + exit(0); +} + +/* Heat CharlieL*/ +int save_violatelaw() { + char buf[128], ok[3]; + + setutmpmode(VIOLATELAW); + clear(); + stand_title("ú»@³æ¤¤¤ß"); + + if(!(cuser.userlevel & PERM_VIOLATELAW)) { + mprints(22, 0, "\033[1;31m§AµL²á°Ú? §A¤S¨S¦³³Q¶}»@³æ~~\033[m"); + pressanykey(); + return 0; + } + + reload_money(); + if(cuser.money < (int)cuser.vl_count*1000) { + sprintf(buf, "\033[1;31m³o¬O§A²Ä %d ¦¸¹H¤Ï¥»¯¸ªk³W" + "¥²¶·Ãº¥X %d $Ptt ,§A¥u¦³ %d ¤¸, ¿ú¤£°÷°Õ!!\033[m", + (int)cuser.vl_count, (int)cuser.vl_count * 1000, cuser.money); + mprints(22, 0, buf); + pressanykey(); + return 0; + } + + move(5,0); + prints("\033[1;37m§Aª¾¹D¶Ü? ¦]¬°§Aªº¹Hªk " + "¤w¸g³y¦¨«Ü¦h¤Hªº¤£«K\033[m\n"); + prints("\033[1;37m§A¬O§_½T©w¥H«á¤£·|¦A¥Ç¤F¡H\033[m\n"); + + if(!getdata(10,0,"½T©w¶Ü¡H[y/n]:", ok, 2, LCECHO) || + ok[0] == 'n' || ok[0] == 'N') { + mprints(22,0,"\033[1;31mµ¥§A·Q³q¤F¦A¨Ó§a!! " + "§Ú¬Û«H§A¤£·|ª¾¿ù¤£§ïªº~~~\033[m"); + pressanykey(); + return 0; + } + + sprintf(buf, "³o¬O§A²Ä %d ¦¸¹Hªk ¥²¶·Ãº¥X %d $Ptt", + cuser.vl_count, cuser.vl_count*1000); + mprints(11,0,buf); + + if(!getdata(10, 0, "n¥I¿ú[y/n]:", ok, 2, LCECHO) || + ok[0] == 'N' || ok[0] == 'n') { + + mprints(22,0, "\033[1;31m ¶â ¦s°÷¿ú ¦A¨Ó§a!!!\033[m"); + pressanykey(); + return 0; + } + + demoney(-1000*cuser.vl_count); + cuser.userlevel &= (~PERM_VIOLATELAW); + passwd_update(usernum, &cuser); + return 0; +} + +void make_blist() { + CreateNameList(); + apply_boards(g_board_names); +} + +extern int currbid; +extern char currBM[]; +extern int currmode; +extern char currboard[]; +static time_t board_note_time; +static char *brd_title; + +void set_board() { + boardheader_t *bp; + + bp = getbcache(currbid); + board_note_time = bp->bupdate; + brd_title = bp->BM; + if(brd_title[0] <= ' ') + brd_title = "¼x¨D¤¤"; + sprintf(currBM, "ªO¥D¡G%s", brd_title); + brd_title = ((bp->bvote != 2 && bp->bvote) ? "¥»¬ÝªO¶i¦æ§ë²¼¤¤" : + bp->title + 7); + currmode = (currmode & (MODE_DIRTY | MODE_MENU)) | MODE_STARTED ; + + if (HAS_PERM(PERM_ALLBOARD) || is_BM(bp->BM)) + currmode = currmode | MODE_BOARD | MODE_POST; + else if(haspostperm(currboard)) + currmode |= MODE_POST; +} + +static void readtitle() { + showtitle(currBM, brd_title); + outs("[¡ö]Â÷¶} [¡÷]¾\\Ū [^P]µoªí¤å³¹ [b]³Æ§Ñ¿ý [d]§R°£ [z]ºëµØ°Ï " + "[TAB]¤åºK [h]elp\n\033[7m ½s¸¹ ¤é ´Á §@ ªÌ ¤å ³¹ ¼Ð ÃD" + " \033[m"); +} + +extern int brc_num; +extern int brc_list[]; +extern char currtitle[]; + +extern int Tagger(); + +static void readdoent(int num, fileheader_t *ent) { + int type; + char *mark, *title, color; + + type = brc_unread(ent->filename,brc_num,brc_list) ? '+' : ' '; + + if((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST)) + type = (type == ' ') ? '*' : '#'; + else if(currmode & MODE_BOARD || HAS_PERM(PERM_LOGINOK)) { + if(ent->filemode & FILE_MARKED) + type = (type == ' ') ? 'm' : 'M'; + + else if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) + type = 'D'; + + else if (ent->filemode & FILE_SOLVED) + type = 's'; + } + + title = subject(mark = ent->title); + if(title == mark) + color = '1', mark = "¡¼"; + else + color = '3', mark = "R:"; + + if(title[47]) + strcpy(title + 44, " ¡K"); /* §â¦h¾lªº string ¬å±¼ */ + + if(strncmp(currtitle, title, 40)) + prints("%6d %c %-7s%-13.12s%s %s\n", num, type, + ent->date, ent->owner, mark, title); + else + prints("%6d %c %-7s%-13.12s\033[1;3%cm%s %s\033[m\n", num, type, + ent->date, ent->owner, color, mark, title); +} + +extern char currfile[]; + +int cmpfilename(fileheader_t *fhdr) { + return (!strcmp(fhdr->filename, currfile)); +} + +extern unsigned char currfmode; + +int cmpfmode(fileheader_t *fhdr) { + return (fhdr->filemode & currfmode); +} + +extern char currowner[]; + +int cmpfowner(fileheader_t *fhdr) { + return !strcasecmp(fhdr->owner, currowner); +} + +extern char *err_bid; +extern userinfo_t *currutmp; + +int whereami(int ent, fileheader_t *fhdr, char *direct) { + boardheader_t *bh, *p[32], *root; + int i,j; + + if(!currutmp->brc_id) return 0; + + move(1,0); + clrtobot(); + bh=getbcache(currutmp->brc_id); + root=getbcache(1); + p[0]=bh; + for(i=0;i<31 && p[i]->parent!=root && p[i]->parent;i++) + p[i+1]=p[i]->parent; + j=i; + prints("§Ú¦bþ?\n%-40.40s %.13s\n", p[j]->title+7, p[j]->BM); + for(j--;j>=0;j--) + prints("%*s %-13.13s %-37.37s %.13s\n", (i-j)*2, "", + p[j]->brdname, p[j]->title, + p[j]->BM); + + pressanykey(); + return FULLUPDATE; +} +static int do_select(int ent, fileheader_t *fhdr, char *direct) { + char bname[20]; + char bpath[60]; + boardheader_t *bh; + struct stat st; + int i; + + move(0, 0); + clrtoeol(); + make_blist(); + namecomplete(MSG_SELECT_BOARD, bname); + if(bname[0]=='\0' || !(i = getbnum(bname))) + return FULLUPDATE; + bh = getbcache(i); + if(!Ben_Perm(bh)) return FULLUPDATE; + strcpy(bname, bh->brdname); + currbid=i; + + setbpath(bpath, bname); + if((*bname == '\0') || (stat(bpath, &st) == -1)) { + move(2, 0); + clrtoeol(); + outs(err_bid); + return FULLUPDATE; + } + + currutmp->brc_id = currbid; + + brc_initial(bname); + set_board(); + setbdir(direct, currboard); + + move(1, 0); + clrtoeol(); + return NEWDIRECT; +} + +/* ----------------------------------------------------- */ +/* §ï¨} innbbsd Âà¥X«H¥ó¡B³s½u¬å«H¤§³B²zµ{§Ç */ +/* ----------------------------------------------------- */ +void outgo_post(fileheader_t *fh, char *board) { + FILE *foo; + + if((foo = fopen("innd/out.bntp", "a"))) { + fprintf(foo, "%s\t%s\t%s\t%s\t%s\n", board, + fh->filename, cuser.userid, cuser.username, fh->title); + fclose(foo); + } +} + +extern char *str_author1; +extern char *str_author2; + +static void cancelpost(fileheader_t *fh, int by_BM) { + FILE *fin, *fout; + char *ptr, *brd; + fileheader_t postfile; + char genbuf[200]; + char nick[STRLEN], fn1[STRLEN], fn2[STRLEN]; + + setbfile(fn1, currboard, fh->filename); + if((fin = fopen(fn1, "r"))) { + brd = by_BM ? "deleted" : "junk"; + + setbpath(fn2, brd); + stampfile(fn2, &postfile); + memcpy(postfile.owner, fh->owner, IDLEN + TTLEN + 10); + postfile.savemode = 'D'; + + if(fh->savemode == 'S') { + nick[0] = '\0'; + while(fgets(genbuf, sizeof(genbuf), fin)) { + if (!strncmp(genbuf, str_author1, LEN_AUTHOR1) || + !strncmp(genbuf, str_author2, LEN_AUTHOR2)) { + if((ptr = strrchr(genbuf, ')'))) + *ptr = '\0'; + if((ptr = (char *)strchr(genbuf, '('))) + strcpy(nick, ptr + 1); + break; + } + } + + if((fout = fopen("innd/cancel.bntp", "a"))) { + fprintf(fout, "%s\t%s\t%s\t%s\t%s\n", currboard, fh->filename, + cuser.userid, nick, fh->title); + fclose(fout); + } + } + + fclose(fin); + Rename(fn1, fn2); + setbdir(genbuf, brd); + append_record(genbuf, &postfile, sizeof(postfile)); + } +} + +extern char *str_reply; +extern char save_title[]; + +/* ----------------------------------------------------- */ +/* µoªí¡B¦^À³¡B½s¿è¡BÂà¿ý¤å³¹ */ +/* ----------------------------------------------------- */ +void do_reply_title(int row, char *title) { + char genbuf[200]; + char genbuf2[4]; + + if(strncasecmp(title, str_reply, 4)) + sprintf(save_title, "Re: %s", title); + else + strcpy(save_title, title); + save_title[TTLEN - 1] = '\0'; + sprintf(genbuf, "±Ä¥Îì¼ÐÃD¡m%.60s¡n¶Ü?[Y] ", save_title); + getdata(row, 0, genbuf, genbuf2, 4, LCECHO); + if(genbuf2[0] == 'n' || genbuf2[0] == 'N') + getdata(++row, 0, "¼ÐÃD¡G", save_title, TTLEN, DOECHO); +} + +static void do_unanonymous_post(char* fpath) { + fileheader_t mhdr; + char title[128]; + char genbuf[200]; + + setbpath(genbuf, "UnAnonymous"); + if(dashd(genbuf)) { + stampfile(genbuf, &mhdr); + unlink(genbuf); + Link(fpath, genbuf); + strcpy(mhdr.owner, cuser.userid); + strcpy(mhdr.title, save_title); + mhdr.savemode = 0; + mhdr.filemode = 0; + setbdir(title, "UnAnonymous"); + append_record(title, &mhdr, sizeof(mhdr)); + } +} + +extern char quote_file[]; +extern char quote_user[]; +extern int curredit; +extern unsigned int currbrdattr; +extern char currdirect[]; +extern char *err_uid; + +#ifdef NO_WATER_POST +static time_t last_post_time = 0; +static time_t water_counts = 0; +#endif +int local_article; +char real_name[20]; + +static int do_general() { + fileheader_t postfile; + char fpath[80], buf[80]; + int aborted, defanony, ifuseanony; + char genbuf[200],*owner; + boardheader_t *bp; + int islocal; + + ifuseanony = 0; + bp = getbcache(currbid); + + clear(); + if(!(currmode & MODE_POST)) { + move(5, 10); + outs("¹ï¤£°_¡A±z¥Ø«eµLªk¦b¦¹µoªí¤å³¹¡I"); + pressanykey(); + return FULLUPDATE; + } + +#ifdef NO_WATER_POST + /* ¤T¤ÀÄÁ¤º³Ì¦hµoªí¤½g¤å³¹ */ + if(currutmp->lastact - last_post_time < 60 * 3) { + if(water_counts >= 5) { + move(5, 10); + outs("¹ï¤£°_¡A±zªº¤å³¹¤Ó¤ôÅo¡A¦h«ä¦Ò¤@¤U¡A«Ý·|¦Apost§a¡I"); + pressanykey(); + return FULLUPDATE; + } + } else { + last_post_time = currutmp->lastact; + water_counts = 0; + } +#endif + + setbfile(genbuf, currboard, FN_POST_NOTE ); + + if(more(genbuf,NA) == -1) + more("etc/"FN_POST_NOTE , NA); + + move(19,0); + prints("µoªí¤å³¹©ó¡i\033[33m %s\033[m ¡j \033[32m%s\033[m ¬ÝªO\n\n", + currboard, bp->title + 7); + + if(quote_file[0]) + do_reply_title(20, currtitle); + else { + getdata(21, 0, "¼ÐÃD¡G", save_title, TTLEN, DOECHO); + strip_ansi(save_title,save_title,0); + } + if(save_title[0] == '\0') + return FULLUPDATE; + + curredit &= ~EDIT_MAIL; + curredit &= ~EDIT_ITEM; + setutmpmode(POSTING); + + /* ¥¼¨ã³Æ Internet ÅvªÌ¡A¥u¯à¦b¯¸¤ºµoªí¤å³¹ */ + if(HAS_PERM(PERM_INTERNET)) + local_article = 0; + else + local_article = 1; + + /* build filename */ + setbpath(fpath, currboard); + stampfile(fpath, &postfile); + + aborted = vedit(fpath, YEA, &islocal); + if(aborted == -1) { + unlink(fpath); + pressanykey(); + return FULLUPDATE; + } + water_counts++; /* po¦¨¥\ */ + + /* set owner to Anonymous , for Anonymous board */ + +#ifdef HAVE_ANONYMOUS + /* Ptt and Jaky */ + defanony=currbrdattr & BRD_DEFAULTANONYMOUS; + if((currbrdattr & BRD_ANONYMOUS) && + ((strcmp(real_name,"r") && defanony) || (real_name[0] && !defanony)) + ) { + strcat(real_name,"."); + owner = real_name; + ifuseanony=1; + } else + owner = cuser.userid; +#else + owner = cuser.userid; +#endif + /* ¿ú */ + aborted = (aborted > MAX_POST_MONEY * 2) ? MAX_POST_MONEY : aborted / 2; + postfile.money = aborted; + strcpy(postfile.owner, owner); + strcpy(postfile.title, save_title); + if(islocal) { /* local save */ + postfile.savemode = 'L'; + postfile.filemode = FILE_LOCAL; + } else + postfile.savemode = 'S'; + + setbdir(buf, currboard); + if(append_record(buf, &postfile, sizeof(postfile)) != -1) { + setbtotal(currbid); + + if(currmode & MODE_SELECT) + append_record(currdirect,&postfile,sizeof(postfile)); + if(!islocal && !(bp->brdattr & BRD_NOTRAN)) + outgo_post(&postfile, currboard); + brc_addlist(postfile.filename); + + if(!(currbrdattr & BRD_HIDE) && + (!bp->level || (currbrdattr & BRD_POSTMASK))) { + setbpath(genbuf, ALLPOST); + stampfile(genbuf, &postfile); + unlink(genbuf); + + /* jochang: boards may spread across many disk */ + /* link doesn't work across device, + Link doesn't work if we have same-time-across-device posts, + we try symlink now */ + { + /* we need absolute path for symlink */ + char abspath[256]=BBSHOME"/"; + strcat(abspath,fpath); + symlink(abspath,genbuf); + } + strcpy(postfile.owner, owner); + strcpy(postfile.title, save_title); + postfile.savemode = 'L'; + setbdir(genbuf, ALLPOST); + if(append_record(genbuf, &postfile, sizeof(postfile)) != -1) { + setbtotal(getbnum(ALLPOST)); + } + } + + outs("¶¶§Q¶K¥X§G§i¡A"); + +#ifdef MAX_POST_MONEY + aborted = (aborted > MAX_POST_MONEY) ? MAX_POST_MONEY : aborted; +#endif + if(strcmp(currboard, "Test") && !ifuseanony) { + prints("³o¬O±zªº²Ä %d ½g¤å³¹¡C ½Z¹S %d »È¡C", + ++cuser.numposts, aborted ); + demoney(aborted); + passwd_update(usernum, &cuser); /* post ¼Æ */ + } else + outs("´ú¸Õ«H¥ó¤£¦C¤J¬ö¿ý¡A·q½Ð¥]²[¡C"); + + /* ¦^À³¨ìì§@ªÌ«H½c */ + + if(curredit & EDIT_BOTH) { + char *str, *msg = "¦^À³¦Ü§@ªÌ«H½c"; + + if((str = strchr(quote_user, '.'))) { + if( +#ifndef USE_BSMTP + bbs_sendmail(fpath, save_title, str + 1) +#else + bsmtp(fpath, save_title, str + 1 ,0) +#endif + < 0) + msg = "§@ªÌµLªk¦¬«H"; + } else { + sethomepath(genbuf, quote_user); + stampfile(genbuf, &postfile); + unlink(genbuf); + Link(fpath, genbuf); + + strcpy(postfile.owner, cuser.userid); + strcpy(postfile.title, save_title); + postfile.savemode = 'B';/* both-reply flag */ + sethomedir(genbuf, quote_user); + if(append_record(genbuf, &postfile, sizeof(postfile)) == -1) + msg = err_uid; + } + outs(msg); + curredit ^= EDIT_BOTH; + } + if(currbrdattr & BRD_ANONYMOUS) + do_unanonymous_post(fpath); + } + pressanykey(); + return FULLUPDATE; +} + +int do_post() { + boardheader_t *bp; + bp = getbcache(currbid); + if(bp->brdattr & BRD_VOTEBOARD) + return do_voteboard(); + else if(!(bp->brdattr & BRD_GROUPBOARD)) + return do_general(); + touchdircache(currbid); + return 0; +} + +extern int b_lines; +extern int curredit; + +static void do_generalboardreply(fileheader_t *fhdr){ + char genbuf[200]; + getdata(b_lines - 1, 0, + "¡¶ ¦^À³¦Ü (F)¬ÝªO (M)§@ªÌ«H½c (B)¤GªÌ¬Ò¬O (Q)¨ú®ø¡H[F] ", + genbuf, 3, LCECHO); + switch(genbuf[0]) { + case 'm': + mail_reply(0, fhdr, 0); + case 'q': + break; + + case 'b': + curredit = EDIT_BOTH; + default: + strcpy(currtitle, fhdr->title); + strcpy(quote_user, fhdr->owner); + quote_file[79] = fhdr->savemode; + do_post(); + } + *quote_file = 0; +} + +int getindex(char *fpath, char *fname, int size) { + int fd, now=0; + fileheader_t fhdr; + + if((fd = open(fpath, O_RDONLY, 0)) != -1) { + while((read(fd, &fhdr, size) == size)) { + now++; + if(!strcmp(fhdr.filename,fname)) { + close(fd); + return now; + } + } + close(fd); + } + return 0; +} + +int invalid_brdname(char *brd) { + register char ch; + + ch = *brd++; + if(not_alnum(ch)) + return 1; + while((ch = *brd++)) { + if(not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') + return 1; + } + return 0; +} + +static void do_reply(fileheader_t *fhdr) { + boardheader_t *bp; + bp = getbcache(currbid); + if (bp->brdattr & BRD_VOTEBOARD) + do_voteboardreply(fhdr); + else + do_generalboardreply(fhdr); +} + +static int reply_post(int ent, fileheader_t *fhdr, char *direct) { + if(!(currmode & MODE_POST)) + return DONOTHING; + + setdirpath(quote_file, direct, fhdr->filename); + do_reply(fhdr); + *quote_file = 0; + return FULLUPDATE; +} + +static int edit_post(int ent, fileheader_t *fhdr, char *direct) { + char fpath[80], fpath0[80]; + char genbuf[200]; + fileheader_t postfile; + boardheader_t *bp; + bp = getbcache(currbid); + if (!HAS_PERM(PERM_SYSOP) && (bp->brdattr & BRD_VOTEBOARD)) + return DONOTHING; + + if ((!HAS_PERM(PERM_SYSOP)) && + strcmp(fhdr->owner, cuser.userid)) + return DONOTHING; + setutmpmode(REEDIT); + setdirpath(genbuf, direct, fhdr->filename); + local_article = fhdr->filemode & FILE_LOCAL; + strcpy(save_title, fhdr->title); + +/* rocker.011018: ³o¸Ì¬O¤£¬O¸ÓÀˬd¤@¤Uקï¤å³¹«áªºmoney©M즳ªº¤ñ¸û? */ + if(vedit(genbuf, 0, NULL) != -1) { + setbpath(fpath, currboard); + stampfile(fpath, &postfile); + unlink(fpath); + setbfile(fpath0, currboard, fhdr->filename); + + Rename(fpath0, fpath); + +/* rocker.011018: fix ¦ê±µ¼Ò¦¡§ï¤å³¹«á¤å³¹´N¤£¨£ªºbug */ + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(fpath0, currboard); + get_record(fpath0, &hdr, sizeof (hdr), num); + + /* ¦A³o¸Ìncheck¤@¤Uì¨Óªºdir¸Ì±¬O¤£¬O¦³³Q¤H°Ê¹L... */ + if (!strcmp (hdr.filename, fhdr->filename)) + { + strcpy(hdr.filename, postfile.filename); + strcpy(hdr.title, save_title); + substitute_record(fpath0, &hdr, sizeof(hdr), num); + } + } + + strcpy(fhdr->filename, postfile.filename); + strcpy(fhdr->title, save_title); + brc_addlist(postfile.filename); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); +/* rocker.011018: ¶¶«K§ó·s¤@¤Ucache */ + touchdircache(currbid); + } + return FULLUPDATE; +} + +extern crosspost_t postrecord; +#define UPDATE_USEREC (currmode |= MODE_DIRTY) + +static int cross_post(int ent, fileheader_t *fhdr, char *direct) { + char xboard[20], fname[80], xfpath[80], xtitle[80], inputbuf[10]; + fileheader_t xfile; + FILE *xptr; + int author = 0; + char genbuf[200]; + char genbuf2[4]; + boardheader_t *bp; + make_blist(); + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + bp = getbcache(currbid); + if (bp && (bp->brdattr & BRD_VOTEBOARD)) + return FULLUPDATE; + namecomplete("Âà¿ý¥»¤å³¹©ó¬ÝªO¡G", xboard); + if(*xboard == '\0' || !haspostperm(xboard)) + return FULLUPDATE; + + if((ent = str_checksum(fhdr->title)) != 0 && + ent == postrecord.checksum[0]) { + /* Àˬd cross post ¦¸¼Æ */ + if(postrecord.times++ > MAX_CROSSNUM) + anticrosspost(); + } else { + postrecord.times = 0; + postrecord.checksum[0] = ent; + } + + ent = 1; + if(HAS_PERM(PERM_SYSOP) || !strcmp(fhdr->owner, cuser.userid)) { + getdata(2, 0, "(1)ì¤åÂà¸ü (2)ÂÂÂà¿ý®æ¦¡¡H[1] ", + genbuf, 3, DOECHO); + if(genbuf[0] != '2') { + ent = 0; + getdata(2, 0, "«O¯dì§@ªÌ¦WºÙ¶Ü?[Y] ", inputbuf, 3, DOECHO); + if (inputbuf[0] != 'n' && inputbuf[0] != 'N') author = 1; + } + } + + if(ent) + sprintf(xtitle, "[Âà¿ý]%.66s", fhdr->title); + else + strcpy(xtitle, fhdr->title); + + sprintf(genbuf, "±Ä¥Îì¼ÐÃD¡m%.60s¡n¶Ü?[Y] ", xtitle); + getdata(2, 0, genbuf, genbuf2, 4, LCECHO); + if(genbuf2[0] == 'n' || genbuf2[0] == 'N') { + if(getdata_str(2, 0, "¼ÐÃD¡G", genbuf, TTLEN, DOECHO,xtitle)) + strcpy(xtitle, genbuf); + } + + getdata(2, 0, "(S)¦sÀÉ (L)¯¸¤º (Q)¨ú®ø¡H[Q] ", genbuf, 3, LCECHO); + if(genbuf[0] == 'l' || genbuf[0] == 's') { + int currmode0 = currmode; + + currmode = 0; + setbpath(xfpath, xboard); + stampfile(xfpath, &xfile); + if(author) + strcpy(xfile.owner, fhdr->owner); + else + strcpy(xfile.owner, cuser.userid); + strcpy(xfile.title, xtitle); + if(genbuf[0] == 'l') { + xfile.savemode = 'L'; + xfile.filemode = FILE_LOCAL; + } else + xfile.savemode = 'S'; + + setbfile(fname, currboard, fhdr->filename); +// if(ent) { + xptr = fopen(xfpath, "w"); + + strcpy(save_title, xfile.title); + strcpy(xfpath, currboard); + strcpy(currboard, xboard); + write_header(xptr); + strcpy(currboard, xfpath); + + fprintf(xptr, "¡° [¥»¤åÂà¿ý¦Û %s ¬ÝªO]\n\n", currboard); + + b_suckinfile(xptr, fname); + addsignature(xptr,0); + fclose(xptr); +/* Cross fs¦³°ÝÃD + } else { + unlink(xfpath); + link(fname, xfpath); + } +*/ + setbdir(fname, xboard); + append_record(fname, &xfile, sizeof(xfile)); + bp = getbcache(getbnum(xboard)); + if(!xfile.filemode && !(bp->brdattr && BRD_NOTRAN)) + outgo_post(&xfile, xboard); + setbtotal(getbnum(xboard)); + cuser.numposts++; + UPDATE_USEREC; + outs("¤å³¹Âà¿ý§¹¦¨"); + pressanykey(); + currmode = currmode0; + } + return FULLUPDATE; +} + +static int read_post(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + int more_result; + + if(fhdr->owner[0] == '-') + return DONOTHING; + + setdirpath(genbuf, direct, fhdr->filename); + + if((more_result = more(genbuf, YEA)) == -1) + return DONOTHING; + + brc_addlist(fhdr->filename); + strncpy(currtitle, subject(fhdr->title), 40); + strncpy(currowner, subject(fhdr->owner), IDLEN + 2); + + switch (more_result) { + case 1: + return READ_PREV; + case 2: + return RELATE_PREV; + case 3: + return READ_NEXT; + case 4: + return RELATE_NEXT; + case 5: + return RELATE_FIRST; + case 6: + return FULLUPDATE; + case 7: + case 8: + if((currmode & MODE_POST)) { + strcpy(quote_file, genbuf); + do_reply(fhdr); + *quote_file = 0; + } + return FULLUPDATE; + case 9: + return 'A'; + case 10: + return 'a'; + case 11: + return '/'; + case 12: + return '?'; + } + + + outmsg("\033[34;46m ¾\\Ū¤å³¹ \033[31;47m (R/Y)\033[30m¦^«H \033[31m" + "(=[]<>)\033[30m¬ÛÃö¥DÃD \033[31m(¡ô¡õ)\033[30m¤W¤U«Ê \033[31m(¡ö)" + "\033[30mÂ÷¶} \033[m"); + + switch(egetch()) { + case 'q': + case 'Q': + case KEY_LEFT: + break; + + case ' ': + case KEY_RIGHT: + case KEY_DOWN: + case KEY_PGDN: + case 'n': + case Ctrl('N'): + return READ_NEXT; + + case KEY_UP: + case 'p': + case Ctrl('P'): + case KEY_PGUP: + return READ_PREV; + + case '=': + return RELATE_FIRST; + + case ']': + case 't': + return RELATE_NEXT; + + case '[': + return RELATE_PREV; + + case '.': + case '>': + return THREAD_NEXT; + + case ',': + case '<': + return THREAD_PREV; + + case Ctrl('C'): + cal(); + return FULLUPDATE; + break; + + case Ctrl('I'): + t_idle(); + return FULLUPDATE; + case 'y': + case 'r': + case 'R': + case 'Y': + if((currmode & MODE_POST)) { + strcpy(quote_file, genbuf); + do_reply(fhdr); + *quote_file = 0; + } + } + return FULLUPDATE; +} + +/* ----------------------------------------------------- */ +/* ±Ä¶°ºëµØ°Ï */ +/* ----------------------------------------------------- */ +static int b_man() { + char buf[64]; + + setapath(buf, currboard); + if( (currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP) ){ + char genbuf[128]; + int fd; + sprintf(genbuf, "%s/.rebuild", buf); + if( (fd = open(genbuf, O_CREAT, 0640)) > 0 ) + close(fd); + } + return a_menu(currboard, buf, HAS_PERM(PERM_ALLBOARD) ? 2 : + (currmode & MODE_BOARD ? 1 : 0)); +} + +#ifndef NO_GAMBLE +static int join_gamble(int ent, fileheader_t *fhdr, char *direct) { + ticket(currbid); + return FULLUPDATE; +} +static int hold_gamble(int ent, fileheader_t *fhdr, char *direct) { + char fn_ticket[128],fn_ticket_end[128],genbuf[128], + msg[256]="",yn[10]=""; + int i; + FILE *fp=NULL; + + if(!(currmode & MODE_BOARD)) return 0; + setbfile(fn_ticket, currboard, FN_TICKET); + setbfile(fn_ticket_end, currboard, FN_TICKET_END); + if(dashf(fn_ticket)) + { + getdata(b_lines - 1, 0, "¤w¸g¦³Á|¿ì½ä½L, " + "¬O§_n [°±¤î¤Uª`]?(N/y)¡G", yn, 3, LCECHO); + if(yn[0]!='y') return FULLUPDATE; + rename(fn_ticket, fn_ticket_end); + return FULLUPDATE; + } + + if(dashf(fn_ticket_end)) + { + getdata(b_lines - 1, 0, "¤w¸g¦³Á|¿ì½ä½L, " + "¬O§_n [¶}¼ú]?(N/y)¡G", yn, 3, LCECHO); + if(yn[0]!='y') return FULLUPDATE; + openticket(currbid); + return FULLUPDATE; + } + getdata(b_lines - 2, 0, "nÁ|¿ì½ä½L (N/y):", yn, 3, LCECHO); + if(yn[0]!='y') return FULLUPDATE; + getdata(b_lines - 1, 0, "½ä¤°»ò? ½Ð¿é¤J¥DÃD (¿é¤J«á½s¿è¤º®e):", + msg, 20, DOECHO); + if(msg[0]==0 || + vedit(fn_ticket_end, NA, NULL)<0) + return FULLUPDATE; + + clear(); + showtitle("Á|¿ì½ä½L",BBSNAME); + setbfile(genbuf, currboard, FN_TICKET_ITEMS); + +// sprintf(genbuf, "%s/"FN_TICKET_ITEMS, direct); + + if(!(fp=fopen(genbuf,"w"))) return FULLUPDATE; + do + { + getdata(2, 0, "¿é¤J±m²¼»ù®æ (»ù®æ:10-10000):",yn,6, LCECHO); + i=atoi(yn); + } while( i<10 || i>10000); + fprintf(fp,"%d\n",i); + move(3,0); + sprintf(genbuf,"½Ð¨ì %s ª© «ö'f'°Ñ»P½ä³Õ!\n\n¤@±i %d Ptt¹ô, ³o¬O%sªº½ä³Õ\n", + currboard, + i, i<100 ? "¤p½ä¦¡" : i<500 ? "¥¥Á¯Å": + i<1000 ?"¶Q±Ú¯Å" : i<5000 ?"´I»¨¯Å" : "¶É®a¿º²£"); + strcat(msg, genbuf); + prints("½Ð¨Ì¦¸¿é¤J±m²¼¦WºÙ, »Ý´£¨Ñ2~8¶µ. (¥¼º¡¤K¶µ, ¿é¤Jª½±µ«öenter)\n"); + for(i=0; i<8; i++) + { + sprintf(yn, " %d)",i+1); + getdata(6+i, 0, yn, genbuf, 9, DOECHO); + if(!genbuf[0] && i>1) + break; + fprintf(fp,"%s\n",genbuf); + } + fclose(fp); + move(8+i,0); + prints("½ä½L³]©w§¹¦¨"); + sprintf(genbuf,"[¤½§i] %s ª© ¶}©l½ä³Õ!", currboard); + post_msg(currboard, genbuf, msg, cuser.userid); + post_msg("Record", genbuf+7, msg, "[°¨¸ô±´¤l]"); + /* Tim ±±¨îCS, ¥H§K¥¿¦bª±ªºuser§â¸ê®Æ¤w¸g¼g¶i¨Ó */ + rename(fn_ticket_end, fn_ticket); // ³]©w§¹¤~§âÀɦW§ï¹L¨Ó + + return FULLUPDATE; +} +#endif + +static int cite_post(int ent, fileheader_t *fhdr, char *direct) { + char fpath[256]; + char title[TTLEN + 1]; + + setbfile(fpath, currboard, fhdr->filename); + strcpy(title, "¡º "); + strncpy(title+3, fhdr->title, TTLEN-3); + title[TTLEN] = '\0'; + a_copyitem(fpath, title, 0, 1); + b_man(); + return FULLUPDATE; +} + +int edit_title(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + fileheader_t tmpfhdr = *fhdr; + int dirty = 0; + + if(currmode & MODE_BOARD || !strcmp(cuser.userid,fhdr->owner)) { + if(getdata(b_lines - 1, 0, "¼ÐÃD¡G", genbuf, TTLEN, DOECHO)) { + strcpy(tmpfhdr.title, genbuf); + dirty++; + } + } + + if(HAS_PERM(PERM_SYSOP)) { + if(getdata(b_lines - 1, 0, "§@ªÌ¡G", genbuf, IDLEN + 2, DOECHO)) { + strcpy(tmpfhdr.owner, genbuf); + dirty++; + } + + if(getdata(b_lines - 1, 0, "¤é´Á¡G", genbuf, 6, DOECHO)) { + sprintf(tmpfhdr.date, "%.5s", genbuf); + dirty++; + } + } + + if(currmode & MODE_BOARD || !strcmp(cuser.userid,fhdr->owner)) { + getdata(b_lines-1, 0, "½T©w(Y/N)?[n] ", genbuf, 3, DOECHO); + if((genbuf[0] == 'y' || genbuf[0] == 'Y') && dirty) { + *fhdr = tmpfhdr; + substitute_record(direct, fhdr, sizeof(*fhdr), ent); +/* rocker.011018: ³o¸ÌÀ³¸Ó§ï¦¨¥Îreferenceªº¤è¦¡¨ú±oì¨ÓªºÀÉ®× */ +#if 0 + if((currmode & MODE_SELECT)) { + int now; + + setbdir(genbuf, currboard); + now = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + substitute_record(genbuf, fhdr, sizeof(*fhdr), now); + } +#else + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* ¦A³o¸Ìncheck¤@¤Uì¨Óªºdir¸Ì±¬O¤£¬O¦³³Q¤H°Ê¹L... */ + if (strcmp (hdr.filename, fhdr->filename)) + num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + + substitute_record(genbuf, fhdr, sizeof(*fhdr), num); + } +#endif + touchdircache(currbid); + } + return FULLUPDATE; + } + return DONOTHING; +} + +extern unsigned int currstat; + +static int solve_post(int ent, fileheader_t * fhdr, char *direct){ + if (HAS_PERM(PERM_SYSOP)) { + fhdr->filemode ^= FILE_SOLVED; + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + touchdircache(currbid); + return PART_REDRAW; + } + return DONOTHING; +} + +static int mark_post(int ent, fileheader_t *fhdr, char *direct) { + + if(!(currmode & MODE_BOARD)) return DONOTHING; + + fhdr->filemode ^= FILE_MARKED; + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + + /* rocker.011018: ¦ê±µ¼Ò¦¡¥Îreference¼W¶i®Ä²v */ + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + char genbuf[100]; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* ¦A³o¸Ìncheck¤@¤Uì¨Óªºdir¸Ì±¬O¤£¬O¦³³Q¤H°Ê¹L... */ + if (strcmp (hdr.filename, fhdr->filename)) + num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + + substitute_record(genbuf, fhdr, sizeof(*fhdr), num); + } + touchdircache(currbid); + return PART_REDRAW; +} + +extern char *msg_sure_ny; + +int del_range(int ent, fileheader_t *fhdr, char *direct) { + char num1[8], num2[8]; + int inum1, inum2; + +/* rocker.011018: ¦ê±µ¼Ò¦¡¤UÁÙ¬O¤£¤¹³\§R°£¤ñ¸û¦n */ + if(currmode & MODE_SELECT) { + outmsg("½Ð¥ý¦^¨ì¥¿±`¼Ò¦¡«á¦A¶i¦æ§R°£..."); + refresh(); + /*safe_sleep(1);*/ + return FULLUPDATE; + } + + if((currstat != READING) || (currmode & MODE_BOARD)) { + getdata(1, 0, "[³]©w§R°£½d³ò] °_ÂI¡G", num1, 5, DOECHO); + inum1 = atoi(num1); + if(inum1 <= 0) { + outmsg("°_ÂI¦³»~"); + refresh(); + /*safe_sleep(1);*/ + return FULLUPDATE; + } + getdata(1, 28, "²×ÂI¡G", num2, 5, DOECHO); + inum2 = atoi(num2); + if(inum2 < inum1) { + outmsg("²×ÂI¦³»~"); + refresh(); + /*safe_sleep(1);*/ + return FULLUPDATE; + } + getdata(1, 48, msg_sure_ny, num1, 3, LCECHO); + if(*num1 == 'y') { + outmsg("³B²z¤¤,½Ðµy«á..."); + refresh(); + if(currmode & MODE_SELECT) { + int fd,size = sizeof(fileheader_t); + char genbuf[100]; + fileheader_t rsfh; + int i = inum1,now; + if(currstat == RMAIL) + sethomedir(genbuf, cuser.userid); + else + setbdir(genbuf,currboard); + if((fd = (open(direct, O_RDONLY, 0))) != -1) { + if(lseek(fd, (off_t)(size * (inum1 - 1)), SEEK_SET) != + -1) { + while(read(fd,&rsfh,size) == size) { + if(i > inum2) + break; + now = getindex(genbuf, rsfh.filename, size); + strcpy(currfile, rsfh.filename); + delete_file(genbuf, sizeof(fileheader_t), now, + cmpfilename); + i++; + } + } + close(fd); + } + } + + delete_range(direct, inum1, inum2); + fixkeep(direct, inum1); + + if(currmode & MODE_BOARD) + setbtotal(currbid); + + return DIRCHANGED; + } + return FULLUPDATE; + } + return DONOTHING; +} + +extern char *msg_del_ny; +extern char *msg_del_ok; + +static int del_post(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[100]; + int not_owned; + boardheader_t *bp; + + bp = getbcache(currbid); + + if((fhdr->filemode & FILE_MARKED) || (fhdr->filemode & FILE_DIGEST) || + (fhdr->owner[0] == '-')) + return DONOTHING; + + not_owned = strcmp(fhdr->owner, cuser.userid); + if((!(currmode & MODE_BOARD) && not_owned) || + ((bp->brdattr & BRD_VOTEBOARD) && !HAS_PERM(PERM_SYSOP)) || + !strcmp(cuser.userid, STR_GUEST)) + return DONOTHING; + + getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO); + if(genbuf[0] == 'y' || genbuf[0] == 'Y') { + strcpy(currfile, fhdr->filename); + + setbfile(genbuf,currboard,fhdr->filename); + if(!delete_file (direct, sizeof(fileheader_t), ent, cmpfilename)) { + + if(currmode & MODE_SELECT) + { + /* rocker.011018: §Q¥Îreference´î§Cloading */ + fileheader_t hdr; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* ¦A³o¸Ìncheck¤@¤Uì¨Óªºdir¸Ì±¬O¤£¬O¦³³Q¤H°Ê¹L... */ + if (strcmp (hdr.filename, fhdr->filename)) + { + num=getindex(genbuf,fhdr->filename,sizeof(fileheader_t)); + get_record(genbuf, &hdr, sizeof (hdr), num); + } + + /* rocker.011018: ³o¸ÌnÁÙì³Q¯}Ãaªºmoney */ + fhdr->money = hdr.money; + delete_file (genbuf, sizeof(fileheader_t), num, cmpfilename); + } + +#if 0 + { + setbdir(genbuf,currboard); + now=getindex(genbuf,fhdr->filename,sizeof(fileheader_t)); + delete_file (genbuf, sizeof(fileheader_t),now,cmpfilename); + } +#endif + cancelpost(fhdr, not_owned); + + setbtotal(currbid); + if (fhdr->money < 0) + fhdr->money = 0; + if (not_owned && strcmp(currboard, "Test")){ + deumoney(searchuser(fhdr->owner), -fhdr->money); + } + if(!not_owned && strcmp(currboard, "Test")) { + if(cuser.numposts) + cuser.numposts--; + move(b_lines - 1, 0); + clrtoeol(); + demoney(-fhdr->money); + passwd_update(usernum, &cuser); /* post ¼Æ */ + prints("%s¡A±zªº¤å³¹´î¬° %d ½g¡A¤ä¥I²M¼ä¶O %d »È", msg_del_ok, + cuser.numposts,fhdr->money); + refresh(); + pressanykey(); + } + return DIRCHANGED; + } + } + return FULLUPDATE; +} + +static int view_postmoney(int ent, fileheader_t *fhdr, char *direct) { + move(b_lines - 1, 0); + clrtoeol(); + prints("³o¤@½g¤å³¹È %d »È", fhdr->money); + refresh(); + pressanykey(); + return FULLUPDATE; +} + +#ifdef OUTJOBSPOOL +/* ¬Ýª©³Æ¥÷ */ +static int tar_addqueue(int ent, fileheader_t *fhdr, char *direct) { + char email[60], qfn[80], ans[2]; + FILE *fp; + char bakboard, bakman; + clear(); + showtitle("¬Ýª©³Æ¥÷", BBSNAME); + move(2, 0); + if( !((currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP)) ) { + move(5, 10); + outs("©pn¬Oª©¥D©Î¬O¯¸ªø¤~¯àÂæÂæ°Ú -.-\"\""); + pressanykey(); + return FULLUPDATE; + } + + sprintf(qfn, BBSHOME "/jobspool/tarqueue.%s", currboard); + if( access(qfn, 0) == 0 ){ + outs("¤w¸g±Æ©w¦æµ{, µy«á·|¶i¦æ³Æ¥÷"); + pressanykey(); + return FULLUPDATE; + } + if( !getdata(4, 0, "½Ð¿é¤J¥Øªº«H½c¡G", email, sizeof(email), DOECHO) ) + return FULLUPDATE; + + /* check email -.-"" */ + if( strstr(email, "@") == NULL || strstr(email, ".bbs@") != NULL ){ + move(6, 0); + outs("±z«ü©wªº«H½c¤£¥¿½T! "); + pressanykey(); + return FULLUPDATE; + } + + getdata(6, 0, "n³Æ¥÷¬Ýª©¤º®e¶Ü(Y/N)?[Y]", ans, 2, LCECHO); + bakboard = (ans[0] == 'n' || ans[0] =='N') ? 0 : 1; + getdata(7, 0, "n³Æ¥÷ºëµØ°Ï¤º®e¶Ü(Y/N)?[N]", ans, 2, LCECHO); + bakman = (ans[0] == 'y' || ans[0] =='Y') ? 1 : 0; + if( !bakboard && !bakman ){ + move(8, 0); + outs("¥i¬O§ÚÌ¥u¯à³Æ¥÷¬Ýª©©ÎºëµØ°ÏªºC ^^\"\"\""); + pressanykey(); + return FULLUPDATE; + } + + fp = fopen(qfn, "w"); + fprintf(fp, "%s\n", cuser.userid); + fprintf(fp, "%s\n", email); + fprintf(fp, "%d,%d\n", bakboard, bakman); + fclose(fp); + + move(10, 0); + outs("¨t²Î¤w¸g±N±zªº³Æ¥÷±Æ¤J¦æµ{, \n"); + outs("µy«á±N·|¦b¨t²Ît²ü¸û§Cªº®ÉÔ±N¸ê®Æ±Hµ¹±z~ :) "); + pressanykey(); + return FULLUPDATE; +} +#endif + +static int sequent_ent; +static int continue_flag; + +/* ----------------------------------------------------- */ +/* ¨Ì§ÇŪ·s¤å³¹ */ +/* ----------------------------------------------------- */ +static int sequent_messages(fileheader_t *fptr) { + static int idc; + char genbuf[200]; + + if(fptr == NULL) + return (idc = 0); + + if(++idc < sequent_ent) + return 0; + + if(!brc_unread(fptr->filename,brc_num,brc_list)) + return 0; + + if(continue_flag) + genbuf[0] = 'y'; + else { + prints("Ū¨ú¤å³¹©ó¡G[%s] §@ªÌ¡G[%s]\n¼ÐÃD¡G[%s]", + currboard, fptr->owner, fptr->title); + getdata(3, 0, "(Y/N/Quit) [Y]: ", genbuf, 3, LCECHO); + } + + if(genbuf[0] != 'y' && genbuf[0]) { + clear(); + return (genbuf[0] == 'q' ? QUIT : 0); + } + + setbfile(genbuf, currboard, fptr->filename); + brc_addlist(fptr->filename); + + if(more(genbuf, YEA) == 0) + outmsg("\033[31;47m \033[31m(R)\033[30m¦^«H \033[31m(¡õ,n)" + "\033[30m¤U¤@«Ê \033[31m(¡ö,q)\033[30mÂ÷¶} \033[m"); + continue_flag = 0; + + switch(egetch()) { + case KEY_LEFT: + case 'e': + case 'q': + case 'Q': + break; + + case 'y': + case 'r': + case 'Y': + case 'R': + if(currmode & MODE_POST) { + strcpy(quote_file, genbuf); + do_reply(fptr); + *quote_file = 0; + } + break; + + case ' ': + case KEY_DOWN: + case '\n': + case 'n': + continue_flag = 1; + } + + clear(); + return 0; +} + +static int sequential_read(int ent, fileheader_t *fhdr, char *direct) { + char buf[40]; + + clear(); + sequent_messages((fileheader_t *) NULL); + sequent_ent = ent; + continue_flag = 0; + setbdir(buf, currboard); + apply_record(buf, sequent_messages, sizeof(fileheader_t)); + return FULLUPDATE; +} + +extern char *fn_notes; +extern char *msg_cancel; +extern char *fn_board; + +/* ----------------------------------------------------- */ +/* ¬ÝªO³Æ§Ñ¿ý¡B¤åºK¡BºëµØ°Ï */ +/* ----------------------------------------------------- */ +int b_note_edit_bname(int bid) { + char buf[64]; + int aborted; + boardheader_t *fh=getbcache(bid); + + setbfile(buf, fh->brdname, fn_notes); + aborted = vedit(buf, NA, NULL); + if(aborted == -1) { + clear(); + outs(msg_cancel); + pressanykey(); + } else { + aborted = (fh->bupdate - time(0)) / 86400 + 1; + sprintf(buf,"%d", aborted > 0 ? aborted : 0); + getdata_buf(3, 0, "½Ð³]©w¦³®Ä´Á(0 - 9999)¤Ñ¡H", buf, 5, DOECHO); + aborted = atoi(buf); + fh->bupdate = aborted ? time(0) + aborted * 86400 : 0; + substitute_record(fn_board, fh, sizeof(boardheader_t), bid); + } + return 0; +} + +static int b_notes_edit() { + if(currmode & MODE_BOARD) { + b_note_edit_bname(currbid); + return FULLUPDATE; + } + return 0; +} + +static int b_water_edit() { + if(currmode & MODE_BOARD) { + friend_edit(BOARD_WATER); + return FULLUPDATE; + } + return 0; +} + +static int visable_list_edit() { + if(currmode & MODE_BOARD) { + friend_edit(BOARD_VISABLE); + hbflreload(currbid); + return FULLUPDATE; + } + return 0; +} + +static int b_post_note() { + char buf[200], yn[3]; + + if(currmode & MODE_BOARD) { + setbfile(buf, currboard, FN_POST_NOTE ); + if(more(buf,NA) == -1) more("etc/"FN_POST_NOTE , NA); + getdata(b_lines - 2, 0, "¬O§_n¥Î¦Ûqpostª`·N¨Æ¶µ?", yn, 3, LCECHO); + if(yn[0] == 'y') + vedit(buf, NA, NULL); + else + unlink(buf); + return FULLUPDATE; + } + return 0; +} + +static int b_application() { + char buf[200]; + + if(currmode & MODE_BOARD) { + setbfile(buf, currboard, FN_APPLICATION); + vedit(buf, NA, NULL); + return FULLUPDATE; + } + return 0; +} + +static int can_vote_edit() { + if(currmode & MODE_BOARD) { + friend_edit(FRIEND_CANVOTE); + return FULLUPDATE; + } + return 0; +} + +static int bh_title_edit() { + boardheader_t *bp; + + if(currmode & MODE_BOARD) { + char genbuf[BTLEN]; + + bp = getbcache(currbid); + move(1,0); + clrtoeol(); + getdata_str(1,0,"½Ð¿é¤J¬ÝªO·s¤¤¤å±Ôz:", genbuf,BTLEN - + 16,DOECHO, bp->title + 7); + + if(!genbuf[0]) + return 0; + strip_ansi( genbuf,genbuf,0); + strcpy(bp->title + 7,genbuf); + substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); + log_usies("SetBoard", currboard); + return FULLUPDATE; + } + return 0; +} + +static int b_notes() { + char buf[64]; + + setbfile(buf, currboard, fn_notes); + if(more(buf, NA) == -1) { + clear(); + move(4, 20); + outs("¥»¬ÝªO©|µL¡u³Æ§Ñ¿ý¡v¡C"); + } + pressanykey(); + return FULLUPDATE; +} + +int board_select() { + char fpath[80]; + char genbuf[100]; + + currmode &= ~MODE_SELECT; + sprintf(fpath, "SR.%s", cuser.userid); + setbfile(genbuf, currboard, fpath); + unlink(genbuf); + if(currstat == RMAIL) + sethomedir(currdirect, cuser.userid); + else + setbdir(currdirect, currboard); + return NEWDIRECT; +} + +int board_digest() { + if(currmode & MODE_SELECT) + board_select(); + currmode ^= MODE_DIGEST; + if(currmode & MODE_DIGEST) + currmode &= ~MODE_POST; + else if (haspostperm(currboard)) + currmode |= MODE_POST; + + setbdir(currdirect, currboard); + return NEWDIRECT; +} + +int board_etc() { + if(!HAS_PERM(PERM_SYSOP)) + return DONOTHING; + currmode ^= MODE_ETC; + if(currmode & MODE_ETC) + currmode &= ~MODE_POST; + else if(haspostperm(currboard)) + currmode |= MODE_POST; + + setbdir(currdirect, currboard); + return NEWDIRECT; +} + +extern char *fn_mandex; + +static int good_post(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + char genbuf2[200]; + int delta = 0; + + if((currmode & MODE_DIGEST) || !(currmode & MODE_BOARD)) + return DONOTHING; + + if(fhdr->filemode & FILE_DIGEST) { + fhdr->filemode = (fhdr->filemode & ~FILE_DIGEST); + if(!strcmp(currboard,"Note") || !strcmp(currboard,"PttBug") || + !strcmp(currboard,"Artdsn") || !strcmp(currboard, "PttLaw")) { + deumoney(searchuser(fhdr->owner),-1000); + if(!(currmode & MODE_SELECT)) + fhdr->money -= 1000; + else + delta = -1000; + } + } else { + fileheader_t digest; + char *ptr, buf[64]; + + memcpy(&digest, fhdr, sizeof(digest)); + digest.filename[0] = 'G'; + strcpy(buf, direct); + ptr = strrchr(buf, '/') + 1; + ptr[0] = '\0'; + sprintf(genbuf, "%s%s", buf, digest.filename); + + if(dashf(genbuf)) unlink (genbuf); + + digest.savemode = digest.filemode = 0; + sprintf(genbuf2, "%s%s", buf, fhdr->filename); + Link(genbuf2, genbuf); + strcpy(ptr, fn_mandex); + append_record(buf, &digest, sizeof(digest)); + + fhdr->filemode = (fhdr->filemode & ~FILE_MARKED) | FILE_DIGEST; + if(!strcmp(currboard, "Note") || !strcmp(currboard, "PttBug") || + !strcmp(currboard,"Artdsn") || !strcmp(currboard, "PttLaw")) { + deumoney(searchuser(fhdr->owner), 1000); + if(!(currmode & MODE_SELECT)) fhdr->money += 1000; + else delta = 1000; + } + } + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + touchdircache(currbid); +/* rocker.011018: ¦ê±µ¼Ò¦¡¥Îreference¼W¶i®Ä²v */ + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + char genbuf[100]; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* ¦A³o¸Ìncheck¤@¤Uì¨Óªºdir¸Ì±¬O¤£¬O¦³³Q¤H°Ê¹L... */ + if (strcmp (hdr.filename, fhdr->filename)) + { + num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + get_record(genbuf, &hdr, sizeof (hdr), num); + } + fhdr->money = hdr.money + delta; + + substitute_record(genbuf, fhdr, sizeof(*fhdr), num); + } +#if 0 + if(currmode & MODE_SELECT) { + int now; + char genbuf[100]; + + setbdir(genbuf, currboard); + now=getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + substitute_record(genbuf, fhdr, sizeof(*fhdr), now); + } +#endif + return PART_REDRAW; +} + +/* help for board reading */ +static char *board_help[] = { + "\0¥þ¥\\¯à¬ÝªO¾Þ§@»¡©ú", + "\01°ò¥»©R¥O", + "(p)(¡ô) ¤W²¾¤@½g¤å³¹ (^P) µoªí¤å³¹", + "(n)(¡õ) ¤U²¾¤@½g¤å³¹ (d) §R°£¤å³¹", + "(P)(PgUp) ¤W²¾¤@¶ (S) ¦ê³s¬ÛÃö¤å³¹", + "(N)(PgDn) ¤U²¾¤@¶ (##) ¸õ¨ì ## ¸¹¤å³¹", + "(r)(¡÷) ¾\\Ū¦¹½g¤å³¹ ($) ¸õ¨ì³Ì«á¤@½g¤å³¹", + "\01¶i¶¥©R¥O", + "(tab)/z ¤åºK¼Ò¦¡/ºëµØ°Ï (a)(A) §ä´M§@ªÌ", + "(b/f) ®iŪ³Æ§Ñ¿ý/°Ñ»P½ä½L (?)(/) §ä´M¼ÐÃD", + "(V/R) §ë²¼/¬d¸ß§ë²¼µ²ªG (^W) §Ú¦bþ¸Ì¥i¬Ý¨ì¬ÝªOªº¤ÀÃþ", + "(x) Âà¿ý¤å³¹¨ì¨ä¥L¬ÝªO (=)/([]<>-+) §ä´Mº½g¤å³¹/¥DÃD¦¡¾\\Ū", +#ifdef INTERNET_EMAIL + "(F) ¤å³¹±H¦^Internet¶l½c (U) ±N¤å³¹ uuencode «á±H¦^¶l½c", +#endif + "(E) «½s¤å³¹ (^H) ¦C¥X©Ò¦³ªº New Post(s)", + "\01ªO¥D©R¥O", + "(G) Á|¿ì½ä½L/°±¤î¤Uª`/¶}¼ú(W/w/v) ½s¿è³Æ§Ñ¿ý/¤ô±í¦W³æ/¥i¬Ý¨£¦W³æ", + "(M/o) Á|¦æ§ë²¼/½s¨p§ë²¼¦W³æ (m/c/g) «O¯d¤å³¹/¿ï¿ýºëµØ/¤åºK", + "(D) §R°£¤@¬q½d³òªº¤å³¹ (T/B) «½s¤å³¹¼ÐÃD/«½s¬Ýª©¼ÐÃD", + "(i) ½s¿è¥Ó½Ð¤J·|ªí®æ (t/^D) ¼Ð°O¤å³¹/¬å°£¼Ð°Oªº¤å³¹", + "(O) ½s¿èPostª`·N¨Æ¶µ (H) ¬ÝªOÁôÂÃ/²{¨", + NULL +}; + +static int b_help() { + show_help(board_help); + return FULLUPDATE; +} + +/* ----------------------------------------------------- */ +/* ªO¥D³]©wÁô§Î/ ¸ÑÁô§Î */ +/* ----------------------------------------------------- */ +char board_hidden_status; +#ifdef BMCHS +extern char *fn_board; +static int change_hidden(int ent, fileheader_t *fhdr, char *direct) +{ + boardheader_t bh; + int bid; + char ans[4]; + + if( !((currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP)) || + currboard[0] == 0 || + (bid = getbnum(currboard)) < 0 || + get_record(fn_board, &bh, sizeof(bh), bid) == -1 ) + return DONOTHING; + + if( ((bh.brdattr & BRD_HIDE) && (bh.brdattr & BRD_POSTMASK)) ){ + getdata(1, 0, "¥Ø«eªO¦bÁô§Îª¬ºA, n¸ÑÁô§Î¹À(Y/N)?[N]", ans, 2, LCECHO); + if( ans[0] != 'y' && ans[0] != 'Y' ) + return FULLUPDATE; + getdata(2, 0, "¦A½T»{¤@¦¸, ¯uªºn§âªOªO¤½¶}¹À @____@(Y/N)?[N]", + ans, 2, LCECHO); + if( ans[0] != 'y' && ans[0] != 'Y' ) + return FULLUPDATE; + if( bh.brdattr & BRD_HIDE ) bh.brdattr -= BRD_HIDE; + if( bh.brdattr & BRD_POSTMASK ) bh.brdattr -= BRD_POSTMASK; + log_usies("OpenBoard", bh.brdname); + outs("§g¤ß¤µ¶Ç²³¤H¡AµL³B¤£»D©¶ºq¡C\n"); + board_hidden_status = 0; + hbflreload(bid); + } + else{ + getdata(1, 0, "¥Ø«eªO¦b²{§Îª¬ºA, nÁô§Î¹À(Y/N)?[N]", ans, 2, LCECHO); + if( ans[0] != 'y' && ans[0] != 'Y' ) + return FULLUPDATE; + bh.brdattr |= BRD_HIDE; + bh.brdattr |= BRD_POSTMASK; + log_usies("CloseBoard", bh.brdname); + outs("§g¤ß¤µ¤w±»§í¡A±©¬ßµ½¦Û¬Ã«¡C\n"); + board_hidden_status = 1; + } + setup_man(&bh); + substitute_record(fn_board, &bh, sizeof(bh), bid); + reset_board(bid); + log_usies("SetBoard", bh.brdname); + pressanykey(); + return FULLUPDATE; +} +#endif + +/* ----------------------------------------------------- */ +/* ¬ÝªO¥\¯àªí */ +/* ----------------------------------------------------- */ +struct onekey_t read_comms[] = { + {KEY_TAB, board_digest}, + {'C', board_etc}, + {'b', b_notes}, + {'c', cite_post}, + {'r', read_post}, + {'z', b_man}, + {'D', del_range}, + {'S', sequential_read}, + {'E', edit_post}, + {'T', edit_title}, + {'s', do_select}, + {'R', b_results}, + {'V', b_vote}, + {'M', b_vote_maintain}, + {'B', bh_title_edit}, + {'W', b_notes_edit}, + {'O', b_post_note}, + {'w', b_water_edit}, + {'v', visable_list_edit}, + {'i', b_application}, + {'o', can_vote_edit}, + {'x', cross_post}, + {'h', b_help}, +#ifndef NO_GAMBLE + {'f', join_gamble}, + {'G', hold_gamble}, +#endif + {'g', good_post}, + {'y', reply_post}, + {'d', del_post}, + {'m', mark_post}, + {'L', solve_post}, + {Ctrl('P'), do_post}, + {Ctrl('W'), whereami}, + {'Q', view_postmoney}, +#ifdef OUTJOBSPOOL + {'u', tar_addqueue}, +#endif +#ifdef BMCHS + {'H', change_hidden}, +#endif + {'\0', NULL} +}; + +time_t board_visit_time; + +int Read() { + int mode0 = currutmp->mode; + int stat0 = currstat, tmpbid=currutmp->brc_id; + char buf[40]; +#ifdef LOG_BOARD + time_t usetime = time(0); +#endif + + setutmpmode(READING); + set_board(); + + if(board_visit_time < board_note_time) { + setbfile(buf, currboard, fn_notes); + more(buf, NA); + pressanykey(); + } + currutmp->brc_id = currbid; + setbdir(buf, currboard); + curredit &= ~EDIT_MAIL; + i_read(READING, buf, readtitle, readdoent, read_comms, + currbid); +#ifdef LOG_BOARD + log_board(currboard, time(0) - usetime); +#endif + brc_update(); + + currutmp->brc_id =tmpbid; + currutmp->mode = mode0; + currstat = stat0; + return 0; +} + +void ReadSelect() { + int mode0 = currutmp->mode; + int stat0 = currstat; + char genbuf[200]; + + currstat = XMODE; + if(do_select(0, 0, genbuf) == NEWDIRECT) + Read(); + currutmp->brc_id=0; + currutmp->mode = mode0; + currstat = stat0; +} + +#ifdef LOG_BOARD +static void log_board(char *mode, time_t usetime) { + time_t now; + char buf[ 256 ]; + + if(usetime > 30) { + now = time(0); + sprintf(buf, "USE %-20.20s Stay: %5ld (%s) %s", + mode, usetime ,cuser.userid ,ctime(&now)); + log_file(FN_USEBOARD,buf); + } +} +#endif + +int Select() { + char genbuf[200]; + + setutmpmode(SELECT); + do_select(0, NULL, genbuf); + return 0; +} diff --git a/mbbsd/board.c b/mbbsd/board.c new file mode 100644 index 00000000..44b4b842 --- /dev/null +++ b/mbbsd/board.c @@ -0,0 +1,1098 @@ +/* $Id: board.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#define BRC_STRLEN 15 /* Length of board name */ +#define BRC_MAXSIZE 24576 +#define BRC_ITEMSIZE (BRC_STRLEN + 1 + BRC_MAXNUM * sizeof( int )) +#define BRC_MAXNUM 80 + +extern userinfo_t *currutmp; +static char *brc_getrecord(char *ptr, char *name, int *pnum, int *list) { + int num; + char *tmp; + + strncpy(name, ptr, BRC_STRLEN); + ptr += BRC_STRLEN; + num = (*ptr++) & 0xff; + tmp = ptr + num * sizeof(int); + if (num > BRC_MAXNUM) + num = BRC_MAXNUM; + *pnum = num; + memcpy(list, ptr, num * sizeof(int)); + return tmp; +} + +static time_t brc_expire_time; + +static char *brc_putrecord(char *ptr, char *name, int num, int *list) { + if(num > 0 && list[0] > brc_expire_time) { + if (num > BRC_MAXNUM) + num = BRC_MAXNUM; + + while(num > 1 && list[num - 1] < brc_expire_time) + num--; + + strncpy(ptr, name, BRC_STRLEN); + ptr += BRC_STRLEN; + *ptr++ = num; + memcpy(ptr, list, num * sizeof(int)); + ptr += num * sizeof(int); + } + return ptr; +} + +extern userec_t cuser; +extern char currboard[]; /* name of currently selected board */ +static int brc_changed = 0; +static char brc_buf[BRC_MAXSIZE]; +int brc_num; +static char brc_name[BRC_STRLEN]; +int brc_list[BRC_MAXNUM]; +static char *fn_boardrc = ".boardrc"; +static int brc_size; + +void brc_update() { + if(brc_changed && cuser.userlevel) { + char dirfile[STRLEN], *ptr; + char tmp_buf[BRC_MAXSIZE - BRC_ITEMSIZE], *tmp; + char tmp_name[BRC_STRLEN]; + int tmp_list[BRC_MAXNUM], tmp_num; + int fd, tmp_size; + + ptr = brc_buf; + if(brc_num > 0) + ptr = brc_putrecord(ptr, brc_name, brc_num, brc_list); + + setuserfile(dirfile, fn_boardrc); + if((fd = open(dirfile, O_RDONLY)) != -1) { + tmp_size = read(fd, tmp_buf, sizeof(tmp_buf)); + close(fd); + } else { + tmp_size = 0; + } + + tmp = tmp_buf; + while(tmp < &tmp_buf[tmp_size] && (*tmp >= ' ' && *tmp <= 'z')) { + tmp = brc_getrecord(tmp, tmp_name, &tmp_num, tmp_list); + if(strncmp(tmp_name, currboard, BRC_STRLEN)) + ptr = brc_putrecord(ptr, tmp_name, tmp_num, tmp_list); + } + brc_size = (int)(ptr - brc_buf); + + if((fd = open(dirfile, O_WRONLY | O_CREAT, 0644)) != -1) { + ftruncate(fd, 0); + write(fd, brc_buf, brc_size); + close(fd); + } + brc_changed = 0; + } +} + +static void read_brc_buf() { + char dirfile[STRLEN]; + int fd; + + if(brc_buf[0] == '\0') { + setuserfile(dirfile, fn_boardrc); + if((fd = open(dirfile, O_RDONLY)) != -1) { + brc_size = read(fd, brc_buf, sizeof(brc_buf)); + close(fd); + } else { + brc_size = 0; + } + } +} + +extern int currbid; +extern unsigned int currbrdattr; +extern boardheader_t *bcache; + +int brc_initial(char *boardname) { + char *ptr; + if(strcmp(currboard, boardname) == 0) { + return brc_num; + } + brc_update(); + strcpy(currboard, boardname); + currbid = getbnum(currboard); + currbrdattr = bcache[currbid - 1].brdattr; + read_brc_buf(); + + ptr = brc_buf; + while(ptr < &brc_buf[brc_size] && (*ptr >= ' ' && *ptr <= 'z')) { + ptr = brc_getrecord(ptr, brc_name, &brc_num, brc_list); + if (strncmp(brc_name, currboard, BRC_STRLEN) == 0) + return brc_num; + } + strncpy(brc_name, boardname, BRC_STRLEN); + brc_num = brc_list[0] = 1; + return 0; +} + +void brc_addlist(char *fname) { + int ftime, n, i; + + if(!cuser.userlevel) + return; + + ftime = atoi(&fname[2]); + if(ftime <= brc_expire_time + /* || fname[0] != 'M' || fname[1] != '.' */ ) { + return; + } + if(brc_num <= 0) { + brc_list[brc_num++] = ftime; + brc_changed = 1; + return; + } + if((brc_num == 1) && (ftime < brc_list[0])) + return; + for(n = 0; n < brc_num; n++) { + if(ftime == brc_list[n]) { + return; + } else if(ftime > brc_list[n]) { + if(brc_num < BRC_MAXNUM) + brc_num++; + for(i = brc_num - 1; --i >= n; brc_list[i + 1] = brc_list[i]); + brc_list[n] = ftime; + brc_changed = 1; + return; + } + } + if(brc_num < BRC_MAXNUM) { + brc_list[brc_num++] = ftime; + brc_changed = 1; + } +} + +static int brc_unread_time(time_t ftime, int bnum, int *blist) { + int n; + + if(ftime <= brc_expire_time ) + return 0; + + if(brc_num <= 0) + return 1; + for(n = 0; n < bnum; n++) { + if(ftime > blist[n]) + return 1; + else if(ftime == blist[n]) + return 0; + } + return 0; +} + +int brc_unread(char *fname, int bnum, int *blist) { + int ftime, n; + + ftime = atoi(&fname[2]); + + if(ftime <= brc_expire_time ) + return 0; + + if(brc_num <= 0) + return 1; + for(n = 0; n < bnum; n++) { + if(ftime > blist[n]) + return 1; + else if(ftime == blist[n]) + return 0; + } + return 0; +} + +#define BRD_UNREAD 1 +#define BRD_FAV 2 +#define BRD_ZAP 4 +#define BRD_TAG 8 + +typedef struct { + int bid, *total; + time_t *lastposttime; + boardheader_t *bh; + unsigned int myattr; +} boardstat_t; + +extern time_t login_start_time; +extern int numboards; +static int *zapbuf=NULL,*favbuf; +static boardstat_t *nbrd; + +#define STR_BBSRC ".bbsrc" +#define STR_FAV ".fav" + +void init_brdbuf() { + register int n, size; + char fname[60]; + + /* MAXBOARDS ==> ¦Ü¦h¬Ý±o¨£ 4 Ó·sªO */ + n = numboards + 4; + size = n * sizeof(int); + zapbuf = (int *) malloc(size); + favbuf = (int *) malloc(size); + + memset(favbuf,0,size); + + while(n) + zapbuf[--n] = login_start_time; + setuserfile(fname, STR_BBSRC); + if((n = open(fname, O_RDONLY, 0600)) != -1) { + read(n, zapbuf, size); + close(n); + } + setuserfile(fname, STR_FAV); + if((n = open(fname, O_RDONLY, 0600)) != -1) { + read(n, favbuf, size); + close(n); + } + + if(!nbrd) + nbrd = (boardstat_t *)malloc(MAX_BOARD * sizeof(boardstat_t)); + brc_expire_time = login_start_time - 365 * 86400; +} + +void save_brdbuf() { + int fd, size; + char fname[60]; + + if(!zapbuf) return; + setuserfile(fname, STR_BBSRC); + if((fd = open(fname, O_WRONLY | O_CREAT, 0600)) != -1) { + size = numboards * sizeof(int); + write(fd, zapbuf, size); + close(fd); + } + setuserfile(fname, STR_FAV); + if((fd = open(fname, O_WRONLY | O_CREAT, 0600)) != -1) { + size = numboards * sizeof(int); + write(fd, favbuf, size); + close(fd); + } +} + +extern char *fn_visable; + +int Ben_Perm(boardheader_t *bptr) { + register int level,brdattr; + register char *ptr; + + level = bptr->level; + brdattr = bptr->brdattr; + + if(HAS_PERM(PERM_SYSOP)) + return 1; + + ptr = bptr->BM; + if(is_BM(ptr)) + return 1; + + /* ¯¦±K¬ÝªO¡G®Ö¹ïº®uªO¥Dªº¦n¤Í¦W³æ */ + + if(brdattr & BRD_HIDE) { /* ÁôÂà */ + if( hbflcheck((int)(bptr-bcache) + 1, currutmp->uid) ){ + if(brdattr & BRD_POSTMASK) + return 0; + else + return 2; + } else + return 1; + } + /* ¨î¾\ŪÅv */ + if(level && !(brdattr & BRD_POSTMASK) && !HAS_PERM(level)) + return 0; + + return 1; +} + +extern char currauthor[]; +extern int b_lines; +extern char currowner[]; + +static int have_author(char* brdname) { + char dirname[100]; + + sprintf(dirname, "¥¿¦b·j´M§@ªÌ[33m%s[m ¬ÝªO:[1;33m%s[0m.....", + currauthor,brdname); + move(b_lines, 0); + clrtoeol(); + outs(dirname); + refresh(); + + setbdir(dirname, brdname); + str_lower(currowner, currauthor); + + return search_rec(dirname, cmpfowner); +} + +static int check_newpost(boardstat_t *ptr) { /* Ptt §ï */ + int tbrc_list[BRC_MAXNUM], tbrc_num; + char bname[BRC_STRLEN]; + char *po; + time_t ftime; + + ptr->myattr &= ~BRD_UNREAD; + if(ptr->bh->brdattr & BRD_GROUPBOARD) + return 0; + + if(*(ptr->total) == 0) + setbtotal(ptr->bid); + if(*(ptr->total) == 0) return 0; + ftime = *(ptr->lastposttime); + read_brc_buf(); + po = brc_buf; + while(po < &brc_buf[brc_size] && (*po >= ' ' && *po <= 'z')) { + po = brc_getrecord(po, bname, &tbrc_num, tbrc_list); + if(strncmp(bname, ptr->bh->brdname, BRC_STRLEN) == 0) { + if(brc_unread_time(ftime,tbrc_num,tbrc_list)) { + ptr->myattr |= BRD_UNREAD; + } + return 1; + } + } + + ptr->myattr |= BRD_UNREAD; + return 1; +} + +extern int currmode; +extern struct bcache_t *brdshm; +static int brdnum; +int class_bid = 0; +static int yank_flag = 1; +static void load_uidofgid(const int gid, const int type){ + boardheader_t *bptr,*currbptr; + int n; + currbptr = &bcache[gid-1]; + for(n=0;n<numboards;n++) + { + bptr = brdshm->sorted[type][n]; + if(bptr->brdname[0]=='\0') continue; + if(bptr->gid == gid) + { + if(currbptr == &bcache[gid-1]) + currbptr->firstchild[type]=bptr; + else + { + currbptr->next[type]=bptr; + currbptr->parent=&bcache[gid-1]; + } + currbptr=bptr; + } + } + if(currbptr == &bcache[gid-1]) + currbptr->firstchild[type]=(boardheader_t *) ~0; + else + currbptr->next[type]=(boardheader_t *) ~0; +} +static boardstat_t * addnewbrdstat(int n, int state) +{ + boardstat_t *ptr=&nbrd[brdnum++]; + boardheader_t *bptr = &bcache[n]; + ptr->total = &(brdshm->total[n]); + ptr->lastposttime = &(brdshm->lastposttime[n]); + ptr->bid = n+1; + ptr->myattr=0; + ptr->myattr=(favbuf[n]&~BRD_ZAP); + if(zapbuf[n] == 0) + ptr->myattr|=BRD_ZAP; + ptr->bh = bptr; + if((bptr->brdattr & BRD_HIDE) && state == 1) + bptr->brdattr |= BRD_POSTMASK; + check_newpost(ptr); + return ptr; +} + +static void load_boards(char *key) { + boardheader_t *bptr = NULL; + int type=cuser.uflag & BRDSORT_FLAG?1:0; + register int i,n; + register int state ; + + if(class_bid>0) + { + bptr = &bcache[class_bid-1]; + if(bptr->firstchild[type]==NULL) + load_uidofgid(class_bid,type); + } + brdnum = 0; + if(class_bid==0) + for(i=0 ; i < numboards; i++) + { + + if( (bptr = brdshm->sorted[type][i]) == NULL ) + continue; + n = (int)( bptr - bcache); + if(!bptr->brdname[0] || bptr->brdattr & BRD_GROUPBOARD || + !((state = Ben_Perm(bptr)) || (currmode & MODE_MENU)) || + (yank_flag == 0 && !(favbuf[n]&BRD_FAV)) || + (yank_flag == 1 && !zapbuf[n]) || + (key[0] && !strcasestr(bptr->title, key)) + ) continue; + addnewbrdstat(n, state); + } + else + for(bptr=bptr->firstchild[type]; bptr!=(boardheader_t *)~0; + bptr=bptr->next[type]) + { + n = (int)( bptr - bcache); + if(!((state = Ben_Perm(bptr)) || (currmode & MODE_MENU)) + ||(yank_flag == 0 && !(favbuf[n]&BRD_FAV)) + ||(yank_flag == 1 && !zapbuf[n]) || + (key[0] && !strcasestr(bptr->title, key))) continue; + addnewbrdstat(n, state); + } +} + +static int search_board() { + int num; + char genbuf[IDLEN + 2]; + move(0, 0); + clrtoeol(); + CreateNameList(); + for(num = 0; num < brdnum; num++) + AddNameList(nbrd[num].bh->brdname); + namecomplete(MSG_SELECT_BOARD, genbuf); + + for (num = 0; num < brdnum; num++) + if (!strcasecmp(nbrd[num].bh->brdname, genbuf)) + return num; + return -1; +} + +static int unread_position(char *dirfile, boardstat_t *ptr) { + fileheader_t fh; + char fname[FNLEN]; + register int num, fd, step, total; + + total = *(ptr->total); + num = total + 1; + if((ptr->myattr&BRD_UNREAD) &&(fd = open(dirfile, O_RDWR)) > 0) { + if(!brc_initial(ptr->bh->brdname)) { + num = 1; + } else { + num = total - 1; + step = 4; + while(num > 0) { + lseek(fd, (off_t)(num * sizeof(fh)), SEEK_SET); + if(read(fd, fname, FNLEN) <= 0 || + !brc_unread(fname,brc_num,brc_list)) + break; + num -= step; + if(step < 32) + step += step >> 1; + } + if(num < 0) + num = 0; + while(num < total) { + lseek(fd, (off_t)(num * sizeof(fh)), SEEK_SET); + if(read(fd, fname, FNLEN) <= 0 || + brc_unread(fname,brc_num,brc_list)) + break; + num++; + } + } + close(fd); + } + if(num < 0) + num = 0; + return num; +} + +static void brdlist_foot() { + prints("\033[34;46m ¿ï¾Ü¬ÝªO \033[31;47m (c)\033[30m·s¤å³¹¼Ò¦¡ " + "\033[31m(v/V)\033[30m¼Ð°O¤wŪ/¥¼Åª \033[31m(y)\033[30m¿z¿ï%s" + " \033[31m(z)\033[30m¤Á´«¿ï¾Ü \033[m", + yank_flag==0 ? "³Ì·R" : yank_flag==1 ? "³¡¥÷" : "¥þ³¡"); +} + +extern unsigned int currstat; +extern char *BBSName; + +static void show_brdlist(int head, int clsflag, int newflag) { + int myrow = 2; + if(class_bid == 1) { + currstat = CLASS; + myrow = 6; + showtitle("¤ÀÃþ¬ÝªO", BBSName); + movie(0); + move(1, 0); + prints( + " " + "¢© ¢~¡X\033[33m¡´\n" + " ùá¡X \033[m " + "¢¨¢i\033[47m¡ó\033[40m¢i¢i¢©ùç\n"); + prints( + " \033[44m ¡s¡s¡s¡s¡s¡s¡s¡s " + "\033[33mùø\033[m\033[44m ¢©¢¨¢i¢i¢i¡¿¡¿¡¿ùø \033[m\n" + " \033[44m " + "\033[33m \033[m\033[44m ¢«¢ª¢i¢i¢i¡¶¡¶¡¶ ùø\033[m\n" + " ¡s¡s¡s¡s¡s¡s¡s¡s \033[33m" + "¢x\033[m ¢ª¢i¢i¢i¢i¢« ùø\n" + " \033[33mùó" + "¡X¡X\033[m ¢« ¡X¡Ï\033[m"); + } else if (clsflag) { + showtitle("¬ÝªO¦Cªí", BBSName); + prints("[¡ö]¥D¿ï³æ [¡÷]¾\\Ū [¡ô¡õ]¿ï¾Ü [y]¸ü¤J [S]±Æ§Ç [/]·j´M " + "[TAB]¤åºK¡E¬ÝªO [h]¨D§U\n" + "\033[7m%-20s Ãþ§O Âà«H%-31s§ë²¼ ªO ¥D \033[m", + newflag ? "Á`¼Æ ¥¼Åª ¬Ý ªO" : " ½s¸¹ ¬Ý ªO", + " ¤¤ ¤å ±Ô z"); + move(b_lines, 0); + brdlist_foot(); + } + + if(brdnum > 0) { + boardstat_t *ptr; + static char *color[8]={"","\033[32m", + "\033[33m","\033[36m","\033[34m","\033[1m", + "\033[1;32m","\033[1;33m"}; + static char *unread[2]={"\33[37m \033[m","\033[1;31m£¾\033[m"}; + + while(++myrow < b_lines) { + move(myrow, 0); + clrtoeol(); + if(head < brdnum) { + ptr = &nbrd[head++]; + if(class_bid == 1) + prints(" "); + if(!newflag) { + prints("%5d%c%s", head, + !(ptr->bh->brdattr & BRD_HIDE) ? ' ': + (ptr->bh->brdattr & BRD_POSTMASK) ? ')' : '-', + (ptr->myattr & BRD_TAG) ? "D " : + (ptr->myattr & BRD_ZAP) ? "- " : + (ptr->bh->brdattr & BRD_GROUPBOARD) ? " " : + unread[ptr->myattr&BRD_UNREAD]); + } else if(ptr->myattr&BRD_ZAP) { + ptr->myattr &= ~BRD_UNREAD; + prints(" ¡ß ¡ß"); + } else { + if(newflag) { + if((ptr->bh->brdattr & BRD_GROUPBOARD)) + prints(" "); + else + prints("%6d%s", (int)(*(ptr->total)), + unread[ptr->myattr&BRD_UNREAD]); + } + } + if(class_bid != 1) { + prints("%s%-13s\033[m%s%5.5s\033[0;37m%2.2s\033[m" + "%-35.35s%c %.13s", + (ptr->myattr & BRD_FAV)?"\033[1;36m":"", + ptr->bh->brdname, + color[(unsigned int) + (ptr->bh->title[1] + ptr->bh->title[2] + + ptr->bh->title[3] + ptr->bh->title[0]) & 07], + ptr->bh->title, ptr->bh->title+5, ptr->bh->title+7, + (ptr->bh->brdattr & BRD_BAD) ? 'X' : + " ARBCDEFGHI"[ptr->bh->bvote], + ptr->bh->BM); + refresh(); + } else { + prints("%-40.40s %.13s", ptr->bh->title + 7, ptr->bh->BM); + } + } + clrtoeol(); + } + } +} + +static char *choosebrdhelp[] = { + "\0¬ÝªO¿ï³æ»²§U»¡©ú", + "\01°ò¥»«ü¥O", + "(p)(¡ô)/(n)(¡õ)¤W¤@ӬݪO / ¤U¤@ӬݪO", + "(P)(^B)(PgUp) ¤W¤@¶¬ÝªO", + "(N)(^F)(PgDn) ¤U¤@¶¬ÝªO", + "($)/(s)/(/) ³Ì«á¤@ӬݪO / ·j´M¬ÝªO / ¥H¤¤¤å·j´M¬ÝªOÃöÁä¦r", + "(¼Æ¦r) ¸õ¦Ü¸Ó¶µ¥Ø", + "\01¶i¶¥«ü¥O", + "(^W) °g¸ô¤F §Ú¦bþ¸Ì", + "(r)(¡÷)(Rtn) ¶i¤J¦h¥\\¯à¾\\Ū¿ï³æ", + "(q)(¡ö) ¦^¨ì¥D¿ï³æ", + "(z)(Z) q¾\\/¤Ïq¾\\¬ÝªO q¾\\/¤Ïq¾\\©Ò¦³¬ÝªO", + "(y) §Úªº³Ì·R/q¾\\¬ÝªO/¥X©Ò¦³¬ÝªO", + "(v/V) ³q³q¬Ý§¹/¥þ³¡¥¼Åª", + "(S) «ö·Ó¦r¥À/¤ÀÃþ±Æ§Ç", + "(t/^T/^A/^D) ¼Ð°O¬ÝªO/¨ú®ø©Ò¦³¼Ð°O/¤w¼Ð°Oªº¥[¤J§Úªº³Ì·R/¨ú®ø§Úªº³Ì·R", + "(m) §â¬ÝªO¥[¤J§Úªº³Ì·R", + "\01¤p²Õªø«ü¥O", + "(E/W/B) ³]©w¬ÝªO/³]©w¤p²Õ³Æ§Ñ/¶}·s¬ÝªO", + "(^P) ²¾°Ê¤w¼Ð°O¬ÝªO¨ì¦¹¤ÀÃþ", + NULL +}; + + +static void set_menu_BM(char *BM) { + if(HAS_PERM(PERM_ALLBOARD) || is_BM(BM)) { + currmode |= MODE_MENU; + cuser.userlevel |= PERM_SYSSUBOP; + } +} + +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int t_lines; +extern char *fn_notes; +static char *privateboard = +"\n\n\n\n ¹ï¤£°_ ¦¹ªO¥Ø«e¥uã¬ÝªO¦n¤Í¶i¤J ½Ð¥ý¦VªO¥D¥Ó½Ð¤J¹Ò³\\¥i"; +static void dozap(int num){ + boardstat_t *ptr; + ptr = &nbrd[num]; + ptr->myattr ^= BRD_ZAP; + if(ptr->bh->brdattr & BRD_NOZAP) ptr->myattr &= ~BRD_ZAP; + if(!(ptr->myattr & BRD_ZAP) ) check_newpost(ptr); + zapbuf[ptr->bid-1] = (ptr->myattr&BRD_ZAP?0:login_start_time); +} +static void choose_board(int newflag) { + static int num = 0; + boardstat_t *ptr; + int head = -1, ch = 0, currmodetmp, tmp,tmp1, bidtmp; + char keyword[13]=""; +#if HAVE_SEARCH_ALL + char genbuf[200]; +#endif + extern time_t board_visit_time; + + setutmpmode(newflag ? READNEW : READBRD); + brdnum = 0; + if(!cuser.userlevel) /* guest yank all boards */ + yank_flag = 2; + + do { + if(brdnum <= 0) { + load_boards(keyword); + if(brdnum <= 0) { + if(keyword[0]!=0) + { + mprints(b_lines-1,0,"¨S¦³¥ô¦ó¬ÝªO¼ÐÃD¦³¦¹ÃöÁä¦r " + "(ª©¥DÀ³ª`·N¬ÝªO¼ÐÃD©R¦W)"); + pressanykey(); + keyword[0]=0; + brdnum = -1; + continue; + } + if(yank_flag<2) + { + brdnum = -1; + yank_flag++; + continue; + } + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + if(m_newbrd(0) == -1) + break; + brdnum = -1; + continue; + } else + break; + } + head = -1; + } + + if(num < 0) + num = 0; + else if(num >= brdnum) + num = brdnum - 1; + + if(head < 0) { + if(newflag) { + tmp = num; + while(num < brdnum) { + ptr = &nbrd[num]; + if(ptr->myattr&BRD_UNREAD) + break; + num++; + } + if(num >= brdnum) + num = tmp; + } + head = (num / p_lines) * p_lines; + show_brdlist(head, 1, newflag); + } else if(num < head || num >= head + p_lines) { + head = (num / p_lines) * p_lines; + show_brdlist(head, 0, newflag); + } + if(class_bid == 1) + ch = cursor_key(7 + num - head, 10); + else + ch = cursor_key(3 + num - head, 0); + + switch(ch) { + case Ctrl('W'): + whereami(0,NULL,NULL); + head=-1; + break; + case 'e': + case KEY_LEFT: + case EOF: + ch = 'q'; + case 'q': + if(keyword[0]) + { + keyword[0]=0; + brdnum=-1; + ch=' '; + } + break; + case 'c': + show_brdlist(head, 1, newflag ^= 1); + break; + case KEY_PGUP: + case 'P': + case 'b': + case Ctrl('B'): + if(num) { + num -= p_lines; + break; + } + case KEY_END: + case '$': + num = brdnum - 1; + break; + case ' ': + case KEY_PGDN: + case 'N': + case Ctrl('F'): + if(num == brdnum - 1) + num = 0; + else + num += p_lines; + break; + case Ctrl('C'): + cal(); + show_brdlist(head, 1, newflag); + break; + case Ctrl('I'): + t_idle(); + show_brdlist(head, 1, newflag); + break; + case KEY_UP: + case 'p': + case 'k': + if (num-- <= 0) + num = brdnum - 1; + break; + case 't': + ptr = &nbrd[num]; + ptr->myattr ^= BRD_TAG; + favbuf[ptr->bid-1]=ptr->myattr; + head = 9999; + case KEY_DOWN: + case 'n': + case 'j': + if (++num < brdnum) + break; + case '0': + case KEY_HOME: + num = 0; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if((tmp = search_num(ch, brdnum)) >= 0) + num = tmp; + brdlist_foot(); + break; + case 'F': + case 'f': + if(class_bid && HAS_PERM(PERM_SYSOP)) + { + bcache[class_bid-1].firstchild[cuser.uflag&BRDSORT_FLAG?1:0] + =NULL; + brdnum = -1; + } + break; + case 'h': + show_help(choosebrdhelp); + show_brdlist(head, 1, newflag); + break; + case '/': + getdata_buf(b_lines-1,0,"½Ð¿é¤J¬ÝªO¤¤¤åÃöÁä¦r:",keyword, 12, DOECHO); + brdnum=-1; + break; + case 'S': + cuser.uflag ^= BRDSORT_FLAG; + brdnum = -1; + break; + case 'y': + if(class_bid==0) + yank_flag = (yank_flag+1)%3; + else + yank_flag = yank_flag%2+1; + brdnum = -1; + break; + case Ctrl('D'): + for(tmp = 0; tmp < numboards; tmp++) + { + if(favbuf[tmp] & BRD_TAG) + { + favbuf[tmp] &= ~BRD_FAV; + favbuf[tmp] &= ~BRD_TAG; + } + } + brdnum = -1; + break; + case Ctrl('A'): + for(tmp = 0; tmp < numboards; tmp++) + { + if(favbuf[tmp] & BRD_TAG) + { + favbuf[tmp] |= BRD_FAV; + favbuf[tmp] &= ~BRD_TAG; + } + } + brdnum = -1; + break; + case Ctrl('T'): + for(tmp = 0; tmp < numboards; tmp++) + favbuf[tmp] &= ~BRD_TAG; + brdnum = -1; + break; + case Ctrl('P'): + if(class_bid!=0 && + (HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU))) { + for(tmp = 0; tmp < numboards; tmp++) { + boardheader_t *bh=&bcache[tmp]; + if(!(favbuf[tmp]&BRD_TAG) || bh->gid==class_bid) + continue; + favbuf[tmp] &= ~BRD_TAG; + if(bh->gid != class_bid) + { + bh->gid = class_bid; + substitute_record(FN_BOARD, bh, + sizeof(boardheader_t), tmp+1); + reset_board(tmp+1); + log_usies("SetBoardGID", bh->brdname); + } + } + brdnum = -1; + } + break; + case 'm': + if(HAS_PERM(PERM_BASIC)) { + ptr = &nbrd[num]; + ptr->myattr ^= BRD_FAV; + favbuf[ptr->bid-1]=ptr->myattr; + head = 9999; + } + break; + case 'z': + if(HAS_PERM(PERM_BASIC)) { + dozap(num); + head = 9999; + } + break; + case 'Z': /* Ptt */ + if(HAS_PERM(PERM_BASIC)) { + for(tmp = 0; tmp < brdnum; tmp++) { + dozap(tmp); + } + head = 9999; + } + break; + case 'v': + case 'V': + ptr = &nbrd[num]; + brc_initial(ptr->bh->brdname); + if(ch == 'v') { + ptr->myattr &= ~BRD_UNREAD; + zapbuf[ptr->bid-1] = time((time_t *) &brc_list[0]); + } else + { + zapbuf[ptr->bid-1] = brc_list[0] = 1; + ptr->myattr |= BRD_UNREAD; + } + brc_num = brc_changed = 1; + brc_update(); + show_brdlist(head, 0, newflag); + break; + case 's': + if((tmp = search_board()) == -1) { + show_brdlist(head, 1, newflag); + break; + } + num = tmp; + case 'E': + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + ptr = &nbrd[num]; + move(1,1); + clrtobot(); + m_mod_board(ptr->bh->brdname); + brdnum = -1; + } + break; + case 'R': + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + m_newbrd(1); + brdnum = -1; + } + break; + case 'B': + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + m_newbrd(0); + brdnum = -1; + } + break; + case 'W': + if(class_bid > 0 && + (HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU))) { + b_note_edit_bname(class_bid); + brdnum = -1; + } + break; + case KEY_RIGHT: + case '\n': + case '\r': + case 'r': + { + char buf[STRLEN]; + + ptr = &nbrd[num]; + + if(!(ptr->bh->brdattr & BRD_GROUPBOARD)) { /* «Dsub class */ + if(!(ptr->bh->brdattr & BRD_HIDE) || + (ptr->bh->brdattr & BRD_POSTMASK)) { + brc_initial(ptr->bh->brdname); + + if(newflag) { + setbdir(buf, currboard); + tmp = unread_position(buf, ptr); + head = tmp - t_lines / 2; + getkeep(buf, head > 1 ? head : 1, tmp + 1); + } + board_visit_time = zapbuf[ptr->bid-1]; + if(!(ptr->myattr&BRD_ZAP)) + time((time_t *) &zapbuf[ptr->bid-1]); + Read(); + check_newpost(ptr); + head = -1; + setutmpmode(newflag ? READNEW : READBRD); + } else { + setbfile(buf, ptr->bh->brdname, FN_APPLICATION); + if(more(buf,YEA)==-1) { + move(1,0); + clrtobot(); + outs(privateboard); + pressanykey(); + } + head = -1; + } + } else { /* sub class */ + move(12,1); + bidtmp = class_bid; + currmodetmp =currmode; + tmp1=num; + num=0; + class_bid = ptr->bid; + if (!(currmode & MODE_MENU))/*¦pªGÁÙ¨S¦³¤p²ÕªøÅv */ + set_menu_BM(ptr->bh->BM); + + if(time(NULL) < ptr->bh->bupdate) { + setbfile(buf, ptr->bh->brdname, fn_notes); + if(more(buf, NA) != -1) + pressanykey(); + } + tmp=currutmp->brc_id; + currutmp->brc_id=ptr->bid; + choose_board(0); + currmode = currmodetmp; /* Â÷¶}ª©ª©«á´N§âÅv®³±¼³á */ + num=tmp1; + class_bid = bidtmp; + currutmp->brc_id=tmp; + brdnum = -1; + } + } + } + } while(ch != 'q'); + save_brdbuf(); +} + +int root_board() { + class_bid = 1; + yank_flag = 1; + choose_board(0); + return 0; +} + +int Boards() { + class_bid = 0; + yank_flag = 0; + choose_board(0); + return 0; +} + + +int New() { + int mode0 = currutmp->mode; + int stat0 = currstat; + + class_bid = 0; + choose_board(1); + currutmp->mode = mode0; + currstat = stat0; + return 0; +} + +/* +int v_favorite(){ + char fname[256]; + char inbuf[2048]; + FILE* fp; + int nGroup; + char* strtmp; + + setuserfile(fname,str_favorite); + + if (!(fp=fopen(fname,"r"))) + return -1; + move(0,0); + clrtobot(); + fgets(inbuf,sizeof(inbuf),fp); + nGroup=atoi(inbuf); + + currutmp->nGroup=0; + currutmp->ninRoot=0; + + while(nGroup!=currutmp->nGroup+1){ + fgets(inbuf,sizeof(inbuf),fp); + prints("%s\n",strtmp=strtok(inbuf," \n")); + strcpy(currutmp->gfavorite[currutmp->nGroup++],strtmp); + while((strtmp=strtok(NULL, " \n"))){ + prints(" %s %d\n",strtmp,getbnum(strtmp)); + } + currutmp->nGroup++; + } + prints("+++%d+++\n",currutmp->nGroup); + + fgets(inbuf,sizeof(inbuf),fp); + + for(strtmp=strtok(inbuf, " \n");strtmp;strtmp=strtok(NULL, " \n")){ + if (strtmp[0]!='#') + prints("*** %s %d\n",strtmp, getbnum(strtmp)); + else + prints("*** %s %d\n",strtmp+1, -1); + currutmp->ninRoot++; + } + + fclose(fp); + pressanykey(); + return 0; +} +*/ diff --git a/mbbsd/cache.c b/mbbsd/cache.c new file mode 100644 index 00000000..73f8ac5b --- /dev/null +++ b/mbbsd/cache.c @@ -0,0 +1,1053 @@ +/* $Id: cache.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> + +#ifdef __FreeBSD__ +#include <machine/param.h> +#endif + +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +#ifndef __FreeBSD__ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ + unsigned short int *array; /* array for GETALL, SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif + +int fcache_semid; + +/* the reason for "safe_sleep" is that we may call sleep during + SIGALRM handler routine, while SIGALRM is blocked. + if we use the original sleep, we'll never wake up. */ +unsigned int safe_sleep(unsigned int seconds) { + /* jochang sleep¦³°ÝÃD®É¥Î*/ + sigset_t set,oldset; + + sigemptyset(&set); + sigprocmask(SIG_BLOCK, &set, &oldset); + if(sigismember(&oldset, SIGALRM)) { + unsigned long retv; +#if !defined(_BBS_UTIL_C_) + log_usies("SAFE_SLEEP ", "avoid hang"); +#endif + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_UNBLOCK,&set,NULL); + retv=sleep(seconds); + sigprocmask(SIG_BLOCK,&set,NULL); + return retv; + } + return sleep(seconds); +} + +#if defined(_BBS_UTIL_C_) +static void setapath(char *buf, char *boardname) { + sprintf(buf, "man/boards/%s", boardname); +} + +static char *str_dotdir = ".DIR"; + +static void setadir(char *buf, char *path) { + sprintf(buf, "%s/%s", path, str_dotdir); +} +#endif + +static void attach_err(int shmkey, char *name) { + fprintf(stderr, "[%s error] key = %x\n", name, shmkey); + fprintf(stderr, "errno = %d: %s\n", errno, strerror(errno)); + exit(1); +} + +static void *attach_shm(int shmkey, int shmsize) { + void *shmptr; + int shmid; + + char *empty_addr; + /* set up one page in-accessible -- jochang */ + { + int fd = open("/dev/zero",O_RDONLY); + int size = ((shmsize + 4095) / 4096) * 4096; + + munmap( + (empty_addr=mmap(0,4096+size,PROT_NONE,MAP_PRIVATE,fd,0))+4096 + ,size); + + close(fd); + } + + shmid = shmget(shmkey, shmsize, 0); + if(shmid < 0) { + shmid = shmget(shmkey, shmsize, IPC_CREAT | 0600); + if(shmid < 0) + attach_err(shmkey, "shmget"); + shmptr = (void *)shmat(shmid, NULL, 0); + if(shmptr == (void *)-1) + attach_err(shmkey, "shmat"); + } else { + shmptr = (void *)shmat(shmid, NULL, 0); + if(shmptr == (void *)-1) + attach_err(shmkey, "shmat"); + } + + /* unmap the page -- jochang */ + { + munmap(empty_addr,4096); + } + return shmptr; +} + + +#define SEM_FLG 0600 /* semaphore mode */ + +/* ----------------------------------------------------- */ +/* semaphore : for critical section */ +/* ----------------------------------------------------- */ +void sem_init(int semkey,int *semid) { + union semun s; + + s.val=1; + *semid = semget(semkey, 1, 0); + if(*semid == -1) { + *semid = semget(semkey, 1, IPC_CREAT | SEM_FLG); + if(*semid == -1) + attach_err(semkey, "semget"); + semctl(*semid, 0, SETVAL, s); + } +} + +void sem_lock(int op,int semid) { + struct sembuf sops; + + sops.sem_num = 0; + sops.sem_flg = SEM_UNDO; + sops.sem_op = op; + semop(semid, &sops, 1); +} + +/* uhash *******************************************/ +/* the design is this: + we use another stand-alone program to create and load data into the hash. + (that program could be run in rc-scripts or something like that) + after loading completes, the stand-alone program sets loaded to 1 and exits. + + the bbs exits if it can't attach to the shared memory or + the hash is not loaded yet. +*/ +uhash_t *uhash; + +/* attach_uhash should be called before using uhash */ +void attach_uhash() { + uhash = attach_shm(UHASH_KEY, sizeof(*uhash)); + if(!uhash->loaded) /* assume fresh shared memory is zeroed */ + exit(1); +} + +void add_to_uhash(int n, char *id) { + int *p, h = StringHash(id); + strcpy(uhash->userid[n], id); + + p = &(uhash->hash_head[h]); + + while(*p != -1) + p = &(uhash->next_in_hash[*p]); + + uhash->next_in_hash[*p = n] = -1; +} + +/* note: after remove_from_uhash(), you should add_to_uhash() + (likely with a different name) */ +void remove_from_uhash(int n) { + int h = StringHash(uhash->userid[n]); + int *p = &(uhash->hash_head[h]); + + while(*p != -1 && *p != n) + p = &(uhash->next_in_hash[*p]); + if(*p == n) + *p = uhash->next_in_hash[n]; +} + +int setumoney(int uid, int money) { + uhash->money[uid-1]=money; + passwd_update_money(uid); + return uhash->money[uid-1]; +} + +int deumoney(int uid, int money) { + if(money<0 && uhash->money[uid-1]<-money) + return setumoney(uid,0); + else + return setumoney(uid,uhash->money[uid-1]+money); +} +int demoney(int money) { + extern int usernum; + return deumoney(usernum,money); +} +int moneyof(int uid){ /* ptt §ï¶iª÷¿ú³B²z®Ä²v */ + return uhash->money[uid-1]; +} +int searchuser(char *userid) { + int h,p; + + h = StringHash(userid); + p = uhash->hash_head[h]; + + while(p != -1) { + if(strcasecmp(uhash->userid[p],userid) == 0) { + strcpy(userid,uhash->userid[p]); + return p + 1; + } + p = uhash->next_in_hash[p]; + } + return 0; +} + +#if !defined(_BBS_UTIL_C_) +extern userec_t xuser; + +int getuser(char *userid) { + int uid; + + if((uid = searchuser(userid))) + passwd_query(uid, &xuser); + return uid; +} + +char *getuserid(int num) { + if(--num >= 0 && num < MAX_USERS) + return ((char *) uhash->userid[num]); + return NULL; +} + +void setuserid(int num, char *userid) { + if(num > 0 && num <= MAX_USERS) { + if(num > uhash->number) + uhash->number = num; + else + remove_from_uhash(num-1); + add_to_uhash(num-1,userid); + } +} + +/* 0 ==> §ä¹L´Á±b¸¹ */ +/* 1 ==> «Ø¥ß·s±b¸¹ */ +/* should do it by searching "" in the hash */ +int searchnewuser(int mode) { + register int i, num; + + num = uhash->number; + i = 0; + + /* ¬°¤°»ò³oÃ䤣¥Î hash table ¥h§ä¦Ón¥Î linear search? */ + while(i < num) { + if(!uhash->userid[i++][0]) + return i; + } + if(mode && (num < MAX_USERS)) + return num + 1; + return 0; +} + +char *u_namearray(char buf[][IDLEN + 1], int *pnum, char *tag) { + register struct uhash_t *reg_ushm = uhash; + register char *ptr, tmp; + register int n, total; + char tagbuf[STRLEN]; + int ch, ch2, num; + + if(*tag == '\0') { + *pnum = reg_ushm->number; + return reg_ushm->userid[0]; + } + for(n = 0; tag[n]; n++) + tagbuf[n] = chartoupper(tag[n]); + tagbuf[n] = '\0'; + ch = tagbuf[0]; + ch2 = ch - 'A' + 'a'; + total = reg_ushm->number; + for(n = num = 0; n < total; n++) { + ptr = reg_ushm->userid[n]; + tmp = *ptr; + if(tmp == ch || tmp == ch2) { + if(chkstr(tag, tagbuf, ptr)) + strcpy(buf[num++], ptr); + } + } + *pnum = num; + return buf[0]; +} +#endif + +/*-------------------------------------------------------*/ +/* .UTMP cache */ +/*-------------------------------------------------------*/ +struct utmpfile_t *utmpshm=NULL; + +void resolve_utmp() { + if(utmpshm == NULL) { + utmpshm = attach_shm(UTMPSHM_KEY, sizeof(*utmpshm)); + } +} + +userinfo_t *currutmp = NULL; + +#if !defined(_BBS_UTIL_C_) +extern unsigned int currstat; +extern userec_t cuser; + +void setutmpmode(int mode) { + if(currstat != mode) + currutmp->mode = currstat = mode; + + /* °lÂÜ¨Ï¥ÎªÌ */ + if(HAS_PERM(PERM_LOGUSER)) { + time_t now = time(NULL); + char msg[200]; + sprintf(msg, "%s setutmpmode to %s(%d) at %s", + cuser.userid, modestring(currutmp, 0), mode, Cdate(&now)); + log_user(msg); + } +} +#endif +/* +static int cmputmpuserid(userinfo_t ** i, userinfo_t ** j) { + return strcasecmp((*i)->userid, (*j)->userid); +} + +static int cmputmpmode(userinfo_t ** i, userinfo_t ** j) { + return (*i)->mode-(*j)->mode; +} + +static int cmputmpidle(userinfo_t ** i, userinfo_t ** j) { + return (*i)->lastact-(*j)->lastact; +} + +static int cmputmpfrom(userinfo_t ** i, userinfo_t ** j) { + return strcasecmp((*i)->from, (*j)->from); +} + +static int cmputmpfive(userinfo_t ** i, userinfo_t ** j) { + int type; + if((type=(*j)->five_win - (*i)->five_win)) + return type; + if((type=(*i)->five_lose - (*j)->five_lose)) + return type; + return (*i)->five_tie-(*j)->five_tie; +} +static int cmputmpsex(userinfo_t ** i, userinfo_t ** j) { + static int ladyfirst[]={1,0,1,0,1,0,3,3}; + return ladyfirst[(*i)->sex]-ladyfirst[(*j)->sex]; +} +static int cmputmppid(userinfo_t ** i, userinfo_t ** j) { + return (*i)->pid-(*j)->pid; +} +static int cmputmpuid(userinfo_t ** i, userinfo_t ** j) { + return (*i)->uid-(*j)->uid; +} +*/ +static int cmputmpuserid(const void *i, const void *j){ + return strcasecmp((*((userinfo_t**)i))->userid, (*((userinfo_t**)j))->userid); +} + +static int cmputmpmode(const void *i, const void *j){ + return (*((userinfo_t**)i))->mode-(*((userinfo_t**)j))->mode; +} + +static int cmputmpidle(const void *i, const void *j){ + return (*((userinfo_t**)i))->lastact-(*((userinfo_t**)j))->lastact; +} + +static int cmputmpfrom(const void *i, const void *j){ + return strcasecmp((*((userinfo_t**)i))->from, (*((userinfo_t**)j))->from); +} + +static int cmputmpfive(const void *i, const void *j){ + int type; + if((type=(*((userinfo_t**)j))->five_win - (*((userinfo_t**)i))->five_win)) + return type; + if((type=(*((userinfo_t**)i))->five_lose - (*((userinfo_t**)j))->five_lose)) + return type; + return (*((userinfo_t**)i))->five_tie-(*((userinfo_t**)j))->five_tie; +} + +static int cmputmpsex(const void *i, const void *j){ + static int ladyfirst[]={1,0,1,0,1,0,3,3}; + return ladyfirst[(*((userinfo_t**)i))->sex]-ladyfirst[(*((userinfo_t**)j))->sex]; +} +static int cmputmppid(const void *i, const void *j){ + return (*((userinfo_t**)i))->pid-(*((userinfo_t**)j))->pid; +} +static int cmputmpuid(const void *i, const void *j){ + return (*((userinfo_t**)i))->uid-(*((userinfo_t**)j))->uid; +} +void sort_utmp() +{ + time_t now=time(NULL); + int count, i, ns; + userinfo_t *uentp; + + if(now-utmpshm->uptime<60 && (now==utmpshm->uptime || utmpshm->busystate)) + return; /* lazy sort */ + utmpshm->busystate=1; + utmpshm->uptime = now; + ns=(utmpshm->currsorted?0:1); + + for(uentp = &utmpshm->uinfo[0], count=0, i=0; + i< USHM_SIZE; i++,uentp = &utmpshm->uinfo[i]) + if(uentp->pid) + { + utmpshm->sorted[ns][0][count++]= uentp; + } + utmpshm->number = count; + qsort(utmpshm->sorted[ns][0],count,sizeof(userinfo_t*),cmputmpuserid); + memcpy(utmpshm->sorted[ns][1],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][2],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][3],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][4],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][5],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][6],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][7],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + qsort(utmpshm->sorted[ns][1], count, sizeof(userinfo_t *), cmputmpmode ); + qsort(utmpshm->sorted[ns][2], count, sizeof(userinfo_t *), cmputmpidle ); + qsort(utmpshm->sorted[ns][3], count, sizeof(userinfo_t *), cmputmpfrom ); + qsort(utmpshm->sorted[ns][4], count, sizeof(userinfo_t *), cmputmpfive ); + qsort(utmpshm->sorted[ns][5], count, sizeof(userinfo_t *), cmputmpsex ); + qsort(utmpshm->sorted[ns][6], count, sizeof(userinfo_t *), cmputmpuid ); + qsort(utmpshm->sorted[ns][7], count, sizeof(userinfo_t *), cmputmppid ); + utmpshm->currsorted=ns; + utmpshm->busystate=0; +} +// Ptt:³oÃä¥[¤JhashÆ[©À §äªÅªºutmp +void getnewutmpent(userinfo_t *up) { + extern int errno; + register int i, p ; + register userinfo_t *uentp; + for(i = 0, p=StringHash(up->userid)%USHM_SIZE; i < USHM_SIZE; i++, p++) { + if(p==USHM_SIZE) p=0; + uentp = &(utmpshm->uinfo[p]); + if(!(uentp->pid)) { + memcpy(uentp, up, sizeof(userinfo_t)); + currutmp = uentp; + sort_utmp(); + return; + } + } + exit(1); +} + +int apply_ulist(int (*fptr)(userinfo_t *)) { + register userinfo_t *uentp; + register int i, state; + + for(i = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(uentp->pid && (PERM_HIDE(currutmp) || !PERM_HIDE(uentp))) + if((state = (*fptr) (uentp))) + return state; + } + return 0; +} + +userinfo_t *search_ulist(int uid) { + return search_ulistn(uid,1); +} + +#if !defined(_BBS_UTIL_C_) +extern int usernum; + +userinfo_t *search_ulist_pid(int pid) { + register int i=0, j, start = 0, end = utmpshm->number - 1; + register userinfo_t **ulist; + ulist=utmpshm->sorted[utmpshm->currsorted][7]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + j=pid-ulist[i]->pid; + if(!j) + { + return (userinfo_t *) (ulist[i]); + } + if(end==start) + { + break; + } + else if(i==start) + { + i=end; + start=end; + } + else if(j>0) start = i; + else end = i; + } + return 0; +} +userinfo_t *search_ulistn(int uid, int unum) { + register int i=0, j, start = 0, end = utmpshm->number - 1; + register userinfo_t **ulist; + ulist=utmpshm->sorted[utmpshm->currsorted][6]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + j= uid - ulist[i]->uid; + if(!j) + { + for(;i>0 && uid==ulist[i-1]->uid;i--);/* «ü¨ì²Ä¤@µ§ */ + if(uid==ulist[i+unum-1]->uid) + return (userinfo_t *) (ulist[i+unum-1]); + break; /* ¶W¹L½d³ò */ + } + if(end==start) + { + break; + } + else if(i==start) + { + i=end; + start=end; + } + else if(j>0) start = i; + else end = i; + } + return 0; +} + +int count_logins(int uid, int show) { + register int i=0, j, start = 0, end = utmpshm->number - 1, count; + register userinfo_t **ulist; + ulist=utmpshm->sorted[utmpshm->currsorted][6]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + j = uid-ulist[i]->uid; + if(!j) + { + for(;i>0 && uid==ulist[i-1]->uid;i--);/* «ü¨ì²Ä¤@µ§ */ + for(count=0;uid==ulist[i+count]->uid;count++) + { + if(show) + prints("(%d) ¥Ø«eª¬ºA¬°: %-17.16s(¨Ó¦Û %s)\n", + count+1, modestring(ulist[i+count], 0), + ulist[i+count]->from); + } + return count; + } + if(end==start) + { + break; + } + else if(i==start) + { + i=end; + start=end; + } + else if(j>0) start = i; + else end = i; + } + return 0; +} + + +void purge_utmp(userinfo_t *uentp) { + logout_friend_online(); + memset(uentp, 0, sizeof(userinfo_t)); +} + +#endif + +/*-------------------------------------------------------*/ +/* .BOARDS cache */ +/*-------------------------------------------------------*/ +extern char *fn_board; +extern int currbid; +bcache_t *brdshm; +boardheader_t *bcache; + +void touchdircache(int bid) +{ + int *i= (int *)&brdshm->dircache[bid - 1][0].filename[0]; + *i=0; +} + +void load_fileheader_cache(int bid, char *direct) +{ + int num=getbtotal(bid); + int n = num-DIRCACHESIZE+1; + if (brdshm->busystate!=1) + { + brdshm->busystate = 1; + get_records(direct, brdshm->dircache[bid - 1] , + sizeof(fileheader_t),n<1?1:n, DIRCACHESIZE); + brdshm->cachetotal[bid-1]=num; // cachetotal¥ý³] ¥H«á¦A§ï¤£¥Î¥þ³¡load + brdshm->busystate = 0; + } + else + {safe_sleep(1);} +} + +int get_fileheader_cache(int bid, char *direct, fileheader_t *headers, + int recbase, int nlines) +{ + int ret, n,num; + + num=getbtotal(bid); + + ret = num-recbase+1, + n = (num - DIRCACHESIZE+1); + + + if(brdshm->dircache[bid - 1][0].filename[0]=='\0') + load_fileheader_cache(bid, direct); + if (n<1) + n=recbase-1; + else + n=recbase-n; + if(n<0) n=0; + if (ret>nlines) ret=nlines; + memcpy(headers, &(brdshm->dircache[bid - 1][n]),sizeof(fileheader_t)*ret); + return ret; +} +static int cmpboardname(boardheader_t **brd, boardheader_t **tmp) { + return strcasecmp((*brd)->brdname, (*tmp)->brdname); +} +static int cmpboardclass(boardheader_t **brd, boardheader_t **tmp) { + return (strncmp((*brd)->title, (*tmp)->title, 4)<<8)+ + strcasecmp((*brd)->brdname, (*tmp)->brdname); +} +static void sort_bcache(){ + int i;/*critical section ¤£¯à³æ¿W©I¥s ©I¥sreload_bcache or reset_board */ + for(i=0;i<brdshm->number;i++) + { + brdshm->sorted[1][i]=brdshm->sorted[0][i]=&bcache[i]; + } + qsort(brdshm->sorted[0], brdshm->number, sizeof(boardheader_t *), + (QCAST)cmpboardname); + qsort(brdshm->sorted[1], brdshm->number, sizeof(boardheader_t *), + (QCAST)cmpboardclass); +} +static void reload_bcache() { + if(brdshm->busystate) { + safe_sleep(1); + } +#if !defined(_BBS_UTIL_C_) + else { + int fd,i; + + brdshm->busystate = 1; + if((fd = open(fn_board, O_RDONLY)) > 0) { + brdshm->number = + read(fd, bcache, MAX_BOARD * sizeof(boardheader_t)) / + sizeof(boardheader_t); + close(fd); + } + memset(brdshm->lastposttime, 0, MAX_BOARD * sizeof(time_t)); + /* µ¥©Ò¦³ boards ¸ê®Æ§ó·s«á¦A³]©w uptime */ + brdshm->uptime = brdshm->touchtime; + log_usies("CACHE", "reload bcache"); + sort_bcache(); + for(i=0;i<brdshm->number;i++) + { + bcache[i].firstchild[0]=NULL; + bcache[i].firstchild[1]=NULL; + } + brdshm->busystate = 0; + } +#endif +} + +int numboards = -1; + +void resolve_boards() { + if(brdshm == NULL) { + brdshm = attach_shm(BRDSHM_KEY, sizeof(*brdshm)); + if(brdshm->touchtime == 0) + brdshm->touchtime = 1; + bcache = brdshm->bcache; + } + + while(brdshm->uptime < brdshm->touchtime) + {reload_bcache();} + numboards = brdshm->number; +} + +void touch_boards() { + time(&(brdshm->touchtime)); + numboards = -1; + resolve_boards(); +} +void addbrd_touchcache() +{ + brdshm->number++; + numboards=brdshm->number; + reset_board(numboards); +} +#if !defined(_BBS_UTIL_C_) +void reset_board(int bid) { /* Ptt: ³o¼Ë´N¤£¥Î¦Ñ¬Otouch board¤F */ + int fd,i; + boardheader_t *bhdr; + + if(--bid < 0) + return; + if(brdshm->busystate) { + safe_sleep(1); + } else { + brdshm->busystate = 1; + bhdr = bcache; + bhdr += bid; + if((fd = open(fn_board, O_RDONLY)) > 0) { + lseek(fd, (off_t)(bid * sizeof(boardheader_t)), SEEK_SET); + read(fd, bhdr, sizeof(boardheader_t)); + close(fd); + } + sort_bcache(); + for(i=0;i<brdshm->number;i++) + { + bcache[i].firstchild[0]=NULL; + bcache[i].firstchild[1]=NULL; + } + brdshm->busystate = 0; + } +} + +int apply_boards(int (*func)(boardheader_t *)) { + register int i; + register boardheader_t *bhdr; + + for(i = 0, bhdr = bcache; i < numboards; i++, bhdr++) { + if(!(bhdr->brdattr & BRD_GROUPBOARD) && Ben_Perm(bhdr) && + (*func)(bhdr) == QUIT) + return QUIT; + } + return 0; +} +#endif + +boardheader_t *getbcache(int bid) { /* Ptt§ï¼g */ + return bcache + bid - 1; +} +int getbtotal(int bid) +{ + return brdshm->total[bid - 1]; +} +void setbtotal(int bid) { + boardheader_t *bh = getbcache(bid); + struct stat st; + char genbuf[256]; + int num,fd; + + sprintf(genbuf, "boards/%s/.DIR", bh->brdname); + + if((fd = open(genbuf, O_RDWR)) < 0) + return; /* .DIR±¾¤F */ + fstat(fd, &st); + num = st.st_size / sizeof(fileheader_t); + brdshm->total[bid - 1] = num; + + if(num>0) + { + lseek(fd, (off_t) (num - 1) * sizeof(fileheader_t), SEEK_SET); + if(read(fd, genbuf, FNLEN)>=0) + { + brdshm->lastposttime[bid - 1]=(time_t) atoi(&genbuf[2]); + } + } + else + brdshm->lastposttime[bid - 1] = 0; + close(fd); + if(num) + touchdircache(bid); +} + +void +touchbpostnum(int bid, int delta) { + int *total = &brdshm->total[bid - 1]; + if (*total) *total += delta; +} + + +int getbnum(char *bname) { + register int i=0, j, start = 0, end = brdshm->number - 1; + register boardheader_t **bhdr; + bhdr=brdshm->sorted[0]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + if(! (j=strcasecmp(bname,bhdr[i]->brdname))) + return (int) (bhdr[i] - bcache +1); + if(end==start) + { + break; + } + else if(i==start) + { + i=end; + start=end; + } + else if(j>0) start = i; + else end = i; + } + return 0; +} + +#if !defined(_BBS_UTIL_C_) +extern char *fn_water; +extern char *str_sysop; + +int haspostperm(char *bname) { + register int i; + char buf[200]; + + setbfile(buf, bname, fn_water); + if(belong(buf, cuser.userid)) + return 0; + + if(!strcasecmp(bname, DEFAULT_BOARD)) + return 1; + + if (!strcasecmp(bname, "PttLaw")) + return 1; + + if(!HAS_PERM(PERM_POST)) + return 0; + + if(!(i = getbnum(bname))) + return 0; + + /* ¯µ±K¬ÝªO¯S§O³B²z */ + if(bcache[i - 1].brdattr & BRD_HIDE) + return 1; + + i = bcache[i - 1].level; + + if (HAS_PERM(PERM_VIOLATELAW) && (i & PERM_VIOLATELAW)) + return 1; + else if (HAS_PERM(PERM_VIOLATELAW)) + return 0; + + return HAS_PERM(i & ~PERM_POST); +} +#endif + +/*-------------------------------------------------------*/ +/* PTT cache */ +/*-------------------------------------------------------*/ +/* cachefor °ÊºA¬Ýª© */ +struct pttcache_t *ptt; + +static void reload_pttcache() { + if(ptt->busystate) + safe_sleep(1); + else { /* jochang: temporary workaround */ + fileheader_t item, subitem; + char pbuf[256], buf[256], *chr; + FILE *fp, *fp1, *fp2; + int id, section = 0; + + ptt->busystate = 1; + ptt->max_film = 0; + bzero(ptt->notes, sizeof ptt->notes); + setapath(pbuf, "Note"); + setadir(buf, pbuf); + id = 0; + if((fp = fopen(buf, "r"))) { + while(fread(&item, sizeof(item), 1, fp)) { + if(item.title[3]=='<' && item.title[8]=='>') { + sprintf(buf,"%s/%s", pbuf, item.filename); + setadir(buf, buf); + if(!(fp1 = fopen(buf, "r"))) + continue; + ptt->next_refresh[section] = ptt->n_notes[section] = id; + section ++; + while(fread(&subitem, sizeof(subitem), 1, fp1)) { + sprintf(buf,"%s/%s/%s", pbuf, item.filename , + subitem.filename); + if(!(fp2=fopen(buf,"r"))) + continue; + fread(ptt->notes[id],sizeof(char), 200*11, fp2); + ptt->notes[id][200*11 - 1]=0; + id++; + fclose(fp2); + if(id >= MAX_MOVIE) + break; + } + fclose(fp1); + if(id >= MAX_MOVIE || section >= MAX_MOVIE_SECTION) + break; + } + } + fclose(fp); + } + ptt->next_refresh[section] = -1; + ptt->n_notes[section] = ptt->max_film = id-1; + ptt->max_history = ptt->max_film - 2; + if(ptt->max_history > MAX_HISTORY - 1) + ptt->max_history = MAX_HISTORY - 1; + if(ptt->max_history <0) ptt->max_history=0; + + fp = fopen("etc/today_is","r"); + if(fp) { + fgets(ptt->today_is,15,fp); + if((chr = strchr(ptt->today_is,'\n'))) + *chr = 0; + ptt->today_is[15] = 0; + fclose(fp); + } + + /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */ + + ptt->uptime = ptt->touchtime ; +#if !defined(_BBS_UTIL_C_) + log_usies("CACHE", "reload pttcache"); +#endif + ptt->busystate = 0; + } +} + +void resolve_garbage() { + int count=0; + + if(ptt == NULL) { + ptt = attach_shm(PTTSHM_KEY, sizeof(*ptt)); + if(ptt->touchtime == 0) + ptt->touchtime = 1; + } + while(ptt->uptime < ptt->touchtime) { /* ¤£¥Îwhileµ¥ */ + reload_pttcache(); + if(count ++ > 10 && ptt->busystate) { +/* Ptt: ³oÃä·|¦³°ÝÃD load¶W¹L10 ¬í·|©Ò¦³¶iloopªºprocess³£Åý busystate = 0 + ³o¼Ë·|©Ò¦³prcosee³£·|¦bload °ÊºA¬ÝªO ·|³y¦¨load¤j¼W + ¦ý¨S¦³¥Î³oÓfunctionªº¸Ü ¸U¤@load passwdÀɪºprocess¦º¤F ¤S¨S¦³¤H§â¥L + ¸Ñ¶} ¦P¼Ëªº°ÝÃDµo¥Í¦breload passwd +*/ + ptt->busystate = 0; +#ifndef _BBS_UTIL_C_ + log_usies("CACHE", "refork Ptt dead lock"); +#endif + } + } +} + +/*-------------------------------------------------------*/ +/* PTT's cache */ +/*-------------------------------------------------------*/ +/* cachefor from host »P³Ì¦h¤W½u¤H¼Æ */ +struct fromcache_t *fcache; + +static void reload_fcache() { + if(fcache->busystate) + safe_sleep(1); + else { + FILE *fp; + + fcache->busystate = 1; + bzero(fcache->domain, sizeof fcache->domain); + if((fp = fopen("etc/domain_name_query","r"))) { + char buf[256],*po; + + fcache->top=0; + while(fgets(buf, sizeof(buf),fp)) { + if(buf[0] && buf[0] != '#' && buf[0] != ' ' && + buf[0] != '\n') { + sscanf(buf,"%s",fcache->domain[fcache->top]); + po = buf + strlen(fcache->domain[fcache->top]); + while(*po == ' ') + po++; + strncpy(fcache->replace[fcache->top],po,49); + fcache->replace[fcache->top] + [strlen(fcache->replace[fcache->top])-1] = 0; + (fcache->top)++; + if(fcache->top == MAX_FROM) + break; + } + } + } + + fcache->max_user=0; + + /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */ + fcache->uptime = fcache->touchtime; +#if !defined(_BBS_UTIL_C_) + log_usies("CACHE", "reload fcache"); +#endif + fcache->busystate = 0; + } +} + +void resolve_fcache() { + if(fcache == NULL) { + fcache = attach_shm(FROMSHM_KEY, sizeof(*fcache)); + if(fcache->touchtime == 0) + fcache->touchtime = 1; + } + while(fcache->uptime < fcache->touchtime) + reload_fcache(); +} + +extern time_t login_start_time; +extern char *fn_visable; +FILE *DEBUG = NULL; + +void hbflreload(int bid) +{ + int hbfl[MAX_FRIEND + 1], i, num, uid; + char buf[128]; + FILE *fp; + + memset(hbfl, 0, sizeof(hbfl)); + setbfile(buf, bcache[bid-1].brdname, fn_visable); + if( (fp = fopen(buf, "r")) != NULL ){ + for( num = 1 ; num <= MAX_FRIEND ; ++num ){ + if( fgets(buf, sizeof(buf), fp) == NULL ) + break; + for( i = 0 ; buf[i] != 0 ; ++i ) + if( buf[i] == ' ' ){ + buf[i] = 0; + break; + } + if( strcasecmp("guest", buf) == 0 || + (uid = searchuser(buf)) == 0 ) { + --num; + continue; + } + hbfl[num] = uid; + } + fclose(fp); + } + hbfl[0] = time(NULL); + memcpy(uhash->hbfl[bid], hbfl, sizeof(hbfl)); +} + +int hbflcheck(int bid, int uid) +{ + int i; + + if( uhash->hbfl[bid][0] < login_start_time - HBFLexpire ) + hbflreload(bid); + for( i = 1 ; uhash->hbfl[bid][i] != 0 && i <= MAX_FRIEND ; ++i ){ + if( uhash->hbfl[bid][i] == uid ) + return 0; + } + return 1; +} diff --git a/mbbsd/cal.c b/mbbsd/cal.c new file mode 100644 index 00000000..680ee9d6 --- /dev/null +++ b/mbbsd/cal.c @@ -0,0 +1,512 @@ +/* $Id: cal.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "perm.h" +#include "proto.h" + +extern struct utmpfile_t *utmpshm; +extern int usernum; + +/* ¨¾°ô Multi play */ +static int count_multiplay(int unmode) { + register int i, j; + register userinfo_t *uentp; + extern struct utmpfile_t *utmpshm; + + for(i = j = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(uentp->uid == usernum) + if(uentp->lockmode == unmode) + j++; + } + return j; +} + +extern userinfo_t *currutmp; +extern char *ModeTypeTable[]; + +int lockutmpmode(int unmode, int state) { + int errorno = 0; + + if(currutmp->lockmode) + errorno = 1; + else if(count_multiplay(unmode)) + errorno = 2; + + if(errorno && !(state == LOCK_THIS && errorno == LOCK_MULTI)) { + clear(); + move(10,20); + if(errorno == 1) + prints("½Ð¥ýÂ÷¶} %s ¤~¯à¦A %s ", + ModeTypeTable[currutmp->lockmode], + ModeTypeTable[unmode]); + else + prints("©êºp! ±z¤w¦³¨ä¥L½u¬Û¦PªºID¥¿¦b%s", + ModeTypeTable[unmode]); + pressanykey(); + return errorno; + } + + setutmpmode(unmode); + currutmp->lockmode = unmode; + return 0; +} + +int unlockutmpmode() { + currutmp->lockmode = 0; + return 0; +} + +extern userec_t cuser; +extern userec_t xuser; + +/* ¨Ï¥Î¿úªº¨ç¼Æ */ +#define VICE_NEW "vice.new" + +/* Heat:µo²¼ */ +int vice(int money, char* item) { + char buf[128]; + unsigned int viceserial=(currutmp->lastact%1000000)*100+rand()%100; + FILE *fp; + demoney(-money); + sprintf(buf, BBSHOME"/home/%c/%s/%s", + cuser.userid[0], cuser.userid, VICE_NEW); + fp = fopen(buf, "a"); + if(!fp ) + {return 0;} + + fprintf(fp, "%08d\n", viceserial); + fclose(fp); + sprintf(buf, "%s ªá¤F%d$ ½s¸¹[%08d]",item, money, viceserial); + mail_id(cuser.userid, buf, "etc/vice.txt", "Ptt¸gÀÙ³¡"); + return 0; +} + +#define lockreturn(unmode, state) if(lockutmpmode(unmode, state)) return +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 +#define lockbreak(unmode, state) if(lockutmpmode(unmode, state)) break +#define SONGBOOK "etc/SONGBOOK" +#define OSONGPATH "etc/SONGO" +extern char trans_buffer[]; +extern char save_title[]; + +static int osong(char *defaultid) { + char destid[IDLEN + 1],buf[200],genbuf[200],filename[256],say[51]; + char receiver[60],ano[2]; + FILE *fp,*fp1;// *fp2; + fileheader_t mail; + time_t now; + int nsongs; + + now = time(NULL); + strcpy(buf, Cdatedate(&now)); + + lockreturn0(OSONG, LOCK_MULTI); + + /* Jaky ¤@¤H¤@¤ÑÂI¤@º */ + if(!strcmp(buf, Cdatedate(&cuser.lastsong)) && !HAS_PERM(PERM_SYSOP)) { + move(22,0); + outs("§A¤µ¤Ñ¤w¸gÂI¹LÅo¡A©ú¤Ñ¦AÂI§a...."); + refresh(); + pressanykey(); + + unlockutmpmode(); + return 0; + } + + if(cuser.money < 200) { + move(22, 0); + outs("ÂIºqn200»Èò!...."); + refresh(); + pressanykey(); + unlockutmpmode(); + return 0; + } + move(12, 0); + clrtobot(); + sprintf(buf, "¿Ë·Rªº %s Åwªï¨Ó¨ì¼Ú®á¦Û°ÊÂIºq¨t²Î\n", cuser.userid); + outs(buf); + trans_buffer[0] = 0; + if(!defaultid){ + getdata(13, 0, "nÂIµ¹½Ö©O:[¥iª½±µ«ö Enter ¥ý¿ïºq]", destid, IDLEN + 1, DOECHO); + while (!destid[0]){ + a_menu("ÂIºqºq¥»", SONGBOOK,0 ); + clear(); + getdata(13, 0, "nÂIµ¹½Ö©O:[¥i«ö Enter «·s¿ïºq]", destid, IDLEN + 1, DOECHO); + } + } + else + strcpy(destid,defaultid); + + /* Heat:ÂIºqªÌ°Î¦W¥\¯à */ + getdata(14,0, "n°Î¦W¶Ü?[y/n]:", ano, 2, DOECHO); + + if(!destid[0]) { + unlockutmpmode(); + return 0; + } + + getdata_str(14, 0, "·Qnn¹ï¥L(¦o)»¡..:", say, 51, DOECHO, "§Ú·R©p.."); + sprintf(save_title, "%s:%s", (ano[0]=='y')?"°Î¦WªÌ":cuser.userid, say); + getdata_str(16, 0, "±H¨ì½Öªº«H½c(¥i¥ÎE-mail)?", receiver, 45, + LCECHO, destid); + + + + if (!trans_buffer[0]){ + outs("\n±µµÛn¿ïºqÅo..¶i¤Jºq¥»¦n¦nªº¿ï¤@ººq§a..^o^"); + pressanykey(); + a_menu("ÂIºqºq¥»", SONGBOOK,0 ); + } + if(!trans_buffer[0] || strstr(trans_buffer, "home") || + strstr(trans_buffer, "boards") || !(fp = fopen(trans_buffer, "r"))) { + unlockutmpmode(); + return 0; + } + + strcpy(filename, OSONGPATH); + + stampfile(filename, &mail); + + unlink(filename); + + if(!(fp1 = fopen(filename, "w"))) { + fclose(fp); + unlockutmpmode(); + return 0; + } + + strcpy(mail.owner, "ÂIºq¾÷"); + sprintf(mail.title, "¡º %s ÂIµ¹ %s ", (ano[0]=='y')?"°Î¦WªÌ":cuser.userid, destid); + mail.savemode = 0; + + while(fgets(buf, 200, fp)) { + char *po; + if(!strncmp(buf, "¼ÐÃD: ", 6)) { + clear(); + move(10,10);prints("%s", buf); + pressanykey(); + fclose(fp); + unlockutmpmode(); + return 0; + } + while((po = strstr(buf, "<~Src~>"))) { + po[0] = 0; + sprintf(genbuf,"%s%s%s",buf,(ano[0]=='y')?"°Î¦WªÌ":cuser.userid,po+7); + strcpy(buf,genbuf); + } + while((po = strstr(buf, "<~Des~>"))) { + po[0] = 0; + sprintf(genbuf,"%s%s%s",buf,destid,po+7); + strcpy(buf,genbuf); + } + while((po = strstr(buf, "<~Say~>"))) { + po[0] = 0; + sprintf(genbuf,"%s%s%s",buf,say,po+7); + strcpy(buf,genbuf); + } + fputs(buf,fp1); + } + fclose(fp1); + fclose(fp); + +// do_append(OSONGMAIL "/.DIR", &mail2, sizeof(mail2)); + + if(do_append(OSONGPATH "/.DIR", &mail, sizeof(mail)) != -1) { + cuser.lastsong = time(NULL); + /* Jaky ¶W¹L 500 ººq´N¶}©l¬å */ + nsongs=get_num_records(OSONGPATH "/.DIR", sizeof(mail)); + if (nsongs > 500){ + delete_range(OSONGPATH "/.DIR", 1, nsongs-500); + } + /* §â²Ä¤@º®³±¼ */ + vice(200, "ÂIºq"); + } + sprintf(save_title, "%s:%s", (ano[0]=='y')?"°Î¦WªÌ":cuser.userid, say); + hold_mail(filename, destid); + + if(receiver[0]) { +#ifndef USE_BSMTP + bbs_sendmail(filename, save_title, receiver); +#else + bsmtp(filename, save_title, receiver,0); +#endif + } + clear(); + outs( + "\n\n ®¥³ß±zÂIºq§¹¦¨Åo..\n" + " ¤@¤p®É¤º°ÊºA¬ÝªO·|¦Û°Ê«·s§ó·s\n" + " ¤j®a´N¥i¥H¬Ý¨ì±zÂIªººqÅo\n\n" + " ÂIºq¦³¥ô¦ó°ÝÃD¥i¥H¨ìNoteªOªººëµØ°Ï§äµª®×\n" + " ¤]¥i¦bNoteªOºëµØ°Ï¬Ý¨ì¦Û¤vªºÂIºq°O¿ý\n" + " ¦³¥ô¦ó«O¶Qªº·N¨£¤]Åwªï¨ìNoteªO¯d¸Ü\n" + " Åý¿Ë¤ÁªºªO¥D¬°±zªA°È\n"); + pressanykey(); + sortsong(); + topsong(); + + unlockutmpmode(); + return 1; +} + +int ordersong() { + osong(NULL); + return 0; +} + +static int inmailbox(int m) { + passwd_query(usernum, &xuser); + cuser.exmailbox = xuser.exmailbox + m; + passwd_update(usernum, &cuser); + return cuser.exmailbox; +} + + +extern int b_lines; + +#if !HAVE_FREECLOAK +/* ªá¿ú¿ï³æ */ +int p_cloak() { + char buf[4]; + getdata(b_lines-1, 0, + currutmp->invisible ? "½T©wn²{¨?[y/N]" : "½T©wnÁô¨?[y/N]", + buf, 3, LCECHO); + if(buf[0] != 'y') + return 0; + if(cuser.money >= 19) { + vice(19, "cloak"); + currutmp->invisible %= 2; + outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); + refresh(); + safe_sleep(1); + } + return 0; +} +#endif + +int p_from() { + char ans[4]; + + getdata(b_lines-2, 0, "½T©wn§ï¬G¶m?[y/N]", ans, 3, LCECHO); + if(ans[0] != 'y') + return 0; + reload_money(); + if(cuser.money < 49) + return 0; + if(getdata_buf(b_lines-1, 0, "½Ð¿é¤J·s¬G¶m:", + currutmp->from, 17, DOECHO)) { + vice(49,"home"); + currutmp->from_alias=0; + } + return 0; +} + +int p_exmail() { + char ans[4],buf[200]; + int n; + + if(cuser.exmailbox >= MAX_EXKEEPMAIL) { + sprintf(buf,"®e¶q³Ì¦h¼W¥[ %d «Ê¡A¤£¯à¦A¶R¤F¡C", MAX_EXKEEPMAIL); + outs(buf); + refresh(); + return 0; + } + sprintf(buf,"±z´¿¼WÁÊ %d «Ê®e¶q¡AÁÙn¦A¶R¦h¤Ö?", + cuser.exmailbox); + + getdata_str(b_lines-2, 0, buf, ans, 3, LCECHO, "10"); + + n = atoi(ans); + if(!ans[0] || !n) + return 0; + if(n + cuser.exmailbox > MAX_EXKEEPMAIL) + n = MAX_EXKEEPMAIL - cuser.exmailbox; + reload_money(); + if(cuser.money < n * 1000) + return 0; + vice(n * 1000, "mail"); + inmailbox(n); + return 0; +} + +void mail_redenvelop(char* from, char* to, int money, char mode){ + char genbuf[200]; + fileheader_t fhdr; + time_t now; + FILE* fp; + sprintf(genbuf, "home/%c/%s", to[0], to); + stampfile(genbuf, &fhdr); + if (!(fp = fopen(genbuf, "w"))) + return; + now = time(NULL); + fprintf(fp, "§@ªÌ: %s\n" + "¼ÐÃD: ©Û°]¶iÄ_\n" + "®É¶¡: %s\n" + "\033[1;33m¿Ë·Rªº %s ¡G\n\n\033[m" + "\033[1;31m §Ú¥]µ¹§A¤@Ó %d ¤¸ªº¤j¬õ¥]³á ^_^\n\n" + " §»´±¡·N«¡A½Ð¯º¯Ç...... ^_^\033[m\n" + , from, ctime(&now), to, money); + fclose(fp); + sprintf(fhdr.title, "©Û°]¶iÄ_"); + strcpy(fhdr.owner, from); + + if (mode == 'y') + vedit(genbuf, NA, NULL); + sprintf(genbuf, "home/%c/%s/.DIR", to[0], to); + append_record(genbuf, &fhdr, sizeof(fhdr)); +} + +int p_give() { + int money; + char id[IDLEN + 1], genbuf[90]; + time_t now = time(0); + + move(1,0); + usercomplete("³o¦ì©¯¹B¨àªºid:", id); + if(!id[0] || !strcmp(cuser.userid,id) || + !getdata(2, 0, "nµ¹¦h¤Ö¿ú:", genbuf, 7, LCECHO)) + return 0; + money = atoi(genbuf); + reload_money(); + if(money > 0 && cuser.money >= money ) { + deumoney(searchuser(id), money); + demoney(-money); + now = time(NULL); + sprintf(genbuf,"%s\tµ¹%s\t%d\t%s", cuser.userid, id, money, + ctime(&now)); + log_file(FN_MONEY, genbuf); + genbuf[0] = 'n'; + getdata(3, 0, "n¦Û¦æ®Ñ¼g¬õ¥]³U¶Ü¡H[y/N]", genbuf, 2, LCECHO); + mail_redenvelop(cuser.userid, id, money, genbuf[0]); + } + return 0; +} + +int p_sysinfo() { + char buf[100]; + long int total,used; + float p; + + move(b_lines-1,0); + clrtoeol(); + cpuload(buf); + outs("CPU t²ü : "); + outs(buf); + + p = swapused(&total,&used); + sprintf(buf, " µêÀÀ°O¾ÐÅé: %.1f%%(¥þ³¡:%ldMB ¥Î±¼:%ldMB)\n", + p*100, total >> 20, used >> 20); + outs(buf); + pressanykey(); + return 0; +} + +/* ¤ppºâ¾÷ */ +static void ccount(float *a, float b, int cmode) { + switch(cmode) { + case 0: + case 1: + case 2: + *a += b; + break; + case 3: + *a -= b; + break; + case 4: + *a *= b; + break; + case 5: + *a /= b; + break; + } +} + +int cal() { + float a = 0; + char flo = 0, ch = 0; + char mode[6] = {' ','=','+','-','*','/'} , cmode = 0; + char buf[100] = "[ 0] [ ] ", b[20] = "0"; + + move(b_lines - 1, 0); + clrtoeol(); + outs(buf); + move(b_lines, 0); + clrtoeol(); + outs("\033[44m ¤ppºâ¾÷ \033[31;47m (0123456789+-*/=) " + "\033[30m¿é¤J \033[31m " + "(Q)\033[30m Â÷¶} \033[m"); + while(1) { + ch = igetch(); + switch(ch) { + case '\r': + ch = '='; + case '=': + case '+': + case '-': + case '*': + case '/': + ccount(&a, atof(b), cmode); + flo = 0; + b[0] = '0'; + b[1] = 0; + move(b_lines - 1, 0); + sprintf(buf, "[%13.2f] [%c] ", a, ch); + outs(buf); + break; + case '.': + if(!flo) + flo = 1; + else + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '0': + if(strlen(b) > 13) + break; + if(flo || b[0] != '0') + sprintf(b,"%s%c",b,ch); + else + b[0]=ch; + move(b_lines - 1, 0); + sprintf(buf, "[%13s] [%c]", b, mode[(int)cmode]); + outs(buf); + break; + case 'q': + return 0; + } + + switch(ch) { + case '=': + a = 0; + cmode = 0; + break; + case '+': + cmode = 2; + break; + case '-': + cmode = 3; + break; + case '*': + cmode = 4; + break; + case '/': + cmode = 5; + break; + } + } +} diff --git a/mbbsd/calendar.c b/mbbsd/calendar.c new file mode 100644 index 00000000..78ca46cf --- /dev/null +++ b/mbbsd/calendar.c @@ -0,0 +1,284 @@ +/* $Id: calendar.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "proto.h" +#include "modes.h" + +typedef struct event_t { + int year, month, day, days; + int color; + char *content; + struct event_t *next; +} event_t; + +static int MonthDay(int m, int leap) { + static int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + return leap && m == 2 ? 29 : day[m - 1]; +} + +static int IsLeap(int y) { + if(y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) + return 1; + else + return 0; +} + +static int Days(int y, int m, int d) { + int i, w; + + w = 1 + 365 * (y - 1) + + ((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400) + + d - 1; + for(i = 1; i < m; i++) + w += MonthDay(i, IsLeap(y)); + return w; +} + +static int ParseDate(char *date, event_t *t) { + char *y, *m, *d; + + y = strtok(date, "/"); + m = strtok(NULL, "/"); + d = strtok(NULL, ""); + if(!y || !m || !d) + return 1; + + t->year = atoi(y); + t->month = atoi(m); + t->day = atoi(d); + if(t->year < 1 || t->month < 1 || t->month > 12 || + t->day < 1 || t->day > 31) + return 1; + t->days = Days(t->year, t->month, t->day); + return 0; +} + +static int ParseColor(char *color) { + struct { + char *str; + int val; + } c[] = { + {"black", 0}, + {"red", 1}, + {"green", 2}, + {"yellow", 3}, + {"blue", 4}, + {"magenta", 5}, + {"cyan", 6}, + {"white", 7} + }; + int i; + + for(i = 0; i < sizeof(c) / sizeof(c[0]); i++) + if(strcasecmp(color, c[i].str) == 0) + return c[i].val; + return 7; +} + +static void InsertEvent(event_t *head, event_t *t) { + event_t *p; + + for(p = head; p->next && p->next->days < t->days; p = p->next); + t->next = p->next; + p->next = t; +} + +static void FreeEvent(event_t *e) { + event_t *n; + + while(e) { + n = e->next; + free(e); + e = n; + } +} + +extern userec_t cuser; + +static event_t *ReadEvent(int today) { + FILE *fp; + char buf[256]; + static event_t head; + + head.next = NULL; + setcalfile(buf, cuser.userid); + fp = fopen(buf, "r"); + if(fp) { + while(fgets(buf, sizeof(buf), fp)) { + char *date, *color, *content; + event_t *t; + + if(buf[0] == '#') + continue; + + date = strtok(buf, " \t\n"); + color = strtok(NULL, " \t\n"); + content = strtok(NULL, "\n"); + if(!date || !color || !content) + continue; + + t = malloc(sizeof(event_t)); + if(ParseDate(date, t) || t->days < today) { + free(t); + continue; + } + t->color = ParseColor(color) + 30; + for(; *content == ' ' || *content == '\t'; content++); + t->content = strdup(content); + InsertEvent(&head, t); + } + fclose(fp); + } + return head.next; +} + +static char **AllocCalBuffer(int line, int len) { + int i; + char **p; + + p = malloc(sizeof(char *) * line); + p[0] = malloc(sizeof(char) * line * len); + for(i = 1; i < line; i++) + p[i] = p[i - 1] + len; + return p; +} + +static void FreeCalBuffer(char **buf) { + free(buf[0]); + free(buf); +} + +#define CALENDAR_COLOR "\33[0;30;47m" +#define HEADER_COLOR "\33[1;44m" +#define HEADER_SUNDAY_COLOR "\33[31m" +#define HEADER_DAY_COLOR "\33[33m" + +static int GenerateCalendar(char **buf, int y, int m, int today, event_t *e) { + static char *week_str[7] = {"¤é", "¤@", "¤G", "¤T", "¥|", "¤", "¤»"}; + static char *month_color[12] = { + "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m", + "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m", + "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m" + }; + static char *month_str[12] = { + "¤@¤ë ", "¤G¤ë ", "¤T¤ë ", "¥|¤ë ", "¤¤ë ", "¤»¤ë ", + "¤C¤ë ", "¤K¤ë ", "¤E¤ë ", "¤Q¤ë ", "¤Q¤@¤ë", "¤Q¤G¤ë" + }; + + char *p, attr1[16], *attr2; + int i, d, w, line = 0, first_day = Days(y, m, 1); + + + /* week day banner */ + p = buf[line]; + p += sprintf(p, " %s%s%s%s", HEADER_COLOR, HEADER_SUNDAY_COLOR, + week_str[0], HEADER_DAY_COLOR); + for(i = 1; i < 7; i++) + p += sprintf(p, " %s", week_str[i]); + p += sprintf(p, "\33[m"); + + /* indent for first line */ + p = buf[++line]; + p += sprintf(p, " %s", CALENDAR_COLOR); + for(i = 0, w = first_day % 7; i < w; i++) + p += sprintf(p, " "); + + /* initial event */ + for(; e && e->days < first_day; e = e->next); + + d = MonthDay(m, IsLeap(y)); + for(i = 1; i <= d; i++, w = (w + 1) % 7) { + attr1[0] = 0; + attr2 = ""; + while(e && e->days == first_day + i - 1) { + sprintf(attr1, "\33[1;%dm", e->color); + attr2 = CALENDAR_COLOR; + e = e->next; + } + if(today == first_day + i - 1) { + strcpy(attr1, "\33[1;37;42m"); + attr2 = CALENDAR_COLOR; + } + p += sprintf(p, "%s%2d%s", attr1, i, attr2); + + if(w == 6) { + p += sprintf(p, "\33[m"); + p = buf[++line]; + /* show month */ + if(line >= 2 && line <= 4) + p += sprintf(p, "%s%2.2s\33[m %s", month_color[m - 1], + month_str[m - 1] + (line - 2) * 2, + CALENDAR_COLOR); + else if(i < d) + p += sprintf(p, " %s", CALENDAR_COLOR); + } else + *p++ = ' '; + } + + /* fill up the last line */ + if(w) { + for(w = 7 - w; w; w--) + p += sprintf(p, w == 1 ? " " : " "); + p += sprintf(p, "\33[m"); + } + return line + 1; +} + +int calendar() { + char **buf; + time_t t; + struct tm now; + int i, y, m, today, lines = 0; + event_t *head = NULL, *e = NULL; + + /* initialize date */ + time(&t); + memcpy(&now, localtime(&t), sizeof(struct tm)); + today = Days(now.tm_year + 1900, now.tm_mon + 1, now.tm_mday); + y = now.tm_year + 1900, m = now.tm_mon + 1; + + /* read event */ + head = e = ReadEvent(today); + + /* generate calendar */ + buf = AllocCalBuffer(22, 256); + for(i = 0; i < 22; i++) + sprintf(buf[i], "%24s", ""); + for(i = 0; i < 3; i++) { + lines += GenerateCalendar(buf + lines, y, m, today, e) + 1; + if(m == 12) + y++, m = 1; + else + m++; + } + + /* output */ + clear(); + outc('\n'); + for(i = 0; i < 22; i++) { + outs(buf[i]); + if(i == 0) { + prints("\t\33[1;37m²{¦b¬O %d.%02d.%02d %2d:%02d:%02d%cm\33[m", + now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, + (now.tm_hour == 0 || now.tm_hour == 12) ? + 12 : now.tm_hour % 12, now.tm_min, now.tm_sec, + now.tm_hour >= 12 ? 'p' : 'a'); + } else if(i >= 2 && e) { + prints("\t\33[1;37m(\33[%dm%3d\33[37m)\33[m %02d/%02d %s", + e->color, e->days - today, + e->month, e->day, e->content); + e = e->next; + } + outc('\n'); + } + FreeEvent(head); + FreeCalBuffer(buf); + pressanykey(); + return 0; +} diff --git a/mbbsd/card.c b/mbbsd/card.c new file mode 100644 index 00000000..cfa10b0c --- /dev/null +++ b/mbbsd/card.c @@ -0,0 +1,625 @@ +/* $Id: card.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" +extern int usernum; + +static int card_remain(int cards[]) { + int i, temp = 0; + + for(i = 0; i < 52; i++) + temp += cards[i]; + if(temp == 52) + return 1; + return 0; +} + +/* 0 Spare , 1 heart , ...3 dimon */ +static int card_flower(int card) { + return (card / 13); +} + +/* 1...13 */ +static int card_number(int card) { + return (card % 13 + 1); +} + +static int card_select(int *now) { + char *cc[2] = {"\033[44m \033[m", + "\033[1;33;41m ¡µ \033[m"}; + + while(1) { + move(20, 0); + clrtoeol(); + prints("%s%s%s%s%s", (*now == 0) ? cc[1] : cc[0], + (*now == 1) ? cc[1] : cc[0], + (*now == 2) ? cc[1] : cc[0], + (*now == 3) ? cc[1] : cc[0], + (*now == 4) ? cc[1] : cc[0]); + switch(egetch()) { + case 'Q': + case 'q': + return 0; + case '+': + case ',': + return 1; + case '\r': + return -1; + case KEY_LEFT: + *now = (*now + 4) % 5; + break; + case KEY_RIGHT: + *now = (*now + 1) % 5; + break; + case '1': + *now = 0; + break; + case '2': + *now = 1; + break; + case '3': + *now = 2; + break; + case '4': + *now = 3; + break; + case '5': + *now = 4; + break; + } + } +} + +static void card_display(int cline, int number, int flower, int show) { + int color = 31; + char *cn[13] = {"¢Ï", "¢±", "¢²", "¢³", "¢´", "¢µ", + "¢¶", "¢·", "¢¸", "10", "¢Ø", "¢ß", "¢Ù"}; + if(flower == 0 || flower == 3) + color = 36; + if((show < 0) && (cline > 1 && cline < 8)) + prints("¢x\033[1;33;42m¡°¡°¡°¡°\033[m¢x"); + else + switch(cline) { + case 1: + prints("¢~¢w¢w¢w¢w¢¡"); + break; + case 2: + prints("¢x\033[1;%dm%s\033[m ¢x", color, cn[number - 1]); + break; + case 3: + if(flower == 1) + prints("¢x\033[1;%dm¢¨¢©¢¨¢©\033[m¢x", color); + else + prints("¢x\033[1;%dm ¢¨¢© \033[m¢x", color); + break; + case 4: + if(flower == 1) + prints("¢x\033[1;%dm¢i¢i¢i¢i\033[m¢x", color); + else if (flower == 3) + prints("¢x\033[1;%dm¢©¢i¢i¢¨\033[m¢x", color); + else + prints("¢x\033[1;%dm¢¨¢i¢i¢©\033[m¢x", color); + break; + case 5: + if(flower == 0) + prints("¢x\033[1;%dm¢i¢i¢i¢i\033[m¢x", color); + else if (flower == 3) + prints("¢x\033[1;%dm¢i¢ª¢«¢i\033[m¢x", color); + else + prints("¢x\033[1;%dm¢ª¢i¢i¢«\033[m¢x", color); + break; + case 6: + if(flower == 0) + prints("¢x\033[1;%dm ¢¨¢© \033[m¢x", color); + else if (flower == 3) + prints("¢x\033[1;%dm¢ª¢¨¢©¢«\033[m¢x", color); + else + prints("¢x\033[1;%dm ¢ª¢« \033[m¢x", color); + break; + case 7: + prints("¢x \033[1;%dm%s\033[m¢x", color, cn[number - 1]); + break; + case 8: + prints("¢¢¢w¢w¢w¢w¢£"); + break; + } +} + +static void card_show(int cpu[], int c[], int me[], int m[]) { + int i, j; + + for(j = 0; j < 8; j++) { + move(2 + j, 0); + clrtoeol(); + for(i = 0; i < 5 && cpu[i] >= 0; i++) + card_display(j + 1, card_number(cpu[i]), + card_flower(cpu[i]), c[i]); + } + + for(j = 0; j < 8; j++) { + move(11 + j, 0); + clrtoeol(); + for(i = 0; i < 5 && me[i] >= 0; i++) + card_display(j + 1, card_number(me[i]), card_flower(me[i]), m[i]); + } +} +static void card_new(int cards[]) { + memset(cards, 0, sizeof(int)*52); +} + +static int card_give(int cards[]) { + int i, error; + for(error=0, i=rand()%52; cards[i] == 1 && error<52; error++, i=rand()%52); + if(error==52) card_new(cards); // Ptt:³oÃ䦳dead lock°ÝÃD + cards[i] = 1; + return i; +} + +static void card_start(char name[]) { + clear(); + stand_title(name); + move(1, 0); + prints(" \033[1;33;41m ¹q ¸£ \033[m"); + move(10, 0); + prints("\033[1;34;44m¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã" + "¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»\033[m"); + move(19, 0); + prints(" \033[1;37;42m ¦Û ¤v \033[m"); +} + +static int card_99_add(int i, int aom, int count) { + if (i == 4 || i == 5 || i == 11) + return count; + else if(i == 12) + return count + 20 * aom; + else if(i == 10) + return count + 10 * aom; + else if(i == 13) + return 99; + else + return count + i; +} + +static int card_99_cpu(int cpu[], int *count) { + int stop = -1; + int twenty = -1; + int ten = -1; + int kill = -1; + int temp, num[10]; + int other = -1; + int think = 99-(*count); + int i, j; + + for(i = 0; i < 10; i++) + num[i] = -1; + for(i = 0; i < 5; i++) { + temp = card_number(cpu[i]); + if(temp == 4 || temp == 5 || temp == 11) + stop = i; + else if(temp == 12) + twenty = i; + else if (temp == 10) + ten = i; + else if (temp == 13) + kill = i; + else { + other = i; + num[temp] = i; + } + } + for(j = 9; j > 0; j--) + if(num[j] >= 0 && j != 4 && j != 5 && think >= j) { + (*count) += j; + return num[j]; + } + if((think >= 20) && (twenty >= 0)) { + (*count) += 20; + return twenty; + } else if((think >= 10) && (ten >= 0)) { + (*count) += 10; + return ten; + } else if(stop >= 0) + return stop; + else if (kill >= 0) { + (*count) = 99; + return kill; + } else if(ten >= 0) { + (*count) -= 10; + return ten; + } else if(twenty >= 0) { + (*count) -= 20; + return twenty; + } else { + (*count) += card_number(cpu[0]); + return 0; + } +} + +int card_99() { + int i, j, turn; + int cpu[5], c[5], me[5], m[5]; + int cards[52]; + int count = 0; + char *ff[4] = {"\033[1;36m¶Â®ç", "\033[1;31m¬õ¤ß", + "\033[1;31m¤è¶ô", "\033[1;36m¶Âªá"}; + char *cn[13] = {"¢Ï", "¢±", "¢²", "¢³", "¢´", "¢µ", + "¢¶", "¢·", "¢¸", "10", "¢Ø", "¢ß", "¢Ù"}; + for(i = 0; i < 5; i++) + cpu[i] = c[i] = me[i] = m[i] = -1; + setutmpmode(CARD_99); + card_start("¤Ñªø¦a¤["); + card_new(cards); + for(i = 0; i < 5; i++) { + cpu[i] = card_give(cards); + me[i] = card_give(cards); + m[i] = 1; + } + card_show(cpu, c, me, m); + j = 0; + turn = 1; + move(21, 0); + clrtoeol(); + prints("[0]¥Ø«e %d , ´Ý %d ÂI\n", count, 99 - count); + prints("¥ª¥kÁä²¾°Ê´å¼Ð, [Enter]½T©w, [ + ]ªí¥[¤G¤Q(¥[¤Q), [Q/q]©ñ±ó¹CÀ¸"); + while(1) { + i = card_select(&j); + if(i == 0) /*©ñ±ó¹CÀ¸*/ + return 0; + count = card_99_add(card_number(me[j]), i, count); + move(21 + (turn / 2) % 2, 0); + clrtoeol(); + prints("[%d]±z¥X %s%s\033[m ¥Ø«e \033[1;31m%d/\033[34m%d\033[m ÂI", + turn, ff[card_flower(me[j])], + cn[card_number(me[j]) - 1], count, 99 - count); + me[j] = card_give(cards); + turn++; + if(count < 0) + count = 0; + card_show(cpu, c, me, m); + pressanykey(); + if(count > 99) { + move(22, 0); + clrtoeol(); + prints("[%d]µ²ªG..YOU LOSS..¥Ø«e \033[1;31m%d/\033[34m%d\033[m ÂI", + turn, count, 99 - count); + pressanykey(); + return 0; + } + i = card_99_cpu(cpu, &count); + move(21 + (turn / 2 + 1) % 2, 40); + prints("[%d]¹q¸£¥X %s%s\033[m ¥Ø«e \033[1;31m%d/\033[34m%d\033[m ÂI", + turn, ff[card_flower(cpu[i])], + cn[card_number(cpu[i]) - 1], count, 99 - count); + cpu[i] = card_give(cards); + turn++; + if(count < 0) + count = 0; + if(count > 99) { + move(22, 0); + clrtoeol(); + prints("[%d]µ²ªG..YOU WIN!..¥Ø«e \033[1;31m%d/\033[34m%d\033[m ÂI", + turn, count, 99 - count); + pressanykey(); + return 0; + } + if(!card_remain(cards)) { + card_new(cards); + for(i = 0; i < 5; i++) { + cards[me[i]] = 1; + cards[cpu[i]] = 1; + } + } + } +} + +#define PMONEY (10) +#define TEN_HALF (5) /*¤QÂI¥bªºTicket*/ +#define JACK (10) /*¶Â³Ç§JªºTicket*/ +#define NINE99 (99) /*99 ªºTicket*/ + +extern userec_t cuser; + +static int game_log(int type, int money) { + FILE *fp; + + if(money > 0) + demoney(money); + + switch(type) { + case JACK: + fp = fopen(BBSHOME "/etc/card/jack.log", "a"); + if(!fp) + return 0; + fprintf(fp, "%s win:%d\n", cuser.userid, money); + fclose(fp); + break; + case TEN_HALF: + fp = fopen(BBSHOME "/etc/card/tenhalf.log", "a"); + if(!fp) + return 0; + fprintf(fp, "%s win:%d\n", cuser.userid, money); + fclose(fp); + break; + } + return 0; +} + +static int card_double_ask() { + char buf[100], buf2[3]; + + sprintf(buf, "[ %s ]±z²{¦b¦@¦³ %d P¹ô, ²{¦bn¤À²Õ(¥[¦¬ %d ¤¸)¶Ü? [y/N]", + cuser.userid, cuser.money, JACK); + reload_money(); + if(cuser.money < JACK) + return 0; + getdata(20, 0, buf, buf2, 2, LCECHO); + if(buf2[0] == 'y' || buf2[0] == 'Y') + return 1; + return 0; +} + +static int card_ask() { + char buf[100], buf2[3]; + + sprintf(buf, "[ %s ]±z²{¦b¦@¦³ %d P¹ô, ÁÙn¥[µP¶Ü? [y/N]", + cuser.userid, cuser.money); + getdata(20, 0 , buf, buf2, 2, LCECHO); + if(buf2[0] == 'y' || buf2[0] == 'Y') + return 1; + return 0; +} + +static int card_alls_lower(int all[]) { + int i, count = 0; + for (i = 0; i < 5 && all[i] >= 0; i++) + if(card_number(all[i]) <= 10) + count += card_number(all[i]); + else + count += 10; + return count; +} + +static int card_alls_upper(int all[]) { + int i, count; + + count = card_alls_lower(all); + for (i = 0; i < 5 && all[i] >= 0 && count <= 11; i++) + if (card_number(all[i]) == 1) + count += 10; + return count; +} + +extern int b_lines; + +static int card_jack(int *db) { + int i, j; + int cpu[5], c[5], me[5], m[5]; + int cards[52]; + + for(i = 0;i<5;i++) + cpu[i] = c[i] = me[i] = m[i] = -1; + + if((*db)<0) { + card_new(cards); + card_start("¶Â³Ç§J"); + for(i = 0; i < 2; i++) { + cpu[i] = card_give(cards); + me[i] = card_give(cards); + } + } else { + card_start("¶Â³Ç§JDOUBLE°l¥[§½"); + cpu[0] = card_give(cards); + cpu[1] = card_give(cards); + me[0] = *db; + me[1] = card_give(cards); + } + c[1] = m[0] = m[1] = 1; + card_show(cpu, c, me, m); + if((card_number(me[0]) == 0 && card_number(me[1]) == 12) || + (card_number(me[1]) == 0 && card_number(me[0]) == 12)) { + if(card_flower(me[0]) == 0 && card_flower(me[1]) == 0) { + move(b_lines - 1, 0); + prints("«D±`¤£¿ùò! (¶W¯Å¶Â³Ç§J!! ¥[ %d ¤¸)", JACK * 10); + game_log(JACK, JACK * 10); + pressanykey(); + return 0; + } else { + move(b_lines - 1, 0); + prints("«Ü¤£¿ùò! (¶Â³Ç§J!! ¥[ %d ¤¸)", JACK * 5); + game_log(JACK, JACK * 5); + pressanykey(); + return 0; + } + } + if((card_number(cpu[0]) == 0 && card_number(cpu[1]) == 12) || + (card_number(cpu[1]) == 0 && card_number(cpu[0]) == 12)) { + c[0] = 1; + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("¼K¼K...¤£¦n·N«ä....¶Â³Ç§J!!"); + game_log(JACK, 0); + pressanykey(); + return 0; + } + if((*db < 0)&& (card_number(me[0]) == card_number(me[1])) && + (card_double_ask())) { + *db = me[1]; + me[1] = card_give(cards); + card_show(cpu, c, me, m); + } + i = 2; + while(i < 5 && card_ask()) { + me[i] = card_give(cards); + m[i] = 1; + card_show(cpu, c, me, m); + if(card_alls_lower(me) > 21) { + move(b_lines - 1, 0); + prints("¶ã¶ã...Ãz±¼¤F!"); + game_log(JACK, 0); + pressanykey(); + return 0; + } + i++; + if((i == 3) && (card_number(me[0]) == 7) && + (card_number(me[1]) == 7) && (card_number(me[2]) == 7)) { + move(b_lines - 1, 0); + prints("«Ü¤£¿ùò! (©¯¹B¤C¸¹!! ¥[ %d ¤¸)", JACK * 7); + game_log(JACK, JACK * 7); + pressanykey(); + return 0; + } + } + if(i == 5) {/*¹L¤Ãö*/ + move(b_lines - 1, 0); + prints("¦n¼F®`ò! ¹L¤Ãö¹Æ! ¥[P¹ô %d ¤¸!", 5 * JACK); + game_log(JACK, JACK * 5); + pressanykey(); + return 0; + } + j = 2; + c[0] = 1; + while((card_alls_upper(cpu) < card_alls_upper(me))|| + ((card_alls_upper(cpu) == card_alls_upper(me) && j < i ) && j < 5)) { + cpu[j] = card_give(cards); + c[j] = 1; + if(card_alls_lower(cpu) > 21) { + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("¨þ¨þ...¹q¸£Ãz±¼¤F! §AŤF! ¥i±oP¹ô %d ¤¸", JACK * 2); + game_log(JACK, JACK * 2); + pressanykey(); + return 0; + } + j++; + } + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("«z«z...¹q¸£Ä¹¤F!"); + game_log(JACK, 0); + pressanykey(); + return 0; +} + +int g_card_jack() { + int db; + char buf[3]; + + setutmpmode(JACK_CARD); + while(1) { + reload_money(); + if(cuser.money < JACK) { + outs("±zªº¿ú¤£°÷ò!¥h¦hµoªí¨Ç¦³·N¸qªº¤å³¹¦A¨Ó~~~"); + return 0; + } + getdata(b_lines - 1, 0, "½T©wnª±¶Â³Ç§J¶Ü ¤@¦¸¤Q¤¸ò?(Y/N)?[N]", + buf, 3, LCECHO); + if((*buf != 'y') && (*buf != 'Y')) + break; + else { + db = -1; + vice(PMONEY, "¶Â³Ç§J"); + card_jack(&db); + if(db >= 0) + card_jack(&db); + } + } + return 0; +} + +static int card_all(int all[]) { + int i, count = 0; + + for (i = 0; i < 5 && all[i] >= 0; i++) + if(card_number(all[i]) <= 10) + count += 2 * card_number(all[i]); + else + count += 1; + return count; +} + +static int ten_helf() { + int i, j; + int cpu[5], c[5], me[5], m[5]; + int cards[52]; + + card_start("¤QÂI¥b"); + card_new(cards); + for (i = 0; i < 5; i++) + cpu[i] = c[i] = me[i] = m[i] = -1; + + cpu[0] = card_give(cards); + me[0] = card_give(cards); + m[0] = 1; + card_show(cpu, c, me, m); + i = 1; + while(i < 5 && card_ask()) { + me[i] = card_give(cards); + m[i] = 1; + card_show(cpu, c, me, m); + if(card_all(me) > 21) { + move(b_lines - 1, 0); + prints("¶ã¶ã...Ãz±¼¤F!"); + game_log(TEN_HALF, 0); + pressanykey(); + return 0; + } + i++; + } + if(i == 5) {/*¹L¤Ãö*/ + move(b_lines - 1, 0); + prints("¦n¼F®`ò! ¹L¤Ãö¹Æ! ¥[P¹ô %d ¤¸!", 5 * PMONEY); + game_log(TEN_HALF, PMONEY * 5); + pressanykey(); + return 0; + } + j = 1; + c[0] = 1; + while( j<5 && ((card_all(cpu) < card_all(me)) || + (card_all(cpu) == card_all(me) && j < i))) { + cpu[j] = card_give(cards); + c[j] = 1; + if(card_all(cpu) > 21) { + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("¨þ¨þ...¹q¸£Ãz±¼¤F! §AŤF! ¥i±oP¹ô %d ¤¸", PMONEY * 2); + game_log(TEN_HALF, PMONEY * 2); + pressanykey(); + return 0; + } + j++; + } + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("«z«z...¹q¸£Ä¹¤F!"); + game_log(TEN_HALF, 0); + pressanykey(); + return 0; +} + +int g_ten_helf() { + char buf[3]; + + setutmpmode(TENHALF); + while(1) { + reload_money(); + if(cuser.money < TEN_HALF) { + outs("±zªº¿ú¤£°÷ò!¥h¦hµoªí¨Ç¦³·N¸qªº¤å³¹¦A¨Ó~~~"); + return 0; + } + getdata(b_lines - 1, 0, + "\033[1;37m½T©wnª±¤QÂI¥b¶Ü ¤@¦¸¤Q¤¸ò?(Y/N)?[N]\033[m", + buf, 3, LCECHO); + if(buf[0] != 'y' && buf[0] != 'Y') + return 0; + else { + vice(PMONEY, "¤QÂI¥b"); + ten_helf(); + } + } + return 0; +} diff --git a/mbbsd/chat.c b/mbbsd/chat.c new file mode 100644 index 00000000..f75383a8 --- /dev/null +++ b/mbbsd/chat.c @@ -0,0 +1,623 @@ +/* $Id: chat.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <ctype.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern userinfo_t *currutmp; +static int chatline; +static int stop_line; /* next line of bottom of message window area */ +static FILE *flog; + +static void printchatline(char *str) { + move(chatline, 0); + if(*str == '>' && !PERM_HIDE(currutmp)) + return; + else if(chatline < stop_line - 1) + chatline++; + else { + region_scroll_up(2, stop_line - 2); + move(stop_line - 2, 0); + } + outs(str); + outc('\n'); + outs("¡÷"); + + if(flog) + fprintf(flog, "%s\n", str); +} + +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +static void chat_clear() { + for(chatline = 2; chatline < stop_line; chatline++) { + move(chatline, 0); + clrtoeol(); + } + move(b_lines, 0); + clrtoeol(); + move(chatline = 2, 0); + outs("¡÷"); +} + +static void print_chatid(char *chatid) { + move(b_lines - 1, 0); + clrtoeol(); + outs(chatid); + outc(':'); +} + +static int chat_send(int fd, char *buf) { + int len; + char genbuf[200]; + + sprintf(genbuf, "%s\n", buf); + len = strlen(genbuf); + return (send(fd, genbuf, len, 0) == len); +} + +static char chatroom[IDLEN]; /* Chat-Room Name */ + +static int chat_recv(int fd, char *chatid) { + static char buf[512]; + static int bufstart = 0; + char genbuf[200]; + int c, len; + char *bptr; + + len = sizeof(buf) - bufstart - 1; + if((c = recv(fd, buf + bufstart, len, 0)) <= 0) + return -1; + c += bufstart; + + bptr = buf; + while(c > 0) { + len = strlen(bptr) + 1; + if(len > c && len < (sizeof buf / 2)) + break; + + if(*bptr == '/') { + switch(bptr[1]) { + case 'c': + chat_clear(); + break; + case 'n': + strncpy(chatid, bptr + 2, 8); + print_chatid(chatid); + clrtoeol(); + break; + case 'r': + strncpy(chatroom, bptr + 2, IDLEN - 1); + break; + case 't': + move(0, 0); + clrtoeol(); + sprintf(genbuf, "½Í¤Ñ«Ç [%s]", chatroom); + prints("\033[1;37;46m %-21s \033[45m ¸ÜÃD¡G%-48s\033[m", + genbuf, bptr + 2); + } + } else + printchatline(bptr); + + c -= len; + bptr += len; + } + + if(c > 0) { + strcpy(genbuf, bptr); + strcpy(buf, genbuf); + bufstart = len - 1; + } else + bufstart = 0; + return 0; +} + +extern userec_t cuser; + +static int printuserent(userinfo_t *uentp) { + static char uline[80]; + static int cnt; + char pline[30]; + + if(!uentp) { + if(cnt) + printchatline(uline); + bzero(uline, 80); + cnt = 0; + return 0; + } + if(!HAS_PERM(PERM_SYSOP) && !HAS_PERM(PERM_SEECLOAK) && uentp->invisible) + return 0; + + sprintf(pline, "%-13s%c%-10s ", uentp->userid, + uentp->invisible ? '#' : ' ', + modestring(uentp, 1)); + if(cnt < 2) + strcat(pline, "¢x"); + strcat(uline, pline); + if(++cnt == 3) { + printchatline(uline); + memset(uline, 0, 80); + cnt = 0; + } + return 0; +} + +static void chathelp(char *cmd, char *desc) { + char buf[STRLEN]; + + sprintf(buf, " %-20s- %s", cmd, desc); + printchatline(buf); +} + +static void chat_help(char *arg) { + if(strstr(arg, " op")) { + printchatline("½Í¤Ñ«ÇºÞ²zû±M¥Î«ü¥O"); + chathelp("[/f]lag [+-][ls]", "³]©wÂê©w¡B¯µ±Kª¬ºA"); + chathelp("[/i]nvite <id>", "ÁܽР<id> ¥[¤J½Í¤Ñ«Ç"); + chathelp("[/k]ick <id>", "±N <id> ½ð¥X½Í¤Ñ«Ç"); + chathelp("[/o]p <id>", "±N Op ªºÅv¤OÂಾµ¹ <id>"); + chathelp("[/t]opic <text>", "´«Ó¸ÜÃD"); + chathelp("[/w]all", "¼s¼½ (¯¸ªø±M¥Î)"); + } else { + chathelp("[//]help", "MUD-like ªÀ¥æ°Êµü"); + chathelp("[/.]help", "chicken °«Âû¥Î«ü¥O"); + chathelp("[/h]elp op", "½Í¤Ñ«ÇºÞ²zû±M¥Î«ü¥O"); + chathelp("[/a]ct <msg>", "°µ¤@Ӱʧ@"); + chathelp("[/b]ye [msg]", "¹D§O"); + chathelp("[/c]lear", "²M°£¿Ã¹õ"); + chathelp("[/j]oin <room>", "«Ø¥ß©Î¥[¤J½Í¤Ñ«Ç"); + chathelp("[/l]ist [room]", "¦C¥X½Í¤Ñ«Ç¨Ï¥ÎªÌ"); + chathelp("[/m]sg <id> <msg>", "¸ò <id> »¡®¨®¨¸Ü"); + chathelp("[/n]ick <id>", "±N½Í¤Ñ¥N¸¹´«¦¨ <id>"); + chathelp("[/p]ager", "¤Á´«©I¥s¾¹"); + chathelp("[/q]uery", "¬d¸ßºô¤Í"); + chathelp("[/r]oom", "¦C¥X¤@¯ë½Í¤Ñ«Ç"); + chathelp("[/u]sers", "¦C¥X¯¸¤W¨Ï¥ÎªÌ"); + chathelp("[/w]ho", "¦C¥X¥»½Í¤Ñ«Ç¨Ï¥ÎªÌ"); + chathelp("[/w]hoin <room>", "¦C¥X½Í¤Ñ«Ç<room> ªº¨Ï¥ÎªÌ"); + } +} + +static void chat_date() { + time_t thetime; + char genbuf[200]; + + time(&thetime); + sprintf(genbuf, "¡» " BBSNAME "¼Ð·Ç®É¶¡: %s", Cdate(&thetime)); + printchatline(genbuf); +} + +static void chat_pager() { + char genbuf[200]; + + char *msgs[] = {"Ãö³¬", "¥´¶}", "©Þ±¼", "¨¾¤ô","¦n¤Í"}; + sprintf(genbuf, "¡» ±zªº©I¥s¾¹:[%s]", + msgs[currutmp->pager = (currutmp->pager+1)%5]); + printchatline(genbuf); +} + +extern char *str_space; +extern userec_t xuser; +extern char *fn_plans; +extern char *err_uid; + +static void chat_query(char *arg) { + char *uid; + int tuid; + + printchatline(""); + strtok(arg, str_space); + if((uid = strtok(NULL, str_space)) && (tuid = getuser(uid))) { + char buf[128], *ptr; + FILE *fp; + + sprintf(buf, "%s(%s) ¦@¤W¯¸ %d ¦¸¡Aµoªí¹L %d ½g¤å³¹", + xuser.userid, xuser.username, xuser.numlogins, xuser.numposts); + printchatline(buf); + + sprintf(buf, "³Ìªñ(%s)±q[%s]¤W¯¸", Cdate(&xuser.lastlogin), + (xuser.lasthost[0] ? xuser.lasthost : "(¤£¸Ô)")); + printchatline(buf); + + sethomefile(buf, xuser.userid, fn_plans); + if((fp = fopen(buf, "r"))) { + tuid = 0; + while(tuid++ < MAX_QUERYLINES && fgets(buf, 128, fp)) { + if((ptr = strchr(buf, '\n'))) + ptr[0] = '\0'; + printchatline(buf); + } + fclose(fp); + } + } else + printchatline(err_uid); +} + +extern char *msg_shortulist; + +static void chat_users() { + printchatline(""); + printchatline("¡i " BBSNAME "ªº¹C«È¦Cªí ¡j"); + printchatline(msg_shortulist); + + if(apply_ulist(printuserent) == -1) + printchatline("ªÅµL¤@¤H"); + printuserent(NULL); +} + +typedef struct chat_command_t { + char *cmdname; /* Chatroom command length */ + void (*cmdfunc) (); /* Pointer to function */ +} chat_command_t; + +static chat_command_t chat_cmdtbl[] = { + {"help", chat_help}, + {"clear", chat_clear}, + {"date", chat_date}, + {"pager", chat_pager}, + {"query", chat_query}, + {"users", chat_users}, + {NULL, NULL} +}; + +static int chat_cmd_match(char *buf, char *str) { + while(*str && *buf && !isspace(*buf)) + if(tolower(*buf++) != *str++) + return 0; + return 1; +} + +static int chat_cmd(char *buf, int fd) { + int i; + + if(*buf++ != '/') + return 0; + + for(i = 0; chat_cmdtbl[i].cmdname; i++) { + if(chat_cmd_match(buf, chat_cmdtbl[i].cmdname)) { + chat_cmdtbl[i].cmdfunc(buf); + return 1; + } + } + return 0; +} + +extern char trans_buffer[256]; /* ¤@¯ë¶Ç»¼ÅÜ¼Æ add by Ptt */ + +#if 0 +static char *select_address() { + int c; + FILE *fp; + char nametab[25][90]; + char iptab[25][18], buf[80]; + + move(1, 0); + clrtobot(); + outs("\n \033[36m¡i§äÓ¦a¤è©ï©ïºb§a!¡j\033[m " + "¡· ¡i¥H¤U¬°¥»¯¸µn°O¦³®×ªº¯ù¼Ó¡j \n"); + trans_buffer[0]=0; + if((fp = fopen("etc/teashop", "r"))) { + for(c = 0; fscanf(fp, "%s%s", iptab[c], nametab[c]) != EOF; c++) { + sprintf(buf,"\n (\033[36m%d\033[0m) %-30s [%s]", + c + 1, nametab[c], iptab[c]); + outs(buf); + } + getdata(20, 10, "¡¹\033[32m ½Ð¿ï¾Ü¡A[0]Â÷¶}¡G\033[0m", buf, 3, + LCECHO); + if(buf[1]) + buf[0] = (buf[0] + 1) * 10 + (buf[1] - '1'); + else + buf[0] -= '1'; + if(buf[0] >= 0 && buf[0] < c) + strcpy(trans_buffer,iptab[(int)buf[0]]); + } else { + outs("¥»¯¸¨S¦³µn°O¥ô¦ó¦X®æ¯ù¼Ó"); + pressanykey(); + } + return trans_buffer; +} +#endif + +extern int usernum; +extern int t_lines; +extern char *msg_seperator; +#define MAXLASTCMD 6 +static int chatid_len = 10; + +int t_chat() { + char inbuf[80], chatid[20], lastcmd[MAXLASTCMD][80], *ptr = ""; + struct sockaddr_in sin; + struct hostent *h; + int cfd, cmdpos, ch; + int currchar; + int newmail; + int chatting = YEA; + char fpath[80]; + char genbuf[200]; + char roomtype; + + if(inbuf[0] == 0) + return -1; + + outs(" ÅX¨®«e©¹ ½Ð±éÔ........ "); + if(!(h = gethostbyname("localhost"))) { + perror("gethostbyname"); + return -1; + } + memset(&sin, 0, sizeof sin); +#ifdef FreeBSD + sin.sin_len = sizeof(sin); +#endif + sin.sin_family = PF_INET; + memcpy(&sin.sin_addr, h->h_addr, h->h_length); + sin.sin_port = htons(NEW_CHATPORT); + cfd = socket(sin.sin_family, SOCK_STREAM, 0); + if(!(connect(cfd, (struct sockaddr *) & sin, sizeof sin))) + roomtype = 1; + else { + sin.sin_port = CHATPORT; + cfd = socket(sin.sin_family, SOCK_STREAM, 0); + if(!(connect(cfd, (struct sockaddr *) & sin, sizeof sin))) + roomtype = 2; + else { + outs("\n " + "«z! ¨S¤H¦b¨ºÃäC...n¦³¨º¦a¤èªº¤H¥ý¥h¶}ªù°Õ!..."); + system("bin/xchatd"); + pressanykey(); + return -1; + } + } + + while(1) { + getdata(b_lines - 1, 0, "½Ð¿é¤J²á¤Ñ¥N¸¹¡G", inbuf, 9, DOECHO); + sprintf(chatid, "%s", (inbuf[0] ? inbuf : cuser.userid)); + chatid[8] = '\0'; +/* + ®榡: /! ¨Ï¥ÎªÌ½s¸¹ ¨Ï¥ÎªÌµ¥¯Å UserID ChatID + ·s®æ¦¡: /! UserID ChatID Password +*/ + if(roomtype == 1) + sprintf(inbuf, "/! %s %s %s", + cuser.userid, chatid, cuser.passwd); + else + sprintf(inbuf, "/! %d %d %s %s", + usernum, cuser.userlevel, cuser.userid, chatid); + chat_send(cfd, inbuf); + if(recv(cfd, inbuf, 3, 0) != 3) + return 0; + if(!strcmp(inbuf, CHAT_LOGIN_OK)) + break; + else if(!strcmp(inbuf, CHAT_LOGIN_EXISTS)) + ptr = "³oÓ¥N¸¹¤w¸g¦³¤H¥Î¤F"; + else if(!strcmp(inbuf, CHAT_LOGIN_INVALID)) + ptr = "³oÓ¥N¸¹¬O¿ù»~ªº"; + else if(!strcmp(inbuf, CHAT_LOGIN_BOGUS)) + ptr = "½Ð¤Å¬£»º¤À¨¶i¤J²á¤Ñ«Ç !!"; + + move(b_lines - 2, 0); + outs(ptr); + clrtoeol(); + bell(); + } + + add_io(cfd, 0); + + newmail = currchar = 0; + cmdpos = -1; + memset(lastcmd, 0, MAXLASTCMD * 80); + + setutmpmode(CHATING); + currutmp->in_chat = YEA; + strcpy(currutmp->chatid, chatid); + + clear(); + chatline = 2; + strcpy(inbuf, chatid); + stop_line = t_lines - 3; + + move(stop_line, 0); + outs(msg_seperator); + move(1, 0); + outs(msg_seperator); + print_chatid(chatid); + memset(inbuf, 0, 80); + + sethomepath(fpath, cuser.userid); + strcpy(fpath, tempnam(fpath, "chat_")); + flog = fopen(fpath, "w"); + + while(chatting) { + move(b_lines - 1, currchar + chatid_len); + ch = igetkey(); + + switch(ch) { + case KEY_DOWN: + cmdpos += MAXLASTCMD - 2; + case KEY_UP: + cmdpos++; + cmdpos %= MAXLASTCMD; + strcpy(inbuf, lastcmd[cmdpos]); + move(b_lines - 1, chatid_len); + clrtoeol(); + outs(inbuf); + currchar = strlen(inbuf); + continue; + case KEY_LEFT: + if(currchar) + --currchar; + continue; + case KEY_RIGHT: + if(inbuf[currchar]) + ++currchar; + continue; + } + + if(!newmail && currutmp->mailalert ) { + newmail = 1; + printchatline("¡» ¾´¡I¶l®t¤S¨Ó¤F..."); + } + + if(ch == I_OTHERDATA) { /* incoming */ + if(chat_recv(cfd, chatid) == -1) { + chatting = chat_send(cfd, "/b"); + break; + } + continue; + } + if(isprint2(ch)) { + if(currchar < 68) { + if(inbuf[currchar]) { /* insert */ + int i; + + for(i = currchar; inbuf[i] && i < 68; i++); + inbuf[i + 1 ] = '\0'; + for(; i > currchar; i--) + inbuf[i] = inbuf[i - 1]; + } else /* append */ + inbuf[currchar + 1] = '\0'; + inbuf[currchar] = ch; + move(b_lines - 1, currchar + chatid_len); + outs(&inbuf[currchar++]); + } + continue; + } + + if(ch == '\n' || ch == '\r') { + if(*inbuf) { + chatting = chat_cmd(inbuf, cfd); + if(chatting == 0) + chatting = chat_send(cfd, inbuf); + if(!strncmp(inbuf, "/b", 2)) + break; + + for(cmdpos = MAXLASTCMD - 1; cmdpos; cmdpos--) + strcpy(lastcmd[cmdpos], lastcmd[cmdpos - 1]); + strcpy(lastcmd[0], inbuf); + + inbuf[0] = '\0'; + currchar = 0; + cmdpos = -1; + } + print_chatid(chatid); + move(b_lines - 1, chatid_len); + continue; + } + + if(ch == Ctrl('H') || ch == '\177') { + if(currchar) { + currchar--; + inbuf[69] = '\0'; + memcpy(&inbuf[currchar], &inbuf[currchar + 1], 69 - currchar); + move(b_lines - 1, currchar + chatid_len); + clrtoeol(); + outs(&inbuf[currchar]); + } + continue; + } + if(ch == Ctrl('Z') || ch == Ctrl('Y')) { + inbuf[0] = '\0'; + currchar = 0; + print_chatid(chatid); + move(b_lines - 1, chatid_len); + continue; + } + + if(ch == Ctrl('C')) { + chat_send(cfd, "/b"); + break; + } + if(ch == Ctrl('D')) { + if(currchar < strlen(inbuf)) { + inbuf[69] = '\0'; + memcpy(&inbuf[currchar], &inbuf[currchar + 1], 69 - currchar); + move(b_lines - 1, currchar + chatid_len); + clrtoeol(); + outs(&inbuf[currchar]); + } + continue; + } + if(ch == Ctrl('K')) { + inbuf[currchar] = 0; + move(b_lines - 1, currchar + chatid_len); + clrtoeol(); + continue; + } + if(ch == Ctrl('A')) { + currchar = 0; + continue; + } + if(ch == Ctrl('E')) { + currchar = strlen(inbuf); + continue; + } + if(ch == Ctrl('I')) { + extern screenline_t *big_picture; + screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); + + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + add_io(0, 0); + t_idle(); + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + free(screen0); + redoscr(); + add_io(cfd, 0); + continue; + } + if(ch == Ctrl('Q')) { + print_chatid(chatid); + move(b_lines - 1, chatid_len); + outs(inbuf); + continue; + } + } + + close(cfd); + add_io(0, 0); + currutmp->in_chat = currutmp->chatid[0] = 0; + + if(flog) { + char ans[4]; + + fclose(flog); + more(fpath, NA); + getdata(b_lines - 1, 0, "²M°£(C) ²¾¦Ü³Æ§Ñ¿ý(M) (C/M)?[C]", + ans, 4, LCECHO); + if (*ans == 'm') { + fileheader_t mymail; + char title[128]; + + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mymail); + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[³Æ.§Ñ.¿ý]"); + strcpy(mymail.title, "·|ij\033[1;33m°O¿ý\033[m"); + sethomedir(title, cuser.userid); + append_record(title, &mymail, sizeof(mymail)); + Rename(fpath, genbuf); + } else + unlink(fpath); + } + + return 0; +} +/* -------------------------------------------------- */ +#if 0 + +extern char page_requestor[]; +extern userinfo_t *currutmp; + +#endif diff --git a/mbbsd/chc_draw.c b/mbbsd/chc_draw.c new file mode 100644 index 00000000..b3bd216f --- /dev/null +++ b/mbbsd/chc_draw.c @@ -0,0 +1,187 @@ +/* $Id: chc_draw.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define SIDE_ROW 10 +#define TURN_ROW 11 +#define STEP_ROW 12 +#define TIME_ROW 13 +#define WARN_ROW 15 +#define MYWIN_ROW 17 +#define HISWIN_ROW 18 + +extern char chc_warnmsg[64], *chc_mateid; +extern rc_t chc_from, chc_to, chc_select; +extern int chc_selected, chc_my, chc_turn, chc_firststep; +extern int chc_lefttime; +extern int chc_hiswin, chc_hislose, chc_histie; + +static char *turn_str[2] = {"¶Âªº", "¬õªº"}; + +static char *num_str[10] = { + "", "¤@", "¤G", "¤T", "¥|", "¤", "¤»", "¤C", "¤K", "¤E" +}; + +static char *chess_str[2][8] = { + /* 0 1 2 3 4 5 6 7 */ + {" ", "±N", "¤h", "¶H", "¨®", "°¨", "¥]", "¨ò"}, + {" ", "«Ó", "¥K", "¬Û", "¨®", "ØX", "¬¶", "§L"} +}; + +static char *chess_brd[BRD_ROW * 2 - 1] = { + /*0 1 2 3 4 5 6 7 8*/ + "¢z¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢{", /* 0 */ + "¢x ¢x ¢x ¢x¢@¢x¡þ¢x ¢x ¢x ¢x", + "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 1 */ + "¢x ¢x ¢x ¢x¡þ¢x¢@¢x ¢x ¢x ¢x", + "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 2 */ + "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", + "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 3 */ + "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", + "¢u¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢t", /* 4 */ + "¢x ·¡ ªe º~ ¬É ¢x", + "¢u¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢t", /* 5 */ + "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", + "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 6 */ + "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", + "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 7 */ + "¢x ¢x ¢x ¢x¢@¢x¡þ¢x ¢x ¢x ¢x", + "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 8 */ + "¢x ¢x ¢x ¢x¡þ¢x¢@¢x ¢x ¢x ¢x", + "¢|¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢}" /* 9 */ +}; + +static char *hint_str[] = { + " q »{¿éÂ÷¶}", + " p n¨D©M´Ñ", + "¤è¦VÁä ²¾°Ê¹C¼Ð", + "Enter ¿ï¾Ü/²¾°Ê" +}; + +void chc_movecur(int r, int c) { + move(r * 2 + 3, c * 4 + 4); +} + +#define BLACK_COLOR "\033[1;36m" +#define RED_COLOR "\033[1;31m" +#define BLACK_REVERSE "\033[1;37;46m" +#define RED_REVERSE "\033[1;37;41m" +#define TURN_COLOR "\033[1;33m" + +static void showstep(board_t board) { + int turn, fc, tc, eatten; + char *dir; + + turn = CHE_O(board[chc_from.r][chc_from.c]); + fc = (turn == (chc_my ^ 1) ? chc_from.c + 1 : 9 - chc_from.c); + tc = (turn == (chc_my ^ 1) ? chc_to.c + 1 : 9 - chc_to.c); + if(chc_from.r == chc_to.r) + dir = "¥"; + else { + if(chc_from.c == chc_to.c) + tc = chc_from.r - chc_to.r; + if(tc < 0) tc = -tc; + + if((turn == (chc_my ^ 1) && chc_to.r > chc_from.r) || + (turn == chc_my && chc_to.r < chc_from.r)) + dir = "¶i"; + else + dir = "°h"; + } + prints("%s%s%s%s%s", + turn == 0 ? BLACK_COLOR : RED_COLOR, + chess_str[turn][CHE_P(board[chc_from.r][chc_from.c])], + num_str[fc], dir, num_str[tc]); + eatten = board[chc_to.r][chc_to.c]; + if(eatten) + prints("¡G %s%s", + CHE_O(eatten) == 0 ? BLACK_COLOR : RED_COLOR, + chess_str[CHE_O(eatten)][CHE_P(eatten)]); + prints("\033[m"); +} + +extern userec_t cuser; + +void chc_drawline(board_t board, int line) { + int i, j; + + move(line, 0); + clrtoeol(); + if(line == 0) { + prints("\033[1;46m ¶H´Ñ¹ï¾Ô \033[45m%30s VS %-30s\033[m", + cuser.userid, chc_mateid); + } else if(line >= 3 && line <= 21) { + outs(" "); + for(i = 0; i < 9; i++) { + j = board[RTL(line)][i]; + if((line & 1) == 1 && j) { + if(chc_selected && + chc_select.r == RTL(line) && chc_select.c == i) + prints("%s%s\033[m", + CHE_O(j) == 0 ? BLACK_REVERSE : RED_REVERSE, + chess_str[CHE_O(j)][CHE_P(j)]); + else + prints("%s%s\033[m", + CHE_O(j) == 0 ? BLACK_COLOR : RED_COLOR, + chess_str[CHE_O(j)][CHE_P(j)]); + } else + prints("%c%c", chess_brd[line - 3][i * 4], + chess_brd[line - 3][i * 4 + 1]); + if(i != 8) + prints("%c%c", chess_brd[line - 3][i * 4 + 2], + chess_brd[line - 3][i * 4 + 3]); + } + outs(" "); + + if(line >= 3 && line < 3 + dim(hint_str)) { + outs(hint_str[line - 3]); + } else if(line == SIDE_ROW) { + prints("\033[1m§A¬O%s%s\033[m", + chc_my == 0 ? BLACK_COLOR : RED_COLOR, + turn_str[chc_my]); + } else if(line == TURN_ROW) { + prints("%s%s\033[m", + TURN_COLOR, + chc_my == chc_turn ? "½ü¨ì§A¤U´Ñ¤F" : "µ¥«Ý¹ï¤è¤U´Ñ"); + } else if(line == STEP_ROW && !chc_firststep) { + showstep(board); + } else if(line == TIME_ROW) { + prints("³Ñ¾l®É¶¡ %d:%02d", chc_lefttime / 60, chc_lefttime % 60); + } else if(line == WARN_ROW) { + outs(chc_warnmsg); + } else if(line == MYWIN_ROW) { + prints("\033[1;33m%12.12s " + "\033[1;31m%2d\033[37m³Ó " + "\033[34m%2d\033[37m±Ñ " + "\033[36m%2d\033[37m©M\033[m", + cuser.userid, + cuser.chc_win, cuser.chc_lose - 1, cuser.chc_tie); + } else if(line == HISWIN_ROW) { + prints("\033[1;33m%12.12s " + "\033[1;31m%2d\033[37m³Ó " + "\033[34m%2d\033[37m±Ñ " + "\033[36m%2d\033[37m©M\033[m", + chc_mateid, + chc_hiswin, chc_hislose - 1, chc_histie); + } + } else if(line == 2 || line == 22) { + outs(" "); + if(line == 2) + for(i = 1; i <= 9; i++) + prints("%s ", num_str[i]); + else + for(i = 9; i >= 1; i--) + prints("%s ", num_str[i]); + } +} + +void chc_redraw(board_t board) { + int i; + + for(i = 0; i <= 22; i++) + chc_drawline(board, i); +} diff --git a/mbbsd/chc_net.c b/mbbsd/chc_net.c new file mode 100644 index 00000000..d094d5f2 --- /dev/null +++ b/mbbsd/chc_net.c @@ -0,0 +1,28 @@ +/* $Id: chc_net.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" + +extern rc_t chc_from, chc_to; + +typedef struct drc_t { + rc_t from, to; +} drc_t; + +int chc_recvmove(int s) { + drc_t buf; + + if(read(s, &buf, sizeof(buf)) != sizeof(buf)) + return 1; + chc_from = buf.from, chc_to = buf.to; + return 0; +} + +void chc_sendmove(int s) { + drc_t buf; + + buf.from = chc_from, buf.to = chc_to; + write(s, &buf, sizeof(buf)); +} diff --git a/mbbsd/chc_play.c b/mbbsd/chc_play.c new file mode 100644 index 00000000..86c17fbc --- /dev/null +++ b/mbbsd/chc_play.c @@ -0,0 +1,277 @@ +/* $Id: chc_play.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern userinfo_t *currutmp; +extern int usernum; + +typedef int (*play_func_t)(int, board_t, board_t); + +static int chc_ipass = 0, chc_hepass = 0; +int chc_lefttime; +int chc_my, chc_turn, chc_selected, chc_firststep; +char chc_warnmsg[64], *chc_mateid; +rc_t chc_from, chc_to, chc_select, chc_cursor; +int chc_hiswin, chc_hislose, chc_histie; + +#define CHC_TIMEOUT 300 +#define SIDE_ROW 10 +#define TURN_ROW 11 +#define STEP_ROW 12 +#define TIME_ROW 13 +#define WARN_ROW 15 +#define MYWIN_ROW 17 +#define HISWIN_ROW 18 + +static int hisplay(int s, board_t board, board_t tmpbrd) { + int start_time; + int endgame = 0, endturn = 0; + + start_time = time(NULL); + while(!endturn) { + chc_lefttime = CHC_TIMEOUT - (time(NULL) - start_time); + if(chc_lefttime < 0) { + chc_lefttime = 0; + + /* to make him break out igetkey() */ + chc_from.r = -2; + chc_sendmove(s); + } + chc_drawline(board, TIME_ROW); + move(1, 0); + oflush(); + switch(igetkey()) { + case 'q': + endgame = 2; + endturn = 1; + break; + case 'p': + if(chc_hepass) { + chc_from.r = -1; + chc_sendmove(s); + endgame = 3; + endturn = 1; + } + break; + case I_OTHERDATA: + if(chc_recvmove(s)) { /* disconnect */ + endturn = 1; + endgame = 1; + } else { + if(chc_from.r == -1) { + chc_hepass = 1; + strcpy(chc_warnmsg, "\033[1;33mn¨D©M§½!\033[m"); + chc_drawline(board, WARN_ROW); + } else { + chc_from.r = 9 - chc_from.r, chc_from.c = 8 - chc_from.c; + chc_to.r = 9 - chc_to.r, chc_to.c = 8 - chc_to.c; + chc_cursor = chc_to; + if(CHE_P(board[chc_to.r][chc_to.c]) == 1) + endgame = 2; + endturn = 1; + chc_hepass = 0; + chc_drawline(board, STEP_ROW); + chc_movechess(board); + chc_drawline(board, LTR(chc_from.r)); + chc_drawline(board, LTR(chc_to.r)); + } + } + break; + } + } + return endgame; +} + +static int myplay(int s, board_t board, board_t tmpbrd) { + int ch, start_time; + int endgame = 0, endturn = 0; + + chc_ipass = 0, chc_selected = 0; + start_time = time(NULL); + chc_lefttime = CHC_TIMEOUT - (time(NULL) - start_time); + bell(); + while(!endturn) { + chc_drawline(board, TIME_ROW); + chc_movecur(chc_cursor.r, chc_cursor.c); + oflush(); + ch = igetkey(); + chc_lefttime = CHC_TIMEOUT - (time(NULL) - start_time); + if(chc_lefttime < 0) + ch = 'q'; + switch(ch) { + case I_OTHERDATA: + if(chc_recvmove(s)) { /* disconnect */ + endgame = 1; + endturn = 1; + } else if(chc_from.r == -1 && chc_ipass) { + endgame = 3; + endturn = 1; + } + break; + case KEY_UP: + chc_cursor.r--; + if(chc_cursor.r < 0) + chc_cursor.r = BRD_ROW - 1; + break; + case KEY_DOWN: + chc_cursor.r++; + if(chc_cursor.r >= BRD_ROW) + chc_cursor.r = 0; + break; + case KEY_LEFT: + chc_cursor.c--; + if(chc_cursor.c < 0) + chc_cursor.c = BRD_COL - 1; + break; + case KEY_RIGHT: + chc_cursor.c++; + if(chc_cursor.c >= BRD_COL) + chc_cursor.c = 0; + break; + case 'q': + endgame = 2; + endturn = 1; + break; + case 'p': + chc_ipass = 1; + chc_from.r = -1; + chc_sendmove(s); + strcpy(chc_warnmsg, "\033[1;33mn¨D©M´Ñ!\033[m"); + chc_drawline(board, WARN_ROW); + bell(); + break; + case '\r': + case '\n': + case ' ': + if(chc_selected) { + if(chc_cursor.r == chc_select.r && + chc_cursor.c == chc_select.c) { + chc_selected = 0; + chc_drawline(board, LTR(chc_cursor.r)); + } else if(chc_canmove(board, chc_select, chc_cursor)) { + if(CHE_P(board[chc_cursor.r][chc_cursor.c]) == 1) + endgame = 1; + chc_from = chc_select; + chc_to = chc_cursor; + if(!endgame) { + memcpy(tmpbrd, board, sizeof(board_t)); + chc_movechess(tmpbrd); + } + if(endgame || !chc_iskfk(tmpbrd)) { + chc_drawline(board, STEP_ROW); + chc_movechess(board); + chc_sendmove(s); + chc_selected = 0; + chc_drawline(board, LTR(chc_from.r)); + chc_drawline(board, LTR(chc_to.r)); + endturn = 1; + } else { + strcpy(chc_warnmsg, "\033[1;33m¤£¥i¥H¤ý¨£¤ý\033[m"); + bell(); + chc_drawline(board, WARN_ROW); + } + } + } else if(board[chc_cursor.r][chc_cursor.c] && + CHE_O(board[chc_cursor.r][chc_cursor.c]) == chc_turn) { + chc_selected = 1; + chc_select = chc_cursor; + chc_drawline(board, LTR(chc_cursor.r)); + } + break; + } + } + return endgame; +} + +extern userec_t cuser; + +static void mainloop(int s, board_t board) { + int endgame; + board_t tmpbrd; + play_func_t play_func[2]; + + play_func[chc_my] = myplay; + play_func[chc_my ^ 1] = hisplay; + for(chc_turn = 1, endgame = 0; !endgame; chc_turn ^= 1) { + chc_firststep = 0; + chc_drawline(board, TURN_ROW); + if(chc_ischeck(board, chc_turn)) { + strcpy(chc_warnmsg, "\033[1;31m±Nx!\033[m"); + bell(); + } else + chc_warnmsg[0] = 0; + chc_drawline(board, WARN_ROW); + endgame = play_func[chc_turn](s, board, tmpbrd); + } + + if(endgame == 1) { + strcpy(chc_warnmsg, "¹ï¤è»{¿é¤F!"); + cuser.chc_win++; + } else if(endgame == 2) { + strcpy(chc_warnmsg, "§A»{¿é¤F!"); + cuser.chc_lose++; + } else { + strcpy(chc_warnmsg, "©M´Ñ"); + cuser.chc_tie++; + } + cuser.chc_lose--; + passwd_update(usernum, &cuser); + chc_drawline(board, WARN_ROW); + bell(); + oflush(); +} + +extern userec_t xuser; + +static void chc_init(int s, board_t board) { + userinfo_t *my = currutmp; + + setutmpmode(CHC); + clear(); + chc_warnmsg[0] = 0; + chc_my = my->turn; + chc_mateid = my->mateid; + chc_firststep = 1; + chc_init_board(board); + chc_redraw(board); + chc_cursor.r = 9, chc_cursor.c = 0; + add_io(s, 0); + + if(my->turn) chc_recvmove(s); + passwd_query(usernum, &xuser); + cuser.chc_win = xuser.chc_win; + cuser.chc_lose = xuser.chc_lose + 1; + cuser.chc_tie = xuser.chc_tie; + cuser.money = xuser.money; + passwd_update(usernum, &cuser); + + getuser(chc_mateid); + chc_hiswin = xuser.chc_win; + chc_hislose = xuser.chc_lose; + chc_histie = xuser.chc_tie; + + if(!my->turn) { + chc_sendmove(s); + chc_hislose++; + } + + chc_redraw(board); +} + +void chc(int s) { + board_t board; + + chc_init(s, board); + mainloop(s, board); + close(s); + add_io(0, 0); + if(chc_my) pressanykey(); +} diff --git a/mbbsd/chc_rule.c b/mbbsd/chc_rule.c new file mode 100644 index 00000000..35d8fe6a --- /dev/null +++ b/mbbsd/chc_rule.c @@ -0,0 +1,186 @@ +/* $Id: chc_rule.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +extern rc_t chc_from, chc_to; +extern int chc_my; + +#define CENTER(a, b) (((a) + (b)) >> 1) + +void chc_init_board(board_t board) { + memset(board, 0, sizeof(board_t)); + board[0][4] = CHE(1, chc_my ^ 1); /* ±N */ + board[0][3] = board[0][5] = CHE(2, chc_my ^ 1); /* ¤h */ + board[0][2] = board[0][6] = CHE(3, chc_my ^ 1); /* ¶H */ + board[0][0] = board[0][8] = CHE(4, chc_my ^ 1); /* ¨® */ + board[0][1] = board[0][7] = CHE(5, chc_my ^ 1); /* °¨ */ + board[2][1] = board[2][7] = CHE(6, chc_my ^ 1); /* ¥] */ + board[3][0] = board[3][2] = board[3][4] = + board[3][6] = board[3][8] = CHE(7, chc_my ^ 1); /* ¨ò */ + + board[9][4] = CHE(1, chc_my); /* «Ó */ + board[9][3] = board[9][5] = CHE(2, chc_my); /* ¥K */ + board[9][2] = board[9][6] = CHE(3, chc_my); /* ¬Û */ + board[9][0] = board[9][8] = CHE(4, chc_my); /* ¨® */ + board[9][1] = board[9][7] = CHE(5, chc_my); /* ØX */ + board[7][1] = board[7][7] = CHE(6, chc_my); /* ¬¶ */ + board[6][0] = board[6][2] = board[6][4] = + board[6][6] = board[6][8] = CHE(7, chc_my); /* §L */ +} + +void chc_movechess(board_t board) { + board[chc_to.r][chc_to.c] = board[chc_from.r][chc_from.c]; + board[chc_from.r][chc_from.c] = 0; +} + +static int dist(rc_t from, rc_t to, int rowcol) { + int d; + + d = rowcol ? from.c - to.c : from.r - to.r; + return d > 0 ? d : -d; +} + +static int between(board_t board, rc_t from, rc_t to, int rowcol) { + int i, rtv = 0; + + if(rowcol) { + if(from.c > to.c) + i = from.c, from.c = to.c, to.c = i; + for(i = from.c + 1; i < to.c; i++) + if(board[to.r][i]) rtv++; + } else { + if(from.r > to.r) + i = from.r, from.r = to.r, to.r = i; + for(i = from.r + 1; i < to.r; i++) + if(board[i][to.c]) rtv++; + } + return rtv; +} + +int chc_canmove(board_t board, rc_t from, rc_t to) { + int i; + int rd, cd, turn; + + rd = dist(from, to, 0); + cd = dist(from, to, 1); + turn = CHE_O(board[from.r][from.c]); + + /* general check */ + if(board[to.r][to.c] && CHE_O(board[to.r][to.c]) == turn) + return 0; + + /* individual check */ + switch(CHE_P(board[from.r][from.c])) { + case 1: /* ±N «Ó */ + if(!(rd == 1 && cd == 0) && + !(rd == 0 && cd == 1)) + return 0; + if((turn == (chc_my ^ 1) && to.r > 2) || + (turn == chc_my && to.r < 7) || + to.c < 3 || to.c > 5) + return 0; + break; + case 2: /* ¤h ¥K */ + if(!(rd == 1 && cd == 1)) + return 0; + if((turn == (chc_my ^ 1) && to.r > 2) || + (turn == chc_my && to.r < 7) || + to.c < 3 || to.c > 5) + return 0; + break; + case 3: /* ¶H ¬Û */ + if(!(rd == 2 && cd == 2)) + return 0; + if((turn == (chc_my ^ 1) && to.r > 4) || + (turn == chc_my && to.r < 5)) + return 0; + /* ©ä¶H»L */ + if(board[CENTER(from.r, to.r)][CENTER(from.c, to.c)]) + return 0; + break; + case 4: /* ¨® */ + if(!(rd > 0 && cd == 0) && + !(rd == 0 && cd > 0)) + return 0; + if(between(board, from, to, rd == 0)) + return 0; + break; + case 5: /* °¨ ØX */ + if(!(rd == 2 && cd == 1) && + !(rd == 1 && cd == 2)) + return 0; + /* ©ä°¨¸} */ + if(rd == 2) { + if(board[CENTER(from.r, to.r)][from.c]) + return 0; + } else { + if(board[from.r][CENTER(from.c, to.c)]) + return 0; + } + break; + case 6: /* ¥] ¬¶ */ + if(!(rd > 0 && cd == 0) && + !(rd == 0 && cd > 0)) + return 0; + i = between(board, from, to, rd == 0); + if((i > 1) || + (i == 1 && !board[to.r][to.c]) || + (i == 0 && board[to.r][to.c])) + return 0; + break; + case 7: /* ¨ò §L */ + if(!(rd == 1 && cd == 0) && + !(rd == 0 && cd == 1)) + return 0; + if(((turn == (chc_my ^ 1) && to.r < 5) || + (turn == chc_my && to.r > 4)) && + cd != 0) + return 0; + if((turn == (chc_my ^ 1) && to.r < from.r) || + (turn == chc_my && to.r > from.r)) + return 0; + break; + } + return 1; +} + +static void findking(board_t board, int turn, rc_t *buf) { + int i, r, c; + + r = (turn == (chc_my ^ 1)) ? 0 : 7; + for(i = 0; i < 3; r++, i++) + for(c = 3; c < 6; c++) + if(CHE_P(board[r][c]) == 1 && + CHE_O(board[r][c]) == turn) { + buf->r = r, buf->c = c; + return ; + } +} + +int chc_iskfk(board_t board) { + rc_t from, to; + + findking(board, 0, &to); + findking(board, 1, &from); + if(from.c == to.c && between(board, from, to, 0) == 0) + return 1; + return 0; +} + +int chc_ischeck(board_t board, int turn) { + rc_t from, to; + + findking(board, turn, &to); + for(from.r = 0;from.r < BRD_ROW; from.r++) + for(from.c = 0; from.c < BRD_COL; from.c++) + if(board[from.r][from.c] && + CHE_O(board[from.r][from.c]) != turn) + if(chc_canmove(board, from, to)) + return 1; + return 0; +} diff --git a/mbbsd/chicken.c b/mbbsd/chicken.c new file mode 100644 index 00000000..f789925f --- /dev/null +++ b/mbbsd/chicken.c @@ -0,0 +1,989 @@ +/* $Id: chicken.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +#define NUM_KINDS 13 /* ¦³¦h¤ÖºØ°Êª« */ + +static const char *cage[17] = { + "½Ï¥Í", "¶g·³", "¥®¦~", "¤Ö¦~", "«C¬K", "«C¦~", + "«C¦~", "¬¡¤O", "§§¦~", "§§¦~", "§§¦~", "¤¤¦~", + "¤¤¦~", "¦Ñ¦~", "¦Ñ¦~", "¦Ñáàáà", "¥j§Æ"}; +static const char *chicken_type[NUM_KINDS] = { + "¤pÂû", "¬ü¤Ö¤k", "«i¤h", "»jµï", + "®£Às", "¦ÑÆN", "¿ß", "Äúµ§¤p·s", + "ª¯ª¯", "´cÅ]", "§ÔªÌ", "£««ó", + "°¨^¤E"}; +static const char *chicken_food[NUM_KINDS] = { + "Âû¹}®Æ", "Àç¾i«p¤ù", "Âû±Æ«K·í", "¦º½¹½º", + "«ÍÅé", "¤pÂû", "¿ß»æ°®", "¤pºµ»æ°®", + "Ä_¿ý", "ÆF®ð", "¶º¹Î", "«K·í", + "Âû»L"}; +static const int egg_price[NUM_KINDS] = { + 5, 25, 30, 40, + 80, 50, 15, 35, + 17, 100, 85, 200, + 200}; +static const int food_price[NUM_KINDS] = { + 4, 6, 8, 10, + 12, 12, 5, 6, + 5, 20, 15, 23, + 23}; +static const char *attack_type[NUM_KINDS] = { + "°Ö", "Ã@¥´", "ºl", "«r", + "¼²À»", "°Ö", "§ì", "½ð", + "«r","¿U¿N","·tÀ»","´Ò¥´", + "¼CÀ»"}; + +static const char *damage_degree[] = { + "°A¤l¦üªº", "ÄÌÄo¦üªº", "¤p¤Oªº", "»´·Lªº", + "¦³ÂI¯kªº", "¨Ï¤Oªº", "¶Ë¤Hªº", "««ªº", + "¨Ï¥þ¤Oªº", "´c¬½¬½ªº", "¦MÀIªº", "ºÆ¨gªº", + "²r¯Pªº", "¨g·¼É«B¦üªº", "Åå¤Ñ°Ê¦aªº", + "P©Rªº", NULL}; + +enum { + OO, FOOD, WEIGHT, CLEAN, RUN, ATTACK, BOOK, HAPPY, SATIS, + TEMPERAMENT, TIREDSTRONG, SICK, HP_MAX, MM_MAX +}; + +extern userec_t cuser; + +static chicken_t *mychicken = &cuser.mychicken; +static int age; + +static const int time_change[NUM_KINDS][14] = +/* ¸É«~ ¹ª« Åé« °®²b ±Ó±¶ §ðÀ»¤O ª¾ÃÑ §Ö¼Ö º¡·N ®ð½è ¯h³Ò ¯f®ð º¡¦å º¡ªk*/ +{ +/*Âû*/ + { 1, 1, 30, 3, 8, 3, 3, 40, 9, 1, 7, 3, 30, 1}, +/*¬ü¤Ö¤k*/ + { 1, 1, 110, 1, 4, 7, 41, 20, 9, 25, 25, 7, 110, 15}, +/*«i¤h*/ + { 1, 1, 200, 5, 4, 10, 33, 20, 15, 10, 27, 1, 200, 9}, +/*»jµï*/ + { 1, 1, 10, 5, 8, 1, 1, 5, 3, 1, 4, 1, 10, 30}, +/*®£Às*/ + { 1, 1,1000, 9, 1, 13, 4, 12, 3, 1, 200, 1, 1000, 3}, +/*¦ÑÆN*/ + { 1, 1, 90, 7, 10, 7, 4, 12, 3, 30, 20, 5, 90, 20}, +/*¿ß*/ + { 1, 1, 30, 5, 5, 6, 4, 8, 3, 15, 7, 4, 30, 21}, +/*Äúµ§¤p·s*/ + { 1, 1, 100, 9, 7, 7, 20, 50, 10, 8, 24, 4, 100, 9}, +/*ª¯*/ + { 1, 1, 45, 8, 7, 9, 3, 40, 20, 3, 9, 5, 45, 1}, +/* ´cÅ] */ + { 1, 1, 45, 10, 11, 11, 5, 21, 11, 1, 9, 5, 45, 25}, +/* §ÔªÌ */ + { 1, 1, 45, 2, 12, 10, 25, 1, 1, 10, 9, 5, 45, 26}, +/* ªü«ó */ + { 1, 1, 150, 4, 8, 13, 95, 25, 7, 10, 25, 5, 175, 85}, +/* °¨^¤E */ + { 1, 1, 147, 2, 10, 10, 85, 20, 4, 25, 25, 5, 145, 95} +}; + +extern userec_t xuser; +extern int usernum; + +int reload_chicken() { + passwd_query(usernum, &xuser); + memcpy(mychicken, &xuser.mychicken, sizeof(chicken_t)); + if(!mychicken->name[0]) + return 0; + else return 1; +} + +#define CHICKENLOG "etc/chicken" + +static int new_chicken() { + char buf[150]; + int price; + time_t now; + + clear(); + move(2,0); + outs("ÅwªïÆ[Á{ \033[33m¡·\033[37;44m PttÃdª«¥«³õ \033[33;40m¡·\033[m.. " + "¥Ø«e³J»ù¡G\n" + "(a)¤pÂû $5 (b)¬ü¤Ö¤k $25 (c)«i¤h $30 (d)»jµï $40 " + "(e)®£Às $80\n" + "(f)¦ÑÆN $50 (g)¿ß $15 (h)Äúµ§¤p·s$35 (i)ª¯ª¯ $17 " + "(j)´cÅ] $100\n" + "(k)§ÔªÌ $85 (l)ªü«ó $200 (m)°¨^¤E $200\n" + "[0]¦Û¤v $0\n"); + getdata_str(6, 0, "½Ð¿ï¾Ü§An¾iªº°Êª«¡G", buf, 3, LCECHO, "0"); + + buf[0] -= 'a'; + if(buf[0]<0 || buf[0]>NUM_KINDS-1) + return 0; + + mychicken->type = buf[0]; + + reload_money(); + price = egg_price[(int)mychicken->type]; + if(cuser.money < price) { + prints("\n ¿ú¤£°÷¶R³J³J,³J³Jn %d ¤¸", price); + refresh(); + return 0; + } + vice(price,"Ãdª«³J"); + while(strlen(mychicken->name)<3) + getdata(8, 0, "À°¨e¨úÓ¦n¦W¦r¡G", mychicken->name, 18, DOECHO); + + now = time(NULL); + sprintf(buf,"\033[31m%s \033[m¾i¤F¤@°¦¥s\033[33m %s \033[mªº " + "\033[32m%s\033[m ©ó %s",cuser.userid, + mychicken->name,chicken_type[(int)mychicken->type],ctime(&now)); + log_file(CHICKENLOG,buf); + mychicken->lastvisit = mychicken->birthday = mychicken->cbirth = now; + mychicken->food = 0; + mychicken->weight = time_change[(int)mychicken->type][WEIGHT]/3; + mychicken->clean = 0; + mychicken->run = time_change[(int)mychicken->type][RUN]; + mychicken->attack = time_change[(int)mychicken->type][ATTACK]; + mychicken->book = time_change[(int)mychicken->type][BOOK]; + mychicken->happy = time_change[(int)mychicken->type][HAPPY]; + mychicken->satis = time_change[(int)mychicken->type][SATIS]; + mychicken->temperament = time_change[(int)mychicken->type][TEMPERAMENT]; + mychicken->tiredstrong = 0; + mychicken->sick = 0; + mychicken->hp = time_change[(int)mychicken->type][WEIGHT]; + mychicken->hp_max = time_change[(int)mychicken->type][WEIGHT]; + mychicken->mm = 0; + mychicken->mm_max = 0; + return 1; +} + +int show_file(char *filename, int y, int lines, int mode) { + FILE *fp; + char buf[256]; + + if(y >= 0) + move(y,0); + clrtoline(lines + y); + if((fp=fopen(filename,"r"))) { + while(fgets(buf,256,fp) && lines--) + outs(Ptt_prints(buf,mode)); + fclose(fp); + } else + return 0; + return 1; +} + +static void show_chicken_stat(chicken_t *thechicken) { + struct tm *ptime; + + ptime = localtime(&thechicken->birthday); + prints(" Name :\033[33m%s\033[m (\033[32m%s\033[m)%*s¥Í¤é " + ":\033[31m%02d\033[m¦~\033[31m%2d\033[m¤ë\033[31m%2d\033[m¤é " + "(\033[32m%s %d·³\033[m)\n" + " Åé:\033[33m%5d/%-5d\033[m ªk:\033[33m%5d/%-5d\033[m §ðÀ»¤O:" + "\033[33m%-7d\033[m ±Ó±¶ :\033[33m%-7d\033[m ª¾ÃÑ :\033[33m%-7d" + "\033[m \n" + " §Ö¼Ö :\033[33m%-7d\033[m º¡·N :\033[33m%-7d\033[m ¯h³Ò :" + "\033[33m%-7d\033[m ®ð½è :\033[33m%-7d \033[mÅé« :" + "\033[33m%-5.2f\033[m \n" + " ¯f®ð :\033[33m%-7d\033[m °®²b :\033[33m%-7d\033[m ¹ª« :" + "\033[33m%-7d\033[m ¤j¸É¤Y:\033[33m%-7d\033[m ÃÄ«~ :\033[33m%-7d" + "\033[m \n", + thechicken->name, chicken_type[(int)thechicken->type], + 15 - strlen(thechicken->name), "", + ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday, + cage[age > 16 ? 16 : age], age, thechicken->hp, thechicken->hp_max, + thechicken->mm, thechicken->mm_max, + thechicken->attack, thechicken->run, thechicken->book, + thechicken->happy, thechicken->satis, thechicken->tiredstrong, + thechicken->temperament, + ((float)(thechicken->hp_max+(thechicken->weight/50))) / 100, + thechicken->sick, thechicken->clean, thechicken->food, + thechicken->oo, thechicken->medicine); +} + +#define CHICKEN_PIC "etc/chickens" +extern char *BBSName; + +void show_chicken_data(chicken_t *thechicken, chicken_t *pkchicken) { + char buf[1024]; + age = ((time(NULL) - thechicken->cbirth)/ (60*60*24)); + if(age < 0) { + thechicken->birthday = thechicken->cbirth = time(NULL)-10*(60*60*24); + age = 10; + } + /*Ptt:debug*/ + thechicken->type %= NUM_KINDS; + clear(); + showtitle(pkchicken ? "¢Þtt°«Âû³õ" : "¢Þtt¾iÂû³õ", BBSName); + move(1,0); + + show_chicken_stat(thechicken); + + sprintf(buf, CHICKEN_PIC "/%c%d", thechicken->type + 'a', + age > 16 ? 16 : age); + show_file(buf, 5, 14, NO_RELOAD); + + move(18,0); + + if(thechicken->sick) + outs("¥Í¯f¤F..."); + if(thechicken->sick > thechicken->hp / 5) + outs("\033[5;31m¾á¤ß...¯f«!!\033[m"); + + if(thechicken->clean > 150) + outs("\033[31m¤S¯ä¤Sżªº..\033[m"); + else if(thechicken->clean > 80) + outs("¦³ÂIż.."); + else if(thechicken->clean < 20) + outs("\033[32m«Ü°®²b..\033[m"); + + if(thechicken->weight > thechicken->hp_max*4) + outs("\033[31m§Ö¹¡¦º¤F!.\033[m"); + else if(thechicken->weight > thechicken->hp_max*3) + outs("\033[32m¹¡¹Ê¹Ê..\033[m"); + else if(thechicken->weight < (thechicken->hp_max / 4)) + outs("\033[31m§Ö¾j¦º¤F!..\033[m"); + else if(thechicken->weight < (thechicken->hp_max / 2)) + outs("¾j¤F.."); + + if(thechicken->tiredstrong > thechicken->hp * 1.7) + outs("\033[31m²Ö±o©ü°g¤F...\033[m"); + else if(thechicken->tiredstrong > thechicken->hp) + outs("²Ö¤F.."); + else if(thechicken->tiredstrong < thechicken->hp / 4) + outs("\033[32mºë¤O©ô²±...\033[m"); + + if(thechicken->hp < thechicken->hp_max / 4) + outs("\033[31mÅé¤O¥ÎºÉ..©a©a¤@®§..\033[m"); + if(thechicken->happy > 500) + outs("\033[32m«Ü§Ö¼Ö..\033[m"); + else if(thechicken->happy < 100) + outs("¤£§Ö¼Ö.."); + if(thechicken->satis > 500) + outs("\033[32m«Üº¡¨¬..\033[m"); + else if(thechicken->satis < 50) + outs("¤£º¡¨¬.."); + + if(pkchicken) { + outs("\n"); + show_chicken_stat(pkchicken); + outs("[¥ô·NÁä] §ðÀ»¹ï¤è [q] ¸¨¶] [o] ¦Y¤j¸É¤Y"); + } +} + +static void ch_eat() { + if(mychicken->food) { + mychicken->weight += time_change[(int)mychicken->type][WEIGHT] + + mychicken->hp_max/5 ; + mychicken->tiredstrong += + time_change[(int)mychicken->type][TIREDSTRONG] / 2; + mychicken->hp_max++; + mychicken->happy += 5; + mychicken->satis += 7; + mychicken->food--; + move(10, 10); + + show_file(CHICKEN_PIC "/eat", 5, 14, NO_RELOAD); + pressanykey(); + } +} + +static void ch_clean() { + mychicken->clean = 0; + mychicken->tiredstrong += + time_change[(int)mychicken->type][TIREDSTRONG] / 3; + show_file(CHICKEN_PIC "/clean", 5, 14, NO_RELOAD); + pressanykey(); +} + +static void ch_guess() { + char *guess[3] = {"°Å¤M", "¥ÛÀY", "¥¬"}, me, ch, win; + + mychicken->happy += time_change[(int)mychicken->type][HAPPY]*1.5; + mychicken->satis += time_change[(int)mychicken->type][SATIS]; + mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG]; + mychicken->attack += time_change[(int)mychicken->type][ATTACK]/4; + move(20,0); + clrtobot(); + outs("§An¥X[\033[32m1\033[m]\033[33m°Å¤M\033[m(\033[32m2\033[m)" + "\033[33m¥ÛÀY\033[m(\033[32m3\033[m)\033[33m¥¬\033[m:\n"); + me = igetch(); + me -= '1'; + if(me > 2 || me < 0) + me = 0; + win = (int)(3.0 * rand()/(RAND_MAX + 1.0)) - 1; + ch = (me + win + 3)%3; + prints("%s:%s ! %s:%s !.....%s", + cuser.userid, guess[(int)me], mychicken->name, guess[(int)ch], + win==0 ? "¥¤â" : win < 0 ? "C..ŤF :D!!" : "¶ã..§Ú¿é¤F :~"); + pressanykey(); +} + +static void ch_book() { + mychicken->book += time_change[(int)mychicken->type][BOOK]; + mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG]; + show_file(CHICKEN_PIC "/read", 5, 14, NO_RELOAD); + pressanykey(); +} + +static void ch_kiss() { + mychicken->happy += time_change[(int)mychicken->type][HAPPY]; + mychicken->satis += time_change[(int)mychicken->type][SATIS]; + mychicken->tiredstrong += + time_change[(int)mychicken->type][TIREDSTRONG] / 2; + show_file(CHICKEN_PIC "/kiss", 5, 14, NO_RELOAD); + pressanykey(); +} + +static void ch_hit() { + mychicken->attack += time_change[(int)mychicken->type][ATTACK]; + mychicken->run += time_change[(int)mychicken->type][RUN]; + mychicken->mm_max += time_change[(int)mychicken->type][MM_MAX]/15; + mychicken->weight -= mychicken->hp_max / 15 ; + mychicken->hp -= (int)((float)time_change[(int)mychicken->type][HP_MAX] * + rand()/(RAND_MAX+1.0)) / 2 + 1; + + if(mychicken->book > 2) + mychicken->book -= 2; + if(mychicken->happy > 2) + mychicken->happy -= 2; + if(mychicken->satis > 2) + mychicken->satis -= 2; + mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG]; + show_file(CHICKEN_PIC "/hit", 5, 14, NO_RELOAD); + pressanykey(); +} + +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +void ch_buyitem(int money, char *picture, int *item) { + int num = 0; + char buf[5]; + + getdata_str(b_lines - 1, 0, "n¶R¦h¤Ö¥÷©O:", buf, 4, DOECHO, "1"); + num = atoi(buf); + if(num < 1) + return; + reload_money(); + if(cuser.money > money*num) { + *item += num; + vice(money*num,"ÁʶRÃdª«,½ä½L¶µ¥Ø"); + show_file(picture, 5, 14, NO_RELOAD); + } else { + move(b_lines-1,0); + clrtoeol(); + outs("²{ª÷¤£°÷ !!!"); + } + pressanykey(); +} + +static void ch_eatoo() { + if(mychicken->oo > 0) { + mychicken->oo--; + mychicken->tiredstrong = 0; + if(mychicken->happy > 5) + mychicken->happy -= 5; + show_file(CHICKEN_PIC "/oo", 5, 14, NO_RELOAD); + pressanykey(); + } +} + +static void ch_eatmedicine() { + if(mychicken->medicine > 0) { + mychicken->medicine--; + mychicken->sick = 0; + if(mychicken->hp_max > 10) + mychicken->hp_max -= 3; + mychicken->hp = mychicken->hp_max; + if(mychicken->happy>10) + mychicken->happy -= 10; + show_file(CHICKEN_PIC "/medicine", 5, 14, NO_RELOAD); + pressanykey(); + } +} + +static void ch_kill() { + char buf[150],ans[4]; + + sprintf(buf, "±ó¾i³o%sn³Q»@ 100 ¤¸, ¬O§_n±ó¾i?(y/N)", + chicken_type[(int)mychicken->type]); + getdata_str(23, 0, buf, ans, 3, DOECHO, "N"); + if(ans[0] == 'y') { + time_t now = time(NULL); + + vice(100,"±ó¾iÃdª«¶O"); + more(CHICKEN_PIC "/deadth",YEA); + sprintf(buf, "\033[31m%s \033[m§â \033[33m%s\033[m\033[32m %s " + "\033[m®_¤F ©ó %s", cuser.userid, + mychicken->name, chicken_type[(int)mychicken->type], ctime(&now)); + log_file(CHICKENLOG, buf); + mychicken->name[0]=0; + } +} + +static int ch_sell() { +/* + int money = (mychicken->weight - time_change[(int)mychicken->type][WEIGHT]) + *(food_price[(int)mychicken->type])/4 + + ( + + ((mychicken->clean / time_change[(int)mychicken->type][CLEAN]) + + (mychicken->run / time_change[(int)mychicken->type][RUN]) + + (mychicken->attack / time_change[(int)mychicken->type][ATTACK]) + + (mychicken->book / time_change[(int)mychicken->type][BOOK]) + + (mychicken->happy / time_change[(int)mychicken->type][HAPPY]) + + (mychicken->satis / time_change[(int)mychicken->type][SATIS]) + + (mychicken->temperament / time_change[(int)mychicken->type][TEMPERAMENT]) + - (mychicken->tiredstrong / time_change[(int)mychicken->type][TIREDSTRONG]) + - (mychicken->sick / time_change[(int)mychicken->type][SICK]) + + (mychicken->hp / time_change[(int)mychicken->type][HP_MAX]) + + (mychicken->mm / time_change[(int)mychicken->type][MM_MAX]) + + 7 - abs(age - 7)) * 3 + ; +*/ + int money = (age * food_price[(int)mychicken->type] * 3 + + (mychicken->hp_max * 10 + mychicken->weight) / + time_change[(int)mychicken->type][HP_MAX]) * 3 / 2 - + mychicken->sick; + char buf[150],ans[4]; + time_t now = time(NULL); + + if(money < 0) + money =0 ; + else if(money > MAX_CHICKEN_MONEY) + money = MAX_CHICKEN_MONEY; //¨¾¤î©ÇÂû + if(mychicken->type == 1 || mychicken->type == 7) { + outs("\n\033[31m £..¿Ë·Rªº..³c½æ¤H¤f¬O·|¥Çªkªºò..\033[m"); + pressanykey(); + return 0; + } + if(age < 5) { + outs("\n ÁÙ¥¼¦¨¦~¤£¯à½æ"); + pressanykey(); + return 0; + } + if(age > 30) { + outs("\n\033[31m ³o..¤Ó¦Ñ¨S¤Hn¤F\033[m"); + pressanykey(); + return 0; + } + + sprintf(buf, "³o°¦%d·³%s¥i¥H½æ %d ¤¸, ¬O§_n½æ?(y/N)", age, + chicken_type[(int)mychicken->type], money); + getdata_str(23, 0, buf, ans, 3, DOECHO, "N"); + if(ans[0]=='y') { + sprintf(buf, "\033[31m%s\033[m §â \033[33m%s\033[m " + "\033[32m%s\033[m ¥Î \033[36m%d\033[m ½æ¤F ©ó %s", + cuser.userid, mychicken->name, + chicken_type[(int)mychicken->type],money,ctime(&now)); + log_file(CHICKENLOG, buf); + mychicken->lastvisit = mychicken->name[0]=0; + passwd_update(usernum, &cuser); + more(CHICKEN_PIC "/sell",YEA); + demoney(money); + return 1; + } + return 0; +} + +static void geting_old(int *hp, int *weight, int diff, int age) { + float ex = 0.9; + + if(age > 70) + ex = 0.1; + else if(age > 30) + ex = 0.5; + else if(age > 20) + ex = 0.7; + + diff /= 60*6; + while(diff--) { + *hp *= ex; + *weight *= ex; + } +} + +/* ¨Ì®É¶¡Åܰʪº¸ê®Æ */ +void time_diff(chicken_t *thechicken) { + int diff; + int theage = ((time(NULL) - thechicken->cbirth)/ (60 * 60 * 24)); + + thechicken->type %= NUM_KINDS ; + diff = (time(NULL)-thechicken->lastvisit)/60; + + if((diff) < 1) + return; + + if(theage > 13 ) /* ¦Ñ¦º */ + geting_old(&thechicken->hp_max, &thechicken->weight, diff, age); + + thechicken->lastvisit = time(NULL); + thechicken->weight -= thechicken->hp_max * diff / 540; /* Åé« */ + if(thechicken->weight < 1) { + thechicken->sick -= thechicken->weight / 10; /* ¾j±o¯f®ð¤W¤É */ + thechicken->weight =1; + } + + /* ²M¼ä«× */ + thechicken->clean += diff * time_change[(int)thechicken->type][CLEAN] / 30; + + /* §Ö¼Ö«× */ + thechicken->happy -= diff / 60; + if(thechicken->happy < 0) + thechicken->happy=0; + thechicken->attack -= + time_change[(int)thechicken->type][ATTACK] * diff / (60 * 32); + if(thechicken->attack < 0) + thechicken->attack = 0; + /* §ðÀ»¤O */ + thechicken->run -= time_change[(int)thechicken->type][RUN] * diff / (60 * 32); + /* ±Ó±¶ */ + if(thechicken->run < 0) + thechicken->run = 0; + thechicken->book -= time_change[(int)thechicken->type][BOOK]*diff/ (60*32); + /* ª¾ÃÑ */ + if(thechicken->book < 0) + thechicken->book = 0; + /* ®ð½è */ + thechicken->temperament++; + + thechicken->satis -= diff / 60 / 3 * time_change[(int)thechicken->type][SATIS]; + /* º¡·N«× */ + if(thechicken->satis < 0) + thechicken->satis = 0; + + /* ż¯fªº */ + if(mychicken->clean > 1000) + mychicken->sick += (mychicken->clean - 400) / 10; + + if(thechicken->weight > 1) + thechicken->sick -= diff / 60; + /* ¯f®ð«ìÅ@ */ + if(thechicken->sick < 0) + thechicken->sick = 0; + thechicken->tiredstrong -= diff * + time_change[(int)thechicken->type][TIREDSTRONG] / 4; + /* ¯h³Ò */ + if(thechicken->tiredstrong < 0) + thechicken->tiredstrong = 0; + /* hp_max */ + if(thechicken->hp >= thechicken->hp_max/2) + thechicken->hp_max += + time_change[(int)thechicken->type][HP_MAX]*diff/ (60*12); + /* hp«ìÅ@ */ + if(!thechicken->sick) + thechicken->hp += + time_change[(int)thechicken->type][HP_MAX]*diff/ (60*6); + if(thechicken->hp>thechicken->hp_max) + thechicken->hp = thechicken->hp_max; + /* mm_max */ + if(thechicken->mm >= thechicken->mm_max/2) + thechicken->mm_max += + time_change[(int)thechicken->type][MM_MAX]*diff/ (60*8); + /* mm«ìÅ@ */ + if(!thechicken->sick) + thechicken->mm += diff; + if(thechicken->mm>thechicken->mm_max) + thechicken->mm = thechicken->mm_max; +} + +static void check_sick() { + /* ż¯fªº */ + if(mychicken->tiredstrong > mychicken->hp * 0.3 && mychicken->clean > 150) + mychicken->sick += (mychicken->clean - 150) / 10; + /* ²Ö¯fªº */ + if(mychicken->tiredstrong > mychicken->hp*1.3) + mychicken->sick += time_change[(int)mychicken->type][SICK]; + /* ¯f®ð¤Ó«ÁÙ°µ¨Æ´îhp */ + if(mychicken->sick > mychicken->hp / 5) { + mychicken->hp -= (mychicken->sick - mychicken->hp / 5)/4; + if(mychicken->hp < 0 ) + mychicken->hp = 0; + } +} + +static int deadtype(chicken_t *thechicken) { + int i; + char buf[150]; + time_t now = time(NULL); + + if(thechicken->hp <= 0) /* hp¥ÎºÉ */ + i = 1; + else if(thechicken->tiredstrong > thechicken->hp * 3 ) /* ¾Þ³Ò¹L«× */ + i = 2; + else if(thechicken->weight > thechicken->hp_max*5) /* ªÎD¹L«× */ + i = 3; + else if(thechicken->weight == 1 && + thechicken->sick > thechicken->hp_max / 4) + i = 4; /* ¾j¦º¤F */ + else if(thechicken->satis <= 0) /* «Ü¤£º¡·N */ + i = 5; + else + return 0; + + if(thechicken == mychicken) { + sprintf(buf,"\033[31m%s\033[m ©Ò¯k·Rªº\033[33m %s\033[32m %s " + "\033[m±¾¤F ©ó %s", + cuser.userid, thechicken->name, + chicken_type[(int)thechicken->type], + ctime(&now)); + log_file(CHICKENLOG, buf); + mychicken->name[0] = 0; + passwd_update(usernum, &cuser); + } + return i; +} + +int showdeadth(int type) { + switch(type) { + case 1: + more(CHICKEN_PIC "/nohp",YEA); + break; + case 2: + more(CHICKEN_PIC "/tootired",YEA); + break; + case 3: + more(CHICKEN_PIC "/toofat",YEA); + break; + case 4: + more(CHICKEN_PIC "/nofood",YEA); + break; + case 5: + more(CHICKEN_PIC "/nosatis", YEA); + break; + default: + return 0; + } + more(CHICKEN_PIC "/deadth",YEA); + return type; +} + +int isdeadth(chicken_t *thechicken) { + int i; + + if(!(i = deadtype(thechicken))) + return 0; + return showdeadth(i); +} + +static void ch_changename() { + char buf[150], newname[20] = ""; + time_t now = time(NULL); + + getdata_str(b_lines - 1, 0, "¶â..§ïÓ¦n¦W¦r§a:", newname, 18, DOECHO, + mychicken->name); + + if(strlen(newname) >= 3 && strcmp(newname,mychicken->name)) { + sprintf(buf, "\033[31m%s\033[m §â¯k·Rªº\033[33m %s\033[32m %s " + "\033[m§ï¦W¬°\033[33m %s\033[m ©ó %s", + cuser.userid, mychicken->name, + chicken_type[(int)mychicken->type], + newname, ctime(&now)); + strcpy(mychicken->name, newname); + log_file(CHICKENLOG,buf); + } +} + +static int select_menu() { + char ch; + + reload_money(); + move(19,0); + prints("\033[44;37m ¿ú :\033[33m %-10d " + " \033[m\n" + "\033[33m(\033[37m1\033[33m)²M²z (\033[37m2\033[33m)¦Y¶º " + "(\033[37m3\033[33m)²q®± (\033[37m4\033[33m)°á®Ñ " + "(\033[37m5\033[33m)¿Ë¥L (\033[37m6\033[33m)¥´¥L " + "(\033[37m7\033[33m)¶R%s$%d (\033[37m8\033[33m)¦Y¸É¤Y\n" + "(\033[37m9\033[33m)¦Y¯fÃÄ (\033[37mo\033[33m)¶R¤j¸É¤Y$100 " + "(\033[37mm\033[33m)¶RÃÄ$10 (\033[37mk\033[33m)±ó¾i " + "(\033[37ms\033[33m)½æ±¼ (\033[37mn\033[33m)§ï¦W " + "(\033[37mq\033[33m)Â÷¶}:\033[m", + cuser.money, + /*chicken_food[(int)mychicken->type], + chicken_type[(int)mychicken->type], + chicken_type[(int)mychicken->type],*/ + chicken_food[(int)mychicken->type], + food_price[(int)mychicken->type]); + do { + switch(ch = igetch()) { + case '1': + ch_clean(); + check_sick(); + break; + case '2': + ch_eat(); + check_sick(); + break; + case '3': + ch_guess(); + check_sick(); + break; + case '4': + ch_book(); + check_sick(); + break; + case '5': + ch_kiss(); + break; + case '6': + ch_hit(); + check_sick(); + break; + case '7': + ch_buyitem(food_price[(int)mychicken->type], CHICKEN_PIC "/food", + &mychicken->food); + break; + case '8': + ch_eatoo(); + break; + case '9': + ch_eatmedicine(); + break; + case 'O': + case 'o': + ch_buyitem(100, CHICKEN_PIC "/buyoo", &mychicken->oo); + break; + case 'M': + case 'm': + ch_buyitem(10, CHICKEN_PIC "/buymedicine", &mychicken->medicine); + break; + case 'N': + case 'n': + ch_changename(); + break; + case 'K': + case 'k': + ch_kill(); + return 0; + case 'S': + case 's': + if(!ch_sell()) break; + case 'Q': + case 'q': + return 0; + } + } while(ch < ' ' || ch>'z'); + return 1; +} + +static int recover_chicken(chicken_t *thechicken) { + char buf[200]; + int price = egg_price[(int)thechicken->type], + money = price + (rand() % price); + + if(time(NULL) - thechicken->lastvisit > (60 * 60 * 24 * 7)) + return 0; + outmsg("\033[33;44m¡¹ÆF¬É¦u½Ã\033[37;45m §O®`©È §Ú¬O¨ÓÀ°§Aªº \033[m"); + bell(); + igetch(); + outmsg("\033[33;44m¡¹ÆF¬É¦u½Ã\033[37;45m §AµLªk¥á¨ì§Ú¤ô²y ¦]¬°§Ú¬O¸tÆF, " + "³Ìªñ¯Ê¿ú·QÁÈ¥~§Ö \033[m"); + bell(); + igetch(); + sprintf(buf, "\033[33;44m¡¹ÆF¬É¦u½Ã\033[37;45m " + "§A¦³¤@Ó訫¤£¤[ªº%sn©Û´«¦^¨Ó¶Ü? ¥un%d¤¸ò \033[m", + chicken_type[(int)thechicken->type], price*2); + outmsg(buf); + bell(); + getdata_str(21, 0, " ¿ï¾Ü¡G(N:§|¤H¹À/y:½ÐÀ°À°§Ú)", buf, 3, LCECHO, "N"); + if(buf[0] == 'y' || buf[0] == 'Y') { + reload_money(); + if(cuser.money < price*2) { + outmsg("\033[33;44m¡¹ÆF¬É¦u½Ã\033[37;45m ¤°»ò ¿ú¨S±a°÷ " + "¨S¿úªº¤p° §Ö¥hÄw¿ú§a \033[m"); + bell(); + igetch(); + return 0; + } + strcpy(thechicken->name, "[¾ß¦^¨Óªº]"); + thechicken->hp = thechicken->hp_max; + thechicken->sick = 0; + thechicken->satis = 2; + vice(money,"ÆF¬É¦u½Ã"); + sprintf(buf, "\033[33;44m¡¹ÆF¬É¦u½Ã\033[37;45m OK¤F °O±oÁý¥LÂIªF¦è " + "¤£µM¥i¯à¥¢®Ä ©À¦b§Ú¤]¦³ª±Ptt ®³§A%d´N¦n \033[m", money); + outmsg(buf); + bell(); + igetch(); + return 1; + } + outmsg("\033[33;44m¡¹ÆF¬É¦u½Ã\033[37;45m ³ºµM»¡§Ú§|¤H! ³o¦~ÀY©R¯u¤£È¿ú " + "°£«D§Ú¦A¨Ó§ä§A §A¦A¤]¨S¾÷·|¤F \033[m"); + bell(); + igetch(); + thechicken->lastvisit = 0; + passwd_update(usernum, &cuser); + return 0; +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 + +int chicken_main() { + lockreturn0(CHICKEN, LOCK_MULTI); + + reload_chicken(); + age = ((time(NULL) - mychicken->cbirth)/ (60*60*24)); + if(!mychicken->name[0] && !recover_chicken(mychicken) && !new_chicken()) { + unlockutmpmode(); + return 0; + } + + do { + time_diff(mychicken); + if(isdeadth(mychicken)) + break; + show_chicken_data(mychicken, NULL); + } while(select_menu()); + reload_money(); + passwd_update(usernum, &cuser); + unlockutmpmode(); + return 0; +} + +extern userinfo_t *currutmp; +extern struct utmpfile_t *utmpshm; + +int chickenpk(int fd) { + char mateid[IDLEN + 1], data[200], buf[200]; + int ch = 0; + + userinfo_t *uin = &utmpshm->uinfo[currutmp->destuip]; + userec_t ouser; + chicken_t *ochicken = &ouser.mychicken; + int r, attmax, i, datac, duid = currutmp->destuid, catched=0, count=0; + + lockreturn0(CHICKEN, LOCK_MULTI); + + strcpy(mateid, currutmp->mateid); /*§â¹ï¤âªºid¥Îlocal buffer°O¦í*/ + + getuser(mateid) ; + memcpy(&ouser, &xuser, sizeof(userec_t)); + reload_chicken(); + if(!ochicken->name[0] || !mychicken->name[0]) { + outmsg("¦³¤@¤è¨S¦³Ãdª«"); /* Ptt:§«¤îpage®É§âÃdª«½æ±¼ */ + bell(); + refresh(); + add_io(0, 0); + close(fd); + unlockutmpmode(); + sleep(1); + return 0; + } + + show_chicken_data(ochicken, mychicken); + add_io(fd, 3); /* §âfd¥[¨ìigetchºÊµø */ + while(1) { + r = rand(); + ch = igetkey(); + getuser(mateid) ; + memcpy(&ouser, &xuser, sizeof(userec_t)); + reload_chicken(); + show_chicken_data(ochicken, mychicken); + time_diff(mychicken); + + i = mychicken->attack* mychicken->hp / mychicken->hp_max; + for(attmax=2; (i = i*9/10); attmax++); + + if(ch == I_OTHERDATA) { + count =0; + datac = recv(fd, data, sizeof(data), 0); + if(datac <= 1) + break; + move(17,0); + outs(data+1); + switch(data[0]) { + case 'c': + catched=1; + move(16,0); + outs("n©ñ¥L¨«¶Ü?(y/N)"); + break; + case 'd': + move(16,0); + outs("ªü~ˤU¤F!!"); + break; + } + if(data[0] == 'd' || data[0]=='q' || data[0]=='l') + break; + continue; + } else if(currutmp->turn) { + count = 0; + currutmp->turn = 0; + uin->turn = 1; + mychicken->tiredstrong ++; + switch(ch) { + case 'y': + if(catched == 1) { + sprintf(data, "lÅý %s ¸¨¶]¤F\n", + ochicken->name); + } + break; + case 'n': + catched =0; + default: + case 'k': + r = r % (attmax + 2); + if(r) { + sprintf(data, "M%s %s%s %s ¶Ë¤F %d ÂI\n", mychicken->name, + damage_degree[r/3>15 ? 15:r/3], + attack_type[(int)mychicken->type], + ochicken->name, r); + ochicken->hp-=r; + } else + sprintf(data, "M%s ı±o¤â³n¥XÀ»µL®Ä\n", mychicken->name); + break; + case 'o': + if(mychicken->oo > 0) { + mychicken->oo--; + mychicken->hp += 300; + if(mychicken->hp > mychicken->hp_max) + mychicken->hp = mychicken->hp_max; + mychicken->tiredstrong = 0; + sprintf(data, "M%s ¦Y¤FÁû¤j¸É¤Y¸É¥RÅé¤O\n", + mychicken->name); + } else + sprintf(data, "M%s ·Q¦Y¤j¸É¤Y, ¥i¬O¨S¦³¤j¸É¤Y¥i¦Y\n", + mychicken->name); + break; + case 'q': + if(r % (mychicken->run+1) > r % (ochicken->run+1)) + sprintf(data, "q%s ¸¨¶]¤F\n", + mychicken->name); + else + sprintf(data, "c%s ·Q¸¨¶], ¦ý³Q %s §ì¨ì¤F\n", + mychicken->name, ochicken->name); + break; + } + if(deadtype(ochicken)) { + strtok(data,"\n"); + strcpy(buf, data); + sprintf(data, "d%s , %s ³Q %s ¥´¦º¤F\n", + buf + 1, ochicken->name, mychicken->name); + } + move(17,0); + outs(data+1); + i = strlen(data) +1; + passwd_update(duid, &ouser); + passwd_update(usernum, &cuser); + send(fd, data, i, 0); + if(data[0]=='q' || data[0]=='d') + break; + } else { + move(17, 0); + if(count++ > 30) + break; + } + } + add_io(0, 0); /* §âigetch«ìÅ@¦^ */ + pressanykey(); + close(fd); + if(!showdeadth(deadtype(mychicken))); + unlockutmpmode(); + return 0; +} diff --git a/mbbsd/dark.c b/mbbsd/dark.c new file mode 100644 index 00000000..52741617 --- /dev/null +++ b/mbbsd/dark.c @@ -0,0 +1,456 @@ +/* $Id: dark.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define RED 1 +#define BLACK 0 +typedef short int sint; + +typedef struct item { + short int color,value,die,out; +} item; + +typedef struct cur{ + short int y,x,end; +} cur; + +static item brd[4][8]; +static cur curr; /* 6 Ó bytes */ +extern userinfo_t *currutmp; + +static char *rname[]={"§L","¬¶","ØX","¨®","¬Û","¥K","«Ó"}; +static char *bname[]={"¨ò","¥]","°¨","¨®","¶H","¤h","±N"}; + +static sint cury[]={3,5,7,9}, curx[]={5,9,13,17,21,25,29,33}; +static sint rcount,bcount,cont,fix; /* cont:¬O§_¥i³s¦Y */ +static sint my=0,mx=0,mly=-1,mlx=-1; /* ²¾°Êªº®y¼Ð ¸ò ¿ï¤lªº®y¼Ð */ + +static sint cur_eaty,cur_eatx; /* ¦Y±¼¹ï¤è¨ä¤lªº¨q¥X®y¼Ð */ +static void brdswap(sint y,sint x,sint ly,sint lx) { + memcpy(&brd[y][x],&brd[ly][lx],sizeof(item)); + brd[ly][lx].die=1; + brd[ly][lx].color=-1; /* ¨S³oÓcolor */ + brd[ly][lx].value=-1; +} + +static void pprints(sint y,sint x,char* s) { + move(y,x); + clrtoeol(); + prints("%s",s); +} + +static sint Is_win(item att, item det, sint y, sint x, sint ly, sint lx) { + sint i,c=0,min,max; + if(att.value == 1) /* ¯¥ */ + { + if(y!=ly && x!=lx) return 0; + if((abs(ly-y)==1 && brd[y][x].die==0)|| + (abs(lx-x)==1 && brd[y][x].die==0)) + return 0; + if(y==ly){ + if(x>lx) {max=x;min=lx;} + else {max=lx;min=x;} + for(i=min+1;i<max;i++) + if(brd[y][i].die==0) c++; + }else if(x==lx){ + if(y>ly) {max=y;min=ly;} + else {max=ly;min=y;} + for(i=min+1;i<max;i++) + if(brd[i][x].die==0) c++; + } + if(c != 1) return 0; + if(det.die == 1) return 0; + return 1; + } + /* «D¯¥ */ + if( ((abs(ly-y)==1&&x==lx) || (abs(lx-x)==1&&ly==y)) && brd[y][x].out==1 ) + { + if(att.value == 0 && det.value == 6) return 1; + else if(att.value == 6 && det.value == 0) return 0; + else if(att.value >= det.value) return 1; + else return 0; + } + return 0; +} + +static sint Is_move(sint y,sint x, sint ly, sint lx) { + if(brd[y][x].die==1 && ((abs(ly-y)==1&&x==lx) || (abs(lx-x)==1&&ly==y))) + return 1; + return 0; +} + +static void brd_rand() { + sint y,x,index; + sint tem[32]; + sint value[32]={0,0,0,0,0,1,1,2,2,3,3,4,4,5,5,6, + 0,0,0,0,0,1,1,2,2,3,3,4,4,5,5,6}; + + bzero(brd, sizeof(brd)); + bzero(tem, sizeof(tem)); + bzero(&curr, sizeof(curr)); + srand(getpid()%2731+time(NULL)%3219); + for(y=0;y<4;y++) + for(x=0;x<8;x++) + while(1) { + index=rand()%32; + if(tem[index]) continue; + brd[y][x].color=(index>15)?0:1; + brd[y][x].value=value[index]; + tem[index]=1; + break; + } +} + +static void brd_prints() { + clear(); + move(1,0); + outs(" + [43;30m¢~¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢¡[m + [43;30m¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x[m + [43;30m¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t[m + [43;30m¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x[m + [43;30m¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t[m + [43;30m¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x[m + [43;30m¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t[m + [43;30m¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x[m + [43;30m¢¢¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢£[m + "); +} + +static void draw_line(sint y, sint f) { + sint i; + char buf[1024],tmp[256]; + + *buf = 0; + *tmp = 0; + strcpy(buf,"\033[43;30m"); + for(i=0; i<8; i++) + { + if(brd[y][i].die==1) + sprintf(tmp,"¢x "); + else if(brd[y][i].out==0) + sprintf(tmp,"¢x¡´"); + else { + sprintf(tmp, "¢x\033[%s1;%dm%s\033[m\033[43;30m", + (f==i)?"1;47;":"",(brd[y][i].color)?31:34, + (brd[y][i].color)?rname[brd[y][i].value]: + bname[brd[y][i].value]); + } + strcat(buf,tmp); + } + strcat(buf,"¢x\033[m"); + + move(cury[y],3); + clrtoeol(); + prints("%s",buf); +} + +static void redraw() { + sint i=0; + for(;i<4;i++) + draw_line(i,-1); +} + +static sint playing(sint fd, sint color,sint ch,sint *b, userinfo_t *uin) { + curr.end = 0; + move(cury[my],curx[mx]); + + if(fix) { + if(ch=='s') { + fix=0; *b=0; return 0; + } else { + draw_line(mly,-1); + } + } + + switch(ch) { + case KEY_LEFT: + if(mx == 0) mx=7; + else mx--; + move(cury[my],curx[mx]); + *b=-1; + break; + case KEY_RIGHT: + if(mx==7) mx=0; + else mx++; + move(cury[my],curx[mx]); + *b=-1; + break; + case KEY_UP: + if(my==0) my=3; + else my--; + move(cury[my],curx[mx]); + *b=-1; + break; + case KEY_DOWN: + if(my==3) my=0; + else my++; + move(cury[my],curx[mx]); + *b=-1; + break; + case 'q':case 'Q': + if(!color) bcount=0; + else rcount=0; + *b=0; + return -2; + case 'p':case 'P': + return -3; + case 'c': + return -4; + case 'g': + return -5; + case 's': /* ½¶}´Ñ¤l ©Î¬O¿ï¾Ü´Ñ¤l */ + /* ¿ï¾Ü´Ñ¤l */ + if(brd[my][mx].out==1) + { + if(brd[my][mx].color != color) + { + *b=-1; + break; + } + if(mly<0) /*¥i¥H¿ï¾Ü*/ + { + mly=my;mlx=mx; + draw_line(my,mx); + *b=-1; + break; + } + else if(mly == my && mlx == mx) /*¤£¿ï¤F*/ + { + mly=-1;mlx=-1; + draw_line(my,-1); + }else + { + draw_line(mly,-1); + mly=my;mlx=mx; + if(brd[mly][mlx].value == 1) fix=1; + draw_line(my,mx); + } + *b=-1; + break; + } + /* ½¶}´Ñ¤l */ + if(mly >=0 ){ *b=-1; break;} /*¥»¨Ó´N¬O½¶}ªº*/ + /* ¨M©w¤@¶}©lªºÃC¦â */ + if(currutmp->color=='.'){ + if(uin->color!='1' && uin->color!='0') + currutmp->color=(brd[my][mx].color)?'1':'0'; + else + currutmp->color=(uin->color=='0')?'1':'0';} + brd[my][mx].out=1; + draw_line(my,-1); + move(cury[my],curx[mx]); + *b=0; + break; + case 'u': + move(0,0);clrtoeol(); + prints("%s¦â%s cont=%d",(brd[my][mx].color == RED)?"¬õ":"¶Â",rname[brd[my][mx].value],cont); + *b=-1; + break; + case '\r': /* ¦Y or ²¾°Ê ly¸òlx¥²¶·¤j©ó0*/ + case '\n': + if( + mly >= 0 /* n¥ý¿ï¤l */ + && + brd[mly][mlx].color != brd[my][mx].color /* ¦P¦â¤£¯à²¾°Ê¤]¤£¯à¦Y */ + && + (Is_move(my,mx,mly,mlx) || Is_win(brd[mly][mlx],brd[my][mx],my,mx,mly,mlx)) + ) + { + if(fix && brd[my][mx].value<0) + { + *b=-1;return 0; + } + if(brd[my][mx].value>=0&&brd[my][mx].die==0) + { + if(!color) bcount--; + else rcount--; + move(cur_eaty,cur_eatx); + prints("%s",(color)?bname[brd[my][mx].value]:rname[brd[my][mx].value]); + if(cur_eatx>=26) + { cur_eatx=5;cur_eaty++; } + else + cur_eatx+=3; + } + brdswap(my,mx,mly,mlx); + draw_line(mly,-1); + draw_line( my,-1); + if(fix==1) *b=-1; + else { mly=-1;mlx=-1;*b=0; } + } + else *b=-1; + break; + default: + *b=-1; + } + + if(!rcount) + return -1; + else if(!bcount) + return -1; + if(*b == -1) return 0; + curr.y = my;curr.x = mx; curr.end=(!*b)?1:0; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(brd),0); + return 0; +} + +int main_dark(int fd,userinfo_t *uin) { + sint end=0,ch=1,go_on,i=0,cont=0; + char buf[16]; + *buf=0;fix=0; + currutmp->color='.'; // '.' ªí¥ÜÁÙ¨S¨M©wÃC¦â + rcount=16;bcount=16; // initialize + cur_eaty=18,cur_eatx=5; + brd_prints(); + if(currutmp->turn) + { + brd_rand(); + send(fd,&brd,sizeof(brd),0); + pprints(21,0," [1;37m[1;33m¡»[1;37m§A¬O¥ý¤â[m"); + pprints(22,0," [1;33m¡»[5;35m½ü¨ì§A¤U¤F[m"); + }else + { + recv(fd,&brd,sizeof(brd),0); + pprints(21,0," [1;33m¡»[1;37m§A¬O«á¤â[m"); + } + move(12,3); + prints("%s[0³Ó0±Ñ][5;31m¢þ¢û[1;37m.[m%s[0³Ó0±Ñ]",currutmp->userid,currutmp->mateid); + outs(" + [1;36m¢®¢¬[1;31m¥\\¯àªí[1;36m¢¢®¢¢¬¢®¢[m + [1;36m¢¬[1;33m ¡ô¡ö¡õ¡÷[1;37m: [1;35m²¾°Ê[m + [1;36m¢®[1;33m ¢û[1;37m: [1;35m ¿ï¤l,½¤l[m + [1;36m¢¬[1;33m enter[1;37m: [1;35m ¦Y´Ñ,©ñ´Ñ[m +¡@[1;33m¤w¸g¸Ñ¨Mªº[1;37m:[1;36m¡@¡@ ¢®[1;33m ¢ø[1;37m: [1;35m ¦X´Ñ[m + ¡@¡@ [1;36m¢¬[1;33m ¢ù[1;37m: [1;35m »{¿é[m + [1;36m¢®[1;33m ¢ë[1;37m: [1;35m ´«Ãä[m"); + + if(currutmp->turn) move(cury[0],curx[0]); + + add_io(fd, 0); + while(end<=0) + { + if(uin->turn=='w' || currutmp->turn=='w') { end=-1; break; } + + ch = igetkey(); + if(ch == I_OTHERDATA) + { + ch=recv(fd,&curr,sizeof(curr),0); + if(ch!=sizeof(curr)) + { + if(uin->turn=='e') { end=-3;break; } + else if(uin->turn!='w') { end=-1; currutmp->turn='w'; break; } + end=-1; break; + } + + if(curr.end==-3) pprints(23,30,"\033[33mn¨D¦X´Ñ\033[m"); + else if(curr.end==-4) pprints(23,30,"\033[33mn¨D´«Ãä\033[m"); + else if(curr.end==-5) pprints(23,30,"\033[33mn¨D³s¦Y\033[m"); + else pprints(23,30,""); + + recv(fd,&brd,sizeof(brd),0); + my=curr.y;mx=curr.x; + redraw(); + if(curr.end) + pprints(22,0," [1;33m¡»[5;35m½ü¨ì§A¤U¤F[m"); + move(cury[my],curx[mx]); + }else + { + if(currutmp->turn=='p') + { + if(ch=='y') { end=-3; currutmp->turn='e'; break; } + else { pprints(23,30,""); *buf=0; currutmp->turn=(uin->turn)?0:1; } + }else if(currutmp->turn=='c') + { + if(ch=='y') { currutmp->color=(currutmp->color=='1')?'0':'1'; + uin->color=(uin->color=='1')?'0':'1'; + pprints(21,0,(currutmp->color=='1')?" \033[1;33m¡»[1;31m§A«ù¬õ¦â´Ñ\033[m":" \033[1;33m¡»[1;36m§A«ù¶Â¦â´Ñ\033[m"); + } + else { pprints(23,30,""); currutmp->turn=(uin->turn)?0:1; } + }else if(currutmp->turn=='g') + { + if(ch=='y') { + cont=1; + pprints(21,0," \033[1;33m¡»[1;31m§A«ù¬õ¦â´Ñ\033[m ¥i³s¦Y"); + } + else { pprints(23,30,""); currutmp->turn=(uin->turn)?0:1; } + } + + if(currutmp->turn==1) + { + if(uin->turn=='g') { cont=1;uin->turn=(currutmp->turn)?0:1; pprints(21,10,"¥i³s¦Y"); } + end=playing(fd,currutmp->color-'0',ch,&go_on,uin); + + if(end == -1) { currutmp->turn='w';break; } + else if(end == -2) { uin->turn='w';break; } + else if(end == -3) { + uin->turn='p';curr.end=-3; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(buf),0); + continue; + } + else if(end == -4) { + if(currutmp->color!='1'&&currutmp->color!='0') + continue; + uin->turn='c';i=0;curr.end=-4; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(buf),0); + continue; + } + else if(end == -5) { + uin->turn='g';curr.end=-5; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(buf),0); + continue; + } + if(!i && currutmp->color=='1') + { pprints(21,0," \033[1;33m¡»[1;31m§A«ù¬õ¦â´Ñ\033[m");i++;move(cury[my],curx[mx]); } + if(!i && currutmp->color=='0') + { pprints(21,0," \033[1;33m¡»[1;36m§A«ù¶Â¦â´Ñ\033[m");i++;move(cury[my],curx[mx]); } + + if(uin->turn == 'e') { end=-3; break; } + if(go_on < 0) continue; + + move(22,0);clrtoeol(); + prints(" [1;33m¡»[1;37m½ü¨ì%s¤U §O©È§O©È ¥LºâÔ£¦Ì[m",currutmp->mateid); + currutmp->turn = 0; + uin->turn = 1; + }else + { + if(ch == 'q'){uin->turn='w';break;} + move(22,0);clrtoeol(); + prints(" [1;33m¡»[1;37m½ü¨ì%s¤U §O©È§O©È ¥LºâÔ£¦Ì[m",currutmp->mateid); + } + } + } + + switch(end) + { + case -1: + case -2: + if(currutmp->turn=='w'){ move(22,0);clrtoeol();prints("[1;31m§AŤF.. ¯u¬O®¥³ß~~[m");} + else {move(22,0);clrtoeol();prints("[1;31m¿é±¼¤F°Õ.....¤U¦¸Åý¥L¦n¬Ý!![m");} + break; + case -3: + pprints(22,0,"[1;31m¦X´Ñò!! ¤U¦¸¦b¤À°ª¤U§a ^_^[m"); + break; + default: + add_io(0,0); + close(fd); + pressanykey(); + return 0; + } + add_io(0,0); + close(fd); + pressanykey(); + return 0; +} diff --git a/mbbsd/descrypt.c b/mbbsd/descrypt.c new file mode 100644 index 00000000..3bb0a5e5 --- /dev/null +++ b/mbbsd/descrypt.c @@ -0,0 +1,616 @@ +/* $Id: descrypt.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ + +/* + * FreeSec: libcrypt for NetBSD + * + * Copyright (c) 1994 David Burren + * All rights reserved. + * + * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet + * crypt.c should now *only* export crypt(), in order to make + * binaries of libcrypt exportable from the USA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/secure/lib/libcrypt/crypt.c,v 1.11 1999/08/28 01:30:24 peter Exp $ + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren <davidb@werj.com.au>. + * + * An excellent reference on the underlying algorithm (and related + * algorithms) is: + * + * B. Schneier, Applied Cryptography: protocols, algorithms, + * and source code in C, John Wiley & Sons, 1994. + * + * Note that in that book's description of DES the lookups for the initial, + * pbox, and final permutations are inverted (this has been brought to the + * attention of the author). A list of errata for this book has been + * posted to the sci.crypt newsgroup by the author and is available for FTP. + * + * ARCHITECTURE ASSUMPTIONS: + * This code assumes that u_longs are 32 bits. It will probably not + * operate on 64-bit machines without modifications. + * It is assumed that the 8-byte arrays passed by reference can be + * addressed as arrays of u_longs (ie. the CPU is not picky about + * alignment). + */ + +#ifndef HAVE_DES_CRYPT + +#include <sys/types.h> +#include <sys/param.h> +#include <pwd.h> +#include <string.h> + +static unsigned char IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static unsigned char inv_key_perm[64]; +static unsigned char u_key_perm[56]; +static unsigned char key_perm[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +static unsigned char key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static unsigned char inv_comp_perm[56]; +static unsigned char comp_perm[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static unsigned char u_sbox[8][64]; +static unsigned char sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static unsigned char un_pbox[32]; +static unsigned char pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +static unsigned long bits32[32] = { + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +static unsigned long saltbits; +static long old_salt; +static unsigned long *bits28, *bits24; +static unsigned char init_perm[64], final_perm[64]; +static unsigned long en_keysl[16], en_keysr[16]; +static unsigned long de_keysl[16], de_keysr[16]; +static int des_initialised = 0; +static unsigned char m_sbox[4][4096]; +static unsigned long psbox[4][256]; +static unsigned long ip_maskl[8][256], ip_maskr[8][256]; +static unsigned long fp_maskl[8][256], fp_maskr[8][256]; +static unsigned long key_perm_maskl[8][128], key_perm_maskr[8][128]; +static unsigned long comp_maskl[8][128], comp_maskr[8][128]; +static unsigned long old_rawkey0, old_rawkey1; + +static unsigned char ascii64[] = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +/* 0000000000111111111122222222223333333333444444444455555555556666 */ +/* 0123456789012345678901234567890123456789012345678901234567890123 */ + +static int ascii_to_bin(char ch) { + if(ch > 'z') + return 0; + if(ch >= 'a') + return ch - 'a' + 38; + if(ch > 'Z') + return 0; + if(ch >= 'A') + return ch - 'A' + 12; + if(ch > '9') + return 0; + if(ch >= '.') + return ch - '.'; + return 0; +} + +static void des_init() { + int i, j, b, k, inbit, obit; + unsigned long *p, *il, *ir, *fl, *fr; + + old_rawkey0 = old_rawkey1 = 0L; + saltbits = 0L; + old_salt = 0L; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for(i = 0; i < 8; i++) + for(j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for(b = 0; b < 4; b++) + for(i = 0; i < 64; i++) + for(j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]; + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for(i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = i; + inv_key_perm[i] = 255; + } + + /* + * Invert the key permutation and initialise the inverted key + * compression permutation. + */ + for(i = 0; i < 56; i++) { + u_key_perm[i] = key_perm[i] - 1; + inv_key_perm[key_perm[i] - 1] = i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for(i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = i; + } + + /* + * Set up the OR-mask arrays for the initial and final permutations, + * and for the key initial and compression permutations. + */ + for(k = 0; k < 8; k++) { + for(i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0L; + *(ir = &ip_maskr[k][i]) = 0L; + *(fl = &fp_maskl[k][i]) = 0L; + *(fr = &fp_maskr[k][i]) = 0L; + for(j = 0; j < 8; j++) { + inbit = 8 * k + j; + if(i & bits8[j]) { + if((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for(i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0L; + *(ir = &key_perm_maskr[k][i]) = 0L; + for(j = 0; j < 7; j++) { + inbit = 8 * k + j; + if(i & bits8[j + 1]) { + if((obit = inv_key_perm[inbit]) == 255) + continue; + if(obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0L; + *(ir = &comp_maskr[k][i]) = 0L; + for(j = 0; j < 7; j++) { + inbit = 7 * k + j; + if(i & bits8[j + 1]) { + if((obit=inv_comp_perm[inbit]) == 255) + continue; + if(obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } + + /* + * Invert the P-box permutation, and convert into OR-masks for + * handling the output of the S-box arrays setup above. + */ + for(i = 0; i < 32; i++) + un_pbox[pbox[i] - 1] = i; + + for(b = 0; b < 4; b++) + for(i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } + + des_initialised = 1; +} + +static void setup_salt(long salt) { + unsigned long obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0L; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + +static int des_setkey(const char *key) { + unsigned long k0, k1, rawkey0, rawkey1; + int shifts, round; + + if(!des_initialised) + des_init(); + + rawkey0 = ntohl(*(unsigned long *) key); + rawkey1 = ntohl(*(unsigned long *) (key + 4)); + + if((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return 0; + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * Do key permutation and split into two 28-bit subkeys. + */ + k0 = key_perm_maskl[0][rawkey0 >> 25] + | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskl[4][rawkey1 >> 25] + | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; + k1 = key_perm_maskr[0][rawkey0 >> 25] + | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskr[4][rawkey1 >> 25] + | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; + /* + * Rotate subkeys and do compression permutation. + */ + shifts = 0; + for(round = 0; round < 16; round++) { + unsigned long t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + + de_keysl[15 - round] = + en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] + | comp_maskl[1][(t0 >> 14) & 0x7f] + | comp_maskl[2][(t0 >> 7) & 0x7f] + | comp_maskl[3][t0 & 0x7f] + | comp_maskl[4][(t1 >> 21) & 0x7f] + | comp_maskl[5][(t1 >> 14) & 0x7f] + | comp_maskl[6][(t1 >> 7) & 0x7f] + | comp_maskl[7][t1 & 0x7f]; + + de_keysr[15 - round] = en_keysr[round] = + comp_maskr[0][(t0 >> 21) & 0x7f] + | comp_maskr[1][(t0 >> 14) & 0x7f] + | comp_maskr[2][(t0 >> 7) & 0x7f] + | comp_maskr[3][t0 & 0x7f] + | comp_maskr[4][(t1 >> 21) & 0x7f] + | comp_maskr[5][(t1 >> 14) & 0x7f] + | comp_maskr[6][(t1 >> 7) & 0x7f] + | comp_maskr[7][t1 & 0x7f]; + } + return 0; +} + +static int do_des(unsigned long l_in, unsigned long r_in, unsigned long *l_out, + unsigned long *r_out, int count) { + /* + * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. + */ + unsigned long l, r, *kl, *kr, *kl1, *kr1; + unsigned long f, r48l, r48r; + int round; + + if(count == 0) { + return 1; + } else if(count > 0) { + /* + * Encrypting + */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* + * Decrypting + */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* + * Do initial permutation (IP). + */ + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; + + while(count--) { + /* + * Do each round. + */ + kl = kl1; + kr = kr1; + round = 16; + while(round--) { + /* + * Expand R to 48 bits (simulate the E-box). + */ + r48l = ((r & 0x00000001) << 23) + | ((r & 0xf8000000) >> 9) + | ((r & 0x1f800000) >> 11) + | ((r & 0x01f80000) >> 13) + | ((r & 0x001f8000) >> 15); + + r48r = ((r & 0x0001f800) << 7) + | ((r & 0x00001f80) << 5) + | ((r & 0x000001f8) << 3) + | ((r & 0x0000001f) << 1) + | ((r & 0x80000000) >> 31); + /* + * Do salting for crypt() and friends, and + * XOR with the permuted key. + */ + f = (r48l ^ r48r) & saltbits; + r48l ^= f ^ *kl++; + r48r ^= f ^ *kr++; + /* + * Do sbox lookups (which shrink it back to 32 bits) + * and do the pbox permutation at the same time. + */ + f = psbox[0][m_sbox[0][r48l >> 12]] + | psbox[1][m_sbox[1][r48l & 0xfff]] + | psbox[2][m_sbox[2][r48r >> 12]] + | psbox[3][m_sbox[3][r48r & 0xfff]]; + /* + * Now that we've permuted things, complete f(). + */ + f ^= l; + l = r; + r = f; + } + r = l; + l = f; + } + /* + * Do final permutation (inverse of IP). + */ + *l_out = fp_maskl[0][l >> 24] + | fp_maskl[1][(l >> 16) & 0xff] + | fp_maskl[2][(l >> 8) & 0xff] + | fp_maskl[3][l & 0xff] + | fp_maskl[4][r >> 24] + | fp_maskl[5][(r >> 16) & 0xff] + | fp_maskl[6][(r >> 8) & 0xff] + | fp_maskl[7][r & 0xff]; + *r_out = fp_maskr[0][l >> 24] + | fp_maskr[1][(l >> 16) & 0xff] + | fp_maskr[2][(l >> 8) & 0xff] + | fp_maskr[3][l & 0xff] + | fp_maskr[4][r >> 24] + | fp_maskr[5][(r >> 16) & 0xff] + | fp_maskr[6][(r >> 8) & 0xff] + | fp_maskr[7][r & 0xff]; + return 0; +} + +char *crypt(char *key, char *setting) { + unsigned long count, salt, l, r0, r1, keybuf[2]; + unsigned char *p, *q; + static unsigned char output[21]; + + if(!des_initialised) + des_init(); + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (unsigned char *)keybuf; + while(q - (unsigned char *)keybuf - 8) { + if((*q++ = *key << 1)) + key++; + } + if(des_setkey((unsigned char *)keybuf)) + return NULL; + + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + salt = (ascii_to_bin(setting[1]) << 6) + | ascii_to_bin(setting[0]); + + output[0] = setting[0]; + /* + * If the encrypted password that the salt was extracted from + * is only 1 character long, the salt will be corrupted. We + * need to ensure that the output string doesn't have an extra + * NUL in it! + */ + output[1] = setting[1] ? setting[1] : output[0]; + + p = output + 2; + + setup_salt(salt); + /* + * Do it. + */ + if(do_des(0L, 0L, &r0, &r1, count)) + return NULL; + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return output; +} +#endif diff --git a/mbbsd/dice.c b/mbbsd/dice.c new file mode 100644 index 00000000..d64ce63c --- /dev/null +++ b/mbbsd/dice.c @@ -0,0 +1,447 @@ +/* $Id: dice.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +#define DICE_TXT BBSHOME "/etc/dice.txt" +#define DICE_DATA BBSHOME "/etc/dice.data" +#define DICE_WIN BBSHOME "/etc/windice.log" +#define DICE_LOST BBSHOME "/etc/lostdice.log" + +#define B_MAX 500 +#define B_MIN 10 +#define B_COMMON 1 +#define B_TIMES 5 +#define B_THIRD 3 + +extern int usernum; +static int flag[100], value[100]; + +typedef struct dicedata_t { + int mybet; + int mymoney; +} dicedata_t; + +static void set_bingo(int bet[]) { + int i, j = 0, k = 0, m = 0; + + for(i = 0; i < 3; i++) + for(j = 2; j > i; j--) + if(bet[j] < bet[j - 1]) { + m = bet[j]; + bet[j] = bet[j - 1]; + bet[j - 1]=m; + } + + for(i = 0; i < 100; i++) + flag[i] = 0; + + for(i = 0; i < 3; i++) + flag[bet[i]]++; + j = bet[0] + bet[1] + bet[2]; + + if((abs(bet[1] - bet[0]) == 1 && abs(bet[2] - bet[0]) == 2) || + (abs(bet[2] - bet[0]) == 1 && abs(bet[1] - bet[0]) == 2)) + flag[66] = B_TIMES; + + if(j < 10){ + flag[7] = B_COMMON; + for(i = 0; i < 3; i++) + if(bet[i] == 4) + flag[74] = B_TIMES; + } else if(j > 11) { + flag[8] = B_COMMON; + for(i = 0; i < 3; i++) + if(bet[i] == 3) + flag[83]=B_TIMES; + } else + flag[11] = B_THIRD; + + for(i = 0; i < 3; i++) + for(j = i; j < 3; j++) { + m = bet[i]; + k = bet[j]; + if(m != k) + flag[m * 10 + k] = B_TIMES; + } +} + +static int bingo(int mybet) { + return flag[mybet]; +} + +int IsNum(char *a, int n) { + int i; + + for(i = 0; i < n; i++) + if (a[i] > '9' || a[i] < '0' ) + return 0; + return 1; +} + +int IsSNum(char *a) { + int i; + + for(i = 0; a[i]; i++) + if(a[i] > '9' || a[i] < '0') + return 0; + return 1; +} + +static void show_data(void) { + move(0, 0); + prints("\033[31m ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{\033[m\n"); + prints("\033[45;37m¿²v¤@\033[m\033[31m ¢x \033[33m[1]©ã¤@ÂI [2]©ã¤GÂI " + "[3]©ã¤TÂI [4]©ã¥|ÂI [5]©ã¤ÂI [6]©ã¤»ÂI \033[31m ¢x\033[m\n"); + prints("\033[31m ¢x \033[33m[7]©ã¤p [8]©ã¤j " + " \033[31m ¢x\033[m\n"); + prints("\033[31m ¢x " + " ¢x\033[m\n"); + prints("\033[45;37m½ß²v¤T\033[m\033[31m ¢x \033[33m[11]©ã¤¤(Á`ÂI¼Æµ¥©ó11" + "©Î10) \033[31m ¢x\033[m\n"); + prints("\033[31m ¢x " + " ¢x\033[m\n"); + prints("\033[45;37m½ß²v¤\033[m\033[31m ¢x \033[33m[74]©ã¤p¥B¥|ÂI [83]©ã" + "¤j¥B¤TÂI [66]©ã³s¸¹ \033[31m ¢x\033[m\n"); + prints("\033[31m ¢x " + " ¢x\033[m\n"); + prints("\033[31m ¢x \033[33m[12]©ã¤@¤GÂI [13]©ã¤@¤TÂI [14]©ã¤@¥|ÂI" + " [15]©ã¤@¤ÂI [16]©ã¤@¤»ÂI\033[31m ¢x\033[m\n"); + prints("\033[31m ¢x \033[33m[23]©ã¤G¤TÂI [24]©ã¤G¥|ÂI [25]©ã¤G¤ÂI" + " [26]©ã¤G¤»ÂI [34]©ã¤T¥|ÂI\033[31m ¢x\033[m\n"); + prints("\033[31m ¢x \033[33m[35]©ã¤T¤ÂI [36]©ã¤T¤»ÂI [45]©ã¥|¤ÂI" + " [46]©ã¥|¤»ÂI [56]©ã¤¤»ÂI\033[31m ¢x\033[m\n"); + prints("\033[31m ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}\033[m\n"); +} + +static void show_count(int index, int money) { + int i = 0, count = 2, j, k; + + value[index] += money; + move(14,0); + clrtoline(18); + for(i = 1, j = 13; i <= 8; i++, count += 12) { + if(i == 6) { + j = 14; + count = 2; + } + move(j,count); + prints("[%2d]:%d ", i, value[i]); + } + + count = 2; + i = 15; + for(j = 1; j <= 5; j++) + for(k = j + 1; k <= 6; k++, count += 12) { + if(j == 2 && k == 4) { + i = 16; + count = 2; + } else if(j==4 && k==5) { + i = 17; + count = 2; + } + move(i,count); + prints("[%d%d]:%d ", j, k, value[j * 10 + k]); + } + + move(18,2); + prints("[11]:%d",value[11]); + move(18,14); + prints("[66]:%d",value[66]); + move(18,26); + prints("[74]:%d",value[74]); + move(18,38); + prints("[83]:%d",value[83]); +} + +static int check_index(int index) { + int i,tp[] = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 23, 24, 25, + 26, 34, 35, 36, 45, 46, 56, 66, 74, 83}; + if(index < 0 || index > 100) + return 0; + for(i = 0; i < 27; i++) + if(index == tp[i]) + return 1; + return 0; +} + +extern userec_t cuser; + +static int del(int total, dicedata_t *table) { + int index, money; + char data[10]; + int i; + + while(1) { + do { + move(22,0); + clrtoeol(); + getdata(21, 0, "¿é¤J°h¿ïªº¼Æ¦r(¥´qÂ÷¶}): ", data, 3, LCECHO); + if(data[0] == 'q' || data[0] == 'Q') + return 0; + } while(!IsNum(data,strlen(data))); + + index = atoi(data); + for(i = 0; i < total; i++) { + if(table[i].mybet == index){ + do { + getdata(21, 0, "¦h¤Ö¿ú: ", data, 10, LCECHO); + } while(!IsNum(data,strlen(data))); + money = atoi(data); + if(money>table[i].mymoney) { + move(22,0); + clrtoeol(); + prints("¤£°÷¦©°Õ"); + i--; + continue; + } + demoney(money); + move(19,0); + clrtoeol(); + prints("§A²{¦b¦³ %u Ptt$¼Ú", cuser.money); + table[i].mymoney -= money; + show_count(index, -money); + break; + } + } + } + return 0; +} + +static int IsLegal(char *data) { + int money = atoi(data); + if(IsNum(data,strlen(data)) && money<=B_MAX && money>=B_MIN) + return money; + return 0; +} + +static void show_output(int bet[]) { + int i, j = 10; + + move(12,0); + clrtoline(17); + /* ¼È®É°°Õ ¦]¬°¨º¦Uclrtoline©Ç©Çªº */ + for(i = 13; i <= 18; i++) { + move(i,0); + prints(" "); + } + move(12,0); + prints("\033[1;31m ¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢{\033[m\n\n\n\n\n\n"); + prints("\033[1;31m ¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢}\033[m"); + for(i = 0; i < 3; i++, j += 25) { + switch(bet[i]) { + case 1: + move(13, j);prints("\033[37m¢~¢w¢w¢w¢w¢¡\033[m"); + move(14, j);prints("\033[37m¢x ¢x\033[m"); + move(15, j);prints("\033[37m¢x ¡´ ¢x\033[m"); + move(16, j);prints("\033[37m¢x ¢x\033[m"); + move(17, j);prints("\033[37m¢¢¢w¢w¢w¢w¢£\033[m"); + break; + case 2: + move(13, j);prints("\033[37m¢~¢w¢w¢w¢w¢¡\033[m"); + move(14, j);prints("\033[37m¢x ¡´¢x\033[m"); + move(15, j);prints("\033[37m¢x ¢x\033[m"); + move(16, j);prints("\033[37m¢x¡´ ¢x\033[m"); + move(17, j);prints("\033[37m¢¢¢w¢w¢w¢w¢£\033[m"); + break; + case 3: + move(13, j);prints("\033[37m¢~¢w¢w¢w¢w¢¡\033[m"); + move(14, j);prints("\033[37m¢x ¡´¢x\033[m"); + move(15, j);prints("\033[37m¢x ¡´ ¢x\033[m"); + move(16, j);prints("\033[37m¢x¡´ ¢x\033[m"); + move(17, j);prints("\033[37m¢¢¢w¢w¢w¢w¢£\033[m"); + break; + case 4: + move(13, j);prints("\033[37m¢~¢w¢w¢w¢w¢¡\033[m"); + move(14, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(15, j);prints("\033[37m¢x ¢x\033[m"); + move(16, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(17, j);prints("\033[37m¢¢¢w¢w¢w¢w¢£\033[m"); + break; + case 5: + move(13, j);prints("\033[37m¢~¢w¢w¢w¢w¢¡\033[m"); + move(14, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(15, j);prints("\033[37m¢x ¡´ ¢x\033[m"); + move(16, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(17, j);prints("\033[37m¢¢¢w¢w¢w¢w¢£\033[m"); + break; + case 6: + move(13, j);prints("\033[37m¢~¢w¢w¢w¢w¢¡\033[m"); + move(14, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(15, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(16, j);prints("\033[37m¢x¡´ ¡´¢x\033[m"); + move(17, j);prints("\033[37m¢¢¢w¢w¢w¢w¢£\033[m"); + break; + } + } +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 + +int dice_main(void) { + char input[10],data[256], ch; + dicedata_t table[256]; + int bet[3], index, money = 0, i, ya = 0, j, total, sig = 0; + FILE *winfp/* , *lostfp */; + + more(DICE_TXT, NA); + reload_money(); + if(cuser.money < 10){ + move(19,0); + prints("\033[1;37m¶W¹L¤Q¤¸¦A¨Óª±§a~~\033[m"); + pressanykey(); + return 0; + } + + lockreturn0(DICE, LOCK_MULTI); + winfp = fopen(DICE_WIN,"a"); + /*lostfp = fopen(DICE_LOST,"a");*/ + if(!winfp /*|| !lostfp*/) + return 0; + + do { + total = 0; i = 0; + ch = 'y'; + clear(); + show_data(); + for(j = 0; j < 3; j++) + bet[j] = rand() % 6 + 1; + + for(j = 0; j < 100; j++) + value[j] = 0; + + while(1) { + move(19,0); + prints("\033[1;32m§A²{¦b¦³\033[1;31m %u \033[1;32mPtt$¼Ú\033[m", + cuser.money); + getdata(20, 0, "\033[1;37m¼Æ¦r:¥[¿ï d:°h¿ï s:¶}©l©ÎÂ÷¶}\033[m: ", + input, 5, LCECHO); + reload_money(); + if(input[0] != 's' && input[0] != 'd' && cuser.money < 10) { + move(21, 0); + clrtoeol(); + prints("\033[1;37m¶W¹L¤Q¤¸¤~¯à½ä~\033[m"); + continue; + } + if(input[0] == 'd' || input[0] == 'D') { + del(i, table); + continue; + } + if(input[0] == 's' || input[0] == 'S') + break; + + if(!IsNum(input,strlen(input))) + continue; + + index=atoi(input); + if(check_index(index) == 0) + continue; +/*¿é¤J¿úªºloop*/ + while(1) { + if(cuser.money < 10) + break; + getdata(21, 0, "\033[1;32m½ä¦h¤Ö¿ú©O\033[1;37m(¤j©ó10 ¤p©ó500)" + "\033[m: ", input, 9, LCECHO); + if(!(money = IsLegal(input))||input[0] == '0') + continue; + reload_money(); + if(money > cuser.money) + continue; + for(j = 0, sig = 0; j < i; j++) + if(table[j].mybet == index) { + if(table[j].mymoney == B_MAX) + sig = 2; + else if(table[j].mymoney+money>B_MAX) { + sig = 1; + break; + } else { + vice(money,"»ë¤l"); + table[j].mymoney += money; + j = -1; + break; + } + } + if(sig == 2) + break; + if(sig == 1) + continue; + if(j != -1) { + bzero((char*)&table[i], sizeof(dicedata_t)); + table[i].mybet = index; + table[i++].mymoney = money; + vice(money,"»ë¤l"); + } + break; + } + reload_money(); + move(19,0); + prints("\033[1;32m§A²{¦b¦³ \033[1;31m%u\033[1;32m Ptt$¼Ú", + cuser.money); + if(sig != 2) + show_count(index, money); + } + + if(i == 0) { + fclose(winfp); + /*fclose(lostfp);*/ + unlockutmpmode(); + return 0; + } + + show_output(bet); + set_bingo(bet); + + for(j = 0; j < i; j++) { + if(table[j].mymoney <= 0) + continue; + ya = bingo(table[j].mybet); + if(ya == 0) { + /*sprintf(data, "%-15s ¿é¤F %-8d $", cuser.userid, + table[j].mymoney); + fprintf(lostfp, "%s\n", data);*/ + continue; + } + demoney(table[j].mymoney * ya + table[j].mymoney); + total += table[j].mymoney * ya; + if (table[j].mymoney * ya > 500){ /* ¶W¹L500¶ô¿ú¤~°µlog ´î¤Öio */ + sprintf(data, "%-15s ©ã%-2d¿ï¶µ%-8d¶ô¿ú ¤¤¤F%d¿ ²bÁÈ:%-8d\n", + cuser.userid,table[j].mybet, + table[j].mymoney, ya, table[j].mymoney * ya); + fputs(data,winfp); + } + ya = 0; + } + + if(total > 0) { + move(21,0); + prints("\033[1;32m§AŤF \033[1;31m%d\033[1;32m Ptt$ ò~~" + " \033[m", total); + } else { + move(21,0); + clrtoeol(); + prints("\033[1;32m¯u¥i±¤ ¤U¦¸¦A¨Ó¸I¸I¹B®ð§a\033[m"); + } + + move(19,0); + clrtoeol(); + prints("\033[1;32m§A²{¦b¦³ \033[1;31m%u\033[1;32m Ptt$¼Ú\033[m", + cuser.money); + + getdata(23, 0, "\033[1;32mÄ~Äò¾Ä°«[\033[1;37my/n\033[1;32m]\033[m: ", + input, 2, LCECHO); + } while(input[0] != 'n' && input[0] != 'N'); + fclose(winfp); + /*fclose(lostfp);*/ + unlockutmpmode(); + return 0; +} diff --git a/mbbsd/edit.c b/mbbsd/edit.c new file mode 100644 index 00000000..19f437af --- /dev/null +++ b/mbbsd/edit.c @@ -0,0 +1,2256 @@ +/* $Id: edit.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "config.h" +#include "common.h" +#include "modes.h" +#include "perm.h" +#include "proto.h" + +#define WRAPMARGIN (511) + +typedef struct textline_t { + struct textline_t *prev; + struct textline_t *next; + int len; + char data[WRAPMARGIN + 1]; +} textline_t; + +extern int current_font_type; +extern char *str_author1; +extern char *str_author2; +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char quote_file[80]; +extern char quote_user[80]; +extern int curredit; +extern unsigned int currbrdattr; +extern char currboard[]; /* name of currently selected board */ +extern char *str_reply; +extern char *str_post1; +extern char *str_post2; +extern char *BBSName; +extern char fromhost[]; +extern unsigned int currstat; +extern crosspost_t postrecord; +extern userinfo_t *currutmp; +extern int KEY_ESC_arg; +extern char reset_color[]; +extern char trans_buffer[256]; + +#define KEEP_EDITING -2 +#define BACKUP_LIMIT 100 +#define SCR_WIDTH 80 + +enum { + NOBODY, MANAGER, SYSOP +}; + +static textline_t *firstline = NULL; +static textline_t *lastline = NULL; +static textline_t *currline = NULL; +static textline_t *blockline = NULL; +static textline_t *top_of_win = NULL; +static textline_t *deleted_lines = NULL; + +extern int local_article; +extern char real_name[20]; +static char line[WRAPMARGIN + 2]; +static int ifuseanony=0; +static int currpnt, currln, totaln; +static int curr_window_line; +static int redraw_everything; +static int insert_character; +static int my_ansimode; +static int raw_mode; +static int edit_margin; +static int blockln = -1; +static int blockpnt; +static int prevln = -1; +static int prevpnt; +static int line_dirty; +static int indent_mode; +static int insert_c = ' '; + +static char fp_bak[] = "bak"; + +char save_title[STRLEN]; + +/* °O¾ÐÅéºÞ²z»P½s¿è³B²z */ +static void indigestion(i) { + fprintf(stderr, "ÄY«¤º¶Ë %d\n", i); +} + +/* Thor: ansi ®y¼ÐÂà´« for color ½s¿è¼Ò¦¡ */ +static int ansi2n(int ansix, textline_t * line) { + register char *data, *tmp; + register char ch; + + data = tmp = line->data; + + while(*tmp) { + if(*tmp == KEY_ESC) { + while((ch = *tmp) && !isalpha(ch)) + tmp++; + if(ch) + tmp++; + continue; + } + if(ansix <= 0) + break; + tmp++; + ansix--; + } + return tmp - data; +} + +static int n2ansi(int nx, textline_t * line) { + register int ansix = 0; + register char *tmp,*nxp; + register char ch; + + tmp = nxp = line->data; + nxp += nx; + + while(*tmp) { + if(*tmp == KEY_ESC) { + while((ch = *tmp) && !isalpha(ch)) + tmp++; + if(ch) + tmp++; + continue; + } + if(tmp >= nxp) + break; + tmp++; + ansix++; + } + return ansix; +} + +/* ¿Ã¹õ³B²z¡G»²§U°T®§¡BÅã¥Ü½s¿è¤º®e */ +static void edit_msg() { + static char *edit_mode[2] = {"¨ú¥N", "´¡¤J"}; + register int n = currpnt; + + if(my_ansimode) /* Thor: §@ ansi ½s¿è */ + n = n2ansi(n, currline); + n++; + move(b_lines, 0); + clrtoeol(); + prints("\033[%sm ½s¿è¤å³¹ \033[31;47m (Ctrl-Z)\033[30m»²§U»¡©ú " + "\033[31;47m(^G)\033[30m´¡¤J¹Ï¤å®w \033[31m(^X,^Q)" + "\033[30mÂ÷¶}ùø%s¢x%c%c%c%cùø %3d:%3d \033[m", + "37;44", + edit_mode[insert_character], + my_ansimode ? 'A' : 'a', indent_mode ? 'I' : 'i', + 'P' , raw_mode ? 'R' : 'r', + currln + 1, n); +} + +static textline_t *back_line(textline_t *pos, int num) { + while(num-- > 0) { + register textline_t *item; + + if(pos && (item = pos->prev)) { + pos = item; + currln--; + } + } + return pos; +} + +static textline_t *forward_line(textline_t *pos, int num) { + while(num-- > 0) { + register textline_t *item; + + if(pos && (item = pos->next)) { + pos = item; + currln++; + } + } + return pos; +} + +static int getlineno() { + int cnt = 0; + textline_t *p = currline; + + while(p && (p != top_of_win)) { + cnt++; + p = p->prev; + } + return cnt; +} + +static char *killsp(char *s) { + while(*s == ' ') + s++; + return s; +} + +static textline_t *alloc_line() { + register textline_t *p; + + if((p = (textline_t *)malloc(sizeof(textline_t)))) { + memset(p, 0, sizeof(textline_t)); + return p; + } + + indigestion(13); + abort_bbs(0); + return NULL; +} + +/* append p after line in list. keeps up with last line */ +static void append(textline_t *p, textline_t *line) { + register textline_t *n; + + if((p->next = n = line->next)) + n->prev = p; + else + lastline = p; + line->next = p; + p->prev = line; +} + +/* + delete_line deletes 'line' from the list, + and maintains the lastline, and firstline pointers. +*/ + +static void delete_line(textline_t *line) { + register textline_t *p = line->prev; + register textline_t *n = line->next; + + if(!p && !n) { + line->data[0] = line->len = 0; + return; + } + if(n) + n->prev = p; + else + lastline = p; + if(p) + p->next = n; + else + firstline = n; + strcat(line->data, "\n"); + line->prev = deleted_lines; + deleted_lines = line; + totaln--; +} + +static int ask(char *prompt) { + int ch; + + move (0, 0); + clrtoeol (); + standout (); + prints ("%s", prompt); + standend (); + ch = igetkey (); + move (0, 0); + clrtoeol (); + return (ch); +} + +static int indent_spcs() { + textline_t* p; + int spcs; + + if(!indent_mode) + return 0; + + for(p = currline; p; p = p->prev) { + for(spcs = 0; p->data[spcs] == ' '; ++spcs); + if (p->data[spcs]) + return spcs; + } + return 0; +} + +/* split 'line' right before the character pos */ +static void split(textline_t *line, int pos) { + if(pos <= line->len) { + register textline_t *p = alloc_line(); + register char *ptr; + int spcs = indent_spcs(); + + totaln++; + + p->len = line->len - pos + spcs; + line->len = pos; + + memset(p->data, ' ', spcs); + p->data[spcs] = 0; + strcat(p->data, (ptr = line->data + pos)); + ptr[0] = '\0'; + append(p, line); + if(line == currline && pos <= currpnt) { + currline = p; + if(pos == currpnt) + currpnt = spcs; + else + currpnt -= pos; + curr_window_line++; + currln++; + } + redraw_everything = YEA; + } +} + +static void insert_char(int ch) { + register textline_t *p = currline; + register int i = p->len; + register char *s; + int wordwrap = YEA; + + if(currpnt > i) { + indigestion(1); + return; + } + if(currpnt < i && !insert_character) { + p->data[currpnt++] = ch; + /* Thor: ansi ½s¿è, ¥i¥Hoverwrite, ¤£»\¨ì ansi code */ + if(my_ansimode) + currpnt = ansi2n(n2ansi(currpnt, p),p); + } else { + while(i >= currpnt) { + p->data[i + 1] = p->data[i]; + i--; + } + p->data[currpnt++] = ch; + i = ++(p->len); + } + if(i < WRAPMARGIN) + return; + s = p->data + (i - 1); + while(s != p->data && *s == ' ') + s--; + while(s != p->data && *s != ' ') + s--; + if(s == p->data) { + wordwrap = NA; + s = p->data + (i - 2); + } + split(p, (s - p->data) + 1); + p = p->next; + i = p->len; + if(wordwrap && i >= 1) { + if(p->data[i - 1] != ' ') { + p->data[i] = ' '; + p->data[i + 1] = '\0'; + p->len++; + } + } +} + +static void insert_string(char *str) { + int ch; + + while((ch = *str++)) { + if(isprint2(ch) || ch == '\033') + insert_char(ch); + else if(ch == '\t') { + do { + insert_char(' '); + } while(currpnt & 0x7); + } else if(ch == '\n') + split(currline, currpnt); + } +} + +static int undelete_line() { + textline_t* p = deleted_lines; + textline_t* currline0 = currline; + textline_t* top_of_win0 = top_of_win; + int currpnt0 = currpnt; + int currln0 = currln; + int curr_window_line0 = curr_window_line; + int indent_mode0 = indent_mode; + + if(!deleted_lines) + return 0; + + indent_mode = 0; + insert_string(deleted_lines->data); + indent_mode = indent_mode0; + deleted_lines = deleted_lines->prev; + free(p); + + currline = currline0; + top_of_win = top_of_win0; + currpnt = currpnt0; + currln = currln0; + curr_window_line = curr_window_line0; + return 0; +} + +/* + 1) lines were joined and one was deleted + 2) lines could not be joined + 3) next line is empty + returns false if: + 1) Some of the joined line wrapped +*/ +static int join(textline_t *line) { + register textline_t *n; + register int ovfl; + + if(!(n = line->next)) + return YEA; + if(!*killsp(n->data)) + return YEA; + + ovfl = line->len + n->len - WRAPMARGIN; + if(ovfl < 0) { + strcat(line->data, n->data); + line->len += n->len; + delete_line(n); + return YEA; + } else { + register char *s; + + s = n->data + n->len - ovfl - 1; + while(s != n->data && *s == ' ') + s--; + while(s != n->data && *s != ' ') + s--; + if(s == n->data) + return YEA; + split(n, (s - n->data) + 1); + if(line->len + n->len >= WRAPMARGIN) { + indigestion(0); + return YEA; + } + join(line); + n = line->next; + ovfl = n->len - 1; + if(ovfl >= 0 && ovfl < WRAPMARGIN - 2) { + s = &(n->data[ovfl]); + if(*s != ' ') { + strcpy(s, " "); + n->len++; + } + } + return NA; + } +} + +static void delete_char() { + register int len; + + if((len = currline->len)) { + register int i; + register char *s; + + if(currpnt >= len) { + indigestion(1); + return; + } + for(i = currpnt, s = currline->data + i; i != len; i++, s++) + s[0] = s[1]; + currline->len--; + } +} + +static void load_file(FILE *fp) { + int indent_mode0 = indent_mode; + + indent_mode = 0; + while(fgets(line, WRAPMARGIN + 2, fp)) + insert_string(line); + fclose(fp); + indent_mode = indent_mode0; +} + +/* ¼È¦sÀÉ */ +char *ask_tmpbuf(int y) { + static char fp_buf[10] = "buf.0"; + static char msg[] = "½Ð¿ï¾Ü¼È¦sÀÉ (0-9)[0]: "; + + msg[19] = fp_buf[4]; + do { + if(!getdata(y, 0, msg, fp_buf + 4, 4, DOECHO)) + fp_buf[4] = msg[19]; + } while(fp_buf[4] < '0' || fp_buf[4] > '9'); + return fp_buf; +} + +static void read_tmpbuf(int n) { + FILE *fp; + char fp_tmpbuf[80]; + char tmpfname[] = "buf.0"; + char *tmpf; + char ans[4] = "y"; + + if(0 <= n && n <= 9) { + tmpfname[4] = '0' + n; + tmpf = tmpfname; + } else { + tmpf = ask_tmpbuf(3); + n = tmpf[4] - '0'; + } + + setuserfile(fp_tmpbuf, tmpf); + if(n != 0 && n != 5 && more(fp_tmpbuf, NA) != -1) + getdata(b_lines - 1, 0, "½T©wŪ¤J¶Ü(Y/N)?[Y]", ans, 4, LCECHO); + if(*ans != 'n' && (fp = fopen(fp_tmpbuf, "r"))) { + prevln = currln; + prevpnt = currpnt; + load_file(fp); + while(curr_window_line >= b_lines) { + curr_window_line--; + top_of_win = top_of_win->next; + } + } +} + +static void write_tmpbuf() { + FILE *fp; + char fp_tmpbuf[80], ans[4]; + textline_t *p; + + setuserfile(fp_tmpbuf, ask_tmpbuf(3)); + if(dashf(fp_tmpbuf)) { + more(fp_tmpbuf, NA); + getdata(b_lines - 1, 0, "¼È¦sÀɤw¦³¸ê®Æ (A)ªþ¥[ (W)Âмg (Q)¨ú®ø¡H[A] ", + ans, 4, LCECHO); + + if(ans[0] == 'q') + return; + } + + if((fp = fopen(fp_tmpbuf, (ans[0] == 'w' ? "w" : "a+")))) { + for(p = firstline; p; p = p->next) { + if(p->next || p->data[0]) + fprintf(fp, "%s\n", p->data); + } + fclose(fp); + } +} + +static void erase_tmpbuf() { + char fp_tmpbuf[80]; + char ans[4] = "n"; + + setuserfile(fp_tmpbuf, ask_tmpbuf(3)); + if(more(fp_tmpbuf, NA) != -1) + getdata(b_lines - 1, 0, "½T©w§R°£¶Ü(Y/N)?[N]", ans, 4, LCECHO); + if(*ans == 'y') + unlink(fp_tmpbuf); +} + +/* ½s¿è¾¹¦Û°Ê³Æ¥÷ */ +void auto_backup() { + if(currline) { + FILE *fp; + textline_t *p, *v; + char bakfile[64]; + int count = 0; + + setuserfile(bakfile, fp_bak); + if((fp = fopen(bakfile, "w"))) { + for(p = firstline; p != NULL && count < 512; p = v,count++) { + v = p->next; + fprintf(fp, "%s\n", p->data); + free(p); + } + fclose(fp); + } + currline = NULL; + } +} + +void restore_backup() { + char bakfile[80], buf[80]; + + setuserfile(bakfile, fp_bak); + if(dashf(bakfile)) { + stand_title("½s¿è¾¹¦Û°Ê´_ì"); + getdata(1, 0, "±z¦³¤@½g¤å³¹©|¥¼§¹¦¨¡A(S)¼g¤J¼È¦sÀÉ (Q)ºâ¤F¡H[S] ", + buf, 4, LCECHO); + if(buf[0] != 'q') { + setuserfile(buf, ask_tmpbuf(3)); + Rename(bakfile, buf); + } else + unlink(bakfile); + } +} + +/* ¤Þ¥Î¤å³¹ */ +static int garbage_line(char *str) { + int qlevel = 0; + + while(*str == ':' || *str == '>') { + if(*(++str) == ' ') + str++; + if(qlevel++ >= 1) + return 1; + } + while(*str == ' ' || *str == '\t') + str++; + if(qlevel >= 1) { + if(!strncmp(str, "¡° ", 3) || !strncmp(str, "==>", 3) || + strstr(str, ") ´£¨ì:\n")) + return 1; + } + return (*str == '\n'); +} + +static void do_quote() { + int op; + char buf[256]; + + getdata(b_lines - 1, 0, "½Ð°Ýn¤Þ¥Îì¤å¶Ü(Y/N/All/Repost)¡H[Y] ", + buf, 3, LCECHO); + op = buf[0]; + + if(op != 'n') { + FILE *inf; + + if((inf = fopen(quote_file, "r"))) { + char *ptr; + int indent_mode0 = indent_mode; + + fgets(buf, 256, inf); + if((ptr = strrchr(buf, ')'))) + ptr[1] = '\0'; + else if((ptr = strrchr(buf, '\n'))) + ptr[0] = '\0'; + + if((ptr = strchr(buf, ':'))) { + char *str; + + while(*(++ptr) == ' '); + + /* ¶¶¤â²o¦Ï¡A¨ú±o author's address */ + if((curredit & EDIT_BOTH) && (str = strchr(quote_user, '.'))) { + strcpy(++str, ptr); + str = strchr(str, ' '); + str[0] = '\0'; + } + } else + ptr = quote_user; + + indent_mode = 0; + insert_string("¡° ¤Þz¡m"); + insert_string(ptr); + insert_string("¡n¤§»Ê¨¥¡G\n"); + + if(op != 'a') /* ¥h±¼ header */ + while(fgets(buf, 256, inf) && buf[0] != '\n'); + + if(op == 'a') + while(fgets(buf, 256, inf)) { + insert_char(':'); + insert_char(' '); + insert_string(Ptt_prints(buf,STRIP_ALL)); + } + else if(op == 'r') + while(fgets(buf, 256, inf)) + insert_string(Ptt_prints(buf,NO_RELOAD)); + else { + if(curredit & EDIT_LIST) /* ¥h±¼ mail list ¤§ header */ + while (fgets(buf, 256, inf) && (!strncmp(buf, "¡° ", 3))); + while(fgets(buf, 256, inf)) { + if(!strcmp(buf, "--\n")) + break; + if(!garbage_line(buf)) { + insert_char(':'); + insert_char(' '); + insert_string(Ptt_prints(buf,STRIP_ALL)); + } + } + } + indent_mode = indent_mode0; + fclose(inf); + } + } +} + +/* ¼f¬d user ¤Þ¨¥ªº¨Ï¥Î */ +static int check_quote() { + register textline_t *p = firstline; + register char *str; + int post_line; + int included_line; + + post_line = included_line = 0; + while(p) { + if(!strcmp(str = p->data, "--")) + break; + if(str[1] == ' ' && ((str[0] == ':') || (str[0] == '>'))) + included_line++; + else { + while(*str == ' ' || *str == '\t') + str++; + if(*str) + post_line++; + } + p = p->next; + } + + if((included_line >> 2) > post_line) { + move(4, 0); + outs("¥»½g¤å³¹ªº¤Þ¨¥¤ñ¨Ò¶W¹L 80%¡A½Ð±z°µ¨Ç·Lªº×¥¿¡G\n\n" + "\033[1;33m1) ¼W¥[¤@¨Ç¤å³¹ ©Î 2) §R°£¤£¥²n¤§¤Þ¨¥\033[m"); + { + char ans[4]; + + getdata(12, 12, "(E)Ä~Äò½s¿è (W)±j¨î¼g¤J¡H[E] ", ans, 4, LCECHO); + if(ans[0] == 'w') + return 0; + } + return 1; + } + return 0; +} + +/* Àɮ׳B²z¡GŪÀÉ¡B¦sÀÉ¡B¼ÐÃD¡Bñ¦WÀÉ */ +static void read_file(char *fpath) { + FILE *fp; + + if((fp = fopen(fpath, "r")) == NULL) { + if((fp = fopen(fpath, "w+"))) { + fclose(fp); + return; + } + indigestion(4); + abort_bbs(0); + } + load_file(fp); +} + +extern userec_t cuser; + +void write_header(FILE *fp) { + time_t now = time(0); + + if(curredit & EDIT_MAIL || curredit & EDIT_LIST) { + fprintf(fp, "%s %s (%s)\n", str_author1, cuser.userid, +#if defined(REALINFO) && defined(MAIL_REALNAMES) + cuser.realname +#else + cuser.username +#endif + ); + } else { + char *ptr; + struct { + char author[IDLEN + 1]; + char board[IDLEN + 1]; + char title[66]; + time_t date; /* last post's date */ + int number; /* post number */ + } postlog; + + strcpy(postlog.author, cuser.userid); + ifuseanony=0; +#ifdef HAVE_ANONYMOUS + if(currbrdattr& BRD_ANONYMOUS) { + int defanony = (currbrdattr & BRD_DEFAULTANONYMOUS); + if(defanony) + getdata(3, 0, "½Ð¿é¤J§A·Q¥ÎªºID¡A¤]¥iª½±µ«ö[Enter]¡A" + "©Î¬O«ö[r]¥Î¯u¦W¡G", real_name, 12, DOECHO); + else + getdata(3, 0, "½Ð¿é¤J§A·Q¥ÎªºID¡A¤]¥iª½±µ«ö[Enter]¨Ï¥ÎìID¡G", + real_name, 12, DOECHO); + if(!real_name[0] && defanony) { + strcpy(real_name, "Anonymous"); + strcpy(postlog.author, real_name); + ifuseanony = 1; + } else { + if(!strcmp("r",real_name) || (!defanony && !real_name[0])) + sprintf(postlog.author,"%s",cuser.userid); + else { + sprintf(postlog.author,"%s.",real_name); + ifuseanony=1; + } + } + } +#endif + strcpy(postlog.board, currboard); + ptr = save_title; + if(!strncmp(ptr, str_reply, 4)) + ptr += 4; + strncpy(postlog.title, ptr, 65); + postlog.date = now; + postlog.number = 1; + append_record(".post", (fileheader_t *)&postlog, sizeof(postlog)); +#ifdef HAVE_ANONYMOUS + if(currbrdattr & BRD_ANONYMOUS) { + int defanony = (currbrdattr & BRD_DEFAULTANONYMOUS); + + fprintf(fp, "%s %s (%s) %s %s\n", str_author1, postlog.author , + (((!strcmp(real_name,"r") && defanony) || + (!real_name[0] && (!defanony))) ? cuser.username : + "²q²q§Ú¬O½Ö ? ^o^"), + local_article ? str_post2 : str_post1, currboard); + } else { + fprintf(fp, "%s %s (%s) %s %s\n", str_author1, cuser.userid, +#if defined(REALINFO) && defined(POSTS_REALNAMES) + cuser.realname, +#else + cuser.username, +#endif + local_article ? str_post2 : str_post1, currboard); + } +#else /* HAVE_ANONYMOUS */ + fprintf(fp, "%s %s (%s) %s %s\n", str_author1, cuser.userid, +#if defined(REALINFO) && defined(POSTS_REALNAMES) + cuser.realname, +#else + cuser.username, +#endif + local_article ? str_post2 : str_post1, currboard); +#endif /* HAVE_ANONYMOUS */ + + } + save_title[72] = '\0'; + fprintf(fp, "¼ÐÃD: %s\n®É¶¡: %s\n", save_title, ctime(&now)); +} + +void addsignature(FILE *fp, int ifuseanony) { + FILE *fs; + int i; + char buf[WRAPMARGIN + 1]; + char fpath[STRLEN]; + + static char msg[] = "½Ð¿ï¾Üñ¦WÀÉ (1-9, 0=¤£¥[)[0]: "; + char ch; + + if(!strcmp(cuser.userid,STR_GUEST)) { + fprintf(fp, "\n--\n¡° µo«H¯¸ :" BBSNAME "(" MYHOSTNAME + ") \n¡» From: %s\n", fromhost); + return; + } + if(!ifuseanony) { + i = showsignature(fpath); + msg[27] = ch = '0' | (cuser.uflag & SIG_FLAG); + getdata(0, 0, msg, buf, 4, DOECHO); + + if(ch != buf[0] && buf[0] >= '0' && buf[0] <= '9') { + ch = buf[0]; + cuser.uflag = (cuser.uflag & ~SIG_FLAG) | (ch & SIG_FLAG); + } + + if(ch != '0') { + fpath[i] = ch; + if((fs = fopen(fpath, "r"))) { + fputs("\n--\n", fp); + for(i = 0; i < MAX_SIGLINES && + fgets(buf, sizeof(buf), fs); i++) + fputs(buf, fp); + fclose(fs); + } + } + } +#ifdef HAVE_ORIGIN +#ifdef HAVE_ANONYMOUS + if(ifuseanony) + fprintf(fp, "\n--\n¡° µo«H¯¸: " BBSNAME "(" MYHOSTNAME + ") \n¡» From: %s\n", "¼Ê¦W¤Ñ¨Ïªº®a"); + else { + char temp[32]; + + strncpy(temp, fromhost, 31); + temp[32] = '\0'; + fprintf(fp, "\n--\n¡° µo«H¯¸: " BBSNAME "(" MYHOSTNAME + ") \n¡» From: %s\n", temp); + } +#else + strncpy (temp,fromhost,15); + fprintf(fp, "\n--\n¡° µo«H¯¸: " BBSNAME "(" MYHOSTNAME + ") \n¡» From: %s\n", temp); +#endif +#endif +} + +static int +write_file(char *fpath, int saveheader, int *islocal) { + time_t now; + struct tm *ptime; + FILE *fp = NULL; + textline_t *p, *v; + char ans[TTLEN], *msg; + int aborted = 0, line = 0, checksum[3], sum = 0, po = 1; + + stand_title("Àɮ׳B²z"); + if(currstat == SMAIL) + msg = "[S]Àx¦s (A)©ñ±ó (T)§ï¼ÐÃD (E)Ä~Äò (R/W/D)Ū¼g§R¼È¦sÀÉ¡H"; + else if(local_article) + msg = "[L]¯¸¤º«H¥ó (S)Àx¦s (A)©ñ±ó (T)§ï¼ÐÃD (E)Ä~Äò " + "(R/W/D)Ū¼g§R¼È¦sÀÉ¡H"; + else + msg = "[S]Àx¦s (L)¯¸¤º«H¥ó (A)©ñ±ó (T)§ï¼ÐÃD (E)Ä~Äò " + "(R/W/D)Ū¼g§R¼È¦sÀÉ¡H"; + getdata(1, 0, msg, ans, 3, LCECHO); + + switch(ans[0]) { + case 'a': + outs("¤å³¹\033[1m ¨S¦³ \033[m¦s¤J"); + safe_sleep(1); + aborted = -1; + break; + case 'r': + read_tmpbuf(-1); + case 'e': + return KEEP_EDITING; + case 'w': + write_tmpbuf(); + return KEEP_EDITING; + case 'd': + erase_tmpbuf(); + return KEEP_EDITING; + case 't': + move(3, 0); + prints("¼ÐÃD¡G%s", save_title); + strcpy(ans,save_title); + if(getdata_buf(4, 0, "·s¼ÐÃD¡G", ans, TTLEN, DOECHO)) + strcpy(save_title, ans); + return KEEP_EDITING; + case 's': + if(!HAS_PERM(PERM_LOGINOK)) { + local_article = 1; + move(2, 0); + prints("±z©|¥¼³q¹L¨¥÷½T»{¡A¥u¯à Local Save¡C\n"); + pressanykey(); + } else + local_article = 0; + break; + case 'l': + local_article = 1; + } + + if(!aborted) { + if(saveheader && !(curredit & EDIT_MAIL) && check_quote()) + return KEEP_EDITING; + + if(!*fpath) { + sethomepath(fpath, cuser.userid); + strcpy(fpath, tempnam(fpath, "ve_")); + } + + if((fp = fopen(fpath, "w")) == NULL) { + indigestion(5); + abort_bbs(0); + } + if(saveheader) + write_header(fp); + } + + for(p = firstline; p; p = v) { + v = p->next; + if(!aborted) { + msg = p->data; + if(v || msg[0]) { + trim(msg); + + line++; + if(currstat == POSTING && po) { + saveheader = str_checksum(msg); + if(saveheader) { + if(postrecord.checksum[po] == saveheader) { + po++; + if(po > 3) { + postrecord.times++; + po =0; + } + } else + po = 1; + if(currstat == POSTING && line >= totaln/2 && + sum < 3) { + checksum[sum++] = saveheader; + } + } + } +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + { + fprintf(fp, "%s\n", hc_convert_str(msg, HC_GBtoBIG, HC_DO_SINGLE)); + } + else +#endif + fprintf(fp, "%s\n", msg); + } + } + free(p); + } + currline = NULL; + + if(postrecord.times > MAX_CROSSNUM - 1) + anticrosspost(); + + if(po && sum == 3) { + memcpy(&postrecord.checksum[1], checksum, sizeof(int) * 3); + postrecord.times =0; + } + if(!aborted) { + if(islocal) + *islocal = (local_article == 1); + if(currstat == POSTING || currstat == SMAIL) + addsignature(fp,ifuseanony); + else if(currstat == REEDIT +#ifndef ALL_REEDIT_LOG + && strcmp(currboard, "SYSOP") == 0 +#endif + ) + { + time(&now); + ptime = localtime(&now); + fprintf(fp, + "¡° ½s¿è: %-15s ¨Ó¦Û: %-20s (%02d/%02d %02d:%02d)\n", + cuser.userid, fromhost, + ptime->tm_mon+1,ptime->tm_mday,ptime->tm_hour,ptime->tm_min); + } + + fclose(fp); + if(local_article && (currstat == POSTING)) + return 0; + return 0; + } + return aborted; +} + + +static void display_buffer() { + register textline_t *p; + register int i; + int inblock; + char buf[WRAPMARGIN + 2]; + int min, max; + + if(currpnt > blockpnt) { + min = blockpnt; + max = currpnt; + } else { + min = currpnt; + max = blockpnt; + } + + for(p = top_of_win, i = 0; i < b_lines; i++) { + move(i, 0); + clrtoeol(); + if(blockln >= 0 && + ((blockln <= currln && blockln <= (currln - curr_window_line + i) && + (currln - curr_window_line + i) <= currln) || + (currln <= (currln - curr_window_line + i) && + (currln - curr_window_line + i) <= blockln))) { + outs("\033[7m"); + inblock = 1; + } else + inblock = 0; + if(p) { + if(my_ansimode) + if(currln == blockln && p == currline && max > min) { + outs("\033[m"); + strncpy(buf, p->data, min); + buf[min] = 0; + outs(buf); + outs("\033[7m"); + strncpy(buf, p->data + min, max - min); + buf[max - min] = 0; + outs(buf); + outs("\033[m"); + outs(p->data + max); + } else + outs(p->data); + else if(currln == blockln && p == currline && max > min) { + outs("\033[m"); + strncpy(buf, p->data, min); + buf[min] = 0; + edit_outs(buf); + outs("\033[7m"); + strncpy(buf, p->data + min, max - min); + buf[max - min] = 0; + edit_outs(buf); + outs("\033[m"); + edit_outs(p->data + max); + } else + edit_outs(&p->data[edit_margin]); + p = p->next; + if(inblock) + outs("\033[m"); + } else + outch('~'); + } + edit_msg(); +} + +static void goto_line(int lino) { + char buf[10]; + + if(lino > 0 || + (getdata(b_lines - 1, 0, "¸õ¦Ü²Ä´X¦æ:", buf, 10, DOECHO) && + sscanf(buf, "%d", &lino) && lino > 0)) { + textline_t* p; + + prevln = currln; + prevpnt = currpnt; + p = firstline; + currln = lino - 1; + + while(--lino && p->next) + p = p->next; + + if(p) + currline = p; + else { + currln = totaln; + currline = lastline; + } + currpnt = 0; + if(currln < 11) { + top_of_win = firstline; + curr_window_line = currln; + } else { + int i; + + curr_window_line = 11; + for(i = curr_window_line; i; i--) + p = p->prev; + top_of_win = p; + } + } + redraw_everything = YEA; +} + +char *strcasestr(const char* big, const char* little) { + char* ans = (char*)big; + int len = strlen(little); + char* endptr = (char*)big + strlen(big) - len; + + while(ans <= endptr) + if(!strncasecmp(ans, little, len)) + return ans; + else + ans++; + return 0; +} + +/* + mode: + 0: prompt + 1: forward + -1: backward +*/ +static void search_str(int mode) { + static char str[80]; + typedef char* (*FPTR)(); + static FPTR fptr; + char ans[4] = "n"; + + if(!mode) { + if(getdata_buf(b_lines - 1, 0,"[·j´M]ÃöÁä¦r:",str, 65, DOECHO)) + if(*str) { + if(getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ", + ans, 4, LCECHO) && *ans == 'y') + fptr = strstr; + else + fptr = strcasestr; + } + } + + if(*str && *ans != 'q') { + textline_t* p; + char *pos = NULL; + int lino; + + if(mode >= 0) { + for(lino = currln, p = currline; p; p = p->next, lino++) + if((pos = fptr(p->data + (lino == currln ? currpnt + 1 : 0), + str)) && (lino != currln || + pos - p->data != currpnt)) + break; + } else { + for(lino = currln, p = currline; p; p = p->prev, lino--) + if((pos = fptr(p->data, str)) && + (lino != currln || pos - p->data != currpnt)) + break; + } + if(pos) { + prevln = currln; + prevpnt = currpnt; + currline = p; + currln = lino; + currpnt = pos - p->data; + if(lino < 11) { + top_of_win = firstline; + curr_window_line = currln; + } else { + int i; + + curr_window_line = 11; + for(i = curr_window_line; i; i--) + p = p->prev; + top_of_win = p; + } + redraw_everything = YEA; + } + } + if(!mode) + redraw_everything = YEA; +} + +static void match_paren() { + static char parens[] = "()[]{}"; + int type; + int parenum = 0; + char *ptype; + textline_t* p; + int lino; + int c, i = 0; + + if(!(ptype = strchr(parens, currline->data[currpnt]))) + return; + + type = (ptype - parens) / 2; + parenum += ((ptype - parens) % 2) ? -1 : 1; + + if(parenum > 0) { + for(lino = currln, p = currline; p; p = p->next, lino++) { + lino = lino; + for(i = (lino == currln) ? currpnt + 1 : 0; + i < strlen(p->data); i++) + if(p->data[i] == '/' && p->data[++i] == '*') { + ++i; + while(1) { + while(i < strlen(p->data) - 1 && + !(p->data[i] == '*' && p->data[i + 1] == '/')) + i++; + if(i >= strlen(p->data) - 1 && p->next) { + p = p->next; + ++lino; + i = 0; + } else + break; + } + } else if((c = p->data[i]) == '\'' || c == '"') { + while(1) { + while(i < (int)(strlen(p->data) - 1)) + if(p->data[++i] == '\\' && i < strlen(p->data) - 2) + ++i; + else if(p->data[i] == c) + goto end_quote; + if(i >= strlen(p->data) - 1 && p->next) { + p = p->next; + ++lino; + i = -1; + } else + break; + } +end_quote: + ; + } else if((ptype = strchr(parens, p->data[i])) && + (ptype - parens) / 2 == type) + if(!(parenum += ((ptype - parens) % 2) ? -1 : 1)) + goto p_outscan; + } + } else { + for(lino = currln, p = currline; p; p = p->prev, lino--) + for(i = (lino == currln) ? currpnt - 1 : strlen(p->data) - 1; + i >= 0; i--) + if(p->data[i] == '/' && p->data[--i] == '*' && i > 0) { + --i; + while(1) { + while(i > 0 && + !(p->data[i] == '*' && p->data[i - 1] == '/')) + i--; + if(i <= 0 && p->prev) { + p = p->prev; + --lino; + i = strlen(p->data) - 1; + } else + break; + } + } else if((c = p->data[i]) == '\'' || c == '"') { + while(1) { + while(i > 0) + if(i > 1 && p->data[i - 2] == '\\') + i -= 2; + else if((p->data[--i]) == c) + goto begin_quote; + if(i <= 0 && p->prev) { + p = p->prev; + --lino; + i = strlen(p->data); + } else + break; + } +begin_quote: + ; + } else if((ptype = strchr(parens, p->data[i])) && + (ptype - parens) / 2 == type) + if(!(parenum += ((ptype - parens) % 2) ? -1 : 1)) + goto p_outscan; + } +p_outscan: + if(!parenum) { + int top = currln - curr_window_line; + int bottom = currln - curr_window_line + b_lines - 1; + + currpnt = i; + currline = p; + curr_window_line += lino - currln; + currln = lino; + + if(lino < top || lino > bottom) { + if(lino < 11) { + top_of_win = firstline; + curr_window_line = currln; + } else { + int i; + + curr_window_line = 11; + for(i = curr_window_line; i; i--) + p = p->prev; + top_of_win = p; + } + redraw_everything = YEA; + } + } +} + +static void block_del(int hide) { + if(blockln < 0) { + blockln = currln; + blockpnt = currpnt; + blockline = currline; + } else { + char fp_tmpbuf[80]; + FILE* fp; + textline_t *begin, *end, *p; + char tmpfname[10] = "buf.0"; + char ans[6] = "w+n"; + + move(b_lines - 1, 0); + clrtoeol(); + if(hide == 1) + tmpfname[4] = 'q'; + else if(!hide && !getdata(b_lines - 1, 0, "§â°Ï¶ô²¾¦Ü¼È¦sÀÉ " + "(0:Cut, 5:Copy, 6-9, q: Cancel)[0] ", + tmpfname + 4, 4, LCECHO)) + tmpfname[4] = '0'; + if(tmpfname[4] < '0' || tmpfname[4] > '9') + tmpfname[4] = 'q'; + if('1' <= tmpfname[4] && tmpfname[4] <= '9') { + setuserfile(fp_tmpbuf, tmpfname); + if(tmpfname[4] != '5' && dashf(fp_tmpbuf)) { + more(fp_tmpbuf, NA); + getdata(b_lines - 1, 0, "¼È¦sÀɤw¦³¸ê®Æ (A)ªþ¥[ (W)Âмg " + "(Q)¨ú®ø¡H[W] ", ans, 4, LCECHO); + if(*ans == 'q') + tmpfname[4] = 'q'; + else if(*ans != 'a') + *ans = 'w'; + } + if(tmpfname[4] != '5') { + getdata(b_lines - 1, 0, "§R°£°Ï¶ô(Y/N)?[N] ", + ans + 2, 4, LCECHO); + if(ans[2] != 'y') + ans[2] = 'n'; + } + } else if(hide != 3) + ans[2] = 'y'; + + tmpfname[5] = ans[1] = ans[3] = 0; + if(tmpfname[4] != 'q') { + if(currln >= blockln) { + begin = blockline; + end = currline; + if(ans[2] == 'y' && !(begin == end && currpnt != blockpnt)) { + curr_window_line -= (currln - blockln); + if(curr_window_line < 0) { + curr_window_line = 0; + if(end->next) + (top_of_win = end->next)->prev = begin->prev; + else + top_of_win = (lastline = begin->prev); + } + currln -= (currln - blockln); + } + } else { + begin = currline; + end = blockline; + } + if(ans[2] == 'y' && !(begin == end && currpnt != blockpnt)) { + if(begin->prev) + begin->prev->next = end->next; + else if(end->next) + top_of_win = firstline = end->next; + else { + currline = top_of_win = firstline = + lastline = alloc_line(); + currln = curr_window_line = edit_margin = 0; + } + + if(end->next) + (currline = end->next)->prev = begin->prev; + else if(begin->prev) { + currline = (lastline = begin->prev); + currln--; + if(curr_window_line > 0) + curr_window_line--; + } + } + + setuserfile(fp_tmpbuf, tmpfname); + if((fp = fopen(fp_tmpbuf, ans))) { + if(begin == end && currpnt != blockpnt) { + char buf[WRAPMARGIN + 2]; + + if(currpnt > blockpnt) { + strcpy(buf, begin->data + blockpnt); + buf[currpnt - blockpnt] = 0; + } else { + strcpy(buf, begin->data + currpnt); + buf[blockpnt - currpnt] = 0; + } + fputs(buf, fp); + } else { + for(p = begin; p != end; p = p->next) + fprintf(fp, "%s\n", p->data); + fprintf(fp, "%s\n", end->data); + } + fclose(fp); + } + + if(ans[2] == 'y') { + if(begin == end && currpnt != blockpnt) { + int min, max; + + if(currpnt > blockpnt) { + min = blockpnt; + max = currpnt; + } else { + min = currpnt; + max = blockpnt; + } + strcpy(begin->data + min, begin->data + max); + begin->len -= max - min; + currpnt = min; + } else { + for(p = begin; p != end; totaln--) + free((p = p->next)->prev); + free(end); + totaln--; + currpnt = 0; + } + } + } + blockln = -1; + redraw_everything = YEA; + } +} + +static void block_shift_left() { + textline_t *begin, *end, *p; + + if(currln >= blockln) { + begin = blockline; + end = currline; + } else { + begin = currline; + end = blockline; + } + p = begin; + while(1) { + if(p->len) { + strcpy(p->data, p->data + 1); + --p->len; + } + if(p == end) + break; + else + p = p->next; + } + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; +} + +static void block_shift_right() { + textline_t *begin, *end, *p; + + if(currln >= blockln) { + begin = blockline; + end = currline; + } else { + begin = currline; + end = blockline; + } + p = begin; + while(1) { + if(p->len < WRAPMARGIN) { + int i = p->len + 1; + + while(i--) + p->data[i + 1] = p->data[i]; + p->data[0] = insert_character ? ' ' : insert_c; + ++p->len; + } + if(p == end) + break; + else + p = p->next; + } + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; +} + +static void transform_to_color(char* line) { + while(line[0] && line[1]) + if(line[0] == '*' && line[1] == '[') { + line[0] = KEY_ESC; + line += 2; + } else + ++line; +} + +static void block_color() { + textline_t *begin, *end, *p; + + if(currln >= blockln) { + begin = blockline; + end = currline; + } else { + begin = currline; + end = blockline; + } + p = begin; + while(1) { + transform_to_color(p->data); + if(p == end) + break; + else + p = p->next; + } + block_del(1); +} + +/* ½s¿è³B²z¡G¥Dµ{¦¡¡BÁä½L³B²z */ +int vedit(char *fpath, int saveheader, int *islocal) { + FILE *fp1; + char last = 0, buf[200]; /* the last key you press */ + int ch, foo; + int lastindent = -1; + int last_margin; + int mode0 = currutmp->mode; + int destuid0 = currutmp->destuid; + unsigned int money=0; + unsigned short int interval=0; + time_t now=0,th; + + textline_t* firstline0 = firstline; + textline_t* lastline0 = lastline; + textline_t* currline0 = currline; + textline_t* blockline0 = blockline; + textline_t* top_of_win0 = top_of_win; + int local_article0 = local_article; + int currpnt0 = currpnt; + int currln0 = currln; + int totaln0 = totaln; + int curr_window_line0 = curr_window_line; + int insert_character0 = insert_character; + int my_ansimode0 = my_ansimode; + int edit_margin0 = edit_margin; + int blockln0 = blockln, count=0, tin=0; + + currutmp->mode = EDITING; + currutmp->destuid = currstat; + insert_character = redraw_everything = 1; + prevln = blockln = -1; + + line_dirty = currpnt = totaln = my_ansimode = 0; + currline = top_of_win = firstline = lastline = alloc_line(); + + if(*fpath) + read_file(fpath); + + if(*quote_file) { + do_quote(); + *quote_file = '\0'; + if(quote_file[79] == 'L') + local_article = 1; + } + + currline = firstline; + currpnt = currln = curr_window_line = edit_margin = last_margin = 0; + + while(1) { + if(redraw_everything || blockln >= 0) { + display_buffer(); + redraw_everything = NA; + } + if(my_ansimode) + ch = n2ansi(currpnt, currline); + else + ch = currpnt - edit_margin; + move(curr_window_line, ch); + if(!line_dirty && strcmp(line, currline->data)) + strcpy(line, currline->data); + ch = igetkey(); + /* jochang debug */ + if((interval = (unsigned short int)((th = currutmp->lastact) - now))) { + now = th; + if((char)ch != last) { + money++; + last = (char)ch; + } + } + if(interval && interval == tin) + count++; + else + { + count=0; + tin = interval; + } + /* ³sÄò240Óinterval¤@¼Ë , ¤À©ú¬O¦bÀÄ°] */ + if(count >= 240) { + sprintf(buf, "\033[1;33;46m%s\033[37m¦b\033[37;45m%s" + "\033[37mªO¹HªkÁÈ¿ú , %s\033[m", cuser.userid, + currboard,ctime(&now)); + log_file ("etc/illegal_money",buf); + money = 0 ; + post_violatelaw(cuser.userid, "Ptt ¨t²Îĵ¹î", "¹HªkÁÈ¿ú", "¦©°£¤£ªk©Ò±o"); + mail_violatelaw(cuser.userid, "Ptt ¨t²Îĵ¹î", "¹HªkÁÈ¿ú", "¦©°£¤£ªk©Ò±o"); +// demoney(10000); +// abort_bbs(0); + } + + if(raw_mode) + switch (ch) { + case Ctrl('S'): + case Ctrl('Q'): + case Ctrl('T'): + continue; + break; + } + if(ch < 0x100 && isprint2(ch)) { + insert_char(ch); + lastindent = -1; + line_dirty = 1; + } else { + if(ch == Ctrl('P') || ch == KEY_UP || ch == KEY_DOWN || + ch == Ctrl('N')) { + if(lastindent == -1) + lastindent = currpnt; + } else + lastindent = -1; + if(ch == KEY_ESC) + switch(KEY_ESC_arg) { + case ',': + ch = Ctrl(']'); + break; + case '.': + ch = Ctrl('T'); + break; + case 'v': + ch = KEY_PGUP; + break; + case 'a': + case 'A': + ch = Ctrl('V'); + break; + case 'X': + ch = Ctrl('X'); + break; + case 'q': + ch = Ctrl('Q'); + break; + case 'o': + ch = Ctrl('O'); + break; + case '-': + ch = Ctrl('_'); + break; + case 's': + ch = Ctrl('S'); + break; + } + + switch(ch) { + case Ctrl('X'): /* Save and exit */ + foo = write_file(fpath, saveheader, islocal); + if(foo != KEEP_EDITING) { + currutmp->mode = mode0; + currutmp->destuid = destuid0; + firstline = firstline0; + lastline = lastline0; + currline = currline0; + blockline = blockline0; + top_of_win = top_of_win0; + local_article = local_article0; + currpnt = currpnt0; + currln = currln0; + totaln = totaln0; + curr_window_line = curr_window_line0; + insert_character = insert_character0; + my_ansimode = my_ansimode0; + edit_margin = edit_margin0; + blockln = blockln0; + if(!foo) + return money; + else + return foo; + } + line_dirty = 1; + redraw_everything = YEA; + break; + case Ctrl('W'): + if(blockln >= 0) + block_del(2); + line_dirty = 1; + break; + case Ctrl('Q'): /* Quit without saving */ + ch = ask("µ²§ô¦ý¤£Àx¦s (Y/N)? [N]: "); + if(ch == 'y' || ch == 'Y') { + currutmp->mode = mode0; + currutmp->destuid = destuid0; + firstline = firstline0; + lastline = lastline0; + currline = currline0; + blockline = blockline0; + top_of_win = top_of_win0; + local_article = local_article0; + currpnt = currpnt0; + currln = currln0; + totaln = totaln0; + curr_window_line = curr_window_line0; + insert_character = insert_character0; + my_ansimode = my_ansimode0; + edit_margin = edit_margin0; + blockln = blockln0; + return -1; + } + line_dirty = 1; + redraw_everything = YEA; + break; + case Ctrl('C'): + ch = insert_character; + insert_character = redraw_everything = YEA; + if(!my_ansimode) + insert_string(reset_color); + else { + char ans[4]; + move(b_lines - 2, 55); + outs("\033[1;33;40mB\033[41mR\033[42mG\033[43mY\033[44mL" + "\033[45mP\033[46mC\033[47mW\033[m"); + if(getdata(b_lines - 1, 0, + "½Ð¿é¤J «G«×/«e´º/I´º[¥¿±`¥Õ¦r¶Â©³][0wb]¡G", + ans, 4, LCECHO)) { + char t[] = "BRGYLPCW"; + char color[15]; + char *tmp, *apos = ans; + int fg, bg; + + strcpy(color, "\033["); + if(isdigit(*apos)) { + sprintf(color, "%s%c", color, *(apos++)); + if(*apos) + sprintf(color, "%s;", color); + } + if(*apos) { + if((tmp = strchr(t, toupper(*(apos++))))) + fg = tmp - t + 30; + else + fg = 37; + sprintf(color, "%s%d", color, fg); + } + if(*apos) { + if((tmp = strchr(t, toupper(*(apos++))))) + bg = tmp - t + 40; + else + bg = 40; + sprintf(color, "%s;%d", color, bg); + } + sprintf(color, "%sm", color); + insert_string(color); + } else + insert_string(reset_color); + } + insert_character = ch; + line_dirty = 1; + break; + case KEY_ESC: + line_dirty = 0; + switch(KEY_ESC_arg) { + case 'U': + t_users(); + redraw_everything = YEA; + line_dirty = 1; + break; + case 'i': + t_idle(); + redraw_everything = YEA; + line_dirty = 1; + break; + case 'n': + search_str(1); + break; + case 'p': + search_str(-1); + break; + case 'L': + case 'J': + goto_line(0); + break; + case ']': + match_paren(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + read_tmpbuf(KEY_ESC_arg - '0'); + redraw_everything = YEA; + break; + case 'l': /* block delete */ + case ' ': + block_del(0); + line_dirty = 1; + break; + case 'u': + if(blockln >= 0) + block_del(1); + line_dirty = 1; + break; + case 'c': + if(blockln >= 0) + block_del(3); + line_dirty = 1; + break; + case 'y': + undelete_line(); + break; + case 'R': + raw_mode ^= 1; + line_dirty = 1; + break; + case 'I': + indent_mode ^= 1; + line_dirty = 1; + break; + case 'j': + if(blockln >= 0) + block_shift_left(); + else if(currline->len) { + int currpnt0 = currpnt; + currpnt = 0; + delete_char(); + currpnt = (currpnt0 <= currline->len) ? currpnt0 : + currpnt0 - 1; + if(my_ansimode) + currpnt = ansi2n(n2ansi(currpnt, currline), + currline); + } + line_dirty = 1; + break; + case 'k': + if(blockln >= 0) + block_shift_right(); + else { + int currpnt0 = currpnt; + + currpnt = 0; + insert_char(' '); + currpnt = currpnt0; + } + line_dirty = 1; + break; + case 'f': + while(currpnt < currline->len && + isalnum(currline->data[++currpnt])); + while(currpnt < currline->len && + isspace(currline->data[++currpnt])); + line_dirty = 1; + break; + case 'b': + while(currpnt && isalnum(currline->data[--currpnt])); + while(currpnt && isspace(currline->data[--currpnt])); + line_dirty = 1; + break; + case 'd': + while(currpnt < currline->len) { + delete_char(); + if(!isalnum(currline->data[currpnt])) + break; + } + while(currpnt < currline->len) { + delete_char(); + if(!isspace(currline->data[currpnt])) + break; + } + line_dirty = 1; + break; + default: + line_dirty = 1; + } + break; + case Ctrl('_'): + if(strcmp(line, currline->data)) { + char buf[WRAPMARGIN]; + + strcpy(buf, currline->data); + strcpy(currline->data, line); + strcpy(line, buf); + currline->len = strlen(currline->data); + currpnt = 0; + line_dirty = 1; + } + break; + case Ctrl('S'): + search_str(0); + break; + case Ctrl('U'): + insert_char('\033'); + line_dirty = 1; + break; + case Ctrl('V'): /* Toggle ANSI color */ + my_ansimode ^= 1; + if(my_ansimode && blockln >= 0) + block_color(); + clear(); + redraw_everything = YEA; + line_dirty = 1; + break; + case Ctrl('I'): + do { + insert_char(' '); + } while(currpnt & 0x7); + line_dirty = 1; + break; + case '\r': + case '\n': + split(currline, currpnt); + line_dirty = 0; + break; + case Ctrl('G'): + { + unsigned int currstat0 = currstat; + setutmpmode(EDITEXP); + a_menu("½s¿è»²§U¾¹", "etc/editexp", + (HAS_PERM(PERM_SYSOP) ? SYSOP : NOBODY)); + currstat = currstat0; + } + if(trans_buffer[0]) { + if((fp1 = fopen(trans_buffer, "r"))) { + int indent_mode0 = indent_mode; + + indent_mode = 0; + prevln = currln; + prevpnt = currpnt; + while(fgets(line, WRAPMARGIN + 2, fp1)) { + if(!strncmp(line,"§@ªÌ:",5) || + !strncmp(line,"¼ÐÃD:",5) || + !strncmp(line,"®É¶¡:",5)) + continue; + insert_string(line); + } + fclose(fp1); + indent_mode = indent_mode0; + while(curr_window_line >= b_lines) { + curr_window_line--; + top_of_win = top_of_win->next; + } + } + } + redraw_everything = YEA; + line_dirty = 1; + break; + case Ctrl('Z'): /* Help */ + more("etc/ve.hlp",YEA); + redraw_everything = YEA; + line_dirty = 1; + break; + case Ctrl('L'): + clear(); + redraw_everything = YEA; + line_dirty = 1; + break; + case KEY_LEFT: + if(currpnt) { + if(my_ansimode) + currpnt = n2ansi(currpnt, currline); + currpnt--; + if(my_ansimode) + currpnt = ansi2n(currpnt, currline); + line_dirty = 1; + } else if(currline->prev) { + curr_window_line--; + currln--; + currline = currline->prev; + currpnt = currline->len; + line_dirty = 0; + } + break; + case KEY_RIGHT: + if(currline->len != currpnt) { + if(my_ansimode) + currpnt = n2ansi(currpnt, currline); + currpnt++; + if(my_ansimode) + currpnt = ansi2n(currpnt, currline); + line_dirty = 1; + } else if(currline->next) { + currpnt = 0; + curr_window_line++; + currln++; + currline = currline->next; + line_dirty = 0; + } + break; + case KEY_UP: + case Ctrl('P'): + if(currline->prev) { + if(my_ansimode) + ch = n2ansi(currpnt,currline); + curr_window_line--; + currln--; + currline = currline->prev; + if(my_ansimode) + currpnt = ansi2n(ch , currline); + else + currpnt = (currline->len > lastindent) ? lastindent : + currline->len; + line_dirty = 0; + } + break; + case KEY_DOWN: + case Ctrl('N'): + if(currline->next) { + if(my_ansimode) + ch = n2ansi(currpnt,currline); + currline = currline->next; + curr_window_line++; + currln++; + if(my_ansimode) + currpnt = ansi2n(ch , currline); + else + currpnt = (currline->len > lastindent) ? lastindent : + currline->len; + line_dirty = 0; + } + break; + case Ctrl('B'): + case KEY_PGUP: + redraw_everything = currln; + top_of_win = back_line(top_of_win, 22); + currln = redraw_everything; + currline = back_line(currline, 22); + curr_window_line = getlineno(); + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; + line_dirty = 0; + break; + case KEY_PGDN: + case Ctrl('F'): + redraw_everything = currln; + top_of_win = forward_line(top_of_win, 22); + currln = redraw_everything; + currline = forward_line(currline, 22); + curr_window_line = getlineno(); + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; + line_dirty = 0; + break; + case KEY_END: + case Ctrl('E'): + currpnt = currline->len; + line_dirty = 1; + break; + case Ctrl(']'): /* start of file */ + prevln = currln; + prevpnt = currpnt; + currline = top_of_win = firstline; + currpnt = currln = curr_window_line = 0; + redraw_everything = YEA; + line_dirty = 0; + break; + case Ctrl('T'): /* tail of file */ + prevln = currln; + prevpnt = currpnt; + top_of_win = back_line(lastline, 23); + currline = lastline; + curr_window_line = getlineno(); + currln = totaln; + redraw_everything = YEA; + currpnt = 0; + line_dirty = 0; + break; + case KEY_HOME: + case Ctrl('A'): + currpnt = 0; + line_dirty = 1; + break; + case KEY_INS: /* Toggle insert/overwrite */ + case Ctrl('O'): + if(blockln >= 0 && insert_character) { + char ans[4]; + + getdata(b_lines - 1, 0, + "°Ï¶ô·L½Õ¥k²¾´¡¤J¦r¤¸(¹w³]¬°ªÅ¥Õ¦r¤¸)", + ans, 4, LCECHO); + insert_c = (*ans) ? *ans : ' '; + } + insert_character ^= 1; + line_dirty = 1; + break; + case Ctrl('H'): + case '\177': /* backspace */ + line_dirty = 1; + if(my_ansimode) { + my_ansimode = 0; + clear(); + redraw_everything = YEA; + } else { + if(currpnt == 0) { + textline_t *p; + + if(!currline->prev) + break; + line_dirty = 0; + curr_window_line--; + currln--; + currline = currline->prev; + currpnt = currline->len; + redraw_everything = YEA; + if(*killsp(currline->next->data) == '\0') { + delete_line(currline->next); + break; + } + p = currline; + while(!join(p)) { + p = p->next; + if(p == NULL) { + indigestion(2); + abort_bbs(0); + } + } + break; + } + currpnt--; + delete_char(); + } + break; + case Ctrl('D'): + case KEY_DEL: /* delete current character */ + line_dirty = 1; + if(currline->len == currpnt) { + textline_t *p = currline; + + while(!join(p)) { + p = p->next; + if(p == NULL) { + indigestion(2); + abort_bbs(0); + } + } + line_dirty = 0; + redraw_everything = YEA; + } else { + delete_char(); + if(my_ansimode) + currpnt = ansi2n(n2ansi(currpnt, currline), currline); + } + break; + case Ctrl('Y'): /* delete current line */ + currline->len = currpnt = 0; + case Ctrl('K'): /* delete to end of line */ + if(currline->len == 0) { + textline_t *p = currline->next; + if(!p) { + p = currline->prev; + if(!p) + break; + if(curr_window_line > 0) { + curr_window_line--; + currln--; + } + } + if(currline == top_of_win) + top_of_win = p; + delete_line(currline); + currline = p; + redraw_everything = YEA; + line_dirty = 0; + break; + } + if(currline->len == currpnt) { + textline_t *p = currline; + + while(!join(p)) { + p = p->next; + if(p == NULL) { + indigestion(2); + abort_bbs(0); + } + } + redraw_everything = YEA; + line_dirty = 0; + break; + } + currline->len = currpnt; + currline->data[currpnt] = '\0'; + line_dirty = 1; + break; + } + if(currln < 0) + currln = 0; + if(curr_window_line < 0) { + curr_window_line = 0; + if(!top_of_win->prev) + indigestion(6); + else { + top_of_win = top_of_win->prev; + rscroll(); + } + } + if(curr_window_line == b_lines) { + curr_window_line = t_lines - 2; + if(!top_of_win->next) + indigestion(7); + else { + top_of_win = top_of_win->next; + move(b_lines, 0); + clrtoeol(); + scroll(); + } + } + } + edit_margin = currpnt < SCR_WIDTH - 1 ? 0 : currpnt / 72 * 72; + + if(!redraw_everything) { + if(edit_margin != last_margin) { + last_margin = edit_margin; + redraw_everything = YEA; + } else { + move(curr_window_line, 0); + clrtoeol(); + if(my_ansimode) + outs(currline->data); + else + edit_outs(&currline->data[edit_margin]); + edit_msg(); + } + } + } +} diff --git a/mbbsd/friend.c b/mbbsd/friend.c new file mode 100644 index 00000000..3d2167ae --- /dev/null +++ b/mbbsd/friend.c @@ -0,0 +1,509 @@ +/* $Id: friend.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +extern char currboard[]; /* name of currently selected board */ +extern char *fn_overrides; +extern userinfo_t *currutmp; +extern char *fn_reject; +extern int usernum; +extern char *str_space; +extern char *msg_uid; + +/* ------------------------------------- */ +/* ¯S§O¦W³æ */ +/* ------------------------------------- */ + +/* Ptt ¨ä¥L¯S§O¦W³æªºÀɦW */ +static char special_list[] = "list.0"; +static char special_des[] = "ldes.0"; + +/* ¯S§O¦W³æªº¤W */ +static unsigned int friend_max[8] = { + MAX_FRIEND, + MAX_REJECT, + MAX_LOGIN_INFO, + MAX_POST_INFO, + MAX_NAMELIST, + MAX_NAMELIST, + MAX_NAMELIST, + MAX_NAMELIST +}; +/* ÁöµM¦n¤Í¸òÃa¤H¦W³æ³£¬O * 2 ¦ý¬O¤@¦¸³Ì¦hload¨ìshm¥u¯à¦³128 */ + +/* Ptt ¦UºØ¯S§O¦W³æªºÀɦW */ +char *friend_file[8] = { + FN_OVERRIDES, + FN_REJECT, + "alohaed", + "postlist", + "", + FN_CANVOTE, + FN_WATER, + FN_VISABLE +}; + +/* Ptt ¦UºØ¯S§O¦W³æªº¸Éz */ +static char *friend_desc[8] = { + "¤Í½Ë´yz¡G", + "´c§Î´cª¬¡G", + "", + "", + "´yz¤@¤U¡G", + "§ë²¼ªÌ´yz¡G", + "´c§Î´cª¬¡G", + "¬ÝªO¦n¤Í´yz" +}; + +/* Ptt ¦UºØ¯S§O¦W³æªº¤¤¤å±Ôz */ +static char *friend_list[8] = { + "¦n¤Í¦W³æ", + "Ãa¤H¦W³æ", + "¤W½u³qª¾", + "·s¤å³¹³qª¾", + "¨ä¥¦¯S§O¦W³æ", + "¨p¤H§ë²¼¦W³æ", + "¬ÝªO¸TÁn¦W³æ", + "¬ÝªO¦n¤Í¦W³æ" +}; + +static void setfriendfile(char *fpath, int type) { + if (type <= 4) /* user list Ptt */ + setuserfile(fpath, friend_file[type]); + else /* board list */ + setbfile(fpath, currboard, friend_file[type]); +} + +static int friend_count(char *fname) { + FILE *fp; + int count = 0; + char buf[200]; + +#if 0 + if ((fp = fopen(fname, "r"))) + while (fgets(buf, 200, fp)) + count++; +#endif + +/*rocker.011018: §Ñ°OÃöÀɤF... */ + if ((fp = fopen(fname, "r"))) + { + while (fgets(buf, 200, fp)) count++; + fclose (fp); + } + + return count; +} + +void friend_add(char *uident, int type) { + char fpath[80]; + + setfriendfile(fpath, type); + if (friend_count(fpath) > friend_max[type]) + return; + + if ((uident[0] > ' ') && !belong(fpath, uident)) + { + FILE *fp; + char buf[40] = ""; + char t_uident[IDLEN + 1]; + + /* Thor: avoid uident run away when get data */ + strcpy(t_uident, uident); + + if (type != FRIEND_ALOHA && type != FRIEND_POST) + getdata(2, 0, friend_desc[type], buf, 40, DOECHO); + + if ((fp = fopen(fpath, "a"))) + { + flock(fileno(fp), LOCK_EX); + fprintf(fp, "%-13s%s\n", t_uident, buf); + flock(fileno(fp), LOCK_UN); + fclose(fp); + } + } +} + +static void friend_special() { + char genbuf[70], i, fname[70]; + + friend_file[FRIEND_SPECIAL] = special_list; + for (i = 0; i <= 9; i++) + { + sprintf(genbuf, " (\033[36m%d\033[m) .. ", i); + special_des[5] = i + '0'; + setuserfile(fname, special_des); + if (dashf(fname)) + { + /* no NULL check?? */ + FILE *fp = fopen(fname, "r"); + + fgets(genbuf + 15, 40, fp); + genbuf[47] = 0; + } + move(i + 12, 0); + clrtoeol(); + outs(genbuf); + } + getdata(22, 0, "½Ð¿ï¾Ü²Ä´X¸¹¯S§O¦W³æ (0~9)[0]?", genbuf, 3, LCECHO); + if (genbuf[0] >= '0' && genbuf[0] <= '9') + { + special_list[5] = genbuf[0]; + special_des[5] = genbuf[0]; + } + else + { + special_list[5] = '0'; + special_des[5] = '0'; + } +} + +static void friend_append(int type, int count) { + char fpath[80], i, j, buf[80], sfile[80]; + FILE *fp, *fp1; + + setfriendfile(fpath, type); + + do + { + move(2, 0); + clrtobot(); + outs("n¤Þ¤Jþ¤@Ó¦W³æ?\n"); + for (i = 0, j = 0; i <= 7; i++) + { + if (i == type) + continue; + j++; + if (i <= 4) + sprintf(buf, " (%d) %-s\n", j, friend_list[(int) i]); + else + sprintf(buf, " (%d) %s ª©ªº %s\n", j, currboard, + friend_list[(int) i]); + outs(buf); + } + outs(" (S) ¿ï¾Ü¨ä¥L¬ÝªOªº¯S§O¦W³æ"); + getdata(11, 0, "½Ð¿ï¾Ü ©Î ª½±µ[Enter] ©ñ±ó:", buf, 3, LCECHO); + if (!buf[0]) + return; + if (buf[0] == 's') + Select(); + } + while (buf[0] < '1' || buf[0] > '9'); + + j = buf[0] - '1'; + if (j >= type) + j++; + if (j == FRIEND_SPECIAL) + friend_special(); + + setfriendfile(sfile, j); + + fp = fopen(sfile, "r"); + while (fgets(buf, 80, fp) && count <= friend_max[type]) + { + char the_id[15]; + + sscanf(buf, "%s", the_id); + if (!belong(fpath, the_id)) + { + if ((fp1 = fopen(fpath, "a"))) + { + flock(fileno(fp1), LOCK_EX); + fputs(buf, fp1); + flock(fileno(fp1), LOCK_UN); + fclose(fp1); + } + } + } + fclose(fp); +} + +void friend_delete(char *uident, int type) { + FILE *fp, *nfp; + char fn[80], fnnew[80]; + char genbuf[200]; + + setfriendfile(fn, type); + + sprintf(fnnew, "%s-", fn); + if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w"))) + { + int length = strlen(uident); + + while (fgets(genbuf, STRLEN, fp)) + if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length)) + fputs(genbuf, nfp); + fclose(fp); + fclose(nfp); + Rename(fnnew, fn); + } +} + +static void friend_editdesc(char *uident, int type) { + FILE *fp, *nfp; + char fnnew[200], genbuf[200], fn[200]; + setfriendfile(fn, type); + sprintf(fnnew, "%s-", fn); + if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w"))) + { + int length = strlen(uident); + + while (fgets(genbuf, STRLEN, fp)) + { + if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length)) + fputs(genbuf, nfp); + else if (!strncmp(genbuf, uident, length)) + { + char buf[50] = ""; + getdata(2, 0, "קï´yz¡G", buf, 40, DOECHO); + fprintf(nfp, "%-13s%s\n", uident, buf); + } + } + fclose(fp); + fclose(nfp); + Rename(fnnew, fn); + } +} + +void friend_load() { + FILE *fp; + int myfriends[MAX_FRIEND]; + int myrejects[MAX_REJECT]; + int friendcount, rejectedcount; + char genbuf[200]; + + memset(myfriends, 0, sizeof(myfriends)); + friendcount = 0; + setuserfile(genbuf, fn_overrides); + if ((fp = fopen(genbuf, "r"))) + { + int unum; + + while (fgets(genbuf, STRLEN, fp) && friendcount < MAX_FRIEND - 1) + if (strtok(genbuf, str_space)) + if ((unum = searchuser(genbuf))) + myfriends[friendcount++] = unum; + fclose(fp); + } + memcpy(currutmp->friend, myfriends, sizeof(myfriends)); + + memset(myrejects, 0, sizeof(myrejects)); + rejectedcount = 0; + setuserfile(genbuf, fn_reject); + if ((fp = fopen(genbuf, "r"))) + { + int unum; + + while (fgets(genbuf, STRLEN, fp) && rejectedcount < MAX_REJECT - 1) + if (strtok(genbuf, str_space)) + if ((unum = searchuser(genbuf))) + myrejects[rejectedcount++] = unum; + fclose(fp); + } + memcpy(currutmp->reject, myrejects, sizeof(myrejects)); + if(currutmp->friendtotal) logout_friend_online(); + login_friend_online(); +} + +extern userec_t cuser; + +static void friend_water(char *message, int type) { /* ¸sÅé¤ô²y added by Ptt */ + char fpath[80], line[80], userid[IDLEN + 1]; + FILE *fp; + + setfriendfile(fpath, type); + if ((fp = fopen(fpath, "r"))) + while(fgets(line, 80, fp)) { + userinfo_t *uentp; + int tuid; + + sscanf(line, "%s", userid); + if((tuid = searchuser(userid)) && tuid != usernum && + (uentp = (userinfo_t *) search_ulist(tuid)) && + isvisible_uid(tuid)) + my_write(uentp->pid, message, uentp->userid, 1); + } + fclose(fp); +} + +void friend_edit(int type) { + char fpath[80], line[80], uident[20]; + int count, column, dirty; + FILE *fp; + char genbuf[200]; + + if (type == FRIEND_SPECIAL) + friend_special(); + setfriendfile(fpath, type); + + if (type == FRIEND_ALOHA || type == FRIEND_POST) + { + if (dashf(fpath)) + { + sprintf(genbuf, "/bin/cp %s %s.old", fpath, fpath); + system(genbuf); + } + } + + dirty = 0; + while (1) + { + stand_title(friend_list[type]); + move(0, 40); + sprintf(line, "(¦W³æ¤W:%dÓ¤H)", friend_max[type]); + outs(line); + count = 0; + CreateNameList(); + + if ((fp = fopen(fpath, "r"))) + { + move(3, 0); + column = 0; + while (fgets(genbuf, STRLEN, fp)) + { + if (genbuf[0] <= ' ') + continue; + strtok(genbuf, str_space); + AddNameList(genbuf); + prints("%-13s", genbuf); + count++; + if (++column > 5) + { + column = 0; + outc('\n'); + } + } + fclose(fp); + } + getdata(1, 0, (count ? + "(A)¼W¥[(D)§R°£(E)קï(P)¤Þ¤J(L)¸Ô²Ó¦C¥X" + "(K)§R°£¾ãÓ¦W³æ(W)¥á¤ô²y(Q)µ²§ô¡H[Q]" : + "(A)¼W¥[ (P)¤Þ¤J¨ä¥L¦W³æ (Q)µ²§ô¡H[Q]"), + uident, 3, LCECHO); + if (*uident == 'a') + { + move(1, 0); + usercomplete(msg_uid, uident); + if (uident[0] && searchuser(uident) && !InNameList(uident)) + { + friend_add(uident, type); + dirty = 1; + } + } + else if (*uident == 'p') + { + friend_append(type, count); + dirty = 1; + } + else if (*uident == 'e' && count) + { + move(1, 0); + namecomplete(msg_uid, uident); + if (uident[0] && InNameList(uident)) + { + friend_editdesc(uident, type); + } + } + else if (*uident == 'd' && count) + { + move(1, 0); + namecomplete(msg_uid, uident); + if (uident[0] && InNameList(uident)) + { + friend_delete(uident, type); + dirty = 1; + } + } + else if (*uident == 'l' && count) + more(fpath, YEA); + else if (*uident == 'k' && count) + { + getdata(2, 0, "¾ã¥÷¦W³æ±N·|³Q§R°£,±z½T©w¶Ü (a/N)?", uident, 3, + LCECHO); + if (*uident == 'a') + unlink(fpath); + dirty = 1; + } + else if (*uident == 'w' && count) + { + if (!getdata(0, 0, "¸sÅé¤ô²y:", uident, 60, DOECHO)) + continue; + if (getdata(0, 0, "½T©w¥á¥X¸sÅé¤ô²y? [Y]", line, 4, LCECHO) && + *line == 'n') + continue; + friend_water(uident, type); + } + else + break; + } + if (dirty) + { + move(2, 0); + outs("§ó·s¸ê®Æ¤¤..½ÐµyÔ....."); + refresh(); + if (type == FRIEND_ALOHA || type == FRIEND_POST) + { + sprintf(genbuf, "%s.old", fpath); + if ((fp = fopen(genbuf, "r"))) + { + while (fgets(line, 80, fp)) + { + sscanf(line, "%s", uident); + sethomefile(genbuf, uident, + type == FRIEND_ALOHA ? "aloha" : "postnotify"); + del_distinct(genbuf, cuser.userid); + } + fclose(fp); + } + sprintf(genbuf, "%s", fpath); + if ((fp = fopen(genbuf, "r"))) + { + while (fgets(line, 80, fp)) + { + sscanf(line, "%s", uident); + sethomefile(genbuf, uident, + type == FRIEND_ALOHA ? "aloha" : "postnotify"); + add_distinct(genbuf, cuser.userid); + } + fclose(fp); + } + } + else if (type == FRIEND_SPECIAL) + { + genbuf[0] = 0; + setuserfile(line, special_des); + if ((fp = fopen(line, "r"))) + { + fgets(genbuf, 30, fp); + fclose(fp); + } + getdata_buf(2, 0, " ½Ð¬°¦¹¯S§O¦W³æ¨ú¤@Ó²µu¦WºÙ:", genbuf, 30, + DOECHO); + if ((fp = fopen(line, "w"))) + { + fprintf(fp, "%s", genbuf); + fclose(fp); + } + } + friend_load(); + } +} + +int t_override() { + friend_edit(FRIEND_OVERRIDE); + return 0; +} + +int t_reject() { + friend_edit(FRIEND_REJECT); + return 0; +} diff --git a/mbbsd/gamble.c b/mbbsd/gamble.c new file mode 100644 index 00000000..23867450 --- /dev/null +++ b/mbbsd/gamble.c @@ -0,0 +1,361 @@ +/* $Id: gamble.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <sys/types.h> +#include <stdlib.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" +extern int usernum; + +#ifndef _BBS_UTIL_C_ +extern userec_t cuser; +extern int b_lines; + +#define MAX_ITEM 8 //³Ì¤j ½ä¶µ(item) Ó¼Æ +#define MAX_ITEM_LEN 30 //³Ì¤j ¨C¤@½ä¶µ¦W¦rªø«× +#define MAX_SUBJECT_LEN 650 //8*81 = 648 ³Ì¤j ¥DÃDªø«× + +static char betname[MAX_ITEM][MAX_ITEM_LEN]; +static int currbid; + +int post_msg(char* bname, char* title, char *msg, char* author) +{ + FILE *fp; + int bid; + fileheader_t fhdr; + time_t now = time(0); + char genbuf[256]; + + /* ¦b bname ª©µoªí·s¤å³¹ */ + sprintf(genbuf, "boards/%s", bname); + stampfile(genbuf, &fhdr); + fp = fopen(genbuf,"w"); + + if(!fp) + return -1; + + fprintf(fp, "§@ªÌ: %s ¬ÝªO: %s\n¼ÐÃD: %s \n",author,bname,title); + fprintf(fp, "®É¶¡: %s\n", ctime(&now)); + + /* ¤å³¹ªº¤º®e */ + fprintf(fp, "%s", msg); + fclose(fp); + + /* ±NÀÉ®×¥[¤J¦Cªí */ + strcpy(fhdr.title, title); + strcpy(fhdr.owner, author); + setbdir(genbuf,bname); + if(append_record(genbuf, &fhdr, sizeof(fhdr))!=-1) + if((bid = getbnum(bname)) > 0) + setbtotal(bid); + return 0; +} + +int post_file(char* bname, char* title, char *filename, char* author) +{ + int size=dashs(filename); + char *msg; + FILE *fp; + + if(size<=0) return -1; + if(!(fp=fopen(filename,"r")) ) return -1; + msg= (char *)malloc(size); + fread(msg,1,size,fp); + size= post_msg(bname, title, msg, author); + fclose(fp); + free(msg); + return size; +} + + +static int load_ticket_record(char *direct, int ticket[]) +{ + char buf[256]; + int i, total=0; + FILE *fp; + sprintf(buf,"%s/"FN_TICKET_RECORD,direct); + if(!(fp=fopen(buf,"r"))) return 0; + for(i=0;i<MAX_ITEM && fscanf(fp, "%9d ",&ticket[i]); i++) + total=total+ticket[i]; + fclose(fp); + return total; +} + +static int show_ticket_data(char *direct, int *price, boardheader_t *bh) { + int i,count, total = 0, end=0, + ticket[MAX_ITEM] = {0, 0, 0, 0, 0, 0, 0, 0}; + FILE *fp; + char genbuf[256]; + + clear(); + if (bh) + { + sprintf(genbuf,"%s ½ä½L", bh->brdname); + showtitle(genbuf, BBSNAME); + } + else + showtitle("Ptt½ä½L", BBSNAME); + move(2, 0); + sprintf(genbuf, "%s/"FN_TICKET_ITEMS, direct); + if(!(fp = fopen(genbuf,"r"))) + { + prints("\n¥Ø«e¨Ã¨S¦³Á|¿ì½ä½L\n"); + sprintf(genbuf, "%s/"FN_TICKET_OUTCOME, direct); + if(more(genbuf, NA)); + return 0; + } + fgets(genbuf,MAX_ITEM_LEN,fp); + *price=atoi(genbuf); + for(count=0; fgets(betname[count],MAX_ITEM_LEN,fp)&&count<MAX_ITEM; count++) + strtok(betname[count],"\r\n"); + fclose(fp); + + prints("\033[32m¯¸³W:\033[m 1.¥iÁʶR¥H¤U¤£¦PÃþ«¬ªº±m²¼¡C¨C±inªá \033[32m%d\033[m ¤¸¡C\n" + " 2.%s\n" + " 3.¶}¼ú®É¥u¦³¤@ºØ±m²¼¤¤¼ú, ¦³ÁʶR¸Ó±m²¼ªÌ, «h¥i¨ÌÁʶRªº±i¼Æ§¡¤À" + "Á`½äª÷¡C\n" + " 4.¨Cµ§¼úª÷¥Ñ¨t²Î©â¨ú 5% ¤§µ|ª÷%s¡C\n\n" + "\033[32m%s:\033[m", *price, + bh?"¦¹½ä½L¥Ñª©¥Dt³dÁ|¿ì¨Ã¥B¨M©w¶}¼ú®É¶¡µ²ªG, ¯¸ªø¤£ºÞ, Ä@½äªA¿é¡C": + "¨t²Î¨C¤Ñ 2:00 11:00 16:00 21:00 ¶}¼ú¡C", + bh?", ¨ä¤¤ 2% ¤Àµ¹¶}¼úª©¥D":"", + bh?"ª©¥D¦Ûq³W«h¤Î»¡©ú":"«e´X¦¸¶}¼úµ²ªG"); + + + sprintf(genbuf, "%s/"FN_TICKET, direct); + if(!dashf(genbuf)) + { + sprintf(genbuf, "%s/"FN_TICKET_END, direct); + end=1; + } + show_file(genbuf, 8, -1, NO_RELOAD); + move(15,0); + prints("\033[1;32m¥Ø«e¤Uª`ª¬ªp:\033[m\n"); + + total=load_ticket_record(direct, ticket); + + prints("\033[33m"); + for(i = 0 ; i<count; i++) + { + prints("%d.%-8s: %-7d", i+1, betname[i], ticket[i]); + if(i==3) prints("\n"); + } + prints("\033[m\n\033[42m ¤Uª`Á`ª÷ÃB:\033[31m %d ¤¸ \033[m",total*(*price)); + if(end) + { + prints("\n½ä½L¤w¸g°±¤î¤Uª`\n"); + return -count; + } + return count; +} + +static void append_ticket_record(char *direct, int ch, int n, int count) { + FILE *fp; + int ticket[8] = {0,0,0,0,0,0,0,0}, i; + char genbuf[256]; + sprintf(genbuf, "%s/"FN_TICKET_USER, direct); + + if((fp = fopen(genbuf,"a"))) { + fprintf(fp, "%s %d %d\n", cuser.userid, ch, n); + fclose(fp); + } + load_ticket_record(direct, ticket); + ticket[ch] += n; + sprintf(genbuf, "%s/" FN_TICKET_RECORD, direct); + if((fp = fopen(genbuf,"w"))) { + for(i=0; i<count; i++) + fprintf(fp,"%d ", ticket[i]); + fclose(fp); + } +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 +int ticket(int bid) +{ + int ch, n, price, count, end=0; + char path[128],fn_ticket[128]; + boardheader_t *bh=NULL; + + if(bid) + { + bh=getbcache(bid); + setbpath(path, bh->brdname); + setbfile(fn_ticket, bh->brdname, FN_TICKET); + currbid = bid; + } + else + strcpy(path,"etc/"); + + lockreturn0(TICKET, LOCK_MULTI); + while(1) { + count=show_ticket_data(path, &price, bh); + if(count<=0) + { + pressanykey(); + break; + } + move(20, 0); + reload_money(); + prints("\033[44m¿ú: %-10d \033[m\n\033[1m½Ð¿ï¾ÜnÁʶRªººØÃþ(1~%d)" + "[Q:Â÷¶}]\033[m:", cuser.money,count); + ch = igetch(); + /*-- + Tim011127 + ¬°¤F±±¨îCS°ÝÃD ¦ý¬O³oÃäÁÙ¤£¯à§¹¥þ¸Ñ¨M³o°ÝÃD, + Yuser³q¹LÀˬd¤U¥h, è¦nª©¥D¶}¼ú, ÁÙ¬O·|³y¦¨userªº³o¦¸¬ö¿ý + «Ü¦³¥i¯à¶]¨ì¤U¦¸½ä½Lªº¬ö¿ý¥h, ¤]«Ü¦³¥i¯à³Qª©¥D·s¶}½ä½L®É¬~±¼ + ¤£¹L³oÃä¦Ü¤Ö¥i¥H°µ¨ìªº¬O, ³»¦h¥u·|¦³¤@µ§¸ê®Æ¬O¿ùªº + --*/ + if(bid && !dashf(fn_ticket)) + { + move(b_lines-1,0); + prints("«z!! @£«®º...ª©¥D¤w¸g°±¤î¤Uª`¤F ¤£¯à½äÂP"); + pressanykey(); + break; + } + + if(ch=='q' || ch == 'Q') + break; + ch-='1'; + if(end || ch >= count || ch < 0) + continue; + n=0; + ch_buyitem(price, "etc/buyticket", &n); + if(n > 0) + append_ticket_record(path,ch,n,count); + } + unlockutmpmode(); + return 0; +} + +int openticket(int bid) { + char path[128],buf[256],outcome[128]; + int i, money=0, count, bet, price, total = 0, ticket[8]={0,0,0,0,0,0,0,0}; + boardheader_t *bh=getbcache(bid); + time_t now = time(NULL); + FILE *fp, *fp1; + + setbpath(path, bh->brdname); + count=-show_ticket_data(path, &price, bh); + if(count==0) + { + setbfile(buf,bh->brdname,FN_TICKET_END); + unlink(buf); //Ptt: ¦³bug + return 0; + } + lockreturn0(TICKET, LOCK_MULTI); + do + { + do + { + getdata(20, 0, "\033[1m¿ï¾Ü¤¤¼úªº¸¹½X(0:¨ú®ø)\033[m:", buf, 3, LCECHO); + bet=atoi(buf); + move(0,0); + clrtoeol(); + } while(bet<0 || bet>count); + if(bet==0) + {unlockutmpmode(); return 0;} + getdata(21, 0, "\033[1m¦A¦¸½T»{¤¤¼úªº¸¹½X\033[m:", buf, 3, LCECHO); + }while(bet!=atoi(buf)); + + bet -= 1; //Âন¯x°}ªºindex + + total=load_ticket_record(path, ticket); + setbfile(buf,bh->brdname,FN_TICKET_END); + if(!(fp1 = fopen(buf,"r"))) + { + unlockutmpmode(); + return 0; + } + // ÁÙ¨S¶}§¹¼ú¤£¯à½ä³Õ ¥unmv¤@¶µ´N¦n + money=total*price; + demoney(money*0.02); + mail_redenvelop("[½ä³õ©âÀY]", cuser.userid, money*0.02, 'n'); + money = ticket[bet] ? money*0.95/ticket[bet]:9999999; + setbfile(outcome,bh->brdname,FN_TICKET_OUTCOME); + if((fp = fopen(outcome, "w"))) + { + fprintf(fp,"½ä½L»¡©ú\n"); + while(fgets(buf,256,fp1)) + { + buf[255]=0; + fprintf(fp,"%s",buf); + } + fprintf(fp,"¤Uª`±¡ªp\n"); + + fprintf(fp, "\033[33m"); + for(i = 0 ; i<count; i++) + { + fprintf(fp, "%d.%-8s: %-7d",i+1,betname[i], ticket[i]); + if(i==3) fprintf(fp,"\n"); + } + fprintf(fp, "\033[m\n"); + + fprintf(fp, "\n\n¶}¼ú®É¶¡¡G %s \n\n" + "¶}¼úµ²ªG¡G %s \n\n" + "©Ò¦³ª÷ÃB¡G %d ¤¸ \n" + "¤¤¼ú¤ñ¨Ò¡G %d±i/%d±i (%f)\n" + "¨C±i¤¤¼ú±m²¼¥i±o %d ªT¢Þ¹ô \n\n", + Cdatelite(&now), betname[bet], total*price, ticket[bet], total, + (float) ticket[bet] / total, money); + + fprintf(fp, "%s ½ä½L¶}¥X:%s ©Ò¦³ª÷ÃB:%d ¤¸ ¼úª÷/±i:%d ¤¸ ¾÷²v:%1.2f\n", + Cdatelite(&now), betname[bet], total*price, money, + total? (float)ticket[bet] / total:0); + + fclose(fp); + } + fclose(fp1); + + setbfile(buf, bh->brdname, FN_TICKET_END); + unlink(buf); +/* + if(fork()) + { + more(outcome,YEA); + unlockutmpmode(); + return 0; + } +*/ + sprintf(buf, "[¤½§i] %s ½ä½L¶}¼ú", bh->brdname); + post_file(bh->brdname, buf, outcome, "[½ä¯«]"); + post_file("Record", buf+7, outcome, "[°¨¸ô±´¤l]"); + /* + ¥H¤U¬Oµ¹¿ú°Ê§@ + */ + setbfile(buf, bh->brdname, FN_TICKET_USER); + if (ticket[bet] && (fp = fopen(buf, "r"))) + { + int mybet, uid; + char userid[IDLEN]; + + while (fscanf(fp, "%s %d %d\n", userid, &mybet, &i) != EOF) + { + if (mybet == bet) + { + printf("®¥³ß %-15s¶R¤F%9d ±i %s, Àò±o %d ªT¢Þ¹ô\n" + ,userid, i, betname[mybet], money * i); + if((uid=getuser(userid))==0) continue; + deumoney(uid, money * i); + sprintf(buf, "%s ¤¤¼ú«¨! $ %d", bh->brdname, money * i); + mail_id(userid, buf, outcome, "Ptt½ä³õ"); + } + } + } + setbfile(buf, bh->brdname, FN_TICKET_RECORD); + unlink(buf); + setbfile(buf, bh->brdname, FN_TICKET_USER); + unlink(buf); + return 0; +} + +int ticket_main() { + ticket(0); + return 0; +} +#endif diff --git a/mbbsd/gomo.c b/mbbsd/gomo.c new file mode 100644 index 00000000..06062ce4 --- /dev/null +++ b/mbbsd/gomo.c @@ -0,0 +1,417 @@ +/* $Id: gomo.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "gomo.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern int usernum; +extern userinfo_t *currutmp; + +char ku[BRDSIZ][BRDSIZ]; +static char *chess[] = { "¡´", "¡³" }; +static int tick, lastcount, mylasttick, hislasttick; + +unsigned char *pat, *adv; + +typedef struct { + char x; + char y; +} Horder_t; + +static Horder_t *v, pool[225]; + +static void HO_init() { + memset(pool, 0, sizeof(pool)); + v = pool; + pat = pat_gomoku; + adv = adv_gomoku; + memset(ku, 0, sizeof(ku)); +} + +static void HO_add(Horder_t *mv) { + *v++ = *mv; +} + +static void HO_undo(Horder_t *mv) { + char *str = "¢z¢s¢{¢u¢q¢t¢|¢r¢}"; + int n1, n2, loc; + + *mv = *(--v); + ku[(int)mv->x][(int)mv->y] = BBLANK; + BGOTO(mv->x, mv->y); + n1 = (mv->x == 0) ? 0 : (mv->x == 14) ? 2 : 1; + n2 = (mv->y == 14)? 0 : (mv->y == 0) ? 2 : 1; + loc= 2 * ( n2 * 3 + n1); + prints("%.2s", str + loc); +} + +extern userec_t cuser; + +static void HO_log(char *user) { + int i; + FILE *log; + char buf[80]; + char buf1[80]; + char title[80]; + Horder_t *ptr = pool; + extern screenline_t *big_picture; + fileheader_t mymail; + + sprintf(buf, "home/%c/%s/F.%d", cuser.userid[0], cuser.userid, + rand() & 65535); + log = fopen(buf, "w"); + + for(i = 1; i < 17; i++) + fprintf(log, "%.*s\n", big_picture[i].len, big_picture[i].data); + + i = 0; + do { + fprintf(log, "[%2d]%s ==> %c%d%c", i + 1, chess[i % 2], + 'A' + ptr->x, ptr->y + 1, (i % 2) ? '\n' : '\t'); + i++; + } while( ++ptr < v); + fclose(log); + + sethomepath(buf1, cuser.userid); + stampfile(buf1, &mymail); + + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[³Æ.§Ñ.¿ý]"); + sprintf(mymail.title, "\033[37;41m´ÑÃÐ\033[m %s VS %s", + cuser.userid, user); + sethomedir(title, cuser.userid); + Rename(buf, buf1); + append_record(title, &mymail, sizeof(mymail)); + + unlink(buf); +} + +static int countgomo() { + Horder_t *ptr; + int i; + + ptr = pool; + i = 0; + do { + i++; + } while(++ptr < v); + return i; +} + +static int chkmv(Horder_t *mv, int color, int limit) { + char *xtype[] = {"\033[1;31m¸õ¤T\033[m", "\033[1;31m¬¡¤T\033[m", + "\033[1;31m¦º¥|\033[m", "\033[1;31m¸õ¥|\033[m", + "\033[1;31m¬¡¥|\033[m", "\033[1;31m¥|¤T\033[m", + "\033[1;31mÂù¤T\033[m", "\033[1;31mÂù¥|\033[m", + "\033[1;31mÂù¥|\033[m", "\033[1;31m³s¤»\033[m", + "\033[1;31m³s¤\033[m"}; + int rule = getstyle(mv->x, mv->y, color, limit); + if(rule > 1 && rule < 13) { + move(15, 40); + outs(xtype[rule - 2]); + bell(); + } + return chkwin(rule, limit); +} + +static int gomo_key(int fd, int ch, Horder_t *mv) { + if( ch >= 'a' && ch <= 'o') { + char pbuf[4], vx, vy; + + *pbuf = ch; + if(fd) + add_io(0, 0); + oldgetdata(17, 0, "ª½±µ«ü©w¦ì¸m :", pbuf, 4, DOECHO); + if(fd) + add_io(fd, 0); + vx = pbuf[0] - 'a'; + vy = atoi(pbuf + 1) - 1; + if(vx >= 0 && vx < 15 && vy >= 0 && vy < 15 && + ku[(int)vx][(int)vy] == BBLANK) { + mv->x = vx; + mv->y = vy; + return 1; + } + } else { + switch(ch) { + case KEY_RIGHT: + mv->x = (mv->x == BRDSIZ - 1) ? mv->x : mv->x + 1; + break; + case KEY_LEFT: + mv->x = (mv->x == 0 ) ? 0 : mv->x - 1; + break; + case KEY_UP: + mv->y = (mv->y == BRDSIZ - 1) ? mv->y : mv->y + 1; + break; + case KEY_DOWN: + mv->y = (mv->y == 0 ) ? 0 : mv->y - 1; + break; + case ' ': + case '\r': + if(ku[(int)mv->x][(int)mv->y] == BBLANK) + return 1; + } + } + return 0; +} + +extern userec_t xuser; + +static int reload_gomo() { + passwd_query(usernum, &xuser); + cuser.five_win = xuser.five_win; + cuser.five_lose = xuser.five_lose; + cuser.five_tie = xuser.five_tie; + return 0; +} + +int gomoku(int fd) { + Horder_t mv; + int me, he, win, ch; + int hewantpass, iwantpass; + userinfo_t *my = currutmp; + + HO_init(); + me = !(my->turn) + 1; + he = my->turn + 1; + win = 1; + tick=time(0) + MAX_TIME; + lastcount = MAX_TIME; + setutmpmode(M_FIVE); + clear(); + + prints("\033[1;46m ¤¤l´Ñ¹ï¾Ô \033[45m%30s VS %-30s\033[m", + cuser.userid, my->mateid); + show_file("etc/@five", 1, -1, ONLY_COLOR); + move(11, 40); + prints("§Ú¬O %s", me == BBLACK ? "¥ý¤â ¡´, ¦³¸T¤â" : "«á¤â ¡³"); + move(16, 40); + prints("\033[1;33m%s", cuser.userid); + move(17, 40); + prints("\033[1;33m%s", my->mateid); + + reload_gomo(); + move(16, 60); + prints("\033[1;31m%d\033[37m³Ó \033[34m%d\033[37m±Ñ \033[36m%d\033[37m©M" + "\033[m", cuser.five_win, cuser.five_lose, cuser.five_tie); + + getuser(my->mateid); + move(17, 60); + prints("\033[1;31m%d\033[37m³Ó \033[34m%d\033[37m±Ñ \033[36m%d\033[37m" + "©M\033[m", xuser.five_win, xuser.five_lose, xuser.five_tie); + + cuser.five_lose++; + /* ¤@¶i¨Ó¥ý¥[¤@³õ±Ñ³õ, ŤF«á¦A¦©¦^¥h, ÁקK§Ö¿é¤F´c·NÂ_½u */ + passwd_update(usernum, &cuser); + + add_io(fd, 0); + + hewantpass = iwantpass = 0; + mv.x = mv.y = 7; + move(18, 40); + prints("%s®É¶¡ÁÙ³Ñ%d:%02d\n", my->turn ? "§Aªº" : "¹ï¤è", + MAX_TIME / 60, MAX_TIME % 60); + for(;;) { + move(13, 40); + outs(my->turn ? "½ü¨ì¦Û¤v¤U¤F!": "µ¥«Ý¹ï¤è¤U¤l.."); + if(lastcount != tick-time(0)) { + lastcount = tick-time(0); + move(18, 40); + prints("%s®É¶¡ÁÙ³Ñ%d:%02d\n", my->turn ? "§Aªº" : "¹ï¤è", + lastcount / 60, lastcount % 60); + if(lastcount <= 0 && my->turn) { + move(19, 40); + outs("®É¶¡¤w¨ì, §A¿é¤F"); + my->five_lose++; + send(fd, '\0', 1, 0); + break; + } + if(lastcount <= -5 && !my->turn) { + move(19, 40); + outs("¹ï¤â¤Ó¤[¨S¤U, §AŤF!"); + win = 1; + cuser.five_lose--; + cuser.five_win++; + my->five_win++; + passwd_update(usernum, &cuser); + mv.x = mv.y = -2; + send(fd, &mv, sizeof(Horder_t), 0); + mv = *(v - 1); + break; + } + } + move(14, 40); + if(hewantpass) { + outs("\033[1;32m©M´Ñn¨D!\033[m"); + bell(); + } else + clrtoeol(); + BGOTOCUR(mv.x, mv.y); + ch = igetkey(); + if(ch != I_OTHERDATA) + iwantpass = 0; + if(ch == 'q') { + if(countgomo() < 10) { + cuser.five_lose--; + passwd_update(usernum, &cuser); + } + send(fd, '\0', 1, 0); + break; + } else if(ch == 'u' && !my->turn && v > pool) { + mv.x = mv.y = -1; + ch = send(fd, &mv, sizeof(Horder_t), 0); + if(ch == sizeof(Horder_t)) { + HO_undo(&mv); + tick = mylasttick; + my->turn = 1; + continue; + } else + break; + } + if(ch == 'p') { + if(my->turn ) { + if(iwantpass == 0) { + iwantpass = 1; + mv.x = mv.y = -2; + send(fd, &mv, sizeof(Horder_t), 0); + mv = *(v - 1); + } + continue; + } else if(hewantpass) { + win = 0; + cuser.five_lose--; + cuser.five_tie++; + my->five_tie++; + passwd_update(usernum, &cuser); + mv.x=mv.y=-2; + send(fd, &mv, sizeof(Horder_t), 0); + mv = *(v - 1); + break; + } + } + + if(ch == I_OTHERDATA) { + ch = recv(fd, &mv, sizeof(Horder_t), 0); + if(ch != sizeof(Horder_t)) { + lastcount=tick-time(0); + if(lastcount >=0) { + win = 1; + cuser.five_lose--; + if(countgomo() >=10) { + cuser.five_win++; + my->five_win++; + } + passwd_update(usernum, &cuser); + outmsg("¹ï¤è»{¿é¤F!!"); + break; + } else { + win = 0; + outmsg("§A¶W¹L®É¶¡¥¼¤U¤l, ¿é¤F!"); + my->five_lose++; + break; + } + } else if(mv.x == -2 && mv.y == -2) { + if(iwantpass == 1) { + win = 0; + cuser.five_lose--; + cuser.five_tie++; + my->five_tie++; + passwd_update(usernum, &cuser); + break; + } else { + hewantpass = 1; + mv = *(v - 1); + continue; + } + } + if(my->turn && mv.x == -1 && mv.y == -1) { + outmsg("¹ï¤è®¬´Ñ"); + tick = hislasttick; + HO_undo(&mv); + my->turn = 0; + continue; + } + + if(!my->turn) { + win = chkmv(&mv, he, he == BBLACK); + HO_add(&mv); + hislasttick = tick; + tick = time(0) + MAX_TIME; + ku[(int)mv.x][(int)mv.y] = he; + bell(); + BGOTO(mv.x, mv.y); + outs(chess[he - 1]); + + if(win) { + outmsg(win == 1 ? "¹ï¤èŤF!" : "¹ï¤è¸T¤â"); + if(win != 1) { + cuser.five_lose--; + cuser.five_win++; + my->five_win++; + passwd_update(usernum, &cuser); + } else + my->five_lose++; + win = -win; + break; + } + my->turn = 1; + } + continue; + } + + if(my->turn) { + if(gomo_key(fd, ch, &mv)) + my->turn = 0; + else + continue; + + if(!my->turn) { + HO_add(&mv); + BGOTO(mv.x, mv.y); + outs(chess[me - 1]); + win = chkmv( &mv, me, me == BBLACK); + ku[(int)mv.x][(int)mv.y] = me; + mylasttick = tick; + tick = time(0) + MAX_TIME; /*˼Æ*/ + lastcount = MAX_TIME; + if(send(fd, &mv, sizeof(Horder_t), 0) != sizeof(Horder_t)) + break; + if(win) { + outmsg(win == 1 ? "§ÚĹÅo~~" : "¸T¤â¿é¤F" ); + if(win == 1) { + cuser.five_lose--; + cuser.five_win++; + my->five_win++; + passwd_update(usernum, &cuser); + } else + my->five_lose++; + break; + } + move(15, 40); + clrtoeol(); + } + } + } + add_io(0, 0); + close(fd); + + igetch(); + if(v > pool) { + char ans[4]; + + getdata(19 , 0, "n«O¯d¥»§½¦¨´ÑÃжÜ?(y/N)", ans, 4, LCECHO); + if(*ans == 'y') + HO_log(my->mateid); + } + return 0; +} diff --git a/mbbsd/gomo1.c b/mbbsd/gomo1.c new file mode 100644 index 00000000..953bad2d --- /dev/null +++ b/mbbsd/gomo1.c @@ -0,0 +1,136 @@ +/* $Id: gomo1.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "proto.h" + +#define QCAST int (*)(const void *, const void *) + +#define BBLANK (0) /* ªÅ¥Õ */ +#define BBLACK (1) /* ¶Â¤l, ¥ý¤â */ +#define BWHITE (2) /* ¥Õ¤l, «á¤â */ +#ifndef BRDSIZ +#define BRDSIZ (15) /* ´Ñ½L³æÃä¤j¤p */ +#endif + +extern char ku[BRDSIZ][BRDSIZ]; + +/* pattern and advance map */ +extern unsigned char *pat, *adv; + +static int intrevcmp(const void *a, const void *b) { + return (*(int *)b - *(int *)a); +} + +/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; dx,dy: -1,0,+1 */ +static int gomo_getindex(int x, int y, int color, int dx, int dy) { + int i, k, n; + for(n = -1, i = 0, k = 1; i < 5; i++, k <<= 1) { + x += dx; + y += dy; + + if((x < 0) || (x >= BRDSIZ) || ( y < 0) || ( y >= BRDSIZ)) { + n += k; + break; + } else if(ku[x][y] != BBLANK) { + n += k; + if(ku[x][y] != color) + break; + } + } + + if(i >= 5) + n += k; + + return n; +} + +int chkwin(int style, int limit) { + if(style == 0x0c) + return 1 /* style */; + else if(limit == 0) { + if(style == 0x0b) + return 1 /* style */; + return 0; + } + if((style < 0x0c) && (style > 0x07)) + return -1 /* -style */; + return 0; +} + +/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; limit:1,0 ; dx,dy: 0,1 */ +static int dirchk(int x, int y, int color, int limit, int dx, int dy) { + int le, ri, loc, style; + + le = gomo_getindex(x, y, color, -dx, -dy); + ri = gomo_getindex(x, y, color, dx, dy); + + loc = (le > ri) ? (((le * (le + 1)) >> 1) + ri) : + (((ri * (ri + 1)) >> 1) + le); + + style = pat[loc]; + + if(limit == 0) + return (style & 0x0f); + + style >>= 4; + + if((style == 3) || (style == 2)) { + int i, n, tmp, nx, ny; + + n = adv[loc >> 1]; + + ((loc & 1) == 0) ? (n >>= 4) : (n &= 0x0f); + + ku[x][y] = color; + + for(i = 0; i < 2; i++) { + if((tmp = (i == 0) ? (-(n >> 2)):(n & 3)) != 0) { + nx = x + (le > ri ? 1 : -1) * tmp * dx; + ny = y + (le > ri ? 1 : -1) * tmp * dy; + + if((dirchk(nx, ny, color, 0, dx, dy) == 0x06) && + (chkwin(getstyle(nx, ny, color, limit), limit) >= 0)) + break; + } + } + if(i >= 2) + style = 0; + ku[x][y] = BBLANK; + } + return style; +} + +/* ¨Ò¥~=F ¿ù»~=E ¦³¤l=D ³s¤=C ³s¤»=B Âù¥|=A ¥|¥|=9 ¤T¤T=8 */ +/* ¥|¤T=7 ¬¡¥|=6 Â_¥|=5 ¦º¥|=4 ¬¡¤T=3 Â_¤T=2 «O¯d=1 µL®Ä=0 */ + +/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; limit: 1,0 */ +int getstyle(int x, int y, int color, int limit) { + int i, j, dir[4], style; + + if((x < 0) || (x >= BRDSIZ) || ( y < 0) || (y >= BRDSIZ)) + return 0x0f; + if(ku[x][y] != BBLANK) + return 0x0d; + + for(i = 0; i < 4; i++) + dir[i] = dirchk(x, y, color, limit, i ? (i>>1) : -1, i ? (i&1) : 1); + + qsort(dir, 4, sizeof(int), (QCAST)intrevcmp); + + if((style = dir[0]) >= 2) { + for(i = 1, j = 6 + (limit ? 1 : 0); i < 4; i++) { + if((style > j) || (dir[i] < 2)) + break; + if(dir[i] > 3) + style = 9; + else if((style < 7) && (style > 3)) + style = 7; + else + style = 8; + } + } + return style; +} diff --git a/mbbsd/guess.c b/mbbsd/guess.c new file mode 100644 index 00000000..27a337f7 --- /dev/null +++ b/mbbsd/guess.c @@ -0,0 +1,364 @@ +/* $Id: guess.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern char *BBSName; +extern int usernum; +#define LOGPASS BBSHOME "/etc/winguess.log" + +static void show_table(char TABLE[], char ifcomputer) { + int i; + + move(0, 35); + prints("\033[1;44;33m ¡i ²q¼Æ¦r ¡j \033[m"); + move(8, 1); + prints("\033[1;44;36m¥Ø «e ¿ ²v\033[m\n"); + prints("\033[1;33m=================\033[m\n"); + if(ifcomputer) { + prints("Ĺ¹q¸£: 2 ¿\n"); + prints("¿é¹q¸£: 0 ¿\n"); + } else { + for(i = 1; i <= 6; i++) + prints("²Ä%d¦¸, %02d¿\n",i,TABLE[i]); + } + prints("\033[33m=================\033[m"); +} + +extern userec_t cuser; + +static unsigned long int get_money(void) { + int money, i; + char data[20]; + + move(1, 0); + prints("±z¥Ø«e¦³:%d Ptt$", cuser.money); + do { + getdata(2, 0, "n½ä¦h¤Ö(5-10©Î«öqÂ÷¶}): ", data, 9, LCECHO); + money = strlen(data); + if(data[0] == 'q' || data[0] == 'Q') { + unlockutmpmode(); + return 0; + } + for(i = 0; i < money; i++) + if(data[i]<'0' || data[i]>'9') { + money = -1; + break; + } + if(money != -1){ + money = atol(data); + reload_money(); + if(money > cuser.money || money <= 4 || money > 10 || + money < 1) + money = -1; + } + } while(money == -1); + move(1,0); + clrtoeol(); + reload_money(); + prints("±z¥Ø«e¦³:%d Ptt$", cuser.money - money); + return money; +} + +static int check_data(char *str) { + int i, j; + + if(strlen(str) != 4) + return -1; + for(i = 0; i < 4; i++) + if(str[i] < '0' || str[i] > '9') + return -1; + for(i = 0; i < 4; i++) + for(j = i + 1; j < 4; j++) + if(str[i] == str[j]) + return -1; + return 1; +} + +static char *get_data(int count) { + static char data[5]; + while(1) { + getdata(6, 0, "¿é¤J¥|¦ì¼Æ¦r(¤£«½Æ): ", data, 5, LCECHO); + if(check_data(data) == 1) + break; + } + return data; +} + +static int guess_play(char *data, char *answer, int count) { + int A_num = 0, B_num = 0; + int i, j; + + for(i = 0; i < 4; i++) { + if(data[i] == answer[i]) + A_num++; + for(j = 0; j < 4; j++) + if(i == j) + continue; + else if(data[i] == answer[j]) { + B_num++; + break; + } + } + if(A_num == 4) + return 1; + move(count + 8,55); + prints("%s => \033[1;32m%dA %dB\033[m", data, A_num, B_num); + return 0; +} + +static int result(int correct, int number) { + char a = 0, b = 0, i, j; + char n1[5], n2[5]; + + sprintf(n1, "%04d",correct); + sprintf(n2, "%04d",number); + for(i = 0; i < 4; i++) + for(j = 0; j < 4; j++) + if(n1[(int)i] == n2[(int)j]) + b++; + for(i = 0; i < 4; i++) + if(n1[(int)i] == n2[(int)i]) { + b--; + a++; + } + return 10 * a + b; +} + +static int legal(int number) { + char i, j; + char temp[5]; + + sprintf(temp, "%04d", number); + for(i = 0; i < 4; i++) + for(j = i + 1; j < 4; j++) + if(temp[(int)i] == temp[(int)j]) + return 0; + return 1; +} + +static void initcomputer(char flag[]) { + int i; + + for(i = 0; i < 10000; i++) + if(legal(i)) + flag[i] = 1; + else + flag[i] = 0; +} + +static int computer(int correct, int total, char flag[], int n[]) { + int guess; + static int j; + int k,i; + char data[5]; + + if(total == 1) { + do { + guess = rand() % 10000; + } while(!legal(guess)); + } else + guess = n[rand() % j]; + k = result(correct, guess); + if(k == 40) { + move(total + 8, 25); + sprintf(data, "%04d", guess); + prints("%s => ²q¤¤¤F!!", data); + return 1; + } else { + move(total + 8, 25); + sprintf(data, "%04d", guess); + prints("%s => \033[1;32m%dA %dB\033[m", data, k / 10, k % 10); + } + j = 0; + for(i = 0; i < 10000; i++) + if(flag[i]) { + if(result(i, guess) != k) + flag[i] = 0; + else + n[j++] = i; + } + return 0; +} + +static void Diff_Random(char *answer) { + register int i = 0, j, k; + + while(i < 4) { + k = rand() % 10 + '0'; + for(j = 0; j < i; j++) + if(k == answer[j]) + break; + if(j == i) { + answer[j] = k; + i++; + } + } + answer[4] = 0; +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 + +int guess_main() { + unsigned long int money; + char computerwin = 0,youwin = 0; + int count = 0,c_count = 0; + char ifcomputer; + char answer[5]; + int *n = NULL; + char yournum[5]; + char *flag = NULL; + static char TABLE[]={0,10,8,4,2,1,0,0,0,0,0}; + FILE *file; + + clear(); + showtitle("²q¼Æ¦r", BBSName); + lockreturn0(GUESSNUM, LOCK_MULTI); + + reload_money(); + if(cuser.money < 5) { + clear(); + move(12, 35); + prints("¿ú¤£°÷°Õ ¦Ü¤Ön 5 Ptt$"); + unlockutmpmode(); + pressanykey(); + return 1; + } + if((money = get_money()) == 0) + return 1; + vice(money,"²q¼Æ¦r"); + + Diff_Random(answer); + move(2, 0); + clrtoeol(); + prints("±z¤Uª` :%d Ptt$", money); + + getdata_str(4, 0, "±zn©M¹q¸£¤ñÁɶÜ? <y/n>[y]:", &ifcomputer, 2, + LCECHO, "y"); + if(ifcomputer == 'y') { + ifcomputer = 1; + show_table(TABLE, 1); + } else { + ifcomputer = 0; + show_table(TABLE, 0); + } + if(ifcomputer) { + do { + getdata(5, 0, "½Ð¿é¤J±znÅý¹q¸£²qªº¼Æ¦r: ", yournum, 5, LCECHO); + } while(!legal(atoi(yournum))); + move(8, 25); + prints("¹q¸£²q"); + flag = malloc(sizeof(char) * 10000); + n = malloc(sizeof(int) * 1500); + initcomputer(flag); + } + move(8, 55); + prints("§A²q"); + while(((!computerwin || !youwin) && count <10 && (ifcomputer)) || + (!ifcomputer && count < 10 && !youwin)) { + if(!computerwin && ifcomputer) { + ++c_count; + if(computer(atoi(yournum), c_count, flag, n)) + computerwin = 1; + } + move(20, 55); + prints("²Ä %d ¦¸¾÷·| ", count + 1); + if(!youwin) { + ++count; + if(guess_play(get_data(count),answer,count)) + youwin=1; + } + } + move(17, 35); + if(ifcomputer) { + free(flag); + free(n); + if(count > c_count) { + prints("§A¿éµ¹¹q¸£¤F"); + move(18, 35); + prints("§A½ß¤F %d ", money); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "¹q¸£²Ä%d¦¸²q¤¤, ", c_count); + if(youwin) + fprintf(file, "%s ²Ä%d¦¸²q¤¤, ", cuser.userid, count); + else + fprintf(file, "%s ¨S²q¤¤, ", cuser.userid); + fprintf(file,"¹q¸£ÁȨ«¤F%s %ld Ptt$\n", cuser.userid, money); + fclose(file); + } + unlockutmpmode(); + pressanykey(); + return 1; + } else if(count < c_count) { + prints("¯u¼F®`, Åý§AÁȨìÅo"); + move(18,35);prints("§AÁȨ«¤F %d ",money*2); + demoney(money*2); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ²Ä%d¦¸²q¤¤, ¹q¸£²Ä%d¦¸²q¤¤, " + "ŤF¹q¸£ %ld Ptt$\n", cuser.userid, count, + c_count, money * 2); + fclose(file); + } + unlockutmpmode(); + pressanykey(); + return 1; + } else { + prints("¯u¼F®`, ©M¹q¸£¥´¦¨¥¤â¤F, ®³¦^¥»¿ú%d\n", money); + demoney(money); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s ©M¹q¸£¥´¦¨¤F¥¤â\n", cuser.userid); + fclose(file); + } + unlockutmpmode(); + pressanykey(); + return 1; + } + } + if(youwin) { + demoney(TABLE[count]*money); + if(count < 5) { + prints("¯u¼F®`, ¿ú³Q§AÁȨ«¤F"); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ²Ä%d¦¸²q¤¤, ŤF %ld Ptt$\n", + cuser.userid, count, TABLE[count] * money); + fclose(file); + } + } else if(count > 5) { + prints("ü, ¤Ó¦h¦¸¤~²q¥X¨Ó¤F"); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ²Ä%d¦¸¤~²q¤¤, ½ß¤F %ld Ptt$\n", + cuser.userid, count, money); + fclose(file); + } + } + else { + prints("¤¦¸²q¥X¨Ó, ÁÙ§A¥»¿ú§a"); + move(18,35); + clrtoeol(); + prints("§A®³¦^¤F%d Ptt$\n", money); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ²Ä%d¦¸²q¤¤, ®³¦^¤F¥»¿ú %ld Ptt$\n", + cuser.userid, count, money); + fclose(file); + } + } + unlockutmpmode(); + pressanykey(); + return 1; + } + move(17,35); + prints("¼K¼K ¼Ð·Çµª®×¬O %s ", answer); + move(18,35); + prints("¤U¦¸¦A¨Ó§a"); + if((file = fopen(BBSHOME "/etc/loseguess.log","a"))) { + fprintf(file,"id: %s ½ä¤F %ld Ptt$\n",cuser.userid,money); + fclose(file); + } + return 1; +} diff --git a/mbbsd/indict.c b/mbbsd/indict.c new file mode 100644 index 00000000..407b5ae9 --- /dev/null +++ b/mbbsd/indict.c @@ -0,0 +1,184 @@ +/* $Id: indict.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +#define REFER "etc/dicts" + +extern userec_t cuser; +char dict[41],database[41]; + +static void addword(char word[]) { + char buf[150],temp[150],a[3]; + FILE *fp = fopen(database,"r+"); + + fgets(buf,130,fp); + fseek(fp,0,2); + if(HAVE_PERM(PERM_LOGINOK)) { + clear(); + move(4,0); + outs(" \033[31mĵ§i\033[m:Y»W·N¶ñ¼g°²¸ê®Æ±N\033[36m¬åid\033[m³B¥÷\n"); + sprintf(temp, "\n¿é¤J½d§Q\n:\033[33m%s\033[m", buf); + outs(temp); + outs("\n½Ð¨Ì¤W¦C½d¨Ò¿é¤J¤@¦æ¸ê®Æ(ª½±µenter©ñ±ó)\n"); + getdata(10, 0, ":", buf, 65, DOECHO); + if(buf[0]) { + getdata(13, 0, "½T©w·s¼W?(Y/n)", a, 2, LCECHO); + if(a[0] != 'n') + fprintf(fp, "%-65s[%s]\n", buf, cuser.userid); + } + } + fclose(fp); + clear(); +} + +static int choose_dict(void) { + int c; + FILE *fp; + char buf[10][21], data[10][21], cho[130]; + + move(12, 0); + clrtobot(); + outs(" " + "¡´ \033[45;33m¦r¨åò ¡º n¬dþ¤@¥»¡H\033[m ¡´"); + + if((fp = fopen(REFER, "r"))) { + for(c = 0; fscanf(fp, "%s %s", buf[c], data[c]) != EOF; c++ ) { + sprintf(cho,"\n " + "(\033[36m%d\033[m) %-20s¤j¦r¨å",c+1,buf[c]); + outs(cho); + } + + getdata(22, 14, " ¡¹ ½Ð¿ï¾Ü¡A[Enter]Â÷¶}¡G", cho, 3, LCECHO); + cho[0] -= '1'; + if(cho[1]) + cho[0] = (cho[0] + 1) * 10 + (cho[1] - '1'); + + if(cho[0] >= 0 && cho[0] < c) { + strcpy(dict, buf[(int)cho[0]]); + strcpy(database, data[(int)cho[0]]); + return 1; + } else + return 0; + } + return 0; +} + +static char *lower(char str[]) { + int c; + static char temp[200]; + + strcpy(temp,str); + for(c = 0; temp[c] !=0; c++) + if(temp[c] >= 'A' && temp[c] <= 'Z') + temp[c] += 'a' - 'A'; + return temp; +} + +int use_dict() { + FILE *fp; + char lang[150], word[80] = ""; + char j, f, buf[120], sys[] = "|\033[31me\033[m:½sÄy¦r¨å"; + int i = 0; + + setutmpmode(DICT); + if(!HAS_PERM(PERM_SYSOP)) + sys[0]=0; + + clear(); + + sprintf(buf,"\033[45m ¡´\033[1;44;33m" + " %-14s\033[3;45m ¡´ ", dict); + strcpy(&buf[100],"\033[m\n"); + for(;;) { + move(0, 0); + sprintf(lang, " ½Ð¿é¤JÃöÁä¦r¦ê(%s) ©Î«ü¥O(h,t,a)\n", dict); + outs(lang); + sprintf(lang, "[\033[32m<ÃöÁä¦r>\033[m|\033[32mh\033[m:help|\033[32m" + "t\033[m:©Ò¦³¸ê®Æ|\033[32ma\033[m:·s¼W¸ê®Æ%s]\n:", sys); + outs(lang); + getdata(2, 0, ":", word, 18, DOECHO); + outs("¸ê®Æ·j´M¤¤½ÐµyÔ...."); + strcpy(word,lower(word)); + if(word[0] == 0) + return 0; + clear(); + move(4, 0); + outs(buf); + if(strlen(word) == 1) { + if(word[0] == 'a') { + clear(); + move(4,0); + outs(buf); + addword(word); + continue; + } else if(word[0] == 't') + word[0] = 0; + else if(word[0] == 'h') { + more("etc/dict.hlp",YEA); + clear(); + continue; + } else if(word[0]=='e') { + vedit(database,NA, NULL); + clear(); + continue; + } else { + outs("¦r¦ê¤Óµu,½Ð¿é¤J¦h¤@ÂIÃöÁä¦r"); + continue; + } + } + + if((fp = fopen(database,"r"))) { + i = 0; + while(fgets(lang,150,fp) != NULL) { + if(lang[65] == '[') { + lang[65] = 0; + f = 1; + } else + f = 0; + if(strstr(lower(lang),word)) { + if(f == 1) + lang[65] = '['; + outs(lang); + i++; + if(!((i+1)%17)) { + move(23, 0); + outs("\033[45m " + "¥ô·NÁäÄ~Äò Q:Â÷¶} " + "\033[m "); + j = igetch(); + if(j == 'q') + break; + else { + clear(); + move(4,0); + outs(buf); + } + } + } + } + } + fclose(fp); + if(i == 0) { + getdata(5, 0, "¨S³oÓ¸ê®ÆC,·s¼W¶Ü?(y/N)", lang, 3, LCECHO); + if(lang[0] == 'y') { + clear(); + move(4,0); + outs(buf); + addword(word); + } + } + } +} + +int x_dict() { + if(choose_dict()) + use_dict(); + return 0; +} diff --git a/mbbsd/io.c b/mbbsd/io.c new file mode 100644 index 00000000..e3d03b9b --- /dev/null +++ b/mbbsd/io.c @@ -0,0 +1,611 @@ +/* $Id: io.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <signal.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#if defined(linux) +#define OBUFSIZE 2048 +#define IBUFSIZE 128 +#else +#define OBUFSIZE 4096 +#define IBUFSIZE 256 +#endif + +extern int current_font_type; +extern char *fn_proverb; +extern userinfo_t *currutmp; +extern unsigned int currstat; +extern pid_t currpid; +extern int errno; +extern screenline_t *big_picture; +extern int t_lines, t_columns; /* Screen size / width */ +extern int curr_idle_timeout; +extern water_t water[6], *swater[5], *water_which; +extern char water_usies; + +static char outbuf[OBUFSIZE], inbuf[IBUFSIZE]; +static int obufsize = 0, ibufsize = 0; +static int icurrchar = 0; + +/* ----------------------------------------------------- */ +/* ©w®ÉÅã¥Ü°ÊºA¬ÝªO */ +/* ----------------------------------------------------- */ +extern userec_t cuser; + +static void hit_alarm_clock() { + if(HAS_PERM(PERM_NOTIMEOUT) || PERM_HIDE(currutmp) || currstat == MAILALL) + return; +// if(time(0) - currutmp->lastact > IDLE_TIMEOUT - 2) { + if(time(0) - currutmp->lastact > curr_idle_timeout - 2) { + clear(); + if(currpid > 0) kill(currpid, SIGHUP); + } +// alarm(IDLE_TIMEOUT); + alarm(curr_idle_timeout); +} + +void init_alarm() { + signal(SIGALRM, (void (*)(int))hit_alarm_clock); +// alarm(IDLE_TIMEOUT); + alarm(curr_idle_timeout); +} + +/* ----------------------------------------------------- */ +/* output routines */ +/* ----------------------------------------------------- */ + +void oflush() { + if(obufsize) { + write(1, outbuf, obufsize); + obufsize = 0; + } +} + +void init_buf() +{ + + memset(inbuf,0,IBUFSIZE); +} +void output(char *s, int len) { + /* Invalid if len >= OBUFSIZE */ + + if(obufsize + len > OBUFSIZE) { + write(1, outbuf, obufsize); + obufsize = 0; + } + memcpy(outbuf + obufsize, s, len); + obufsize += len; +} + +int ochar(int c) { + if(obufsize > OBUFSIZE - 1) { + write(1, outbuf, obufsize); + obufsize = 0; + } + outbuf[obufsize++] = c; + return 0; +} + +/* ----------------------------------------------------- */ +/* input routines */ +/* ----------------------------------------------------- */ + +static int i_newfd = 0; +static struct timeval i_to, *i_top = NULL; +static int (*flushf) () = NULL; + +void add_io(int fd, int timeout) { + i_newfd = fd; + if(timeout) { + i_to.tv_sec = timeout; + i_to.tv_usec = 16384; /* Ptt: §ï¦¨16384 ÁקK¤£«ö®Éfor loop¦Ycpu time + 16384 ¬ù¨C¬í64¦¸ */ + i_top = &i_to; + } else + i_top = NULL; +} + +int num_in_buf() { + return icurrchar - ibufsize; +} + +int watermode = -1; +/* Ptt ¤ô²y¦^ÅU¥Îªº°Ñ¼Æ */ +/* watermode = -1 ¨S¦b¦^¤ô²y + = 0 ¦b¦^¤W¤@Áû¤ô²y (Ctrl-R) + > 0 ¦b¦^«e n Áû¤ô²y (Ctrl-R Ctrl-R) */ + +/* + dogetch() is not reentrant-safe. SIGUSR[12] might happen at any time, + and dogetch() might be called again, and then ibufsize/icurrchar/inbuf + might be inconsistent. + We try to not segfault here... +*/ + +static int dogetch() { + int len; + + if(ibufsize <= icurrchar) { + + if(flushf) + (*flushf)(); + + refresh(); + + if(i_newfd) { + + struct timeval timeout; + fd_set readfds; + + if(i_top) timeout=*i_top; /* copy it because select() might change it */ + + FD_ZERO(&readfds); + FD_SET(0, &readfds); + FD_SET(i_newfd, &readfds); + + /* jochang: modify first argument of select from FD_SETSIZE */ + /* since we are only waiting input from fd 0 and i_newfd(>0) */ + + while((len = select(i_newfd+1, &readfds, NULL, NULL, i_top?&timeout:NULL))<0) + { + if(errno != EINTR) + abort_bbs(0); + /* raise(SIGHUP); */ + } + + if(len == 0) + return I_TIMEOUT; + + if(i_newfd && FD_ISSET(i_newfd, &readfds)) + return I_OTHERDATA; + } + + while((len = read(0, inbuf, IBUFSIZE)) <= 0) { + if(len == 0 || errno != EINTR) + abort_bbs(0); + /* raise(SIGHUP); */ + } + ibufsize = len; + icurrchar = 0; + } + + if(currutmp) + currutmp->lastact = time(0); + return inbuf[icurrchar++]; +} + +static int water_which_flag=0; +int igetch() { + register int ch; + while((ch = dogetch())) { + switch(ch) { + case Ctrl('L'): + redoscr(); + continue; + case Ctrl('U'): + if(currutmp != NULL && currutmp->mode != EDITING + && currutmp->mode != LUSERS && currutmp->mode) { + + screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); + int y, x, my_newfd; + + getyx(&y, &x); + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + my_newfd = i_newfd; + i_newfd = 0; + t_users(); + i_newfd = my_newfd; + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + move(y, x); + free(screen0); + redoscr(); + continue; + } else + return (ch); + case KEY_TAB: + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ) + if( currutmp != NULL && watermode > 0 ){ + watermode = (watermode + water_which->count) + % water_which->count + 1; + t_display_new(); + continue; + } + return ch; + break; + + case Ctrl('R'): + if(currutmp == NULL) + return (ch); + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + if( watermode > 0 ){ + watermode = (watermode + water_which->count) + % water_which->count + 1; + t_display_new(); + continue; + } + else if( currutmp->mode == 0 && + (currutmp->chatid[0]==2 || currutmp->chatid[0]==3) && + water_which->count != 0 && watermode == 0) { + /* ²Ä¤G¦¸«ö Ctrl-R */ + watermode = 1; + t_display_new(); + continue; + } + else if(currutmp->msgs[0].pid) { + /* ²Ä¤@¦¸«ö Ctrl-R (¥²¶·¥ý³Q¥á¹L¤ô²y) */ + screenline_t *screen0; + int y, x, my_newfd; + screen0 = calloc(t_lines, sizeof(screenline_t)); + getyx(&y, &x); + memcpy(screen0, big_picture, t_lines*sizeof(screenline_t)); + + /* ¦pªG¥¿¦btalkªº¸Ü¥ý¤£³B²z¹ï¤è°e¹L¨Óªº«Ê¥] (¤£¥hselect) */ + my_newfd = i_newfd; + i_newfd = 0; + show_last_call_in(0); + watermode = 0; + my_write(currutmp->msgs[0].pid, "¤ô²y¥á¹L¥h ¡G ", + currutmp->msgs[0].userid, 0); + i_newfd = my_newfd; + + /* ÁÙì¿Ã¹õ */ + memcpy(big_picture, screen0, t_lines*sizeof(screenline_t)); + move(y, x); + free(screen0); + redoscr(); + continue; + } + else + return ch; + } + + if( currutmp->msgs[0].pid && + WATERMODE(WATER_OFO) && watermode == -1 ){ + int y, x, my_newfd; + screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + getyx(&y, &x); + my_newfd = i_newfd; + i_newfd = 0; + my_write2(); + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + i_newfd = my_newfd; + move(y, x); + free(screen0); + redoscr(); + continue; + } + + return ch; + case '\n': /* Ptt§â \n®³±¼ */ + continue; + case Ctrl('T'): + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + if(watermode > 0) { + if(watermode>1) + watermode--; + else + watermode = water_which->count; + t_display_new(); + continue; + } + } + return (ch); + + case Ctrl('E'): + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + if(watermode >0){ + if( water_which_flag == (int)water_usies ) + water_which_flag = 0; + else + water_which_flag = + (water_which_flag+1) % (int)(water_usies+1); + if(water_which_flag==0) + water_which = &water[0]; + else + water_which = swater[water_which_flag-1]; + watermode = 1; + t_display_new(); + continue; + } + } + return ch; + + case Ctrl('W'): + if(watermode >0) + { + water_which_flag=(water_which_flag+water_usies)%(water_usies+1); + if(water_which_flag==0) + water_which = &water[0]; + else + water_which = swater[water_which_flag-1]; + watermode = 1; + t_display_new(); + continue; + } + else return ch; + default: + return ch; + } + } + return 0; +} + +int oldgetdata(int line, int col, char *prompt, char *buf, int len, int echo) { + register int ch, i; + int clen; + int x = col, y = line; + extern unsigned char scr_cols; +#define MAXLASTCMD 12 + static char lastcmd[MAXLASTCMD][80]; + + strip_ansi(buf, buf, STRIP_ALL); + + if(prompt) { + + move(line, col); + + clrtoeol(); + + outs(prompt); + + x += strip_ansi(NULL,prompt,0); + } + + if(!echo) { + len--; + clen = 0; + while((ch = igetch()) != '\r') { + if(ch == '\177' || ch == Ctrl('H')) { + if(!clen) { + bell(); + continue; + } + clen--; + if(echo) { + ochar(Ctrl('H')); + ochar(' '); + ochar(Ctrl('H')); + } + continue; + } +// Ptt +#ifdef BIT8 + if(!isprint2(ch)) +#else + if(!isprint(ch)) +#endif + { + if(echo) + bell(); + continue; + } + + if(clen >= len) { + if(echo) + bell(); + continue; + } + buf[clen++] = ch; + if(echo) + ochar(ch); + } + buf[clen] = '\0'; + outc('\n'); + oflush(); + } else { + int cmdpos = -1; + int currchar = 0; + + standout(); + for(clen = len--; clen; clen--) + outc(' '); + standend(); + buf[len] = 0; + move(y, x); + edit_outs(buf); + clen = currchar = strlen(buf); + + while(move(y, x + currchar), (ch = igetkey()) != '\r') { + switch(ch) { + case KEY_DOWN: + case Ctrl('N'): + buf[clen] = '\0'; /* Ptt */ + strncpy(lastcmd[cmdpos], buf, 79); + cmdpos += MAXLASTCMD - 2; + case Ctrl('P'): + case KEY_UP: + if(ch == KEY_UP || ch == Ctrl('P')) { + buf[clen] = '\0'; /* Ptt */ + strncpy(lastcmd[cmdpos], buf, 79); + } + cmdpos++; + cmdpos %= MAXLASTCMD; + strncpy(buf, lastcmd[cmdpos], len); + buf[len] = 0; + + move(y, x); /* clrtoeof */ + for(i = 0; i <= clen; i++) + outc(' '); + move(y, x); + edit_outs(buf); + clen = currchar = strlen(buf); + break; + case KEY_LEFT: + if(currchar) + --currchar; + break; + case KEY_RIGHT: + if(buf[currchar]) + ++currchar; + break; + case '\177': + case Ctrl('H'): + if(currchar) { + currchar--; + clen--; + for(i = currchar; i <= clen; i++) + buf[i] = buf[i + 1]; + move(y, x + clen); + outc(' '); + move(y, x); + edit_outs(buf); + } + break; + case Ctrl('Y'): + currchar = 0; + case Ctrl('K'): + buf[currchar] = 0; + move(y, x + currchar); + for(i = currchar; i < clen; i++) + outc(' '); + clen = currchar; + break; + case Ctrl('D'): + if(buf[currchar]) { + clen--; + for(i = currchar; i <= clen; i++) + buf[i] = buf[i + 1]; + move(y, x + clen); + outc(' '); + move(y, x); + edit_outs(buf); + } + break; + case Ctrl('A'): + currchar = 0; + break; + case Ctrl('E'): + currchar = clen; + break; + default: + if(isprint2(ch) && clen < len && x + clen < scr_cols) { + for(i = clen + 1; i > currchar;i--) + buf[i] = buf[i - 1]; + buf[currchar] = ch; + move(y, x + currchar); + edit_outs(buf + currchar); + currchar++; + clen++; + } + break; + }/* end case */ + } /* end while */ + + if(clen > 1) + for(cmdpos = MAXLASTCMD - 1; cmdpos; cmdpos--) { + strcpy(lastcmd[cmdpos], lastcmd[cmdpos - 1]); + strncpy(lastcmd[0], buf, len); + } + if(echo) + outc('\n'); + refresh(); + } + if((echo == LCECHO) && ((ch = buf[0]) >= 'A') && (ch <= 'Z')) + buf[0] = ch | 32; +#ifdef SUPPORT_GB + if(echo == DOECHO && current_font_type == TYPE_GB) + { + strcpy(buf,hc_convert_str(buf, HC_GBtoBIG, HC_DO_SINGLE)); + } +#endif + return clen; +} + +/* Ptt */ +int getdata_buf(int line, int col, char *prompt, char *buf, int len, int echo) { + return oldgetdata(line, col, prompt, buf, len, echo); +} + +char +getans(char *prompt) +{ + char ans[5]; + + getdata(t_lines-1, 0, prompt, ans, 4, LCECHO); + return ans[0]; +} + +int getdata_str(int line, int col, char *prompt, char *buf, int len, int echo, char *defaultstr) { + strncpy(buf, defaultstr, len); + + buf[len] = 0; + return oldgetdata(line, col, prompt, buf, len, echo); +} + +int getdata(int line, int col, char *prompt, char *buf, int len, int echo) { + buf[0] = 0; + return oldgetdata(line, col, prompt, buf, len, echo); +} + +int +rget(int x,char *prompt) +{ + register int ch; + + move(x,0); + clrtobot(); + outs(prompt); + refresh(); + + ch = igetch(); + if( ch >= 'A' && ch <= 'Z') ch |= 32; + + return ch; +} + + +int KEY_ESC_arg; + +int igetkey() { + int mode; + int ch, last; + + mode = last = 0; + while(1) { + ch = igetch(); + if(mode == 0) { + if(ch == KEY_ESC) + mode = 1; + else + return ch; /* Normal Key */ + } else if (mode == 1) { /* Escape sequence */ + if(ch == '[' || ch == 'O') + mode = 2; + else if(ch == '1' || ch == '4') + mode = 3; + else { + KEY_ESC_arg = ch; + return KEY_ESC; + } + } else if(mode == 2) { /* Cursor key */ + if(ch >= 'A' && ch <= 'D') + return KEY_UP + (ch - 'A'); + else if(ch >= '1' && ch <= '6') + mode = 3; + else + return ch; + } else if (mode == 3) { /* Ins Del Home End PgUp PgDn */ + if(ch == '~') + return KEY_HOME + (last - '1'); + else + return ch; + } + last = ch; + } +} + diff --git a/mbbsd/kaede.c b/mbbsd/kaede.c new file mode 100644 index 00000000..c0bd5103 --- /dev/null +++ b/mbbsd/kaede.c @@ -0,0 +1,95 @@ +/* $Id: kaede.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "proto.h" + +extern struct utmpfile_t *utmpshm; +extern userec_t cuser; + +char *Ptt_prints(char *str, int mode) { + char *po , strbuf[256]; + + while((po = strstr(str, "\033*s"))) { + po[0] = 0; + sprintf(strbuf, "%s%s%s", str, cuser.userid, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*t"))) { + time_t now = time(0); + + po[0] = 0; + sprintf(strbuf, "%s%s", str, Cdate(&now)); + str[strlen(strbuf)-1] = 0; + strcat(strbuf, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*u"))) { + int attempts; + + attempts = utmpshm->number; + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, attempts, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*b"))) { + po[0] = 0; + sprintf(strbuf, "%s%d/%d%s", str, cuser.month, cuser.day, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*l"))) { + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, cuser.numlogins, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*p"))) { + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, cuser.numposts, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*n"))) { + po[0] = 0; + sprintf(strbuf, "%s%s%s", str, cuser.username, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*m"))) { + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, cuser.money, po + 3); + strcpy(str, strbuf); + } + strip_ansi(str, str ,mode); + return str; +} + +int Rename(char* src, char* dst) { + if(rename(src, dst) == 0) + return 0; + return -1; +} + +int Link(char* src, char* dst) { + char cmd[200]; + + if(strcmp(src, BBSHOME "/home") == 0) + return 1; + if(link(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +char *my_ctime(const time_t *t) { + struct tm *tp; + static char ans[100]; + + tp = localtime(t); + sprintf(ans, "%02d/%02d/%02d %02d:%02d:%02d", (tp->tm_year % 100), + tp->tm_mon + 1,tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); + return ans; +} diff --git a/mbbsd/lovepaper.c b/mbbsd/lovepaper.c new file mode 100644 index 00000000..52e8cbd5 --- /dev/null +++ b/mbbsd/lovepaper.c @@ -0,0 +1,120 @@ +/* $Id: lovepaper.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#define DATA "etc/lovepaper.dat" + +extern userec_t cuser; + +int x_love() { + char buf1[200], save_title[TTLEN + 1]; + char receiver[61], path[STRLEN] = "home/"; + int x, y = 0, tline = 0, poem = 0; + FILE *fp, *fpo; + time_t timenow; + struct tm *gtime; + fileheader_t mhdr; + + setutmpmode(LOVE); + time(&timenow); + gtime = localtime(&timenow); + sprintf(buf1,"%c/%s/love%d%d", + cuser.userid[0], cuser.userid,gtime->tm_sec,gtime->tm_min); + strcat(path,buf1); + move(1,0); + clrtobot(); + + outs("\nÅwªï¨Ï¥Î±¡®Ñ²£¥Í¾¹ v0.00 ª© \n"); + outs("¦³¦óÃø¥H±Ò¾¦ªº¸Ü,¥æ¥Ñ¨t²ÎÀ°§A»¡§a.\nª¨ª¨»¡ : Àݱ¡¤£¥Çªk.\n"); + + if(!getdata(7, 0, "¦¬«H¤H¡G", receiver, 60, DOECHO)) return 0; + if(receiver[0] && !(searchuser(receiver) && + getdata(8, 0, "¥D ÃD¡G", save_title, + TTLEN, DOECHO))) { + move(10, 0); + outs("¦¬«H¤H©Î¥DÃD¤£¥¿½T, ±¡®ÑµLªk¶Ç»¼. "); + pressanykey(); + return 0; + } + + fpo = fopen(path, "w"); + fprintf(fpo, "\n"); + if((fp = fopen(DATA, "r"))) { + while(fgets(buf1,100, fp)) { + switch(buf1[0]) { + case '#': + break; + case '@': + if(!strncmp(buf1, "@begin", 6) || !strncmp(buf1, "@end", 4)) + tline=3; + else if(!strncmp(buf1,"@poem",5)) { + poem = 1; + tline = 1; + fprintf(fpo, "\n\n"); + } else + tline=2; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + sscanf(buf1,"%d",&x); + y = (rand() % (x - 1)) * tline; + break; + default: + if(!poem) { + if(y > 0) + y = y - 1; + else { + if(tline > 0) { + fprintf(fpo, "%s", buf1); + tline--; + } + } + } else { + if(buf1[0] == '$') + y--; + else if(y == 0) + fprintf(fpo,"%s",buf1); + } + } + + } + + fclose(fp); + fclose(fpo); + if(vedit(path, YEA, NULL) == -1) { + unlink(path); + clear(); + outs("\n\n ©ñ±ó±H±¡®Ñ\n"); + pressanykey(); + return -2; + } + sethomepath(buf1, receiver); + stampfile(buf1, &mhdr); + Rename(path, buf1); + strncpy(mhdr.title, save_title, TTLEN); + strcpy(mhdr.owner, cuser.userid); + mhdr.savemode = '\0'; + sethomedir(path, receiver ); + if(append_record(path, &mhdr, sizeof(mhdr)) == -1) + return -1; + hold_mail(buf1, receiver); + return 1; + } + return 0; +} diff --git a/mbbsd/mail.c b/mbbsd/mail.c new file mode 100644 index 00000000..e480abb2 --- /dev/null +++ b/mbbsd/mail.c @@ -0,0 +1,1675 @@ +/* $Id: mail.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +extern int TagNum; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char save_title[]; /* used by editor when inserting */ +extern int curredit; +extern char *err_uid; +extern char *msg_cancel; +extern char *msg_uid; +extern char *fn_overrides; +extern char quote_file[80]; +extern char quote_user[80]; +extern char *fn_notes; +extern char *msg_mailer; +extern char *msg_sure_ny; +extern char *BBSName; +extern char currtitle[44]; +extern unsigned char currfmode; /* current file mode */ +extern char *msg_del_ny; +extern char currfile[FNLEN]; +extern int currmode; +extern char currboard[]; /* name of currently selected board */ +extern char *str_space; +extern char *str_author1; +extern char *str_author2; +extern userinfo_t *currutmp; +extern unsigned int currstat; +extern pid_t currpid; +extern int usernum; +extern char *str_mail_address; +extern userec_t cuser; + +char currmaildir[32]; +static char msg_cc[] = "\033[32m[¸s²Õ¦W³æ]\033[m\n"; +static char listfile[] = "list.0"; +static int mailkeep = 0, mailsum = 0; +static int mailsumlimit = 0,mailmaxkeep = 0; + +int setforward() { + char buf[80], ip[50] = "", yn[4]; + FILE *fp; + + sethomepath(buf, cuser.userid); + strcat(buf,"/.forward"); + if((fp = fopen(buf,"r"))) { + fscanf(fp,"%s",ip); + fclose(fp); + } + getdata_buf(b_lines - 1, 0, "½Ð¿é¤J«H½c¦Û°ÊÂà±Hªºemail¦a§}:", + ip, 41, DOECHO); + if(ip[0] && ip[0] != ' ') { + getdata(b_lines, 0, "½T©w¶}±Ò¦Û°ÊÂà«H¥\\¯à?(Y/n)", yn, 3, + LCECHO); + if(yn[0] != 'n' && (fp = fopen(buf, "w"))) { + move(b_lines,0); + clrtoeol(); + fprintf(fp,"%s",ip); + fclose(fp); + outs("³]©w§¹¦¨!"); + refresh(); + return 0; + } + } + move(b_lines,0); + clrtoeol(); + outs("¨ú®ø¦Û°ÊÂà«H!"); + unlink(buf); + refresh(); + return 0; +} + +int built_mail_index() { + char genbuf[128]; + + getdata(b_lines, 0, + "««Ø«H½c?(ĵ§i:½Ð½T©w«H½c¦³°ÝÃD®É¤~¨Ï¥Î)(y/N)", genbuf, 3, + LCECHO); + if(genbuf[0] != 'y') return 0; + + sprintf(genbuf, BBSHOME "/bin/buildir " BBSHOME "/home/%c/%s", + cuser.userid[0], cuser.userid); + move(22,0); + prints("\033[1;31m¤w¸g³B²z§¹²¦!! ½Ñ¦h¤£«K ·q½Ðì½Ì~\033[m");pressanykey(); + system(genbuf); + return 0; +} + +int mailalert(char *userid) +{ + userinfo_t *uentp=NULL; + int n,tuid,i; + + if((tuid=searchuser(userid))==0) return -1; + + n=count_logins(tuid, 0); + for(i=1;i<=n;i++) + if((uentp = (userinfo_t *)search_ulistn(tuid, i))) + uentp->mailalert=1; + return 0; +} + +int mail_muser(userec_t muser, char *title, char *filename) { + return mail_id(muser.userid, title, filename, cuser.userid); +} + +/* Heat: ¥Îid¨Ó±H«H,¤º®e«hlink·Ç³Æ¦nªºÀÉ®× */ +int mail_id(char* id, char *title, char *filename, char *owner) { + fileheader_t mhdr; + char genbuf[128]; + sethomepath(genbuf, id); + if(stampfile(genbuf, &mhdr)) + return 0; + strcpy(mhdr.owner, owner); + strncpy(mhdr.title, title, TTLEN); + mhdr.savemode = 0; + mhdr.filemode = 0; + Link(filename, genbuf); + sethomedir(genbuf,id); + append_record(genbuf, &mhdr, sizeof(mhdr)); + mailalert(id); + return 0; +} + +int invalidaddr(char *addr) { + if(*addr == '\0') + return 1; /* blank */ + while(*addr) { + if(not_alnum(*addr) && !strchr("[].%!@:-_;", *addr)) + return 1; + addr++; + } + return 0; +} + +int m_internet() { + char receiver[60]; + + getdata(20, 0, "¦¬«H¤H¡G", receiver, 60, DOECHO); + if(strchr(receiver, '@') && !invalidaddr(receiver) && + getdata(21, 0, "¥D ÃD¡G", save_title, TTLEN, DOECHO)) + do_send(receiver, save_title); + else { + move(22, 0); + outs("¦¬«H¤H©Î¥DÃD¤£¥¿½T, ½Ð«·s¿ï¨ú«ü¥O"); + pressanykey(); + } + return 0; +} + +void m_init() { + sethomedir(currmaildir, cuser.userid); +} + +int chkmailbox() { + if(!HAVE_PERM(PERM_SYSOP) && !HAVE_PERM(PERM_MAILLIMIT)) { + int max_keepmail = MAX_KEEPMAIL; + if ( HAS_PERM(PERM_SYSSUBOP) || HAS_PERM(PERM_SMG) || + HAS_PERM(PERM_PRG) || HAS_PERM(PERM_ACTION) || HAS_PERM(PERM_PAINT)) + { + mailsumlimit = 700; + max_keepmail = 500; + } + else if(HAS_PERM(PERM_BM)) + { + mailsumlimit = 500; + max_keepmail = 300; + } + else if(HAS_PERM(PERM_LOGINOK)) + mailsumlimit = 200; + else + mailsumlimit = 50; + mailsumlimit += cuser.exmailbox * 10; + mailmaxkeep = max_keepmail + cuser.exmailbox; + m_init(); + if((mailkeep = get_num_records(currmaildir, sizeof(fileheader_t))) > + mailmaxkeep) { + move(b_lines, 0); + clrtoeol(); + bell(); + prints("±z«O¦s«H¥ó¼Æ¥Ø %d ¶W¥X¤W %d, ½Ð¾ã²z", + mailkeep, mailmaxkeep); + bell(); + refresh(); + igetch(); + return mailkeep; + } + if((mailsum = get_sum_records(currmaildir, sizeof(fileheader_t))) > + mailsumlimit) { + move(b_lines, 0); + clrtoeol(); + bell(); + prints("±z«O¦s«H¥ó®e¶q %d(k)¶W¥X¤W %d(k), ½Ð¾ã²z", + mailsum, mailsumlimit); + bell(); + refresh(); + igetch(); + return mailkeep; + } + } + return 0; +} + +static void do_hold_mail(char *fpath, char *receiver, char *holder) { + char buf[80], title[128]; + + fileheader_t mymail; + + sethomepath(buf, holder); + stampfile(buf, &mymail); + + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[³Æ.§Ñ.¿ý]"); + if(receiver) { + sprintf(title, "(%s) %s", receiver, save_title); + strncpy(mymail.title, title, TTLEN); + } else + strcpy(mymail.title, save_title); + + sethomedir(title, holder); + + unlink(buf); + Link(fpath, buf); + /* Ptt: append_record->do_append */ + do_append(title, &mymail, sizeof(mymail)); +} + +extern userec_t xuser; + +void hold_mail(char *fpath, char *receiver) { + char buf[4]; + + getdata(b_lines - 1, 0, "¤w¶¶§Q±H¥X¡A¬O§_¦Û¦s©³½Z(Y/N)¡H[N] ", + buf, 4, LCECHO); + + if(buf[0] == 'y') + do_hold_mail(fpath, receiver, cuser.userid); +} + +int do_send(char *userid, char *title) { + fileheader_t mhdr; + char fpath[STRLEN]; + char receiver[IDLEN]; + char genbuf[200]; + int internet_mail, i; + + if(strchr(userid, '@')) + internet_mail = 1; + else { + internet_mail = 0; + if(!getuser(userid)) + return -1; + if(!(xuser.userlevel & PERM_READMAIL)) + return -3; + + if(!title) + getdata(2, 0, "¥DÃD¡G", save_title, TTLEN, DOECHO); + curredit |= EDIT_MAIL; + curredit &= ~EDIT_ITEM; + } + + setutmpmode(SMAIL); + + fpath[0] = '\0'; + + if(internet_mail) { + int res, ch; + + if(vedit(fpath, NA, NULL) == -1) { + unlink(fpath); + clear(); + return -2; + } + clear(); + prints("«H¥ó§Y±N±Hµ¹ %s\n¼ÐÃD¬°¡G%s\n½T©wn±H¥X¶Ü? (Y/N) [Y]", + userid, title); + ch = igetch(); + switch(ch) { + case 'N': + case 'n': + outs("N\n«H¥ó¤w¨ú®ø"); + res = -2; + break; + default: + outs("Y\n½ÐµyÔ, «H¥ó¶Ç»¼¤¤...\n"); + res = +#ifndef USE_BSMTP + bbs_sendmail(fpath, title, userid); +#else + bsmtp(fpath, title, userid,0); +#endif + hold_mail(fpath, userid); + } + unlink(fpath); + return res; + } else { + strcpy(receiver, userid); + sethomepath(genbuf, userid); + stampfile(genbuf, &mhdr); + strcpy(mhdr.owner, cuser.userid); + strncpy(mhdr.title, save_title, TTLEN); + mhdr.savemode = '\0'; + if(vedit(genbuf, YEA, NULL) == -1) { + unlink(genbuf); + clear(); + return -2; + } + clear(); + sethomefile(fpath, userid, FN_OVERRIDES); + i=belong(fpath, cuser.userid); + sethomefile(fpath, userid, FN_REJECT); + + if(i || !belong(fpath, cuser.userid)) //Ptt:¥Îbelong¦³ÂI°Q¹½ + { + sethomedir(fpath, userid); + if(append_record(fpath, &mhdr, sizeof(mhdr)) == -1) + return -1; + mailalert(userid); + } + hold_mail(genbuf, userid); + return 0; + } +} + +void my_send(char *uident) { + switch(do_send(uident, NULL)) { + case -1: + outs(err_uid); + break; + case -2: + outs(msg_cancel); + break; + case -3: + prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uident); + break; + } + pressanykey(); +} + +int m_send() { + char uident[40]; + + stand_title("¥BÅ¥·ªº¸Ü"); + usercomplete(msg_uid, uident); + showplans(uident); + if(uident[0]) + my_send(uident); + return 0; +} + +/* ¸s²Õ±H«H¡B¦^«H : multi_send, multi_reply */ +extern struct word_t *toplev; + +static void multi_list(int *reciper) { + char uid[16]; + char genbuf[200]; + + while(1) { + stand_title("¸s²Õ±H«H¦W³æ"); + ShowNameList(3, 0, msg_cc); + getdata(1, 0, + "(I)¤Þ¤J¦n¤Í (O)¤Þ¤J¤W½u³qª¾ (N)¤Þ¤J·s¤å³¹³qª¾ " + "(0-9)¤Þ¤J¨ä¥L¯S§O¦W³æ\n" + "(A)¼W¥[ (D)§R°£ (M)½T»{±H«H¦W³æ (Q)¨ú®ø ¡H[M]", + genbuf, 4, LCECHO); + switch(genbuf[0]) { + case 'a': + while(1) { + move(1, 0); + usercomplete("½Ð¿é¤Jn¼W¥[ªº¥N¸¹(¥u«ö ENTER µ²§ô·s¼W): ", uid); + if(uid[0] == '\0') + break; + + move(2, 0); + clrtoeol(); + + if(!searchuser(uid)) + outs(err_uid); + else if(!InNameList(uid)) { + AddNameList(uid); + (*reciper)++; + } + ShowNameList(3, 0, msg_cc); + } + break; + case 'd': + while(*reciper) { + move(1, 0); + namecomplete("½Ð¿é¤Jn§R°£ªº¥N¸¹(¥u«ö ENTER µ²§ô§R°£): ", uid); + if(uid[0] == '\0') + break; + if(RemoveNameList(uid)) + (*reciper)--; + ShowNameList(3, 0, msg_cc); + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + listfile[5] = genbuf[0]; + genbuf[0] = '1'; + case 'i': + setuserfile(genbuf, genbuf[0] == '1' ? listfile : fn_overrides); + ToggleNameList(reciper, genbuf, msg_cc); + break; + case 'o': + setuserfile(genbuf, "alohaed"); + ToggleNameList(reciper, genbuf, msg_cc); + break; + case 'n': + setuserfile(genbuf, "postlist"); + ToggleNameList(reciper, genbuf, msg_cc); + break; + case 'q': + *reciper = 0; + return; + default: + return; + } + } +} + +static void multi_send(char *title) { + FILE *fp; + struct word_t *p; + fileheader_t mymail; + char fpath[TTLEN], *ptr; + int reciper, listing; + char genbuf[256]; + + CreateNameList(); + listing = reciper = 0; + if(*quote_file) { + AddNameList(quote_user); + reciper = 1; + fp = fopen(quote_file, "r"); + while(fgets(genbuf, 256, fp)) { + if(strncmp(genbuf, "¡° ", 3)) { + if(listing) + break; + } else { + if(listing) { + strtok(ptr = genbuf + 3, " \n\r"); + do { + if(searchuser(ptr) && !InNameList(ptr) && + strcmp(cuser.userid, ptr)) { + AddNameList(ptr); + reciper++; + } + } while((ptr = (char *)strtok(NULL, " \n\r"))); + } else if(!strncmp(genbuf + 3, "[³q§i]", 6)) + listing = 1; + } + } + ShowNameList(3, 0, msg_cc); + } + + multi_list(&reciper); + move(1, 0); + clrtobot(); + + if(reciper) { + setutmpmode(SMAIL); + if(title) + do_reply_title(2, title); + else { + getdata(2, 0, "¥DÃD¡G", fpath, 64, DOECHO); + sprintf(save_title, "[³q§i] %s", fpath); + } + + setuserfile(fpath, fn_notes); + + if((fp = fopen(fpath, "w"))) { + fprintf(fp, "¡° [³q§i] ¦@ %d ¤H¦¬¥ó", reciper); + listing = 80; + + for(p = toplev; p; p = p->next) { + reciper = strlen(p->word) + 1; + if(listing + reciper > 75) { + listing = reciper; + fprintf(fp, "\n¡°"); + } else + listing += reciper; + + fprintf(fp, " %s", p->word); + } + memset(genbuf, '-', 75); + genbuf[75] = '\0'; + fprintf(fp, "\n%s\n\n", genbuf); + fclose(fp); + } + + curredit |= EDIT_LIST; + + if(vedit(fpath, YEA, NULL) == -1) { + unlink(fpath); + curredit = 0; + outs(msg_cancel); + pressanykey(); + return; + } + + stand_title("±H«H¤¤..."); + refresh(); + + listing = 80; + + for(p = toplev; p; p = p->next) { + reciper = strlen(p->word) + 1; + if(listing + reciper > 75) { + listing = reciper; + outc('\n'); + } else { + listing += reciper; + outc(' '); + } + outs(p->word); + if(searchuser(p->word) && strcmp(STR_GUEST, p->word) ) + sethomepath(genbuf, p->word); + else + continue; + stampfile(genbuf, &mymail); + unlink(genbuf); + Link(fpath, genbuf); + + strcpy(mymail.owner, cuser.userid); + strcpy(mymail.title, save_title); + mymail.savemode = 'M'; /* multi-send flag */ + sethomedir(genbuf, p->word); + if(append_record(genbuf, &mymail, sizeof(mymail)) == -1) + outs(err_uid); + mailalert(p->word); + } + hold_mail(fpath, NULL); + unlink(fpath); + curredit = 0; + } else + outs(msg_cancel); + pressanykey(); +} + +static int multi_reply(int ent, fileheader_t *fhdr, char *direct) { + if(fhdr->savemode != 'M') + return mail_reply(ent, fhdr, direct); + + stand_title("¸s²Õ¦^«H"); + strcpy(quote_user, fhdr->owner); + setuserfile(quote_file, fhdr->filename); + multi_send(fhdr->title); + return 0; +} + +int mail_list() { + stand_title("¸s²Õ§@·~"); + multi_send(NULL); + return 0; +} + +int mail_all() { + FILE *fp; + fileheader_t mymail; + char fpath[TTLEN]; + char genbuf[200]; + extern struct uhash_t *uhash; + int i, unum; + char *userid; + + stand_title("µ¹©Ò¦³¨Ï¥ÎªÌªº¨t²Î³q§i"); + setutmpmode(SMAIL); + getdata(2, 0, "¥DÃD¡G", fpath, 64, DOECHO); + sprintf(save_title, "[¨t²Î³q§i]\033[1;32m %s\033[m", fpath); + + setuserfile(fpath, fn_notes); + + if((fp = fopen(fpath, "w"))) { + fprintf(fp, "¡° [\033[1m¨t²Î³q§i\033[m] ³o¬O«Êµ¹©Ò¦³¨Ï¥ÎªÌªº«H\n"); + fprintf(fp, "-----------------------------------------------------" + "----------------------\n"); + fclose(fp); + } + + *quote_file = 0; + + curredit |= EDIT_MAIL; + curredit &= ~EDIT_ITEM; + if(vedit(fpath, YEA, NULL) == -1) { + curredit = 0; + unlink(fpath); + outs(msg_cancel); + pressanykey(); + return 0; + } + curredit = 0; + + setutmpmode(MAILALL); + stand_title("±H«H¤¤..."); + + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mymail); + unlink(genbuf); + Link(fpath, genbuf); + unlink(fpath); + strcpy(fpath, genbuf); + + strcpy(mymail.owner, cuser.userid); /*¯¸ªø ID*/ + strcpy(mymail.title, save_title); + mymail.savemode = 0; + + sethomedir(genbuf, cuser.userid); + if(append_record(genbuf, &mymail, sizeof(mymail)) == -1) + outs(err_uid); + + for(unum = uhash->number, i = 0; i < unum; i++) { + if(bad_user_id(uhash->userid[i])) + continue; /* Ptt */ + + userid = uhash->userid[i]; + if(strcmp(userid,STR_GUEST) && strcmp(userid, "new") && + strcmp(userid, cuser.userid)) { + sethomepath(genbuf, userid); + stampfile(genbuf, &mymail); + unlink(genbuf); + Link(fpath, genbuf); + + strcpy(mymail.owner, cuser.userid); + strcpy(mymail.title, save_title); + mymail.savemode = 0; + /* mymail.filemode |= FILE_MARKED; Ptt ¤½§i§ï¦¨¤£·|mark */ + sethomedir(genbuf, userid); + if(append_record(genbuf, &mymail, sizeof(mymail)) == -1) + outs(err_uid); + sprintf(genbuf, "%*s %5d / %5d", IDLEN + 1, userid, i + 1, unum); + outmsg(genbuf); + refresh(); + } + } + return 0; +} + +int mail_mbox() { + char cmd[100]; + fileheader_t fhdr; + + sprintf(cmd, "/tmp/%s.uu", cuser.userid); + sprintf(fhdr.title, "%s ¨p¤H¸ê®Æ", cuser.userid); + doforward(cmd, &fhdr, 'Z'); + return 0; +} + +static int m_forward(int ent, fileheader_t *fhdr, char *direct) { + char uid[STRLEN]; + + stand_title("Âà¹F«H¥ó"); + usercomplete(msg_uid, uid); + if(uid[0] == '\0') + return FULLUPDATE; + + strcpy(quote_user, fhdr->owner); + setuserfile(quote_file, fhdr->filename); + sprintf(save_title, "%.64s (fwd)", fhdr->title); + move(1, 0); + clrtobot(); + prints("Âà«Hµ¹: %s\n¼Ð ÃD: %s\n", uid, save_title); + + switch(do_send(uid, save_title)) { + case -1: + outs(err_uid); + break; + case -2: + outs(msg_cancel); + break; + case -3: + prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uid); + break; + } + pressanykey(); + return FULLUPDATE; +} + +static int delmsgs[128]; +static int delcnt; +static int mrd; + +static int read_new_mail(fileheader_t *fptr) { + static int idc; + char done = NA, delete_it; + char fname[256]; + char genbuf[4]; + + if(fptr == NULL) { + delcnt = 0; + idc = 0; + return 0; + } + idc++; + if(fptr->filemode) + return 0; + clear(); + move(10, 0); + prints("±znŪ¨Ó¦Û[%s]ªº°T®§(%s)¶Ü¡H", fptr->owner, fptr->title); + getdata(11, 0, "½Ð±z½T©w(Y/N/Q)?[Y] ", genbuf, 3, DOECHO); + if(genbuf[0] == 'q') + return QUIT; + if(genbuf[0] == 'n') + return 0; + + setuserfile(fname, fptr->filename); + fptr->filemode |= FILE_READ; + if(substitute_record(currmaildir, fptr, sizeof(*fptr), idc)) + return -1; + + mrd = 1; + delete_it = NA; + while(!done) { + int more_result = more(fname, YEA); + + switch(more_result) { + case 1: + return READ_PREV; + case 2: + return RELATE_PREV; + case 3: + return READ_NEXT; + case 4: + return RELATE_NEXT; + case 5: + return RELATE_FIRST; + case 6: + return 0; + case 7: + mail_reply(idc, fptr, currmaildir); + return FULLUPDATE; + case 8: + multi_reply(idc, fptr, currmaildir); + return FULLUPDATE; + } + move(b_lines, 0); + clrtoeol(); + outs(msg_mailer); + refresh(); + + switch(egetch()) { + case 'r': + case 'R': + mail_reply(idc, fptr, currmaildir); + break; + case 'x': + m_forward(idc, fptr, currmaildir); + break; + case 'y': + multi_reply(idc, fptr, currmaildir); + break; + case 'd': + case 'D': + delete_it = YEA; + default: + done = YEA; + } + } + if(delete_it) { + clear(); + prints("§R°£«H¥ó¡m%s¡n", fptr->title); + getdata(1, 0, msg_sure_ny, genbuf, 2, LCECHO); + if(genbuf[0] == 'y') { + unlink(fname); + delmsgs[delcnt++] = idc; + } + } + clear(); + return 0; +} + +int m_new() { + clear(); + mrd = 0; + setutmpmode(RMAIL); + read_new_mail(NULL); + clear(); + curredit |= EDIT_MAIL; + curredit &= ~EDIT_ITEM; + if(apply_record(currmaildir, read_new_mail, sizeof(fileheader_t)) == -1) { + outs("¨S¦³·s«H¥ó¤F"); + pressanykey(); + return -1; + } + curredit = 0; + if(delcnt) { + while(delcnt--) + delete_record(currmaildir, sizeof(fileheader_t), delmsgs[delcnt]); + } + outs(mrd ? "«H¤w¾\\²¦" : "¨S¦³·s«H¥ó¤F"); + pressanykey(); + return -1; +} + +static void mailtitle() { + char buf[256] = ""; + + showtitle("\0¶l¥ó¿ï³æ", BBSName); + sprintf(buf,"[¡ö]Â÷¶}[¡ô¡õ]¿ï¾Ü[¡÷]¾\\Ū«H¥ó [R]¦^«H [x]Âà¹F " + "[y]¸s²Õ¦^«H [O]¯¸¥~«H:%s [h]¨D§U\n\033[7m" + "½s¸¹ ¤é ´Á §@ ªÌ «H ¥ó ¼Ð ÃD \033[32m", + HAS_PERM(PERM_NOOUTMAIL)? "\033[31mÃö\033[m":"¶}"); + outs(buf); + buf[0]=0; + if(mailsumlimit) { + sprintf(buf,"(®e¶q:%d/%dk %d/%d½g)", mailsum, mailsumlimit, + mailkeep, mailmaxkeep); + } + sprintf(buf, "%s%*s\033[m", buf, 29 - (int) strlen(buf), ""); + outs(buf); +} + +static void maildoent(int num, fileheader_t *ent) { + char *title, *mark, color, type = "+ Mm"[ent->filemode]; + + if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) + type = 'D'; + + title = subject(mark = ent->title); + if(title == mark) { + color = '1'; + mark = "¡º"; + } else { + color = '3'; + mark = "R:"; + } + + if(strncmp(currtitle, title, 40)) + prints("%5d %c %-7s%-15.14s%s %.46s\n", num, type, + ent->date, ent->owner, mark, title); + else + prints("%5d %c %-7s%-15.14s\033[1;3%cm%s %.46s\033[0m\n", num, type, + ent->date, ent->owner, color, mark, title); +} + +#ifdef POSTBUG +extern int bug_possible; +#endif + + +static int m_idle(int ent, fileheader_t *fhdr, char *direct) { + t_idle(); + return FULLUPDATE; +} + +static int mail_del(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + + if(fhdr->filemode & FILE_MARKED) + return DONOTHING; + + getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO); + if(genbuf[0] == 'y') { + strcpy(currfile, fhdr->filename); + if(!delete_file(direct, sizeof(*fhdr), ent, cmpfilename)) { + setdirpath(genbuf, direct, fhdr->filename); + unlink(genbuf); + if((currmode & MODE_SELECT)) { + int now; + + sethomedir(genbuf, cuser.userid); + now = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + delete_file(genbuf, sizeof(fileheader_t), now, cmpfilename); + } + return DIRCHANGED; + } + } + return FULLUPDATE; +} + +static int mail_read(int ent, fileheader_t *fhdr, char *direct) { + char buf[64]; + char done, delete_it, replied; + + clear(); + setdirpath(buf, direct, fhdr->filename); + strncpy(currtitle, subject(fhdr->title), 40); + done = delete_it = replied = NA; + while(!done) { + int more_result = more(buf, YEA); + + if(more_result != -1) { + fhdr->filemode |= FILE_READ; + if((currmode & MODE_SELECT)) { + int now; + + now = getindex(currmaildir, fhdr->filename, + sizeof(fileheader_t)); + substitute_record(currmaildir, fhdr, sizeof(*fhdr), now); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + } + else + substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent); + } + switch(more_result) { + case 1: + return READ_PREV; + case 2: + return RELATE_PREV; + case 3: + return READ_NEXT; + case 4: + return RELATE_NEXT; + case 5: + return RELATE_FIRST; + case 6: + return FULLUPDATE; + case 7: + mail_reply(ent, fhdr, direct); + return FULLUPDATE; + case 8: + multi_reply(ent, fhdr, direct); + return FULLUPDATE; + } + move(b_lines, 0); + clrtoeol(); + refresh(); + outs(msg_mailer); + + switch(egetch()) { + case 'r': + case 'R': + replied = YEA; + mail_reply(ent, fhdr, direct); + break; + case 'x': + m_forward(ent, fhdr, direct); + break; + case 'y': + multi_reply(ent, fhdr, direct); + break; + case 'd': + delete_it = YEA; + default: + done = YEA; + } + } + if(delete_it) + mail_del(ent, fhdr, direct); + else { + fhdr->filemode |= FILE_READ; +#ifdef POSTBUG + if(replied) + bug_possible = YEA; +#endif + if((currmode & MODE_SELECT)) { + int now; + + now = getindex(currmaildir, fhdr->filename, sizeof(fileheader_t)); + substitute_record(currmaildir, fhdr, sizeof(*fhdr), now); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + } else + substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent); +#ifdef POSTBUG + bug_possible = NA; +#endif + } + return FULLUPDATE; +} + +/* in boards/mail ¦^«Hµ¹ì§@ªÌ¡AÂà«H¯¸¥ç¥i */ +int mail_reply(int ent, fileheader_t *fhdr, char *direct) { + char uid[STRLEN]; + char *t; + FILE *fp; + char genbuf[512]; + + stand_title("¦^ «H"); + + /* §PÂ_¬O boards ©Î mail */ + if(curredit & EDIT_MAIL) + setuserfile(quote_file, fhdr->filename); + else + setbfile(quote_file, currboard, fhdr->filename); + + /* find the author */ + strcpy(quote_user, fhdr->owner); + if(strchr(quote_user, '.')) { + genbuf[0] = '\0'; + if((fp = fopen(quote_file, "r"))) { + fgets(genbuf, 512, fp); + fclose(fp); + } + + t = strtok(genbuf, str_space); + if(!strcmp(t, str_author1) || !strcmp(t, str_author2)) + strcpy(uid, strtok(NULL, str_space)); + else { + outs("¿ù»~: §ä¤£¨ì§@ªÌ¡C"); + pressanykey(); + return FULLUPDATE; + } + } else + strcpy(uid, quote_user); + + /* make the title */ + do_reply_title(3, fhdr->title); + prints("\n¦¬«H¤H: %s\n¼Ð ÃD: %s\n", uid, save_title); + + /* edit, then send the mail */ + ent = curredit; + switch(do_send(uid, save_title)) { + case -1: + outs(err_uid); + break; + case -2: + outs(msg_cancel); + break; + case -3: + prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uid); + break; + } + curredit = ent; + pressanykey(); + return FULLUPDATE; +} + +static int mail_edit(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + + if(!HAS_PERM(PERM_SYSOP) && + strcmp(cuser.userid, fhdr->owner) && + strcmp("[³Æ.§Ñ.¿ý]", fhdr->owner)) + return DONOTHING; + + setdirpath(genbuf, direct, fhdr->filename); + vedit(genbuf, NA, NULL); + return FULLUPDATE; +} + +static int mail_nooutmail(int ent, fileheader_t *fhdr, char *direct) +{ + cuser.userlevel ^= PERM_NOOUTMAIL; + passwd_update(usernum, &cuser); + return FULLUPDATE; + +} + +static int mail_mark(int ent, fileheader_t *fhdr, char *direct) { + fhdr->filemode ^= FILE_MARKED; + + if((currmode & MODE_SELECT)) { + int now; + + now = getindex(currmaildir, fhdr->filename, sizeof(fileheader_t)); + substitute_record(currmaildir, fhdr, sizeof(*fhdr), now); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + } else + substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent); + return PART_REDRAW; +} + +/* help for mail reading */ +static char *mail_help[] = { + "\0¹q¤l«H½c¾Þ§@»¡©ú", + "\01°ò¥»©R¥O", + "(p)(¡ô) «e¤@½g¤å³¹", + "(n)(¡õ) ¤U¤@½g¤å³¹", + "(P)(PgUp) «e¤@¶", + "(N)(PgDn) ¤U¤@¶", + "(##)(cr) ¸õ¨ì²Ä ## µ§", + "($) ¸õ¨ì³Ì«á¤@µ§", + "\01¶i¶¥©R¥O", + "(r)(¡÷)/(R)Ū«H / ¦^«H", + "(O) Ãö³¬/¶}±Ò ¯¸¥~«H¥óÂà¤J", + "(c/z) ¦¬¤J¦¹«H¥ó¶i¤J¨p¤H«H¥ó§¨/¶i¤J¨p¤H«H¥ó§¨", + "(x/X) Âà¹F«H¥ó/Âà¿ý¤å³¹¨ì¨ä¥L¬ÝªO", + "(y) ¸s²Õ¦^«H", + "(F) ±N«H¶Ç°e¦^±zªº¹q¤l«H½c (u)¤ô²y¾ã²z±H¦^«H½c", + "(d) ±þ±¼¦¹«H", + "(D) ±þ±¼«ü©w½d³òªº«H", + "(m) ±N«H¼Ð°O¡A¥H¨¾³Q²M°£", + "(^G) ¥ß§Y««Ø«H½c («H½c·´·l®É¥Î)", + "(t) ¼Ð°O±ý§R°£«H¥ó", + "(^D) §R°£¤w¼Ð°O«H¥ó", + NULL +}; + +static int m_help() { + show_help(mail_help); + return FULLUPDATE; +} + +static int mail_cross_post(int ent, fileheader_t *fhdr, char *direct) { + char xboard[20], fname[80], xfpath[80], xtitle[80], inputbuf[10]; + fileheader_t xfile; + FILE *xptr; + int author = 0; + char genbuf[200]; + char genbuf2[4]; + + make_blist(); + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + namecomplete("Âà¿ý¥»¤å³¹©ó¬ÝªO¡G", xboard); + if(*xboard == '\0' || !haspostperm(xboard)) + return FULLUPDATE; + + ent = 1; + if(HAS_PERM(PERM_SYSOP) || !strcmp(fhdr->owner, cuser.userid)) { + getdata(2, 0, "(1)ì¤åÂà¸ü (2)ÂÂÂà¿ý®æ¦¡¡H[1] ", + genbuf, 3, DOECHO); + if(genbuf[0] != '2') { + ent = 0; + getdata(2, 0, "«O¯dì§@ªÌ¦WºÙ¶Ü?[Y] ", inputbuf, 3, DOECHO); + if(inputbuf[0] != 'n' && inputbuf[0] != 'N') + author = 1; + } + } + + if(ent) + sprintf(xtitle, "[Âà¿ý]%.66s", fhdr->title); + else + strcpy(xtitle, fhdr->title); + + sprintf(genbuf, "±Ä¥Îì¼ÐÃD¡m%.60s¡n¶Ü?[Y] ", xtitle); + getdata(2, 0, genbuf, genbuf2, 4, LCECHO); + if(*genbuf2 == 'n') + if(getdata(2, 0, "¼ÐÃD¡G", genbuf, TTLEN, DOECHO)) + strcpy(xtitle, genbuf); + + getdata(2, 0, "(S)¦sÀÉ (L)¯¸¤º (Q)¨ú®ø¡H[Q] ", genbuf, 3, LCECHO); + if(genbuf[0] == 'l' || genbuf[0] == 's') { + int currmode0 = currmode; + + currmode = 0; + setbpath(xfpath, xboard); + stampfile(xfpath, &xfile); + if(author) + strcpy(xfile.owner, fhdr->owner); + else + strcpy(xfile.owner, cuser.userid); + strcpy(xfile.title, xtitle); + if(genbuf[0] == 'l') { + xfile.savemode = 'L'; + xfile.filemode = FILE_LOCAL; + } else + xfile.savemode = 'S'; + + setuserfile(fname, fhdr->filename); + if(ent) { + xptr = fopen(xfpath, "w"); + + strcpy(save_title, xfile.title); + strcpy(xfpath, currboard); + strcpy(currboard, xboard); + write_header(xptr); + strcpy(currboard, xfpath); + + fprintf(xptr, "¡° [¥»¤åÂà¿ý¦Û %s «H½c]\n\n", cuser.userid); + + b_suckinfile(xptr, fname); + addsignature(xptr,0); + fclose(xptr); + } else { + unlink(xfpath); + Link(fname, xfpath); + } + + setbdir(fname, xboard); + append_record(fname, &xfile, sizeof(xfile)); + setbtotal(getbnum(xboard)); + if(!xfile.filemode) + outgo_post(&xfile, xboard); + cuser.numposts++; + passwd_update(usernum, &cuser); + outs("¤å³¹Âà¿ý§¹¦¨"); + pressanykey(); + currmode = currmode0; + } + return FULLUPDATE; +} + +int mail_man() { + char buf[64],buf1[64]; + if (HAS_PERM(PERM_MAILLIMIT)) { + int mode0 = currutmp->mode; + int stat0 = currstat; + + sethomeman(buf, cuser.userid); + sprintf(buf1, "%s ªº«H¥ó§¨", cuser.userid); + a_menu(buf1, buf, 1); + currutmp->mode = mode0; + currstat = stat0; + return FULLUPDATE; + } + return DONOTHING; +} + +static int mail_cite(int ent, fileheader_t *fhdr, char *direct) { + char fpath[256]; + char title[TTLEN + 1]; + static char xboard[20]; + char buf[20]; + boardheader_t *bp; + + setuserfile(fpath, fhdr->filename); + strcpy(title, "¡º "); + strncpy(title+3, fhdr->title, TTLEN-3); + title[TTLEN] = '\0'; + a_copyitem(fpath, title, 0, 1); + + if(cuser.userlevel >= PERM_BM) { + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + make_blist(); + namecomplete("¿é¤J¬Ýª©¦WºÙ (ª½±µEnter¶i¤J¨p¤H«H¥ó§¨)¡G", buf); + if(*buf) + strcpy(xboard, buf); + if(*xboard && (bp = getbcache(getbnum(xboard)))) { + setapath(fpath, xboard); + setutmpmode(ANNOUNCE); + a_menu(xboard, fpath, HAS_PERM(PERM_ALLBOARD) ? 2 : + is_BM(bp->BM) ? 1 : 0); + } else { + mail_man(); + } + return FULLUPDATE; + } else { + mail_man(); + return FULLUPDATE; + } +} + +static int mail_save(int ent, fileheader_t *fhdr, char *direct) { + char fpath[256]; + char title[TTLEN+1]; + + if(HAS_PERM(PERM_MAILLIMIT)) { + setuserfile(fpath, fhdr->filename); + strcpy(title, "¡º "); + strncpy(title + 3, fhdr->title, TTLEN - 3); + title[TTLEN] = '\0'; + a_copyitem(fpath, title, fhdr->owner, 1); + sethomeman(fpath, cuser.userid); + a_menu(cuser.userid, fpath, 1); + return FULLUPDATE; + } + return DONOTHING; +} + +#ifdef OUTJOBSPOOL +static int mail_waterball(int ent, fileheader_t *fhdr, char *direct) +{ + static char address[60], cmode = 1; + char fname[500], genbuf[200]; + FILE *fp; + int now; + + if(!address[0]) + strcpy(address, cuser.email); + if(address[0]) { + sprintf(genbuf, "±Hµ¹ [%s] ¶Ü(Y/N/Q)¡H[Y] ", address); + getdata(b_lines - 2, 0, genbuf, fname, 3, LCECHO); + if(fname[0] == 'q') { outmsg("¨ú®ø³B²z"); return 1; } + if(fname[0] == 'n') + address[0] = '\0'; + } + + if(!address[0]) { + getdata(b_lines - 2, 0, "½Ð¿é¤J¶l¥ó¦a§}¡G", fname, 60, DOECHO); + if(fname[0] && strchr(fname, '.')) { + strcpy(address, fname); + } else { + outmsg("¨ú®ø³B²z"); + return 1; + } + } + if(invalidaddr(address)) + return -2; + + // sprintf(fname, "%d\n", cmode); + getdata(b_lines - 1, 0, "¨Ï¥Î¼Ò¦¡(0/1)? [1]", fname, 3, LCECHO); + cmode = (fname[0] != '0' && fname[0] != '1') ? 1 : fname[0] - '0'; + + now = time(NULL); + sprintf(fname, BBSHOME "/jobspool/water.src.%s-%d", + cuser.userid, now); + sprintf(genbuf, "cp " BBSHOME "/home/%c/%s/%s %s", + cuser.userid[0], cuser.userid, fhdr->filename, fname); + system(genbuf); + /* dirty code ;x */ + sprintf(fname, BBSHOME "/jobspool/water.des.%s-%d", + cuser.userid, now); + fp = fopen(fname, "wt"); + fprintf(fp, "%s\n%s\n%d\n", cuser.userid, address, cmode); + fclose(fp); + return FULLUPDATE; +} +#endif +static struct onekey_t mail_comms[] = { + {'z', mail_man}, + {'c', mail_cite}, + {'s', mail_save}, + {'d', mail_del}, + {'D', del_range}, + {'r', mail_read}, + {'R', mail_reply}, + {'E', mail_edit}, + {'m', mail_mark}, + {'O', mail_nooutmail}, + {'T', edit_title}, + {'x', m_forward}, + {'X', mail_cross_post}, + {Ctrl('G'), built_mail_index}, /* ׫H½c */ + {'y', multi_reply}, + {Ctrl('I'), m_idle}, + {'h', m_help}, +#ifdef OUTJOBSPOOL + {'u', mail_waterball}, +#endif + {'\0', NULL} +}; + +int m_read() { + if(get_num_records(currmaildir, sizeof(fileheader_t))) { + curredit = EDIT_MAIL; + curredit &= ~EDIT_ITEM; + i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms, -1); + curredit = 0; + currutmp->mailalert = load_mailalert(cuser.userid); + return 0; + } else { + outs("±z¨S¦³¨Ó«H"); + return XEASY; + } +} + +/* ±H¯¸¤º«H */ +static int send_inner_mail(char *fpath, char *title, char *receiver) { + char genbuf[256]; + fileheader_t mymail; + + if(!searchuser(receiver)) + return -2; + sethomepath(genbuf, receiver); + stampfile(genbuf, &mymail); + if(!strcmp(receiver, cuser.userid)) { + strcpy(mymail.owner, "[" BBSNAME "]"); + mymail.filemode = FILE_READ; + } else + strcpy(mymail.owner, cuser.userid); + strncpy(mymail.title, title, TTLEN); + unlink(genbuf); + Link(fpath, genbuf); + sethomedir(genbuf, receiver); + return do_append(genbuf, &mymail, sizeof(mymail)); +} + +#include <netdb.h> +#include <pwd.h> +#include <time.h> + +#ifndef USE_BSMTP +static int bbs_sendmail(char *fpath, char *title, char *receiver) { + static int configured = 0; + static char myhostname[STRLEN]; + static char myusername[20]; + struct hostent *hbuf; + struct passwd *pbuf; + char *ptr; + char genbuf[256]; + FILE *fin, *fout; + + /* ¤¤³~ÄdºI */ + if((ptr = strchr(receiver, ';'))) { + struct tm *ptime; + time_t now; + + *ptr = '\0'; + } + + if((ptr = strstr(receiver, str_mail_address)) || !strchr(receiver,'@')) { + char hacker[20]; + int len; + + if(strchr(receiver,'@')) { + len = ptr - receiver; + memcpy(hacker, receiver, len); + hacker[len] = '\0'; + } else + strcpy(hacker,receiver); + return send_inner_mail(fpath, title, hacker); + } + + /* setup the hostname and username */ + if(!configured) { + /* get host name */ + hbuf = gethostbyname("localhost"); + if(hbuf) + strncpy(myhostname, hbuf->h_name, STRLEN); + + /* get bbs uident */ + pbuf = getpwuid(getuid()); + if(pbuf) + strncpy(myusername, pbuf->pw_name, 20); + if(hbuf && pbuf) + configured = 1; + else + return -1; + } + + /* Running the sendmail */ + if(fpath == NULL) { + sprintf(genbuf, "/usr/sbin/sendmail %s > /dev/null", receiver); + fin = fopen("etc/confirm", "r"); + } else { + sprintf(genbuf, "/usr/sbin/sendmail -f %s%s %s > /dev/null", + cuser.userid, str_mail_address, receiver); + fin = fopen(fpath, "r"); + } + fout = popen(genbuf, "w"); + if(fin == NULL || fout == NULL) + return -1; + + if(fpath) + fprintf(fout, "Reply-To: %s%s\nFrom: %s%s\n", + cuser.userid, str_mail_address, cuser.userid, + str_mail_address); + fprintf(fout, "To: %s\nSubject: %s\n", receiver, title); + fprintf(fout, "X-Disclaimer: " BBSNAME "¹ï¥»«H¤º®e®¤¤£t³d¡C\n\n"); + + while(fgets(genbuf, 255, fin)) { + if(genbuf[0] == '.' && genbuf[1] == '\n') + fputs(". \n", fout); + else + fputs(genbuf, fout); + } + fclose(fin); + fprintf(fout, ".\n"); + pclose(fout); + return 0; +} +#else /* USE_BSMTP */ + +int bsmtp(char *fpath, char *title, char *rcpt, int method) { + char buf[80], *ptr; + time_t chrono; + MailQueue mqueue; + + /* check if the mail is a inner mail */ + if((ptr = strstr(rcpt, str_mail_address)) || !strchr(rcpt, '@')) { + char hacker[20]; + int len; + + if(strchr(rcpt,'@')) { + len = ptr - rcpt; + memcpy(hacker, rcpt, len); + hacker[len] = '\0'; + } else + strcpy(hacker, rcpt); + return send_inner_mail(fpath, title, hacker); + } + + chrono = time(NULL); + if(method != MQ_JUSTIFY) { /* »{ÃÒ«H */ + /* stamp the queue file */ + strcpy(buf, "out/"); + for(;;) { + sprintf(buf + 4,"M.%ld.A", ++chrono); + if(!dashf(buf)) { + Link(fpath, buf); + break; + } + } + + fpath = buf; + + strcpy(mqueue.filepath, fpath); + strcpy(mqueue.subject, title); + } + /* setup mail queue */ + mqueue.mailtime = chrono; + mqueue.method = method; + strcpy(mqueue.sender, cuser.userid); + strcpy(mqueue.username, cuser.username); + strcpy(mqueue.rcpt, rcpt); + if(do_append("out/.DIR", (fileheader_t *)&mqueue, sizeof(mqueue)) < 0) + return 0; + return chrono; +} +#endif /* USE_BSMTP */ + +int doforward(char *direct, fileheader_t *fh, int mode) { + static char address[60]; + char fname[500]; + int return_no; + char genbuf[200]; + + if(!address[0]) + strcpy(address, cuser.email); + + if(address[0]) { + sprintf(genbuf, "½T©wÂà±Hµ¹ [%s] ¶Ü(Y/N/Q)¡H[Y] ", address); + getdata(b_lines - 1, 0, genbuf, fname, 3, LCECHO); + + if(fname[0] == 'q') { + outmsg("¨ú®øÂà±H"); + return 1; + } + if(fname[0] == 'n') + address[0] = '\0'; + } + + if(!address[0]) { + do{ + getdata(b_lines - 1, 0, "½Ð¿é¤JÂà±H¦a§}¡G", fname, 60, DOECHO); + if(fname[0]) { + if(strchr(fname, '.')) + strcpy(address, fname); + else + sprintf(address, "%s.bbs@%s", fname, MYHOSTNAME); + } else { + outmsg("¨ú®øÂà±H"); + return 1; + } + }while(mode=='Z' && strstr(address, MYHOSTNAME)); + } + if(invalidaddr(address)) + return -2; + + sprintf(fname, "¥¿Âà±Hµ¹ %s, ½ÐµyÔ...", address); + outmsg(fname); + move(b_lines - 1, 0); + refresh(); + + /* °lÂÜ¨Ï¥ÎªÌ */ + if(HAS_PERM(PERM_LOGUSER)) { + time_t now = time(NULL); + char msg[200]; + + sprintf(msg, "%s mailforward to %s at %s", + cuser.userid, address, Cdate(&now)); + log_user(msg); + } + + if(mode == 'Z') { + sprintf(fname, TAR_PATH " cfz - home/%c/%s | " + "/usr/bin/uuencode %s.tgz > %s", + cuser.userid[0], cuser.userid, cuser.userid, direct); + system(fname); + strcpy(fname, direct); + } else if(mode == 'U') { + char tmp_buf[128]; + + sprintf(fname, "/tmp/bbs.uu%05d", currpid); + sprintf(tmp_buf, "/usr/bin/uuencode %s/%s uu.%05d > %s", + direct, fh->filename, currpid, fname); + system(tmp_buf); + } else if (mode == 'F'){ + char tmp_buf[128]; + + sprintf(fname, "/tmp/bbs.f%05d", currpid); + sprintf(tmp_buf, "cp %s/%s %s",direct,fh->filename,fname); + system(tmp_buf); + } else + return -1; + + return_no = +#ifndef USE_BSMTP + bbs_sendmail(fname, fh->title, address); +#else + bsmtp(fname, fh->title, address,mode); +#endif + unlink(fname); + return (return_no); +} + +int load_mailalert(char *userid) { + struct stat st; + char maildir[256]; + int fd; + register int numfiles; + fileheader_t my_mail; + + sethomedir(maildir, userid); + if(!HAS_PERM(PERM_BASIC)) + return 0; + if(stat(maildir, &st) < 0) + return 0; + numfiles = st.st_size / sizeof(fileheader_t); + if(numfiles <= 0) + return 0; + + /* ¬Ý¬Ý¦³¨S¦³«H¥óÁÙ¨SŪ¹L¡H±qÀɧÀ¦^ÀYÀˬd¡A®Ä²v¸û°ª */ + if((fd = open(maildir, O_RDONLY)) > 0) { + lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET); + while(numfiles--) { + read(fd, &my_mail, sizeof(fileheader_t)); + if(!(my_mail.filemode & FILE_READ)) { + close(fd); + return 1; + } + lseek(fd, -(off_t)2 * sizeof(fileheader_t), SEEK_CUR); + } + close(fd); + } + return 0; +} + +#ifdef EMAIL_JUSTIFY +static void mail_justify(userec_t muser) { + fileheader_t mhdr; + char title[128], buf1[80]; + FILE* fp; + + sethomepath(buf1, muser.userid); + stampfile(buf1, &mhdr); + unlink(buf1); + strcpy(mhdr.owner, cuser.userid); + strncpy(mhdr.title, "[¼f®Ö³q¹L]", TTLEN); + mhdr.savemode = 0; + mhdr.filemode = 0; + + if(valid_ident(muser.email) && !invalidaddr(muser.email)) { + char title[80], *ptr; + unsigned short checksum; /* 16-bit is enough */ + char ch; + + checksum = searchuser(muser.userid); + ptr = muser.email; + while((ch = *ptr++)) { + if(ch <= ' ') + break; + if(ch >= 'A' && ch <= 'Z') + ch |= 0x20; + checksum = (checksum << 1) ^ ch; + } + + sprintf(title, "[PTT BBS]To %s(%d:%d) [User Justify]", + muser.userid, getuser(muser.userid) + MAGIC_KEY, checksum); + if( +#ifndef USE_BSMTP + bbs_sendmail(NULL, title, muser.email) +#else + bsmtp(NULL, title, muser.email, MQ_JUSTIFY); +#endif + < 0) + Link("etc/bademail", buf1); + else + Link("etc/replyemail", buf1); + } else + Link("etc/bademail", buf1); + sethomedir(title, muser.userid); + append_record(title, &mhdr, sizeof(mhdr)); +} +#endif /* EMAIL_JUSTIFY */ diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c new file mode 100644 index 00000000..c4849da5 --- /dev/null +++ b/mbbsd/mbbsd.c @@ -0,0 +1,1465 @@ +/* $Id: mbbsd.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <setjmp.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <syslog.h> +#include <errno.h> +#include <netdb.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/telnet.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" +#ifdef FreeBSD + #include <machine/limits.h> +#else + #include <limits.h> +#endif + +#define SOCKET_QLEN 4 +#define TH_LOW 100 +#define TH_HIGH 120 + +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern userinfo_t *currutmp; +extern int curr_idle_timeout; + +static void do_aloha (char *hello); + +static jmp_buf byebye; + +int talkrequest = NA; + +static char remoteusername[40] = "?"; + +extern struct fromcache_t *fcache; +extern struct utmpfile_t *utmpshm; +extern int fcache_semid; + +static unsigned char enter_uflag; +static int use_shell_login_mode = 0; + +char fromhost[STRLEN] = "\0"; + +static struct sockaddr_in xsin; + +/* set signal handler, which won't be reset once signal comes */ +static void +signal_restart (int signum, void (*handler) (int)) +{ + struct sigaction act; + act.sa_handler = handler; + memset (&(act.sa_mask), 0, sizeof (sigset_t)); + act.sa_flags = 0; + sigaction (signum, &act, NULL); +} + +static void +start_daemon () +{ + int n; + char buf[80]; + + /* + * More idiot speed-hacking --- the first time conversion makes the C + * library open the files containing the locale definition and time zone. + * If this hasn't happened in the parent process, it happens in the + * children, once per connection --- and it does add up. + */ + time_t dummy = time (NULL); + struct tm *dummy_time = localtime (&dummy); + + strftime (buf, 80, "%d/%b/%Y:%H:%M:%S", dummy_time); + + if ((n = fork ())){ + exit (0); + } + + /* rocker.011018: it's a good idea to close all unexcept fd!! */ + n = getdtablesize (); + while (n) + close (--n); + /* rocker.011018: we don't need to remember original tty, + so request a new session id */ + setsid (); + + /* rocker.011018: after new session, + we should insure the process is clean daemon */ + if ((n = fork ())){ + exit (0); + } +} + +static void +reapchild (int sig) +{ + int state, pid; + + while ((pid = waitpid (-1, &state, WNOHANG | WUNTRACED)) > 0) + ; +} + +#define BANNER \ +"¡i" BBSNAME "¡j¡· ¥x¤j¬y¦æºô ¡·(" MYHOSTNAME ") ½Õ´T(" MYIP ") " +/* +#define BANNER \ +"¡i" BBSNAME "¡j¡· ¥x¤j¬y¦æºô ¡·(" MYHOSTNAME ")\r\n"\ +" ½Õ´T(" MYIP ") " +*/ +/* check load and print approriate banner string in buf */ +static int +chkload (char *buf) +{ + char cpu_load[30]; + int i; + + i = cpuload (cpu_load); + + sprintf (buf, BANNER" ¨t²Ît²ü\r\n %s %s \r\n", cpu_load, + (i > MAX_CPULOAD ? "¡A°ªt²ü¶q¡A½Ðµy«á¦A¨Ó " + "(½Ð§Q¥Îport 3000~3010³s½u)" : "")); +#ifdef INSCREEN + strcpy(buf, (i > MAX_CPULOAD ? BANNER + "°ªt²ü¶q¡A½Ðµy«á¦A¨Ó(½Ð§Q¥Îport 3000~3010³s½u)" : "")); +#else + sprintf(buf, BANNER "%s\r\n", + (i > MAX_CPULOAD ? "°ªt²ü¶q¡A½Ðµy«á¦A¨Ó(½Ð§Q¥Îport 3000~3010³s½u)":"")); +#endif + if (i > MAX_CPULOAD) + return 1; + else if (i > MAX_CPULOAD / 2) + curr_idle_timeout = 10 * 60; + else + curr_idle_timeout = 30 * 60; + + return 0; +} + +extern userec_t cuser; + +void +log_user (char *msg) +{ + char filename[200]; + + sprintf (filename, BBSHOME "/home/%c/%s/USERLOG", + cuser.userid[0], cuser.userid); + log_file (filename, msg); +} + +extern time_t login_start_time; + +void +log_usies (char *mode, char *mesg) +{ + char genbuf[200]; + time_t now = time (0); + + if (!mesg) + sprintf (genbuf, cuser.userid[0] ? "%s %s %-12s Stay:%d (%s)" : + "%s %s %s Stay:%d (%s)", + Cdate (&now), mode, cuser.userid, + (int)(now - login_start_time) / 60, cuser.username); + else + sprintf (genbuf, cuser.userid[0] ? "%s %s %-12s %s" : "%s %s %s%s", + Cdate (&now), mode, cuser.userid, mesg); + log_file (FN_USIES, genbuf); + + /* °lÂÜ¨Ï¥ÎªÌ */ + if (HAS_PERM (PERM_LOGUSER)) + log_user (genbuf); +} + +static void +setflags (int mask, int value) +{ + if (value) + cuser.uflag |= mask; + else + cuser.uflag &= ~mask; +} + +extern int usernum; +extern int currmode; + +void +u_exit (char *mode) +{ + //userec_t xuser; + int diff = (time (0) - login_start_time) / 60; + + reload_money(); + auto_backup (); + save_brdbuf(); + setflags (PAGER_FLAG, currutmp->pager != 1); + setflags (CLOAK_FLAG, currutmp->invisible); + + cuser.invisible = currutmp->invisible; + cuser.pager = currutmp->pager; + cuser.mind = currutmp->mind; + if (!(HAS_PERM (PERM_SYSOP) && HAS_PERM (PERM_DENYPOST)) && + !currutmp->invisible ) + do_aloha ("<<¤U¯¸³qª¾>> -- §Ú¨«Åo¡I"); + + purge_utmp (currutmp); + if ((cuser.uflag != enter_uflag) || (currmode & MODE_DIRTY) || diff) + { + if (!diff && cuser.numlogins) + cuser.numlogins = --cuser.numlogins; + /* Leeym ¤W¯¸°±¯d®É¶¡¨î¦¡ */ + } + passwd_update (usernum, &cuser); + log_usies (mode, NULL); +} + +static void +system_abort () +{ + if (currmode) + u_exit ("ABORT"); + + clear (); + refresh (); + fprintf (stdout, "ÁÂÁÂ¥úÁ{, °O±o±`¨Ó³á !\n"); + exit (0); +} + +void +abort_bbs (int sig) +{ + if (currmode) + u_exit ("AXXED"); + exit (0); +} + +static void +abort_bbs_debug (int sig) +{ + static int reentrant = 0; + + if (!reentrant){ + reentrant = 1; + if (currmode) + u_exit ("AXXED"); + setproctitle("debug me!(%d)",sig); + sleep(3600); /* wait 60 mins for debug */ + } + exit (0); +} + +/* µn¿ý BBS µ{¦¡ */ +static void +mysrand () +{ + srand (time (NULL) + currutmp->pid); /* ®É¶¡¸ò pid ·í rand ªº seed */ +} + +extern userec_t xuser; + +int +dosearchuser (char *userid) +{ + if ((usernum = getuser (userid))) + memcpy (&cuser, &xuser, sizeof (cuser)); + else + memset (&cuser, 0, sizeof (cuser)); + return usernum; +} + +static void +talk_request () +{ + bell (); + bell (); + if (currutmp->msgcount){ + char buf[200]; + time_t now = time (0); + + sprintf (buf, "\033[33;41m¡¹%s\033[34;47m [%s] %s \033[0m", + utmpshm->uinfo[currutmp->destuip].userid, my_ctime (&now), + (currutmp->sig == 2)? "«n®ø®§¼s¼½¡I(½ÐCtrl-U,l¬d¬Ý¼ö°T°O¿ý)" + : "©I¥s¡B©I¥s¡AÅ¥¨ì½Ð¦^µª"); + move (0, 0); + clrtoeol (); + outs (buf); + refresh (); + } + else{ + unsigned char mode0 = currutmp->mode; + char c0 = currutmp->chatid[0]; + screenline_t *screen0 = calloc (t_lines, sizeof (screenline_t)); + extern screenline_t *big_picture; + + currutmp->mode = 0; + currutmp->chatid[0] = 1; + memcpy (screen0, big_picture, t_lines * sizeof (screenline_t)); + talkreply (); + currutmp->mode = mode0; + currutmp->chatid[0] = c0; + memcpy (big_picture, screen0, t_lines * sizeof (screenline_t)); + free (screen0); + redoscr (); + } +} + +extern char *fn_writelog; +FILE *fp_writelog = NULL; + +void +show_last_call_in (int save) +{ + char buf[200]; + sprintf (buf, "\033[1;33;46m¡¹%s\033[37;45m %s \033[m", + currutmp->msgs[0].userid, currutmp->msgs[0].last_call_in); + move (b_lines, 0); + clrtoeol (); + refresh (); + outmsg (buf); + + if (save){ + char genbuf[200]; + time_t now; + if (!fp_writelog){ + sethomefile (genbuf, cuser.userid, fn_writelog); + fp_writelog = fopen (genbuf, "a"); + } + if (fp_writelog){ + time (&now); + fprintf (fp_writelog, "%s \033[0m[%s]\n", buf, Cdatelite (&now)); + } + } +} + +extern unsigned int currstat; +water_t water[6], *swater[6], *water_which=&water[0]; +char water_usies=0; +extern int watermode; +static int add_history_water(water_t *w, msgque_t *msg) +{ + memcpy(&w->msg[w->top], msg, sizeof(msgque_t)); + w->top++; + w->top %= WATERMODE(WATER_OFO) ? 5 : MAX_REVIEW; + + if (w->count < MAX_REVIEW) + w->count++; + + return w->count; +} + +static int +add_history(msgque_t *msg) +{ + int i,j; + water_t *tmp; + add_history_water(&water[0], msg); + for(i = 0 ; i < 5 && swater[i] ; i++ ) + if( swater[i]->pid == msg->pid ) + break; + if( i != 5 ){ + if( !swater[i] ){ + water_usies = i + 1; + swater[i] = &water[i + 1]; + strcpy(swater[i]->userid, msg->userid); + swater[i]->pid = msg->pid; + } + tmp = swater[i]; + } + else{ + tmp = swater[4]; + memset(swater[4], 0, sizeof (water_t)); + strcpy(swater[4]->userid, msg->userid); + swater[4]->pid = msg->pid; + i = 4; + } + + for( j = i ; j > 0 ; j-- ) + swater[j] = swater[j - 1]; + swater[0] = tmp; + add_history_water(swater[0], msg); + + if(WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + if( watermode > 0 && + (water_which == swater[0] || water_which == &water[0]) ){ + if (watermode < water_which->count) + watermode++; + t_display_new(); + } + } + return i; +} + +static void +write_request (int sig) +{ + struct tm *ptime; + time_t now; + + time (&now); + ptime = localtime (&now); + + if (currutmp->pager != 0 && + cuser.userlevel != 0 && + currutmp->msgcount != 0 && + currutmp->mode != TALK && + currutmp->mode != EDITING && + currutmp->mode != CHATING && + currutmp->mode != PAGE && + currutmp->mode != IDLE && + currutmp->mode != MAILALL && currutmp->mode != MONITOR) + { + int i; + char c0 = currutmp->chatid[0]; + int currstat0 = currstat; + unsigned char mode0 = currutmp->mode; + + currutmp->mode = 0; + currutmp->chatid[0] = 2; + currstat = XMODE; + + do + { + bell (); + show_last_call_in (1); + igetch (); + currutmp->msgcount--; + if (currutmp->msgcount >= MAX_MSGS) + { + /* this causes chaos... jochang */ + raise (SIGFPE); + } + + add_history(&currutmp->msgs[0]); + for (i = 0; i < currutmp->msgcount; i++) + currutmp->msgs[i] = currutmp->msgs[i + 1]; + } + while (currutmp->msgcount); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + } + else + { + bell (); + show_last_call_in (1); + add_history(&currutmp->msgs[0]); + + refresh (); + currutmp->msgcount = 0; + } +} + +#if 0 +static void +write_request (int sig) +{ + int i, mtimemin, wu; + static char inlock = 0; + if( inlock ) /* ¦pªG¤w¸g¶i¨Ó¤F (ªí¥Ü¤WÓ¤ô²yÁÙ¨S¦³³B²z§¹, + ·sªº¤ô²y¤S¶i¨Ó) «h¤£°µ¥ô¦ó¨Æª½±µ return */ + return; + inlock = 1; + do{ + for( wu = 0 ; wu < 5 ; ++wu ) + if( water[wu].pid == currutmp->msgs[0].pid ) + break; + if( wu == 5 ){ + for( i = 0, mtimemin = INT_MAX ; i < 5 ; ++i ) + if( water[i].pid == 0 ){ + ++water_usies; + wu = i; + break; + } + else if( water[i].mtime < mtimemin ){ + mtimemin = water[i].mtime; + wu = i; + } + water[wu].pid = currutmp->msgs[0].pid; + strcpy(water[wu].userid, currutmp->msgs[0].userid); + water[wu].msgtop = 0; + for( i = 0 ; i < 5 ; ++i ) + water[wu].msg[i][0] = 0; + } + water[wu].mtime = time(NULL); + strncpy(water[wu].msg[ (int)water[wu].msgtop ], + currutmp->msgs[0].last_call_in, 64); + ++water[wu].msgtop; + water[wu].msgtop %= 5; + + bell (); + show_last_call_in (1); + refresh(); + + if( watermode == 0 ){ /* in waterball selection mode + if( wu != 0 ){ + water_scr(water_which, 0); + qsort(water, 5, sizeof(water_t), cmpwatermtime); + for( i = 0 ; i < 5 ; ++i ) + if( water[i].pid == 0 ) + break; + else + water_scr(i, 0); + water_scr(water_which = 0, 1); + refresh(); + } */ + } + --currutmp->msgcount; + for( i = 0 ; i < currutmp->msgcount - 1 ; ++i ) + currutmp->msgs[i] = currutmp->msgs[i + 1]; + } while( currutmp->msgcount > 0 ); + inlock = 0; +} +#endif + +static void +multi_user_check () +{ + register userinfo_t *ui; + register pid_t pid; + char genbuf[3]; + + if (HAS_PERM (PERM_SYSOP)) + return; /* don't check sysops */ + + if (cuser.userlevel){ + if (!(ui = (userinfo_t *) search_ulist (usernum))) + return; /* user isn't logged in */ + + pid = ui->pid; + if (!pid /*|| (kill(pid, 0) == -1) */ ) + return; /* stale entry in utmp file */ + + getdata (b_lines - 1, 0, "±z·Q§R°£¨ä¥L«½Æªº login (Y/N)¶Ü¡H[Y] ", + genbuf, 3, LCECHO); + + if (genbuf[0] != 'n'){ + if (pid > 0) + kill (pid, SIGHUP); + log_usies ("KICK ", cuser.username); + } + else{ + if (search_ulistn(usernum, 3)!=NULL) + system_abort (); /* Goodbye(); */ + } + } + else{ + /* allow multiple guest user */ + if (search_ulistn(usernum, 100)!=NULL){ + outs ("\n©êºp¡A¥Ø«e¤w¦³¤Ó¦h guest, ½Ðµy«á¦A¸Õ¡C\n"); + pressanykey (); + oflush (); + exit (1); + } + } +} + +/* bad login */ +static char str_badlogin[] = "logins.bad"; + +static void +logattempt (char *uid, char type) +{ + char fname[40]; + int fd, len; + char genbuf[200]; + + sprintf (genbuf, "%c%-12s[%s] %s@%s\n", type, uid, + Cdate (&login_start_time), remoteusername, fromhost); + len = strlen (genbuf); + if ((fd = open (str_badlogin, O_WRONLY | O_CREAT | O_APPEND, 0644)) > 0){ + write (fd, genbuf, len); + close (fd); + } + if (type == '-'){ + sprintf (genbuf, "[%s] %s\n", Cdate (&login_start_time), fromhost); + len = strlen (genbuf); + sethomefile (fname, uid, str_badlogin); + if ((fd = open (fname, O_WRONLY | O_CREAT | O_APPEND, 0644)) > 0){ + write (fd, genbuf, len); + close (fd); + } + } +} + +extern char *str_new; +extern char *err_uid; + +static void +login_query () +{ + char uid[IDLEN + 1], passbuf[PASSLEN]; + int attempts; + char genbuf[200]; + extern struct utmpfile_t *utmpshm; + resolve_utmp (); + attach_uhash (); + attempts = utmpshm->number; + show_file ("etc/Welcome", 1, -1, NO_RELOAD); + output ("1", 1); + if (attempts >= MAX_ACTIVE){ + outs ("¥Ñ©ó¤H¼Æ¤Ó¦h¡A½Ð±zµy«á¦A¨Ó¡C\n"); + refresh (); + exit (1); + } + + /* hint */ + + attempts = 0; + while (1){ + if (attempts++ >= LOGINATTEMPTS){ + more ("etc/goodbye", NA); + pressanykey (); + exit (1); + } + getdata (20, 0, "½Ð¿é¤J¥N¸¹¡A©Î¥H[guest]°ÑÆ[¡A¥H[new]µù¥U¡G", + uid, IDLEN + 1, DOECHO); + if (strcasecmp (uid, str_new) == 0){ +#ifdef LOGINASNEW + new_register (); + break; +#else + outs ("¥»¨t²Î¥Ø«eµLªk¥H new µù¥U, ½Ð¥Î guest ¶i¤J\n"); + continue; +#endif + } + else if (uid[0] == '\0' || !dosearchuser (uid)){ + outs (err_uid); + } + else if (strcmp (uid, STR_GUEST)){ + getdata (21, 0, MSG_PASSWD, passbuf, PASSLEN, NOECHO); + passbuf[8] = '\0'; + + if (!checkpasswd (cuser.passwd, passbuf) + /* || (HAS_PERM(PERM_SYSOP) && !use_shell_login_mode) */ ){ + logattempt (cuser.userid, '-'); + outs (ERR_PASSWD); + } + else{ + logattempt (cuser.userid, ' '); + if (strcasecmp ("SYSOP", cuser.userid) == 0) + cuser.userlevel = PERM_BASIC | PERM_CHAT | PERM_PAGE | + PERM_POST | PERM_LOGINOK | PERM_MAILLIMIT | + PERM_CLOAK | PERM_SEECLOAK | PERM_XEMPT | + PERM_DENYPOST | PERM_BM | PERM_ACCOUNTS | + PERM_CHATROOM | PERM_BOARD | PERM_SYSOP | PERM_BBSADM; + break; + } + } + else{ /* guest */ + cuser.userlevel = 0; + cuser.uflag = COLOR_FLAG | PAGER_FLAG | BRDSORT_FLAG | MOVIE_FLAG; + break; + } + } + multi_user_check (); + sethomepath (genbuf, cuser.userid); + mkdir (genbuf, 0755); +} + +void +add_distinct (char *fname, char *line) +{ + FILE *fp; + int n = 0; + + if ((fp = fopen (fname, "a+"))){ + char buffer[80]; + char tmpname[100]; + FILE *fptmp; + + strcpy (tmpname, fname); + strcat (tmpname, "_tmp"); + if (!(fptmp = fopen (tmpname, "w"))){ + fclose (fp); + return; + } + rewind (fp); + while (fgets (buffer, 80, fp)){ + char *p = buffer + strlen (buffer) - 1; + + if (p[-1] == '\n' || p[-1] == '\r') + p[-1] = 0; + if (!strcmp (buffer, line)) + break; + sscanf (buffer + strlen (buffer) + 2, "%d", &n); + fprintf (fptmp, "%s%c#%d\n", buffer, 0, n); + } + + if (feof (fp)) + fprintf (fptmp, "%s%c#1\n", line, 0); + else{ + sscanf (buffer + strlen (buffer) + 2, "%d", &n); + fprintf (fptmp, "%s%c#%d\n", buffer, 0, n + 1); + while (fgets (buffer, 80, fp)){ + sscanf (buffer + strlen (buffer) + 2, "%d", &n); + fprintf (fptmp, "%s%c#%d\n", buffer, 0, n); + } + } + fclose (fp); + fclose (fptmp); + unlink (fname); + rename (tmpname, fname); + } +} + +void +del_distinct (char *fname, char *line) +{ + FILE *fp; + int n = 0; + + if ((fp = fopen (fname, "r"))){ + char buffer[80]; + char tmpname[100]; + FILE *fptmp; + + strcpy (tmpname, fname); + strcat (tmpname, "_tmp"); + if (!(fptmp = fopen (tmpname, "w"))){ + fclose (fp); + return; + } + rewind (fp); + while (fgets (buffer, 80, fp)){ + char *p = buffer + strlen (buffer) - 1; + + if (p[-1] == '\n' || p[-1] == '\r') + p[-1] = 0; + if (!strcmp (buffer, line)) + break; + sscanf (buffer + strlen (buffer) + 2, "%d", &n); + fprintf (fptmp, "%s%c#%d\n", buffer, 0, n); + } + + if (!feof (fp)) + while (fgets (buffer, 80, fp)){ + sscanf (buffer + strlen (buffer) + 2, "%d", &n); + fprintf (fptmp, "%s%c#%d\n", buffer, 0, n); + } + fclose (fp); + fclose (fptmp); + unlink (fname); + rename (tmpname, fname); + } +} + +#ifdef WHERE +static int +where (char *from) +{ + register int i = 0, count = 0, j; + + for (j = 0; j < fcache->top; j++){ + char *token = strtok (fcache->domain[j], "&"); + + i = 0; + count = 0; + while (token){ + if (strstr (from, token)) + count++; + token = strtok (NULL, "&"); + i++; + } + if (i == count) + break; + } + if (i != count) + return 0; + return j; +} +#endif + +static void +check_BM () +{ + int i; + boardheader_t *bhdr; + extern boardheader_t *bcache; + extern int numboards; + + cuser.userlevel &= ~PERM_BM; + for (i = 0, bhdr = bcache; i < numboards && !is_BM (bhdr->BM); i++, bhdr++) + ; +} + +extern pid_t currpid; +extern crosspost_t postrecord; + +static void +setup_utmp (int mode) +{ + userinfo_t uinfo; + /* + char buf[80]; + char remotebuf[1024]; + time_t now = time(NULL); + */ + memset (&uinfo, 0, sizeof (uinfo)); + uinfo.pid = currpid = getpid (); + uinfo.uid = usernum; + uinfo.mode = currstat = mode; + uinfo.msgcount = 0; + uinfo.mailalert = load_mailalert (cuser.userid); + if (!(cuser.numlogins % 20) && cuser.userlevel & PERM_BM) + check_BM (); /* Ptt ¦Û°Ê¨ú¤UÂ÷¾ªO¥DÅv¤O */ + + uinfo.userlevel = cuser.userlevel; + uinfo.sex = cuser.sex % 8; + uinfo.lastact = time (NULL); + + postrecord.times = 0; /* pºâcrosspost¼Æ */ + + strcpy (uinfo.userid, cuser.userid); + strcpy (uinfo.realname, cuser.realname); + strcpy (uinfo.username, cuser.username); + strncpy (uinfo.from, fromhost, 23); + + uinfo.five_win = cuser.five_win; + uinfo.five_lose = cuser.five_lose; + uinfo.five_tie = cuser.five_tie; + + uinfo.invisible = cuser.invisible % 2; + uinfo.pager = cuser.pager%5; + uinfo.mind = cuser.mind; + uinfo.brc_id = 0; +#ifdef WHERE + uinfo.from_alias = where (fromhost); +#else + uinfo.from_alias = 0; +#endif +#ifndef FAST_LOGIN + setuserfile (buf, "remoteuser"); + + strcpy (remotebuf, fromhost); + strcat (remotebuf, ctime (&now)); + remotebuf[strlen (remotebuf) - 1] = 0; + add_distinct (buf, remotebuf); +#endif + if (enter_uflag & CLOAK_FLAG) + uinfo.invisible = YEA; + getnewutmpent (&uinfo); +#ifndef _BBS_UTIL_C_ + friend_load (); +#endif +} + +extern char margs[]; +extern char *str_sysop; +extern char *loginview_file[NUMVIEWFILE][2]; + +static void +user_login () +{ + char ans[4], i; + char genbuf[200]; + struct tm *ptime, *tmp; + time_t now; + int a; + /*** Heat:¼s§iµü + char *ADV[] = { + "7/17 @LIVE ¶Ã¼u, ¦óªYÁJ ªº ¤J³õ¨÷n°eµ¹ ptt ªº·R¥ÎªÌ!", + "±ýª¾¸Ô±¡½Ð¬Ý PttAct ªO!!", + }; ***/ + + log_usies ("ENTER", fromhost); + setproctitle ("%s: %s", margs, cuser.userid); + resolve_garbage (); + resolve_fcache (); + resolve_boards (); + memset( &water[0],0,sizeof(water_t) * 6); + strcpy(water[0].userid, " ¥þ³¡ "); + /* ªì©l¤Æ uinfo¡Bflag¡Bmode */ + setup_utmp (LOGIN); + mysrand (); /* ªì©l¤Æ: random number ¼W¥[user¸ò®É¶¡ªº®t²§ */ + currmode = MODE_STARTED; + enter_uflag = cuser.uflag; + + /* get local time */ + time (&now); + ptime = localtime (&now); + tmp = localtime (&cuser.lastlogin); + if ((a = utmpshm->number) > fcache->max_user){ + fcache->max_user = a; + fcache->max_time = now; + } + init_brdbuf(); + brc_initial (DEFAULT_BOARD); + set_board (); + /* µe±³B²z¶}©l */ + if (!(HAS_PERM (PERM_SYSOP) && HAS_PERM (PERM_DENYPOST)) && !currutmp->invisible ) + do_aloha ("<<¤W¯¸³qª¾>> -- §Ú¨Ó°Õ¡I"); + if (ptime->tm_mday == cuser.day && ptime->tm_mon + 1 == cuser.month){ + more ("etc/Welcome_birth", NA); + currutmp->birth = 1; + } + else{ +#ifdef MULTI_WELCOME_LOGIN + char buf[80]; + int nScreens; + for( nScreens = 0 ; nScreens < 10 ; ++nScreens ){ + sprintf(buf, "etc/Welcome_login.%d", nScreens); + if( access(buf, 0) < 0 ) + break; + } + printf("%d\n", nScreens); + if( nScreens == 0 ){ // multi screen error? + more ("etc/Welcome_login", NA); + } + else{ + sprintf(buf, "etc/Welcome_login.%d", (int)login_start_time % nScreens); + more (buf, NA); + } +#else + more ("etc/Welcome_login", NA); +#endif +// pressanykey(); +// more("etc/CSIE_Week", NA); + currutmp->birth = 0; + } + + if (cuser.userlevel){/* not guest */ + move (t_lines - 4, 0); + prints (" Åwªï±z²Ä \033[1;33m%d\033[0;37m «×«ô³X¥»¯¸¡A" + "¤W¦¸±z¬O±q \033[1;33m%s\033[0;37m ³s©¹¥»¯¸¡A\n" + " §Ú°O±o¨º¤Ñ¬O \033[1;33m%s\033[0;37m¡C\n", + ++cuser.numlogins, cuser.lasthost, Cdate (&cuser.lastlogin)); + pressanykey (); + + if (currutmp->birth && tmp->tm_mday != ptime->tm_mday){ + more ("etc/birth.post", YEA); + brc_initial ("WhoAmI"); + set_board (); + do_post (); + } + setuserfile (genbuf, str_badlogin); + if (more (genbuf, NA) != -1){ + getdata (b_lines - 1, 0, "±zn§R°£¥H¤W¿ù»~¹Á¸Õªº°O¿ý¶Ü(Y/N)?[Y]", + ans, 3, LCECHO); + if (*ans != 'n') + unlink (genbuf); + } + check_register (); + strncpy (cuser.lasthost, fromhost, 16); + cuser.lasthost[15] = '\0'; + restore_backup (); + } + else if (!strcmp (cuser.userid, STR_GUEST)){ + char *nick[13] = { + "·¦¤l", "¨©´ß", "¤º¦ç", "Ä_¯S²~", "½¨®³½", + "¾ð¸", "¯BµÓ", "¾c¤l", "¼ç¤ô¸¥", "Å]¤ý", + "ÅKÅø", "¦Ò¨÷", "¤j¬ü¤k" + }; + char *name[13] = { + "¤j¤ý·¦¤l", "ÆxÄMÁ³", "¤ñ°ò¥§", "¥i¤f¥i¼Ö", "¥õªaªº³½", + "¾Ð", "°ª©£«Î", "AIR Jordon", "¬õ¦â¤Q¤ë¸¹", "§å½ð½ð", + "SASAYA·¦¥¤", "Àn³J", "¥¬¾|§J÷«³½»µ·" + }; + char *addr[13] = { + "¤Ñ°ó¼Ö¶é", "¤j®ü", "ºñ®q¤p©]¦±", "¬ü°ê", "ºñ¦â¬À·äÁG", + "»·¤è", "쥻®ü", "NIKE", "ĬÁp", "¨k¤K618«Ç", + "·R¤§¨ý", "¤Ñ¤W", "ÂŦâ¬À·äÁG" + }; + i = login_start_time % 13; + sprintf (cuser.username, "®üÃäº}¨Óªº%s", nick[(int) i]); + sprintf (currutmp->username, cuser.username); + sprintf (cuser.realname, name[(int) i]); + sprintf (currutmp->realname, cuser.realname); + sprintf (cuser.address, addr[(int) i]); + cuser.sex = i % 8; + currutmp->pager = 2; + pressanykey (); + } + else + pressanykey (); + + if (!PERM_HIDE (currutmp)) + cuser.lastlogin = login_start_time; + + passwd_update (usernum, &cuser); + + for (i = 0; i < NUMVIEWFILE; i++) + if ((cuser.loginview >> i) & 1) + more (loginview_file[(int) i][0], YEA); + + +} + +static void +do_aloha (char *hello) +{ + FILE *fp; + char userid[80]; + char genbuf[200]; + + setuserfile (genbuf, "aloha"); + if ((fp = fopen (genbuf, "r"))){ + sprintf (genbuf, hello); + while (fgets (userid, 80, fp)){ + userinfo_t *uentp; + int tuid; + + if ((tuid = searchuser (userid)) && tuid != usernum && + (uentp = (userinfo_t *) search_ulist (tuid)) && + isvisible(uentp, currutmp)){ + my_write (uentp->pid, genbuf, uentp->userid, 2); + } + } + fclose (fp); + } +} + +static void +do_term_init () +{ + term_init (); + initscr (); +} + +extern char *fn_register; +extern int showansi; + +static void +start_client () +{ + extern struct commands_t cmdlist[]; +#if FORCE_PROCESS_REGISTER_FORM + int nreg; +#endif + + /* system init */ + nice (2); /* Ptt: lower priority */ + login_start_time = time (0); + currmode = 0; + + signal (SIGHUP, abort_bbs); + signal (SIGTERM, abort_bbs); + signal (SIGPIPE, abort_bbs); + + signal (SIGINT, abort_bbs_debug); + signal (SIGQUIT, abort_bbs_debug); + signal (SIGILL, abort_bbs_debug); + signal (SIGABRT, abort_bbs_debug); + signal (SIGFPE, abort_bbs_debug); + signal (SIGBUS, abort_bbs_debug); + signal (SIGSEGV, abort_bbs_debug); + + signal_restart (SIGUSR1, talk_request); + signal_restart (SIGUSR2, write_request); + + dup2 (0, 1); + + do_term_init (); + signal (SIGALRM, abort_bbs); + alarm (600); + login_query (); /* Ptt ¥[¤Wlogin time out */ + user_login (); + m_init (); + +#if FORCE_PROCESS_REGISTER_FORM + if (HAS_PERM (PERM_SYSOP) && (nreg = dashs (fn_register) / 163) > 100){ + char cpu_load[30]; + if (cpuload (cpu_load) > MAX_CPULOAD * 2 / 3) + /* DickG: ®Ú¾Ú¥Ø«eªº load ¨Ó¨M©wn¼f®Öªº¼Æ¥Ø */ + scan_register_form (fn_register, 1, nreg / 20); + else + scan_register_form (fn_register, 1, nreg / 10); + } +#endif + if (HAVE_PERM (PERM_SYSOP | PERM_BM)) + b_closepolls (); + if (!(cuser.uflag & COLOR_FLAG)) + showansi = 0; +#ifdef DOTIMEOUT + /* init_alarm(); */// cause strange logout with saving post. + signal (SIGALRM, SIG_IGN); +#else + signal (SIGALRM, SIG_IGN); +#endif + if (chkmailbox ()) + m_read (); + + domenu (MMENU, "¥D¥\\¯àªí", (currutmp->mailalert ? 'M' : 'C'), cmdlist); +} + +/* FSA (finite state automata) for telnet protocol */ +static void +telnet_init () +{ + static char svr[] = { + IAC, DO, TELOPT_TTYPE, + IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE, + IAC, WILL, TELOPT_ECHO, + IAC, WILL, TELOPT_SGA + }; + char *cmd; + int n, len, rset; + struct timeval to; + char buf[64]; + for (n = 0, cmd = svr; n < 4; n++){ + len = (n == 1 ? 6 : 3); + write (0, cmd, len); + cmd += len; + to.tv_sec = 3; + to.tv_usec = 0; + rset=1; + if (select (1, (fd_set *) & rset, NULL, NULL, &to) > 0) + recv(0, buf, sizeof (buf),0); + } +} + +/* ¨ú±o remote user name ¥H§P©w¨¥÷ */ +/* + * rfc931() speaks a common subset of the RFC 931, AUTH, TAP, IDENT and RFC + * 1413 protocols. It queries an RFC 931 etc. compatible daemon on a remote + * host to look up the owner of a connection. The information should not be + * used for authentication purposes. This routine intercepts alarm signals. + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + +#define STRN_CPY(d,s,l) { strncpy((d),(s),(l)); (d)[(l)-1] = 0; } +#define RFC931_TIMEOUT 10 +#define RFC931_PORT 113 /* Semi-well-known port */ +#define ANY_PORT 0 /* Any old port will do */ + +/* timeout - handle timeouts */ +static void +timeout (int sig) +{ + longjmp (byebye, sig); +} + +static void +getremotename (struct sockaddr_in *from, char *rhost, char *rname) +{ + + /* get remote host name */ + +#ifdef FAST_LOGIN + strcpy (rhost, (char *) inet_ntoa (from->sin_addr)); +#else + struct sockaddr_in our_sin; + struct sockaddr_in rmt_sin; + unsigned rmt_port, rmt_pt; + unsigned our_port, our_pt; + FILE *fp; + char buffer[512], user[80], *cp; + int s; + static struct hostent *hp; + + + hp = NULL; + if (setjmp (byebye) == 0){ + signal (SIGALRM, timeout); + alarm (3); + hp = gethostbyaddr ((char *) &from->sin_addr, sizeof (struct in_addr), + from->sin_family); + alarm (0); + } + strcpy (rhost, hp ? hp->h_name : (char *) inet_ntoa (from->sin_addr)); + +/* + * Use one unbuffered stdio stream for writing to and for reading from the + * RFC931 etc. server. This is done because of a bug in the SunOS 4.1.x + * stdio library. The bug may live in other stdio implementations, too. + * When we use a single, buffered, bidirectional stdio stream ("r+" or "w+" + * mode) we read our own output. Such behaviour would make sense with + * resources that support random-access operations, but not with sockets. + */ + + s = sizeof (our_sin); + if (getsockname (0, (struct sockaddr *) &our_sin, &s) < 0) + return; + + if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) + return; + + if (!(fp = fdopen (s, "r+"))){ + close (s); + return; + } + /* Set up a timer so we won't get stuck while waiting for the server. */ + if (setjmp (byebye) == 0){ + signal (SIGALRM, timeout); + alarm (RFC931_TIMEOUT); + +/* + * Bind the local and remote ends of the query socket to the same IP + * addresses as the connection under investigation. We go through all + * this trouble because the local or remote system might have more than + * one network address. The RFC931 etc. client sends only port numbers; + * the server takes the IP addresses from the query socket. + */ + our_pt = ntohs (our_sin.sin_port); + our_sin.sin_port = htons (ANY_PORT); + + rmt_sin = *from; + rmt_pt = ntohs (rmt_sin.sin_port); + rmt_sin.sin_port = htons (RFC931_PORT); + + setbuf (fp, (char *) 0); + s = fileno (fp); + + if (bind (s, (struct sockaddr *) &our_sin, sizeof (our_sin)) >= 0 && + connect (s, (struct sockaddr *) &rmt_sin, sizeof (rmt_sin)) >= 0){ +/* + * Send query to server. Neglect the risk that a 13-byte write would + * have to be fragmented by the local system and cause trouble with + * buggy System V stdio libraries. + */ + fprintf (fp, "%u,%u\r\n", rmt_pt, our_pt); + fflush (fp); +/* + * Read response from server. Use fgets()/sscanf() so we can work + * around System V stdio libraries that incorrectly assume EOF when a + * read from a socket returns less than requested. + */ + if (fgets (buffer, sizeof (buffer), fp) && !ferror (fp) + && !feof (fp) + && sscanf (buffer, "%u , %u : USERID :%*[^:]:%79s", &rmt_port, + &our_port, user) == 3 && rmt_pt == rmt_port + && our_pt == our_port){ + +/* + * Strip trailing carriage return. It is part of the protocol, not + * part of the data. + */ + if ((cp = (char *) strchr (user, '\r'))) + *cp = 0; + strcpy (rname, user); + } + } + alarm (0); + } + fclose (fp); +#endif +} + +static int +bind_port (int port) +{ + int sock, on; + + sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + + on = 1; + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)); + setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof (on)); + + on = 0; + setsockopt (sock, SOL_SOCKET, SO_LINGER, (char *) &on, sizeof (on)); + + xsin.sin_port = htons (port); + if (bind (sock, (struct sockaddr *) &xsin, sizeof xsin) < 0){ + syslog (LOG_INFO, "bbsd bind_port can't bind to %d", port); + exit (1); + } + if (listen (sock, SOCKET_QLEN) < 0){ + syslog (LOG_INFO, "bbsd bind_port can't listen to %d", port); + exit (1); + } + return sock; +} + + +/*******************************************************/ + + +static void shell_login (int argc, char *argv[], char *envp[]); +static void daemon_login (int argc, char *argv[], char *envp[]); +static int check_ban_and_load (int fd); +#ifdef SUPPORT_GB +extern int current_font_type; +#endif + +int +main (int argc, char *argv[], char *envp[]) +{ + /* avoid SIGPIPE */ + signal (SIGPIPE, SIG_IGN); + + /* avoid erroneous signal from other mbbsd */ + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + + /* check if invoked as "bbs" */ + if (argc == 3) + shell_login (argc, argv, envp); + else + daemon_login (argc, argv, envp); + + return 0; +} + +static void +shell_login (int argc, char *argv[], char *envp[]) +{ + + /* Give up root privileges: no way back from here */ + setgid (BBSGID); + setuid (BBSUID); + chdir (BBSHOME); + + /* mmap passwd file */ + if (passwd_mmap ()) + exit (1); + + use_shell_login_mode = 1; + initsetproctitle (argc, argv, envp); + + /* copy fromindent: Standard input:1138: Error:Unexpected end of file + the original "bbs" */ + if (argc > 1){ + strcpy (fromhost, argv[1]); + if (argc > 3) + strcpy (remoteusername, argv[3]); + } + + close (2); + /* don't close fd 1, at least init_tty need it */ + + init_tty (); + if (check_ban_and_load (0)){ + exit (0); + } + start_client (); +} + +static void +daemon_login (int argc, char *argv[], char *envp[]) +{ + int msock, csock; /* socket for Master and Child */ + FILE *fp; + int listen_port = 23; + int len_of_sock_addr; + char buf[256]; + + /* setup standalone */ + + start_daemon(); + + signal_restart(SIGCHLD, reapchild); + + /* choose port */ + if(argc == 1) + listen_port = 3006; + else if(argc >= 2) + listen_port = atoi(argv[1]); + + sprintf(margs, "%s %d ", argv[0],listen_port); + + /* port binding */ + xsin.sin_family = AF_INET; + msock = bind_port(listen_port); + if(msock<0) { + syslog(LOG_INFO, "mbbsd bind_port failed.\n"); + exit(1); + } + + + initsetproctitle(argc, argv, envp); + setproctitle("%s: listening ", margs); + + /* Give up root privileges: no way back from here */ + setgid(BBSGID); + setuid(BBSUID); + chdir(BBSHOME); + + /* mmap passwd file */ + if(passwd_mmap()) + { + exit(1); + } + sprintf(buf, "run/mbbsd.%d.pid", listen_port); + if((fp = fopen(buf, "w"))) { + fprintf(fp, "%d\n", getpid()); + fclose(fp); + } + + /* main loop */ + for(;;) { + len_of_sock_addr = sizeof(xsin); + csock = accept(msock, (struct sockaddr *)&xsin, &len_of_sock_addr); + + if(csock < 0) { + if(errno!=EINTR) sleep(1); + continue; + } + + if(check_ban_and_load(csock)) + { + close(csock); + continue; + } + + if(fork()==0) + break; + else + close(csock); + + } + /* here is only child running */ + + setproctitle("%s: ...login wait... ", margs); + close(msock); + dup2(csock, 0); + close(csock); + + getremotename(&xsin, fromhost, remoteusername); + telnet_init(); + start_client(); + close(0); + close(1); +} + +/* check if we're banning login and if the load is too high. + if login is permitted, return 0; + else return -1; + approriate message is output to fd. +*/ +static int check_ban_and_load(int fd) +{ + FILE *fp; + static char buf[256]; + static time_t chkload_time = 0; + static int overload = 0; /* overload or banned, update every 1 sec */ + static int banned = 0; + + if((time(0) - chkload_time) > 1) { + overload = chkload(buf); + banned = !access(BBSHOME "/BAN",R_OK) && + (strcmp(fromhost, "localhost") != 0); + chkload_time = time(0); + } + + write(fd, buf, strlen(buf)); + + if(banned && (fp = fopen(BBSHOME "/BAN", "r"))) { + while(fgets(buf, 256, fp)) + write(fd, buf, strlen(buf)); + fclose(fp); + } + + if(banned || overload) + return -1; + +#ifdef INSCREEN + write(fd, INSCREEN, strlen(INSCREEN)); +#endif + + return 0; +} diff --git a/mbbsd/menu.c b/mbbsd/menu.c new file mode 100644 index 00000000..d48670b3 --- /dev/null +++ b/mbbsd/menu.c @@ -0,0 +1,596 @@ +/* $Id: menu.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" +extern int usernum; +extern int talkrequest; +extern char *fn_register; +extern char currboard[]; /* name of currently selected board */ +extern int currmode; +extern unsigned int currstat; +extern char reset_color[]; +extern userinfo_t *currutmp; +extern char *BBSName; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +/* help & menu processring */ +static int refscreen = NA; +extern char *boardprefix; +extern struct utmpfile_t *utmpshm; + +int egetch() { + int rval; + + while(1) { + rval = igetkey(); + if(talkrequest) { + talkreply(); + refscreen = YEA; + return rval; + } + if(rval != Ctrl('L')) + return rval; + redoscr(); + } +} + +extern userec_t cuser; +extern char *fn_board; +extern char board_hidden_status; + +void showtitle(char *title, char *mid) { + char buf[40], numreg[50]; + int nreg, spc = 0, pad, bid; + boardheader_t bh; + static char lastboard[16] = {0}; + + spc = strlen(mid); + if(title[0] == 0) + title++; + else if(currutmp->mailalert) { + mid = "\033[41;5m ¶l®t¨Ó«ö¹aÅo " TITLE_COLOR; + spc = 22; + } else if(HAS_PERM(PERM_SYSOP) && (nreg = dashs(fn_register)/163) > 10) { + /* ¶W¹L¤QÓ¤H¥¼¼f®Ö */ + sprintf(numreg, "\033[41;5m ¦³%03d/%03d¥¼¼f®Ö " TITLE_COLOR, + nreg, + (int)dashs("register.new.tmp") / 163); + mid = numreg; + spc = 22; + } + spc = 66 - strlen(title) - spc - strlen(currboard); + if(spc < 0) + spc = 0; + pad = 1 - (spc & 1); + memset(buf, ' ', spc >>= 1); + buf[spc] = '\0'; + + clear(); + prints(TITLE_COLOR "¡i%s¡j%s\033[33m%s%s%s\033[3%s¡m", + title, buf, mid, buf, " " + pad, + currmode & MODE_SELECT ? "6m¨t¦C" : currmode & MODE_ETC ? "5m¨ä¥L" : + currmode & MODE_DIGEST ? "2m¤åºK" : "7m¬ÝªO"); + + if( strcmp(currboard, lastboard) ){ /* change board */ + if( currboard[0] != 0 && + (bid = getbnum(currboard)) > 0 && + (get_record(fn_board, &bh, sizeof(bh), bid) != -1) ){ + board_hidden_status = ((bh.brdattr & BRD_HIDE) && + (bh.brdattr & BRD_POSTMASK)); + strncpy(lastboard, currboard, sizeof(lastboard)); + } + } + + if( board_hidden_status ) + prints("\033[32m%s", currboard); + else + prints("%s", currboard); + prints("\033[3%dm¡n\033[0m\n", currmode & MODE_SELECT ? 6 : + currmode & MODE_ETC ? 5 : currmode & MODE_DIGEST ? 2 : 7); +} + +/* °Êµe³B²z */ +#define FILMROW 11 +static unsigned char menu_row = 12; +static unsigned char menu_column = 20; +static char mystatus[160]; + +static int u_movie() { + cuser.uflag ^= MOVIE_FLAG; + return 0; +} + +void movie(int i) { + extern struct pttcache_t *ptt; + static short history[MAX_HISTORY]; + static char myweek[] = "¤Ñ¤@¤G¤T¥|¤¤»"; + const char *msgs[] = {"Ãö³¬", "¥´¶}", "©Þ±¼", "¨¾¤ô","¦n¤Í"}; + time_t now = time(NULL); + struct tm *ptime = localtime(&now); + + if((currstat != CLASS) && (cuser.uflag & MOVIE_FLAG) && + !ptt->busystate && ptt->max_film > 0) { + if(currstat == PSALE) { + i = PSALE; + reload_money(); + } else { + do { + if(!i) + i = 1 + (int)(((float)ptt->max_film * + rand()) / (RAND_MAX + 1.0)); + + for(now = ptt->max_history; now >= 0; now--) + if(i == history[now]) { + i = 0; + break; + } + } while(i == 0); + } + + memcpy(history, &history[1], ptt->max_history * sizeof(short)); + history[ptt->max_history] = now = i; + + if(i == 999) /* Goodbye my friend */ + i = 0; + + move(1, 0); + clrtoline(1 + FILMROW); /* ²M±¼¤W¦¸ªº */ + Jaky_outs(ptt->notes[i], 11); /* ¥u¦L11¦æ´N¦n */ + outs(reset_color); + } + i = ptime->tm_wday << 1; + sprintf(mystatus, "\033[34;46m[%d/%d ¬P´Á%c%c %d:%02d]\033[1;33;45m%-14s" + "\033[30;47m ¥Ø«e§{¸Ì¦³ \033[31m%d\033[30m¤H, §Ú¬O\033[31m%-12s" + "\033[30m[¦©¾÷]\033[31m%s\033[0m", + ptime->tm_mon + 1, ptime->tm_mday, myweek[i], myweek[i + 1], + ptime->tm_hour, ptime->tm_min, currutmp->birth ? + "¥Í¤én½Ð«Èò" : ptt->today_is, + utmpshm->number, cuser.userid, msgs[currutmp->pager]); + outmsg(mystatus); + refresh(); +} + +static int show_menu(commands_t *p) { + register int n = 0; + register char *s; + const char *state[4]={"¥Î¥\\«¬", "¦w¶h«¬", "¦Û©w«¬", "SHUTUP"}; + char buf[80]; + + movie(currstat); + + move(menu_row, 0); + while((s = p[n].desc)) { + if(HAS_PERM(p[n].level)) { + sprintf(buf, s + 2, state[cuser.proverb % 4]); + prints("%*s (\033[1;36m%c\033[0m)%s\n", menu_column, "", s[1], + buf); + } + n++; + } + return n - 1; +} + +void domenu(int cmdmode, char *cmdtitle, int cmd, commands_t cmdtable[]) { + int lastcmdptr; + int n, pos, total, i; + int err; + int chkmailbox(); + static char cmd0[LOGIN]; + + if(cmd0[cmdmode]) + cmd = cmd0[cmdmode]; + + setutmpmode(cmdmode); + + showtitle(cmdtitle, BBSName); + + total = show_menu(cmdtable); + + outmsg(mystatus); + lastcmdptr = pos = 0; + + do { + i = -1; + switch(cmd) { + case Ctrl('C'): + cal(); + i = lastcmdptr; + refscreen = YEA; + break; + case Ctrl('I'): + t_idle(); + refscreen = YEA; + i = lastcmdptr; + break; + case Ctrl('N'): + New(); + refscreen = YEA; + i = lastcmdptr; + break; + case Ctrl('A'): + if(mail_man() == FULLUPDATE) + refscreen = YEA; + i = lastcmdptr; + break; + case KEY_DOWN: + i = lastcmdptr; + case KEY_HOME: + case KEY_PGUP: + do { + if(++i > total) + i = 0; + } while(!HAS_PERM(cmdtable[i].level)); + break; + case KEY_END: + case KEY_PGDN: + i = total; + break; + case KEY_UP: + i = lastcmdptr; + do { + if(--i < 0) + i = total; + } while(!HAS_PERM(cmdtable[i].level)); + break; + case KEY_LEFT: + case 'e': + case 'E': + if(cmdmode == MMENU) + cmd = 'G'; + else if((cmdmode == MAIL) && chkmailbox()) + cmd = 'R'; + else + return; + default: + if((cmd == 's' || cmd == 'r') && + (currstat == MMENU || currstat == TMENU || currstat == XMENU)) { + if(cmd == 's') + ReadSelect(); + else + Read(); + refscreen = YEA; + i = lastcmdptr; + break; + } + + if(cmd == '\n' || cmd == '\r' || cmd == KEY_RIGHT) { + move(b_lines, 0); + clrtoeol(); + + currstat = XMODE; + + if((err = (*cmdtable[lastcmdptr].cmdfunc) ()) == QUIT) + return; + currutmp->mode = currstat = cmdmode; + + if(err == XEASY) { + refresh(); + safe_sleep(1); + } else if(err != XEASY + 1 || err == FULLUPDATE) + refscreen = YEA; + + if(err != -1) + cmd = cmdtable[lastcmdptr].desc[0]; + else + cmd = cmdtable[lastcmdptr].desc[1]; + cmd0[cmdmode] = cmdtable[lastcmdptr].desc[0]; + } + + if(cmd >= 'a' && cmd <= 'z') + cmd &= ~0x20; + while(++i <= total) + if(cmdtable[i].desc[1] == cmd) + break; + } + + if(i > total || !HAS_PERM(cmdtable[i].level)) + continue; + + if(refscreen) { + showtitle(cmdtitle, BBSName); + + show_menu(cmdtable); + + outmsg(mystatus); + refscreen = NA; + } + cursor_clear(menu_row + pos, menu_column); + n = pos = -1; + while(++n <= (lastcmdptr = i)) + if(HAS_PERM(cmdtable[n].level)) + pos++; + + cursor_show(menu_row + pos, menu_column); + } while(((cmd = egetch()) != EOF) || refscreen); + + abort_bbs(0); +} +/* INDENT OFF */ + +/* administrator's maintain menu */ +static commands_t adminlist[] = { + {m_user, PERM_ACCOUNTS, "UUser ¨Ï¥ÎªÌ¸ê®Æ"}, + {search_user_bypwd, PERM_SYSOP, "SSearch User ¯S®í·j´M¨Ï¥ÎªÌ"}, + {search_user_bybakpwd,PERM_SYSOP, "OOld User data ¬d¾\\³Æ¥÷¨Ï¥ÎªÌ¸ê®Æ"}, + {m_board, PERM_SYSOP, "BBoard ³]©w¬ÝªO"}, + {m_register, PERM_SYSOP, "RRegister ¼f®Öµù¥Uªí³æ"}, + {cat_register, PERM_SYSOP, "CCatregister µLªk¼f®Ö®É¥Îªº"}, + {x_file, PERM_SYSOP|PERM_VIEWSYSOP, "XXfile ½s¿è¨t²ÎÀÉ®×"}, + {give_money, PERM_SYSOP|PERM_VIEWSYSOP, "GGivemoney ¬õ¥]Âû"}, +#ifdef HAVE_MAILCLEAN + {m_mclean, PERM_SYSOP, "MMail Clean ²M²z¨Ï¥ÎªÌÓ¤H«H½c"}, +#endif +#ifdef HAVE_REPORT + {m_trace, PERM_SYSOP, "TTrace ³]©w¬O§_°O¿ý°£¿ù¸ê°T"}, +#endif + {NULL, 0, NULL} +}; + +/* mail menu */ +static commands_t maillist[] = { + {m_new, PERM_READMAIL, "RNew ¾\\Ū·s¶i¶l¥ó"}, + {m_read, PERM_READMAIL, "RRead ¦h¥\\¯àŪ«H¿ï³æ"}, + {m_send, PERM_BASIC, "RSend ¯¸¤º±H«H"}, + {main_bbcall, PERM_LOGINOK, "BBBcall \033[1;31m¹q¸Ü¯µ®Ñ\033[m"}, + {x_love, PERM_LOGINOK, "PPaper \033[1;32m±¡®Ñ²£¥Í¾¹\033[m "}, + {mail_list, PERM_BASIC, "RMail List ¸s²Õ±H«H"}, + {setforward, PERM_LOGINOK,"FForward \033[32m³]©w«H½c¦Û°ÊÂà±H\033[m"}, + {m_sysop, 0, "YYes, sir! ½Ô´A¯¸ªø"}, + {m_internet, PERM_INTERNET, "RInternet ±H«H¨ì Internet"}, + {mail_mbox, PERM_INTERNET, "RZip UserHome §â©Ò¦³¨p¤H¸ê®Æ¥´¥]¦^¥h"}, + {built_mail_index, PERM_LOGINOK, "SSavemail §â«H¥ó±Ï¦^¨Ó"}, + {mail_all, PERM_SYSOP, "RAll ±H«Hµ¹©Ò¦³¨Ï¥ÎªÌ"}, + {NULL, 0, NULL} +}; + +/* Talk menu */ +static commands_t talklist[] = { + {t_users, 0, "UUsers §¹¥þ²á¤Ñ¤â¥U"}, + {t_pager, PERM_BASIC, "PPager ¤Á´«©I¥s¾¹"}, + {t_idle, 0, "IIdle µo§b"}, + {t_query, 0, "QQuery ¬d¸ßºô¤Í"}, + {t_qchicken, 0, "WWatch Pet ¬d¸ßÃdª«"}, + {t_talk, PERM_PAGE, "TTalk §ä¤H²á²á"}, + {t_chat, PERM_CHAT, "CChat §ä®a¯ù§{³ð¯ù¥h"}, +#ifdef HAVE_MUD + {x_mud, 0, "VVrChat \033[1;32mµêÀÀ¹ê·~²á¤Ñ¼s³õ\033[m"}, +#endif + {t_display, 0, "DDisplay Åã¥Ü¤W´X¦¸¼ö°T"}, + {NULL, 0, NULL} +}; + +/* name menu */ +static int t_aloha() { + friend_edit(FRIEND_ALOHA); + return 0; +} + +static int t_special() { + friend_edit(FRIEND_SPECIAL); + return 0; +} + +static commands_t namelist[] = { + {t_override, PERM_LOGINOK,"OOverRide ¦n¤Í¦W³æ"}, + {t_reject, PERM_LOGINOK, "BBlack Ãa¤H¦W³æ"}, + {t_aloha,PERM_LOGINOK, "AALOHA ¤W¯¸³qª¾¦W³æ"}, +#ifdef POSTNOTIFY + {t_post,PERM_LOGINOK, "NNewPost ·s¤å³¹³qª¾¦W³æ"}, +#endif + {t_special,PERM_LOGINOK, "SSpecial ¨ä¥L¯S§O¦W³æ"}, + {NULL, 0, NULL} +}; + +/* User menu */ +static commands_t userlist[] = { + {u_info, PERM_LOGINOK, "IInfo ³]©wÓ¤H¸ê®Æ»P±K½X"}, + {calendar, PERM_LOGINOK, "CCalendar Ó¤H¦æ¨Æ¾ä"}, + {u_editcalendar, PERM_LOGINOK, "CCalendarEdit ½s¿èÓ¤H¦æ¨Æ¾ä"}, + {u_loginview, PERM_LOGINOK, "LLogin View ¿ï¾Ü¶i¯¸µe±"}, + {u_ansi, 0, "AANSI ¤Á´« ANSI \033[36m±m\033[35m¦â\033[37m/" + "\033[30;47m¶Â\033[1;37m¥Õ\033[m¼Ò¥Ü"}, + {u_movie, 0, "MMovie ¤Á´«°Êµe¼Ò¥Ü"}, +#ifdef HAVE_SUICIDE + {u_kill, PERM_BASIC, "IKill ¦Û±þ¡I¡I"}, +#endif + {u_editplan, PERM_LOGINOK, "QQueryEdit ½s¿è¦W¤ùÀÉ"}, + {u_editsig, PERM_LOGINOK, "SSignature ½s¿èñ¦WÀÉ"}, +#if HAVE_FREECLOAK + {u_cloak, PERM_LOGINOK, "CCloak Áô¨³N"}, +#else + {u_cloak, PERM_CLOAK, "CCloak Áô¨³N"}, +#endif + {u_register, PERM_BASIC, "RRegister ¶ñ¼g¡mµù¥U¥Ó½Ð³æ¡n"}, + {u_list, PERM_SYSOP, "UUsers ¦C¥Xµù¥U¦W³æ"}, + {NULL, 0, NULL} +}; + +/* XYZ tool menu */ +static commands_t xyzlist[] = { +#ifdef HAVE_LICENSE + {x_gpl, 0, "LLicense GNU ¨Ï¥Î°õ·Ó"}, +#endif +#ifdef HAVE_INFO + {x_program, 0, "PProgram ¥»µ{¦¡¤§ª©¥»»Pª©Åv«Å§i"}, +#endif + {x_boardman,0, "MMan Boards ¡m¬Ýª©ºëµØ°Ï±Æ¦æº]¡n"}, +// {x_boards,0, "HHot Boards ¡m¬Ýª©¤H®ð±Æ¦æº]¡n"}, + {x_history, 0, "HHistory ¡m§Ú̪º¦¨ªø¡n"}, + {x_note, 0, "NNote ¡m»Ä²¢W»¶¬y¨¥ª©¡n"}, + {x_login,0, "SSystem ¡m¨t²Î«n¤½§i¡n"}, + {x_week, 0, "WWeek ¡m¥»¶g¤¤Q¤j¼öªù¸ÜÃD¡n"}, + {x_issue, 0, "IIssue ¡m¤µ¤é¤Q¤j¼öªù¸ÜÃD¡n"}, + {x_today, 0, "TToday ¡m¤µ¤é¤W½u¤H¦¸²Îp¡n"}, + {x_yesterday, 0, "YYesterday ¡m¬Q¤é¤W½u¤H¦¸²Îp¡n"}, + {x_user100 ,0, "UUsers ¡m¨Ï¥ÎªÌ¦Ê¤j±Æ¦æº]¡n"}, + {x_birth, 0, "BBirthday ¡m¤µ¤é¹Ø¬P¤jÆ[¡n"}, + {p_sysinfo, 0, "XXload ¡m¬d¬Ý¨t²Ît²ü¡n"}, + {NULL, 0, NULL} +}; + +/* Ptt money menu */ +static commands_t moneylist[] = { + {p_give, 0, "00Give µ¹¨ä¥L¤H¿ú"}, + {save_violatelaw, 0,"11ViolateLaw ú»@³æ"}, +#if !HAVE_FREECLOAK + {p_cloak, 0, "22Cloak ¤Á´« Áô¨/²{¨ $19 /¦¸"}, +#endif + {p_from, 0, "33From ¼È®Éקï¬G¶m $49 /¦¸"}, + {ordersong,0, "44OSong ¼Ú®á°ÊºAÂIºq¾÷ $200 /¦¸"}, + {p_exmail, 0, "55Exmail ÁʶR«H½c $1000/«Ê"}, + {NULL, 0, NULL} +}; + +static int p_money() { + domenu(PSALE, "¢Þtt¶q³c©±", '0', moneylist); + return 0; +}; + +static commands_t jceelist[] = { + {x_90,PERM_LOGINOK, "0090 JCEE ¡i90¾Ç¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î¡j"}, + {x_89,PERM_LOGINOK, "1189 JCEE ¡i89¾Ç¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î¡j"}, + {x_88,PERM_LOGINOK, "2288 JCEE ¡i88¾Ç¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î¡j"}, + {x_87,PERM_LOGINOK, "3387 JCEE ¡i87¾Ç¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î¡j"}, + {x_86,PERM_LOGINOK, "4486 JCEE ¡i86¾Ç¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î¡j"}, + {NULL, 0, NULL} +}; + +static int m_jcee() { + domenu(JCEE, "¢Þtt¬dº]¨t²Î", '0', jceelist); + return 0; +} + +static int forsearch(); +static int playground(); + +/* Ptt Play menu */ +static commands_t playlist[] = { +#if HAVE_JCEE + {m_jcee, PERM_LOGINOK, "JJCEE ¡i ¤j¾ÇÁp¦Ò¬dº]¨t²Î ¡j"}, +#endif + {note, PERM_LOGINOK, "NNote ¡i ¨è¨è¬y¨¥ª© ¡j"}, + {x_weather,0 , "WWeather ¡i ®ð¶H¹w³ø ¡j"}, + {x_stock,0 , "SStock ¡i ªÑ¥«¦æ±¡ ¡j"}, +#ifdef HAVE_BIG2 + {x_big2, 0, "BBig2 ¡i ºô¸ô¤j¦Ñ¤G ¡j"}, +#endif +#ifdef HAVE_MJ + {x_mj, PERM_LOGINOK, "QQkmj ¡i ºô¸ô¥´³Â±N ¡j"}, +#endif +#ifdef HAVE_BRIDGE + {x_bridge, PERM_LOGINOK, "OOkBridge ¡i ¾ôµPÄv§Þ ¡j"}, +#endif +#ifdef HAVE_GOPHER + {x_gopher, PERM_LOGINOK, "GGopher ¡i ¦a¹«¸ê®Æ®w ¡j"}, +#endif +#ifdef HAVE_TIN + {x_tin, PERM_LOGINOK, "NNEWS ¡i ºô»Ú·s»D ¡j"}, +#endif +#ifdef BBSDOORS + {x_bbsnet, PERM_LOGINOK, "BBBSNet ¡i ¨ä¥L BBS¯¸ ¡j"}, +#endif +#ifdef HAVE_WWW + {x_www, PERM_LOGINOK, "WWWW Browser ¡i ¨L¨L¨L ¡j"}, +#endif + {forsearch,PERM_LOGINOK, "SSearchEngine¡i\033[1;35m ¢Þtt·j´M¾¹ \033[m¡j"}, + {topsong,PERM_LOGINOK, "TTop Songs ¡i\033[1;32m¼Ú®áÂIºq±Æ¦æº]\033[m¡j"}, + {p_money,PERM_LOGINOK, "PPay ¡i\033[1;31m ¢Þtt¶q³c©± \033[m¡j"}, + {chicken_main,PERM_LOGINOK, "CChicken " + "¡i\033[1;34m ¢Þtt¾iÂû³õ \033[m¡j"}, + {playground,PERM_LOGINOK, "AAmusement ¡i\033[1;33m ¢Þtt¹C¼Ö³õ \033[m¡j"}, + {NULL, 0, NULL} +}; + +static commands_t plist[] = { + +/* {p_ticket_main, PERM_LOGINOK,"00Pre ¡i Á`²Î¾÷ ¡j"}, + {alive, PERM_LOGINOK, "00Alive ¡i q²¼Âû ¡j"}, +*/ + {ticket_main, PERM_LOGINOK, "11Gamble ¡i ¢Þtt½ä³õ ¡j"}, + {guess_main, PERM_LOGINOK, "22Guess number¡i ²q¼Æ¦r ¡j"}, + {othello_main, PERM_LOGINOK, "33Othello ¡i ¶Â¥Õ´Ñ ¡j"}, +// {dice_main, PERM_LOGINOK, "44Dice ¡i ª±»ë¤l ¡j"}, + {vice_main, PERM_LOGINOK, "44Vice ¡i µo²¼¹ï¼ú ¡j"}, + {g_card_jack, PERM_LOGINOK, "55Jack ¡i ¶Â³Ç§J ¡j"}, + {g_ten_helf, PERM_LOGINOK, "66Tenhalf ¡i ¤QÂI¥b ¡j"}, + {card_99, PERM_LOGINOK, "77Nine ¡i ¤E¤Q¤E ¡j"}, + {NULL, 0, NULL} +}; + +static int playground() { + domenu(AMUSE, "¢Þtt¹C¼Ö³õ",'1',plist); + return 0; +} + +static commands_t slist[] = { + {x_dict,0, "11Dictionary " + "¡i\033[1;33m ½ì¨ý¤j¦r¨å \033[m¡j"}, + {main_railway, PERM_LOGINOK, "33Railway " + "¡i\033[1;32m ¤õ¨®ªí¬d¸ß \033[m¡j"}, + {NULL, 0, NULL} +}; + +static int forsearch() { + domenu(SREG, "¢Þtt·j´M¾¹", '1', slist); + return 0; +} + +/* main menu */ + +static int admin() { + domenu(ADMIN, "¨t²ÎºûÅ@", 'X', adminlist); + return 0; +} + +static int Mail() { + domenu(MAIL, "¹q¤l¶l¥ó", 'R', maillist); + return 0; +} + +static int Talk() { + domenu(TMENU, "²á¤Ñ»¡¸Ü", 'U', talklist); + return 0; +} + +static int User() { + domenu(UMENU, "Ó¤H³]©w", 'A', userlist); + return 0; +} + +static int Xyz() { + domenu(XMENU, "¤u¨ãµ{¦¡", 'M', xyzlist); + return 0; +} + +static int Play_Play() { + domenu(PMENU, "ºô¸ô¹C¼Ö³õ", 'A', playlist); + return 0; +} + +static int Name_Menu() { + domenu(NMENU, "¥Õ¦â®£©Æ", 'O', namelist); + return 0; +} + +commands_t cmdlist[] = { + {admin,PERM_SYSOP|PERM_VIEWSYSOP, "00Admin ¡i ¨t²ÎºûÅ@°Ï ¡j"}, + {Announce, 0, "AAnnounce ¡i ºëµØ¤½§GÄæ ¡j"}, + {Boards, 0, "FFavorite ¡i §Ú ªº ³Ì·R ¡j"}, + {root_board, 0, "CClass ¡i ¤À²Õ°Q½×°Ï ¡j"}, + {Mail, PERM_BASIC, "MMail ¡i ¨p¤H«H¥ó°Ï ¡j"}, + {Talk, 0, "TTalk ¡i ¥ð¶¢²á¤Ñ°Ï ¡j"}, + {User, 0, "UUser ¡i Ó¤H³]©w°Ï ¡j"}, + {Xyz, 0, "XXyz ¡i ¨t²Î¤u¨ã°Ï ¡j"}, + {Play_Play,0, "PPlay ¡i ¹C¼Ö³õ/¤j¾Ç¬dº]¡j"}, + {Name_Menu,PERM_LOGINOK, "NNamelist ¡i ½s¯S§O¦W³æ ¡j"}, + {Goodbye, 0, "GGoodbye Â÷¶}¡A¦A¨£¡K¡K"}, + {NULL, 0, NULL} +}; diff --git a/mbbsd/more.c b/mbbsd/more.c new file mode 100644 index 00000000..f7755874 --- /dev/null +++ b/mbbsd/more.c @@ -0,0 +1,931 @@ +/* $Id: more.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "perm.h" +#include "proto.h" + +extern int showansi; +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char *str_author1; +extern char *str_author2; +extern char *str_post1; +extern char *str_post2; +extern char *msg_seperator; +extern char reset_color[]; + +#define MORE_BUFSIZE 4096 +#define MORE_WINSIZE 4096 +#define STR_ANSICODE "[0123456789;," + +static int more_base, more_size, more_head; +static unsigned char more_pool[MORE_BUFSIZE]; + + +#define MAXPATHLEN 256 +static char *more_help[] = { + "\0¾\\Ū¤å³¹¥\\¯àÁä¨Ï¥Î»¡©ú", + "\01´å¼Ð²¾°Ê¥\\¯àÁä", + "(¡ô) ¤W±²¤@¦æ", + "(¡õ)(Enter) ¤U±²¤@¦æ", + "(^B)(PgUp)(BackSpace) ¤W±²¤@¶", + "(¡÷)(PgDn)(Space) ¤U±²¤@¶", + "(0)(g)(Home) Àɮ׶}ÀY", + "($)(G) (End) ÀÉ®×µ²§À", + "\01¨ä¥L¥\\¯àÁä", + "(/) ·j´M¦r¦ê", + "(n/N) «½Æ¥¿/¤Ï¦V·j´M", + "(TAB) URL³sµ²", + "(Ctrl-T) ¦s¨ì¼È¦sÀÉ", + "(:/f/b) ¸õ¦Ü¬Y¶/¤U/¤W½g", + "(F/B) ¸õ¦Ü¦P¤@·j´M¥DÃD¤U/¤W½g", + "(a/A) ¸õ¦Ü¦P¤@§@ªÌ¤U/¤W½g", + "([/]) ¥DÃD¦¡¾\\Ū ¤W/¤U", + "(t) ¥DÃD¦¡´`§Ç¾\\Ū", + "(Ctrl-C) ¤ppºâ¾÷", + "(q)(¡ö) µ²§ô", + "(h)(H)(?) »²§U»¡©úµe±", + NULL +}; + +int beep = 0; + +static void +more_goto (int fd, off_t off) +{ + int base = more_base; + + if (off < base || off >= base + more_size) + { + more_base = base = off & (-MORE_WINSIZE); + lseek (fd, base, SEEK_SET); + more_size = read (fd, more_pool, MORE_BUFSIZE); + } + more_head = off - base; +} + +static int +more_readln (int fd, unsigned char *buf) +{ + int ch; + + unsigned char *data, *tail, *cc; + int len, bytes, in_ansi; + int size, head, ansilen; + + len = bytes = in_ansi = ansilen = 0; + tail = buf + ANSILINELEN - 1; + size = more_size; + head = more_head; + data = &more_pool[head]; + + do + { + if (head >= size) + { + more_base += size; + data = more_pool; + more_size = size = read (fd, data, MORE_BUFSIZE); + if (size == 0) + break; + head = 0; + } + + ch = *data++; + head++; + bytes++; + if (ch == '\n') + { + break; + } + if (ch == '\t') + { + do + { + *buf++ = ' '; + } + while ((++len & 7) && len < 80); + } + else if (ch == '\033') + { + if (atoi (data + 1) > 47) + { + if ((cc = strchr (data + 1, 'm')) != NULL) + { + ch = cc - data + 1; + + data += ch; + head += ch; + bytes += ch; + } + } + else + { + if (showansi) + *buf++ = ch; + in_ansi = 1; + } + } + else if (in_ansi) + { + if (showansi) + *buf++ = ch; + if (!strchr (STR_ANSICODE, ch)) + in_ansi = 0; + } + else if (isprint2 (ch)) + { + len++; + *buf++ = ch; + } + } + while (len < 80 && buf < tail); + *buf = '\0'; + more_head = head; + return bytes; +} + +/* not used +static int readln(FILE *fp, char *buf) { + register int ch, i, len, bytes, in_ansi; + + len = bytes = in_ansi = i = 0; + while(len < 80 && i < ANSILINELEN && (ch = getc(fp)) != EOF) { + bytes++; + if(ch == '\n') + break; + else if(ch == '\t') + do { + buf[i++] = ' '; + } while((++len & 7) && len < 80); + else if(ch == '\a') + beep = 1; + else if(ch == '\033') { + if(showansi) + buf[i++] = ch; + in_ansi = 1; + } else if(in_ansi) { + if(showansi) + buf[i++] = ch; + if(!strchr("[0123456789;,", ch)) + in_ansi = 0; + } else if(isprint2(ch)) { + len++; + buf[i++] = ch; + } + } + buf[i] = '\0'; + return bytes; +} +*/ + +extern userec_t cuser; + +static int more_web(char *fpath, int promptend); + +int more(char *fpath, int promptend) { + extern char* strcasestr(); + static char *head[4] = {"§@ªÌ", "¼ÐÃD", "®É¶¡" ,"Âà«H"}; + char *ptr, *word = NULL, buf[ANSILINELEN + 1], *ch1; + struct stat st; + +/* rocker */ + //FILE *fp; + int fd, fsize; + + unsigned int pagebreak[MAX_PAGES], pageno, lino = 0; + int line, ch, viewed, pos, numbytes; + int header = 0; + int local = 0; + char search_char0=0; + static char search_str[81]=""; + typedef char* (*FPTR)(); + static FPTR fptr; + int searching = 0; + int scrollup = 0; + char *printcolor[3]= {"44","33;45","0;34;46"}, color =0; + char *http[80]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + /* Ptt */ + char pagemode = 0; + char pagecount = 0; + + memset(pagebreak, 0, sizeof(pagebreak)); + if(*search_str) + search_char0 = *search_str; + *search_str = 0; + + + fd = open (fpath, O_RDONLY, 0600); + if (fd < 0) return -1; + + if(fstat(fd, &st) || ((fsize = st.st_size) <= 0) || S_ISDIR (st.st_mode)) + { + close(fd); //Ptt + return -1; + } + pagebreak[0] = pageno = viewed = line = pos = 0; + clear(); + +/* rocker */ + + more_base = more_head = more_size = 0; + + while((numbytes = more_readln(fd, buf)) || (line == t_lines)) { + if(scrollup) { + rscroll(); + move(0, 0); + } + if(numbytes) { /* ¤@¯ë¸ê®Æ³B²z */ + if(!viewed) { /* begin of file */ + if(showansi) { /* header processing */ + if(!strncmp(buf, str_author1, LEN_AUTHOR1)) { + line = 3; + word = buf + LEN_AUTHOR1; + local = 1; + } else if(!strncmp(buf, str_author2, LEN_AUTHOR2)) { + line = 4; + word = buf + LEN_AUTHOR2; + } + + while(pos < line) { + if(!pos && ((ptr = strstr(word, str_post1)) || + (ptr = strstr(word, str_post2)))) { + ptr[-1] = '\0'; + prints("\033[47;34m %s \033[44;37m%-53.53s" + "\033[47;34m %.4s \033[44;37m%-13s\033[m\n", + head[0], word, ptr, ptr + 5); + } else if (pos < 4) + prints("\033[47;34m %s \033[44;37m%-72.72s" + "\033[m\n", head[pos], word); + + viewed += numbytes; + numbytes = more_readln(fd, buf); + + /* ²Ä¤@¦æ¤Óªø¤F */ + if(!pos && viewed > 79) { + /* ²Ä¤G¦æ¤£¬O [¼Ð....] */ + if(memcmp( buf, head[1], 2)) { + /* Ū¤U¤@¦æ¶i¨Ó³B²z */ + viewed += numbytes; + numbytes = more_readln(fd, buf); + } + } + pos++; + } + if(pos) { + header = 1; + + prints("\033[36m%s\033[m\n", msg_seperator); + line = pos = 4; + } + } + lino = pos; + word = NULL; + } + + /* ¡°³B²z¤Þ¥ÎªÌ & ¤Þ¨¥ */ + if((buf[1] == ' ') && (buf[0] == ':' || buf[0] == '>')) + word = "\033[36m"; + else if(!strncmp(buf, "¡°", 2) || !strncmp(buf, "==>", 3)) + word = "\033[32m"; + + ch1 = buf; + while(1) { + int i; + char e,*ch2; + + if((ch2 = strstr(ch1, "http://"))) + ; + else if((ch2 = strstr(ch1,"gopher://"))) + ; + else if((ch2 = strstr(ch1,"mailto:"))) + ; + else + break; + for(e = 0; ch2[(int)e] != ' ' && ch2[(int)e] != '\n' && + ch2[(int)e] != '\0' && ch2[(int)e] != '"' && + ch2[(int)e] != ';' && ch2[(int)e] != ']'; e++); + for(i = 0; http[i] && i < 80; i++) + if(!strncmp(http[i], ch2, e) && http[(int)e] == 0) + break; + if(!http[i]) { + http[i] = (char *)malloc(e + 1); + strncpy(http[i], ch2, e); + http[i][(int)e] = 0; + pagecount++; + } + ch1 = &ch2[7]; + } + if(word) + outs(word); + { + char msg[500], *pos; + + if(*search_str && (pos = fptr(buf, search_str))) { + char SearchStr[81]; + char buf1[100], *pos1; + + strncpy(SearchStr, pos, strlen(search_str)); + SearchStr[strlen(search_str)] = 0; + searching = 0; + sprintf(msg, "%.*s\033[7m%s\033[m", pos - buf, buf, + SearchStr); + while((pos = fptr(pos1 = pos + strlen(search_str), + search_str))) { + sprintf(buf1, "%.*s\033[7m%s\033[m", pos - pos1, + pos1, SearchStr); + strcat(msg, buf1); + } + strcat(msg, pos1); + outs(Ptt_prints(msg,NO_RELOAD)); + } else + outs(Ptt_prints(buf,NO_RELOAD)); + } + if(word) { + outs("\033[m"); + word = NULL; + } + outch('\n'); + + if(beep) { + bell(); + beep = 0; + } + + if(line < b_lines) /* ¤@¯ë¸ê®ÆŪ¨ú */ + line++; + + if(line == b_lines && searching == -1) { + if(pageno > 0) + more_goto(fd, viewed = pagebreak[--pageno]); + else + searching = 0; + lino = pos = line = 0; + clear(); + continue; + } + + if(scrollup) { + move(line = b_lines, 0); + clrtoeol(); + for(pos = 1; pos < b_lines; pos++) + viewed += more_readln(fd, buf); + } else if(pos == b_lines) /* ±²°Ê¿Ã¹õ */ + scroll(); + else + pos++; + + if(!scrollup && ++lino >= b_lines && pageno < MAX_PAGES - 1) { + pagebreak[++pageno] = viewed; + lino = 1; + } + + if(scrollup) { + lino = scrollup; + scrollup = 0; + } + viewed += numbytes; /* ²ÖpŪ¹L¸ê®Æ */ + } else + line = b_lines; /* end of END */ + + if(promptend && + ((!searching && line == b_lines) || viewed == fsize)) { + /* Kaede è¦n 100% ®É¤£°± */ + move(b_lines, 0); + if(viewed == fsize) { + if(searching == 1) + searching = 0; + color = 0; + } else if(pageno == 1 && lino == 1) { + if(searching == -1) + searching = 0; + color = 1; + } else + color = 2; + + prints("\033[m\033[%sm ÂsÄý P.%d(%d%%) %s %-30.30s%s", + printcolor[(int)color], + pageno, + (int)((viewed * 100) / fsize), + pagemode ? "\033[30;47m" : "\033[31;47m", + pagemode ? http[pagemode-1] : "(h)\033[30m¨D§U \033[31m¡÷¡õ[PgUp][", + pagemode ? "\033[31m[TAB]\033[30m¤Á´« \033[31m[Enter]\033[30m¿ï©w \033[31m¡ö\033[30m©ñ±ó\033[m" : "PgDn][Home][End]\033[30m´å¼Ð²¾°Ê \033[31m¡ö[q]\033[30mµ²§ô \033[m"); + + + while(line == b_lines || (line > 0 && viewed == fsize)) { + switch((ch = egetch())) { + case ':': + { + char buf[10]; + int i = 0; + + getdata(b_lines - 1, 0, "Goto Page: ", buf, 5, DOECHO); + sscanf(buf, "%d", &i); + if(0 < i && i < MAX_PAGES && (i == 1 || pagebreak[i - 1])) + pageno = i - 1; + else if(pageno) + pageno--; + lino = line = 0; + break; + } + case '/': + { + char ans[4] = "n"; + + *search_str = search_char0; + getdata_buf(b_lines - 1, 0,"[·j´M]ÃöÁä¦r:", search_str, + 40, DOECHO); + if(*search_str) { + searching = 1; + if(getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ", + ans, 4, LCECHO) && *ans == 'y') + fptr = strstr; + else + fptr = strcasestr; + } + if(*ans == 'q') + searching = 0; + if(pageno) + pageno--; + lino = line = 0; + break; + } + case 'n': + if(*search_str) { + searching = 1; + if(pageno) + pageno--; + lino = line = 0; + } + break; + case 'N': + if(*search_str) { + searching = -1; + if(pageno) + pageno--; + lino = line = 0; + } + break; + case 'r': + case 'R': + case 'Y': + close(fd); + return 7; + case 'y': + close(fd); + return 8; + case 'A': + close(fd); + return 9; + case 'a': + close(fd); + return 10; + case 'F': + close(fd); + return 11; + case 'B': + close(fd); + return 12; + case KEY_LEFT: + if(pagemode) { + pagemode = 0; + *search_str = 0; + if(pageno) + pageno--; + lino = line = 0; + break; + } + close(fd); + return 6; + case 'q': + close(fd); + return 0; + case 'b': + close(fd); + return 1; + case 'f': + close(fd); + return 3; + case ']': /* Kaede ¬°¤F¥DÃD¾\Ū¤è«K */ + close(fd); + return 4; + case '[': /* Kaede ¬°¤F¥DÃD¾\Ū¤è«K */ + close(fd); + return 2; + case '=': /* Kaede ¬°¤F¥DÃD¾\Ū¤è«K */ + close(fd); + return 5; + case Ctrl('F'): + case KEY_PGDN: + line = 1; + break; + case 't': + if(viewed == fsize) { + close(fd); + return 4; + } + line = 1; + break; + case ' ': + if(viewed == fsize) { + close(fd); + return 3; + } + line = 1; + break; + case KEY_RIGHT: + if(viewed == fsize) { + close(fd); + return 0; + } + line = 1; + break; + case '\r': + case '\n': + if(pagemode) { + more_web(http[pagemode-1],YEA); + pagemode = 0; + *search_str = 0; + if(pageno) + pageno--; + lino = line = 0; + break; + } + case KEY_DOWN: + if(viewed == fsize || + (promptend == 2 && (ch == '\r' || ch == '\n'))) { + close(fd); + return 3; + } + line = t_lines - 2; + break; + case '$': + case 'G': + case KEY_END: + line = t_lines; + break; + case '0': + case 'g': + case KEY_HOME: + pageno = line = 0; + break; + case 'h': + case 'H': + case '?': + /* Kaede Buggy ... */ + show_help(more_help); + if(pageno) + pageno--; + lino = line = 0; + break; + case 'E': + if(HAS_PERM(PERM_SYSOP) && strcmp(fpath, "etc/ve.hlp")) { + close(fd); + vedit(fpath, NA, NULL); + return 0; + } + break; + case Ctrl('C'): + cal(); + if(pageno) + pageno--; + lino = line = 0; + break; + + case Ctrl('T'): + getdata(b_lines - 2, 0, "§â³o½g¤å³¹¦¬¤J¨ì¼È¦sÀÉ¡H[y/N] ", + buf, 4, LCECHO); + if(buf[0] == 'y') { + char tmpbuf[128]; + + setuserfile(tmpbuf, ask_tmpbuf(b_lines - 1)); + sprintf(buf, "cp -f %s %s", fpath, tmpbuf); + system(buf); + } + if(pageno) + pageno--; + lino = line = 0; + break; +#if 0 + case Ctrl('I'): + if(!pagecount) + break; + pagemode = (pagemode % pagecount) + 1; + strncpy(search_str,http[pagemode-1],80); + search_str[80] =0; + fptr = strstr; + if(pageno) + pageno--; + lino = line = 0; + break; +#endif + case KEY_UP: + line = -1; + break; + case Ctrl('B'): + case KEY_PGUP: + if(pageno > 1) { + if(lino < 2) + pageno -= 2; + else + pageno--; + lino = line = 0; + } else if(pageno && lino > 1) + pageno = line = 0; + break; + case Ctrl('H'): + if(pageno > 1) { + if(lino < 2) + pageno -= 2; + else + pageno--; + lino = line = 0; + } else if(pageno && lino > 1) + pageno = line = 0; + else { + close(fd); + return 1; + } + } + } + + if(line > 0) { + move(b_lines, 0); + clrtoeol(); + refresh(); + } else if(line < 0) { /* Line scroll up */ + if(pageno <= 1) { + if(lino == 1 || !pageno) { + close(fd); + return 1; + } + if(header && lino <= 5) { + more_goto(fd, viewed = pagebreak[scrollup = lino = + pageno = 0] = 0); + clear(); + } + } + if(pageno && lino > 1 + local) { + line = (lino - 2) - local; + if(pageno > 1 && viewed == fsize) + line += local; + scrollup = lino - 1; + more_goto(fd, viewed = pagebreak[pageno - 1]); + while(line--) + viewed += more_readln(fd, buf); + } else if(pageno > 1) { + scrollup = b_lines - 1; + line = (b_lines - 2) - local; + more_goto(fd, viewed = pagebreak[--pageno - 1]); + while(line--) + viewed += more_readln(fd, buf); + } + line = pos = 0; + } else { + pos = 0; + more_goto (fd, viewed = pagebreak[pageno]); + move(0,0); + clear(); + } + } + } + + close(fd); + if(promptend) { + pressanykey(); + clear(); + } else + outs(reset_color); + return 0; +} + +static int more_web(char *fpath, int promptend) { + char *ch, *ch1 = NULL; + char *hostname = fpath,userfile[MAXPATHLEN],file[MAXPATHLEN]="/"; + char genbuf[200]; + time_t dtime; +#if !defined(USE_LYNX) && defined(USE_PROXY) + int a; + FILE *fp; + struct hostent *h; + struct sockaddr_in sin; +#endif + + if((ch = strstr(fpath, "mailto:"))) { + if(!HAS_PERM(PERM_LOGINOK)) { + move(b_lines - 1,0); + outs("\033[41m ±zªºÅv¤£¨¬µLªk¨Ï¥Îinternet mail... \033[m"); + refresh(); + return 0; + } + if(!invalidaddr(&ch[7]) && + getdata(b_lines - 1, 0, "[±H«H]¥DÃD¡G", genbuf, 40, DOECHO)) + do_send(&ch[7], genbuf); + else { + move(b_lines - 1,0); + outs("\033[41m ¦¬«H¤Hemail ©Î ¼ÐÃD ¦³»~... \033[m"); + refresh(); + } + return 0; + } + if((ch = strstr(fpath, "gopher://"))) { + item_t item; + + strcpy(item.X.G.server, &ch[9]); + strcpy(item.X.G.path, "1/"); + item.X.G.port = 70; + gem(fpath , &item, 0); + return 0; + } + if((ch = strstr(fpath, "http://"))) + hostname=&ch[7]; + if((ch = strchr(hostname, '/'))) { + *ch = 0; + if(&ch1[1]) + strcat(file,&ch[1]); + } + if(file[strlen(file) - 1] == '/') + strcat(file,"index.html"); + move(b_lines-1,0); + clrtoeol(); +#ifdef USE_PROXY + sprintf(genbuf, "\033[33;44m ¥¿¦b³s©¹%s.(proxy:%s).....½ÐµyÔ....\033[m", + hostname, PROXYSERVER); +#else + sprintf(genbuf, "\033[33;44m ¥¿¦b³s©¹%s......½ÐµyÔ....\033[m", hostname); +#endif + outs(genbuf); + refresh(); + +#ifdef LOCAL_PROXY +/* ¥ý§ä local disk ªº proxy */ + time(&dtime); + sprintf(userfile,"hproxy/%s%s",hostname,file); + if(dashf(userfile) && (dtime - dasht(userfile)) < HPROXYDAY * 24 * 60 + && more(userfile,promptend)) { + return 1; + } + ch=userfile - 1; + while((ch1 = strchr(ch + 1,'/'))) { + *ch1 = 0; + if(!dashd(ch)) + mkdir(ch+1,0755); + chdir(ch+1); + *ch1 = '/'; + ch = ch1; + } + chdir(BBSHOME); +#endif + +#ifndef USE_LYNX +#ifdef USE_PROXY + if(!(h = gethostbyname(PROXYSERVER))) { + outs("\033[33;44m §ä¤£¨ì³oÓproxy server!..\033[m"); + refresh(); + return; + } + ()memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + + if(h == NULL) + sin.sin_addr.s_addr = inet_addr(PROXYSERVER); + else + ()memcpy(&sin.sin_addr.s_addr, h->h_addr, h->h_length); + + sin.sin_port = htons((ushort)PROXYPORT); /* HTTP port */ + a = socket(AF_INET, SOCK_STREAM, 0); + if((connect(a, (struct sockaddr *) & sin, sizeof sin)) < 0) { + outs("\033[1;44m ³s±µ¨ìproxy¨ü¨ì©Úµ´ ! \033[m"); + refresh(); + return; + } + sprintf(genbuf,"GET http://%s/%s HTTP/1.1\n",hostname,file); +#else + if(!(h = gethostbyname(hostname))) { + outs("\033[33;44m §ä¤£¨ì³oÓserver!..\033[m"); + refresh(); + return; + } + ()memset((char *) &sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + + if(h == NULL) + sin.sin_addr.s_addr = inet_addr(hostname); + else + ()memcpy(&sin.sin_addr.s_addr, h->h_addr, h->h_length); + + sin.sin_port = htons((ushort)80); + a = socket(AF_INET, SOCK_STREAM, 0); + if((connect(a, (struct sockaddr *) & sin, sizeof sin)) < 0) { + outs("\033[1;44m ³s±µ¨ü¨ì©Úµ´ ! \033[m"); + refresh(); + return; + } + sprintf(genbuf, "GET %s\n", file); +#endif + + for(i = strlen(file); file[i - 1] != '/' && i > 0 ; i--); + file[i] = 0; + + i = strlen(genbuf); + write(a, genbuf, i); + +#define BLANK 001 +#define ISPRINT 002 +#define PRE 004 +#define CENTER 010 + if((fp = fopen(userfile,"w"))) { + int flag = 2, c; + char path[MAXPATHLEN]; + unsigned char j, k; + + while((i = read(a,genbuf,200))) { + if(i < 0) + return; + genbuf[i]=0; + + for(j = 0, k = 0; genbuf[j] && j < i; j++) { + if((flag & ISPRINT) && genbuf[j] == '<') + flag |= BLANK; + else if((flag & ISPRINT) && genbuf[j] == '>') + flag &= ~BLANK; + else { + if(!(flag & BLANK)) { + if(j != k && (genbuf[j] != '\n' || flag & PRE)) + genbuf[k++] = genbuf[j]; + } else { + switch(char_lower(genbuf[j])) { + case 'a': + break; + case 'b': + if(genbuf[j + 1] == 'r' && genbuf[j + 2] == '>') + genbuf[k++] = '\n'; + break; + case 'h': + if(genbuf[j + 1] == 'r' && + (genbuf[j + 2] == '>' || + genbuf[j + 2] == 's')) { + strncpy(&genbuf[k], "\n--\n", 4); + k += 4; + } + break; + case 'l': + if(genbuf[j + 1] == 'i' && genbuf[j + 2]=='>') { + strncpy(&genbuf[k], "\n¡· ", 4); + k += 4; + } + break; + case 'p': + if(genbuf[j + 1]=='>') { + genbuf[k++] = '\n'; + genbuf[k++] = '\n'; + } else if(genbuf[j + 1] == 'r' && + genbuf[j + 2] == 'e') + flag ^= PRE; + break; + case 't': + if(genbuf[j + 1] == 'd' && genbuf[j + 2]=='>') { + strncpy(&genbuf[k], "\n-\n", 3); + k += 3; + } + break; + } + } + if((genbuf[j] & 0x80) && (flag & ISPRINT)) + flag &= ~ISPRINT; + else + flag |= ISPRINT; + } + } + genbuf[k]=0; + fputs(genbuf, fp); + } + fclose(fp); + close(a); + return more(userfile, promptend); + } + return 0; +#else /* use lynx dump */ + sprintf(genbuf, "lynx -dump http://%s%s > %s", hostname, file, userfile); + system(genbuf); + return more(userfile, promptend); +#endif +} diff --git a/mbbsd/name.c b/mbbsd/name.c new file mode 100644 index 00000000..2f84a1fe --- /dev/null +++ b/mbbsd/name.c @@ -0,0 +1,473 @@ +/* $Id: name.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <signal.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +extern char *str_space; +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +word_t *toplev = NULL; +static word_t *current = NULL; +static char *msg_more = "\033[7m-- More --\033[m"; + +typedef char (*arrptr)[]; +/* name complete for user ID */ + +static int UserMaxLen(char cwlist[][IDLEN + 1], int cwnum, int morenum, + int count) { + int len, max = 0; + + while(count-- > 0 && morenum < cwnum) { + len = strlen(cwlist[morenum++]); + if (len > max) + max = len; + } + return max; +} + +static int UserSubArray(char cwbuf[][IDLEN + 1], char cwlist[][IDLEN + 1], + int cwnum, int key, int pos) { + int key2, num = 0; + int n, ch; + + key = chartoupper(key); + if(key >= 'A' && key <= 'Z') + key2 = key | 0x20; + else + key2 = key ; + + for(n = 0; n < cwnum; n++) { + ch = cwlist[n][pos]; + if(ch == key || ch == key2) + strcpy(cwbuf[num++], cwlist[n]); + } + return num; +} + +static void FreeNameList() { + word_t *p, *temp; + + for(p = toplev; p; p = temp) { + temp = p->next; + free(p->word); + free(p); + } +} + +void CreateNameList() { + if(toplev) + FreeNameList(); + toplev = current = NULL; +} + +void AddNameList(char *name) { + word_t *node; + + node = (word_t *)malloc(sizeof(word_t)); + node->next = NULL; + node->word = (char *)malloc(strlen(name) + 1); + strcpy(node->word, name); + + if(toplev) + current = current->next = node; + else + current = toplev = node; +} + +int RemoveNameList(char *name) { + word_t *curr, *prev = NULL; + + for(curr = toplev; curr; curr = curr->next) { + if(!strcmp(curr->word, name)) { + if(prev == NULL) + toplev = curr->next; + else + prev->next = curr->next; + + if(curr == current) + current = prev; + free(curr->word); + free(curr); + return 1; + } + prev = curr; + } + return 0; +} + +int InNameList(char *name) { + word_t *p; + + for(p = toplev; p; p = p->next) + if(!strcmp(p->word, name)) + return 1; + return 0; +} + +void ShowNameList(int row, int column, char *prompt) { + word_t *p; + + move(row, column); + clrtobot(); + outs(prompt); + + column = 80; + for(p = toplev; p; p = p->next) { + row = strlen(p->word) + 1; + if(column + row > 76) { + column = row; + outc('\n'); + } else { + column += row; + outc(' '); + } + outs(p->word); + } +} + +void ToggleNameList(int *reciper, char *listfile, char *msg) { + FILE *fp; + char genbuf[200]; + + if((fp = fopen(listfile, "r"))) { + while(fgets(genbuf, STRLEN, fp)) { + strtok(genbuf, str_space); + if(!InNameList(genbuf)) { + AddNameList(genbuf); + (*reciper)++; + } else { + RemoveNameList(genbuf); + (*reciper)--; + } + } + fclose(fp); + ShowNameList(3, 0, msg); + } +} + +static int NumInList(word_t *list) { + register int i; + + for(i = 0; list; i++) + list = list->next; + return i; +} + +int chkstr(char *otag, char *tag, char *name) { + char ch, *oname = name; + + while(*tag) { + ch = *name++; + if(*tag != chartoupper(ch)) + return 0; + tag++; + } + if(*tag && *name == '\0') + strcpy(otag, oname); + return 1; +} + +static word_t *GetSubList(char *tag, word_t *list) { + word_t *wlist, *wcurr; + char tagbuf[STRLEN]; + int n; + + wlist = wcurr = NULL; + for(n = 0; tag[n]; n++) + tagbuf[n] = chartoupper(tag[n]); + tagbuf[n] = '\0'; + + while(list) { + if(chkstr(tag, tagbuf, list->word)) { + register word_t *node; + + node = (word_t *)malloc(sizeof(word_t)); + node->word = list->word; + node->next = NULL; + if(wlist) + wcurr->next = node; + else + wlist = node; + wcurr = node; + } + list = list->next; + } + return wlist; +} + +static void ClearSubList(word_t *list) { + struct word_t *tmp_list; + + while(list) { + tmp_list = list->next; + free(list); + list = tmp_list; + } +} + +static int MaxLen(word_t *list, int count) { + int len = strlen(list->word); + int t; + + while(list && count) { + if((t = strlen(list->word)) > len) + len = t; + list = list->next; + count--; + } + return len; +} + +void namecomplete(char *prompt, char *data) { + char *temp; + word_t *cwlist, *morelist; + int x, y, origx, origy; + int ch; + int count = 0; + int clearbot = NA; + + if(toplev == NULL) + AddNameList(""); + cwlist = GetSubList("", toplev); + morelist = NULL; + temp = data; + + outs(prompt); + clrtoeol(); + getyx(&y, &x); + getyx(&origy, &origx); + standout(); + prints("%*s", IDLEN + 1, ""); + standend(); + move(y, x); + refresh(); + + while((ch = igetch()) != EOF) { + if(ch == '\n' || ch == '\r') { + *temp = '\0'; + outc('\n'); + if(NumInList(cwlist) == 1) + strcpy(data, cwlist->word); + ClearSubList(cwlist); + break; + } + if(ch == ' ') { + int col, len; + + if(NumInList(cwlist) == 1) { + strcpy(data, cwlist->word); + move(y, x); + outs(data + count); + count = strlen(data); + temp = data + count; + getyx(&y, &x); + continue; + } + clearbot = YEA; + col = 0; + if(!morelist) + morelist = cwlist; + len = MaxLen(morelist, p_lines); + move(2, 0); + clrtobot(); + printdash("¬ÛÃö¸ê°T¤@Äýªí"); + while(len + col < 80) { + int i; + + for(i = p_lines; (morelist) && (i > 0); i--) { + move(3 + (p_lines - i), col); + outs(morelist->word); + morelist = morelist->next; + } + col += len + 2; + if(!morelist) + break; + len = MaxLen(morelist, p_lines); + } + if(morelist) { + move(b_lines, 0); + outs(msg_more); + } + move(y, x); + continue; + } + if(ch == '\177' || ch == '\010') { + if(temp == data) + continue; + temp--; + count--; + *temp = '\0'; + ClearSubList(cwlist); + cwlist = GetSubList(data, toplev); + morelist = NULL; + x--; + move(y, x); + outc(' '); + move(y, x); + continue; + } + + if(count < STRLEN && isprint(ch)) { + word_t *node; + + *temp++ = ch; + count++; + *temp = '\0'; + node = GetSubList(data, cwlist); + if(node == NULL) { + temp--; + *temp = '\0'; + count--; + continue; + } + ClearSubList(cwlist); + cwlist = node; + morelist = NULL; + move(y, x); + outc(ch); + x++; + } + } + if(ch == EOF) + /* longjmp(byebye, -1); */ + raise(SIGHUP); /* jochang: don't know if this is necessary... */ + outc('\n'); + refresh(); + if(clearbot) { + move(2, 0); + clrtobot(); + } + if(*data) { + move(origy, origx); + outs(data); + outc('\n'); + } +} + +void usercomplete(char *prompt, char *data) { + char *temp; + char *cwbuf, *cwlist; + int cwnum, x, y, origx, origy; + int clearbot = NA, count = 0, morenum = 0; + char ch; + + cwbuf = malloc(MAX_USERS * (IDLEN + 1)); + cwlist = u_namearray((arrptr)cwbuf, &cwnum, ""); + temp = data; + + outs(prompt); + clrtoeol(); + getyx(&y, &x); + getyx(&origy, &origx); + standout(); + prints("%*s", IDLEN + 1, ""); + standend(); + move(y, x); + while((ch = igetch()) != EOF) { + if(ch == '\n' || ch == '\r') { + int i; + char *ptr; + + *temp = '\0'; + outc('\n'); + ptr = (char *)cwlist; + for(i = 0; i < cwnum; i++) { + if(strncasecmp(data, ptr, IDLEN + 1) == 0) + strcpy(data, ptr); + ptr += IDLEN + 1; + } + break; + } else if(ch == ' ') { + int col, len; + + if(cwnum == 1) { + strcpy(data, (char *)cwlist); + move(y, x); + outs(data + count); + count = strlen(data); + temp = data + count; + getyx(&y, &x); + continue; + } + clearbot = YEA; + col = 0; + len = UserMaxLen((arrptr)cwlist, cwnum, morenum, p_lines); + move(2, 0); + clrtobot(); + printdash("¨Ï¥ÎªÌ¥N¸¹¤@Äýªí"); + while(len + col < 79) { + int i; + + for(i = 0; morenum < cwnum && i < p_lines; i++) { + move(3 + i, col); + prints("%s ", cwlist + (IDLEN + 1) * morenum++); + } + col += len + 2; + if(morenum >= cwnum) + break; + len = UserMaxLen((arrptr)cwlist, cwnum, morenum, p_lines); + } + if(morenum < cwnum) { + move(b_lines, 0); + outs(msg_more); + } else + morenum = 0; + move(y, x); + continue; + } else if(ch == '\177' || ch == '\010') { + if(temp == data) + continue; + temp--; + count--; + *temp = '\0'; + cwlist = u_namearray((arrptr)cwbuf, &cwnum, data); + morenum = 0; + x--; + move(y, x); + outc(' '); + move(y, x); + continue; + } else if(count < STRLEN && isprint(ch)) { + int n; + + *temp++ = ch; + *temp = '\0'; + n = UserSubArray((arrptr)cwbuf, (arrptr)cwlist, cwnum, ch, count); + if(n == 0) { + temp--; + *temp = '\0'; + continue; + } + cwlist = cwbuf; + count++; + cwnum = n; + morenum = 0; + move(y, x); + outc(ch); + x++; + } + } + free(cwbuf); + if(ch == EOF) + /* longjmp(byebye, -1); */ + raise(SIGHUP); /* jochang: don't know if this is necessary */ + outc('\n'); + refresh(); + if(clearbot) { + move(2, 0); + clrtobot(); + } + if(*data) { + move(origy, origx); + outs(data); + outc('\n'); + } +} diff --git a/mbbsd/osdep.c b/mbbsd/osdep.c new file mode 100644 index 00000000..967a4db0 --- /dev/null +++ b/mbbsd/osdep.c @@ -0,0 +1,79 @@ +/* $Id: osdep.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> + +#if defined(linux) +int cpuload(char *str) { + double l[3] = {-1, -1, -1}; + FILE *fp; + + if((fp = fopen("/proc/loadavg", "r"))) { + if(fscanf(fp, "%lf %lf %lf", &l[0], &l[1], &l[2]) != 3) + l[0] = -1; + fclose(fp); + } + if(str) { + if(l[0] != -1) + sprintf(str, " %.2f %.2f %.2f", l[0], l[1], l[2]); + else + strcpy(str, " (unknown) "); + } + return (int)l[0]; +} + +double swapused(long *total, long *used) { + double percent = -1; + char buf[101]; + FILE *fp; + + if((fp = fopen("/proc/meminfo","r"))) { + while(fgets(buf, 100, fp) && buf[0] != 'S'); + if(sscanf(buf + 6, "%ld %ld", total, used) == 2) + if(*total != 0) + percent = (double)*used / (double)*total; + fclose(fp); + } + return percent; +} + +#elif __FreeBSD__ >=4 + +#include <kvm.h> + +int cpuload(char *str) { + double l[3] = {-1, -1, -1}; + if(getloadavg(l, 3) != 3) + l[0] = -1; + + if(str) { + if(l[0] != -1) + sprintf(str, " %.2f %.2f %.2f", l[0], l[1], l[2]); + else + strcpy(str, " (unknown) "); + } + return (int)l[0]; +} + +double swapused(long *total, long *used) { + double percent = -1; + kvm_t *kd; + struct kvm_swap swapinfo; + int pagesize; + + kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); + if(kd) { + if(kvm_getswapinfo(kd, &swapinfo, 1, 0) == 0) { + pagesize = getpagesize(); + *total = swapinfo.ksw_total * pagesize; + *used = swapinfo.ksw_used * pagesize; + if(*total != 0) + percent = (double)*used / (double)*total; + } + kvm_close(kd); + } + return percent; +} +#endif diff --git a/mbbsd/othello.c b/mbbsd/othello.c new file mode 100644 index 00000000..47b8cef3 --- /dev/null +++ b/mbbsd/othello.c @@ -0,0 +1,541 @@ +/* $Id: othello.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern char *BBSName; + +#define LOGFILE "etc/othello.log" +#define SECRET "etc/othello.secret" +#define NR_TABLE 2 + +#define true 1 +#define false 0 +#define STARTX 3 +#define STARTY 20 +#define NONE_CHESS " " +#define WHITE_CHESS "¡´" +#define BLACK_CHESS "¡³" +#define HINT_CHESS "¡" +#define NONE 0 +#define HINT 1 +#define BLACK 2 +#define WHITE 3 + +#define INVERT(COLOR) (((COLOR))==WHITE?BLACK:WHITE) + +static char nowx = 3, nowy = 3; +static char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS}; +static char DIRX[] = {-1,-1,-1, 0, 1, 1, 1, 0}; +static char DIRY[] = {-1, 0, 1, 1, 1, 0,-1,-1}; +static char number[2]; + +static char pass = 0; +static char if_hint = 0; +static int think, which_table; + +static char nowboard[10][10]= +{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; +static char init_table[NR_TABLE+1][5][5] = { + {{ 0, 0, 0, 0, 0}, + { 0,30,-3, 2, 2}, + { 0,-3,-3,-1,-1}, + { 0, 2,-1, 1, 1}, + { 0, 2,-1, 1, 0}}, + + {{ 0, 0, 0, 0, 0}, + { 0,70, 5,20,30}, + { 0, 5,-5, 3, 3}, + { 0,20, 3, 5, 5}, + { 0,30, 3, 5, 5}}, + + {{ 0, 0, 0, 0, 0}, + { 0, 5, 2, 2, 2}, + { 0, 2, 1, 1, 1}, + { 0, 2, 1, 1, 1}, + { 0, 2, 1, 1, 1}} +}; + +static char table[NR_TABLE + 1][10][10]; +static void print_chess(int x, int y, char chess) { + move(STARTX - 1 + x * 2, STARTY - 2 + y * 4); + if(chess != HINT || if_hint == 1) + prints(CHESS_TYPE[(int)chess]); + else + prints(CHESS_TYPE[NONE]); + refresh(); +} + +extern userec_t cuser; + +static void printboard() { + int i; + + move(STARTX, STARTY); + prints("¢z¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢{"); + for(i = 0; i < 7; i++) { + move(STARTX + 1 + i * 2, STARTY); + prints ("¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x"); + move(STARTX + 2 + i * 2, STARTY); + prints ("¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t"); + } + move(STARTX + 1 + i * 2, STARTY); + prints("¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x"); + move(STARTX + 2 + i * 2, STARTY); + prints("¢|¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢}"); + print_chess(4, 4, WHITE); + print_chess(5, 5, WHITE); + print_chess(4, 5, BLACK); + print_chess(5, 4, BLACK); + move(3, 56); + prints("(¶Â)%s",cuser.userid); + move(3, 72); + prints(": 02"); + move(4, 56); + prints("(¥Õ)¹q¸£ : 02"); + move(6, 56); + prints("¡ ¥i¥H¤U¤§³B"); + move(7, 56); + prints("[q] °h¥X"); + move(8, 56); + prints("[h] ¶}±Ò/Ãö³¬ ´£¥Ü"); + move(9,56); + prints("[Enter][Space] ¤U´Ñ"); + move(10, 56); + prints("¤W:¡ô, i"); + move(11, 56); + prints("¤U:¡õ, k"); + move(12, 56); + prints("¥ª:¡ö, j"); + move(13, 56); + prints("¥k:¡÷, l"); +} + +static int get_key(char nowx, char nowy) { + int ch; + + move(STARTX - 1 + nowx * 2, STARTY - 1 + nowy * 4); + ch = igetkey(); + move(STARTX - 1 + nowx * 2, STARTY - 2 + nowy * 4); + if(nowboard[(int)nowx][(int)nowy] != HINT || if_hint==1) + outs(CHESS_TYPE[(int)nowboard[(int)nowx][(int)nowy]]); + else + outs(CHESS_TYPE[NONE]); + return ch; +} + +static int eatline(int i, int j, char color, int dir, char chessboard[][10]) { + int tmpx,tmpy; + char tmpchess; + + tmpx = i + DIRX[dir]; + tmpy = j + DIRY[dir]; + tmpchess = chessboard[tmpx][tmpy]; + if(tmpchess == -1) + return false; + if(tmpchess != INVERT(color)) + return false; + + tmpx += DIRX[dir]; + tmpy += DIRY[dir]; + tmpchess = chessboard[tmpx][tmpy]; + while(tmpchess != -1) { + if(tmpchess < BLACK) + return false; + if(tmpchess == color) { + while(i != tmpx || j != tmpy) { + chessboard[i][j] = color; + i += DIRX[dir]; + j += DIRY[dir]; + } + return true; + } + tmpx += DIRX[dir]; + tmpy += DIRY[dir]; + tmpchess = chessboard[tmpx][tmpy]; + } + return false; +} + +static int if_can_put(int x, int y, char color, char chessboard[][10]) { + int i, temp, checkx, checky; + + if(chessboard[x][y]<BLACK) + for(i = 0; i < 8; i++) { + checkx = x + DIRX[i]; + checky = y + DIRY[i]; + temp = chessboard[checkx][checky]; + if(temp < BLACK) + continue; + if(temp != color) + while(chessboard[checkx += DIRX[i]][checky += DIRY[i]] > HINT) + if(chessboard[checkx][checky] == color) + return true; + } + return false; +} + +static int get_hint(char color) { + int i, j, temp = 0; + + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) { + if(nowboard[i][j] == HINT) + nowboard[i][j] = NONE; + if(if_can_put(i, j, color, nowboard)) { + nowboard[i][j] = HINT; + temp++; + } + print_chess(i, j, nowboard[i][j]); + } + return temp; +} + +static void eat(int x, int y, int color, char chessboard[][10]) { + int k; + + for(k = 0; k < 8; k++) + eatline(x, y, color, k, chessboard); +} + +static void end_of_game(int quit) { + FILE *fp,*fp1; + char *opponent[] = {"","CD-65","","À¦¨à","¤p«Ä","","¤j¤H","±M®a"}; + + move(STARTX - 1, 30); + prints (" "); + move(22, 35); + fp = fopen(LOGFILE, "a"); + if(!quit) { + fp1 = fopen(SECRET, "a"); + if(fp1) { + fprintf(fp1, "%d,%d,%s,%02d,%02d\n", think, which_table, + cuser.userid, number[0], number[1]); + fclose(fp1); + } + } + + if(quit) { + if(number[0] == 2 && number[1] == 2) { + if(fp) + fclose(fp); + return; + } + fprintf(fp, "¦b%s¯Å¤¤, %sÁ{°}²æ°k\n", opponent[think], cuser.userid); + if(fp) + fclose(fp); + return; + } + if(number[0] > number[1]) { + prints("§AŤF¹q¸£%02d¤l", number[0] - number[1]); + if(think == 6 && number[0] - number[1] >= 50) + demoney(200); + if(think == 7 && number[0] - number[1] >= 40) + demoney(200); + if(fp) + fprintf(fp, "¦b%s¯Å¤¤, %s¥H %02d:%02d ŤF¹q¸£%02d¤l\n", + opponent[think], cuser.userid, number[0], number[1], + number[0] - number[1]); + } else if(number[1] > number[0]) { + prints("¹q¸£Ä¹¤F§A%02d¤l", number[1] - number[0]); + if(fp) { + fprintf(fp, "¦b%s¯Å¤¤, ", opponent[think]); + if(number[1] - number[0] > 20) + fprintf(fp, "¹q¸£¥H %02d:%02d ºG¹q%s %02d¤l\n", number[1], + number[0], cuser.userid, number[1] - number[0]); + else + fprintf(fp, "¹q¸£¥H %02d:%02d ŤF%s %02d¤l\n", number[1], + number[0], cuser.userid, number[1] - number[0]); + } + } else { + prints("§A©M¹q¸£¥´¦¨¥¤â!!"); + if(fp) + fprintf(fp, "¦b%s¯Å¤¤, %s©M¹q¸£¥H %02d:%02d ¥´¦¨¤F¥¤â\n", + opponent[think], cuser.userid, number[1], number[0]); + } + if(fp) + fclose(fp); + move(1,1); + igetkey(); +} + +static void othello_redraw() { + int i, j; + + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) + print_chess(i, j, nowboard[i][j]); +} + +static int player(char color) { + int ch; + + if(get_hint(color)) { + while(true) { + ch = get_key(nowx,nowy); + switch(ch) { + case 'J': + case 'j': + case KEY_LEFT: + nowy--; + break; + case 'L': + case 'l': + case KEY_RIGHT: + nowy++; + break; + case 'I': + case 'i': + case KEY_UP: + nowx--; + break; + case 'K': + case 'k': + case KEY_DOWN: + nowx++; + break; + case ' ': + case '\r': + if(nowboard[(int)nowx][(int)nowy] != HINT) + break; + pass = 0; + nowboard[(int)nowx][(int)nowy] = color; + eat(nowx, nowy, color, nowboard); + print_chess(nowx, nowy, color); + return true; + case 'q': + end_of_game(1); + return false; + case 'H': + case 'h': + if_hint = if_hint^1; + othello_redraw(); + break; + } + if(nowx == 9) + nowx=1; + if(nowx == 0) + nowx=8; + if(nowy == 9) + nowy=1; + if(nowy == 0) + nowy=8; + } + } else { + pass++; + if(pass == 1) { + move(23, 34); + prints("§A¥²»Ý©ñ±ó³o¤@¨B!!"); + igetch(); + move(28,23); + prints(" "); + } else { + end_of_game(0); + return false; + } + } + return 0; +} + +static void init() { + int i, j, i1, j1; + + nowx = 4; + nowy = 4; + number[0] = number[1] = 2; + for(i = 1; i <= 8; i++) + for(j = 1;j <= 8; j++) { + i1 = 4.5 - abs(4.5 - i); + j1 = 4.5 - abs(4.5 - j); + table[0][i][j] = init_table[0][i1][j1]; + table[1][i][j] = init_table[1][i1][j1]; + } + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) + nowboard[i][j] = NONE; + nowboard[4][4] = nowboard[5][5] = WHITE; + nowboard[4][5] = nowboard[5][4] = BLACK; +} + +static void report() { + int i, j; + + number[0] = number[1] = 0; + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) + if(nowboard[i][j] == BLACK) + number[0]++; + else if(nowboard[i][j] == WHITE) + number[1]++; + move(3, 60); + prints("%s", cuser.userid); + move(3, 72); + prints(": %02d", number[0]); + move(4, 60); + prints("¹q¸£ : %02d", number[1]); +} + +static int EVL(char chessboard[][10], int color, int table_number) { + int points = 0,a,b; + for(a = 1; a <= 8; a++) + for(b = 1; b <= 8; b++) + if(chessboard[a][b] > HINT) { + if(chessboard[a][b] == BLACK) + points += table[table_number][a][b]; + else + points -= table[table_number][a][b]; + } + return ((color == BLACK) ? points : -points); +} + +static int alphabeta(int alpha, int beta, int level, char chessboard[][10], + int thinkstep, int color, int table) { + int i, j, k, flag = 1; + char tempboard[10][10]; + if(level == thinkstep+1) + return EVL(chessboard, (level & 1 ? color : ((color - 2) ^ 1) + 2), + table); + for(i = 1; i <= 8; i++) { + for(j = 1; j <= 8; j++) { + if(if_can_put(i, j, color, chessboard)) { + flag = 0; + memcpy(tempboard, chessboard, sizeof(char) * 100); + eat(i, j, color, tempboard); + + k = alphabeta(alpha, beta, level + 1, tempboard, thinkstep, + ((color - 2) ^ 1) + 2, table); + if(((level & 1) && k > alpha)) + alpha = k; + else if(!(level & 1) && k < beta) + beta = k; + if(alpha >= beta) + break; + } + } + } + if(flag) + return EVL(chessboard, color, table); + return ((level & 1) ? alpha : beta); +} + +static int Computer(int thinkstep, int table) { + int i, j, maxi = 0, maxj = 0, level = 1; + char chessboard[10][10]; + int alpha = -10000, k; + if((number[0] + number[1]) > 44) + table = NR_TABLE; + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) { + if(if_can_put(i,j,WHITE,nowboard)) { + memcpy(chessboard, nowboard, sizeof(char) * 100); + eat(i, j, WHITE, chessboard); + k = alphabeta(alpha, 10000, level + 1, chessboard, thinkstep, + BLACK, table); + if(k > alpha) { + alpha = k; + maxi = i; + maxj = j; + } + } + } + if(alpha != -10000) { + eat(maxi, maxj, WHITE, nowboard); + pass = 0; + nowx = maxi; + nowy = maxj; + } else { + move(23, 30); + prints("¹q¸£©ñ±ó³o¤@¨B´Ñ!!"); + pass++; + if(pass == 2) { + move(23, 24); + prints(" "); + end_of_game(0); + return false; + } + igetch(); + move(23, 24); + prints(" "); + } + return true; +} + +static int choose() { + char thinkstep[2]; + + move(2, 0); + prints("½Ð¿ï¾ÜÃø«×:"); + move(5, 0); + prints("(1) CD-65\n"); /* ·Q 1 ¨B */ + prints("(2) À¦¨à\n"); /* ·Q 3 ¨B */ + prints("(3) ¤p«Ä\n"); /* ·Q 4 ¨B */ + do { + getdata(4, 0, "½Ð¿ï¾Ü¤@Ó¹ï¶H©M±z¹ï¥´:(1~5)", thinkstep, 2, LCECHO); + } while(thinkstep[0] < '1' || thinkstep[0] > '3'); + clear(); + switch(thinkstep[0]) { + case '2': + thinkstep[0] = '3'; + break; + case '3': + thinkstep[0] = '4'; + break; + default: + thinkstep[0] = '1'; + break; + } + return atoi(thinkstep); +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 + +int othello_main() { + lockreturn0(OTHELLO, LOCK_MULTI); + clear(); + init(); + think = choose(); + showtitle("¶Â¥Õ´Ñ", BBSName); + printboard(); + which_table = rand() % NR_TABLE; + while(true) { + move(STARTX - 1, 30); + prints("½ü¨ì§A¤U¤F..."); + if(!player(BLACK)) + break; + report(); + othello_redraw(); + if(number[0] + number[1] == 64) { + end_of_game(0); + break; + } + move(STARTX - 1, 30); + prints("¹q¸£«ä¦Ò¤¤..."); + refresh(); + if(!Computer(think, which_table)) + break; + report(); + othello_redraw(); + if(number[0] + number[1] == 64) { + end_of_game(0); + break; + } + } + more(LOGFILE, YEA); + unlockutmpmode(); + return 1; +} diff --git a/mbbsd/page.c b/mbbsd/page.c new file mode 100644 index 00000000..c77ef421 --- /dev/null +++ b/mbbsd/page.c @@ -0,0 +1,130 @@ +/* $Id: page.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#define hpressanykey(a) {move(22, 0); prints(a); pressanykey();} +static void filt_railway(char* fpath) { + char buf[256], tmppath[32]; + FILE* fp = fopen(fpath, "w"), *tp; + + sprintf(tmppath, "%s.railway", fpath); + if(!fp || !(tp = fopen(tmppath, "r"))) + return; + + while(fgets(buf, 255, tp)) { + if(strstr(buf, "INLINE")) + continue; + if(strstr(buf, "LINK")) + break; + fprintf(fp, "%s", buf); + } + fclose(fp); + fclose(tp); + unlink(tmppath); +} + +extern userec_t cuser; + +int main_railway() { + fileheader_t mhdr; + char genbuf[200]; + int from, to, time_go, time_reach; + char tt[2], type[2]; + char command[256], buf[8]; + char *addr[]= { + "°ò¶©", "¤K°ô", "¤C°ô", "¤°ô", "¦Á¤î", "«n´ä", "ªQ¤s", "¥x¥_", "¸UµØ", + "ªO¾ô", "¾ðªL", "¤s¨Î", "Åaºq", "®ç¶é", "¤ºÃc", "¤¤Ãc", "®H¤ß", "·¨±ö", + "´ò¤f", "·sÂ×", "¦Ë¥_", "·s¦Ë", "»¤s", "±T³»", "¦Ë«n", "³y¾ô", "Â×´I", + "½Í¤å", "¤j¤s", "«áÀs", "Às´ä", "¥Õ¨F¤Ù", "·s®H", "³q¾]", "b¸Ì", + "¤é«n", "¤j¥Ò", "»O¤¤´ä", "²M¤ô", "¨F³À", "Às¤«", "¤j¨{", "°l¤À", + "]®ß", "«n¶Õ", "»ÉÆr", "¤T¸q", "³Ó¿³", "®õ¦w", "¦Z¨½", "Â×ì", "¼æ¤l", + "¥x¤¤", "¯Q¤é", "¦¨¥\\", "¹ü¤Æ", "ªá¾Â", "ûªL", "¥Ã¹t", "ªÀÀY", + "¥Ð¤¤", "¤G¤ô", "ªL¤º", "¥Ûºh", "¤æ¤»", "¤æ«n", "¥ÛÀt", "¤jªL", + "¥Á¶¯", "¹Å¸q", "¤ô¤W", "«n¹t", "«á¾À", "·sÀç", "¬hÀç", "ªL»ñÀç", + "¶©¥Ð", "©ÞªL", "µ½¤Æ", "·s¥«", "¥Ã±d", "¥x«n", "«O¦w", "¤¤¬w", + "¤j´ò", "¸ô¦Ë", "©£¤s", "¾ôÀY", "·£±ê", "¥ªÀç", "°ª¶¯", "»ñ¤s", + "¤E¦±°ó", "«ÌªF", NULL, NULL + }; + + setutmpmode(RAIL_WAY); + clear(); + move(0,25); + prints("\033[1;37;45m ¤õ¨®¬d¸ß¨t²Î \033[1;44;33m§@ªÌ:Heat\033[m"); + move(1,0); + outs("\033[1;33m + 1.°ò¶© 16.¤¤Ãc 31.Às´ä 46.»ÉÆr 61.¥Ð¤¤ 76.ªL»ñÀç 91.°ª¶¯ + 2.¤K°ô 17.®H¤ß 32.¥Õ¨F¤Ù 47.¤T¸q 62.¤G¤ô 77.¶©¥Ð 92.»ñ¤s + 3.¤C°ô 18.·¨±ö 33.·s®H 48.³Ó¿³ 63.ªL¤º 78.©ÞªL 93.¤E¦±°ó + 4.¤°ô 19.´ò¤f 34.³q¾] 49.®õ¦w 64.¥Ûºh 79.µ½¤Æ 94.«ÌªF + 5.¦Á¤î 20.·sÂ× 35.b¸Ì 50.¦Z¨½ 65.¤æ¤» 80.·s¥« + 6.«n´ä 21.¦Ë¥_ 36.¤é«n 51.Â×ì 66.¤æ«n 81.¥Ã±d + 7.ªQ¤s 22.·s¦Ë 37.¤j¥Ò 52.¼æ¤l 67.¥ÛÀt 82.¥x«n + 8.¥x¥_ 23.»¤s 38.»O¤¤´ä 53.¥x¤¤ 68.¤jªL 83.«O¦w + 9.¸UµØ 24.±T³» 39.²M¤ô 54.¯Q¤é 69.¥Á¶¯ 84.¤¤¬w +10.ªO¾ô 25.¦Ë«n 40.¨F³À 55.¦¨¥\\ 70.¹Å¸q 85.¤j´ò +11.¾ðªL 26.³y¾ô 41.Às¤« 56.¹ü¤Æ 71.¤ô¤W 86.¸ô¦Ë +12.¤s¨Î 27.Â×´I 42.¤j¨{ 57.ªá¾Â 72.«n¹t 87.©£¤s +13.Åaºq 28.½Í¤å 43.°l¤À 58.ûªL 73.«á¾À 88.¾ôÀY +14.®ç¶é 29.¤j¤s 44.]®ß 59.¥Ã¹t 74.·sÀç 89.·£±ê +15.¤ºÃc 30.«áÀs 45.«n¶Õ 60.ªÀÀY 75.¬hÀç 90.¥ªÀç\033[m"); + + getdata(17, 0, "\033[1;35m§A½T©wn·j´M¶Ü?[y/n]:\033[m", buf, 2, LCECHO); + if(buf[0] != 'y' && buf[0] != 'Y') + return 0; + while(1) + if(getdata(18, 0, "\033[1;35m½Ð¿é¤J°_¯¸(1-94):\033[m", buf, 3, LCECHO) && + (from = atoi(buf)) >= 1 && from <= 94) + break; + while(1) + if(getdata(18, 40, "\033[1;35m½Ð¿é¤J¥Øªº¦a(1-94):\033[m", + buf, 3, LCECHO) && + (to = atoi(buf)) >= 1 && to <= 94) + break; + while(1) + if(getdata(19, 0, "\033[1;35m½Ð¿é¤J®É¶¡°Ï¬q(0-23) ¥Ñ:\033[m", + buf,3,LCECHO) && + (time_go = atoi(buf)) >= 0 && time_go <= 23) + break; + while(1) + if(getdata(19, 40, "\033[1;35m¨ì:\033[m", buf, 3, LCECHO) && + (time_reach=atoi(buf)) >= 0 && time_reach <= 23) + break; + while(1) + if(getdata(20, 0, "\033[1;35m·Q¬d¸ß 1:¹ï¸¹§Ö¨® 2:´¶³q¥§Ö\033[m", + type,2,LCECHO) && (type[0] == '1' || type[0] == '2')) + break; + while(1) + if(getdata(21, 0, "\033[1;35m±ý¬d¸ß 1:¥Xµo®É¶¡ 2:¨ì¹F®É¶¡\033[m", + tt, 2, LCECHO) && + (tt[0]=='1' || tt[0]=='2')) + break; + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mhdr); + strcpy(mhdr.owner, "Ptt·j´M¾¹"); + strncpy(mhdr.title, "¤õ¨®®É¨è·j´Mµ²ªG", TTLEN); + mhdr.savemode = '\0'; + + sprintf(command,"echo \"from-station=%s&to-station=%s" + "&from-time=%02d00&to-time=%02d00&tt=%s&type=%s\" | " + "lynx -dump -post_data " + "\"http://www.railway.gov.tw/cgi-bin/timetk.cgi\" > %s.railway", + addr[from - 1], addr[to - 1], time_go, time_reach, + (tt[0] == '1') ? "start" : "arriv", + (type[0] == '1') ? "fast" : "slow", genbuf); + + system(command); + filt_railway(genbuf); + sethomedir(genbuf, cuser.userid); + if(append_record(genbuf, &mhdr, sizeof(mhdr)) == -1) + return -1; + hpressanykey("\033[1;31m§ÚÌ·|§â·j´Mµ²ªG«Ü§Ö´N±Hµ¹§Aò ^_^\033[m"); + return 0; +} diff --git a/mbbsd/passwd.c b/mbbsd/passwd.c new file mode 100644 index 00000000..28a31119 --- /dev/null +++ b/mbbsd/passwd.c @@ -0,0 +1,138 @@ +/* $Id: passwd.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "proto.h" + +extern char *fn_passwd; + +static userec_t *passwd_image = NULL; +static int passwd_image_size; +static int semid = -1; + +#ifndef SEM_R +#define SEM_R 0400 +#endif + +#ifndef SEM_A +#define SEM_A 0200 +#endif + +#ifndef __FreeBSD__ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + u_short *array; /* array for GETALL & SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif + +int passwd_mmap() { + int fd; + + fd = open(fn_passwd, O_RDWR); + if(fd > 0) + { + struct stat st; + + fstat(fd, &st); + passwd_image_size = st.st_size; + passwd_image = mmap(NULL, passwd_image_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if(passwd_image == (userec_t *)-1) { + perror("mmap"); + return -1; + } +/* rocker 011018: after success get mmap, close file descript */ + close (fd); + + semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A | IPC_CREAT | IPC_EXCL); + if(semid == -1) { + if(errno == EEXIST) { + semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A); + if(semid == -1) { + perror("semget"); + exit(1); + } + } else { + perror("semget"); + exit(1); + } + } else { + union semun s; + + s.val = 1; + if(semctl(semid, 0, SETVAL, s) == -1) { + perror("semctl"); + exit(1); + } + } + } else { + perror(fn_passwd); + return -1; + } + return 0; +} + +extern int usernum; +int passwd_update_money(int num) { + int money; + if(num < 1 || num > MAX_USERS) + return -1; + money = moneyof(num); + memcpy(&passwd_image[num - 1].money, &money, sizeof(int)); + return 0; +} + +int passwd_update(int num, userec_t *buf) { + if(num < 1 || num > MAX_USERS) + return -1; + buf->money = moneyof(num); + memcpy(&passwd_image[num - 1], buf, sizeof(userec_t)); + return 0; +} + +int passwd_query(int num, userec_t *buf) { + if(num < 1 || num > MAX_USERS) + return -1; + memcpy(buf, &passwd_image[num - 1], sizeof(userec_t)); + return 0; +} + +int passwd_apply(int (*fptr)(userec_t *)) { + int i; + + for(i = 0; i < MAX_USERS; i++) + if((*fptr)(&passwd_image[i]) == QUIT) + return QUIT; + return 0; +} + +void passwd_lock() { + struct sembuf buf = { 0, -1, SEM_UNDO }; + + if(semop(semid, &buf, 1)) { + perror("semop"); + exit(1); + } +} + +void passwd_unlock() { + struct sembuf buf = { 0, 1, SEM_UNDO }; + + if(semop(semid, &buf, 1)) { + perror("semop"); + exit(1); + } +} diff --git a/mbbsd/read.c b/mbbsd/read.c new file mode 100644 index 00000000..b92f95e7 --- /dev/null +++ b/mbbsd/read.c @@ -0,0 +1,998 @@ +/* $Id: read.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +#define MAXPATHLEN 256 + +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char currowner[IDLEN + 2]; +extern char currtitle[44]; +extern char currauthor[IDLEN + 2]; +extern char *str_reply; +extern char *msg_fwd_ok; +extern char *msg_fwd_err1; +extern char *msg_fwd_err2; +extern int currmode; +extern unsigned int currstat; +extern char currboard[]; /* name of currently selected board */ +extern int KEY_ESC_arg; +extern int curredit; +extern char *msg_mailer; +extern int currbid; +extern bcache_t *brdshm; + +char currdirect[64]; +static fileheader_t *headers = NULL; +static int last_line; +static int hit_thread; + +/* rocker.011018: add new tag */ + +extern int rget(); +extern char getans(); +extern void touchdircache(); +extern int get_fileheader_cache(); + +/* rocker.011018: ·sªºtag¤è¦¡ */ + +#define MAXTAGS 256 + +#include <sys/mman.h> + +typedef struct +{ + time_t chrono; + int recno; +} TagItem; + + +/* ----------------------------------------------------- */ +/* Tag List ¼ÐÅÒ */ +/* ----------------------------------------------------- */ + + +int TagNum; /* tag's number */ +TagItem TagList[MAXTAGS]; /* ascending list */ + +void +UnTagger (int locus) +{ + if (locus > TagNum) return; + + TagNum--; + + if (TagNum > locus) + memcpy(&TagList[locus], &TagList[locus + 1], + (TagNum - locus) * sizeof(TagItem)); +} + +int +Tagger(time_t chrono, int recno, int mode) +{ + int head, tail, posi = 0, comp; + + for (head = 0, tail = TagNum - 1, comp = 1; head <= tail;) + { + posi = (head + tail) >> 1; + comp = TagList[posi].chrono - chrono; + if (!comp) + { + break; + } + else if (comp < 0) + { + head = posi + 1; + } + else + { + tail = posi - 1; + } + } + + if (mode == TAG_NIN) + { + if (!comp && recno) /* µ´¹ïÄYÂÔ¡G³s recno ¤@°_¤ñ¹ï */ + comp = recno - TagList[posi].recno; + return comp; + + } + + if (!comp) + { + if (mode != TAG_TOGGLE) + return NA; + + TagNum--; + memcpy(&TagList[posi], &TagList[posi + 1], + (TagNum - posi) * sizeof(TagItem)); + } + else if (TagNum < MAXTAGS) + { + TagItem *tagp, buf[MAXTAGS]; + + tail = (TagNum - head) * sizeof(TagItem); + tagp = &TagList[head]; + memcpy(buf, tagp, tail); + tagp->chrono = chrono; + tagp->recno = recno; + memcpy(++tagp, buf, tail); + TagNum++; + } + else + { + bell(); + return 0; /* full */ + } + return YEA; +} + + +void +EnumTagName( char *fname, int locus) +{ + sprintf(fname, "M.%d.A", (int) TagList[locus].chrono); +} + +void +EnumTagFhdr(fileheader_t *fhdr, char *direct, int locus) +{ + get_record(direct, fhdr, sizeof(fileheader_t), TagList[locus].recno); +} + +/* -1 : ¨ú®ø */ +/* 0 : single article */ +/* ow: whole tag list */ + +int +AskTag(char *msg) +{ + char buf[80]; + int num; + + num = TagNum; + sprintf(buf, "¡» %s A)¤å³¹ T)¼Ð°O Q)uit?", msg); + switch (rget(b_lines-1, buf)) + { + case 'q': + num = -1; + break; + case 'a': + num = 0; + } + return num; +} + + +#include <sys/mman.h> + +#define BATCH_SIZE 65536 + +char * +f_map (char *fpath, int *fsize) +{ + int fd, size; + struct stat st; + + if ((fd = open(fpath, O_RDONLY)) < 0) + return (char *) -1; + + if (fstat(fd, &st) || !S_ISREG(st.st_mode) || (size = st.st_size) <= 0) + { + close(fd); + return (char *) -1; + } + + fpath = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + *fsize = size; + return fpath; +} + + +static int +TagThread(char *direct) +{ + int fsize, count; + char *title, *fimage; + fileheader_t *head, *tail; + + fimage = f_map(direct, &fsize); + if ( fimage == (char *) -1) + return DONOTHING; + + head = (fileheader_t *) fimage; + tail = (fileheader_t *) (fimage + fsize); + count = 0; + do + { + count++; + title = subject(head->title); + if (!strncmp( currtitle, title,TTLEN)) + { + if (!Tagger(atoi (head->filename + 2), count, TAG_INSERT)) + break; + } + } while (++head < tail); + + munmap(fimage, fsize); + return FULLUPDATE; +} + + +int +TagPruner(int bid) +{ + if (TagNum && ((currstat != READING) || (currmode & MODE_BOARD))) + { + if(getans("§R°£©Ò¦³¼Ð°O[N]?") != 'y') + return FULLUPDATE; + delete_range(currdirect, 0, 0); + TagNum = 0; + if(bid>0); + setbtotal(bid); + return NEWDIRECT; + } + return DONOTHING; +} + + +/* ----------------------------------------------------- */ +/* cursor & reading record position control */ +/* ----------------------------------------------------- */ +keeploc_t *getkeep(char *s, int def_topline, int def_cursline) { + static struct keeploc_t *keeplist = NULL; + struct keeploc_t *p; + void *malloc(); + + if(def_cursline >= 0) + for(p = keeplist; p; p = p->next) { + if(!strcmp(s, p->key)) { + if(p->crs_ln < 1) + p->crs_ln = 1; + return p; + } + } + else + def_cursline = -def_cursline; + p = (keeploc_t *)malloc(sizeof(keeploc_t)); + p->key = (char *)malloc(strlen(s) + 1); + strcpy(p->key, s); + p->top_ln = def_topline; + p->crs_ln = def_cursline; + p->next = keeplist; + return (keeplist = p); +} + +void fixkeep(char *s, int first) { + keeploc_t *k; + + k = getkeep(s, 1, 1); + if(k->crs_ln >= first) { + k->crs_ln = (first == 1 ? 1 : first - 1); + k->top_ln = (first < 11 ? 1 : first - 10); + } +} + +/* calc cursor pos and show cursor correctly */ +static int cursor_pos(keeploc_t *locmem, int val, int from_top) { + int top; + + if(val > last_line) { + bell(); + val = last_line; + } + if(val <= 0) { + bell(); + val = 1; + } + + top = locmem->top_ln; + if(val >= top && val < top + p_lines) { + cursor_clear(3 + locmem->crs_ln - top, 0); + locmem->crs_ln = val; + cursor_show(3 + val - top, 0); + return DONOTHING; + } + locmem->top_ln = val - from_top; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = val; + return PARTUPDATE; +} + +static int move_cursor_line(keeploc_t *locmem, int mode) { + int top, crs; + int reload = 0; + + top = locmem->top_ln; + crs = locmem->crs_ln; + if(mode == READ_PREV) { + if(crs <= top) { + top -= p_lines - 1; + if(top < 1) + top = 1; + reload = 1; + } + if(--crs < 1) { + crs = 1; + reload = -1; + } + } else if(mode == READ_NEXT) { + if(crs >= top + p_lines - 1) { + top += p_lines - 1; + reload = 1; + } + if(++crs > last_line) { + crs = last_line; + reload = -1; + } + } + locmem->top_ln = top; + locmem->crs_ln = crs; + return reload; +} + +static int thread(keeploc_t *locmem, int stype) { + static char a_ans[32], t_ans[32]; + char ans[32], s_pmt[64]; + register char *tag, *query = NULL; + register int now, pos, match, near = 0; + fileheader_t fh; + int circulate_flag = 1; /* circulate at end or begin */ + + match = hit_thread = 0; + now = pos = locmem->crs_ln; + if(stype == 'A') { + if(!*currowner) + return DONOTHING; + str_lower(a_ans, currowner); + query = a_ans; + circulate_flag = 0; + stype = 0; + } else if(stype == 'a') { + if(!*currowner) + return DONOTHING; + str_lower(a_ans, currowner); + query = a_ans; + circulate_flag = 0; + stype = RS_FORWARD; + } else if(stype == '/') { + if(!*t_ans) + return DONOTHING; + query = t_ans; + circulate_flag = 0; + stype = RS_TITLE | RS_FORWARD; + } else if(stype == '?') { + if(!*t_ans) + return DONOTHING; + circulate_flag = 0; + query = t_ans; + stype = RS_TITLE; + } else if(stype & RS_RELATED) { + tag = headers[pos - locmem->top_ln].title; + if(stype & RS_CURRENT) { + if(stype & RS_FIRST) { + if(!strncmp(currtitle, tag, 40)) + return DONOTHING; + near = 0; + } + query = currtitle; + } else { + query = subject(tag); + if(stype & RS_FIRST) { + if(query == tag) + return DONOTHING; + near = 0; + } + } + } else if(!(stype & RS_THREAD)) { + query = (stype & RS_TITLE) ? t_ans : a_ans; + if(!*query && query == a_ans) { + if(*currowner) + strcpy(a_ans, currowner); + else if (*currauthor) + strcpy(a_ans, currauthor); + } + sprintf(s_pmt, "%s·j´M%s [%s] ",(stype & RS_FORWARD) ? "©¹«á":"©¹«e", + (stype & RS_TITLE) ? "¼ÐÃD" : "§@ªÌ", query); + getdata(b_lines - 1, 0, s_pmt, ans, 30, DOECHO); + if(*ans) + strcpy(query, ans); + else if(*query == '\0') + return DONOTHING; + } + + tag = fh.owner; + + do { + if(!circulate_flag || stype & RS_RELATED) { + if(stype & RS_FORWARD) { + if(++now > last_line) + return DONOTHING; + } else { + if(--now <= 0) { + if((stype & RS_FIRST) && (near)) { + hit_thread = 1; + return cursor_pos(locmem, near, 10); + } + return DONOTHING; + } + } + } else { + if(stype & RS_FORWARD) { + if(++now > last_line) + now = 1; + } else if(--now <= 0) + now = last_line; + } + + get_record(currdirect, &fh, sizeof(fileheader_t), now); + + if(fh.owner[0] == '-') + continue; + + if(stype & RS_THREAD) { + if(strncasecmp(fh.title, str_reply, 3)) { + hit_thread = 1; + return cursor_pos(locmem, now, 10); + } + continue; + } + + if(stype & RS_TITLE) + tag = subject(fh.title); + + if(((stype & RS_RELATED) && !strncmp(tag, query, 40)) || + (!(stype & RS_RELATED) && ((query == currowner) ? + !strcmp(tag, query) : + strstr_lower(tag, query)))) { + if((stype & RS_FIRST) && tag != fh.title) { + near = now; + continue; + } + + hit_thread = 1; + match = cursor_pos(locmem, now, 10); + if((!(stype & RS_CURRENT)) && + (stype & RS_RELATED) && + strncmp(currtitle, query, 40)) { + strncpy(currtitle, query, 40); + match = PARTUPDATE; + } + break; + } + } while(now != pos); + + return match; +} + + +#ifdef INTERNET_EMAIL +static void mail_forward(fileheader_t *fhdr, char *direct, int mode) { + int i; + char buf[STRLEN]; + char *p; + + strncpy(buf, direct, sizeof(buf)); + if((p = strrchr(buf, '/'))) + *p = '\0'; + switch(i = doforward(buf, fhdr, mode)) { + case 0: + outmsg(msg_fwd_ok); + break; + case -1: + outmsg(msg_fwd_err1); + break; + case -2: + outmsg(msg_fwd_err2); + break; + default: + break; + } + refresh(); + sleep(1); +} +#endif + +extern userec_t cuser; + +static int select_read(keeploc_t *locmem, int sr_mode) { + register char *tag,*query,*temp; + fileheader_t fh; + char fpath[80], genbuf[MAXPATHLEN], buf3[5]; + char static t_ans[TTLEN+1]=""; + char static a_ans[IDLEN+1]=""; + int fd, fr, size = sizeof(fileheader_t); + struct stat st; +/* rocker.011018: make a reference number for process article */ + int reference = 0; + + if((currmode & MODE_SELECT)) + return -1; + if(sr_mode == RS_TITLE) + query = subject(headers[locmem->crs_ln - locmem->top_ln].title); + else if(sr_mode == RS_NEWPOST) + { + strcpy(buf3, "Re: "); + query = buf3; + } + else + { + char buff[80]; + + query = (sr_mode == RS_RELATED) ? t_ans : a_ans; + sprintf(buff, "·j´M%s [%s] ", + (sr_mode == RS_RELATED) ? "¼ÐÃD" : "§@ªÌ", query); + getdata(b_lines, 0,buff, query, 30, DOECHO); + if(!(*query)) + return DONOTHING; + } + + if((fd = open(currdirect, O_RDONLY, 0)) != -1) { + sprintf(genbuf,"SR.%s",cuser.userid); + if(currstat==RMAIL) + sethomefile(fpath,cuser.userid,genbuf); + else + setbfile(fpath,currboard,genbuf); + if(((fr = open(fpath,O_WRONLY | O_CREAT | O_TRUNC,0600)) != -1)) { + switch(sr_mode) { + case RS_TITLE: + while(read(fd,&fh,size) == size) { + ++reference; + tag = subject(fh.title); + if(!strncmp(tag, query, 40)) + { + fh.money = reference | FHR_REFERENCE; + write(fr,&fh,size); + } + } + break; + case RS_RELATED: + while(read(fd,&fh,size) == size) { + ++reference; + tag = fh.title; + if(strcasestr(tag,query)) + { + fh.money = reference | FHR_REFERENCE; + write(fr,&fh,size); + } + } + break; + case RS_NEWPOST: + while(read(fd, &fh, size) == size) { + ++reference; + tag = fh.title; + temp = strstr(tag, query); + if(temp == NULL || temp != tag) + { + write(fr, &fh, size); + fh.money = reference | FHR_REFERENCE; + } + } + case RS_AUTHOR: + while(read(fd,&fh,size) == size) { + ++reference; + tag = fh.owner; + if(strcasestr(tag,query)) + { + write(fr,&fh,size); + fh.money = reference | FHR_REFERENCE; + } + } + break; + } + fstat(fr,&st); + close(fr); + } + close(fd); + if(st.st_size) { + currmode |= MODE_SELECT; + strcpy(currdirect,fpath); + } + } + return st.st_size; +} + +extern userec_t xuser; + +static int i_read_key(onekey_t *rcmdlist, keeploc_t *locmem, int ch, int bid) { + int i, mode = DONOTHING; + + switch(ch) { + case 'q': + case 'e': + case KEY_LEFT: + return (currmode & MODE_SELECT) ? board_select() : + (currmode & MODE_ETC) ? board_etc() : + (currmode & MODE_DIGEST) ? board_digest() : DOQUIT; + case Ctrl('L'): + redoscr(); + break; +/* + case Ctrl('C'): + cal(); + return FULLUPDATE; + break; +*/ + case KEY_ESC: + if(KEY_ESC_arg == 'i') { + t_idle(); + return FULLUPDATE; + } + break; + case Ctrl('H'): + if(select_read(locmem, RS_NEWPOST)) + return NEWDIRECT; + else + return READ_REDRAW; + case 'a': + case 'A': + if(select_read(locmem,RS_AUTHOR)) + return NEWDIRECT; + else + return READ_REDRAW; + case '/': + case '?': + if(select_read(locmem,RS_RELATED)) + return NEWDIRECT; + else + return READ_REDRAW; + case 'S': + if(select_read(locmem,RS_TITLE)) + return NEWDIRECT; + else + return READ_REDRAW; + /* quick search title first */ + case '=': + return thread(locmem, RELATE_FIRST); + case '\\': + return thread(locmem, CURSOR_FIRST); + /* quick search title forword */ + case ']': + return thread(locmem, RELATE_NEXT); + case '+': + return thread(locmem, CURSOR_NEXT); + /* quick search title backword */ + case '[': + return thread(locmem, RELATE_PREV); + case '-': + return thread(locmem, CURSOR_PREV); + case '<': + case ',': + return thread(locmem, THREAD_PREV); + case '.': + case '>': + return thread(locmem, THREAD_NEXT); + case 'p': + case 'k': + case KEY_UP: + return cursor_pos(locmem, locmem->crs_ln - 1, p_lines - 2); + case 'n': + case 'j': + case KEY_DOWN: + return cursor_pos(locmem, locmem->crs_ln + 1, 1); + case ' ': + case KEY_PGDN: + case 'N': + case Ctrl('F'): + if(last_line >= locmem->top_ln + p_lines) { + if(last_line > locmem->top_ln + p_lines) + locmem->top_ln += p_lines; + else + locmem->top_ln += p_lines - 1; + locmem->crs_ln = locmem->top_ln; + return PARTUPDATE; + } + cursor_clear(3 + locmem->crs_ln - locmem->top_ln, 0); + locmem->crs_ln = last_line; + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + break; + case KEY_PGUP: + case Ctrl('B'): + case 'P': + if(locmem->top_ln > 1) { + locmem->top_ln -= p_lines; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = locmem->top_ln; + return PARTUPDATE; + } + break; + case KEY_END: + case '$': + if(last_line >= locmem->top_ln + p_lines) { + locmem->top_ln = last_line - p_lines + 1; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = last_line; + return PARTUPDATE; + } + cursor_clear(3 + locmem->crs_ln - locmem->top_ln, 0); + locmem->crs_ln = last_line; + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + break; + case 'F': + case 'U': + if(HAS_PERM(PERM_FORWARD)) { + mail_forward(&headers[locmem->crs_ln - locmem->top_ln], + currdirect, ch /*== 'U'*/); + /*by CharlieL*/ + return FULLUPDATE; + } + break; + case Ctrl('Q'): + return my_query(headers[locmem->crs_ln - locmem->top_ln].owner); + case Ctrl('S'): + if(HAS_PERM(PERM_ACCOUNTS)) { + int id; + userec_t muser; + + strcpy(currauthor, headers[locmem->crs_ln - locmem->top_ln].owner); + stand_title("¨Ï¥ÎªÌ³]©w"); + move(1, 0); + if((id = getuser(headers[locmem->crs_ln - locmem->top_ln].owner))){ + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } + return FULLUPDATE; + } + break; + +/* rocker.011018: ±Ä¥Î·sªºtag¼Ò¦¡ */ + case 't': +/* rocker.011112: ¸Ñ¨M¦Aselect mode¼Ð°O¤å³¹ªº°ÝÃD */ + if (Tagger(atoi(headers[locmem->crs_ln - locmem->top_ln].filename + 2), + (currmode & MODE_SELECT) ? + (headers[locmem->crs_ln - locmem->top_ln].money & ~FHR_REFERENCE) : + locmem->crs_ln, TAG_TOGGLE)) + return POS_NEXT; + return DONOTHING; + + case Ctrl('C'): + if (TagNum) + { + TagNum = 0; + return FULLUPDATE; + } + return DONOTHING; + + case Ctrl('T'): + return TagThread(currdirect); + case Ctrl('D'): + return TagPruner(bid); + case '\n': + case '\r': + case 'l': + case KEY_RIGHT: + ch = 'r'; + default: + for(i = 0; rcmdlist[i].fptr; i++) { + if(rcmdlist[i].key == ch) { + mode = (*(rcmdlist[i].fptr))(locmem->crs_ln, + &headers[locmem->crs_ln - + locmem->top_ln], currdirect); + break; + } + if(rcmdlist[i].key == 'h') + if(currmode & (MODE_ETC | MODE_DIGEST)) + return DONOTHING; + } + } + return mode; +} + +void i_read(int cmdmode, char *direct, void (*dotitle)(), void (*doentry)(), onekey_t *rcmdlist, int bidcache) { + keeploc_t *locmem = NULL; + int recbase = 0, mode, ch; + int num = 0, entries = 0; + int i; + int jump = 0; + char genbuf[4]; + char currdirect0[64]; + int last_line0 = last_line; + int hit_thread0 = hit_thread; + fileheader_t *headers0 = headers; + + strcpy(currdirect0 ,currdirect); +#define FHSZ sizeof(fileheader_t) +// Ptt:³oÃäheaders ¥i¥H°w¹ï¬ÝªOªº³Ì«á60½g°µcache + headers = (fileheader_t *)calloc(p_lines, FHSZ); + strcpy(currdirect, direct); + mode = NEWDIRECT; + +/* rocker.011018: ¥[¤J·sªºtag¾÷¨î */ + TagNum = 0; + + do { + /* ¨Ì¾Ú mode Åã¥Ü fileheader */ + setutmpmode(cmdmode); + switch(mode) { + case NEWDIRECT: /* ²Ä¤@¦¸¸ü¤J¦¹¥Ø¿ý */ + case DIRCHANGED: + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST)) ) + last_line=getbtotal(currbid); + else + last_line= get_num_records(currdirect, FHSZ); + + if(mode == NEWDIRECT) { + if(last_line == 0) { + if(curredit & EDIT_ITEM) { + outs("¨S¦³ª««~"); + refresh(); + goto return_i_read; + } else if(curredit & EDIT_MAIL) { + outs("¨S¦³¨Ó«H"); + refresh(); + goto return_i_read; + } else if(currmode & MODE_ETC) { + board_etc(); /* Kaede */ + outmsg("©|¥¼¦¬¿ý¨ä¥¦¤å³¹"); + refresh(); + } else if(currmode & MODE_DIGEST) { + board_digest(); /* Kaede */ + outmsg("©|¥¼¦¬¿ý¤åºK"); + refresh(); + } else if(currmode & MODE_SELECT) { + board_select(); /* Leeym */ + outmsg("¨S¦³¦¹¨t¦Cªº¤å³¹"); + refresh(); + } else { + getdata(b_lines - 1, 0, + "¬ÝªO·s¦¨¥ß (P)µoªí¤å³¹ (Q)Â÷¶}¡H[Q] ", + genbuf, 4, LCECHO); + if(genbuf[0] == 'p') + do_post(); + goto return_i_read; + } + } + num = last_line - p_lines + 1; + locmem = getkeep(currdirect, num < 1 ? 1 : num, last_line); + } + recbase = -1; + + case FULLUPDATE: + (*dotitle)(); + + case PARTUPDATE: + if(last_line < locmem->top_ln + p_lines) { + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST))) + num=getbtotal(currbid); + else + num = get_num_records(currdirect, FHSZ); + + if(last_line != num) { + last_line = num; + recbase = -1; + } + } + + if(last_line == 0) + goto return_i_read; + else if(recbase != locmem->top_ln) { + recbase = locmem->top_ln; + if(recbase > last_line) { + recbase = (last_line - p_lines) >> 1; + if(recbase < 1) + recbase = 1; + locmem->top_ln = recbase; + } + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST)) + && (last_line - recbase) < DIRCACHESIZE ) + entries = get_fileheader_cache(currbid, currdirect, headers, + recbase, p_lines); + else + entries = get_records(currdirect, headers, FHSZ, recbase, + p_lines); + } + if(locmem->crs_ln > last_line) + locmem->crs_ln = last_line; + move(3, 0); + clrtobot(); + case PART_REDRAW: + move(3, 0); + for (i = 0; i < entries; i++) + (*doentry) (locmem->top_ln + i, &headers[i]); + case READ_REDRAW: + outmsg(curredit & EDIT_ITEM ? + "\033[44m ¨p¤H¦¬Âà \033[30;47m Ä~Äò? \033[m" : + curredit & EDIT_MAIL ? msg_mailer : MSG_POSTER); + break; + case READ_PREV: + case READ_NEXT: + case RELATE_PREV: + case RELATE_NEXT: + case RELATE_FIRST: + case POS_NEXT: + case 'A': + case 'a': + case '/': + case '?': + jump = 1; + break; + } + + /* Ū¨úÁä½L¡A¥[¥H³B²z¡A³]©w mode */ + if(!jump) { + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + ch = egetch(); + mode = DONOTHING; + } else + ch = ' '; + + if(mode == POS_NEXT) { + mode = cursor_pos(locmem, locmem->crs_ln + 1, 1); + if(mode == DONOTHING) + mode = PART_REDRAW; + jump = 0; + } else if(ch >= '0' && ch <= '9') { + if((i = search_num(ch, last_line)) != -1) + mode = cursor_pos(locmem, i + 1, 10); + } else { + if(!jump) + mode = i_read_key(rcmdlist, locmem, ch, currbid); + while(mode == READ_NEXT || mode == READ_PREV || + mode == RELATE_FIRST || mode == RELATE_NEXT || + mode == RELATE_PREV || mode == THREAD_NEXT || + mode == THREAD_PREV || mode == 'A' || mode == 'a' || + mode == '/' || mode == '?') { + int reload; + + if(mode == READ_NEXT || mode == READ_PREV) + reload = move_cursor_line(locmem, mode); + else { + reload = thread(locmem, mode); + if(!hit_thread) { + mode = FULLUPDATE; + break; + } + } + + if(reload == -1) { + mode = FULLUPDATE; + break; + } else if(reload) { + recbase = locmem->top_ln; + + if(bidcache>0 && !(currmode &(MODE_SELECT| MODE_DIGEST)) + && last_line-recbase<DIRCACHESIZE ) + entries = get_fileheader_cache(currbid, currdirect, + headers, recbase, p_lines); + else + entries = get_records(currdirect, headers, FHSZ, recbase, + p_lines); + + if(entries <= 0) { + last_line = -1; + break; + } + } + num = locmem->crs_ln - locmem->top_ln; + if(headers[num].owner[0] != '-') + mode = i_read_key(rcmdlist, locmem, ch, bidcache); + } + } + } while(mode != DOQUIT); +#undef FHSZ + + return_i_read: + free(headers); + last_line = last_line0; + hit_thread = hit_thread0; + headers = headers0; + strcpy(currdirect ,currdirect0); + return; +} diff --git a/mbbsd/record.c b/mbbsd/record.c new file mode 100644 index 00000000..59bc6a75 --- /dev/null +++ b/mbbsd/record.c @@ -0,0 +1,536 @@ +/* $Id: record.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "proto.h" + +#undef HAVE_MMAP +#define BUFSIZE 512 + +extern char *str_reply; + +static void PttLock(int fd, int size, int mode) { + static struct flock lock_it; + int ret; + + lock_it.l_whence = SEEK_CUR; /* from current point */ + lock_it.l_start = 0; /* -"- */ + lock_it.l_len = size; /* length of data */ + lock_it.l_type = mode; /* set exclusive/write lock */ + lock_it.l_pid = 0; /* pid not actually interesting */ + while((ret = fcntl(fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR); +} + +#define safewrite write + +int get_num_records(char *fpath, int size) { + struct stat st; + if(stat(fpath, &st) == -1) + return 0; + return st.st_size / size; +} + +int get_sum_records(char* fpath, int size) { + struct stat st; + long ans = 0; + FILE* fp; + fileheader_t fhdr; + char buf[200], *p; + + if(!(fp = fopen(fpath, "r"))) + return -1; + + strcpy(buf, fpath); + p = strrchr(buf, '/') + 1; + + while(fread(&fhdr, size, 1, fp) == 1) { + strcpy(p, fhdr.filename); + if(stat(buf, &st) == 0 && S_ISREG(st.st_mode) && st.st_nlink == 1) + ans += st.st_size; + } + fclose(fp); + return ans / 1024; +} + +int get_record(char *fpath, void *rptr, int size, int id) { + int fd = -1; + + if(id < 1 || (fd = open(fpath, O_RDONLY, 0)) != -1) { + if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) != -1) { + if(read(fd, rptr, size) == size) { + close(fd); + return 0; + } + } + close(fd); + } + return -1; +} + +int get_records(char *fpath, void *rptr, int size, int id, int number) { + int fd; + + if(id < 1 || (fd = open(fpath, O_RDONLY, 0)) == -1) + return -1; + + if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) == -1) { + close(fd); + return 0; + } + if((id = read(fd, rptr, size * number)) == -1) { + close(fd); + return -1; + } + close(fd); + return id / size; +} + +int substitute_record(char *fpath, void *rptr, int size, int id) { + int fd; + + if(id < 1 || (fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) + return -1; + + lseek(fd, (off_t) (size * (id - 1)), SEEK_SET); + PttLock(fd, size, F_WRLCK); + safewrite(fd, rptr, size); + PttLock(fd, size, F_UNLCK); + close(fd); + + return 0; +} + +/* rocker.011022: ÁקKlockÀɶ}±Ò®É¤£¥¿±`Â_½u,³y¦¨¥Ã¤[lock */ +static int +force_open (char *fname) +{ + int fd; + time_t expire; + + expire = time(NULL) - 3600; /* lock ¦s¦b¶W¹L¤@Ó¤p®É´N¬O¦³°ÝÃD! */ + + if (dasht (fname) < expire) return -1; + unlink(fname); + fd = open (fname, O_WRONLY|O_TRUNC, 0644); + + return fd; +} + + +#if !defined(_BBS_UTIL_C_) +/* new/old/lock file processing */ +typedef struct nol_t { + char newfn[256]; + char oldfn[256]; + char lockfn[256]; +} nol_t; + +static void nolfilename(nol_t *n, char *fpath) { + sprintf(n->newfn, "%s.new", fpath); + sprintf(n->oldfn, "%s.old", fpath); + sprintf(n->lockfn, "%s.lock", fpath); +} + +int delete_record(char fpath[], int size, int id) { + nol_t my; + char abuf[BUFSIZE]; + int fdr, fdw, fd; + int count; + + nolfilename(&my, fpath); + if((fd = open(my.lockfn, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1) + return -1; + + flock(fd, LOCK_EX); + + if((fdr = open(fpath, O_RDONLY, 0)) == -1) { + move(10,10); + outs("delete_record failed!!! (open)"); + pressanykey(); + flock(fd, LOCK_UN); + close(fd); + return -1; + } + + if( + ((fdw = open(my.newfn, O_WRONLY | O_CREAT | O_EXCL, 0644)) == -1) && + ((fdw = force_open (my.newfn)) == -1)) { + flock(fd, LOCK_UN); + close(fd); + close(fdr); + return -1; + } + count = 1; + while(read(fdr, abuf, size) == size) { + if(id != count++ && (safewrite(fdw, abuf, size) == -1)) { + unlink(my.newfn); + close(fdr); + close(fdw); + flock(fd, LOCK_UN); + close(fd); + return -1; + } + } + close(fdr); + close(fdw); + if(Rename(fpath, my.oldfn) == -1 || Rename(my.newfn, fpath) == -1) { + flock(fd, LOCK_UN); + close(fd); + return -1; + } + flock(fd, LOCK_UN); + close(fd); + return 0; +} + +static char *title_body(char *title) { + if(!strncasecmp(title, str_reply, 3)) { + title += 3; + if(*title == ' ') + title++; + } + return title; +} + +int delete_range(char *fpath, int id1, int id2) { + fileheader_t fhdr; + nol_t my; + char fullpath[STRLEN], *t; + int fdr, fdw, fd; + int count; + extern int Tagger(); + + nolfilename(&my, fpath); + + if((fd = open(my.lockfn, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1) + return -1; + + flock(fd, LOCK_EX); + + if((fdr = open(fpath, O_RDONLY, 0)) == -1) { + flock(fd, LOCK_UN); + close(fd); + return -1; + } + + if( + ((fdw = open(my.newfn, O_WRONLY | O_CREAT | O_EXCL, 0644)) == -1) && + ((fdw = force_open (my.newfn)) == -1)) { + close(fdr); + flock(fd, LOCK_UN); + close(fd); + return -1; + } + + count = 1; + strcpy(fullpath, fpath); + t = strrchr(fullpath, '/') + 1; + + while(read(fdr, &fhdr, sizeof(fileheader_t)) == sizeof(fileheader_t)) + { + strcpy(t, fhdr.filename); + +/* rocker.011018: add new tag delete */ + if ( + (fhdr.filemode & FILE_MARKED) || /* ¼Ð°O */ + (fhdr.filemode & FILE_DIGEST) || /* ¤åºK */ + (id1 && (count < id1 || count > id2)) || /* range */ + (!id1 && Tagger(atoi (t + 2), count, TAG_NIN))) /* TagList */ + { + if((safewrite(fdw, &fhdr, sizeof(fileheader_t)) == -1)) { + close(fdr); + close(fdw); + unlink(my.newfn); + flock(fd, LOCK_UN); + close(fd); + return -1; + } + } + else + { + //if(dashd(fullpath)) + unlink(fullpath); + } + ++count; + } + close(fdr); + close(fdw); + if(Rename(fpath, my.oldfn) == -1 || Rename(my.newfn, fpath) == -1) { + flock(fd, LOCK_UN); + close(fd); + return -1; + } + flock(fd, LOCK_UN); + close(fd); + return 0; +} + +int search_rec(char* dirname, int (*filecheck)()) { + fileheader_t fhdr; + FILE *fp; + int ans = 0; + + if(!(fp = fopen(dirname, "r"))) + return 0; + + while(fread(&fhdr, sizeof(fhdr), 1, fp)) { + ans++; + if((*filecheck) (&fhdr)) { + fclose(fp); + return ans; + } + } + fclose(fp); + return 0; +} + +int delete_files(char* dirname, int (*filecheck)(), int record) { + fileheader_t fhdr; + FILE *fp, *fptmp; + int ans = 0; + char tmpfname[128]; + char genbuf[256]; + char deleted[256]; + fileheader_t delfh; + char deletedDIR[] = "boards/deleted/.DIR"; + + strcpy(deleted, "boards/deleted"); + + if(!(fp = fopen(dirname, "r"))) + return ans; + + strcpy(tmpfname, dirname); + strcat(tmpfname, "_tmp"); + + if(!(fptmp = fopen(tmpfname, "w"))) { + fclose(fp); + return ans; + } + + while(fread(&fhdr, sizeof(fhdr), 1, fp)){ + if((*filecheck)(&fhdr)) { + ans++; + setdirpath(genbuf, dirname, fhdr.filename); + if (record){ + deleted[14] = '\0'; + stampfile(deleted, &delfh); + strcpy(delfh.owner, fhdr.owner); + strcpy(delfh.title, fhdr.title); + Link(genbuf, deleted); + append_record(deletedDIR, &delfh, sizeof(delfh)); + } + unlink(genbuf); + } else + fwrite(&fhdr, sizeof(fhdr), 1, fptmp); + } + + fclose(fp); + fclose(fptmp); + unlink(dirname); + Rename(tmpfname, dirname); + + return ans; +} + +int delete_file(char *dirname, int size, int ent, int (*filecheck)()) { + char abuf[BUFSIZE]; + int fd; + struct stat st; + long numents; + + if(ent < 1 || (fd = open(dirname, O_RDWR)) == -1) + return -1; + flock(fd, LOCK_EX); + fstat(fd, &st); + numents = ((long) st.st_size) / size; + if(((long) st.st_size) % size) + fprintf(stderr, "align err\n"); + if(lseek(fd, (off_t) size * (ent - 1), SEEK_SET) != -1) { + if(read(fd, abuf, size) == size){ + if((*filecheck) (abuf)) { + int i; + + for(i = ent; i < numents; i++) { + if(lseek(fd, (off_t)((i) * size), SEEK_SET) == -1 || + read(fd, abuf, size) != size || + lseek(fd, (off_t)(i - 1) * size, SEEK_SET) == -1) + break; + if(safewrite(fd, abuf, size) != size) + break; + } + ftruncate(fd, (off_t) size * (numents - 1)); + flock(fd, LOCK_UN); + close(fd); + return 0; + } + } + } + lseek(fd, 0, SEEK_SET); + ent = 1; + while(read(fd, abuf, size) == size) { + if((*filecheck)(abuf)) { + int i; + + for(i = ent; i < numents; i++) { + if(lseek(fd, (off_t) (i + 1) * size, SEEK_SET) == -1 || + read(fd, abuf, size) != size || + lseek(fd, (off_t) (i) * size, SEEK_SET) == -1 || + safewrite(fd, abuf, size) != size) + break; + } + ftruncate(fd, (off_t) size * (numents - 1)); + flock(fd, LOCK_UN); + close(fd); + return 0; + } + ent++; + } + flock(fd, LOCK_UN); + close(fd); + return -1; +} + +#endif /* !defined(_BBS_UTIL_C_) */ + +int apply_record(char *fpath, int (*fptr)(), int size) { + char abuf[BUFSIZE]; + FILE* fp; + + if(!(fp = fopen(fpath, "r"))) + return -1; + + while(fread(abuf, 1, size, fp) == size) + if((*fptr) (abuf) == QUIT) { + fclose(fp); + return QUIT; + } + fclose(fp); + return 0; +} + +/* mail / post ®É¡A¨Ì¾Ú®É¶¡«Ø¥ßÀɮסA¥[¤W¶lÂW */ +int stampfile(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + int fp = 0; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while (*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "M.%ld.A", ++dtime ); + if(fp == -1 && errno != EEXIST) + return -1; + } while((fp = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644)) == -1); + close(fp); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); + return 0; +} + +void stampdir(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while(*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "D%lX", ++dtime & 07777); + } while(mkdir(fpath, 0755) == -1); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); +} + +void stamplink(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while(*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "S%lX", ++dtime ); + } while(symlink("temp", fpath) == -1); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); +} + +int do_append(char *fpath, fileheader_t *record, int size) { + int fd; + + if((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) { + perror("open"); + return -1; + } + flock(fd, LOCK_EX); + lseek(fd, 0, SEEK_END); + + safewrite(fd, record, size); + + flock(fd, LOCK_UN); + close(fd); + return 0; +} + +int append_record(char *fpath, fileheader_t *record, int size) { +#if !defined(_BBS_UTIL_C_) + int m,n; + if(get_num_records(fpath, sizeof(fileheader_t)) <= MAX_KEEPMAIL * 2) { + FILE *fp; + char buf[512],address[200]; + + for(n = strlen(fpath) - 1 ; fpath[n] != '/' && n > 0; n--); + strncpy(buf, fpath, n + 1); + buf[n + 1] = 0; + for(m = strlen(buf) - 2 ; buf[m] != '/' && m > 0 ; m--); + strcat(buf, ".forward"); + if((fp = fopen(buf,"r"))) { + fscanf(fp,"%s",address); + fclose(fp); + if(buf[0] != 0 && buf[0] != ' ') { + buf[n + 1] = 0; + strcat(buf, record->filename); + do_append(fpath,record,size); +#ifndef USE_BSMTP + bbs_sendmail(buf,record->title,address); +#else + bsmtp(buf, record->title, address, 0); +#endif + return 0; + } + } + } +#endif + + do_append(fpath,record,size); + + return 0; +} diff --git a/mbbsd/register.c b/mbbsd/register.c new file mode 100644 index 00000000..e9c25be5 --- /dev/null +++ b/mbbsd/register.c @@ -0,0 +1,339 @@ +/* $Id: register.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#define _XOPEN_SOURCE + +#include <stdio.h> +#include <strings.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +extern char *str_new; +extern char *msg_uid; +extern int t_lines, t_columns; /* Screen size / width */ +extern char *str_mail_address; + +/* password encryption */ +static char pwbuf[14]; + +char *genpasswd(char *pw) { + if(pw[0]) { + char saltc[2], c; + int i; + + i = 9 * getpid(); + saltc[0] = i & 077; + saltc[1] = (i >> 6) & 077; + + for(i = 0; i < 2; i++) { + c = saltc[i] + '.'; + if(c > '9') + c += 7; + if(c > 'Z') + c += 6; + saltc[i] = c; + } + strcpy(pwbuf, pw); + return crypt(pwbuf, saltc); + } + return ""; +} + +int checkpasswd(char *passwd, char *test) { + char *pw; + + strncpy(pwbuf, test, 14); + pw = crypt(pwbuf, passwd); + return (!strncmp(pw, passwd, 14)); +} + +/* Àˬd user µù¥U±¡ªp */ +int bad_user_id(char *userid) { + int len, i; + len = strlen(userid); + + if(len < 2) + return 1; + + if (not_alpha(userid[0])) + return 1; + for (i=1; i<len; i++) //DickG:×¥¿¤F¥u¤ñ¸û userid ²Ä¤@Ó¦r¤¸ªº bug + if(not_alnum(userid[i])) + return 1; + + if(strcasecmp(userid, str_new) == 0) + return 1; + + /* while((ch = *(++userid))) + if(not_alnum(ch)) + return 1;*/ + return 0; +} + +/* -------------------------------- */ +/* New policy for allocate new user */ +/* (a) is the worst user currently */ +/* (b) is the object to be compared */ +/* -------------------------------- */ +static int compute_user_value(userec_t *urec, time_t clock) { + int value; + + /* if (urec) has XEMPT permission, don't kick it */ + if((urec->userid[0] == '\0') || (urec->userlevel & PERM_XEMPT) + /*|| (urec->userlevel & PERM_LOGINOK)*/ + || !strcmp(STR_GUEST,urec->userid)) + return 999999; + value = (clock - urec->lastlogin) / 60; /* minutes */ + + /* new user should register in 30 mins */ + if(strcmp(urec->userid, str_new) == 0) + return 30 - value; +#if 0 + if (!urec->numlogins) /* ¥¼ login ¦¨¥\ªÌ¡A¤£«O¯d */ + return -1; + if (urec->numlogins <= 3) /* #login ¤Ö©ó¤TªÌ¡A«O¯d 20 ¤Ñ */ + return 20 * 24 * 60 - value; +#endif + /* ¥¼§¹¦¨µù¥UªÌ¡A«O¯d 15 ¤Ñ */ + /* ¤@¯ë±¡ªp¡A«O¯d 120 ¤Ñ */ + return (urec->userlevel & PERM_LOGINOK ? 120 : 15) * 24 * 60 - value; +} + +int check_and_expire_account(int uid,userec_t *urec) +{ + userec_t zerorec; + time_t now=time(NULL); + char genbuf[200],genbuf2[200]; + int val; + if((val = compute_user_value(urec, now)) < 0) { + sprintf(genbuf, "#%d %-12s %15.15s %d %d %d", + uid, urec->userid, ctime(&(urec->lastlogin)) + 4, + urec->numlogins, urec->numposts, val); + if(val > -1 * 60 * 24 * 365) { + memset(&zerorec, 0, sizeof(zerorec)); + log_usies("CLEAN", genbuf); + sprintf(genbuf, "home/%c/%s", urec->userid[0], + urec->userid); + sprintf(genbuf2, "tmp/%s", urec->userid); + if(dashd(genbuf) && Rename(genbuf, genbuf2)) { + sprintf(genbuf, "/bin/rm -fr home/%c/%s >/dev/null 2>&1", + urec->userid[0],urec->userid); + system(genbuf); + } + passwd_update(uid, &zerorec); + remove_from_uhash(uid - 1); + add_to_uhash(uid - 1, ""); + } + else + { + val=0; + log_usies("DATED", genbuf); + } + } + return val; +} + +extern char *fn_passwd; + +int getnewuserid() { + char genbuf[50]; + static char *fn_fresh = ".fresh"; + userec_t utmp,zerorec; + time_t clock; + struct stat st; + int fd, i; + + memset(&zerorec, 0, sizeof(zerorec)); + clock = time(NULL); + + /* Lazy method : ¥ý§ä´M¤w¸g²M°£ªº¹L´Á±b¸¹ */ + if((i = searchnewuser(0)) == 0) { + /* ¨C 1 Ó¤p®É¡A²M²z user ±b¸¹¤@¦¸ */ + if((stat(fn_fresh, &st) == -1) || (st.st_mtime < clock - 3600)) { + if((fd = open(fn_fresh, O_RDWR | O_CREAT, 0600)) == -1) + return -1; + write(fd, ctime(&clock), 25); + close(fd); + log_usies("CLEAN", "dated users"); + + fprintf(stdout, "´M§ä·s±b¸¹¤¤, ½Ðµy«Ý¤ù¨è...\n\r"); + + if((fd = open(fn_passwd, O_RDWR | O_CREAT, 0600)) == -1) + return -1; + + /* ¤£¾å±o¬°¤°»òn±q 2 ¶}©l... Ptt:¦]¬°SYSOP¦b1 */ + for(i = 2; i <= MAX_USERS; i++) { + passwd_query(i, &utmp); + check_and_expire_account(i,&utmp); + } + } + } + + passwd_lock(); + i = searchnewuser(1); + if((i <= 0) || (i > MAX_USERS)) { + passwd_unlock(); + if(more("etc/user_full", NA) == -1) + fprintf(stdout, "©êºp¡A¨Ï¥ÎªÌ±b¸¹¤w¸gº¡¤F¡AµLªkµù¥U·sªº±b¸¹\n\r"); + safe_sleep(2); + exit(1); + } + + sprintf(genbuf, "uid %d", i); + log_usies("APPLY", genbuf); + + strcpy(zerorec.userid, str_new); + zerorec.lastlogin = clock; + passwd_update(i, &zerorec); + setuserid(i, zerorec.userid); + passwd_unlock(); + return i; +} + +void new_register() { + extern userec_t xuser; + userec_t newuser; + char passbuf[STRLEN]; + int allocid, try, id; + + memset(&newuser, 0, sizeof(newuser)); + more("etc/register", NA); + try = 0; + while(1) { + if(++try >= 6) { + outs("\n±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a\n"); + refresh(); + + pressanykey(); + oflush(); + exit(1); + } + getdata(17, 0, msg_uid, newuser.userid, IDLEN + 1, DOECHO); + + if(bad_user_id(newuser.userid)) + outs("µLªk±µ¨ü³oÓ¥N¸¹¡A½Ð¨Ï¥Î^¤å¦r¥À¡A¨Ã¥B¤£n¥]§tªÅ®æ\n"); + else if ((id=getuser(newuser.userid)) && + (id=check_and_expire_account(id,&xuser))>=0) + { + if(id==999999) + outs("¦¹¥N¸¹¤w¸g¦³¤H¨Ï¥Î ¬O¤£¦º¤§¨"); + else + { + sprintf(passbuf,"¦¹¥N¸¹¤w¸g¦³¤H¨Ï¥Î ÁÙ¦³%d¤Ñ¤~¹L´Á \n",id/(60*24)); + outs(passbuf); + } + } + else + break; + } + + try = 0; + while(1) { + if(++try >= 6) { + outs("\n±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a\n"); + refresh(); + + pressanykey(); + oflush(); + exit(1); + } + if((getdata(19, 0, "½Ð³]©w±K½X¡G", passbuf, PASSLEN, NOECHO) < 3) || + !strcmp(passbuf, newuser.userid)) { + outs("±K½X¤Ó²³æ¡A©ö¾D¤J«I¡A¦Ü¤Ön 4 Ó¦r¡A½Ð«·s¿é¤J\n"); + continue; + } + strncpy(newuser.passwd, passbuf, PASSLEN); + getdata(20, 0, "½ÐÀˬd±K½X¡G", passbuf, PASSLEN, NOECHO); + if(strncmp(passbuf, newuser.passwd, PASSLEN)) { + outs("±K½X¿é¤J¿ù»~, ½Ð«·s¿é¤J±K½X.\n"); + continue; + } + passbuf[8] = '\0'; + strncpy(newuser.passwd, genpasswd(passbuf), PASSLEN); + break; + } + newuser.userlevel = PERM_DEFAULT; + newuser.uflag = COLOR_FLAG | BRDSORT_FLAG | MOVIE_FLAG; + newuser.firstlogin = newuser.lastlogin = time(NULL); + newuser.money = 0; + newuser.pager = 1; + allocid = getnewuserid(); + if(allocid > MAX_USERS || allocid <= 0) { + fprintf(stderr, "¥»¯¸¤H¤f¤w¹F¹¡©M¡I\n"); + exit(1); + } + + if(passwd_update(allocid, &newuser) == -1) { + fprintf(stderr, "«Èº¡¤F¡A¦A¨£¡I\n"); + exit(1); + } + setuserid(allocid, newuser.userid); + if(!dosearchuser(newuser.userid)) { + fprintf(stderr, "µLªk«Ø¥ß±b¸¹\n"); + exit(1); + } +} + +extern userec_t cuser; + +void check_register() { + char *ptr = NULL; + + stand_title("½Ð¸Ô²Ó¶ñ¼gÓ¤H¸ê®Æ"); + + while(strlen(cuser.username) < 2) + getdata(2, 0, "ºï¸¹¼ÊºÙ¡G", cuser.username, 24, DOECHO); + + for(ptr = cuser.username; *ptr; ptr++) { + if (*ptr == 9) /* TAB convert */ + *ptr = ' '; + } + while(strlen(cuser.realname) < 4) + getdata(4, 0, "¯u¹ê©m¦W¡G", cuser.realname, 20, DOECHO); + + while(strlen(cuser.address) < 8) + getdata(6, 0, "Ápµ¸¦a§}¡G", cuser.address, 50, DOECHO); + + + if(!strchr(cuser.email, '@')) { + bell(); + move(t_lines - 4, 0); + prints("¡° ¬°¤F±zªºÅv¯q¡A½Ð¶ñ¼g¯u¹êªº E-mail address¡A " + "¥H¸ê½T»{»Õ¤U¨¥÷¡A\n" + "®æ¦¡¬° \033[44muser@domain_name\033[0m ©Î \033[44muser" + "@\\[ip_number\\]\033[0m¡C\n\n" + "¡° ¦pªG±z¯uªº¨S¦³ E-mail¡A½Ðª½±µ«ö [return] §Y¥i¡C"); + + do { + getdata(8, 0, "¹q¤l«H½c¡G", cuser.email, 50, DOECHO); + if(!cuser.email[0]) + sprintf(cuser.email, "%s%s", cuser.userid, str_mail_address); + } while(!strchr(cuser.email, '@')); + + } + if(!HAS_PERM(PERM_SYSOP) && !HAS_PERM(PERM_LOGINOK)) { + /* ¦^ÂйL¨¥÷»{ÃÒ«H¨ç¡A©Î´¿¸g E-mail post ¹L */ + clear(); + move(9,3); + prints("½Ð¸Ô¶ñ¼g\033[32mµù¥U¥Ó½Ð³æ\033[m¡A" + "³q§i¯¸ªø¥HÀò±o¶i¶¥¨Ï¥ÎÅv¤O¡C\n\n\n\n"); + u_register(); + } + +#ifdef NEWUSER_LIMIT + if(!(cuser.userlevel & PERM_LOGINOK) && !HAS_PERM(PERM_SYSOP)) { + if(cuser.lastlogin - cuser.firstlogin < 3 * 86400) + cuser.userlevel &= ~PERM_POST; + more("etc/newuser", YEA); + } +#endif +} diff --git a/mbbsd/screen.c b/mbbsd/screen.c new file mode 100644 index 00000000..46ad5b38 --- /dev/null +++ b/mbbsd/screen.c @@ -0,0 +1,559 @@ +/* $Id: screen.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int showansi; + +extern char *clearbuf; +extern char *cleolbuf; +extern char *scrollrev; +extern char *strtstandout; +extern char *endstandout; +extern int clearbuflen; +extern int cleolbuflen; +extern int scrollrevlen; +extern int strtstandoutlen; +extern int endstandoutlen; +extern int automargins; +#ifdef SUPPORT_GB +static int current_font_type=TYPE_BIG5; +static int gbinited=0; +#endif +#define SCR_WIDTH 80 +#define o_clear() output(clearbuf,clearbuflen) +#define o_cleol() output(cleolbuf,cleolbuflen) +#define o_scrollrev() output(scrollrev,scrollrevlen) +#define o_standup() output(strtstandout,strtstandoutlen) +#define o_standdown() output(endstandout,endstandoutlen) + +unsigned char scr_lns, scr_cols; +static unsigned char cur_ln = 0, cur_col = 0; +static unsigned char docls, downfrom = 0; +static unsigned char standing = NA; +static char roll = 0; +static int scrollcnt, tc_col, tc_line; + +screenline_t *big_picture = NULL; + +#define MODIFIED (1) /* if line has been modifed, screen output */ +#define STANDOUT (2) /* if this line has a standout region */ + +int tputs(const char *str, int affcnt, int (*putc)(int)); + +void initscr() { + if(!big_picture) { + scr_lns = t_lines; + scr_cols = t_columns = ANSILINELEN; + /* scr_cols = MIN(t_columns, ANSILINELEN); */ + big_picture = (screenline_t *) calloc(scr_lns, sizeof(screenline_t)); + docls = YEA; + } +} + +void move(int y, int x) { + cur_col = x; + cur_ln = y; +} + +void getyx(int *y, int *x) { + *y = cur_ln; + *x = cur_col; +} + +static void rel_move(int was_col, int was_ln, int new_col, int new_ln) { + if(new_ln >= t_lines || new_col >= t_columns) + return; + + tc_col = new_col; + tc_line = new_ln; + if(new_col == 0) { + if(new_ln == was_ln) { + if(was_col) + ochar('\r'); + return; + } else if(new_ln == was_ln + 1) { + ochar('\n'); + if(was_col) + ochar('\r'); + return; + } + } + + if(new_ln == was_ln) { + if(was_col == new_col) + return; + + if(new_col == was_col - 1) { + ochar(Ctrl('H')); + return; + } + } + do_move(new_col, new_ln); +} + +static void standoutput(char *buf, int ds, int de, int sso, int eso) { + int st_start, st_end; + + if(eso <= ds || sso >= de) { + output(buf + ds, de - ds); + } else { + st_start = MAX(sso, ds); + st_end = MIN(eso, de); + if(sso > ds) + output(buf + ds, sso - ds); + o_standup(); + output(buf + st_start, st_end - st_start); + o_standdown(); + if(de > eso) + output(buf + eso, de - eso); + } +} + +void redoscr() { + register screenline_t *bp; + register int i, j, len; + + o_clear(); + for(tc_col = tc_line = i = 0, j = roll; i < scr_lns; i++, j++) { + if(j >= scr_lns) + j = 0; + bp = &big_picture[j]; + if((len = bp->len)) { + rel_move(tc_col, tc_line, 0, i); + if(bp->mode & STANDOUT) + standoutput(bp->data, 0, len, bp->sso, bp->eso); + else + output(bp->data, len); + tc_col += len; + if(tc_col >= t_columns) { + if (automargins) + tc_col = t_columns - 1; + else { + tc_col -= t_columns; + tc_line++; + if(tc_line >= t_lines) + tc_line = b_lines; + } + } + bp->mode &= ~(MODIFIED); + bp->oldlen = len; + } + } + rel_move(tc_col, tc_line, cur_col, cur_ln); + docls = scrollcnt = 0; + oflush(); +} + +void refresh() { + register screenline_t *bp = big_picture; + register int i, j, len; + extern int automargins; + extern int scrollrevlen; + if(num_in_buf()) + return; + + if((docls) || (abs(scrollcnt) >= (scr_lns - 3))) { + redoscr(); + return; + } + + if(scrollcnt < 0) { + if(!scrollrevlen) { + redoscr(); + return; + } + rel_move(tc_col, tc_line, 0, 0); + do { + o_scrollrev(); + } while(++scrollcnt); + } else if (scrollcnt > 0) { + rel_move(tc_col, tc_line, 0, b_lines); + do { + ochar('\n'); + } while(--scrollcnt); + } + + for(i = 0, j = roll; i < scr_lns; i++, j++) { + if(j >= scr_lns) + j = 0; + bp = &big_picture[j]; + len = bp->len; + if(bp->mode & MODIFIED && bp->smod < len) { + bp->mode &= ~(MODIFIED); + if(bp->emod >= len) + bp->emod = len - 1; + rel_move(tc_col, tc_line, bp->smod, i); + + if(bp->mode & STANDOUT) + standoutput(bp->data, bp->smod, bp->emod + 1, + bp->sso, bp->eso); + else + output(&bp->data[bp->smod], bp->emod - bp->smod + 1); + tc_col = bp->emod + 1; + if(tc_col >= t_columns) { + if(automargins) { + tc_col -= t_columns; + if(++tc_line >= t_lines) + tc_line = b_lines; + } else + tc_col = t_columns - 1; + } + } + + if(bp->oldlen > len) { + rel_move(tc_col, tc_line, len, i); + o_cleol(); + } + bp->oldlen = len; + + } + + rel_move(tc_col, tc_line, cur_col, cur_ln); + + oflush(); +} + +void clear() { + register screenline_t *slp; + + register int i; + + docls = YEA; + cur_col = cur_ln = roll = downfrom = i = 0; + do { + slp = &big_picture[i]; + slp->mode = slp->len = slp->oldlen = 0; + } while(++i < scr_lns); +} + +void clrtoeol() { + register screenline_t *slp; + register int ln; + + standing = NA; + if((ln = cur_ln + roll) >= scr_lns) + ln -= scr_lns; + slp = &big_picture[ln]; + if(cur_col <= slp->sso) + slp->mode &= ~STANDOUT; + + if(cur_col > slp->oldlen) { + for(ln = slp->len; ln <= cur_col; ln++) + slp->data[ln] = ' '; + } + + if(cur_col < slp->oldlen) { + for(ln = slp->len; ln >= cur_col; ln--) + slp->data[ln] = ' '; + } + + slp->len = cur_col; +} + +void clrtoline(int line) { + register screenline_t *slp; + register int i, j; + + for(i = cur_ln, j = i + roll; i < line; i++, j++) { + if(j >= scr_lns) + j -= scr_lns; + slp = &big_picture[j]; + slp->mode = slp->len = 0; + if(slp->oldlen) + slp->oldlen = 255; + } +} + +void clrtobot() { + clrtoline(scr_lns); +} + +void outch(unsigned char c) { + register screenline_t *slp; + register int i; + + if((i = cur_ln + roll) >= scr_lns) + i -= scr_lns; + slp = &big_picture[i]; + + if(c == '\n' || c == '\r') { + if(standing) { + slp->eso = MAX(slp->eso, cur_col); + standing = NA; + } + if((i = cur_col - slp->len) > 0) + memset(&slp->data[slp->len], ' ', i + 1); + slp->len = cur_col; + cur_col = 0; + if(cur_ln < scr_lns) + cur_ln++; + return; + } +/* + else if(c != '\033' && !isprint2(c)) + { + c = '*'; //substitute a '*' for non-printable + } +*/ + if(cur_col >= slp->len) { + for(i = slp->len; i < cur_col; i++) + slp->data[i] = ' '; + slp->data[cur_col] = '\0'; + slp->len = cur_col + 1; + } + + if(slp->data[cur_col] != c) { + slp->data[cur_col] = c; + if((slp->mode & MODIFIED) != MODIFIED) + slp->smod = slp->emod = cur_col; + slp->mode |= MODIFIED; + if(cur_col > slp->emod) + slp->emod = cur_col; + if(cur_col < slp->smod) + slp->smod = cur_col; + } + + if (++cur_col >= scr_cols) + { + if (standing && (slp->mode & STANDOUT)) + { + standing = 0; + slp->eso = MAX(slp->eso, cur_col); + } + cur_col = 0; + if (cur_ln < scr_lns) + cur_ln++; + } + +} + +static void parsecolor(char *buf) { + char *val; + char data[24]; + + data[0] = '\0'; + val = (char *)strtok(buf, ";"); + + while(val) { + if(atoi(val) < 30) { + if(data[0]) + strcat(data, ";"); + strcat(data, val); + } + val = (char *) strtok(NULL, ";"); + } + strcpy(buf, data); +} + +#define NORMAL (00) +#define ESCAPE (01) +#define VTKEYS (02) + +void outc(unsigned char ch) { + if(showansi) + outch(ch); + else { + static char buf[24]; + static int p = 0; + static int mode = NORMAL; + int i; + + switch(mode) { + case NORMAL: + if(ch == '\033') + mode = ESCAPE; + else + outch(ch); + return; + case ESCAPE: + if(ch == '[') + mode = VTKEYS; + else { + mode = NORMAL; + outch(''); + outch(ch); + } + return; + case VTKEYS: + if(ch == 'm') { + buf[p++] = '\0'; + parsecolor(buf); + } else if((p < 24) && (not_alpha(ch))) { + buf[p++] = ch; + return; + } + if(buf[0]) { + outch(''); + outch('['); + + for(i = 0; (p = buf[i]); i++) + outch(p); + outch(ch); + } + p = 0; + mode = NORMAL; + } + } +} + +static void do_outs(char *str) { + while(*str) + { + outc(*str++); + } +} +#ifdef SUPPORT_GB +static void gb_init() +{ + if(current_font_type == TYPE_GB) + { + hc_readtab(BBSHOME"/etc/hc.tab"); + } + gbinited = 1; +} + +static void gb_outs(char *str) +{ + do_outs(hc_convert_str(str, HC_BIGtoGB, HC_DO_SINGLE)); +} +#endif +int edit_outs(char *text) { + register int column = 0; + register char ch; +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + text = hc_convert_str(text, HC_BIGtoGB, HC_DO_SINGLE); +#endif + while((ch = *text++) && (++column < SCR_WIDTH)) + outch(ch == 27 ? '*' : ch); + + return 0; +} + +void outs(char *str) { +#ifdef SUPPORT_GB + if(current_font_type == TYPE_BIG5) +#endif + do_outs(str); +#ifdef SUPPORT_GB + else + { + if(!gbinited) gb_init(); + gb_outs(str); + } +#endif +} + + +/* Jaky */ +void Jaky_outs(char *str, int line) { +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + str = hc_convert_str(str, HC_BIGtoGB, HC_DO_SINGLE); +#endif + while(*str && line) { + outc(*str); + if(*str=='\n') + line--; + str++; + } +} + +void outmsg(char *msg) { + move(b_lines, 0); + clrtoeol(); +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + msg = hc_convert_str(msg, HC_BIGtoGB, HC_DO_SINGLE); +#endif + while(*msg) + outc(*msg++); +} + +void prints(char *fmt, ...) { + va_list args; + char buff[1024]; + + va_start(args, fmt); + vsprintf(buff, fmt, args); + va_end(args); + outs(buff); +} + +void mprints(int y, int x, char *str) { + move(y, x); + clrtoeol(); + prints(str); +} + +void scroll() { + scrollcnt++; + if(++roll >= scr_lns) + roll = 0; + move(b_lines, 0); + clrtoeol(); +} + +void rscroll() { + scrollcnt--; + if(--roll < 0) + roll = b_lines; + move(0, 0); + clrtoeol(); +} + +void region_scroll_up(int top, int bottom) { + int i; + + if(top > bottom) { + i = top; + top = bottom; + bottom = i; + } + + if(top < 0 || bottom >= scr_lns) + return; + + for(i = top; i < bottom; i++) + big_picture[i] = big_picture[i + 1]; + memset(big_picture + i, 0, sizeof(*big_picture)); + memset(big_picture[i].data, ' ', scr_cols); + save_cursor(); + change_scroll_range(top, bottom); + do_move(0, bottom); + scroll_forward(); + change_scroll_range(0, scr_lns - 1); + restore_cursor(); + refresh(); +} + +void standout() { + if(!standing && strtstandoutlen) { + register screenline_t *slp; + + slp = &big_picture[((cur_ln + roll) % scr_lns)]; + standing = YEA; + slp->sso = slp->eso = cur_col; + slp->mode |= STANDOUT; + } +} + +void standend() { + if(standing && strtstandoutlen) { + register screenline_t *slp; + + slp = &big_picture[((cur_ln + roll) % scr_lns)]; + standing = NA; + slp->eso = MAX(slp->eso, cur_col); + } +} diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c new file mode 100644 index 00000000..9218b7f0 --- /dev/null +++ b/mbbsd/stuff.c @@ -0,0 +1,524 @@ +/* $Id: stuff.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +extern int currmode; +extern char *fn_mandex; +extern char *str_reply; +extern char *str_space; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern userec_t cuser; + +/* ----------------------------------------------------- */ +/* set file path for boards/user home */ +/* ----------------------------------------------------- */ +static char *str_home_file = "home/%c/%s/%s"; +static char *str_board_file = "boards/%s/%s"; + +#define STR_DOTDIR ".DIR" +static char *str_dotdir = STR_DOTDIR; + +void setcalfile(char *buf, char *userid) { + sprintf(buf, "home/%c/%s/calendar", userid[0], userid); +} + +void sethomepath(char *buf, char *userid) { + sprintf(buf, "home/%c/%s", userid[0], userid); +} + +void sethomedir(char *buf, char *userid) { + sprintf(buf, str_home_file, userid[0], userid, str_dotdir); +} + +void sethomeman(char *buf, char *userid) { + sprintf(buf, str_home_file, userid[0], userid, "man"); +} + +void sethomefile(char *buf, char *userid, char *fname) { + sprintf(buf, str_home_file, userid[0], userid, fname); +} + +void setuserfile(char *buf, char *fname) { + sprintf(buf, str_home_file, cuser.userid[0], cuser.userid, fname); +} + +void setapath(char *buf, char *boardname) { + sprintf(buf, "man/boards/%s", boardname); +} + +void setadir(char *buf, char *path) { + sprintf(buf, "%s/%s", path, str_dotdir); +} + +void setbpath(char *buf, char *boardname) { + sprintf(buf, "boards/%s", boardname); +} + +void setbdir(char *buf, char *boardname) { + sprintf(buf, str_board_file, boardname, + currmode & MODE_ETC ? ".ETC" : + (currmode & MODE_DIGEST ? fn_mandex : str_dotdir)); +} + +void setbfile(char *buf, char *boardname, char *fname) { + sprintf(buf, str_board_file, boardname, fname); +} + +void setdirpath(char *buf, char *direct, char *fname) { + strcpy(buf, direct); + direct = strrchr(buf, '/'); + strcpy(direct + 1, fname); +} + +char *subject(char *title) { + if(!strncasecmp(title, str_reply, 3)) { + title += 3; + if(*title == ' ') + title++; + } + return title; +} + +/* ----------------------------------------------------- */ +/* ¦r¦êÂà´«Àˬd¨ç¼Æ */ +/* ----------------------------------------------------- */ +int str_checksum(char *str) { + int n = 1; + if(strlen(str) < 6) + return 0; + while(*str) + n += *(str++) * (n); + return n; +} + +void str_lower(char *t, char *s) { + register unsigned char ch; + + do { + ch = *s++; + *t++ = char_lower(ch); + } while(ch); +} + +int strstr_lower(char *str, char *tag) { + char buf[STRLEN]; + + str_lower(buf, str); + return (int)strstr(buf, tag); +} + +void trim(char *buf) { /* remove trailing space */ + char *p = buf; + + while(*p) + p++; + while(--p >= buf) { + if(*p == ' ') + *p = '\0'; + else + break; + } +} + +/* ----------------------------------------------------- */ +/* ¦r¦êÀˬd¨ç¼Æ¡G^¤å¡B¼Æ¦r¡BÀɦW¡BE-mail address */ +/* ----------------------------------------------------- */ +int isprint2(char ch) { + return ((ch & 0x80) ? 1 : isprint(ch)); + //return 1; +} + +int not_alpha(char ch) { + return (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z'); +} + +int not_alnum(char ch) { + return (ch < '0' || (ch > '9' && ch < 'A') || + (ch > 'Z' && ch < 'a') || ch > 'z'); +} + +int invalid_pname(char *str) { + char *p1, *p2, *p3; + + p1 = str; + while(*p1) { + if(!(p2 = strchr(p1, '/'))) + p2 = str + strlen(str); + if(p1 + 1 > p2 || p1 + strspn(p1, ".") == p2) + return 1; + for(p3 = p1; p3 < p2; p3++) + if(not_alnum(*p3) && !strchr("@[]-._", *p3)) + return 1; + p1 = p2 + (*p2 ? 1 : 0); + } + return 0; +} + +int valid_ident(char *ident) { + static char *invalid[] = {"unknown@", "root@", "gopher@", "bbs@", + "@bbs", "guest@", "@ppp", "@slip", NULL}; + char buf[128]; + int i; + + str_lower(buf, ident); + for(i = 0; invalid[i]; i++) + if(strstr(buf, invalid[i])) + return 0; + return 1; +} + +int is_uBM(char *list, char *id) { + register int len; + + if(list[0] == '[') + list++; + if(list[0] > ' ') { + len = strlen(id); + do { + if(!strncasecmp(list, id, len)) { + list += len; + if((*list == 0) || (*list == '/') || + (*list == ']') || (*list == ' ')) + return 1; + } + if((list = strchr(list,'/')) != NULL) + list++; + else + break; + } while(1); + } + return 0; +} + +int is_BM(char *list) { + if(is_uBM(list,cuser.userid)) { + cuser.userlevel |= PERM_BM; /* Ptt ¦Û°Ê¥[¤WBMªºÅv§Q */ + return 1; + } + return 0; +} + +int userid_is_BM(char *userid, char *list) { + register int ch, len; + + ch = list[0]; + if((ch > ' ') && (ch < 128)) { + len = strlen(userid); + do { + if(!strncasecmp(list, userid, len)) { + ch = list[len]; + if((ch == 0) || (ch == '/') || (ch == ']')) + return 1; + } + while((ch = *list++)) { + if(ch == '/') + break; + } + } while(ch); + } + return 0; +} + +/* ----------------------------------------------------- */ +/* ÀÉ®×Àˬd¨ç¼Æ¡GÀɮסB¥Ø¿ý¡BÄÝ©ó */ +/* ----------------------------------------------------- */ +off_t dashs(char *fname) { + struct stat st; + + if(!stat(fname, &st)) + return st.st_size; + else + return -1; +} + +long dasht(char *fname) { + struct stat st; + + if(!stat(fname, &st)) + return st.st_mtime; + else + return -1; +} + +int dashl(char *fname) { + struct stat st; + + return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode)); +} + +int dashf(char *fname) { + struct stat st; + + return (stat(fname, &st) == 0 && S_ISREG(st.st_mode)); +} + +int dashd(char *fname) { + struct stat st; + + return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); +} + +int belong(char *filelist, char *key) { + FILE *fp; + int rc = 0; + + if((fp = fopen(filelist, "r"))) { + char buf[STRLEN], *ptr; + + while(fgets(buf, STRLEN, fp)) { + if((ptr = strtok(buf, str_space)) && !strcasecmp(ptr, key)) { + rc = 1; + break; + } + } + fclose(fp); + } + return rc; +} + +char *Cdate(time_t *clock) { + static char foo[32]; + struct tm *mytm = localtime(clock); + + strftime(foo, 32, "%m/%d/%Y %T %a", mytm); + return foo; +} + +char *Cdatelite(time_t *clock) { + static char foo[32]; + struct tm *mytm = localtime(clock); + + strftime(foo, 32, "%m/%d/%Y %T", mytm); + return foo; +} + +char *Cdatedate(time_t *clock){ + static char foo[32]; + struct tm *mytm = localtime(clock); + + strftime(foo, 32, "%m/%d/%Y", mytm); + return foo; +} + +static void capture_screen() { + char fname[200]; + FILE* fp; + extern screenline_t *big_picture; + extern unsigned char scr_lns; + int i; + + getdata(b_lines - 2, 0, "§â³oÓµe±¦¬¤J¨ì¼È¦sÀÉ¡H[y/N] ", + fname, 4, LCECHO); + if(fname[0] != 'y' ) return; + + setuserfile(fname, ask_tmpbuf(b_lines - 1)); + if((fp = fopen(fname, "w"))) { + for(i = 0; i < scr_lns; i++) + fprintf(fp, "%.*s\n", big_picture[i].len, big_picture[i].data); + fclose(fp); + } +} + +void pressanykey() { + int ch; + + outmsg("\033[37;45;1m " + "¡´ ½Ð«ö \033[33m(Space/Return)\033[37m Ä~Äò ¡´" + " \033[33m(^T)\033[37m ¦s¼È¦sÀÉ \033[m"); + do { + ch = igetkey(); + + if(ch == Ctrl('T')) { + capture_screen(); + break; + } + } while((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); + move(b_lines, 0); + clrtoeol(); + refresh(); +} + +int vmsg (const char *fmt, ...) +{ + va_list ap; + char msg[80] = {0}; + int ch; + + va_start (ap, fmt); + vsprintf (msg, fmt, ap); + va_end (ap); + + move (b_lines, 0); + clrtoeol (); + + if (*msg) + prints ("\033[1;36;44m ¡» %-55.54s \033[33;46m \033[200m\033[1431m\033[506m[½Ð«ö¥ô·NÁäÄ~Äò]\033[201m \033[m", msg); + else + outs ("\033[46;1m \033[37m" + "\033[200m\033[1431m\033[506m¡¼ ½Ð«ö \033[33m(Space/Return)\033[37m Ä~Äò ¡¼\033[201m" + " \033[m"); + + do { + ch = igetkey(); + + if(ch == Ctrl('T')) { + capture_screen(); + break; + } + } while((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); + + + move (b_lines, 0); + clrtoeol (); + refresh (); + return ch; +} + +void bell() { + char c; + + c = Ctrl('G'); + write(1, &c, 1); +} + +int search_num(int ch, int max) { + int clen = 1; + int x, y; + extern unsigned char scr_cols; + char genbuf[10]; + + outmsg("\033[7m ¸õ¦Ü²Ä´X¶µ¡G\033[m"); + outc(ch); + genbuf[0] = ch; + getyx(&y, &x); + x--; + while((ch = igetch()) != '\r') { + if(ch == 'q' || ch == 'e') + return -1; + if(ch == '\n') + break; + if(ch == '\177' || ch == Ctrl('H')) { + if(clen == 0) { + bell(); + continue; + } + clen--; + move(y, x + clen); + outc(' '); + move(y, x + clen); + continue; + } + if(!isdigit(ch)) { + bell(); + continue; + } + if(x + clen >= scr_cols || clen >= 6) { + bell(); + continue; + } + genbuf[clen++] = ch; + outc(ch); + } + genbuf[clen] = '\0'; + move(b_lines, 0); + clrtoeol(); + if(genbuf[0] == '\0') + return -1; + clen = atoi(genbuf); + if(clen == 0) + return 0; + if(clen > max) + return max; + return clen - 1; +} + +void stand_title(char *title) { + clear(); + prints("\033[1;37;46m¡i %s ¡j\033[m\n", title); +} + +void cursor_show(int row, int column) { + move(row, column); + outs(STR_CURSOR); + move(row, column + 1); +} + +void cursor_clear(int row, int column) { + move(row, column); + outs(STR_UNCUR); +} + +int cursor_key(int row, int column) { + int ch; + + cursor_show(row, column); + ch = egetch(); + move(row, column); + outs(STR_UNCUR); + return ch; +} + +void printdash(char *mesg) { + int head = 0, tail; + + if(mesg) + head = (strlen(mesg) + 1) >> 1; + + tail = head; + + while(head++ < 38) + outch('-'); + + if(tail) { + outch(' '); + outs(mesg); + outch(' '); + } + + while(tail++ < 38) + outch('-'); + outch('\n'); +} + +int log_file(char *filename,char *buf) { + FILE *fp; + + if((fp = fopen(filename, "a" )) != NULL ) { + fputs( buf, fp ); + if(!strchr(buf,'\n')) + fputc('\n',fp); + fclose( fp ); + return 0; + } + else + return -1; +} + +void show_help(char *helptext[]) { + char *str; + int i; + + clear(); + for(i = 0; (str = helptext[i]); i++) { + if(*str == '\0') + prints("\033[1m¡i %s ¡j\033[0m\n", str + 1); + else if(*str == '\01') + prints("\n\033[36m¡i %s ¡j\033[m\n", str + 1); + else + prints(" %s\n", str); + } + pressanykey(); +} diff --git a/mbbsd/syspost.c b/mbbsd/syspost.c new file mode 100644 index 00000000..b7aefe10 --- /dev/null +++ b/mbbsd/syspost.c @@ -0,0 +1,102 @@ +/* $Id: syspost.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +extern char *str_permid[]; +extern userec_t cuser; + +void post_change_perm(int oldperm, int newperm, char *sysopid, char *userid) { + FILE *fp; + fileheader_t fhdr; + time_t now = time(0); + char genbuf[200], reason[30]; + int i, flag=0; + + strcpy(genbuf, "boards/Security"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + + fprintf(fp, "§@ªÌ: [¨t²Î¦w¥þ§½] ¬ÝªO: Security\n" + "¼ÐÃD: [¤½¦w³ø§i] ¯¸ªøקïÅv³ø§i\n" + "®É¶¡: %s\n", ctime(&now)); + for(i = 5; i < NUMPERMS; i++) { + if(((oldperm >> i) & 1) != ((newperm >> i) & 1)) { + fprintf (fp, " ¯¸ªø\033[1;32m%s%s%s%s\033[mªºÅv\n", + sysopid, + (((oldperm >> i) & 1) ? "\033[1;33mÃö³¬":"\033[1;33m¶}±Ò"), + userid, str_permid[i]); + flag++; + } + } + + if(flag) { + clrtobot(); + clear(); + while(!getdata_str(5, 0, "½Ð¿é¤J²z¥Ñ¥H¥Üt³d¡G", + reason, 60, DOECHO, "¬Ýª©ª©¥D:")); + fprintf(fp, "\n \033[1;37m¯¸ªø%sקïÅv²z¥Ñ¬O¡G%s\033[m", + cuser.userid, reason); + fclose(fp); + + sprintf(fhdr.title, "[¤½¦w³ø§i] ¯¸ªø%sקï%sÅv³ø§i", + cuser.userid, userid); + strcpy(fhdr.owner, "[¨t²Î¦w¥þ§½]"); + append_record("boards/Security/.DIR", &fhdr, sizeof(fhdr)); + } +} + +void post_violatelaw(char* crime, char* police, char* reason, char* result){ + char genbuf[200]; + fileheader_t fhdr; + time_t now; + FILE *fp; + strcpy(genbuf, "boards/Security"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + now = time(NULL); + fprintf(fp, "§@ªÌ: [Pttªk°|] ¬ÝªO: Security\n" + "¼ÐÃD: [³ø§i] %-20s ¹Hªk§P¨M³ø§i\n" + "®É¶¡: %s\n" + "\033[1;32m%s\033[m§P¨M¡G\n \033[1;32m%s\033[m" + "¦]\033[1;35m%s\033[m¦æ¬°¡A\n¹H¤Ï¥»¯¸¯¸³W¡A³B¥H\033[1;35m%s\033[m¡A¯S¦¹¤½§i", + crime, ctime(&now), police, crime, reason, result); + fclose(fp); + sprintf(fhdr.title, "[³ø§i] %-20s ¹Hªk§P¨M³ø§i", crime); + strcpy(fhdr.owner, "[Pttªk°|]"); + append_record("boards/Security/.DIR", &fhdr, sizeof(fhdr)); + + strcpy(genbuf, "boards/ViolateLaw"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + now = time(NULL); + fprintf(fp, "§@ªÌ: [Pttªk°|] ¬ÝªO: ViolateLaw\n" + "¼ÐÃD: [³ø§i] %-20s ¹Hªk§P¨M³ø§i\n" + "®É¶¡: %s\n" + "\033[1;32m%s\033[m§P¨M¡G\n \033[1;32m%s\033[m" + "¦]\033[1;35m%s\033[m¦æ¬°¡A\n¹H¤Ï¥»¯¸¯¸³W¡A³B¥H\033[1;35m%s\033[m¡A¯S¦¹¤½§i", + crime, ctime(&now), police, crime, reason, result); + fclose(fp); + sprintf(fhdr.title, "[³ø§i] %-20s ¹Hªk§P¨M³ø§i", crime); + strcpy(fhdr.owner, "[Pttªk°|]"); + + append_record("boards/ViolateLaw/.DIR", &fhdr, sizeof(fhdr)); + +} + +void post_newboard(char* bgroup, char* bname, char* bms){ + char genbuf[256], title[128]; + sprintf(title, "[·sª©¦¨¥ß] %s", bname); + sprintf(genbuf, "%s ¶}¤F¤@Ó·sª© %s : %s\n\n·s¥ôª©¥D¬° %s\n\n®¥³ß*^_^*\n", + cuser.userid, bname, bgroup, bms); + post_msg("Record", title, genbuf, "[¨t²Î]"); +} diff --git a/mbbsd/talk.c b/mbbsd/talk.c new file mode 100644 index 00000000..3012b2d2 --- /dev/null +++ b/mbbsd/talk.c @@ -0,0 +1,2663 @@ +/* $Id: talk.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <syslog.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <netdb.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +#define QCAST int (*)(const void *, const void *) + +extern userinfo_t *currutmp; +extern char *ModeTypeTable[MAX_MODES]; +extern char *fn_overrides; +extern int usernum; +extern char *msg_sure_ny; +extern char *msg_cancel; +extern unsigned int currstat; +extern char *fn_writelog; +extern FILE *fp_writelog; +extern pid_t currpid; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern int t_lines, t_columns; /* Screen size / width */ +extern char *fn_talklog; +extern char currauthor[IDLEN + 2]; +extern char *msg_usr_left; +extern char *msg_uid; +extern char *BBSName; +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern char fromhost[]; +extern char *err_uid; +extern int talkrequest; +extern char *msg_shortulist; +extern char *msg_nobody; +extern boardheader_t *bcache; +extern int curr_idle_timeout; +extern userec_t cuser; +extern userec_t xuser; + + +static char *IdleTypeTable[] = { + "°¸¦bªá§b°Õ", "±¡¤H¨Ó¹q", "³V¹¤¤", "«ô¨£©P¤½", "°²¦ºª¬ºA", "§Ú¦b«ä¦Ò" +}; +static char *sig_des[] = { + "°«Âû", "²á¤Ñ", "", "¤U´Ñ", "¶H´Ñ", "·t´Ñ" +}; + +#define MAX_SHOW_MODE 3 +#define M_INT 15 /* monitor mode update interval */ +#define P_INT 20 /* interval to check for page req. in + * talk/chat */ +#define BOARDFRI 1 + +typedef struct talkwin_t { + int curcol, curln; + int sline, eline; +} talkwin_t; + +typedef struct pickup_t { + userinfo_t *ui; + time_t idle; + int friend; +} pickup_t; + +extern int bind( /* int,struct sockaddr *, int */ ); +extern char *getuserid(); +extern struct utmpfile_t *utmpshm; +extern int watermode; +extern water_t water[6], *swater[5], *water_which; +extern char *friend_file[8], water_usies; + +/* °O¿ý friend ªº user number */ +//#define PICKUP_WAYS 7 //Ãö±¼¤k¤hÀu¥ý +#define PICKUP_WAYS 6 + +static int pickup_way = 0; +static char *fcolor[11] = { + "", "\033[36m", "\033[32m", "\033[1;32m", + "\033[33m", "\033[1;33m", "\033[1;37m", "\033[1;37m", + "\033[31m", "\033[1;35m", "\033[1;36m" +}; +static char save_page_requestor[40]; +static char page_requestor[40]; +static char description[30]; +static FILE *flog; + + +char *modestring(userinfo_t * uentp, int simple) { + static char modestr[40]; + static char *notonline = "¤£¦b¯¸¤W"; + register int mode = uentp->mode; + register char *word; + int fri_stat; + +/* for debugging */ + if (mode >= MAX_MODES) + { + syslog(LOG_WARNING, "what!? mode = %d", mode); + word = ModeTypeTable[mode % MAX_MODES]; + } + else + word = ModeTypeTable[mode]; + fri_stat = friend_stat(currutmp, uentp); + if (!(HAS_PERM(PERM_SYSOP) || HAS_PERM(PERM_SEECLOAK)) && + ( + (uentp->invisible || (fri_stat & HRM)) && + !((fri_stat & HFM) && (fri_stat & HRM)) + ) + ) + return notonline; + else if (mode == EDITING) + { + sprintf(modestr, "E:%s", + ModeTypeTable[uentp->destuid < EDITING ? uentp->destuid : + EDITING]); + word = modestr; + } + else if (!mode && *uentp->chatid == 1) + { + if (!simple) + sprintf(modestr, "¦^À³ %s", getuserid(uentp->destuid)); + else + sprintf(modestr, "¦^À³©I¥s"); + } + else if (!mode && *uentp->chatid == 2) + if (uentp->msgcount < 10) + { + char *cnum[10] = + {"", "¤@", "¨â", "¤T", "¥|", "¤", "¤»", "¤C", + "¤K", "¤E"}; + sprintf(modestr, "¤¤%sÁû¤ô²y", cnum[uentp->msgcount]); + } + else + sprintf(modestr, "¤£¦æ¤F @_@"); + else if (!mode && *uentp->chatid == 3) + sprintf(modestr, "¤ô²y·Ç³Æ¤¤"); + else if (!mode) + return (uentp->destuid == 6) ? uentp->chatid : + IdleTypeTable[(0 <= uentp->destuid && uentp->destuid < 6) ? + uentp->destuid : 0]; + else if (simple) + return word; + else if (uentp->in_chat && mode == CHATING) + sprintf(modestr, "%s (%s)", word, uentp->chatid); + else if (mode == TALK) + { + if (!isvisible_uid(uentp->destuid))/* Leeym ¹ï¤è(µµ¦â)Áô§Î */ + sprintf(modestr, "%s", "¥æ½Í ªÅ®ð");/* Leeym ¤j®a¦Û¤vµo´§§a¡I */ + else + sprintf(modestr, "%s %s", word, getuserid(uentp->destuid)); + } + else if (mode == M_FIVE) + { + if (!isvisible_uid(uentp->destuid)) + sprintf(modestr, "%s", "¤¤l´Ñ ªÅ®ð"); + else + sprintf(modestr, "%s %s", word, getuserid(uentp->destuid)); + } + else if (mode == CHC) + { + if (isvisible_uid(uentp->destuid)) + sprintf(modestr, "%s", "¤U¶H´Ñ"); + else + sprintf(modestr, "¤U¶H´Ñ %s", getuserid(uentp->destuid)); + } + else if (mode != PAGE && mode != TQUERY) + return word; + else + sprintf(modestr, "%s %s", word, getuserid(uentp->destuid)); + + return (modestr); +} + +int set_friend_bit(userinfo_t * me, userinfo_t * ui) { + int unum, *myfriends, hit=0, n; + +/* §PÂ_¹ï¤è¬O§_¬°§ÚªºªB¤Í ? */ + unum = ui->uid; + myfriends = me->friend; + while ((n = *myfriends++)) + { + if (unum == n) + { + hit = IFH; + break; + } + } + +/* §PÂ_§Ú¬O§_¬°¹ï¤èªºªB¤Í ? */ + myfriends = ui->friend; + while ((unum = *myfriends++)) + { + if (unum == me->uid) + { + hit |= HFM; + break; + } + } + +/* §PÂ_¹ï¤è¬O§_¬°§Úªº¤³¤H ? */ + + unum = ui->uid; + myfriends = me->reject; + while ((n = *myfriends++)) + { + if (unum == n) + { + hit |= IRH; + break; + } + } + +/* §PÂ_§Ú¬O§_¬°¹ï¤èªº¤³¤H ? */ + myfriends = ui->reject; + while ((unum = *myfriends++)) + { + if (unum == me->uid) + { + hit |= HRM; + break; + } + } + return hit; +} +int reverse_friend_stat(int stat) +{ + int stat1=0; + if(stat & IFH) + stat1 |=HFM; + if(stat & IRH) + stat1 |=HRM; + if(stat & HFM) + stat1 |=IFH; + if(stat & HRM) + stat1 |=IRH; + if(stat & IBH) + stat1 |=IBH; + return stat1; +} + +int login_friend_online(){ + userinfo_t *uentp; + int i, stat, stat1; + int offset=(int) (currutmp - &utmpshm->uinfo[0]); + for (i=0;i<utmpshm->number && currutmp->friendtotal<MAX_FRIEND; i++) + { + uentp = (utmpshm->sorted[utmpshm->currsorted][0][i]); + if(uentp && uentp->uid && (stat=set_friend_bit(currutmp,uentp))) + { + stat1=reverse_friend_stat(stat); + stat <<= 24; + stat |= (int) (uentp - &utmpshm->uinfo[0]); + currutmp->friend_online[currutmp->friendtotal++]=stat; + if(uentp!=currutmp && uentp->friendtotal<MAX_FRIEND) + { + stat1 <<= 24; + stat1 |= offset; + uentp->friend_online[uentp->friendtotal++]=stat1; + } + } + } + return 0; +} + +int logout_friend_online(){ + int i, j, k; + int offset=(int) (currutmp - &utmpshm->uinfo[0]); + userinfo_t *ui; + while(currutmp->friendtotal) + { + i = currutmp->friendtotal-1; + j = (currutmp->friend_online[i] & 0xFFFFFF); + currutmp->friend_online[i]=0; + ui = &utmpshm->uinfo[j]; + if(ui->pid && ui!=currutmp) + { + for(k=0; k<ui->friendtotal && + (int)(ui->friend_online[k] & 0xFFFFFF) !=offset; k++); + if(k<ui->friendtotal) + { + ui->friendtotal--; + ui->friend_online[k]=ui->friend_online[ui->friendtotal]; + ui->friend_online[ui->friendtotal]=0; + } + } + currutmp->friendtotal--; + currutmp->friend_online[currutmp->friendtotal]=0; + } + return 0; +} + + +int friend_stat(userinfo_t *me, userinfo_t * ui) +{ + int i, j, hit=0; +/* ¬ÝªO¦n¤Í */ + if (me->brc_id && ui->brc_id == me->brc_id) + { + hit = IBH; + } + for(i=0;me->friend_online[i];i++) + { + j = (me->friend_online[i] & 0xFFFFFF); + if(ui == &utmpshm->uinfo[j]) + { + hit |= me->friend_online[i] >>24; + break; + } + } + if (PERM_HIDE(ui)) + return hit & ST_FRIEND; + return hit; +} + +int isvisible_stat(userinfo_t * me, userinfo_t * uentp, int fri_stat) { + if (uentp->userid[0] == 0) + return 0; + + if (PERM_HIDE(uentp) && !(PERM_HIDE(me)))/* ¹ï¤èµµ¦âÁô§Î¦Ó§A¨S¦³ */ + return 0; + else if ((me->userlevel & PERM_SYSOP) || + ((fri_stat & HRM) && (fri_stat & HFM))) /* ¯¸ªø¬Ýªº¨£¥ô¦ó¤H */ + return 1; + + if (uentp->invisible && !(me->userlevel & PERM_SEECLOAK)) return 0; + + return (fri_stat & HRM) ? 0 : 1; +} + +int isvisible(userinfo_t * me, userinfo_t * uentp) { + return isvisible_stat(currutmp, uentp, friend_stat(me, uentp)); +} + +int isvisible_uid(int tuid){ + userinfo_t *uentp; + + if(!tuid || !(uentp = search_ulist(tuid))) + return 1; + return isvisible(currutmp, uentp); +} + +/* ¯u¹ê°Ê§@ */ +static void my_kick(userinfo_t * uentp) { + char genbuf[200]; + + getdata(1, 0, msg_sure_ny, genbuf, 4, LCECHO); + clrtoeol(); + if (genbuf[0] == 'y') + { + sprintf(genbuf, "%s (%s)", uentp->userid, uentp->username); + log_usies("KICK ", genbuf); + if((uentp->pid <= 0 || kill(uentp->pid, SIGHUP) == -1) && (errno == ESRCH)) + purge_utmp(uentp); + outs("½ð¥X¥hÅo"); + } + else + outs(msg_cancel); + pressanykey(); +} + +static void chicken_query(char *userid) { + char buf[100]; + + if (getuser(userid)) + { + if (xuser.mychicken.name[0]) + { + time_diff(&(xuser.mychicken)); + if (!isdeadth(&(xuser.mychicken))) + { + show_chicken_data(&(xuser.mychicken), NULL); + sprintf(buf, "\n\n¥H¤W¬O %s ªºÃdª«¸ê®Æ..", userid); + outs(buf); + } + } + else + { + move(1, 0); + clrtobot(); + sprintf(buf, "\n\n%s ¨Ã¨S¦³¾iÃdª«..", userid); + outs(buf); + } + pressanykey(); + } +} + +int my_query(char *uident) { + userec_t muser; + int tuid, i, fri_stat=0; + unsigned long int j; + userinfo_t *uentp; + static const char *money[10] = + {"¶Å¥x°ª¿v", "¨ª³h", "²M´H", "´¶³q", "¤p±d", + "¤p´I", "¤¤´I", "¤j´I¯Î", "´I¥i¼Ä°ê", "¤ñº¸»\\¤Ñ"}, + *sex[8] = + {MSG_BIG_BOY, MSG_BIG_GIRL, + MSG_LITTLE_BOY, MSG_LITTLE_GIRL, + MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME}; + + + if ((tuid = getuser(uident))) + { + memcpy(&muser, &xuser, sizeof(muser)); + move(1, 0); + clrtobot(); + move(1, 0); + setutmpmode(TQUERY); + currutmp->destuid = tuid; + + j = muser.money; + for (i = 0; i < 10 && j > 10; i++) + j /= 10; + prints("¡m¢×¢Ò¼ÊºÙ¡n%s(%s)%*s¡m¸gÀÙª¬ªp¡n%s\n", + muser.userid, + muser.username, + 26 - strlen(muser.userid) - strlen(muser.username), "", + money[i]); + prints("¡m¤W¯¸¦¸¼Æ¡n%d¦¸", muser.numlogins); + move(2, 40); + prints("¡m¤å³¹½g¼Æ¡n%d½g\n", muser.numposts); + + if((uentp = (userinfo_t *) search_ulist(tuid))) + fri_stat=friend_stat(currutmp, uentp); + prints("\033[1;33m¡m¥Ø«e°ÊºA¡n%-28.28s\033[m", + (uentp && isvisible_stat(currutmp, uentp, fri_stat)) ? + modestring(uentp, 0) : "¤£¦b¯¸¤W"); + + outs(((uentp && uentp->mailalert) || load_mailalert(muser.userid)) + ? "¡m¨p¤H«H½c¡n¦³·s¶i«H¥óÁÙ¨S¬Ý\n" : + "¡m¨p¤H«H½c¡n©Ò¦³«H¥ó³£¬Ý¹L¤F\n"); + prints("¡m¤W¦¸¤W¯¸¡n%-28.28s¡m¤W¦¸¬G¶m¡n%s\n", + Cdate(&muser.lastlogin), + (muser.lasthost[0] ? muser.lasthost : "(¤£¸Ô)")); + if ((uentp && fri_stat&HFM) || HAS_PERM(PERM_SYSOP)) + prints("¡m ©Ê §O ¡n%-28.28s¡m¨p¦³°]²£¡n%ld »È¨â\n", + sex[muser.sex % 8], + muser.money); + prints("¡m¤¤l´Ñ¾ÔÁZ¡n%3d ³Ó %3d ±Ñ %3d ©M " + "¡m¶H´Ñ¾ÔÁZ¡n%3d ³Ó %3d ±Ñ %3d ©M", + muser.five_win, muser.five_lose, muser.five_tie, + muser.chc_win, muser.chc_lose, muser.chc_tie); + showplans(uident); + pressanykey(); + return FULLUPDATE; + } + return DONOTHING; +} + +static char t_last_write[200] = ""; + +void water_scr(water_t **currwater, int which, char type) +{ + if( type == 1 ){ + int i; + int colors[] = {33, 37, 33, 37, 33}; + move(8 + which, 28);prints(" "); + move(8 + which, 28); + prints("\033[1;37;45m %-14s \033[0m", currwater[which]->userid); + for( i = 0 ; i < 5 ; ++i ){ + move(16 + i, 4); + prints(" "); + move(16 + i, 4); + if( currwater[which]->msg[ (currwater[which]->top-i+4) % 5 ].last_call_in[0] != 0 ) + prints("\033[0m \033[1;%d;44m¡¹%-64s\033[0m \n", + colors[i], + currwater[which]->msg[ (currwater[which]->top-i+4) % 5 ].last_call_in); + else + prints("\033[0m¡@\n"); + } + move(0, 0);prints(" "); + move(0, 0); + prints("\033[0m¤ÏÀ» %s:", currwater[which]->userid); + clrtoeol(); + move(0, strlen(currwater[which]->userid) + 6); + } + else{ + move(8 + which, 28); + prints("123456789012345678901234567890"); + // refresh(); + move(8 + which, 28); + prints("\033[1;37;44m %-13s¡@\033[0m", currwater[which]->userid); + // refresh(); + } +} + +void my_write2(void) +{ + int i, ch, currstat0, currwater_usies; + char genbuf[256], msg[80], done = 0, c0, which; + water_t *tw, *currwater[5]; + unsigned char mode0; + + watermode = 0; + currstat0 = currstat; + c0 = currutmp->chatid[0]; + mode0 = currutmp->mode; + currutmp->mode = 0; + currutmp->chatid[0] = 3; + currstat = XMODE; + + // init screen + memcpy(currwater, swater, sizeof(water_t*) * 5); + currwater_usies = water_usies; + move(7, 28); + prints("\033[1;33;46m ¡ô ¤ô²y¤ÏÀ»¹ï¶H ¡õ\033[0m"); + for( i = 0 ; i < 5 ; ++i ) + if( currwater[i] == NULL || currwater[i]->pid == 0 ) + break; + else + water_scr(currwater, i, 0); + move(15, 4); + prints("\033[0m \033[1;35m¡º\033[1;36m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\033[1;35m¡º\033[0m "); + move(22, 4); + prints(" \033[1;35m¡º\033[1;36m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\033[1;35m¡º\033[0m "); + move(21, 4);prints(" "); + move(21, 4); + prints("\033[0m \033[1;37;46m%-66s\033[0m \n", t_last_write); + water_scr(currwater, 0, 1); + refresh(); + + which = 0; + do{ + switch( (ch = igetkey()) ){ + case Ctrl('T'): + case KEY_UP: + if( currwater_usies != 1 ){ + water_scr(currwater, which, 0); + which = (which - 1 + currwater_usies) % currwater_usies; + water_scr(currwater, which, 1); + refresh(); + } + break; + + case KEY_DOWN: + case Ctrl('R'): + if( currwater_usies != 1 ){ + water_scr(currwater, which, 0); + which = (which + 1 + currwater_usies) % currwater_usies; + water_scr(currwater, which, 1); + refresh(); + } + break; + + case KEY_LEFT: + done = 1; + break; + + default: + done = 1; + watermode = 1; + tw = currwater[(int)which]; + + if( ch != '\r' && ch != '\n' ){ + msg[0] = ch, msg[1] = 0; + } + else + msg[0] = 0; + move(0, 0);prints("\033[m"); clrtoeol(); + refresh(); + sprintf(genbuf, "§ðÀ» %s:", tw->userid); + if( !oldgetdata(0, 0, genbuf, msg, + 80-strlen(tw->userid)-6, DOECHO) ) + break; + + my_write(tw->pid, msg, tw->userid, 4); + break; + } + } while( !done ); + + watermode = -1; + currstat = currstat0; + currutmp->chatid[0] = c0; + currutmp->mode = mode0; +} + +/* + ³Q©I¥sªº®É¾÷: + 1. ¥á¸s²Õ¤ô²y flag = 1 (pre-edit) + 2. ¦^¤ô²y flag = 0 + 3. ¤W¯¸aloha flag = 2 (pre-edit) + 4. ¼s¼½ flag = 3 if SYSOP, otherwise flag = 1 (pre-edit) + 5. ¥á¤ô²y flag = 0 + 6. my_write2 flag = 4 (pre-edit) but confirm +*/ +int my_write(pid_t pid, char *prompt, char *id, int flag) { + int len, currstat0 = currstat, fri_stat; + char msg[80], destid[IDLEN + 1]; + char genbuf[200], buf[200], c0 = currutmp->chatid[0]; + unsigned char mode0 = currutmp->mode; + time_t now; + struct tm *ptime; + userinfo_t *uin; + uin = (userinfo_t *)search_ulist_pid(pid); + strcpy(destid, id); + + if(!uin && !(flag == 0 && water_which->count> 0)) { + outmsg("\033[1;33;41mÁV¿|! ¹ï¤è¤w¸¨¶]¤F(¤£¦b¯¸¤W)! \033[37m~>_<~\033[m"); + clrtoeol(); + refresh(); + watermode = -1; + return 0; + } + currutmp->mode = 0; + currutmp->chatid[0] = 3; + currstat = XMODE; + + time(&now); + ptime = localtime(&now); + + if(flag == 0) { + /* ¤@¯ë¤ô²y */ + watermode = 0; + if(!(len = getdata(0, 0, prompt, msg, 56, DOECHO))) { + outmsg("\033[1;33;42mºâ¤F! ©ñ§A¤@°¨...\033[m"); + clrtoeol(); + refresh(); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + watermode = -1; + return 0; + } + + if(watermode > 0) { + int i; + + i = (water_which->top- watermode + MAX_REVIEW) % MAX_REVIEW; + uin = (userinfo_t *)search_ulist_pid(water_which->msg[i].pid); + strcpy(destid, water_which->msg[i].userid); + } + } else { + /* pre-edit ªº¤ô²y */ + strcpy(msg, prompt); + len = strlen(msg); + } + + watermode = -1; + strip_ansi(msg, msg, 0); + if(uin && *uin->userid && (flag == 0 || flag == 4)) { + sprintf(buf, "¥áµ¹ %s : %s [Y/n]?", uin->userid, msg); + getdata(0, 0, buf, genbuf, 3, LCECHO); + if(genbuf[0] == 'n') { + outmsg("\033[1;33;42mºâ¤F! ©ñ§A¤@°¨...\033[m"); + clrtoeol(); + refresh(); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + watermode = -1; + return 0; + } + } + + if(!uin || !*uin->userid || strcasecmp(destid, uin->userid)) { + outmsg("\033[1;33;41mÁV¿|! ¹ï¤è¤w¸¨¶]¤F(¤£¦b¯¸¤W)! \033[37m~>_<~\033[m"); + clrtoeol(); + refresh(); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + return 0; + } + + fri_stat=friend_stat(currutmp, uin); + time(&now); + if(flag != 2) { /* aloha ªº¤ô²y¤£¥Î¦s¤U¨Ó */ + /* ¦s¨ì¦Û¤vªº¤ô²yÀÉ */ + if(!fp_writelog) + { + sethomefile(genbuf, cuser.userid, fn_writelog); + fp_writelog = fopen(genbuf, "a"); + } + if(fp_writelog) { + fprintf(fp_writelog, "To %s: %s [%s]\n", + uin->userid, msg, Cdatelite(&now)); + snprintf(t_last_write, 66, "To %s: %s", uin->userid, msg); + } + } + + if(flag == 3 && uin->msgcount) { + /* ¤£À´ */ + uin->destuip = currutmp - &utmpshm->uinfo[0]; + uin->sig = 2; + if(uin->pid > 0) kill(uin->pid, SIGUSR1); + } else if(flag != 2 && + !HAS_PERM(PERM_SYSOP) && + (uin->pager == 3 || + uin->pager == 2 || + (uin->pager == 4 && + !(fri_stat & HFM)))) + outmsg("\033[1;33;41mÁV¿|! ¹ï¤è¨¾¤ô¤F! \033[37m~>_<~\033[m"); + else { + if(uin->msgcount < MAX_MSGS) { + unsigned char pager0 = uin->pager; + + uin->pager = 2; + uin->msgs[uin->msgcount].pid = currpid; + strcpy(uin->msgs[uin->msgcount].userid, cuser.userid); + strcpy(uin->msgs[uin->msgcount++].last_call_in, msg); + uin->pager = pager0; + } else if (flag != 2) + outmsg("\033[1;33;41mÁV¿|! ¹ï¤è¤£¦æ¤F! (¦¬¨ì¤Ó¦h¤ô²y) \033[37m@_@\033[m"); + + if(uin->msgcount == 1 && (uin->pid <= 0 || kill(uin->pid, SIGUSR2) == -1) && flag != 2) + outmsg("\033[1;33;41mÁV¿|! ¨S¥´¤¤! \033[37m~>_<~\033[m"); + else if(uin->msgcount == 1 && flag != 2) + outmsg("\033[1;33;44m¤ô²y¯{¹L¥h¤F! \033[37m*^o^*\033[m"); + else if(uin->msgcount > 1 && uin->msgcount < MAX_MSGS && flag != 2) + outmsg("\033[1;33;44m¦A¸É¤W¤@²É! \033[37m*^o^*\033[m"); + } + + clrtoeol(); + refresh(); + + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + return 1; +} +void t_display_new() { + static int t_display_new_flag=0; + int i, off=2; + if (t_display_new_flag) + return; + else + t_display_new_flag = 1; + + if( WATERMODE(WATER_ORIG) ) + water_which = &water[0]; + else + off =3; + + if (water[0].count && watermode > 0){ + move(1, 0); + outs("¢w¢w¢w¢w¢w¢w¢w¤ô¢w²y¢w¦^¢wÅU¢w¢w¢w"); + outs(WATERMODE(WATER_ORIG) ? + "¢w¢w¢w¢w¢w¢w¥Î[Ctrl-R Ctrl-T]Áä¤Á´«¢w¢w¢w¢w¢w" : + "¥Î[Ctrl-R Ctrl-T Ctrl-E Ctrl-W ]Áä¤Á´«¢w¢w¢w¢w"); + if( WATERMODE(WATER_NEW) ){ + move(2, 0); + clrtoeol(); + for (i = 0; i<6 ; i++){ + if(i>0) + prints("%s%-13.13s\033[m", + swater[i-1]==water_which?"\033[1;33;47m ": + " ", + swater[i-1] ? swater[i-1]->userid:""); + else + prints("%s ¥þ³¡ \033[m", + water_which==&water[0]?"\033[1;33;45m ": + " "); + } + } + + for (i = 0; i < water_which->count; i++){ + int a = (water_which->top - i - 1 + MAX_REVIEW) % MAX_REVIEW, + len = 75-strlen(water_which->msg[a].last_call_in) + -strlen(water_which->msg[a].userid); + if(len<0) len=0; + + move(i + (WATERMODE(WATER_ORIG)?2:3), 0); + clrtoeol(); + if (watermode - 1 != i) + prints("\033[1;33;46m %s \033[37;45m %s \033[m%*s", + water_which->msg[a].userid, + water_which->msg[a].last_call_in, len, + ""); + else + prints("\033[1;44m>\033[1;33;47m%s " + "\033[37;45m %s \033[m%*s", + water_which->msg[a].userid, + water_which->msg[a].last_call_in, + len,""); + } + + if (t_last_write[0]){ + move(i + off, 0); + clrtoeol(); + prints(t_last_write); + i++; + } + move(i + off, 0); + outs("¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w"); + if( WATERMODE(WATER_NEW)) + while( i++ <= water[0].count ) { + move(i + off, 0); + clrtoeol(); + } + } + + t_display_new_flag = 0; +} +#if 0 +void t_display_new() { + int i, which=water_which; + char buf[200]; + + if (t_display_new_flag) + return; + else + t_display_new_flag = 1; + + if (oldmsg_count && watermode > 0) + { + move(1, 0); + outs( + "¢w¢w¢w¢w¢w¢w¢w¤ô¢w²y¢w¦^¢wÅU¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¥Î[Ctrl-R Ctrl-T]Áä¤Á´«¢w¢w¢w¢w¢w"); + move(2, 0); + prints(" |"); + for (i = 0; i<5 && water[i].pid != 0; i++) + prints(" %s%13.13s \033[m|",which==i?"\033[1;33m":"", + water[i].userid); + + for( i = 0 ; i < 5 && + water[which].msg[ (water[which].msgtop-i+4) % 5 ][0] != 0; ++i ){ + move(3 + i, 0); + if (watermode - 1 != i) + sprintf(buf, "\033[1;33;46m %s \033[37;45m %s \033[m", + water[which].userid, + water[which].msg[ (water[which].msgtop-i+4) % 5 ]); + else + sprintf(buf, "\033[1;44m>\033[1;33;47m%s \033[37;45m %s \033[m", + water[which].userid, + water[which].msg[ (water[which].msgtop-i+4) % 5 ]); + } + /* + for (i = 0; i < oldmsg_count; i++) + { + int a = (water[water_which].top - i - 1 + MAX_REVIEW) % MAX_REVIEW; + + move(i + 3, 0); + clrtoeol(); + if (watermode - 1 != i) + sprintf(buf, "\033[1;33;46m %s \033[37;45m %s \033[m", + oldmsg[a].userid, oldmsg[a].last_call_in); + else + sprintf(buf, "\033[1;44m>\033[1;33;47m%s " + "\033[37;45m %s \033[m", + oldmsg[a].userid, oldmsg[a].last_call_in); + outs(buf); + } +*/ + if (t_last_write[0]) + { + move(i + 3, 0); + clrtoeol(); + outs(t_last_write); + i++; + } + move(i + 3, 0); + outs("¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w"); + } + t_display_new_flag = 0; +} +#endif + +int t_display() { + char genbuf[200], ans[4]; + if(fp_writelog) + { fclose(fp_writelog); fp_writelog=NULL;} + setuserfile(genbuf, fn_writelog); + if (more(genbuf, YEA) != -1) + { + getdata(b_lines - 1, 0, "²M°£(C) ²¾¦Ü³Æ§Ñ¿ý(M) «O¯d(R) (C/M/R)?[R]", + ans, 3, LCECHO); + if (*ans == 'm') + { + fileheader_t mymail; + char title[128], buf[80]; + + sethomepath(buf, cuser.userid); + stampfile(buf, &mymail); + + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[³Æ.§Ñ.¿ý]"); + strcpy(mymail.title, "¼ö½u\033[37;41m°O¿ý\033[m"); + sethomedir(title, cuser.userid); + Rename(genbuf, buf); + append_record(title, &mymail, sizeof(mymail)); + } + else if (*ans == 'c') + unlink(genbuf); + return FULLUPDATE; + } + return DONOTHING; +} + +static void do_talk_nextline(talkwin_t * twin) { + twin->curcol = 0; + if (twin->curln < twin->eline) + ++(twin->curln); + else + region_scroll_up(twin->sline, twin->eline); + move(twin->curln, twin->curcol); +} + +static void do_talk_char(talkwin_t * twin, int ch) { + extern screenline_t *big_picture; + screenline_t *line; + int i; + char ch0, buf[81]; + + if (isprint2(ch)) + { + ch0 = big_picture[twin->curln].data[twin->curcol]; + if (big_picture[twin->curln].len < 79) + move(twin->curln, twin->curcol); + else + do_talk_nextline(twin); + outc(ch); + ++(twin->curcol); + line = big_picture + twin->curln; + if (twin->curcol < line->len) + { /* insert */ + ++(line->len); + memcpy(buf, line->data + twin->curcol, 80); + save_cursor(); + do_move(twin->curcol, twin->curln); + ochar(line->data[twin->curcol] = ch0); + for (i = twin->curcol + 1; i < line->len; i++) + ochar(line->data[i] = buf[i - twin->curcol - 1]); + restore_cursor(); + } + line->data[line->len] = 0; + return; + } + + switch (ch) + { + case Ctrl('H'): + case '\177': + if (twin->curcol == 0) + return; + line = big_picture + twin->curln; + --(twin->curcol); + if (twin->curcol < line->len) + { + --(line->len); + save_cursor(); + do_move(twin->curcol, twin->curln); + for (i = twin->curcol; i < line->len; i++) + ochar(line->data[i] = line->data[i + 1]); + line->data[i] = 0; + ochar(' '); + restore_cursor(); + } + move(twin->curln, twin->curcol); + return; + case Ctrl('D'): + line = big_picture + twin->curln; + if (twin->curcol < line->len) + { + --(line->len); + save_cursor(); + do_move(twin->curcol, twin->curln); + for (i = twin->curcol; i < line->len; i++) + ochar(line->data[i] = line->data[i + 1]); + line->data[i] = 0; + ochar(' '); + restore_cursor(); + } + return; + case Ctrl('G'): + bell(); + return; + case Ctrl('B'): + if (twin->curcol > 0) + { + --(twin->curcol); + move(twin->curln, twin->curcol); + } + return; + case Ctrl('F'): + if (twin->curcol < 79) + { + ++(twin->curcol); + move(twin->curln, twin->curcol); + } + return; + case KEY_TAB: + twin->curcol += 8; + if (twin->curcol > 80) + twin->curcol = 80; + move(twin->curln, twin->curcol); + return; + case Ctrl('A'): + twin->curcol = 0; + move(twin->curln, twin->curcol); + return; + case Ctrl('K'): + clrtoeol(); + return; + case Ctrl('Y'): + twin->curcol = 0; + move(twin->curln, twin->curcol); + clrtoeol(); + return; + case Ctrl('E'): + twin->curcol = big_picture[twin->curln].len; + move(twin->curln, twin->curcol); + return; + case Ctrl('M'): + case Ctrl('J'): + line = big_picture + twin->curln; + strncpy(buf, line->data, line->len); + buf[line->len] = 0; + do_talk_nextline(twin); + break; + case Ctrl('P'): + line = big_picture + twin->curln; + strncpy(buf, line->data, line->len); + buf[line->len] = 0; + if (twin->curln > twin->sline) + { + --(twin->curln); + move(twin->curln, twin->curcol); + } + break; + case Ctrl('N'): + line = big_picture + twin->curln; + strncpy(buf, line->data, line->len); + buf[line->len] = 0; + if (twin->curln < twin->eline) + { + ++(twin->curln); + move(twin->curln, twin->curcol); + } + break; + } + trim(buf); + if (*buf) + fprintf(flog, "%s%s: %s%s\n", + (twin->eline == b_lines - 1) ? "\033[1;35m" : "", + (twin->eline == b_lines - 1) ? + getuserid(currutmp->destuid) : cuser.userid, buf, + (ch == Ctrl('P')) ? "\033[37;45m(Up)\033[m" : "\033[m"); +} + +static void do_talk(int fd) { + struct talkwin_t mywin, itswin; + char mid_line[128], data[200]; + int i, datac, ch; + int im_leaving = 0; + FILE *log; + struct tm *ptime; + time_t now; + char genbuf[200], fpath[100]; + + time(&now); + ptime = localtime(&now); + + sethomepath(fpath, cuser.userid); + strcpy(fpath, tempnam(fpath, "talk_")); + flog = fopen(fpath, "w"); + + setuserfile(genbuf, fn_talklog); + + if ((log = fopen(genbuf, "w"))) + fprintf(log, "[%d/%d %d:%02d] & %s\n", + ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, + ptime->tm_min, save_page_requestor); + setutmpmode(TALK); + + ch = 58 - strlen(save_page_requestor); + sprintf(genbuf, "%s¡i%s", cuser.userid, cuser.username); + i = ch - strlen(genbuf); + if (i >= 0) + i = (i >> 1) + 1; + else + { + genbuf[ch] = '\0'; + i = 1; + } + memset(data, ' ', i); + data[i] = '\0'; + + sprintf(mid_line, "\033[1;46;37m ½Í¤Ñ»¡¦a \033[45m%s%s¡j" + " »P %s%s\033[0m", data, genbuf, save_page_requestor, data); + + memset(&mywin, 0, sizeof(mywin)); + memset(&itswin, 0, sizeof(itswin)); + + i = b_lines >> 1; + mywin.eline = i - 1; + itswin.curln = itswin.sline = i + 1; + itswin.eline = b_lines - 1; + + clear(); + move(i, 0); + outs(mid_line); + move(0, 0); + + add_io(fd, 0); + + while (1) + { + ch = igetkey(); + if (ch == I_OTHERDATA) + { + datac = recv(fd, data, sizeof(data), 0); + if (datac <= 0) + break; + for (i = 0; i < datac; i++) + do_talk_char(&itswin, data[i]); + } + else + { + if (ch == Ctrl('C')) + { + if (im_leaving) + break; + move(b_lines, 0); + clrtoeol(); + outs("¦A«ö¤@¦¸ Ctrl-C ´N¥¿¦¡¤¤¤î½Í¸ÜÅo¡I"); + im_leaving = 1; + continue; + } + if (im_leaving) + { + move(b_lines, 0); + clrtoeol(); + im_leaving = 0; + } + switch (ch) + { + case KEY_LEFT: /* §â2byteªºÁä§ï¬°¤@byte */ + ch = Ctrl('B'); + break; + case KEY_RIGHT: + ch = Ctrl('F'); + break; + case KEY_UP: + ch = Ctrl('P'); + break; + case KEY_DOWN: + ch = Ctrl('N'); + break; + } + data[0] = (char) ch; + if (send(fd, data, 1, 0) != 1) + break; + if (log) + fprintf(log, "%c", (ch == Ctrl('M')) ? '\n' : (char) *data); + do_talk_char(&mywin, *data); + } + } + if (log) + fclose(log); + + add_io(0, 0); + close(fd); + + if (flog) + { + char ans[4]; + extern screenline_t *big_picture; + extern unsigned char scr_lns; + int i; + + time(&now); + fprintf(flog, "\n\033[33;44mÂ÷§Oµe± [%s] ... \033[m\n", + Cdatelite(&now)); + for (i = 0; i < scr_lns; i++) + fprintf(flog, "%.*s\n", big_picture[i].len, big_picture[i].data); + fclose(flog); + more(fpath, NA); + getdata(b_lines - 1, 0, "²M°£(C) ²¾¦Ü³Æ§Ñ¿ý(M). (C/M)?[C]", + ans, 4, LCECHO); + if (*ans == 'm') + { + fileheader_t mymail; + char title[128]; + + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mymail); + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[³Æ.§Ñ.¿ý]"); + sprintf(mymail.title, "¹ï¸Ü°O¿ý \033[1;36m(%s)\033[m", + getuserid(currutmp->destuid)); + sethomedir(title, cuser.userid); + Rename(fpath, genbuf); + append_record(title, &mymail, sizeof(mymail)); + } + else + unlink(fpath); + flog = 0; + } + setutmpmode(XINFO); +} + +#define lockreturn(unmode, state) if(lockutmpmode(unmode, state)) return + +static void my_talk(userinfo_t * uin, int fri_stat) { + int sock, msgsock, length, ch, error = 0; + struct sockaddr_in server; + pid_t pid; + char c; + char genbuf[4]; + + unsigned char mode0 = currutmp->mode; + + ch = uin->mode; + strcpy(currauthor, uin->userid); + + if (ch == EDITING || ch == TALK || ch == CHATING || ch == PAGE || + ch == MAILALL || ch == MONITOR || ch == M_FIVE || ch == CHC || + (!ch && (uin->chatid[0] == 1 || uin->chatid[0] == 3)) || + uin->lockmode == M_FIVE || uin->lockmode == CHC) + { + outs("¤H®a¦b¦£°Õ"); + } + else if (!HAS_PERM(PERM_SYSOP) && + ( + ((fri_stat& HRM) && !(fri_stat& HFM)) || + ((!uin->pager) && !(fri_stat & HFM)) + ) + ) + { + outs("¹ï¤èÃö±¼©I¥s¾¹¤F"); + } + else if (!HAS_PERM(PERM_SYSOP) && + ( + ((fri_stat & HRM) && !(fri_stat& HFM)) || + uin->pager == 2 + ) + ) + { + outs("¹ï¤è©Þ±¼©I¥s¾¹¤F"); + } + else if (!HAS_PERM(PERM_SYSOP) && + !(fri_stat & HFM) && uin->pager == 4) + { + outs("¹ï¤è¥u±µ¨ü¦n¤Íªº©I¥s"); + } + else if (!(pid = uin->pid) /*|| (kill(pid, 0) == -1) */ ) + { +// resetutmpent(); + outs(msg_usr_left); + } + else + { + showplans(uin->userid); + getdata(2, 0, "n©M¥L(¦o) (T)½Í¤Ñ(F)¤U¤¤l´Ñ(P)°«Ãdª«" + "(C)¤U¶H´Ñ(D)¤U·t´Ñ(N)¨S¨Æ§ä¿ù¤H¤F?[N] ", genbuf, 4, LCECHO); + switch (*genbuf) + { + case 'y': + case 't': + uin->sig = SIG_TALK; + break; + case 'f': + lockreturn(M_FIVE, LOCK_THIS); + uin->sig = SIG_GOMO; + break; + case 'c': + lockreturn(CHC, LOCK_THIS); + uin->sig = SIG_CHC; + break; + case 'd': + uin->sig = SIG_DARK; + break; + case 'p': + reload_chicken(); + getuser(uin->userid); + if (uin->lockmode == CHICKEN || currutmp->lockmode == CHICKEN) + error = 1; + if (!cuser.mychicken.name[0] || !xuser.mychicken.name[0]) + error = 2; + if (error) + { + outmsg(error == 2 ? "¨Ã«D¨â¤H³£¾iÃdª«" : + "¦³¤@¤èªºÃdª«¥¿¦b¨Ï¥Î¤¤"); + bell(); + refresh(); + sleep(1); + return; + } + uin->sig = SIG_PK; + break; + default: + return; + } + + uin->turn = 1; + currutmp->turn = 0; + strcpy(uin->mateid, currutmp->userid); + strcpy(currutmp->mateid, uin->userid); + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) + { + perror("sock err"); + unlockutmpmode(); + return; + } + server.sin_family = PF_INET; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = 0; + if (bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0) + { + close(sock); + perror("bind err"); + unlockutmpmode(); + return; + } + length = sizeof(server); + if (getsockname(sock, (struct sockaddr *) &server, &length) < 0) + { + close(sock); + perror("sock name err"); + unlockutmpmode(); + return; + } + currutmp->sockactive = YEA; + currutmp->sockaddr = server.sin_port; + currutmp->destuid = uin->uid; + setutmpmode(PAGE); + uin->destuip = currutmp - &utmpshm->uinfo[0]; + if(pid > 0) kill(pid, SIGUSR1); + clear(); + prints("¥¿©I¥s %s.....\nÁä¤J Ctrl-D ¤¤¤î....", uin->userid); + + listen(sock, 1); + add_io(sock, 5); + while (1) + { + ch = igetch(); + if (ch == I_TIMEOUT) + { + ch = uin->mode; + if (!ch && uin->chatid[0] == 1 && + uin->destuip == currutmp - &utmpshm->uinfo[0]) + { + bell(); + outmsg("¹ï¤è¦^À³¤¤..."); + refresh(); + } + else if (ch == EDITING || ch == TALK || ch == CHATING || + ch == PAGE || ch == MAILALL || ch == MONITOR || + ch == M_FIVE || ch == CHC || + (!ch && (uin->chatid[0] == 1 || + uin->chatid[0] == 3))) + { + add_io(0, 0); + close(sock); + currutmp->sockactive = currutmp->destuid = 0; + outmsg("¤H®a¦b¦£°Õ"); + pressanykey(); + unlockutmpmode(); + return; + } + else + { +#ifdef linux + add_io(sock, 20); /* added for linux... achen */ +#endif + move(0, 0); + outs("¦A"); + bell(); + + uin->destuip = currutmp - &utmpshm->uinfo[0]; + if(pid <= 0 || kill(pid, SIGUSR1) == -1) + { +#ifdef linux + add_io(sock, 20); /* added 4 linux... achen */ +#endif + outmsg(msg_usr_left); + refresh(); + pressanykey(); + unlockutmpmode(); + return; + } + continue; + } + } + + if (ch == I_OTHERDATA) + break; + + if (ch == '\004') + { + add_io(0, 0); + close(sock); + currutmp->sockactive = currutmp->destuid = 0; + unlockutmpmode(); + return; + } + } + + msgsock = accept(sock, (struct sockaddr *) 0, (int *) 0); + if (msgsock == -1) + { + perror("accept"); + unlockutmpmode(); + return; + } + add_io(0, 0); + close(sock); + currutmp->sockactive = NA; + read(msgsock, &c, sizeof c); + + if (c == 'y') + { + sprintf(save_page_requestor, "%s (%s)", + uin->userid, uin->username); + /* gomo */ + switch (uin->sig) + { + case SIG_DARK: + main_dark(msgsock, uin); + break; + case SIG_PK: + chickenpk(msgsock); + break; + case SIG_GOMO: + gomoku(msgsock); + break; + case SIG_CHC: + chc(msgsock); + break; + case SIG_TALK: + default: + do_talk(msgsock); + } + } + else + { + move(9, 9); + outs("¡i¦^µ¡j "); + switch (c) + { + case 'a': + outs("§Ú²{¦b«Ü¦£¡A½Ðµ¥¤@·|¨à¦A call §Ú¡A¦n¶Ü¡H"); + break; + case 'b': + prints("¹ï¤£°_¡A§Ú¦³¨Æ±¡¤£¯à¸ò§A %s....", sig_des[uin->sig]); + break; + case 'd': + outs("§ÚnÂ÷¯¸Åo..¤U¦¸¦A²á§a.........."); + break; + case 'c': + outs("½Ð¤£n§n§Ú¦n¶Ü¡H"); + break; + case 'e': + outs("§ä§Ú¦³¨Æ¶Ü¡H½Ð¥ý¨Ó«Hò...."); + break; + case 'f': + { + char msgbuf[60]; + + read(msgsock, msgbuf, 60); + prints("¹ï¤£°_¡A§Ú²{¦b¤£¯à¸ò§A %s¡A¦]¬°\n", sig_des[uin->sig]); + move(10, 18); + outs(msgbuf); + } + break; + case '1': + prints("%s¡H¥ý®³100»È¨â¨Ó..", sig_des[uin->sig]); + break; + case '2': + prints("%s¡H¥ý®³1000»È¨â¨Ó..", sig_des[uin->sig]); + break; + default: + prints("§Ú²{¦b¤£·Q %s °Õ.....:)", sig_des[uin->sig]); + } + close(msgsock); + } + } + currutmp->mode = mode0; + currutmp->destuid = 0; + unlockutmpmode(); + pressanykey(); +} + +/* ¿ï³æ¦¡²á¤Ñ¤¶± */ +#define US_PICKUP 1234 +#define US_RESORT 1233 +#define US_ACTION 1232 +#define US_REDRAW 1231 + +static void t_showhelp() { + clear(); + + outs("\033[36m¡i ¥ð¶¢²á¤Ñ¨Ï¥Î»¡©ú ¡j\033[m\n\n" + "(¡ö)(e) µ²§ôÂ÷¶} (h) ¬Ý¨Ï¥Î»¡©ú\n" + "(¡ô)/(¡õ)(n) ¤W¤U²¾°Ê (TAB) ¤Á´«±Æ§Ç¤è¦¡\n" + "(PgUp)(^B) ¤W¶¿ï³æ ( )(PgDn)(^F) ¤U¶¿ï³æ\n" + "(Hm)/($)(Ed) º/§À (S) " + "¨Ó·½/¦n¤Í´yz/¾ÔÁZ ¤Á´«\n" + "(m) ±H«H (q/c) " + "¬d¸ßºô¤Í/Ãdª«\n" + "(r) ¾\\Ū«H¥ó (l) ¬Ý¤W¦¸¼ö°T\n" + "(f) ¥þ³¡/¦n¤Í¦Cªí (¼Æ¦r) ¸õ¦Ü¸Ó¨Ï¥ÎªÌ\n" + "(p) ¤Á´«©I¥s¾¹ (g/i) µ¹¿ú/¤Á´«¤ß±¡\n" + "(a/d/o) ¦n¤Í ¼W¥[/§R°£/קï (/)(s) ºô¤ÍID/¼ÊºÙ·j´M"); + + if (HAS_PERM(PERM_PAGE)) + { + outs("\n\n\033[36m¡i ¥æ½Í±M¥ÎÁä ¡j\033[m\n\n" + "(¡÷)(t)(Enter) ¸ò¥L¡þ¦o²á¤Ñ\n" + "(w) ¼ö½u Call in\n" + "(b) ¹ï¦n¤Í¼s¼½ (¤@©wn¦b¦n¤Í¦Cªí¤¤)\n" + "(^R) §Y®É¦^À³ (¦³¤H Call in §A®É)"); + } + + if (HAS_PERM(PERM_SYSOP)) + { + outs("\n\n\033[36m¡i ¯¸ªø±M¥ÎÁä ¡j\033[m\n\n"); + if (HAS_PERM(PERM_SYSOP)) + outs("(u)/(H) ³]©w¨Ï¥ÎªÌ¸ê®Æ/¤Á´«Áô§Î¼Ò¦¡\n"); + outs("(R)/(K) ¬d¸ß¨Ï¥ÎªÌªº¯u¹ê©m¦W/§âÃa³J½ð¥X¥h\n"); + } + pressanykey(); +} + +static int listcuent(userinfo_t * uentp) { + if((!uentp->invisible || HAS_PERM(PERM_SYSOP) || HAS_PERM(PERM_SEECLOAK))) + AddNameList(uentp->userid); + return 0; +} + +static void creat_list() { + CreateNameList(); + apply_ulist(listcuent); +} + +static int search_pickup(int num, int actor, pickup_t pklist[]) { + char genbuf[IDLEN + 2]; + + move(1, 0); + creat_list(); + namecomplete(msg_uid, genbuf); + if (genbuf[0]) + { + int n = (num + 1) % actor; + while (n != num) + { + if (!strcasecmp(pklist[n].ui->userid, genbuf)) + return n; + if (++n >= actor) + n = 0; + } + } + return -1; +} + +/* Kaede show friend description */ +static char *friend_descript(char *uident) { + static char *space_buf = " "; + static char desc_buf[80]; + char fpath[80], name[IDLEN + 2], *desc, *ptr; + int len, flag; + FILE *fp; + char genbuf[200]; + + setuserfile(fpath, friend_file[0]); + + if ((fp = fopen(fpath, "r"))) + { + sprintf(name, "%s ", uident); + len = strlen(name); + desc = genbuf + 13; + + while ((flag = (int) fgets(genbuf, STRLEN, fp))) + { + if (!memcmp(genbuf, name, len)) + { + if ((ptr = strchr(desc, '\n'))) + ptr[0] = '\0'; + if (desc) + break; + } + } + fclose(fp); + if (desc && flag) + strcpy(desc_buf, desc); + else + return space_buf; + + return desc_buf; + } + else + return space_buf; +} + +static char *descript(int show_mode, userinfo_t * uentp, time_t diff, + fromcache_t * fcache) { + switch (show_mode) + { + case 1: + return friend_descript(uentp->userid); + case 0: + return (((uentp->pager != 2 && uentp->pager != 3 && diff) || + HAS_PERM(PERM_SYSOP)) ? +#ifdef WHERE + uentp->from_alias ? fcache->replace[uentp->from_alias] : + uentp->from +#else + uentp->from +#endif + : "*"); + case 2: + sprintf(description, "%3d/%3d/%3d", uentp->five_win, + uentp->five_lose, uentp->five_tie); + description[20] = 0; + return description; + default: + syslog(LOG_WARNING, "damn!!! what's wrong?? show_mode = %d", + show_mode); + return ""; + } +} + +static int pickup_user_cmp(time_t now, int sortedway, int cmp_fri, + pickup_t pklist[], int *bfriends_number, int *ifh_number, + int *hfm_number,int *irh_number, char *keyword) +{ + int i, fri_stat, is_friend, count=0, diff; + userinfo_t *uentp; + for (i=0;i<utmpshm->number;i++) + { + uentp = (utmpshm->sorted[utmpshm->currsorted][sortedway][i]); + if (!uentp || !uentp->pid) continue; + fri_stat = friend_stat(currutmp, uentp); + if(uentp->uid==currutmp->uid) + fri_stat = fri_stat|IFH|HFM; + is_friend = (fri_stat & IRH) && !(fri_stat & IFH) ? 0 : + fri_stat & ST_FRIEND; + if (!isvisible_stat(currutmp, uentp, fri_stat) || + ((cmp_fri==1 && !is_friend) || + (cmp_fri==-1 && is_friend)) || + (keyword[0] && !strcasestr(uentp->username,keyword)) + ) continue; + if (bfriends_number && fri_stat & IBH) (*bfriends_number)++; + if (ifh_number && fri_stat & IFH) (*ifh_number)++; + if (hfm_number && fri_stat & HFM) (*hfm_number)++; + if (irh_number && fri_stat & IRH) (*irh_number)++; +#ifdef SHOW_IDLE_TIME + diff = now - uentp->lastact; +#ifdef DOTIMEOUT + /* prevent fault /dev mount from kicking out users */ + if ((diff > curr_idle_timeout + 10) && + (diff < 60 * 60 * 24 * 5)) + { + if ((uentp->pid <= 0 || kill(uentp->pid, SIGHUP) == -1) && + (errno == ESRCH)) + purge_utmp(uentp); + continue; + } +#endif + pklist[count].idle = diff; +#endif + pklist[count].friend = fri_stat; + pklist[count].ui = uentp; + count++; + } + return count; +} + +static int cmputmpfriend(const void *i, const void *j) +{ + if((((pickup_t*)j)->friend&ST_FRIEND)==(((pickup_t*)i)->friend&ST_FRIEND)) + return strcasecmp( ((pickup_t*)i)->ui->userid, + ((pickup_t*)j)->ui->userid); + else + return (((pickup_t*)j)->friend&ST_FRIEND) - + (((pickup_t*)i)->friend&ST_FRIEND); +} + +static void pickup_user() { + static int real_name = 0; + static int show_mode = 0; + static int show_uid = 0; + static int show_board = 0; + static int show_pid = 0; + static int num = 0; + char genbuf[200]; + +#ifdef WHERE + extern struct fromcache_t *fcache; +#endif + + register userinfo_t *uentp; + register pid_t pid0 = 0; /* Ptt ©w¦ì */ + register int id0 = 0; /* US_PICKUP®Éªº´å¼Ð¥Î */ + register int state = US_PICKUP, ch; + register int actor = 0, head, foot; + int fri_stat, bfriends_number, ifh_number, irh_number, hfm_number; + int savemode = currstat; + int i, sortedway; /* ¥u¬Oloop¦³¥Î¨ì */ + time_t diff, freshtime; + pickup_t pklist[USHM_SIZE]; /* parameter Pttµù */ +/* num : ²{¦bªº´å¼Ð¦ì */ +/* foot: ¦¹¶ªº¸}¸} */ + char buf[20],keyword[13]=""; /* actor:¦@¦³¦h¤Öuser */ + char pagerchar[5] = "* -Wf"; + char *msg_pickup_way[PICKUP_WAYS] = + { + "¶Ù! ªB¤Í", + "ºô¤Í¥N¸¹", + "ºô¤Í°ÊºA", + "µo§b®É¶¡", + "¨Ó¦Û¦ó¤è", + "¤¤l´Ñ ", +// "¤k¤hÀu¥ý" + }; + char *MODE_STRING[MAX_SHOW_MODE] = + { + "¬G¶m", + "¦n¤Í´yz", + "¤¤l´Ñ¾ÔÁZ" + }; + char + *Mind[] = + {" ", + "^-^", "^_^", "Q_Q", "@_@", "/_\\", "=_=", "-_-", "-.-", ">_<", + "-_+", "!_!", "o_o", "z_Z", "O_O", "O.O", "$_$", "^*^", "O_<", + "³ß!", "«ã!", "«s!", "¼Ö!", ":) ", ":( ", ":~ ", ":q ", ":O ", + ":D ", ":p ", ";) ", ":> ", ";> ", ":< ", ":)~", ":D~", ">< ", + "^^;", "^^|", "ú;", NULL}; + + while (1) + { + if (utmpshm->uptime > freshtime || state == US_PICKUP || + state ==US_RESORT) + { + state = US_PICKUP; + time(&freshtime); + ifh_number=hfm_number=irh_number=bfriends_number = actor = ch = 0; + if(pickup_way==0) + sortedway=0; + else + sortedway=pickup_way-1; + + //qsort(pklist,actor,sizeof(pickup_t),cmputmpfriend); + if(pickup_way==0 || (cuser.uflag & FRIEND_FLAG)) + { + actor=pickup_user_cmp(freshtime, sortedway, 1, + pklist, &bfriends_number, &ifh_number, &hfm_number, + NULL,keyword); + if(sortedway==0) + qsort(pklist,actor,sizeof(pickup_t),cmputmpfriend); + if(!(cuser.uflag & FRIEND_FLAG)) + actor=pickup_user_cmp(freshtime, sortedway, -1, + pklist+actor, NULL, NULL, NULL, &irh_number, + keyword); + } + else + { + actor=pickup_user_cmp(freshtime, sortedway, 0, + pklist, &bfriends_number, &ifh_number, &hfm_number, + &irh_number, keyword); + } + + + if (!actor) + { + if(keyword[0]) + { + mprints(b_lines-1,0, + "·j´M¤£¨ì¥ô¦ó¤H !!"); + keyword[0]=0; + pressanykey(); + continue; + } + getdata(b_lines - 1, 0, + "§AªºªB¤ÍÁÙ¨S¤W¯¸¡An¬Ý¬Ý¤@¯ëºô¤Í¶Ü(Y/N)¡H[Y]", + genbuf, 4, LCECHO); + if (genbuf[0] != 'n') + { + cuser.uflag &= ~FRIEND_FLAG; + continue; + } + return; + } + } + if (state >= US_ACTION) + { + showtitle((cuser.uflag & FRIEND_FLAG) ? "¦n¤Í¦Cªí" : "¥ð¶¢²á¤Ñ", + BBSName); + prints(" ±Æ§Ç¡G[%s] ¤W¯¸¤H¼Æ¡G%-4d\033[1;32m§ÚªºªB¤Í¡G%-3d" + "\033[33m»P§Ú¬°¤Í¡G%-3d\033[36mªO¤Í¡G%-4d\033[31mÃa¤H¡G" + "%-2d\033[m\n" + "\033[7m %s P%c¥N¸¹ %-17s%-17s%-13s%-10s\033[m\n", + msg_pickup_way[pickup_way], actor, ifh_number, + hfm_number, bfriends_number, irh_number, + show_uid ? "UID" : "No.", + (HAS_PERM(PERM_SEECLOAK) || HAS_PERM(PERM_SYSOP)) ? 'C' : ' ', + real_name ? "©m¦W" : "¼ÊºÙ", + MODE_STRING[show_mode], + show_board ? "Board" : "°ÊºA", + show_pid ? " PID" : "³Æµù µo§b" + ); + } + else + { + move(3, 0); + clrtobot(); + } + if (pid0) + for (ch = 0; ch < actor; ch++) + { + if (pid0 == (pklist[ch].ui)->pid && + id0 == 256 * pklist[ch].ui->userid[0] + + pklist[ch].ui->userid[1]) + { + num = ch; + } + } + if (num < 0) + num = 0; + else if (num >= actor) + num = actor - 1; + head = (num / p_lines) * p_lines; + foot = head + p_lines; + if (foot > actor) + foot = actor; + for (ch = head; ch < foot; ch++) + { + uentp = pklist[ch].ui; + + if (!uentp->pid) + { + prints("%5d < Â÷¯¸¤¤..>\n",ch); + continue; + } +#ifdef SHOW_IDLE_TIME + diff = pklist[ch].idle; + if (diff > 59990) diff = 59990; /* Doma: ¥H§K¤@¤j¦êªºµo§b®É¶¡ */ + if (diff > 0) + sprintf(buf, "%3ld'%02ld", diff / 60, diff % 60); + else + buf[0] = '\0'; +#else + buf[0] = '\0'; +#endif + i = pklist[ch].friend; +#ifdef SHOWPID + if (show_pid) + sprintf(buf, "%6d", uentp->pid); +#endif + if (PERM_HIDE(uentp)) + state = 9; + else if(currutmp == uentp) + state =10; + else if(i & IRH && !(i & IFH)) + state = 8; + else + state =(i&ST_FRIEND)>>2; + diff = uentp->pager & !(i&HRM); + prints("%5d %c%c%s%-13s%-17.16s\033[m%-17.16s%-13.13s" + "\33[33m%-4.4s\33[m%s\n", +#ifdef SHOWUID + show_uid ? uentp->uid : +#endif + (ch + 1), + (i & HRM) ? 'X' : + pagerchar[uentp->pager % 5], + (uentp->invisible ? ')' : ' '), + fcolor[state], + /* %s */ + uentp->userid, + + /* %-13s ¼ÊºÙ */ +#ifdef REALINFO + real_name ? uentp->realname : +#endif + uentp->username, + /* %-17.16s ¬G¶m */ + descript(show_mode, uentp, diff, fcache), + + /* %-17.16s ¬ÝªO */ +#ifdef SHOWBOARD + show_board ? (uentp->brc_id == 0 ? "" : + bcache[uentp->brc_id - 1].brdname) : +#endif + /* %-13.13s */ + modestring(uentp, 0), + /* %4s ³Æµù */ + ((uentp->userlevel & PERM_VIOLATELAW) ? "³q½r" : + (uentp->birth ? "¹Ø¬P" : + Mind[uentp->mind])), + /* %s µo§b */ + buf); + } + if (state == US_PICKUP) + continue; + + move(b_lines, 0); + outs("\033[31;47m(TAB/f)\033[30m±Æ§Ç/¦n¤Í \033[31m(t)\033[30m²á¤Ñ " + "\033[31m(a/d/o)\033[30m¥æ¤Í \033[31m(q)\033[30m¬d¸ß " + "\033[31m(w)\033[30m¤ô²y \033[31m(m)\033[30m±H«H \033[31m(h)" + "\033[30m½u¤W»²§U \033[m"); + state = 0; + while (!state) + { + ch = cursor_key(num + 3 - head, 0); + if (ch == KEY_RIGHT || ch == '\n' || ch == '\r') + ch = 't'; + + switch (ch) + { + case KEY_LEFT: + case 'e': + case 'E': + if(!keyword[0]) return; + keyword[0]=0; + state = US_PICKUP; + break; + + case KEY_TAB: + pickup_way = (pickup_way + 1) % PICKUP_WAYS; + state = US_RESORT; + num = 0; + break; + + case KEY_DOWN: + case 'n': + case 'j': + if (++num < actor) + { + if (num >= foot) + state = US_REDRAW; + break; + } + case '0': + case KEY_HOME: + num = 0; + if (head) + state = US_REDRAW; + break; + case 'H': + if (HAS_PERM(PERM_SYSOP)) + { + currutmp->userlevel ^= PERM_DENYPOST; + state = US_REDRAW; + } + break; + case 'D': + if (HAS_PERM(PERM_SYSOP)) + { + char buf[100]; + + sprintf(buf, "¥N¸¹ [%s]¡G", currutmp->userid); + if (!getdata(1, 0, buf, currutmp->userid, IDLEN + 1, + DOECHO)) + strcpy(currutmp->userid, cuser.userid); + state = US_REDRAW; + } + break; + case 'F': + if (HAS_PERM(PERM_SYSOP)) + { + char buf[100]; + + sprintf(buf, "¬G¶m [%s]¡G", currutmp->from); + if (!getdata(1, 0, buf, currutmp->from, 17, DOECHO)) + strncpy(currutmp->from, fromhost, 23); + state = US_REDRAW; + } + break; + case 'C': +#if !HAVE_FREECLOAK + if (HAS_PERM(PERM_CLOAK)) +#endif + { + currutmp->invisible ^= 1; + state = US_REDRAW; + } + break; + case ' ': + case KEY_PGDN: + case Ctrl('F'): + if (foot < actor) + { + num += p_lines; + state = US_REDRAW; + break; + } + if (head) + num = 0; + state = US_PICKUP; + break; + case KEY_UP: + case 'k': + if (--num < head) + { + if (num < 0) + { + num = actor - 1; + if (actor == foot) + break; + } + state = US_REDRAW; + } + break; + case KEY_PGUP: + case Ctrl('B'): + case 'P': + if (head) + { + num -= p_lines; + state = US_REDRAW; + break; + } + + case KEY_END: + case '$': + num = actor - 1; + if (foot < actor) + state = US_REDRAW; + break; + + case '/': + getdata_buf(b_lines-1,0,"½Ð¿é¤J¼ÊºÙÃöÁä¦r:",keyword, 12, + DOECHO); + state = US_PICKUP; + break; + case 's': + if ((i = search_pickup(num, actor, pklist)) >= 0) + num = i; + state = US_ACTION; + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { /* Thor: ¥i¥H¥´¼Æ¦r¸õ¨ì¸Ó¤H */ + int tmp; + if ((tmp = search_num(ch, actor - 1)) >= 0) + num = tmp; + state = US_REDRAW; + } + break; +#ifdef REALINFO + case 'R': /* Åã¥Ü¯u¹ê©m¦W */ + if (HAS_PERM(PERM_SYSOP)) + real_name ^= 1; + state = US_PICKUP; + break; +#endif +#ifdef SHOWUID + case 'U': + if (HAS_PERM(PERM_SYSOP)) + show_uid ^= 1; + state = US_PICKUP; + break; +#endif +#ifdef SHOWBOARD + case 'Y': + if (HAS_PERM(PERM_SYSOP)) + show_board ^= 1; + state = US_PICKUP; + break; +#endif +#ifdef SHOWPID + case '#': + if (HAS_PERM(PERM_SYSOP)) + show_pid ^= 1; + state = US_PICKUP; + break; +#endif + + case 'b': /* broadcast */ + if (cuser.uflag & FRIEND_FLAG || HAS_PERM(PERM_SYSOP)) + { + int actor_pos = actor; + char ans[4]; + + state = US_PICKUP; + if (!getdata(0, 0, "¼s¼½°T®§:", genbuf, 60, DOECHO)) + break; + if (getdata(0, 0, "½T©w¼s¼½? [Y]", ans, 4, LCECHO) && + *ans == 'n') + break; + while (actor_pos) + { + uentp = pklist[--actor_pos].ui; + fri_stat = pklist[actor_pos].friend; + if (uentp->pid && + currpid != uentp->pid && + uentp->pid > 0 && kill(uentp->pid, 0) != -1 && + (HAS_PERM(PERM_SYSOP) || + (uentp->pager != 3 && + (uentp->pager != 4 || fri_stat & HFM)))) + my_write(uentp->pid, genbuf, uentp->userid, HAS_PERM(PERM_SYSOP) ? 3 : 1); + } + } + break; + case 'S': /* Åã¥Ü¦n¤Í´yz */ + show_mode = (++show_mode) % MAX_SHOW_MODE; + state = US_PICKUP; + break; + case 'u': /* ½u¤Wקï¸ê®Æ */ + case 'K': /* §âÃa³J½ð¥X¥h */ + if (!HAS_PERM(PERM_ACCOUNTS)) + continue; + state = US_ACTION; + break; + case 'i': + state = US_ACTION; + break; + case Ctrl('S'): + state = US_ACTION; + break; + case 't': + case 'w': + if (!(cuser.userlevel & PERM_LOGINOK)) + continue; + state = US_ACTION; + break; + case 'a': + case 'd': + case 'o': + case 'f': + case 'g': + if (!HAS_PERM(PERM_LOGINOK)) + /* µù¥U¤~¦³ Friend */ + break; + if (ch == 'f') + { + cuser.uflag ^= FRIEND_FLAG; + state = US_PICKUP; + break; + } + state = US_ACTION; + break; + case 'q': + case 'c': + case 'm': + case 'r': + case 'l': + /* guest ¥u¯à query */ + if (!cuser.userlevel && ch != 'q' && ch != 'l') + break; + case 'h': + state = US_ACTION; + break; + case 'p': + if (HAS_PERM(PERM_BASIC)) + { + t_pager(); + state = US_REDRAW; + } + break; + case 'W': + { + int tmp; + char *wm[3] = {"¤@¯ë", "¶i¶¥", "¥¼¨Ó"}; + tmp = cuser.uflag2 & WATER_MASK; + cuser.uflag2 -= tmp; + tmp = (tmp + 1) % 3; + cuser.uflag2 |= tmp; + prints("¤Á´«¨ì %s ¤ô²y¼Ò¦¡", wm[tmp]); + refresh(); + sleep(1); + state = US_REDRAW; + } + default: /* refresh screen */ + state = US_REDRAW; + } + } + + if (state != US_ACTION) + { + pid0 = 0; + continue; + } + + /* Ptt decide cur */ + uentp = pklist[num].ui; + fri_stat = friend_stat(currutmp, uentp); + pid0 = uentp->pid; + id0 = 256 * uentp->userid[0] + uentp->userid[1]; + + if (ch == 'w') + { + if ((uentp->pid != currpid) && + (HAS_PERM(PERM_SYSOP) || + (uentp->pager != 3 && + (fri_stat & HFM || uentp->pager != 4)))) + { + cursor_show(num + 3 - head, 0); + sprintf(genbuf, "Call-In %s ¡G", uentp->userid); + my_write(uentp->pid, genbuf, uentp->userid, 0); + } + } + else if (ch == 'l') + { /* Thor: ¬Ý Last call in */ + t_display(); + } + else + { + switch (ch) + { + case 'r': + m_read(); + break; + case 'g': /* give money */ + move(b_lines - 2, 0); + if (strcmp(uentp->userid, cuser.userid)) + { + sprintf(genbuf, "nµ¹ %s ¦h¤Ö¿ú©O? ", uentp->userid); + outs(genbuf); + if (getdata(b_lines - 1, 0, "[»È¦æÂà±b]:", genbuf, 7, + LCECHO)) + { + clrtoeol(); + if ((ch = atoi(genbuf)) <= 0) + break; + reload_money(); + if (ch > cuser.money) + outs("\033[41m ²{ª÷¤£¨¬~~\033[m"); + else + { + deumoney(uentp->uid, ch); + sprintf(genbuf, "\033[44m ¶â..ÁٳѤU %d ¿ú.." + "\033[m", demoney(-1*ch)); + outs(genbuf); + sprintf(genbuf, "%s\tµ¹%s\t%d\t%s", cuser.userid, + uentp->userid, ch, + ctime(&currutmp->lastact)); + log_file(FN_MONEY, genbuf); + mail_redenvelop(cuser.userid, uentp->userid, ch, 'Y'); + } + } + else + { + clrtoeol(); + outs("\033[41m ¥æ©ö¨ú®ø! \033[m"); + } + } + else + outs("\033[33m ¦Û¤vµ¹¦Û¤v? A²Â..\033[m"); + refresh(); + sleep(1); + break; +#ifdef SHOWMIND + case 'i': + move(3,0); + clrtobot(); + for (i = 1; Mind[i]!=NULL; i++) + { + move(5+(i-1)/7,((i-1)%7)*10); + prints("%2d: %s",i,Mind[i]); + } + getdata(b_lines - 1, 0, "§A²{¦bªº¤ß±¡ 0:µL q¤£ÅÜ [q]:", + genbuf, 3, LCECHO); + if (genbuf[0] && genbuf[0] != 'q') + currutmp->mind=atoi(genbuf)%i; + state = US_REDRAW; + break; +#endif + case 'a': + friend_add(uentp->userid, FRIEND_OVERRIDE); + friend_load(); + state = US_PICKUP; + break; + case 'd': + friend_delete(uentp->userid, FRIEND_OVERRIDE); + friend_load(); + state = US_PICKUP; + break; + case 'o': + t_override(); + state = US_PICKUP; + break; + case 'K': + if (uentp->pid > 0 && kill(uentp->pid, 0) != -1) + { + move(1, 0); + clrtobot(); + move(2, 0); + my_kick(uentp); + state = US_PICKUP; + } + break; + case 'm': + stand_title("±H «H"); + prints("[±H«H] ¦¬«H¤H¡G%s", uentp->userid); + my_send(uentp->userid); + break; + case 'q': + strcpy(currauthor, uentp->userid); + my_query(uentp->userid); + break; + case 'c': + chicken_query(uentp->userid); + break; + case 'u': /* Thor: ¥i½u¤W¬d¬Ý¤Îקï¨Ï¥ÎªÌ */ + { + int id; + userec_t muser; + + strcpy(currauthor, uentp->userid); + stand_title("¨Ï¥ÎªÌ³]©w"); + move(1, 0); + if ((id = getuser(uentp->userid))) + { + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } + } + break; + + case 'h': /* Thor: ¬Ý Help */ + t_showhelp(); + break; + + case 't': + if (uentp->pid != currpid && + (strcmp(uentp->userid, cuser.userid))) + { + move(1, 0); + clrtobot(); + move(3, 0); + my_talk(uentp, fri_stat); + state = US_PICKUP; + } + break; + } + } + setutmpmode(savemode); + } +} + +int t_users() { + int destuid0 = currutmp->destuid; + int mode0 = currutmp->mode; + int stat0 = currstat; + + setutmpmode(LUSERS); + pickup_user(); + currutmp->mode = mode0; + currutmp->destuid = destuid0; + currstat = stat0; + return 0; +} + +int t_pager() { + currutmp->pager = (currutmp->pager + 1) % 5; + return 0; +} + +int t_idle() { + int destuid0 = currutmp->destuid; + int mode0 = currutmp->mode; + int stat0 = currstat; + char genbuf[20]; + char buf[80], passbuf[PASSLEN]; + + setutmpmode(IDLE); + getdata(b_lines - 1, 0, "²z¥Ñ¡G[0]µo§b (1)±µ¹q¸Ü (2)³V¹ (3)¥´½OºÎ " + "(4)¸Ë¦º (5)ù¤¦ (6)¨ä¥L (Q)¨S¨Æ¡H", genbuf, 3, DOECHO); + if (genbuf[0] == 'q' || genbuf[0] == 'Q') + { + currutmp->mode = mode0; + currstat = stat0; + return 0; + } + else if (genbuf[0] >= '1' && genbuf[0] <= '6') + currutmp->destuid = genbuf[0] - '0'; + else + currutmp->destuid = 0; + + if (currutmp->destuid == 6) + if (!cuser.userlevel || + !getdata(b_lines - 1, 0, "µo§bªº²z¥Ñ¡G", currutmp->chatid, 11, + DOECHO)) + currutmp->destuid = 0; + do + { + move(b_lines - 2, 0); + clrtoeol(); + sprintf(buf, "(Âê©w¿Ã¹õ)µo§bì¦]: %s", (currutmp->destuid != 6) ? + IdleTypeTable[currutmp->destuid] : currutmp->chatid); + outs(buf); + refresh(); + getdata(b_lines - 1, 0, MSG_PASSWD, passbuf, PASSLEN, NOECHO); + passbuf[8] = '\0'; + } + while (!checkpasswd(cuser.passwd, passbuf) && + strcmp(STR_GUEST, cuser.userid)); + + currutmp->mode = mode0; + currutmp->destuid = destuid0; + currstat = stat0; + + return 0; +} + +int t_qchicken() { + char uident[STRLEN]; + + stand_title("¬d¸ßÃdª«"); + usercomplete(msg_uid, uident); + if (uident[0]) + chicken_query(uident); + return 0; +} + +int t_query() { + char uident[STRLEN]; + + stand_title("¬d¸ßºô¤Í"); + usercomplete(msg_uid, uident); + if (uident[0]) + my_query(uident); + return 0; +} + +int t_talk() { + char uident[16]; + int tuid, unum, ucount; + userinfo_t *uentp; + char genbuf[4]; +/* + if (count_ulist() <= 1) + { + outs("¥Ø«e½u¤W¥u¦³±z¤@¤H¡A§ÖÁܽЪB¤Í¨Ó¥úÁ{¡i" BBSNAME "¡j§a¡I"); + return XEASY; + } +*/ + stand_title("¥´¶}¸Ü§X¤l"); + creat_list(); + namecomplete(msg_uid, uident); + if (uident[0] == '\0') + return 0; + + move(3, 0); + if (!(tuid = searchuser(uident)) || tuid == usernum) + { + outs(err_uid); + pressanykey(); + return 0; + } + +/* multi-login check */ + unum = 1; + while ((ucount = count_logins(tuid, 0)) > 1) + { + outs("(0) ¤£·Q talk ¤F...\n"); + count_logins(tuid, 1); + getdata(1, 33, "½Ð¿ï¾Ü¤@Ó²á¤Ñ¹ï¶H [0]¡G", genbuf, 4, DOECHO); + unum = atoi(genbuf); + if (unum == 0) + return 0; + move(3, 0); + clrtobot(); + if (unum > 0 && unum <= ucount) + break; + } + + if ((uentp = (userinfo_t *) search_ulistn(tuid, unum))) + my_talk(uentp, friend_stat(currutmp, uentp)); + + return 0; +} + +/* ¦³¤H¨Ó¦êªù¤l¤F¡A¦^À³©I¥s¾¹ */ +static userinfo_t *uip; +void talkreply() { + struct hostent *h; + char buf[4]; + struct sockaddr_in sin; + char genbuf[200]; + int a, sig = currutmp->sig; + + talkrequest = NA; + uip = &utmpshm->uinfo[currutmp->destuip]; + sprintf(page_requestor, "%s (%s)", uip->userid, uip->username); + currutmp->destuid = uip->uid; + currstat = XMODE; /* ÁקK¥X²{°Êµe */ + + clear(); + + prints("\n\n"); + prints(" (Y) Åý§ÚÌ %s §a¡I" + " (A) §Ú²{¦b«Ü¦£¡A½Ðµ¥¤@·|¨à¦A call §Ú\n", sig_des[sig]); + prints(" (N) §Ú²{¦b¤£·Q %s" + " (B) ¹ï¤£°_¡A§Ú¦³¨Æ±¡¤£¯à¸ò§A %s\n", + sig_des[sig], sig_des[sig]); + prints(" (C) ½Ð¤£n§n§Ú¦n¶Ü¡H" + " (D) §ÚnÂ÷¯¸Åo..¤U¦¸¦A²á§a.......\n"); + prints(" (E) ¦³¨Æ¶Ü¡H½Ð¥ý¨Ó«H" + " (F) \033[1;33m§Ú¦Û¤v¿é¤J²z¥Ñ¦n¤F...\033[m\n"); + prints(" (1) %s¡H¥ý®³100»È¨â¨Ó" + " (2) %s¡H¥ý®³1000»È¨â¨Ó..\n\n", sig_des[sig], sig_des[sig]); + + getuser(uip->userid); + currutmp->msgs[0].pid = uip->pid; + strcpy(currutmp->msgs[0].userid, uip->userid); + strcpy(currutmp->msgs[0].last_call_in, "©I¥s¡B©I¥s¡AÅ¥¨ì½Ð¦^µª (Ctrl-R)"); + prints("¹ï¤è¨Ó¦Û [%s]¡A¦@¤W¯¸ %d ¦¸¡A¤å³¹ %d ½g\n", + uip->from, xuser.numlogins, xuser.numposts); + showplans(uip->userid); + show_last_call_in(0); + + sprintf(genbuf, "§A·Q¸ò %s %s°Ú¡H½Ð¿ï¾Ü(Y/N/A/B/C/D/E/F/1/2)[N] ", + page_requestor, sig_des[sig]); + getdata(0, 0, genbuf, buf, 4, LCECHO); + + if (uip->mode != PAGE) + { + sprintf(genbuf, "%s¤w°±¤î©I¥s¡A«öEnterÄ~Äò...", page_requestor); + getdata(0, 0, genbuf, buf, 4, LCECHO); + return; + } + currutmp->msgcount = 0; + strcpy(save_page_requestor, page_requestor); + memset(page_requestor, 0, sizeof(page_requestor)); + if (!(h = gethostbyname("localhost"))) + { + perror("gethostbyname"); + return; + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = h->h_addrtype; + memcpy(&sin.sin_addr, h->h_addr, h->h_length); + sin.sin_port = uip->sockaddr; + a = socket(sin.sin_family, SOCK_STREAM, 0); + if ((connect(a, (struct sockaddr *) &sin, sizeof(sin)))) + { + perror("connect err"); + return; + } + if (!buf[0] || !strchr("yabcdef12", buf[0])) + buf[0] = 'n'; + write(a, buf, 1); + if (buf[0] == 'f' || buf[0] == 'F') + { + if (!getdata(b_lines, 0, "¤£¯àªºì¦]¡G", genbuf, 60, DOECHO)) + strcpy(genbuf, "¤£§i¶D§A«¨ !! ^o^"); + write(a, genbuf, 60); + } + uip->destuip = currutmp - &utmpshm->uinfo[0]; + if (buf[0] == 'y') + switch (sig) + { + case SIG_DARK: + main_dark(a, uip); + break; + case SIG_PK: + chickenpk(a); + break; + case SIG_GOMO: + gomoku(a); + break; + case SIG_CHC: + chc(a); + break; + case SIG_TALK: + default: + do_talk(a); + } + else + close(a); + clear(); +} + +/* ºô¤Í°ÊºA²ªí */ +/* not used +static int shortulist(userinfo_t * uentp) { + static int lineno, fullactive, linecnt; + static int moreactive, page, num; + char uentry[50]; + int state; + + if (!lineno) + { + lineno = 3; + page = moreactive ? (page + p_lines * 3) : 0; + linecnt = num = moreactive = 0; + move(1, 70); + prints("Page: %d", page / (p_lines) / 3 + 1); + move(lineno, 0); + } + + if (uentp == NULL) + { + int finaltally; + + clrtoeol(); + move(++lineno, 0); + clrtobot(); + finaltally = fullactive; + lineno = fullactive = 0; + return finaltally; + } + if ((!HAS_PERM(PERM_SYSOP) && + !HAS_PERM(PERM_SEECLOAK) && + uentp->invisible) || + ((friend_stat(currutmp, uentp) & HRM) && + !HAS_PERM(PERM_SYSOP))) + { + if (lineno >= b_lines) + return 0; + if (num++ < page) + return 0; + memset(uentry, ' ', 25); + uentry[25] = '\0'; + } + else + { + fullactive++; + if (lineno >= b_lines) + { + moreactive = 1; + return 0; + } + if (num++ < page) + return 0; + + state = (currutmp == uentp) ? 10 : + (friend_stat(currutmp,uentp)&ST_FRIEND)>>2; + + if (PERM_HIDE(uentp)) + state = 9; + + sprintf(uentry, "%s%-13s%c%-10s%s ", fcolor[state], + uentp->userid, uentp->invisible ? '#' : ' ', + modestring(uentp, 1), state ? "\033[0m" : ""); + } + if (++linecnt < 3) + { + strcat(uentry, "¢x"); + outs(uentry); + } + else + { + outs(uentry); + linecnt = 0; + clrtoeol(); + move(++lineno, 0); + } + return 0; +} +*/ diff --git a/mbbsd/term.c b/mbbsd/term.c new file mode 100644 index 00000000..61a0128d --- /dev/null +++ b/mbbsd/term.c @@ -0,0 +1,144 @@ +/* $Id: term.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <termios.h> +#include <string.h> +#include <syslog.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +int tgetent(const char *bp, char *name); +char *tgetstr(const char *id, char **area); +int tgetflag(const char *id); +int tgetnum(const char *id); +int tputs(const char *str, int affcnt, int (*putc)(int)); +char *tparm(const char *str, ...); +char *tgoto(const char *cap, int col, int row); + +static struct termios tty_state, tty_new; + +/* ----------------------------------------------------- */ +/* basic tty control */ +/* ----------------------------------------------------- */ +void init_tty() { + if(tcgetattr(1, &tty_state) < 0) { + syslog(LOG_ERR, "tcgetattr(): %m"); + return; + } + memcpy(&tty_new, &tty_state, sizeof(tty_new)); + tty_new.c_lflag &= ~(ICANON | ECHO | ISIG); +/* tty_new.c_cc[VTIME] = 0; + tty_new.c_cc[VMIN] = 1; */ + tcsetattr(1, TCSANOW, &tty_new); + system("stty raw -echo"); +} + +/* ----------------------------------------------------- */ +/* init tty control code */ +/* ----------------------------------------------------- */ + + +#define TERMCOMSIZE (40) + +char *clearbuf = "\33[H\33[J"; +int clearbuflen = 6; + +char *cleolbuf = "\33[K"; +int cleolbuflen = 3; + +char *scrollrev = "\33M"; +int scrollrevlen = 2; + +char *strtstandout = "\33[7m"; +int strtstandoutlen = 4; + +char *endstandout = "\33[m"; +int endstandoutlen = 3; + +int t_lines = 24; +int b_lines = 23; +int p_lines = 20; +int t_columns = 80; + +int automargins = 1; + +static char *outp; +static int *outlp; + + +static int outcf(int ch) { + if(*outlp < TERMCOMSIZE) { + (*outlp)++; + *outp++ = ch; + } + return 0; +} + +extern screenline_t *big_picture; + +static void term_resize(int sig) { + struct winsize newsize; + screenline_t *new_picture; + + signal(SIGWINCH, SIG_IGN); /* Don't bother me! */ + ioctl(0, TIOCGWINSZ, &newsize); + if(newsize.ws_row > t_lines) { + new_picture = (screenline_t *)calloc(newsize.ws_row, + sizeof(screenline_t)); + if(new_picture == NULL) { + syslog(LOG_ERR, "calloc(): %m"); + return; + } + free(big_picture); + big_picture = new_picture; + } + + t_lines=newsize.ws_row; + b_lines=t_lines-1; + p_lines=t_lines-4; + + signal(SIGWINCH, term_resize); +} + +int term_init() { + signal(SIGWINCH, term_resize); + return YEA; +} + +char term_buf[32]; + +void do_move(int destcol, int destline) { + char buf[16], *p; + + sprintf(buf, "\33[%d;%dH", destline + 1, destcol + 1); + for(p = buf; *p; p++) + ochar(*p); +} + +void save_cursor() { + ochar('\33'); + ochar('7'); +} + +void restore_cursor() { + ochar('\33'); + ochar('8'); +} + +void change_scroll_range(int top, int bottom) { + char buf[16], *p; + + sprintf(buf, "\33[%d;%dr", top + 1, bottom + 1); + for(p = buf; *p; p++) + ochar(*p); +} + +void scroll_forward() { + ochar('\33'); + ochar('D'); +} diff --git a/mbbsd/toolkit.c b/mbbsd/toolkit.c new file mode 100644 index 00000000..81a0d6f0 --- /dev/null +++ b/mbbsd/toolkit.c @@ -0,0 +1,14 @@ +/* $Id: toolkit.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <ctype.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" + +unsigned StringHash(unsigned char *s) { + unsigned int v=0; + while(*s) { + v = (v << 8) | (v >> 24); + v ^= toupper(*s++); /* note this is case insensitive */ + } + return (v * 2654435769UL) >> (32 - HASH_BITS); +} diff --git a/mbbsd/topsong.c b/mbbsd/topsong.c new file mode 100644 index 00000000..d3a65447 --- /dev/null +++ b/mbbsd/topsong.c @@ -0,0 +1,79 @@ +/* $Id: topsong.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define MAX_SONGS 300 +#define QCAST int (*)(const void *, const void *) + +typedef struct songcmp_t { + char name[100]; + char cname[100]; + long int count; +} songcmp_t; + +static long int totalcount=0; + +static int count_cmp(songcmp_t *b, songcmp_t *a) { + return (a->count - b->count); +} + +int topsong() { + more(FN_TOPSONG,YEA); + return 0; +} + +static int strip_blank(char *cbuf, char *buf) { + for(; *buf; buf++) + if(*buf != ' ') + *cbuf++ = *buf; + *cbuf = 0; + return 0; +} + +void sortsong() { + FILE *fo, *fp = fopen(BBSHOME "/" FN_USSONG, "r"); + songcmp_t songs[MAX_SONGS + 1]; + int n; + char buf[256], cbuf[256]; + + memset(songs , 0, sizeof(songs)); + if(!fp) return; + if(!(fo = fopen(FN_TOPSONG,"w"))) { + fclose(fp); + return; + } + + totalcount = 0; + while(fgets(buf, 200, fp)) { + strtok(buf, "\n\r"); + strip_blank(cbuf, buf); + if(!cbuf[0] || !isprint2(cbuf[0])) + continue; + + for(n = 0; n < MAX_SONGS && songs[n].name[0]; n++) + if(!strcmp(songs[n].cname,cbuf)) + break; + strcpy(songs[n].name, buf); + strcpy(songs[n].cname, cbuf); + songs[n].count++; + totalcount++; + } + qsort(songs, MAX_SONGS, sizeof(songcmp_t), (QCAST)count_cmp); + fprintf(fo, + " \033[36m¢w¢w\033[37m¦W¦¸\033[36m¢w¢w¢w¢w¢w¢w\033[37mºq" + " ¦W\033[36m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\033[37m¦¸¼Æ\033[36m" + "¢w¢w\033[32m¦@%ld¦¸\033[36m¢w¢w\033[m\n", totalcount); + for(n = 0; n < 100 && songs[n].name[0]; n++) { + fprintf(fo, " %5d. %-38.38s %4ld \033[32m[%.2f]\033[m\n", n + 1, + songs[n].name, songs[n].count, + (float)songs[n].count/totalcount); + } + fclose(fp); + fclose(fo); +} diff --git a/mbbsd/uptime b/mbbsd/uptime new file mode 100644 index 00000000..4f8281fb --- /dev/null +++ b/mbbsd/uptime @@ -0,0 +1,23 @@ +cache.c: if(fcache->busystate) +cache.c: fcache->busystate = 1; +cache.c: bzero(fcache->domain, sizeof fcache->domain); +cache.c: fcache->top=0; +cache.c: sscanf(buf,"%s",fcache->domain[fcache->top]); +cache.c: po = buf + strlen(fcache->domain[fcache->top]); +cache.c: strncpy(fcache->replace[fcache->top],po,49); +cache.c: fcache->replace[fcache->top] +cache.c: [strlen(fcache->replace[fcache->top])-1] = 0; +cache.c: (fcache->top)++; +cache.c: if(fcache->top == MAX_FROM) +cache.c: fcache->max_user=0; +cache.c: fcache->uptime = fcache->touchtime; +cache.c: fcache->busystate = 0; +cache.c: if(fcache->touchtime == 0) +cache.c: fcache->touchtime = 1; +cache.c: while(fcache->uptime < fcache->touchtime) +mbbsd.c: for (j = 0; j < fcache->top; j++){ +mbbsd.c: char *token = strtok (fcache->domain[j], "&"); +mbbsd.c: if ((a = utmpshm->number) > fcache->max_user){ +mbbsd.c: fcache->max_user = a; +mbbsd.c: fcache->max_time = now; +talk.c: uentp->from_alias ? fcache->replace[uentp->from_alias] : diff --git a/mbbsd/user.c b/mbbsd/user.c new file mode 100644 index 00000000..41aacfa9 --- /dev/null +++ b/mbbsd/user.c @@ -0,0 +1,980 @@ +/* $Id: user.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +extern int numboards; +extern boardheader_t *bcache; +extern char *loginview_file[NUMVIEWFILE][2]; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern time_t login_start_time; +extern char *msg_uid; +extern int usernum; +extern char *msg_sure_ny; +extern userinfo_t *currutmp; +extern int showansi; +extern char reset_color[]; +extern char *fn_proverb; +extern char *fn_plans; +extern char *msg_del_ok; +extern char *fn_register; +extern char *msg_nobody; +extern userec_t cuser; +extern userec_t xuser; + +static char *sex[8] = { + MSG_BIG_BOY, MSG_BIG_GIRL, MSG_LITTLE_BOY, MSG_LITTLE_GIRL, + MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME +}; + +int u_loginview() { + int i; + unsigned int pbits = cuser.loginview; + char choice[5]; + + clear(); + move(4,0); + for(i = 0; i < NUMVIEWFILE ; i++) + prints(" %c. %-20s %-15s \n", 'A' + i, + loginview_file[i][1],((pbits >> i) & 1 ? "£¾" : "¢æ")); + + clrtobot(); + while(getdata(b_lines - 1, 0, "½Ð«ö [A-N] ¤Á´«³]©w¡A«ö [Return] µ²§ô¡G", + choice, 3, LCECHO)) { + i = choice[0] - 'a'; + if(i >= NUMVIEWFILE || i < 0) + bell(); + else { + pbits ^= (1 << i); + move( i + 4 , 28 ); + prints((pbits >> i) & 1 ? "£¾" : "¢æ"); + } + } + + if(pbits != cuser.loginview) { + cuser.loginview = pbits ; + passwd_update(usernum, &cuser); + } + return 0; +} + +void user_display(userec_t *u, int real) { + int diff = 0; + char genbuf[200]; + + clrtobot(); + prints( + " \033[30;41m¢r¢s¢r¢s¢r¢s\033[m \033[1;30;45m ¨Ï ¥Î ªÌ" + " ¸ê ®Æ " + " \033[m \033[30;41m¢r¢s¢r¢s¢r¢s\033[m\n"); + prints(" ¥N¸¹¼ÊºÙ: %s(%s)\n" + " ¯u¹ê©m¦W: %s\n" + " ©~¦í¦í§}: %s\n" + " ¹q¤l«H½c: %s\n" + " ©Ê §O: %s\n" + " »È¦æ±b¤á: %ld »È¨â\n", + u->userid, u->username, u->realname, u->address, u->email, + sex[u->sex % 8], u->money); + + sethomedir(genbuf, u->userid); + prints(" ¨p¤H«H½c: %d «Ê (ÁʶR«H½c: %d «Ê)\n" + " ¨¤ÀÃÒ¸¹: %s\n" + " ¤â¾÷¸¹½X: %010d\n" + " ¥Í ¤é: %02i/%02i/%02i\n" + " ¤pÂû¦W¦r: %s\n", + get_num_records(genbuf, sizeof(fileheader_t)), + u->exmailbox, u->ident, u->mobile, + u->month, u->day, u->year % 100, u->mychicken.name); + prints(" µù¥U¤é´Á: %s", ctime(&u->firstlogin)); + prints(" «e¦¸¥úÁ{: %s", ctime(&u->lastlogin)); + prints(" «e¦¸ÂIºq: %s", ctime(&u->lastsong)); + prints(" ¤W¯¸¤å³¹: %d ¦¸ / %d ½g\n", + u->numlogins, u->numposts); + + if(real) { + strcpy(genbuf, "bTCPRp#@XWBA#VSM0123456789ABCDEF"); + for(diff = 0; diff < 32; diff++) + if(!(u->userlevel & (1 << diff))) + genbuf[diff] = '-'; + prints(" »{ÃÒ¸ê®Æ: %s\n" + " userÅv: %s\n", + u->justify, genbuf); + } else { + diff = (time(0) - login_start_time) / 60; + prints(" °±¯d´Á¶¡: %d ¤p®É %2d ¤À\n", + diff / 60, diff % 60); + } + + /* Thor: ·Q¬Ý¬Ý³oÓ user ¬O¨º¨Çª©ªºª©¥D */ + if(u->userlevel >= PERM_BM) { + int i; + boardheader_t *bhdr; + + outs(" ¾á¥ôªO¥D: "); + + for(i = 0, bhdr = bcache; i < numboards; i++, bhdr++) { + if(is_uBM(bhdr->BM,u->userid)) { + outs(bhdr->brdname); + outc(' '); + } + } + outc('\n'); + } + outs(" \033[30;41m¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r" + "¢s¢r¢s¢r¢s¢r¢s\033[m"); + + outs((u->userlevel & PERM_LOGINOK) ? + "\n±zªºµù¥Uµ{§Ç¤w¸g§¹¦¨¡AÅwªï¥[¤J¥»¯¸" : + "\n¦pªGn´£ª@Åv¡A½Ð°Ñ¦Ò¥»¯¸¤½§GÄæ¿ì²zµù¥U"); + +#ifdef NEWUSER_LIMIT + if((u->lastlogin - u->firstlogin < 3 * 86400) && !HAS_PERM(PERM_POST)) + outs("\n·s¤â¤W¸ô¡A¤T¤Ñ«á¶}©ñÅv"); +#endif +} + +void mail_violatelaw(char* crime, char* police, char* reason, char* result){ + char genbuf[200]; + fileheader_t fhdr; + time_t now; + FILE *fp; + sprintf(genbuf, "home/%c/%s", crime[0], crime); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + now = time(NULL); + fprintf(fp, "§@ªÌ: [Pttªk°|]\n" + "¼ÐÃD: [³ø§i] ¹Hªk§P¨M³ø§i\n" + "®É¶¡: %s\n" + "\033[1;32m%s\033[m§P¨M¡G\n \033[1;32m%s\033[m" + "¦]\033[1;35m%s\033[m¦æ¬°¡A\n¹H¤Ï¥»¯¸¯¸³W¡A³B¥H\033[1;35m%s\033[m¡A¯S¦¹³qª¾" + "\n½Ð¨ì PttLaw ¬d¸ß¬ÛÃöªk³W¸ê°T¡A¨Ã¨ì Play-Pay-ViolateLaw ú¥æ»@³æ", + ctime(&now), police, crime, reason, result); + fclose(fp); + sprintf(fhdr.title, "[³ø§i] ¹Hªk§P¨M³ø§i"); + strcpy(fhdr.owner, "[Pttªk°|]"); + sprintf(genbuf, "home/%c/%s/.DIR", crime[0], crime); + append_record(genbuf, &fhdr, sizeof(fhdr)); +} + +static void violate_law(userec_t *u, int unum){ + char ans[4], ans2[4]; + char reason[128]; + move(1,0); + clrtobot(); + move(2,0); + prints("(1)Cross-post (2)¶Ãµo¼s§i«H (3)¶Ãµo³sÂê«H\n"); + prints("(4)ÄÌÂZ¯¸¤W¨Ï¥ÎªÌ (8)¨ä¥L¥H»@³æ³B¸m¦æ¬°\n(9)¬å id ¦æ¬°\n"); + getdata(5, 0, "(0)µ²§ô", + ans, 3, DOECHO); + switch(ans[0]){ + case '1': + sprintf(reason, "%s", "Cross-post"); + break; + case '2': + sprintf(reason, "%s", "¶Ãµo¼s§i«H"); + break; + case '3': + sprintf(reason, "%s", "¶Ãµo³sÂê«H"); + break; + case '4': + while(!getdata(7, 0, "½Ð¿é¤J³QÀËÁ|²z¥Ñ¥H¥Üt³d¡G", reason, 50, DOECHO)); + strcat(reason, "[ÄÌÂZ¯¸¤W¨Ï¥ÎªÌ]"); + break; + case '8': + case '9': + while(!getdata(6, 0, "½Ð¿é¤J²z¥Ñ¥H¥Üt³d¡G", reason, 50, DOECHO)); + break; + default: + return; + } + getdata(7, 0, msg_sure_ny, ans2, 3, LCECHO); + if(*ans2 != 'y') + return; + if (ans[0]=='9'){ + char src[STRLEN], dst[STRLEN]; + sprintf(src, "home/%c/%s", u->userid[0], u->userid); + sprintf(dst, "tmp/%s", u->userid); + Rename(src, dst); + log_usies("KILL", u->userid); + post_violatelaw(u->userid, cuser.userid, reason, "¬å°£ ID"); + u->userid[0] = '\0'; + setuserid(unum, u->userid); + passwd_update(unum, u); + } + else{ + u->userlevel |= PERM_VIOLATELAW; + u->vl_count ++; + passwd_update(unum, u); + post_violatelaw(u->userid, cuser.userid, reason, "»@³æ³B¥÷"); + mail_violatelaw(u->userid, cuser.userid, reason, "»@³æ³B¥÷"); + } + pressanykey(); +} + +extern char* str_permid[]; + +void uinfo_query(userec_t *u, int real, int unum) { + userec_t x; + register int i = 0, fail, mail_changed; + char ans[4], buf[STRLEN], *p; + char genbuf[200], reason[50]; + unsigned long int money = 0; + fileheader_t fhdr; + int flag = 0, temp = 0, money_change = 0; + time_t now; + + FILE *fp; + + fail = mail_changed = 0; + + memcpy(&x, u, sizeof(userec_t)); + getdata(b_lines - 1, 0, real ? + "(1)§ï¸ê®Æ(2)³]±K½X(3)³]Åv(4)¬å±b¸¹(5)§ïID" + "(6)±þ/´_¬¡Ãdª«(7)¼f§P [0]µ²§ô " : + "½Ð¿ï¾Ü (1)קï¸ê®Æ (2)³]©w±K½X ==> [0]µ²§ô ", + ans, 3, DOECHO); + + if(ans[0] > '2' && !real) + ans[0] = '0'; + + if(ans[0] == '1' || ans[0] == '3') { + clear(); + i = 2; + move(i++, 0); + outs(msg_uid); + outs(x.userid); + } + + switch(ans[0]) { + case '7': + violate_law(&x, unum); + return; + case '1': + move(0, 0); + outs("½Ð³v¶µ×§ï¡C"); + + getdata_buf(i++, 0," ¼Ê ºÙ ¡G",x.username, 24, DOECHO); + if(real) { + getdata_buf(i++, 0, "¯u¹ê©m¦W¡G", x.realname, 20, DOECHO); + getdata_buf(i++, 0, "¨¤ÀÃÒ¸¹¡G", x.ident, 11, DOECHO); + getdata_buf(i++, 0, "©~¦í¦a§}¡G", x.address, 50, DOECHO); + } + sprintf(buf, "%010d", x.mobile); + getdata_buf(i++, 0, "¤â¾÷¸¹½X¡G", buf, 11, LCECHO); + x.mobile=atoi(buf); + getdata_str(i++, 0, "¹q¤l«H½c[ÅÜ°Ên«·s»{ÃÒ]¡G", buf, 50, DOECHO, + x.email); + if(strcmp(buf,x.email) && strchr(buf, '@')) { + strcpy(x.email,buf); + mail_changed = 1 - real; + } + + sprintf(genbuf, "%i", (u->sex + 1) % 8); + getdata_str(i++, 0, "©Ê§O (1)¸¯®æ (2)©j±µ (3)©³} (4)¬ü¬Ü (5)Á¦¨û " + "(6)ªü«¼ (7)´Óª« (8)Äqª«¡G", + buf, 3, DOECHO,genbuf); + if(buf[0] >= '1' && buf[0] <= '8') + x.sex = (buf[0] - '1') % 8; + else + x.sex = u->sex % 8; + + while(1) { + int len; + + sprintf(genbuf, "%02i/%02i/%02i", + u->month, u->day, u->year % 100); + len = getdata_str(i, 0, "¥Í¤é ¤ë¤ë/¤é¤é/¦è¤¸¡G", buf, 9, + DOECHO,genbuf); + if(len && len != 8) + continue; + if(!len) { + x.month = u->month; + x.day = u->day; + x.year = u->year; + } else if(len == 8) { + x.month = (buf[0] - '0') * 10 + (buf[1] - '0'); + x.day = (buf[3] - '0') * 10 + (buf[4] - '0'); + x.year = (buf[6] - '0') * 10 + (buf[7] - '0'); + } else + continue; + if(!real && (x.month > 12 || x.month < 1 || x.day > 31 || + x.day < 1 || x.year > 90 || x.year < 40)) + continue; + i++; + break; + } + if(real) { + unsigned long int l; + if(HAS_PERM(PERM_BBSADM)) { + sprintf(genbuf, "%d", x.money); + if(getdata_str(i++, 0,"»È¦æ±b¤á¡G", buf, 10, DOECHO,genbuf)) + if((l = atol(buf)) >= 0) { + if(l != x.money) { + money_change = 1; + money = x.money; + x.money = l; + } + } + } + sprintf(genbuf, "%d", x.exmailbox); + if(getdata_str(i++, 0,"ÁʶR«H½c¼Æ¡G", buf, 4, DOECHO,genbuf)) + if((l = atol(buf)) >= 0) + x.exmailbox = (int)l; + + getdata_buf(i++, 0, "»{ÃÒ¸ê®Æ¡G", x.justify, 44, DOECHO); + getdata_buf(i++, 0, "³Ìªñ¥úÁ{¾÷¾¹¡G", x.lasthost, 16, DOECHO); + + sprintf(genbuf, "%d", x.numlogins); + if(getdata_str(i++, 0,"¤W½u¦¸¼Æ¡G", buf, 10, DOECHO,genbuf)) + if((fail = atoi(buf)) >= 0) + x.numlogins = fail; + + sprintf(genbuf,"%d", u->numposts); + if(getdata_str(i++, 0, "¤å³¹¼Æ¥Ø¡G", buf, 10, DOECHO,genbuf)) + if((fail = atoi(buf)) >= 0) + x.numposts = fail; + sprintf(genbuf, "%d", u->vl_count); + if (getdata_str(i++, 0, "¹Hªk°O¿ý¡G", buf, 10, DOECHO, genbuf)) + if ((fail = atoi(buf)) >= 0) + x.vl_count = fail; + + sprintf(genbuf, "%d/%d/%d", u->five_win, u->five_lose, + u->five_tie); + if(getdata_str(i++, 0, "¤¤l´Ñ¾ÔÁZ ³Ó/±Ñ/©M¡G", buf, 16, DOECHO, + genbuf)) + while(1) { + p = strtok(buf, "/\r\n"); + if(!p) break; + x.five_win = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.five_lose = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.five_tie = atoi(p); + break; + } + sprintf(genbuf, "%d/%d/%d", u->chc_win, u->chc_lose, u->chc_tie); + if(getdata_str(i++, 0, "¶H´Ñ¾ÔÁZ ³Ó/±Ñ/©M¡G", buf, 16, DOECHO, + genbuf)) + while(1) { + p = strtok(buf, "/\r\n"); + if(!p) break; + x.chc_win = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.chc_lose = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.chc_tie = atoi(p); + break; + } + fail = 0; + } + break; + + case '2': + i = 19; + if(!real) { + if(!getdata(i++, 0, "½Ð¿é¤Jì±K½X¡G", buf, PASSLEN, NOECHO) || + !checkpasswd(u->passwd, buf)) { + outs("\n\n±z¿é¤Jªº±K½X¤£¥¿½T\n"); + fail++; + break; + } + } + else{ + char witness[3][32]; + time_t now = time(NULL); + for(i=0;i<3;i++){ + if(!getdata(19+i, 0, "½Ð¿é¤J¨ó§UÃÒ©ú¤§¨Ï¥ÎªÌ¡G", witness[i], 32, DOECHO)){ + outs("\n¤£¿é¤J«hµLªk§ó§ï\n"); + fail++; + break; + } + else if (!getuser(witness[i])){ + outs("\n¬dµL¦¹¨Ï¥ÎªÌ\n"); + fail++; + break; + } + else if (now - xuser.firstlogin < 6*30*24*60*60){ + outs("\nµù¥U¥¼¶W¹L¥b¦~¡A½Ð«·s¿é¤J\n"); + i--; + } + } + if (i < 3) + break; + else + i = 20; + } + + if(!getdata(i++, 0, "½Ð³]©w·s±K½X¡G", buf, PASSLEN, NOECHO)) { + outs("\n\n±K½X³]©w¨ú®ø, Ä~Äò¨Ï¥Î±K½X\n"); + fail++; + break; + } + strncpy(genbuf, buf, PASSLEN); + + getdata(i++, 0, "½ÐÀˬd·s±K½X¡G", buf, PASSLEN, NOECHO); + if(strncmp(buf, genbuf, PASSLEN)) { + outs("\n\n·s±K½X½T»{¥¢±Ñ, µLªk³]©w·s±K½X\n"); + fail++; + break; + } + buf[8] = '\0'; + strncpy(x.passwd, genpasswd(buf), PASSLEN); + if (real) + x.userlevel &= (!PERM_LOGINOK); + break; + + case '3': + i = setperms(x.userlevel, str_permid); + if(i == x.userlevel) + fail++; + else { + flag=1; + temp=x.userlevel; + x.userlevel = i; + } + break; + + case '4': + i = QUIT; + break; + + case '5': + if (getdata_str(b_lines - 3, 0, "·sªº¨Ï¥ÎªÌ¥N¸¹¡G", genbuf, IDLEN + 1, + DOECHO,x.userid)) { + if(searchuser(genbuf)) { + outs("¿ù»~! ¤w¸g¦³¦P¼Ë ID ªº¨Ï¥ÎªÌ"); + fail++; + } else + strcpy(x.userid, genbuf); + } + break; + case '6': + if(x.mychicken.name[0]) + x.mychicken.name[0] = 0; + else + strcpy(x.mychicken.name,"[¦º]"); + break; + default: + return; + } + + if(fail) { + pressanykey(); + return; + } + + getdata(b_lines - 1, 0, msg_sure_ny, ans, 3, LCECHO); + if(*ans == 'y') { + if(flag) + post_change_perm(temp,i,cuser.userid,x.userid); + if(strcmp(u->userid, x.userid)) { + char src[STRLEN], dst[STRLEN]; + + sethomepath(src, u->userid); + sethomepath(dst, x.userid); + Rename(src, dst); + setuserid(unum, x.userid); + } + memcpy(u, &x, sizeof(x)); + if(mail_changed) { +#ifdef EMAIL_JUSTIFY + x.userlevel &= ~PERM_LOGINOK; + mail_justify(); +#endif + } + + if(i == QUIT) { + char src[STRLEN], dst[STRLEN]; + + sprintf(src, "home/%c/%s", x.userid[0], x.userid); + sprintf(dst, "tmp/%s", x.userid); + if(Rename(src, dst)) { + sprintf(genbuf, "/bin/rm -fr %s >/dev/null 2>&1", src); +/* do not remove + system(genbuf); +*/ + } + log_usies("KILL", x.userid); + x.userid[0] = '\0'; + setuserid(unum, x.userid); + } else + log_usies("SetUser", x.userid); + if(money_change) + setumoney(unum,x.money); + passwd_update(unum, &x); + now = time(0); + if(money_change) { + strcpy(genbuf, "boards/Security"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + + now = time(NULL); + fprintf(fp, "§@ªÌ: [¨t²Î¦w¥þ§½] ¬ÝªO: Security\n" + "¼ÐÃD: [¤½¦w³ø§i] ¯¸ªøקïª÷¿ú³ø§i\n" + "®É¶¡: %s\n" + " ¯¸ªø\033[1;32m%s\033[m§â\033[1;32m%s\033[m" + "ªº¿ú±q\033[1;35m%ld\033[m§ï¦¨\033[1;35m%d\033[m", + ctime(&now), cuser.userid, x.userid, money, x.money); + + clrtobot (); + clear(); + while(!getdata(5, 0, "½Ð¿é¤J²z¥Ñ¥H¥Üt³d¡G", reason, 60, DOECHO)); + + fprintf(fp, "\n \033[1;37m¯¸ªø%sקï¿ú²z¥Ñ¬O¡G%s\033[m", + cuser.userid, reason); + fclose(fp); + sprintf(fhdr.title, "[¤½¦w³ø§i] ¯¸ªø%sקï%s¿ú³ø§i", cuser.userid, + x.userid); + strcpy(fhdr.owner, "[¨t²Î¦w¥þ§½]"); + append_record("boards/Security/.DIR", &fhdr, sizeof(fhdr)); + } + } +} + +int u_info() { + move(2, 0); + user_display(&cuser, 0); + uinfo_query(&cuser, 0, usernum); + strcpy(currutmp->realname, cuser.realname); + strcpy(currutmp->username, cuser.username); + return 0; +} + +int u_ansi() { + showansi ^= 1; + cuser.uflag ^= COLOR_FLAG; + outs(reset_color); + return 0; +} + +int u_cloak() { + outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); + return XEASY; +} + +int u_switchproverb() { +/* char *state[4]={"¥Î¥\\«¬","¦w¶h«¬","¦Û©w«¬","SHUTUP"}; */ + char buf[100]; + + cuser.proverb =(cuser.proverb +1) %4; + setuserfile(buf,fn_proverb); + if(cuser.proverb==2 && dashd(buf)) { + FILE *fp = fopen(buf,"a"); + + fprintf(fp,"®y¥k»Êª¬ºA¬°[¦Û©w«¬]n°O±o³]®y¥k»Êªº¤º®eò!!"); + fclose(fp); + } + passwd_update(usernum, &cuser); + return 0; +} + +int u_editproverb() { + char buf[100]; + + setutmpmode(PROVERB); + setuserfile(buf,fn_proverb); + move(1,0); + clrtobot(); + outs("\n\n ½Ð¤@¦æ¤@¦æ¨Ì§ÇÁä¤J·Q¨t²Î´£¿ô§Aªº¤º®e,\n" + " Àx¦s«á°O±o§âª¬ºA³]¬° [¦Û©w«¬] ¤~¦³§@¥Î\n" + " ®y¥k»Ê³Ì¦h100±ø"); + pressanykey(); + vedit(buf,NA, NULL); + return 0; +} + +void showplans(char *uid) { + char genbuf[200]; + + sethomefile(genbuf, uid, fn_plans); + if(!show_file(genbuf, 7, MAX_QUERYLINES, ONLY_COLOR)) + prints("¡mÓ¤H¦W¤ù¡n%s ¥Ø«e¨S¦³¦W¤ù", uid); +} + +int showsignature(char *fname) { + FILE *fp; + char buf[256]; + int i, j; + char ch; + + clear(); + move(2, 0); + setuserfile(fname, "sig.0"); + j = strlen(fname) - 1; + + for(ch = '1'; ch <= '9'; ch++) { + fname[j] = ch; + if((fp = fopen(fname, "r"))) { + prints("\033[36m¡i ñ¦WÀÉ.%c ¡j\033[m\n", ch); + for(i = 0; i++ < MAX_SIGLINES && fgets(buf, 256, fp); outs(buf)); + fclose(fp); + } + } + return j; +} + +int u_editsig() { + int aborted; + char ans[4]; + int j; + char genbuf[200]; + + j = showsignature(genbuf); + + getdata(0, 0, "ñ¦WÀÉ (E)½s¿è (D)§R°£ (Q)¨ú®ø¡H[Q] ", ans, 4, LCECHO); + + aborted = 0; + if(ans[0] == 'd') + aborted = 1; + if(ans[0] == 'e') + aborted = 2; + + if(aborted) { + if(!getdata(1, 0, "½Ð¿ï¾Üñ¦WÀÉ(1-9)¡H[1] ", ans, 4, DOECHO)) + ans[0] = '1'; + if(ans[0] >= '1' && ans[0] <= '9') { + genbuf[j] = ans[0]; + if(aborted == 1) { + unlink(genbuf); + outs(msg_del_ok); + } else { + setutmpmode(EDITSIG); + aborted = vedit(genbuf, NA, NULL); + if(aborted != -1) + outs("ñ¦WÀɧó·s§¹²¦"); + } + } + pressanykey(); + } + return 0; +} + +int u_editplan() { + char genbuf[200]; + + getdata(b_lines - 1, 0, "¦W¤ù (D)§R°£ (E)½s¿è [Q]¨ú®ø¡H[Q] ", + genbuf, 3, LCECHO); + + if(genbuf[0] == 'e') { + int aborted; + + setutmpmode(EDITPLAN); + setuserfile(genbuf, fn_plans); + aborted = vedit(genbuf, NA, NULL); + if(aborted != -1) + outs("¦W¤ù§ó·s§¹²¦"); + pressanykey(); + return 0; + } else if(genbuf[0] == 'd') { + setuserfile(genbuf, fn_plans); + unlink(genbuf); + outmsg("¦W¤ù§R°£§¹²¦"); + } + return 0; +} + +int u_editcalendar() { + char genbuf[200]; + + getdata(b_lines - 1, 0, "¦æ¨Æ¾ä (D)§R°£ (E)½s¿è [Q]¨ú®ø¡H[Q] ", + genbuf, 3, LCECHO); + + if(genbuf[0] == 'e') { + int aborted; + + setutmpmode(EDITPLAN); + setcalfile(genbuf, cuser.userid); + aborted = vedit(genbuf, NA, NULL); + if(aborted != -1) + outs("¦æ¨Æ¾ä§ó·s§¹²¦"); + pressanykey(); + return 0; + } else if(genbuf[0] == 'd') { + setcalfile(genbuf, cuser.userid); + unlink(genbuf); + outmsg("¦æ¨Æ¾ä§R°£§¹²¦"); + } + return 0; +} + +/* ¨Ï¥ÎªÌ¶ñ¼gµù¥Uªí®æ */ +static void getfield(int line, char *info, char *desc, char *buf, int len) { + char prompt[STRLEN]; + char genbuf[200]; + + sprintf(genbuf, "ì¥ý³]©w¡G%-30.30s (%s)", buf, info); + move(line, 2); + outs(genbuf); + sprintf(prompt, "%s¡G", desc); + if(getdata_str(line + 1, 2, prompt, genbuf, len, DOECHO, buf)) + strcpy(buf, genbuf); + move(line, 2); + prints("%s¡G%s", desc, buf); + clrtoeol(); +} + +static int removespace(char* s){ + int i, index; + + for(i=0, index=0;s[i];i++){ + if (s[i] != ' ') + s[index++] = s[i]; + } + s[index] = '\0'; + return index; +} + +int u_register() { + char rname[20], addr[50], ident[11], mobile[20]; + char phone[20], career[40], email[50],birthday[9],sex_is[2],year,mon,day; + char ans[3], *ptr; + FILE *fn; + time_t now; + char genbuf[200]; + + if(cuser.userlevel & PERM_LOGINOK) { + outs("±zªº¨¥÷½T»{¤w¸g§¹¦¨¡A¤£»Ý¶ñ¼g¥Ó½Ðªí"); + return XEASY; + } + if((fn = fopen(fn_register, "r"))) { + while(fgets(genbuf, STRLEN, fn)) { + if((ptr = strchr(genbuf, '\n'))) + *ptr = '\0'; + if(strncmp(genbuf, "uid: ", 5) == 0 && + strcmp(genbuf + 5, cuser.userid) == 0) { + fclose(fn); + outs("±zªºµù¥U¥Ó½Ð³æ©|¦b³B²z¤¤¡A½Ð@¤ßµ¥Ô"); + return XEASY; + } + } + fclose(fn); + } + + getdata(b_lines - 1, 0, "±z½T©wn¶ñ¼gµù¥U³æ¶Ü(Y/N)¡H[N] ", ans, 3, LCECHO); + if(ans[0] != 'y') + return FULLUPDATE; + + move(2, 0); + clrtobot(); + strcpy(ident, cuser.ident); + strcpy(rname, cuser.realname); + strcpy(addr, cuser.address); + strcpy(email, cuser.email); + sprintf(mobile,"0%09d",cuser.mobile); + sprintf(birthday, "%02i/%02i/%02i", + cuser.month, cuser.day, cuser.year % 100); + sex_is[0]=(cuser.sex % 8)+'1';sex_is[1]=0; + career[0] = phone[0] = '\0'; + while(1) { + clear(); + move(1, 0); + prints("%s(%s) ±z¦n¡A½Ð¾Ú¹ê¶ñ¼g¥H¤Uªº¸ê®Æ:", + cuser.userid, cuser.username); + do{ + getfield(3, "D120908396", "¨¤ÀÃÒ¸¹", ident, 11); + }while(removespace(ident)<10 || !isalpha(ident[0])); + do{ + getfield(5, "½Ð¥Î¤¤¤å", "¯u¹ê©m¦W", rname, 20); + }while(!removespace(rname) || isalpha(rname[0])); + do{ + getfield(7, "¾Ç®Õ¨t¯Å©Î³æ¦ì¾ºÙ", "ªA°È³æ¦ì", career, 40); + }while(!removespace(career)); + do{ + getfield(9, "¥]¬A¹ì«Ç©ÎªùµP¸¹½X", "¥Ø«e¦í§}", addr, 50); + }while(!(addr[0])); + do{ + getfield(11, "¥]¬Aªø³~¼·¸¹°Ï°ì½X", "³sµ¸¹q¸Ü", phone, 20); + }while(!removespace(phone)); + getfield(13, "¥u¿é¤J¼Æ¦r ¦p:0912345678", "¤â¾÷¸¹½X", mobile, 20); + while(1) { + int len; + + getfield(15,"¤ë¤ë/¤é¤é/¦è¤¸ ¦p:09/27/76","¥Í¤é",birthday,9); + len = strlen(birthday); + if(!len) { + sprintf(birthday, "%02i/%02i/%02i", + cuser.month, cuser.day, cuser.year % 100); + mon = cuser.month; + day = cuser.day; + year = cuser.year; + } else if(len == 8) { + mon = (birthday[0] - '0') * 10 + (birthday[1] - '0'); + day = (birthday[3] - '0') * 10 + (birthday[4] - '0'); + year = (birthday[6] - '0') * 10 + (birthday[7] - '0'); + } else + continue; + if(mon > 12 || mon < 1 || day > 31 || day < 1 || year > 90 || + year < 40) + continue; + break; + } + getfield(17, "1.¸¯®æ 2.©j±µ ", "©Ê§O", sex_is, 2); + getfield(19, "¨¤À»{ÃÒ¥Î", "E-Mail Address", email, 50); + + getdata(b_lines - 1, 0, "¥H¤W¸ê®Æ¬O§_¥¿½T(Y/N)¡H(Q)¨ú®øµù¥U [N] ", + ans, 3, LCECHO); + if(ans[0] == 'q') + return 0; + if(ans[0] == 'y') + break; + } + strcpy(cuser.ident, ident); + strcpy(cuser.realname, rname); + strcpy(cuser.address, addr); + strcpy(cuser.email, email); + cuser.mobile = atoi(mobile); + cuser.sex= (sex_is[0] - '1') % 8; + cuser.month = mon; + cuser.day = day; + cuser.year = year; + if((fn = fopen(fn_register, "a"))) { + now = time(NULL); + trim(career); + trim(addr); + trim(phone); + fprintf(fn, "num: %d, %s", usernum, ctime(&now)); + fprintf(fn, "uid: %s\n", cuser.userid); + fprintf(fn, "ident: %s\n", ident); + fprintf(fn, "name: %s\n", rname); + fprintf(fn, "career: %s\n", career); + fprintf(fn, "addr: %s\n", addr); + fprintf(fn, "phone: %s\n", phone); + fprintf(fn, "mobile: %s\n", mobile); + fprintf(fn, "email: %s\n", email); + fprintf(fn, "----\n"); + fclose(fn); + } + clear(); + move(9,3); + prints("³Ì«áPost¤@½g\033[32m¦Û§Ú¤¶²Ð¤å³¹\033[mµ¹¤j®a§a¡A" + "§i¶D©Ò¦³¦Ñ°©ÀY\033[31m§Ú¨Ó°Õ^$¡C\\n\n\n\n"); + pressanykey(); + cuser.userlevel |= PERM_POST; + brc_initial("WhoAmI"); + set_board(); + do_post(); + cuser.userlevel &= ~PERM_POST; + return 0; +} + +/* ¦C¥X©Ò¦³µù¥U¨Ï¥ÎªÌ */ +extern struct uhash_t *uhash; +static int usercounter, totalusers, showrealname; +static ushort u_list_special; + +static int u_list_CB(userec_t *uentp) { + static int i; + char permstr[8], *ptr; + register int level; + + if(uentp == NULL) { + move(2, 0); + clrtoeol(); + prints("\033[7m ¨Ï¥ÎªÌ¥N¸¹ %-25s ¤W¯¸ ¤å³¹ %s " + "³Ìªñ¥úÁ{¤é´Á \033[0m\n", + showrealname ? "¯u¹ê©m¦W" : "ºï¸¹¼ÊºÙ", + HAS_PERM(PERM_SEEULEVELS) ? "µ¥¯Å" : ""); + i = 3; + return 0; + } + + if(bad_user_id(uentp->userid)) + return 0; + + if((uentp->userlevel & ~(u_list_special)) == 0) + return 0; + + if(i == b_lines) { + prints("\033[34;46m ¤wÅã¥Ü %d/%d ¤H(%d%%) \033[31;47m " + "(Space)\033[30m ¬Ý¤U¤@¶ \033[31m(Q)\033[30m Â÷¶} \033[m", + usercounter, totalusers, usercounter * 100 / totalusers); + i = igetch(); + if(i == 'q' || i == 'Q') + return QUIT; + i = 3; + } + if(i == 3) { + move(3, 0); + clrtobot(); + } + + level = uentp->userlevel; + strcpy(permstr, "----"); + if(level & PERM_SYSOP) + permstr[0] = 'S'; + else if(level & PERM_ACCOUNTS) + permstr[0] = 'A'; + else if(level & PERM_DENYPOST) + permstr[0] = 'p'; + + if(level & (PERM_BOARD)) + permstr[1] = 'B'; + else if(level & (PERM_BM)) + permstr[1] = 'b'; + + if(level & (PERM_XEMPT)) + permstr[2] = 'X'; + else if(level & (PERM_LOGINOK)) + permstr[2] = 'R'; + + if(level & (PERM_CLOAK | PERM_SEECLOAK)) + permstr[3] = 'C'; + + ptr = (char *)Cdate(&uentp->lastlogin); + ptr[18] = '\0'; + prints("%-14s %-27.27s%5d %5d %s %s\n", + uentp->userid, + showrealname ? uentp->realname : uentp->username, + uentp->numlogins, uentp->numposts, + HAS_PERM(PERM_SEEULEVELS) ? permstr : "", ptr); + usercounter++; + i++; + return 0; +} + +int u_list() { + char genbuf[3]; + + setutmpmode(LAUSERS); + showrealname = u_list_special = usercounter = 0; + totalusers = uhash->number; + if(HAS_PERM(PERM_SEEULEVELS)) { + getdata(b_lines - 1, 0, "Æ[¬Ý [1]¯S®íµ¥¯Å (2)¥þ³¡¡H", + genbuf, 3, DOECHO); + if(genbuf[0] != '2') + u_list_special = PERM_BASIC | PERM_CHAT | PERM_PAGE | PERM_POST | PERM_LOGINOK | PERM_BM; + } + if(HAS_PERM(PERM_CHATROOM) || HAS_PERM(PERM_SYSOP)) { + getdata(b_lines - 1, 0, "Åã¥Ü [1]¯u¹ê©m¦W (2)¼ÊºÙ¡H", + genbuf, 3, DOECHO); + if(genbuf[0] != '2') + showrealname = 1; + } + u_list_CB(NULL); + if(passwd_apply(u_list_CB) == -1) { + outs(msg_nobody); + return XEASY; + } + move(b_lines, 0); + clrtoeol(); + prints("\033[34;46m ¤wÅã¥Ü %d/%d ªº¨Ï¥ÎªÌ(¨t²Î®e¶qµL¤W) " + "\033[31;47m (½Ð«ö¥ô·NÁäÄ~Äò) \033[m", usercounter, totalusers); + egetch(); + return 0; +} diff --git a/mbbsd/var.c b/mbbsd/var.c new file mode 100644 index 00000000..7b07f63b --- /dev/null +++ b/mbbsd/var.c @@ -0,0 +1,268 @@ +/* $Id: var.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" + +char *str_permid[] = { + "°ò¥»Åv¤O", /* PERM_BASIC */ + "¶i¤J²á¤Ñ«Ç", /* PERM_CHAT */ + "§ä¤H²á¤Ñ", /* PERM_PAGE */ + "µoªí¤å³¹", /* PERM_POST */ + "µù¥Uµ{§Ç»{ÃÒ", /* PERM_LOGINOK */ + "«H¥óµL¤W", /* PERM_MAILLIMIT */ + "Áô¨³N", /* PERM_CLOAK */ + "¬Ý¨£§ÔªÌ", /* PERM_SEECLOAK */ + "¥Ã¤[«O¯d±b¸¹", /* PERM_XEMPT */ + "¯¸ªøÁô¨³N", /* PERM_DENYPOST */ + "ªO¥D", /* PERM_BM */ + "±b¸¹Á`ºÞ", /* PERM_ACCOUNTS */ + "²á¤Ñ«ÇÁ`ºÞ", /* PERM_CHATCLOAK */ + "¬ÝªOÁ`ºÞ", /* PERM_BOARD */ + "¯¸ªø", /* PERM_SYSOP */ + "BBSADM", /* PERM_POSTMARK */ + "¤£¦C¤J±Æ¦æº]", /* PERM_NOTOP */ + "¹Hªk³q½r¤¤", /* PERM_VIOLATELAW */ + "¤£±µ¨ü¯¸¥~ªº«H", /* PERM_ */ + "¨S·Q¨ì", /* PERM_ */ + "µøı¯¸ªø", /* PERM_VIEWSYSOP */ + "Æ[¹î¨Ï¥ÎªÌ¦æÂÜ", /* PERM_LOGUSER */ + "ºëµØ°ÏÁ`¾ã²zÅv", /* PERM_Announce */ + "¤½Ãö²Õ", /* PERM_RELATION */ + "¯S°È²Õ", /* PERM_SMG */ + "µ{¦¡²Õ", /* PERM_PRG */ + "¬¡°Ê²Õ", /* PERM_ACTION */ + "¬ü¤u²Õ", /* PERM_PAINT */ + "¥ßªk²Õ", /* PERM_LAW */ + "¤p²Õªø", /* PERM_SYSSUBOP */ + "¤@¯Å¥DºÞ", /* PERM_LSYSOP */ + "¢Þ¢ü¢ü" /* PERM_PTT */ +}; + +char *str_permboard[] = { + "¤£¥i Zap", /* BRD_NOZAP */ + "¤£¦C¤J²Îp", /* BRD_NOCOUNT */ + "¤£Âà«H", /* BRD_NOTRAN */ + "¸s²Õª©", /* BRD_GROUP */ + "ÁôÂê©", /* BRD_HIDE */ + "¨î(¤£»Ý³]©w)", /* BRD_POSTMASK */ + "°Î¦Wª©", /* BRD_ANONYMOUS */ + "¹w³]°Î¦Wª©", /* BRD_DEFAULTANONYMOUS */ + "¹Hªk§ï¶i¤¤¬Ýª©", /* BRD_BAD */ + "³s¸p±M¥Î¬Ýª©", /* BRD_VOTEBOARD */ + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", + "¨S·Q¨ì", +}; + +int usernum; +pid_t currpid; /* current process ID */ +unsigned int currstat; +int currmode = 0; +int curredit = 0; +int showansi = 1; +int curr_idle_timeout = IDLE_TIMEOUT; +time_t login_start_time; +userec_t cuser; /* current user structure */ +userec_t xuser; /* lookup user structure */ +char quote_file[80] = "\0"; +char quote_user[80] = "\0"; +time_t paste_time; +char paste_title[STRLEN]; +char paste_path[256]; +int paste_level; +char currtitle[40] = "\0"; +char vetitle[40] = "\0"; +char currowner[IDLEN + 2] = "\0"; +char currauthor[IDLEN + 2] = "\0"; +char currfile[FNLEN]; /* current file name @ bbs.c mail.c */ +unsigned char currfmode; /* current file mode */ +char currboard[IDLEN + 2]; +int currbid; +unsigned int currbrdattr; +char currBM[IDLEN * 3 + 10]; +char reset_color[4] = "\033[m"; +char margs[64] = "\0"; /* main argv list*/ +crosspost_t postrecord; /* anti cross post */ + +/* global string variables */ +/* filename */ + +char *fn_passwd = FN_PASSWD; +char *fn_board = FN_BOARD; +char *fn_note_ans = FN_NOTE_ANS; +char *fn_register = "register.new"; +char *fn_plans = "plans"; +char *fn_writelog = "writelog"; +char *fn_talklog = "talklog"; +char *fn_overrides = FN_OVERRIDES; +char *fn_reject = FN_REJECT; +char *fn_canvote = FN_CANVOTE; +char *fn_notes = "notes"; +char *fn_water = FN_WATER; +char *fn_visable = FN_VISABLE; +char *fn_mandex = "/.Names"; +char *fn_proverb = "proverb"; + +/* are descript in userec.loginview */ + +char *loginview_file[NUMVIEWFILE][2] = { + {FN_NOTE_ANS ,"»Ä²¢W»¶¬y¨¥ªO"}, + {FN_TOPSONG ,"ÂIºq±Æ¦æº]" }, + {"etc/topusr" ,"¤Q¤j±Æ¦æº]" }, + {"etc/topusr100" ,"¦Ê¤j±Æ¦æº]" }, + {"etc/birth.today" ,"¤µ¤é¹Ø¬P" }, + {"etc/weather.tmp" ,"¤Ñ®ð§Ö³ø" }, + {"etc/stock.tmp" ,"ªÑ¥«§Ö³ø" }, + {"etc/day" ,"¤µ¤é¤Q¤j¸ÜÃD" }, + {"etc/week" ,"¤@¶g¤¤Q¤j¸ÜÃD"}, + {"etc/today" ,"¤µ¤Ñ¤W¯¸¤H¦¸" }, + {"etc/yesterday" ,"¬Q¤é¤W¯¸¤H¦¸" }, + {"etc/history" ,"¾ú¥v¤Wªº¤µ¤Ñ" }, + {"etc/topboardman" ,"ºëµØ°Ï±Æ¦æº]" }, + {"etc/topboard.tmp","¬ÝªO¤H®ð±Æ¦æº]"} +}; + +/* message */ +char *msg_seperator = MSG_SEPERATOR; +char *msg_mailer = MSG_MAILER; +char *msg_shortulist = MSG_SHORTULIST; + +char *msg_cancel = MSG_CANCEL; +char *msg_usr_left = MSG_USR_LEFT; +char *msg_nobody = MSG_NOBODY; + +char *msg_sure_ny = MSG_SURE_NY; +char *msg_sure_yn = MSG_SURE_YN; + +char *msg_bid = MSG_BID; +char *msg_uid = MSG_UID; + +char *msg_del_ok = MSG_DEL_OK; +char *msg_del_ny = MSG_DEL_NY; + +char *msg_fwd_ok = MSG_FWD_OK; +char *msg_fwd_err1 = MSG_FWD_ERR1; +char *msg_fwd_err2 = MSG_FWD_ERR2; + +char *err_board_update = ERR_BOARD_UPDATE; +char *err_bid = ERR_BID; +char *err_uid = ERR_UID; +char *err_filename = ERR_FILENAME; + +char *str_mail_address = "." BBSUSER "@" MYHOSTNAME; +char *str_new = "new"; +char *str_reply = "Re: "; +char *str_space = " \t\n\r"; +char *str_sysop = "SYSOP"; +char *str_author1 = STR_AUTHOR1; +char *str_author2 = STR_AUTHOR2; +char *str_post1 = STR_POST1; +char *str_post2 = STR_POST2; +char *BBSName = BBSNAME; + +/* #define MAX_MODES 78 */ +/* MAX_MODES is defined in common.h */ + +char *ModeTypeTable[MAX_MODES] = { + "µo§b", /* IDLE */ + "¥D¿ï³æ", /* MMENU */ + "¨t²ÎºûÅ@", /* ADMIN */ + "¶l¥ó¿ï³æ", /* MAIL */ + "¥æ½Í¿ï³æ", /* TMENU */ + "¨Ï¥ÎªÌ¿ï³æ", /* UMENU */ + "XYZ ¿ï³æ", /* XMENU */ + "¤ÀÃþ¬ÝªO", /* CLASS */ + "Play¿ï³æ", /* PMENU */ + "½s¯S§O¦W³æ", /* NMENU */ + "¢Þtt¶q³c©±", /* PSALE */ + "µoªí¤å³¹", /* POSTING */ + "¬ÝªO¦Cªí", /* READBRD */ + "¾\\Ū¤å³¹", /* READING */ + "·s¤å³¹¦Cªí", /* READNEW */ + "¿ï¾Ü¬ÝªO", /* SELECT */ + "Ū«H", /* RMAIL */ + "¼g«H", /* SMAIL */ + "²á¤Ñ«Ç", /* CHATING */ + "¨ä¥L", /* XMODE */ + "´M§ä¦n¤Í", /* FRIEND */ + "¤W½u¨Ï¥ÎªÌ", /* LAUSERS */ + "¨Ï¥ÎªÌ¦W³æ", /* LUSERS */ + "°lÂܯ¸¤Í", /* MONITOR */ + "©I¥s", /* PAGE */ + "¬d¸ß", /* TQUERY */ + "¥æ½Í", /* TALK */ + "½s¦W¤ùÀÉ", /* EDITPLAN */ + "½sñ¦WÀÉ", /* EDITSIG */ + "§ë²¼¤¤", /* VOTING */ + "³]©w¸ê®Æ", /* XINFO */ + "±Hµ¹¯¸ªø", /* MSYSOP */ + "¨L¨L¨L", /* WWW */ + "¥´¤j¦Ñ¤G", /* BIG2 */ + "¦^À³", /* REPLY */ + "³Q¤ô²y¥´¤¤", /* HIT */ + "¤ô²y·Ç³Æ¤¤", /* DBACK */ + "µ§°O¥»", /* NOTE */ + "½s¿è¤å³¹", /* EDITING */ + "µo¨t²Î³q§i", /* MAILALL */ + "ºN¨â°é", /* MJ */ + "¹q¸£¾Ü¤Í", /* P_FRIEND */ + "¤W¯¸³~¤¤", /* LOGIN */ + "¬d¦r¨å", /* DICT */ + "¥´¾ôµP", /* BRIDGE */ + "§äÀÉ®×", /* ARCHIE */ + "¥´¦a¹«", /* GOPHER */ + "¬ÝNews", /* NEWS */ + "±¡®Ñ²£¥Í¾¹", /* LOVE */ + "½sÄy»²§U¾¹", /* EDITEXP */ + "¥Ó½ÐIP¦ì§}", /* IPREG */ + "ºôºÞ¿ì¤½¤¤", /* NetAdm */ + "µêÀÀ¹ê·~§{", /* DRINK */ + "pºâ¾÷", /* CAL */ + "½sÄy®y¥k»Ê", /* PROVERB */ + "¤½§GÄæ", /* ANNOUNCE */ + "¨è¬y¨¥ª©", /* EDNOTE */ + "^º~½Ķ¾÷", /* CDICT */ + "À˵ø¦Û¤vª««~", /* LOBJ */ + "ÂIºq", /* OSONG */ + "¥¿¦bª±¤pÂû", /* CHICKEN */ + "ª±±m¨é", /* TICKET */ + "²q¼Æ¦r", /* GUESSNUM */ + "¹C¼Ö³õ", /* AMUSE */ + "¶Â¥Õ´Ñ", /* OTHELLO */ + "ª±»ë¤l", /* DICE*/ + "µo²¼¹ï¼ú", /* VICE */ + "¹G¹Gáàing", /* BBCALL */ + "ú»@³æ", /* CROSSPOST */ + "¤¤l´Ñ", /* M_FIVE */ + "21ÂIing", /* JACK_CARD */ + "10ÂI¥bing", /* TENHALF */ + "¶W¯Å¤E¤Q¤E", /* CARD_99 */ + "¤õ¨®¬d¸ß", /* RAIL_WAY */ + "·j´M¿ï³æ", /* SREG */ + "¤U¶H´Ñ", /* CHC */ + "¤U·tµX", /* DARK */ + "NBA¤j²q´ú" /* TMPJACK */ + "¢Þtt¬dº]¨t²Î", /* JCEE */ + "«½s¤å³¹" /* REEDIT */ +}; diff --git a/mbbsd/vice.c b/mbbsd/vice.c new file mode 100644 index 00000000..46f695d9 --- /dev/null +++ b/mbbsd/vice.c @@ -0,0 +1,151 @@ +/* $Id: vice.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" +extern int usernum; + +#define VICE_PLAY BBSHOME "/etc/vice/vice.play" +#define VICE_DATA "vice.new" +#define VICE_BINGO BBSHOME "/etc/vice.bingo" +#define VICE_SHOW BBSHOME "/etc/vice.show" +#define VICE_LOST BBSHOME "/etc/vice/vice.lost" +#define VICE_WIN BBSHOME "/etc/vice/vice.win" +#define VICE_END BBSHOME "/etc/vice/vice.end" +#define VICE_NO BBSHOME "/etc/vice/vice.no" +#define MAX_NO_PICTURE 2 +#define MAX_WIN_PICTURE 2 +#define MAX_LOST_PICTURE 3 +#define MAX_END_PICTURE 5 + + + +static int vice_load(char tbingo[6][15]) { + FILE *fb = fopen(VICE_BINGO, "r"); + char buf[16], *ptr; + int i = 0; + if(!fb) return -1; bzero((char*)tbingo, sizeof(tbingo)); + while(i < 6 && fgets(buf, 15, fb)) { + if((ptr = strchr(buf, '\n'))) + *ptr = 0; + strcpy(tbingo[i++], buf); + } + fclose(fb); + return 0; +} + +static int check(char tbingo[6][15], char *data) { + int i = 0, j; + + if(!strcmp(data, tbingo[0])) + return 8; + + for(j = 8; j > 0; j--) + for(i = 1; i < 6; i++) + if(!strncmp(data+8-j, tbingo[i]+8-j,j)) + return j - 1; + return 0; +} +// Ptt: showfile ran_showfile more ¤TªÌn¾ã¦X +static int ran_showfile(int y, int x, char *filename, int maxnum) { + FILE *fs; + char buf[512]; + + bzero(buf, sizeof(char) * 512); + sprintf(buf, "%s%d", filename, rand() % maxnum + 1); + if(!(fs = fopen(buf, "r"))) { + move(10,10); + prints("can't open file: %s", buf); + return 0; + } + + move(y, x); + + while(fgets(buf, 511, fs)) + prints("%s", buf); + + fclose(fs); + return 1; +} + +static int ran_showmfile(char *filename, int maxnum) { + char buf[256]; + + sprintf(buf, "%s%d", filename, rand() % maxnum + 1); + return more(buf, YEA); +} + +extern userec_t cuser; + +int vice_main() { + FILE *fd; + char tbingo[6][15]; + char buf_data[256] + , serial[16], ch[2], *ptr; + int TABLE[] = {0,10,200,1000,4000,10000,40000,100000,200000}; + int total = 0, money, i = 4, j = 0; + + setuserfile(buf_data, VICE_DATA); + if(!dashf(buf_data)) { + ran_showmfile(VICE_NO, MAX_NO_PICTURE); + return 0; + } + if(vice_load(tbingo)<0) return -1; + clear(); + ran_showfile(0, 0, VICE_PLAY, 1); + ran_showfile(10, 0, VICE_SHOW, 1); + + if(!(fd = fopen(buf_data, "r"))) + return 0; + j = 0; + i = 0; + move(10,24); + clrtoeol(); + prints("³o¤@´Áªºµo²¼¸¹½X"); + while(fgets(serial, 15, fd)) { + if((ptr = strchr(serial,'\r'))) + *ptr = 0; + if(j == 0) + i++; + move(10 + i, 24 + j); + prints("%s", serial); + j += 9; + j %= 45; + } + getdata(8, 0, "«ö'c'¶}©l¹ï¼ú¤F(©Î¬O¥ô·NÁäÂ÷¶})): ", ch, 2, LCECHO); + if(ch[0] != 'c' || lockutmpmode(VICE, LOCK_MULTI)){ + fclose(fd); + return 0; + } + + showtitle("µo²¼¹ï¼ú", BBSNAME); + rewind(fd); + while(fgets(serial, 15, fd)) { + if((ptr = strchr(serial,'\n'))) + *ptr = 0; + money = TABLE[check(tbingo,serial)]; + total += money; + prints("%s ¤¤¤F %d\n", serial, money); + } + pressanykey(); + if(total > 0) { + ran_showmfile(VICE_WIN, MAX_WIN_PICTURE); + move(22,0); + clrtoeol(); + prints("¥þ³¡ªºµo²¼¤¤¤F %d ¶ô¿ú\n", total); + demoney(total); + } else + ran_showmfile(VICE_LOST, MAX_LOST_PICTURE); + + fclose(fd); + unlink(buf_data); + pressanykey(); + unlockutmpmode(); + return 0; +} diff --git a/mbbsd/vote.c b/mbbsd/vote.c new file mode 100644 index 00000000..62916c99 --- /dev/null +++ b/mbbsd/vote.c @@ -0,0 +1,1068 @@ +/* $Id: vote.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +static int total; +extern int numboards; +extern boardheader_t *bcache; /* Thor: for speed up */ +extern char *err_board_update; +extern char *fn_board; +extern char *msg_seperator; +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern int currmode; +extern int usernum; +extern char currboard[]; /* name of currently selected board */ +extern userec_t cuser; + +static char STR_bv_control[] = "control"; /* §ë²¼¤é´Á ¿ï¶µ */ +static char STR_bv_desc[] = "desc"; /* §ë²¼¥Øªº */ +static char STR_bv_ballots[] = "ballots"; +static char STR_bv_flags[] = "flags"; +static char STR_bv_comments[] = "comments"; /* §ë²¼ªÌªº«Ø·N */ +static char STR_bv_limited[] = "limited"; /* ¨p¤H§ë²¼ */ +static char STR_bv_title[] = "vtitle"; + +static char STR_bv_results[] = "results"; + +static char STR_new_control[] = "control0"; /* §ë²¼¤é´Á ¿ï¶µ */ +static char STR_new_desc[] = "desc0"; /* §ë²¼¥Øªº */ +static char STR_new_ballots[] = "ballots0"; +static char STR_new_flags[] = "flags0"; +static char STR_new_comments[] = "comments0"; /* §ë²¼ªÌªº«Ø·N */ +static char STR_new_limited[] = "limited0"; /* ¨p¤H§ë²¼ */ +static char STR_new_title[] = "vtitle0"; + +int strip_ansi(char *buf, char *str, int mode) { + register int ansi, count = 0; + + for(ansi = 0; *str /*&& *str != '\n' */; str++) { + if(*str == 27) { + if(mode) { + if(buf) + *buf++ = *str; + count++; + } + ansi = 1; + } else if(ansi && strchr("[;1234567890mfHABCDnsuJKc=n", *str)) { + if((mode == NO_RELOAD && !strchr("c=n", *str)) || + (mode == ONLY_COLOR && strchr("[;1234567890m", *str))) { + if(buf) + *buf++ = *str; + count++; + } + if(strchr("mHn ", *str)) + ansi = 0; + } else { + ansi =0; + if(buf) + *buf++ = *str; + count++; + } + } + if(buf) + *buf = '\0'; + return count; +} + +void b_suckinfile(FILE *fp, char *fname) { + FILE *sfp; + + if((sfp = fopen(fname, "r"))) { + char inbuf[256]; + + while(fgets(inbuf, sizeof(inbuf), sfp)) + fputs(inbuf, fp); + fclose(sfp); + } +} + +static void b_count(char *buf, int counts[]) { + char inchar; + int fd; + + memset(counts, 0, 31 * sizeof(counts[0])); + total = 0; + if((fd = open(buf, O_RDONLY)) != -1) { + flock(fd, LOCK_EX); /* Thor: ¨¾¤î¦h¤H¦P®Éºâ */ + while(read(fd, &inchar, 1) == 1) { + counts[(int)(inchar - 'A')]++; + total++; + } + flock(fd, LOCK_UN); + close(fd); + } +} + + +static int b_nonzeroNum(char *buf) { + int i = 0; + char inchar; + int fd; + + if((fd = open(buf, O_RDONLY)) != -1) { + while(read(fd, &inchar, 1) == 1) + if(inchar) + i++; + close(fd); + } + return i; +} + +static void vote_report(char *bname, char *fname, char *fpath) { + register char *ip; + time_t dtime; + int fd, bid; + fileheader_t header; + + ip = fpath; + while(*(++ip)); + *ip++ = '/'; + + /* get a filename by timestamp */ + + dtime = time(0); + for(;;) { + sprintf(ip, "M.%ld.A", ++dtime); + fd = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644); + if(fd >= 0) + break; + dtime++; + } + close(fd); + + log_usies("TESTfn", fname); + log_usies("TESTfp", fpath); + + unlink(fpath); + link(fname, fpath); + + /* append record to .DIR */ + + memset(&header, 0, sizeof(fileheader_t)); + strcpy(header.owner, "[°¨¸ô±´¤l]"); + sprintf(header.title, "[%s] ¬ÝªO ¿ï±¡³ø¾É", bname); + { + register struct tm *ptime = localtime(&dtime); + + sprintf(header.date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); + } + strcpy(header.filename, ip); + + strcpy(ip, ".DIR"); + if((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) >= 0) { + flock(fd, LOCK_EX); + lseek(fd, 0, SEEK_END); + write(fd, &header, sizeof(fileheader_t)); + flock(fd, LOCK_UN); + close(fd); + if((bid = getbnum(bname)) > 0) + setbtotal(bid); + + } + +} + +static void b_result_one(boardheader_t *fh, int ind) { + FILE *cfp, *tfp, *frp, *xfp; + char *bname ; + char buf[STRLEN]; + char inbuf[80]; + int counts[31]; + int num ; + int junk; + char b_control[64]; + char b_newresults[64]; + char b_report[64]; + time_t closetime, now; + + fh->bvote--; + + if(fh->bvote==0) + fh->bvote=2; + else if(fh->bvote==2) + fh->bvote=1; + + if(ind) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, ind); + sprintf(STR_new_control, "%s%d", STR_bv_control, ind); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, ind); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, ind); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, ind); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, ind); + sprintf(STR_new_title, "%s%d", STR_bv_title, ind); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + strcpy(STR_new_title, STR_bv_title); + } + + bname = fh->brdname; + + setbfile(buf, bname, STR_new_control); + cfp = fopen(buf,"r"); + fscanf(cfp, "%d\n%lu\n", &junk, &closetime); + fclose(cfp); + + setbfile(b_control, bname, "tmp"); + if(rename(buf, b_control) == -1) + return; + setbfile(buf, bname, STR_new_flags); + num = b_nonzeroNum(buf); + unlink(buf); + setbfile(buf, bname, STR_new_ballots); + b_count(buf, counts); + unlink(buf); + + setbfile(b_newresults, bname, "newresults"); + if((tfp = fopen(b_newresults, "w")) == NULL) + return; + + now = time(NULL); + setbfile(buf, bname, STR_new_title); + + if((xfp=fopen(buf,"r"))) { + fgets(inbuf, sizeof(inbuf), xfp); + fprintf(tfp, "%s\n¡» §ë²¼¦WºÙ: %s\n\n", msg_seperator, inbuf); + } + + fprintf(tfp, "%s\n¡» §ë²¼¤¤¤î©ó: %s\n\n¡» ²¼¿ïÃD¥Ø´yz:\n\n", + msg_seperator, ctime(&closetime)); + fh->vtime = now; + + setbfile(buf, bname, STR_new_desc); + + b_suckinfile(tfp, buf); + unlink(buf); + + if((cfp = fopen(b_control, "r"))) { + fgets(inbuf, sizeof(inbuf), cfp); + fgets(inbuf, sizeof(inbuf), cfp); + fprintf(tfp, "\n¡»§ë²¼µ²ªG:(¦@¦³ %d ¤H§ë²¼,¨C¤H³Ì¦h¥i§ë %d ²¼)\n", + num, junk); + while(fgets(inbuf, sizeof(inbuf), cfp)) { + inbuf[(strlen(inbuf) - 1)] = '\0'; + num = counts[inbuf[0] - 'A']; + fprintf(tfp, " %-42s %3d ²¼ %02.2f%%\n", inbuf + 3, num, + (float)(num*100)/(float)(total)); + } + fclose(cfp); + } + unlink(b_control); + + fprintf(tfp, "%s\n¡» ¨Ï¥ÎªÌ«Øij¡G\n\n", msg_seperator); + setbfile(buf, bname, STR_new_comments); + b_suckinfile(tfp, buf); + unlink(buf); + + fprintf(tfp, "%s\n¡» Á`²¼¼Æ = %d ²¼\n\n", msg_seperator, total); + fclose(tfp); + + setbfile(b_report, bname, "report"); + if((frp = fopen(b_report, "w"))) { + b_suckinfile(frp, b_newresults); + fclose(frp); + } + sprintf(inbuf, "boards/%s", bname); + vote_report(bname, b_report, inbuf); + if(!(fh->brdattr &BRD_NOCOUNT)) { + sprintf(inbuf, "boards/%s", "Record"); + vote_report(bname, b_report, inbuf); + } + unlink(b_report); + + tfp = fopen(b_newresults, "a"); + setbfile(buf, bname, STR_bv_results); + b_suckinfile(tfp, buf); + fclose(tfp); + Rename(b_newresults, buf); +} + +static void b_result(boardheader_t *fh) { + FILE *cfp; + time_t closetime, now; + int i; + char buf[STRLEN]; + char temp[STRLEN]; + + now = time(NULL); + for(i = 0; i < 9; i++) { + if(i) + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + else + strcpy(STR_new_control, STR_bv_control); + + setbfile(buf, fh->brdname, STR_new_control); + cfp = fopen(buf,"r"); + if (!cfp) + continue; + fgets(temp,sizeof(temp),cfp); + fscanf(cfp, "%lu\n", &closetime); + fclose(cfp); + if(closetime < now) + b_result_one(fh,i); + } +} + +static int b_close(boardheader_t *fh) { + time_t now; + now = time(NULL); + + if(fh->bvote == 2) { + if(fh->vtime < now - 3 * 86400) { + fh->bvote = 0; + return 1; + } + else + return 0; + } + b_result(fh); + return 1; +} + +int b_closepolls() { + static char *fn_vote_polling = ".polling"; + boardheader_t *fhp; + FILE *cfp; + time_t now; + int pos, dirty; + time_t last; + char timebuf[100]; + + now = time(NULL); +/* Edited by CharlieL for can't auto poll bug */ + + if((cfp = fopen(fn_vote_polling,"r"))) { + fgets(timebuf,100*sizeof(char),cfp); + sscanf(timebuf, "%lu", &last); + fclose(cfp); + if(last + 3600 >= now) + return 0; + } + + if((cfp = fopen(fn_vote_polling, "w")) == NULL) + return 0; + fprintf(cfp, "%lu\n%s\n", now, ctime(&now)); + fclose(cfp); + + dirty = 0; + for(fhp = bcache, pos = 1; pos <= numboards; fhp++, pos++) { + if(fhp->bvote && b_close(fhp)) { + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + dirty = 1; + } + } + if(dirty) /* vote flag changed */ + reset_board(pos); + + return 0; +} + +static int vote_view(char *bname, int index) { + boardheader_t *fhp; + FILE* fp; + char buf[STRLEN], genbuf[STRLEN], inbuf[STRLEN]; + struct stat stbuf; + int fd, num = 0, i, pos, counts[31]; + time_t closetime; + + if(index) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, index); + sprintf(STR_new_control, "%s%d", STR_bv_control, index); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, index); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, index); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, index); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, index); + sprintf(STR_new_title, "%s%d", STR_bv_title, index); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + strcpy(STR_new_title, STR_bv_title); + } + + setbfile(buf, bname, STR_new_ballots); + if((fd = open(buf, O_RDONLY)) > 0) { + fstat(fd, &stbuf); + close(fd); + } else + stbuf.st_size = 0; + + setbfile(buf, bname, STR_new_title); + move(0, 0); + clrtobot(); + + if((fp = fopen(buf, "r"))) { + fgets(inbuf, sizeof(inbuf), fp); + prints("\n§ë²¼¦WºÙ: %s", inbuf); + } + + setbfile(buf, bname, STR_new_control); + fp = fopen(buf, "r"); + fgets(inbuf, sizeof(inbuf), fp); + fscanf(fp, "%lu\n", &closetime); + + prints("\n¡» ¹wª¾§ë²¼¬ö¨Æ: ¨C¤H³Ì¦h¥i§ë %d ²¼,¥Ø«e¦@¦³ %d ²¼,\n" + "¥»¦¸§ë²¼±Nµ²§ô©ó %s", atoi(inbuf), stbuf.st_size, + ctime(&closetime)); + + /* Thor: ¶}©ñ ²¼¼Æ ¹wª¾ */ + setbfile(buf, bname, STR_new_flags); + num = b_nonzeroNum(buf); + + setbfile(buf, bname, STR_new_ballots); + b_count(buf, counts); + + prints("¦@¦³ %d ¤H§ë²¼\n", num); + total = 0; + + while(fgets(inbuf, sizeof(inbuf), fp)) { + inbuf[(strlen(inbuf) - 1)] = '\0'; + inbuf[30] = '\0'; /* truncate */ + i = inbuf[0] - 'A'; + num = counts[i]; + move(i % 15 + 6, i / 15 * 40); + prints(" %-32s%3d ²¼", inbuf, num); + total += num; + } + fclose(fp); + pos = getbnum(bname); + fhp = bcache + pos - 1; + move(t_lines - 3, 0); + prints("¡» ¥Ø«eÁ`²¼¼Æ = %d ²¼", total); + getdata(b_lines - 1, 0, "(A)¨ú®ø§ë²¼ (B)´£¦¶}²¼ (C)Ä~Äò¡H[C] ", genbuf, + 4, LCECHO); + if(genbuf[0] == 'a') { + setbfile(buf, bname, STR_new_control); + unlink(buf); + setbfile(buf, bname, STR_new_flags); + unlink(buf); + setbfile(buf, bname, STR_new_ballots); + unlink(buf); + setbfile(buf, bname, STR_new_desc); + unlink(buf); + setbfile(buf, bname, STR_new_limited); + unlink(buf); + setbfile(buf,bname, STR_new_title); + unlink(buf); + + if(fhp->bvote) + fhp->bvote--; + if (fhp->bvote == 2) + fhp->bvote = 1; + + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + reset_board(pos); + } else if(genbuf[0] == 'b') { + b_result_one(fhp,index); + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + + reset_board(pos); + } + return FULLUPDATE; +} + +static int vote_view_all(char *bname) { + int i; + int x = -1; + FILE *fp, *xfp; + char buf[STRLEN], genbuf[STRLEN]; + char inbuf[80]; + + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_title, STR_bv_title); + setbfile(buf, bname, STR_new_control); + move(0, 0); + if((fp=fopen(buf,"r"))) { + prints("(0) "); + x = 0; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp=fopen(buf,"r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "µL¼ÐÃD"); + prints("%s\n", inbuf); + fclose(xfp); + } + + for(i = 1; i < 9; i++) { + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + sprintf(STR_new_title, "%s%d", STR_bv_title, i); + setbfile(buf, bname, STR_new_control); + if((fp=fopen(buf,"r"))) { + prints("(%d) ", i); + x = i; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp=fopen(buf,"r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "µL¼ÐÃD"); + prints("%s\n", inbuf); + fclose(xfp); + } + } + + if(x < 0) + return FULLUPDATE; + sprintf(buf, "n¬Ý´X¸¹§ë²¼ [%d] ", x); + + getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO); + + if(genbuf[0] < '0' || genbuf[0] > '8') + genbuf[0] = '0'+x; + + if(genbuf[0] != '0') + sprintf(STR_new_control, "%s%c", STR_bv_control, genbuf[0]); + else + strcpy(STR_new_control, STR_bv_control); + + setbfile(buf, bname, STR_new_control); + + if((fp=fopen(buf,"r"))) { + fclose(fp); + return vote_view(bname, genbuf[0] - '0'); + } + else + return FULLUPDATE; +} + +static int vote_maintain(char *bname) { + FILE *fp = NULL; + char inbuf[STRLEN], buf[STRLEN]; + int num = 0, aborted, pos, x, i; + time_t closetime; + boardheader_t *fhp; + char genbuf[4]; + + if(!(currmode & MODE_BOARD)) + return 0; + if((pos = getbnum(bname)) <= 0) + return 0; + + stand_title("Á|¿ì§ë²¼"); + fhp = bcache + pos - 1; + +/* CharlieL */ + if(fhp->bvote != 2 && fhp->bvote !=0) { + getdata(b_lines - 1, 0, + "(V)Æ[¹î¥Ø«e§ë²¼ (M)Á|¿ì·s§ë²¼ (A)¨ú®ø©Ò¦³§ë²¼ (Q)Ä~Äò [Q]", + genbuf, 4, LCECHO); + if(genbuf[0] == 'v') + return vote_view_all(bname); + else if(genbuf[0] == 'a') { + fhp->bvote=0; + + setbfile(buf, bname, STR_bv_control); + unlink(buf); + setbfile(buf, bname, STR_bv_flags); + unlink(buf); + setbfile(buf, bname, STR_bv_ballots); + unlink(buf); + setbfile(buf, bname, STR_bv_desc); + unlink(buf); + setbfile(buf, bname, STR_bv_limited); + unlink(buf); + setbfile(buf, bname, STR_bv_title); + unlink(buf); + + for(i = 1; i < 9; i++) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, i); + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, i); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, i); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, i); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, i); + sprintf(STR_new_title, "%s%d", STR_bv_title, i); + + setbfile(buf, bname, STR_new_control); + unlink(buf); + setbfile(buf, bname, STR_new_flags); + unlink(buf); + setbfile(buf, bname, STR_new_ballots); + unlink(buf); + setbfile(buf, bname, STR_new_desc); + unlink(buf); + setbfile(buf, bname, STR_new_limited); + unlink(buf); + setbfile(buf, bname, STR_new_title); + unlink(buf); + } + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + + return FULLUPDATE; + } else if(genbuf[0] != 'm' || fhp->bvote > 10) + return FULLUPDATE; + } + + strcpy(STR_new_control, STR_bv_control); + setbfile(buf,bname, STR_new_control); + x = 0; + while(x < 9 && (fp = fopen(buf,"r")) != NULL) { + fclose(fp); + x++; + sprintf(STR_new_control, "%s%d", STR_bv_control, x); + setbfile(buf, bname, STR_new_control); + } + if(fp) + fclose(fp); + if(x >=9) + return FULLUPDATE; + if(x) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots,x); + sprintf(STR_new_control, "%s%d", STR_bv_control,x); + sprintf(STR_new_desc, "%s%d", STR_bv_desc,x); + sprintf(STR_new_flags, "%s%d", STR_bv_flags,x); + sprintf(STR_new_comments, "%s%d", STR_bv_comments,x); + sprintf(STR_new_limited, "%s%d", STR_bv_limited,x); + sprintf(STR_new_title, "%s%d", STR_bv_title,x); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + strcpy(STR_new_title, STR_bv_title); + } + clear(); + move(0,0); + prints("²Ä %d ¸¹§ë²¼\n", x); + setbfile(buf, bname, STR_new_title); + getdata(4, 0, "½Ð¿é¤J§ë²¼¦WºÙ", inbuf, 30, LCECHO); + if(inbuf[0]=='\0') + strcpy(inbuf,"¤£ª¾¦Wªº"); + fp = fopen(buf, "w"); + fprintf(fp, "%s", inbuf); + fclose(fp); + + prints("«ö¥ô¦óÁä¶}©l½s¿è¦¹¦¸ [§ë²¼©v¦®]"); + pressanykey(); + setbfile(buf, bname, STR_new_desc); + aborted = vedit(buf, NA, NULL); + if(aborted== -1) { + clear(); + outs("¨ú®ø¦¹¦¸§ë²¼"); + pressanykey(); + return FULLUPDATE; + } + aborted = 0; + setbfile(buf, bname, STR_new_flags); + unlink(buf); + + getdata(4, 0, + "¬O§_©w§ë²¼ªÌ¦W³æ¡G(y)½sÄy¥i§ë²¼¤Hû¦W³æ[n]¥ô¦ó¤H¬Ò¥i§ë²¼:[N]", + inbuf, 2, LCECHO); + setbfile(buf, bname, STR_new_limited); + if(inbuf[0] == 'y') { + fp = fopen(buf, "w"); + fprintf(fp,"¦¹¦¸§ë²¼³]"); + fclose(fp); + friend_edit(FRIEND_CANVOTE); + } else { + if(dashf(buf)) + unlink(buf); + } + clear(); + getdata(0, 0, "¦¹¦¸§ë²¼¶i¦æ´X¤Ñ (¤@¨ì¤Q¤Ñ)¡H", inbuf, 4, DOECHO); + + closetime = atoi(inbuf); + if(closetime <= 0) + closetime = 1; + else if(closetime >10) + closetime = 10; + + closetime = closetime * 86400 + time(NULL); + setbfile(buf, bname, STR_new_control); + fp = fopen(buf, "w"); + fprintf(fp, "00\n%lu\n", closetime); + + outs("\n½Ð¨Ì§Ç¿é¤J¿ï¶µ, «ö ENTER §¹¦¨³]©w"); + num = 0; + while(!aborted) { + sprintf(buf, "%c) ", num + 'A'); + getdata((num % 15) + 2, (num / 15) * 40, buf, inbuf, 36, DOECHO); + if(*inbuf) { + fprintf(fp, "%1c) %s\n", (num+'A'), inbuf); + num++; + } + if((*inbuf == '\0' && num >= 1) || num == 30) + aborted = 1; + } + sprintf(buf, "½Ð°Ý¨C¤H³Ì¦h¥i§ë´X²¼¡H([1]¡ã%d): ", num); + + getdata(t_lines-3, 0, buf, inbuf, 3, DOECHO); + + if(atoi(inbuf) <= 0 || atoi(inbuf) > num) + strcpy(inbuf,"1"); + + rewind(fp); + fprintf(fp, "%2d\n", MAX(1, atoi(inbuf))); + fclose(fp); + + if(fhp->bvote == 2) + fhp->bvote = 0; + else if(fhp->bvote == 1) + fhp->bvote = 2; + else if(fhp->bvote == 2) + fhp->bvote = 1; + + fhp->bvote ++; + + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + reset_board(pos); + outs("¶}©l§ë²¼¤F¡I"); + + return FULLUPDATE; +} + +static int vote_flag(char *bname, int index, char val) { + char buf[256], flag; + int fd, num, size; + + if(index) + sprintf(STR_new_flags, "%s%d", STR_bv_flags, index); + else + strcpy(STR_new_flags, STR_bv_flags); + + num = usernum - 1; + setbfile(buf, bname, STR_new_flags); + if((fd = open(buf, O_RDWR | O_CREAT, 0600)) == -1) + return -1; + size = lseek(fd, 0, SEEK_END); + memset(buf, 0, sizeof(buf)); + while(size <= num) { + write(fd, buf, sizeof(buf)); + size += sizeof(buf); + } + lseek(fd, num, SEEK_SET); + read(fd, &flag, 1); + if(flag == 0 && val != 0) { + lseek(fd, num, SEEK_SET); + write(fd, &val, 1); + } + close(fd); + return flag; +} + +static int same(char compare, char list[], int num) { + int n; + int rep = 0; + + for(n = 0; n < num; n++) { + if(compare == list[n]) + rep = 1; + if(rep == 1) + list[n] = list[n + 1]; + } + return rep; +} + +static int user_vote_one(char *bname, int ind) { + FILE* cfp,*fcm; + char buf[STRLEN]; + boardheader_t *fhp; + int pos = 0, i = 0, count = 0, tickets, fd; + char inbuf[80], choices[31], vote[4], chosen[31]; + time_t closetime; + + if(ind) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, ind); + sprintf(STR_new_control, "%s%d", STR_bv_control, ind); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, ind); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, ind); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, ind); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, ind); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + } + + setbfile(buf, bname, STR_new_control); + cfp = fopen(buf,"r"); + if(!cfp) + return FULLUPDATE; + + setbfile(buf, bname, STR_new_limited); /* Ptt */ + if(dashf(buf)) { + setbfile(buf, bname, FN_CANVOTE); + if(!belong(buf, cuser.userid)) { + fclose(cfp); + outs("\n\n¹ï¤£°_! ³o¬O¨p¤H§ë²¼..§A¨Ã¨S¦³¨üÁÜò!"); + pressanykey(); + return FULLUPDATE; + } else { + outs("\n\n®¥³ß§A¨üÁܦ¹¦¸¨p¤H§ë²¼....<«ö¥ô·NÁäÀ˵ø¦¹¦¸¨üÁܦW³æ>"); + pressanykey(); + more(buf, YEA); + } + } + if(vote_flag(bname, ind, '\0')) { + outs("\n\n¦¹¦¸§ë²¼¡A§A¤w§ë¹L¤F¡I"); + pressanykey(); + return FULLUPDATE; + } + + setutmpmode(VOTING); + setbfile(buf, bname, STR_new_desc); + more(buf, YEA); + + stand_title("§ë²¼½c"); + if((pos = getbnum(bname)) <= 0) + return 0; + + fhp = bcache + pos - 1; + fgets(inbuf, sizeof(inbuf), cfp); + tickets = atoi(inbuf); + fscanf(cfp,"%lu\n", &closetime); + + prints("§ë²¼¤è¦¡¡G½T©w¦n±zªº¿ï¾Ü«á¡A¿é¤J¨ä¥N½X(A, B, C...)§Y¥i¡C\n" + "¦¹¦¸§ë²¼§A¥i¥H§ë %1d ²¼¡C" + "«ö 0 ¨ú®ø§ë²¼ , 1 §¹¦¨§ë²¼\n" + "¦¹¦¸§ë²¼±Nµ²§ô©ó¡G%s \n", + tickets, ctime(&closetime)); + move(5, 0); + memset(choices, 0, sizeof(choices)); + memset(chosen , 0, sizeof(chosen)); + + while(fgets(inbuf, sizeof(inbuf), cfp)) { + move((count % 15) + 5, (count / 15) * 40); + prints( " %s", strtok(inbuf, "\n\0")); + choices[count++] = inbuf[0]; + } + fclose(cfp); + + while(1) { + vote[0] = vote[1] = '\0'; + move(t_lines - 2, 0); + prints("§AÁÙ¥i¥H§ë %2d ²¼", tickets - i); + getdata(t_lines - 4, 0, "¿é¤J±zªº¿ï¾Ü: ", vote, 3, DOECHO); + *vote = toupper(*vote); + if(vote[0] == '0' || (!vote[0] && !i)) { + outs("°Oªº¦A¨Ó§ë³á!!"); + break; + } else if(vote[0] == '1' && i) + ; + else if(!vote[0]) + continue; + else if(index(choices, vote[0]) == NULL) /* µL®Ä */ + continue; + else if(same(vote[0], chosen, i)) { + move(((vote[0] - 'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40); + prints(" "); + i--; + continue; + } else { + if(i == tickets) + continue; + chosen[i] = vote[0]; + move(((vote[0]-'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40); + prints("*"); + i++; + continue; + } + + if(vote_flag(bname, ind, vote[0]) != 0) + prints("«ÂЧ벼! ¤£¤©p²¼¡C"); + else { + setbfile(buf, bname, STR_new_ballots); + if((fd = open(buf, O_WRONLY | O_CREAT | O_APPEND, 0600)) == 0) + outs("µLªk§ë¤J²¼Ôo\n"); + else { + struct stat statb; + char buf[3], mycomments[3][74], b_comments[80]; + + for(i = 0; i < 3; i++) + strcpy(mycomments[i], "\n"); + + flock(fd, LOCK_EX); + for(count = 0; count < 31; count++) { + if(chosen[count]) + write(fd, &chosen[count], 1); + } + flock(fd, LOCK_UN); + fstat(fd, &statb); + close(fd); + getdata(b_lines - 2, 0, + "±z¹ï³o¦¸§ë²¼¦³¤°»òÄ_¶Qªº·N¨£¶Ü¡H(y/n)[N]", + buf, 3 ,DOECHO); + if(buf[0] == 'Y' || buf[0] == 'y'){ + do { + move(5,0);clrtobot(); + outs("½Ð°Ý±z¹ï³o¦¸§ë²¼¦³¤°»òÄ_¶Qªº·N¨£¡H" + "³Ì¦h¤T¦æ¡A«ö[Enter]µ²§ô"); + for(i = 0; (i < 3) && + getdata(7 + i, 0, "¡G", mycomments[i], 74, + DOECHO); i++); + getdata(b_lines-2,0, "(S)Àx¦s (E)«·s¨Ó¹L " + "(Q)¨ú®ø¡H[S]", buf, 3, LCECHO); + } while(buf[0] == 'E' || buf[0] == 'e'); + if(buf[0] == 'Q' || buf[0] == 'q') + break; + setbfile(b_comments, bname, STR_new_comments); + if(mycomments[0]) + if((fcm = fopen(b_comments, "a"))){ + fprintf(fcm, + "\033[36m¡³¨Ï¥ÎªÌ\033[1;36m %s " + "\033[;36mªº«Øij¡G\033[m\n", + cuser.userid); + for(i = 0; i < 3; i++) + fprintf(fcm, " %s\n", mycomments[i]); + fprintf(fcm, "\n"); + fclose(fcm); + } + } + move(b_lines - 1 ,0); + prints("¤w§¹¦¨§ë²¼¡I\n"); + } + } + break; + } + pressanykey(); + return FULLUPDATE; +} + +static int user_vote(char *bname) { + int pos; + boardheader_t *fhp; + char buf[STRLEN]; + FILE* fp,*xfp; + int i, x = -1; + char genbuf[STRLEN]; + char inbuf[80]; + + if((pos = getbnum(bname)) <= 0) + return 0; + + fhp = bcache + pos - 1; + + move(0,0); + clrtobot(); + + if(fhp->bvote == 2 || fhp->bvote == 0) { + outs("\n\n¥Ø«e¨Ã¨S¦³¥ô¦ó§ë²¼Á|¦æ¡C"); + pressanykey(); + return FULLUPDATE; + } + + if(!HAS_PERM(PERM_LOGINOK)) { + outs("\n¹ï¤£°_! ±z¥¼º¡¤G¤Q·³, ÁÙ¨S¦³§ë²¼Åv³á!"); + pressanykey(); + return FULLUPDATE; + } + + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_title, STR_bv_title); + setbfile(buf, bname, STR_new_control); + move(0, 0); + if((fp = fopen(buf, "r"))) { + prints("(0) "); + x = 0; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp = fopen(buf,"r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "µL¼ÐÃD"); + prints("%s\n", inbuf); + fclose(xfp); + } + + for(i = 1; i < 9; i++) { + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + sprintf(STR_new_title, "%s%d", STR_bv_title, i); + setbfile(buf, bname, STR_new_control); + if((fp = fopen(buf, "r"))) { + prints("(%d) ", i); + x = i; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp = fopen(buf, "r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "µL¼ÐÃD"); + prints("%s\n", inbuf); + fclose(xfp); + } + } + + if(x < 0) + return FULLUPDATE; + + sprintf(buf, "n§ë´X¸¹§ë²¼ [%d] ", x); + + getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO); + + if(genbuf[0] < '0' || genbuf[0] > '8') + genbuf[0] = x + '0'; + + if(genbuf[0] != '0') + sprintf(STR_new_control, "%s%c", STR_bv_control, genbuf[0]); + else + strcpy(STR_new_control, STR_bv_control); + + setbfile(buf, bname, STR_new_control); + + if((fp = fopen(buf, "r"))){ + fclose(fp); + + return user_vote_one(bname, genbuf[0] - '0'); + } else + return FULLUPDATE; +} + +static int vote_results(char *bname) { + char buf[STRLEN]; + + setbfile(buf, bname, STR_bv_results); + if(more(buf, YEA) == -1) + outs("\n¥Ø«e¨S¦³¥ô¦ó§ë²¼ªºµ²ªG¡C"); + return FULLUPDATE; +} + +int b_vote_maintain() { + return vote_maintain(currboard); +} + +int b_vote() { + return user_vote(currboard); +} + +int b_results() { + return vote_results(currboard); +} diff --git a/mbbsd/voteboard.c b/mbbsd/voteboard.c new file mode 100644 index 00000000..1286d986 --- /dev/null +++ b/mbbsd/voteboard.c @@ -0,0 +1,447 @@ +/* $Id: voteboard.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +#define VOTEBOARD "NewBoard" + +extern char currboard[]; +extern int currbid; +extern boardheader_t *bcache; +extern int currmode; +extern userec_t cuser; + +void do_voteboardreply(fileheader_t *fhdr){ + char genbuf[1024]; + char reason[60]; + char fpath[80]; + char oldfpath[80]; + char opnion[10]; + char *ptr; + FILE *fo, *fp; + fileheader_t votefile; + int len; + int i, j; + int fd; + time_t endtime, now = time(NULL); + int hastime = 0; + + + clear(); + if(!(currmode & MODE_POST)) { + move(5, 10); + outs("¹ï¤£°_¡A±z¥Ø«eµLªk¦b¦¹µoªí¤å³¹¡I"); + pressanykey(); + return; + } + + setbpath(fpath, currboard); + stampfile(fpath, &votefile); + + setbpath(oldfpath, currboard); + + strcat(oldfpath, "/"); + strcat(oldfpath, fhdr->filename); + + fp = fopen(oldfpath, "r"); + + len = strlen(cuser.userid); + + while(fgets(genbuf, 1024, fp)){ + if (!strncmp(genbuf, "³s¸pµ²§ô®É¶¡", 12)){ + hastime = 1; + ptr = strchr(genbuf, '('); + sscanf(ptr+1, "%ld", &endtime); + if (endtime < now){ + prints("³s¸p®É¶¡¤w¹L"); + pressanykey(); + fclose(fp); + return; + } + } + if (!strncmp(genbuf+4, cuser.userid, len)){ + move(5, 10); + prints("±z¤w¸g³s¸p¹L¥»½g¤F"); + opnion[0] = 'n'; + getdata(7, 0, "nקï±z¤§«eªº³s¸p¶Ü¡H(Y/N) [N]", opnion, 3, LCECHO); + if (opnion[0] != 'y'){ + fclose(fp); + return; + } + strcpy(reason, genbuf+19); + } + } + fclose(fp); + + if((fd = open(oldfpath, O_RDONLY)) == -1) + return; + flock(fd, LOCK_EX); + + fo = fopen(fpath, "w"); + + if (!fo) + return; + i = 0; + while(fo){ + j = 0; + do{ + if (read(fd, genbuf+j, 1)<=0){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + j++; + }while(genbuf[j-1] !='\n'); + genbuf[j] = '\0'; + i++; + if (!strncmp("----------", genbuf, 10)) + break; + if (i > 3) + prints(genbuf); + fprintf(fo, "%s", genbuf); + } + if (!hastime){ + now += 14*24*60*60; + fprintf(fo, "³s¸pµ²§ô®É¶¡: (%ld)%s", now, ctime(&now)); + now -= 14*24*60*60; + } + + fprintf(fo, "%s", genbuf); + + do{ + if (!getdata(18, 0, "½Ð°Ý±z (Y)¤ä«ù (N)¤Ï¹ï ³oÓijÃD¡G", opnion, 3, LCECHO)){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + }while(opnion[0] != 'y' && opnion[0] != 'n'); + + if (!getdata(20, 0, "½Ð°Ý±z»P³oÓijÃDªºÃö«Y©Î³s¸p²z¥Ñ¬°¦ó¡G", reason, 40, DOECHO)){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + + i = 0; + + while(fo){ + i++; + j = 0; + do{ + if (read(fd, genbuf+j, 1)<=0){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + j++; + }while(genbuf[j-1] !='\n'); + genbuf[j] = '\0'; + if (!strncmp("----------", genbuf, 10)) + break; + if (strncmp(genbuf+4, cuser.userid, len)) + fprintf(fo, "%3d.%s", i, genbuf+4); + else + i--; + } + if (opnion[0] == 'y') + fprintf(fo, "%3d.%-15s%-34s ¨Ó·½:%s\n", i, cuser.userid, reason,cuser.lasthost); + i = 0; + fprintf(fo, "%s", genbuf); + while(fo){ + i++; + j = 0; + do{ + if (!read(fd, genbuf+j, 1)) + break; + j++; + }while(genbuf[j-1] !='\n'); + genbuf[j] = '\0'; + if (j <= 3) + break; + if (strncmp(genbuf+4, cuser.userid, len)) + fprintf(fo, "%3d.%s", i, genbuf+4); + else + i--; + } + if (opnion[0] == 'n') + fprintf(fo, "%3d.%-15s%-34s ¨Ó·½:%s\n", i, cuser.userid, reason,cuser.lasthost); + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(oldfpath); + rename(fpath, oldfpath); +} + +int do_voteboard() { + fileheader_t votefile; + char topic[100]; + char title[80]; + char genbuf[1024]; + char fpath[80]; + FILE* fp; + int temp, i; + time_t now = time(NULL); + + clear(); + if(!(currmode & MODE_POST)) { + move(5, 10); + outs("¹ï¤£°_¡A±z¥Ø«eµLªk¦b¦¹µoªí¤å³¹¡I"); + pressanykey(); + return FULLUPDATE; + } + + move(0, 0); + clrtobot(); + prints("±z¥¿¦b¨Ï¥Î PTT ªº³s¸p¨t²Î\n"); + prints("¥»³s¸p¨t²Î±N¸ß°Ý±z¤@¨Ç°ÝÃD¡A½Ð¤p¤ß¦^µª¤~¯à¶}©l³s¸p\n"); + prints("¥ô·N´£¥X³s¸p®×ªÌ¡A±N³Q¦C¤J¥»¨t²Î¤£¨üÅwªï¨Ï¥ÎªÌ³á\n"); + pressanykey(); + move(0, 0); + clrtobot(); + prints("(1)¥Ó½Ð·sª© (2)¼o°£Âª© (3)³s¸pª©¥D (4)½}§Kª©¥D\n"); + if (!strcmp(currboard, VOTEBOARD)) + prints("(5)³s¸p¤p²Õªø (6)½}§K¤p²Õªø "); + if (!strcmp(currboard, VOTEBOARD) && HAS_PERM(PERM_SYSOP)) + prints("(7)¯¸¥Á¤½§ë"); + prints("(8)¥Ó½Ð·s¸s²Õ"); + + do{ + getdata(3, 0, "½Ð¿é¤J³s¸pÃþ§O¡G", topic, 3, DOECHO); + temp = atoi(topic); + }while(temp <= 0 && temp >= 9); + + switch(temp){ + case 1: + do{ + if (!getdata(4, 0, "½Ð¿é¤J¬Ýª©^¤å¦WºÙ¡G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if (invalid_brdname(topic)) + outs("¤£¬O¥¿½Tªº¬Ýª©¦WºÙ"); + else if (getbnum(topic) > 0) + outs("¥»¦WºÙ¤w¸g¦s¦b"); + else + break; + }while(temp > 0); + sprintf(title, "[¥Ó½Ð·sª©] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s","¥Ó½Ð·sª©", "^¤å¦WºÙ: ", topic, "¤¤¤å¦WºÙ: "); + + if (!getdata(5, 0, "½Ð¿é¤J¬Ýª©¤¤¤å¦WºÙ¡G", topic, 20, DOECHO)) + return FULLUPDATE; + strcat(genbuf, topic); + strcat(genbuf, "\n¬Ýª©Ãþ§O: "); + if (!getdata(6, 0, "½Ð¿é¤J¬Ýª©Ãþ§O¡G", topic, 20, DOECHO)) + return FULLUPDATE; + strcat(genbuf, topic); + strcat(genbuf, "\nª©¥D¦W³æ: "); + getdata(7, 0, "½Ð¿é¤Jª©¥D¦W³æ¡G", topic, IDLEN * 3 + 3, DOECHO); + strcat(genbuf, topic); + strcat(genbuf, "\n¥Ó½Ðì¦]: \n"); + outs("½Ð¿é¤J¥Ó½Ðì¦](¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 2: + do{ + if (!getdata(4, 0, "½Ð¿é¤J¬Ýª©^¤å¦WºÙ¡G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if (getbnum(topic) <= 0) + outs("¥»¦WºÙ¨Ã¤£¦s¦b"); + else + break; + }while(temp > 0); + sprintf(title, "[¼o°£Âª©] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n","¼o°£Âª©", "^¤å¦WºÙ: ", topic); + strcat(genbuf, "\n¼o°£ì¦]: \n"); + outs("½Ð¿é¤J¼o°£ì¦](¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + + break; + case 3: + do{ + if (!getdata(4, 0, "½Ð¿é¤J¬Ýª©^¤å¦WºÙ¡G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if (getbnum(topic) <= 0) + outs("¥»¦WºÙ¨Ã¤£¦s¦b"); + else + break; + }while(temp > 0); + sprintf(title, "[³s¸pª©¥D] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s%s","³s¸pª©¥D", "^¤å¦WºÙ: ", topic, "¥Ó½Ð ID : ", cuser.userid); + strcat(genbuf, "\n¥Ó½Ð¬F¨£: \n"); + outs("½Ð¿é¤J¥Ó½Ð¬F¨£(¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 4: + do{ + if (!getdata(4, 0, "½Ð¿é¤J¬Ýª©^¤å¦WºÙ¡G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if ((i = getbnum(topic)) <= 0) + outs("¥»¦WºÙ¨Ã¤£¦s¦b"); + else + break; + }while(temp > 0); + sprintf(title, "[½}§Kª©¥D] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s","½}§Kª©¥D", "^¤å¦WºÙ: ", topic, "ª©¥D ID : "); + do{ + if (!getdata(6, 0, "½Ð¿é¤Jª©¥DID¡G", topic, IDLEN + 1, DOECHO)) + return FULLUPDATE; + else if (!userid_is_BM(topic, bcache[i-1].BM)) + outs("¤£¬O¸Óª©ªºª©¥D"); + else + break; + }while(temp > 0); + strcat(genbuf, topic); + strcat(genbuf, "\n½}§Kì¦]: \n"); + outs("½Ð¿é¤J½}§Kì¦](¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 5: + if (!getdata(4, 0, "½Ð¿é¤J¤p²Õ¤¤^¤å¦WºÙ¡G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "[³s¸p¤p²Õªø] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s%s","³s¸p¤p²Õªø", "¤p²Õ¦WºÙ: ", topic, "¥Ó½Ð ID : ", cuser.userid); + strcat(genbuf, "\n¥Ó½Ð¬F¨£: \n"); + outs("½Ð¿é¤J¥Ó½Ð¬F¨£(¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 6: + + if (!getdata(4, 0, "½Ð¿é¤J¤p²Õ¤¤^¤å¦WºÙ¡G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "[½}§K¤p²Õªø] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s","½}§K¤p²Õªø", "¤p²Õ¦WºÙ: ", topic, "¤p²Õªø ID : "); + if (!getdata(6, 0, "½Ð¿é¤J¤p²ÕªøID¡G", topic, IDLEN + 1, DOECHO)) + return FULLUPDATE; + strcat(genbuf, topic); + strcat(genbuf, "\n½}§Kì¦]: \n"); + outs("½Ð¿é¤J½}§Kì¦](¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 7: + if (!HAS_PERM(PERM_SYSOP)) + return FULLUPDATE; + if (!getdata(4, 0, "½Ð¿é¤J¤½§ë¥DÃD¡G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "%s %s", "[¯¸¥Á¤½§ë]", topic); + sprintf(genbuf, "%s\n\n%s%s\n","¯¸¥Á¤½§ë", "¤½§ë¥DÃD: ", topic); + strcat(genbuf, "\n¤½§ëì¦]: \n"); + outs("½Ð¿é¤J¤½§ëì¦](¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 8: + if(!getdata(4, 0, "½Ð¿é¤J¸s²Õ¤¤^¤å¦WºÙ¡G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "[¥Ó½Ð·s¸s²Õ] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s%s","¥Ó½Ð¸s²Õ", "¸s²Õ¦WºÙ: ", topic, "¥Ó½Ð ID : ", cuser.userid); + strcat(genbuf, "\n¥Ó½Ð¬F¨£: \n"); + outs("½Ð¿é¤J¥Ó½Ð¬F¨£(¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g¤£µM¤£·|®Öã³á"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "¡G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + default: + return FULLUPDATE; + } + strcat(genbuf, "³s¸pµ²§ô®É¶¡: "); + now += 14*24*60*60; + sprintf(topic, "(%ld)", now); + strcat(genbuf, topic); + strcat(genbuf, ctime(&now)); + now -= 14*24*60*60; + strcat(genbuf, "----------¤ä«ù----------\n"); + strcat(genbuf, "----------¤Ï¹ï----------\n"); + outs("¶}©l³s¸p¹Æ"); + setbpath(fpath, currboard); + stampfile(fpath, &votefile); + + if (!(fp = fopen(fpath, "w"))){ + outs("¶}ÀÉ¥¢±Ñ¡A½ÐµyÔ«¨Ó¤@¦¸"); + return FULLUPDATE; + } + fprintf(fp, "%s%s %s%s\n%s%s\n%s%s", "§@ªÌ: ", cuser.userid, + "¬ÝªO: ", currboard, + "¼ÐÃD: ", title, + "®É¶¡: ", ctime(&now)); + fprintf(fp, "%s\n", genbuf); + fclose(fp); + strcpy(votefile.owner, cuser.userid); + strcpy(votefile.title, title); + votefile.savemode = 'S'; + setbdir(genbuf, currboard); + if(append_record(genbuf, &votefile, sizeof(votefile)) != -1) + setbtotal(currbid); + do_voteboardreply(&votefile); + return FULLUPDATE; +} diff --git a/mbbsd/xyz.c b/mbbsd/xyz.c new file mode 100644 index 00000000..786add30 --- /dev/null +++ b/mbbsd/xyz.c @@ -0,0 +1,448 @@ +/* $Id: xyz.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern char *fn_note_ans; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char *BBSName; +extern char fromhost[]; +extern userinfo_t *currutmp; +extern int curr_idle_timeout; +extern userec_t cuser; + +/* ¦UºØ²Îp¤Î¬ÛÃö¸ê°T¦Cªí */ +/* Ptt90¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î */ +int x_90() { + extern char dict[21], database[41]; + strcpy(dict, "(90)ã¦ÒÃÒ¸¹/©m¦W/¾Ç®Õ/¬ì¨t/Ãþ²Õ"); + strcpy(database, "etc/90"); + use_dict(); + return 0; +} + +/* Ptt89¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î */ +int x_89() { + extern char dict[21], database[41]; + strcpy(dict, "(89)ã¦ÒÃÒ¸¹/©m¦W/¾Ç®Õ/¬ì¨t/Ãþ²Õ"); + strcpy(database, "etc/89"); + use_dict(); + return 0; +} +/* Ptt88¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î */ +int x_88() { + extern char dict[21], database[41]; + + strcpy(dict, "(88)ã¦ÒÃÒ¸¹/©m¦W/¾Ç®Õ/¬ì¨t/Ãþ²Õ"); + strcpy(database, "etc/88"); + use_dict(); + return 0; +} +/* Ptt87¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î */ +int x_87() { + extern char dict[21], database[41]; + + strcpy(dict, "(87)ã¦ÒÃÒ¸¹/©m¦W/¾Ç®Õ/¬ì¨t"); + strcpy(database, "etc/87"); + use_dict(); + return 0; +} + +/* Ptt86¦~«×¤j¾ÇÁp©Û¬dº]¨t²Î */ +int x_86() { + extern char dict[21], database[41]; + + strcpy(dict, "(86)ã¦ÒÃÒ¸¹/©m¦W/¾Ç®Õ/¬ì¨t"); + strcpy(database, "etc/86"); + use_dict(); + return 0; +} + +int x_boardman() { + more("etc/topboardman", YEA); + return 0; +} + +int x_user100() { + more("etc/topusr100", YEA); + return 0; +} + +int x_history() { + more("etc/history", YEA); + return 0; +} + +#ifdef HAVE_X_BOARDS +static int x_boards() { + more("etc/topboard.tmp", YEA); + return 0; +} +#endif + +int x_birth() { + more("etc/birth.today", YEA); + return 0; +} + +int x_weather() { + more("etc/weather.tmp", YEA); + return 0; +} + +int x_stock() { + more("etc/stock.tmp", YEA); + return 0; +} + +int x_note() { + more(fn_note_ans, YEA); + return 0; +} + +int x_issue() { + more("etc/day", YEA); + return 0; +} + +int x_week() { + more("etc/week", YEA); + return 0; +} + +int x_today() { + more("etc/today", YEA); + return 0; +} + +int x_yesterday() { + more("etc/yesterday", YEA); + return 0; +} + +int x_login() { + more("etc/Welcome_login", YEA); + return 0; +} + +#ifdef HAVE_INFO +static int x_program() { + more("etc/version", YEA); + return 0; +} +#endif + +#ifdef HAVE_LICENSE +static int x_gpl() { + more("etc/GPL", YEA); + return 0; +} +#endif + +/* Â÷¶} BBS ¯¸ */ +int note() { + static char *fn_note_tmp = "note.tmp"; + static char *fn_note_dat = "note.dat"; + int total = 0, i, collect, len; + struct stat st; + char buf[256], buf2[80]; + int fd, fx; + FILE *fp, *foo; + + typedef struct notedata_t { + time_t date; + char userid[IDLEN + 1]; + char username[19]; + char buf[3][80]; + } notedata_t; + notedata_t myitem; + + if(cuser.money < 5) { + outmsg("\033[1;41m «u§r! n§ë¤»È¤~¯à¯d¨¥...¨S¿úC..\033[m"); + clrtoeol(); + refresh(); + return 0; + } + + setutmpmode(EDNOTE); + do { + myitem.buf[0][0] = myitem.buf[1][0] = myitem.buf[2][0] = '\0'; + move(12, 0); + clrtobot(); + outs("\n§ë¤»È... ¹Í... ½Ð¯d¨¥ (¦Ü¦h¤T¦æ)¡A«ö[Enter]µ²§ô"); + for(i = 0; (i < 3) && getdata(16 + i, 0, "¡G", myitem.buf[i], 78, + DOECHO) && *myitem.buf[i]; i++); + getdata(b_lines - 1, 0, "(S)Àx¦s (E)«·s¨Ó¹L (Q)¨ú®ø¡H[S] ", + buf, 3, LCECHO); + + if(buf[0] == 'q' || (i == 0 && *buf != 'e')) + return 0; + } while(buf[0] == 'e'); + demoney(-5); + strcpy(myitem.userid, cuser.userid); + strncpy(myitem.username, cuser.username, 18); + myitem.username[18] = '\0'; + time(&(myitem.date)); + + /* begin load file */ + if((foo = fopen(".note", "a")) == NULL) + return 0; + + if((fp = fopen(fn_note_ans, "w")) == NULL) + return 0; + + if((fx = open(fn_note_tmp, O_WRONLY | O_CREAT, 0644)) <= 0) + return 0; + + if((fd = open(fn_note_dat, O_RDONLY)) == -1) + total = 1; + else if(fstat(fd, &st) != -1) { + total = st.st_size / sizeof(notedata_t) + 1; + if (total > MAX_NOTE) + total = MAX_NOTE; + } + + fputs("\033[1;31;44m¡ó¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t" + "\033[37m»Ä²¢W»¶ªO\033[31m¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¡ó" + "\033[m\n", fp); + collect = 1; + + while(total) { + sprintf(buf, "\033[1;31m¢~¢t\033[32m %s \033[37m(%s)", + myitem.userid, myitem.username); + len = strlen(buf); + + for(i = len ; i < 73; i++) + strcat(buf, " "); + sprintf(buf2, " \033[1;36m%.14s\033[31m ¢u¢¡\033[m\n", + Cdate(&(myitem.date))); + strcat(buf, buf2); + fputs(buf, fp); + if(collect) + fputs(buf, foo); + for(i = 0 ; i < 3 && *myitem.buf[i]; i++) { + fprintf(fp, "\033[1;31m¢x\033[m%-74.74s\033[1;31m¢x\033[m\n", + myitem.buf[i]); + if(collect) + fprintf(foo, "\033[1;31m¢x\033[m%-74.74s\033[1;31m¢x\033[m\n", + myitem.buf[i]); + } + fputs("\033[1;31m¢¢¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢£\033[m\n",fp); + + if(collect) { + fputs("\033[1;31m¢¢¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢£\033[m\n", foo); + fclose(foo); + collect = 0; + } + + write(fx, &myitem, sizeof(myitem)); + + if(--total) + read(fd, (char *) &myitem, sizeof(myitem)); + } + fputs("\033[1;31;44m¡ó¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¡ó\033[m\n",fp); + fclose(fp); + close(fd); + close(fx); + Rename(fn_note_tmp, fn_note_dat); + more(fn_note_ans, YEA); + return 0; +} + +static void mail_sysop() { + FILE *fp; + char genbuf[200]; + + if((fp = fopen("etc/sysop", "r"))) { + int i, j; + char *ptr; + + typedef struct sysoplist_t { + char userid[IDLEN + 1]; + char duty[40]; + } sysoplist_t; + sysoplist_t sysoplist[9]; + + j = 0; + while(fgets(genbuf, 128, fp)) { + if((ptr = strchr(genbuf, '\n'))) { + *ptr = '\0'; + if((ptr = strchr(genbuf, ':'))) { + *ptr = '\0'; + do { + i = *++ptr; + } while(i == ' ' || i == '\t'); + if(i) { + strcpy(sysoplist[j].userid, genbuf); + strcpy(sysoplist[j++].duty, ptr); + } + } + } + } + + move(12, 0); + clrtobot(); + prints("%16s %-18sÅv³d¹º¤À\n\n", "½s¸¹", "¯¸ªø ID"); + + for(i = 0; i < j; i++) + prints("%15d. \033[1;%dm%-16s%s\033[0m\n", + i + 1, 31 + i % 7, sysoplist[i].userid, sysoplist[i].duty); + prints("%-14s0. \033[1;%dmÂ÷¶}\033[0m", "", 31 + j % 7); + getdata(b_lines - 1, 0, " ½Ð¿é¤J¥N½X[0]¡G", + genbuf, 4, DOECHO); + i = genbuf[0] - '0' - 1; + if(i >= 0 && i < j) { + clear(); + do_send(sysoplist[i].userid, NULL); + } + } +} + +int m_sysop() { + setutmpmode(MSYSOP); + mail_sysop(); + return 0; +} + +int Goodbye() { + extern void movie(); + char genbuf[100]; + + getdata(b_lines - 1, 0, "±z½T©wnÂ÷¶}¡i " BBSNAME " ¡j¶Ü(Y/N)¡H[N] ", + genbuf, 3, LCECHO); + + if(*genbuf != 'y') + return 0; + + movie(999); + if(cuser.userlevel) { + getdata(b_lines - 1, 0, + "(G)ÀH·¦Ó³u (M)¦«¹Ú¯¸ªø (N)»Ä²¢W»¶¬y¨¥ª©¡H[G] ", + genbuf, 3, LCECHO); + if(genbuf[0] == 'm') + mail_sysop(); + else if(genbuf[0] == 'n') + note(); + } + + clear(); + prints("\033[1;36m¿Ë·Rªº \033[33m%s(%s)\033[36m¡A§O§Ñ¤F¦A«×¥úÁ{\033[45;33m" + " %s \033[40;36m¡I\n¥H¤U¬O±z¦b¯¸¤ºªºµù¥U¸ê®Æ:\033[0m\n", + cuser.userid, cuser.username, BBSName); + user_display(&cuser, 0); + pressanykey(); + + more("etc/Logout",NA); + pressanykey(); + u_exit("EXIT "); + return QUIT; +} + +/* ¤ä´©¥~±¾µ{¦¡ : tin¡Bgopher¡Bwww¡Bbbsnet¡Bgame¡Bcsh */ +#define LOOKFIRST (0) +#define LOOKLAST (1) +#define QUOTEMODE (2) +#define MAXCOMSZ (1024) +#define MAXARGS (40) +#define MAXENVS (20) +#define BINDIR BBSHOME"/bin/" + +#define MAXPATHLEN 256 + +#ifdef HAVE_TIN +static int x_tin() { + clear(); + return exec_cmd(NEWS, YEA, "bin/tin.sh", "TIN"); +} +#endif + +#ifdef HAVE_GOPHER +static int x_gopher() { + clear(); + return exec_cmd(GOPHER, YEA, "bin/gopher.sh", "GOPHER"); +} +#endif + +#ifdef HAVE_WWW +static int x_www() { + return exec_cmd(WWW, NA, "bin/www.sh", "WWW"); +} +#endif + +#ifdef HAVE_IRC +static int x_irc() { + return exec_cmd(XMODE, NA, "bin/irc.sh", "IRC"); +} +#endif + +#ifdef HAVE_ARCHIE +static int x_archie() { + char buf[STRLEN], ans[4]; + char genbuf1[100], genbuf2[200]; + char *s; + + setutmpmode(ARCHIE); + clear(); + outs("\nÅwªï¥úÁ{¡i\033[1;33;44m" BBSNAME "\033[m¡j¨Ï¥Î " + "\033[32mARCHIE\033[m ¥\\¯à\n"); + outs("\n¥»¥\\¯à±N¬°±z¦C¥X¦bþÓ FTP ¯¸¦s¦³±z±ý´M§äªºÀÉ®×.\n"); + outs("\n½Ð¿é¤J±ý·j´Mªº¦r¦ê, ©Îª½±µ«ö <ENTER> ¨ú®ø¡C\n"); + outs("\n coder by Harimau\n"); + outs(" modified by Leeym\n"); + getdata(13,0,"·j´M¦r¦ê¡G",buf,20,DOECHO,0); + if(buf[0]=='\0') { + prints("\n¨ú®ø·j´M.....\n"); + pressanykey(); + return; + } + + for(s = buf; *s != '\0'; s++) { + if(isspace(*s)) { + prints("\n¤@¦¸¥u¯à·j´M¤@Ó¦r¦ê°Õ, ¤£¯à¤Ó³g¤ß³á!!"); + pressanykey(); + return; + } + } + bbssetenv("ARCHIESTRING", buf); + exec_cmd(ARCHIE, YEA, "bin/archie.sh", ARCHIE); + log_usies("ARCHIE", ""); + strcpy(genbuf1, buf); + sprintf(buf, BBSHOME "/tmp/archie.%s", cuser.userid); + if(dashf(buf)) { + getdata(0, 0, "n±Nµ²ªG±H¦^«H½c¶Ü(Y/N)¡H[N]", ans, 3, DOECHO,0); + if(*ans == 'y') { + fileheader_t mhdr; + char title[128], buf1[80]; + FILE* fp; + + sethomepath(buf1, cuser.userid); + stampfile(buf1, &mhdr); + strcpy(mhdr.owner, cuser.userid); + sprintf(genbuf2, "Archie ·j´MÀÉ®×: %s µ²ªG", genbuf1); + strcpy(mhdr.title, genbuf2); + mhdr.savemode = 0; + mhdr.filemode = 0; + sethomedir(title, cuser.userid); + append_record(title, &mhdr, sizeof(mhdr)); + Link(buf, buf1); + } + more( buf, YEA); + unlink (buf); + } +} +#endif /* HAVE_ARCHIE */ diff --git a/sample/Makefile b/sample/Makefile new file mode 100644 index 00000000..7ba47da6 --- /dev/null +++ b/sample/Makefile @@ -0,0 +1,11 @@ +SUBDIR=etc innd +BBSHOME?=$(HOME) + +all: + +install: + @for i in $(SUBDIR); do\ + cd $$i;\ + make BBSHOME=$(BBSHOME) OSTYPE=$(OSTYPE) $@;\ + cd ..;\ + done diff --git a/sample/crontab b/sample/crontab new file mode 100644 index 00000000..5acc8403 --- /dev/null +++ b/sample/crontab @@ -0,0 +1,56 @@ +20 7 * * * bin/mailog.sh > /dev/null +20 6 * * * rm -f out/*; rm -f out/.DIR + +# ¨C¤Ñ 12:00 17:00 20:00 00:00 ¶}¼ú¡C +0 2,11,16,21 * * * bin/openticket.sh > /dev/null + +# ¨C¤Ñ¦¤W²M°£¹L´Á¨Ï¥ÎªÌ +10 7 * * * bin/reaper > /dev/null 2> /dev/null + +# ¨CÓ¤p®É 1 ¤À°õ¦æ¤W¯¸¤H¦¸²Îp +1 * * * * bin/account > /dev/null 2> /dev/null + +# ¨CÓ¤p®É 10 ¤À°õ¦æ¼öªù¸ÜÃD²Îp +50 * * * * bin/parse_news +10 * * * * bin/poststat /home/bbs > /dev/null + +# ¨C¤Ñ5:30°õ¦æ¨Ï¥ÎªÌ±Æ¦æº]§ó·s +30 5 * * * bin/topusr 10 etc/topusr > /dev/null +30 3 * * * bin/topusr 100 etc/topusr100 > /dev/null +30 5 * * * bin/yearsold > /dev/null +30 5 * * * bin/horoscope + +# ¨CÓ¤ë¤@, ¤Q¤¸¹ÂIºq±Æ¦æº] +20 6 1,15 * * bin/topsong.sh + +# ¨C¶g¤T,¤»²ÎpÂà«H©Ò¦³ªO +35 6 * * 6 bin/showboard ~/.BOARDS > ~/etc/BOARD.rec + +# ¨C¶g¤@¦¤W§âuser home²M¤@²M +20 3 * * * (/bin/rm -f logins.bad; bin/expire ) > /dev/null +1 7 * * 1 bin/deluserfile > /dev/null + +# ¨C¶g¤G¦¤W 4:30 , ±N BBS boards ¤¤¶W¹L¤C¤Ñªº SR. ¨t¦CªºÀɮ׬屼 +30 4 * * 2 /usr/bin/find /home/bbs/boards/ -mtime +7 -name SR\* -exec rm -f {} ';' +30 4 * * 2 /bin/rm -f ~/tmp/* + +# ¨C¤Ñ°õ¦æ¤@¦¸¥Í¤éµ{¦ +1 2 * * * bin/birth > /dev/null + +# ¨C¤ÑºëµØ°Ïindex¤@¦¸ index«e¬å±¼deletedªººëµØ°Ï +15 6 * * * rm -rf man/boards/deleted +20 6 * * * bin/mandex > /dev/null +30 6 * * * bin/openvice > /dev/null + +# ¨C¤Ñ¬å±¼ÂIºq¶W¹L5¤ÑÀÉ®× +40 6 * * * ( find /home/bbs/etc/SONGO/M* -mtime +5 -exec rm -f {} ';' ) + +#¤Ñ®ðªÑ²¼ +0 5,11,17,23 * * * bin/weather.sh > /dev/null +20 12 * * * bin/stock.sh > /dev/null + +# ¨CÓ¤ë¤@¸¹¦¤W 3:50 , ±N BBS ¨t²Î¤¤ªø«×¬°¹sªºÀɮ׬屼 +50 3 1 * * ( /usr/bin/find /home1/bbs -size 0 -exec rm -f {} ';' ) + +#¨C¤Ñ¦¤W 6:30 §âbbs¤¤ªºhome©Mpasswords³Æ¥÷ +30 6 * * * bin/backpasswd.sh > /dev/null diff --git a/sample/etc/Logout b/sample/etc/Logout new file mode 100644 index 00000000..c1552af8 --- /dev/null +++ b/sample/etc/Logout @@ -0,0 +1,20 @@ + +[30;44m¢g¢i[40m [30;44m¢j [m [1;33mÁ` ºÊ[m + [34m¢l ¢j[30;44m¢n[34;47m¢« ¢ª[44m [m [1;34m(root)[m + [30;44m¢k[34;40m ¢m[30;44m¢m[1;31;47m PTT [44m [m [1;37mDavidYu[m + [33m ¡Y ¢j[30;44m¢o¢« ¢«[47m I`ll [44m [m + [33m ¢A [30;43m¢n[33;40m¢m [44m [30;47mbe back![44m [m [1;33m°õ¦æ»s§@[m + [33m¢A [33m¢¨[30;43m¡þ[40m [44m [34;47m¢©[0;30;47m [44m [m [1;34m(bbsadm)[m + [30;43m¢o[1;37;40m¢¨¢©¡´[;30;43m¢« [33;44m¢g¢d¢d[34;47m¢©[30;47m [34m¢¨[44m [m [1;37m DavidYu[m + [30;43m¢n[33;40m¢c[1;37m¢i¢i [43m [0;34;43m¢¨[37;44m ¢« [m [1;33m¾É ºt[m + [30;43m¢n [44m [m [1;34m(sysop)[m + [43m [31m ¢w[33;44m¢j [m [1;37m DomaDoma Ricas [m + [33m¢e¢e¢c[30;43m¢l [33;44m¢l [m [1;37m keelar stary[m +[40m [30;43m¢n[40m [33m¢ª[43m [33;44m¢m [m +[40m [30;43m¢o[33;40m¢f¢b ¢ª[30;43m¡Z [33;44m¢k [m [1;33m¬ü³N«ü¾É[m +[34;40m¢h¢e¢c[33m¢ª[30;43m¡Z¡Z¡Z¡þ¢ª¢e[34m¢d¢b [44m [m [1;37mSkyline(µøı¯¸ªø) Vica [m +[44m [30m¢¨¢i[43m¢« ¢ª[44m [m [1;33mºë µØ °Ï[m +[44m [30m¢¨¢«¢¨[47m¢f¢c [37;43m¢h¢e¢c[31;44m¢c¢b¢c [m [1;37mcbcdf[m +[44m [34;40m¢n [30;47m¢g¢c [31m¢ª[41m [31;44m¢« [m [1;31m¯S§O·PÁÂ[m +[44m [34;40m¢l [30;47m¢g¢c[37;41m¢p [31;44m¢© [m [1;36m*s[m +[44m [40m¡@¢á¢ó£B¢ò¢é¢ì¢í[30;47m¢©[41m [31;44m¢« [m [1;37m(¥»¯¸ªº³Ì¨Î¥D¨¤³á)[m diff --git a/sample/etc/Makefile b/sample/etc/Makefile new file mode 100644 index 00000000..8881af2a --- /dev/null +++ b/sample/etc/Makefile @@ -0,0 +1,18 @@ +SUBDIR=chickens +BBSHOME?=$(HOME) +TARGET=$(BBSHOME)/etc/ +FILES= Welcome Welcome_login goodbye register registered ve.hlp Logout\ + Welcome_birth domain_name_query feast today_boring + +all: + +install_sub: + @for i in $(SUBDIR); do\ + cd $$i;\ + make BBSHOME=$(BBSHOME) OSTYPE=$(OSTYPE) install;\ + cd ..;\ + done + +install: install_sub + install -d $(TARGET) + install -c -m 644 $(FILES) $(TARGET) diff --git a/sample/etc/Welcome b/sample/etc/Welcome new file mode 100644 index 00000000..c8abb5a0 --- /dev/null +++ b/sample/etc/Welcome @@ -0,0 +1,18 @@ + +[1;37mWelcome to ... + + + + + +[31m ____ _ _ ____ ____ ____ +[31m| _ \| |_| |_ | __ )| __ ) ___| +[33m| |_) | __| __| | _ \| _ \___ \ +[32m| __/| |_| |_ | |_) | |_) |__) | +[34m|_| \__|\__| |____/|____/____/ + + + + + +[31mÅw[32mªï[33m»Y[34mÁ{[37m¡·PttBBS¡·¥Ø«e¯¸¤W¦³[[33m*u[37m]¤H[m diff --git a/sample/etc/Welcome_birth b/sample/etc/Welcome_birth new file mode 100644 index 00000000..c0496fed --- /dev/null +++ b/sample/etc/Welcome_birth @@ -0,0 +1,23 @@ + ¶Ù*s ¦£¶Ü? ¤£n§Ñ°O¦Û¤vªº¥Í¤é³á!![5m °O±oµoªí·P¨¥....[m + + [1m ¢~¢¡¢~¢¡¢~¢w¢w¢¡¢~¢w¢w¢¡¢~¢w¢w¢¡¢~¢¡¢~¢¡ + [m ¢x¢¢¢£¢x¢x [1;5;33m¡¸[m ¢x¢x [1;5;33m¡¸[m ¢x¢x[1;5;33m ¡¸[m ¢x¢x¢¢¢£¢x + [1m ¢x¢~¢¡¢x¢x¢~¢¡¢x¢x¢~¢w¢£¢x¢~¢w¢£¢¢¢¡¢~¢£ + [m ¢¢¢£¢¢¢£¢¢¢£¢¢¢£¢¢¢£ ¢¢¢£ ¢¢¢£[37;40m[0m + [1m ¢~¢¡ + [m¢~¢¡ [1;5;33m¡¸[m ¢~¢w¢w¢¡¢~¢£¢¢¢¡¢~¢¡ ¢~¢¡¢~¢w¢w¢¡¢~¢¡¢~¢¡ + [1m¢x¢¢¢w¢¡¢~¢¡¢x¢~¢w¢£¢¢¢¡¢~¢£¢x¢¢¢w¢¡¢~¢w¢£¢x¢x[1;5;33m ¡¸[0;1m ¢x¢x¢¢¢£¢x + [m¢x [1;5;33m¡¸[0;1m ¢x¢x¢x¢x¢x ¢x¢¢¢¡¢x¢~¢¡¢x¢x [1;5;33m¡¸[0;1m ¢x¢x¢~¢¡¢x¢¢¢¡¢~¢£ + [1m¢¢¢w¢w¢£¢¢¢£¢¢¢£ ¢¢¢w¢£¢¢¢£¢¢¢£¢¢¢w¢w¢£¢¢¢£¢¢¢£ ¢¢¢£ + +Ãظ֤@º°e¨Î¤H, [1;5;33m ¡ó ¡ó ¡ó ¡ó[m [1;33m§å½ð½ð¹ê·~§{[m¥þÅéû¤u +¤©®ÉÁ÷³·Ã¾¤ë¤Ñ; [1;36m ¢~¢¡¢~¢¡¢~¢¡¢~¢¡[m +¯¬µ»´§u¶ªF®ü, [1;31;47m¢~¢r¢r¢r¢r¢r¢r¢r¢r¢¡[m ¸Û¤ßªº¯¬ºÖ! +¦¼¼vÂܸñ²{«n¤s; [1;36;46m¢x¡¸¡¹¡¸¡¹¡¸¡¹¡¸¡¹¢x[m ¤@Ó¤H¥Íªº¥t¤@Ó¶¥¬q´N¦¹¶}©l +¥Í¾÷½´«k¥V¤£Â_, [1;47;31m¢~¢r¢w¢w¢w¢w¢w¢w¢w¢w¢r¢¡[m ±æ¯à¤@¦|·¶¶. +¤éÂà¬P²¾«Ý©ú¬K; [1;33;46mùéùûùúùûùúùûùúùûùúùûùúùë[m +§Ö·NºZ¬¡¤H¶¡¦æ, [1;35;46m¢xùüùýùüùýùüùýùüùýùüùý¢x[m +¼ÖµÀô¨¼Ö¦Û²K. [1;32;45m¢z¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢{[m + [1;32;44m¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}[m + [1;31m¡¹¡¹¯¬§A¥Í¤é§Ö¼Ö¡¹¯¬§A¥Í¤é§Ö¼Ö¡¹¯¬§A¥Í¤é§Ö¼Ö¡¹¯¬§A¥Í¤é§Ö¼Ö¡¹¯¬§A¥Í¤é§Ö¼Ö¡¹[0m + [1;31m¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b¢b diff --git a/sample/etc/Welcome_login b/sample/etc/Welcome_login new file mode 100644 index 00000000..e5560602 --- /dev/null +++ b/sample/etc/Welcome_login @@ -0,0 +1,12 @@ + + + + + + + + + Åwªï¨Ï¥Î PttBBS ¡I + + + ¦³¥ô¦ó°ÝÃD½Ð¨ì ptt2.csie.ntu.edu.tw ªº PttSrc ªO°Q½×ò! diff --git a/sample/etc/chickens/Makefile b/sample/etc/chickens/Makefile new file mode 100644 index 00000000..37d46a1b --- /dev/null +++ b/sample/etc/chickens/Makefile @@ -0,0 +1,23 @@ +BBSHOME?=$(HOME) +TARGET=$(BBSHOME)/etc/chickens/ +FILES= buymedicine buyoo clean deadth eat food hit kiss\ + medicine nofood nohp nosatis oo read sell toofat tootired\ + a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16\ + b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 b16\ + c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16\ + d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16\ + e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 e10 e11 e12 e13 e14 e15 e16\ + f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16\ + g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 g10 g11 g12 g13 g14 g15 g16\ + h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h16\ + i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16\ + j0 j1 j2 j3 j4 j5 j6 j7 j8 j9 j10 j11 j12 j13 j14 j15 j16\ + k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k11 k12 k13 k14 k15 k16\ + l0 l1 l2 l3 l4 l5 l6 l7 l8 l9 l10 l11 l12 l13 l14 l15 l16\ + m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 m16 + +all: + +install: + install -d $(TARGET) + install -c -m 644 $(FILES) $(TARGET) diff --git a/sample/etc/chickens/a0 b/sample/etc/chickens/a0 new file mode 100644 index 00000000..db81a6e2 --- /dev/null +++ b/sample/etc/chickens/a0 @@ -0,0 +1,11 @@ + + + [41m //¡þ[m + [1;35;41m ¡¸ [m + [1;32;41m ¡´¡´ [m + [41m ¡´[m[1;5;33;41m¡´[m[41m¡´ [m + [1;36;41m ¡´¡´ [m + [41m [m + + + diff --git a/sample/etc/chickens/a1 b/sample/etc/chickens/a1 new file mode 100644 index 00000000..e0517a99 --- /dev/null +++ b/sample/etc/chickens/a1 @@ -0,0 +1,11 @@ + + + + [1;5;35m¡H¡H[m + [1;34m¢c¢i¢i¢c[m [1;5;34m¡¹[m[1;5;33m¡I¡I[m + ¡´ ¡´ [1;35m¢¬[m[1;33m/[m[1;32m/[m + ¡´ ¡´ [1;5;31m|/[m + [1;32m¡þ[m¡´¡´[1;32m¡þ[m[1;5;31m|[m + [1;31m/|\[m + + diff --git a/sample/etc/chickens/a10 b/sample/etc/chickens/a10 new file mode 100644 index 00000000..f57b0c1d --- /dev/null +++ b/sample/etc/chickens/a10 @@ -0,0 +1,15 @@ + [1;31m ¢¨¢¨[m + [1;31m ¢«[m ¡´ + [1;33m ¡´[m ¡´¡´ ¡´ [1;32m ¡·[m¡´ + [1;33m ¡´[m[1;35m ¡´[m ¡´ ¡´ ¡´ [1;31m ¢©[m + [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´ ¡´¡´¡´ ¡´ ¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ + [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ ¡´ + [1;32m ¡´[m [1;32m ¡´[m ¡´ ¡´ + ¡´¡´¡´[1;31m¢[m¡´¡´ ¡´¡´ ¡´¡´ + [1;31m ¢¬ ¢[m ¡´[1;5;33m¡´[m¡´ ¡´[1;5;33m¡´[m¡´ + [1;31m /\¢ /\¢[m ¡´¡´ ¡´¡´ + + + diff --git a/sample/etc/chickens/a11 b/sample/etc/chickens/a11 new file mode 100644 index 00000000..34c70f42 --- /dev/null +++ b/sample/etc/chickens/a11 @@ -0,0 +1,15 @@ + [1;31m ¢¨¢¨[m + [1;31m ¢«[m ¡´ + [1;33m ¡´[m ¡´¡´ ¡´ [1;32m ¡·[m¡´ + [1;33m ¡´[m[1;35m ¡´[m ¡´ ¡´ ¡´ [1;31m ¢©[m + [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´ ¡´¡´¡´ ¡´ ¡´ [1;33m ¡´¡´ ¡´¡´[m + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ [1;33m¡´[m[1;5;32m ¡ó[m[1;33m¡´[m [1;33m¡´[m[1;5;35m ¡ó[m[1;33m¡´[m + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ [1;33m¡´[m [1;31m¢©[m [1;33m¡´[m [1;31m ¢©[m + [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ ¡´ [1;33m¡´ ¡´ ¡´ ¡´[m + [1;32m ¡´[m [1;32m ¡´[m ¡´ ¡´ [1;33m¡´ ¡´ ¡´ ¡´[m + ¡´¡´¡´[1;31m¢[m¡´¡´ [1;33m¡´¡´¡´ ¡´¡´¡´[m + [1;31m ¢¬ ¢[m [1;31m ¡þ ¢@ ¡þ ¢@[m + [1;31m /\¢ /\¢ /|\ /|\ /|\ /|\[m + + + diff --git a/sample/etc/chickens/a12 b/sample/etc/chickens/a12 new file mode 100644 index 00000000..1f5a40e6 --- /dev/null +++ b/sample/etc/chickens/a12 @@ -0,0 +1,13 @@ + [1;31m ¢¨¢¨[m + ¡´¡´ [1;31m ¢«[m ¡´ + ¡´[1;33m ¡´[m[1;31m ¡´¡´[m ¡´ [1;32m ¡·[m¡´ + ¡´[1;33m ¡´[m[1;35m ¡´[m [1;31m ¡´[m ¡´ ¡´ [1;31m ¢©[m + ¡´[1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´[1;5;36m ¡´[m ¡´¡´ ¡´ ¡´ + ¡´[1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ + [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ + [1;32m ¡´[m [1;32m ¡´[m ¡´ [1;5;36m ¡´¡´[m ¡´ + ¡´¡´¡´[1;31m¢[m¡´¡´ + [1;31m ¢¬ ¢[m + [1;31m /\¢ /\¢[m + diff --git a/sample/etc/chickens/a13 b/sample/etc/chickens/a13 new file mode 100644 index 00000000..2304849a --- /dev/null +++ b/sample/etc/chickens/a13 @@ -0,0 +1,14 @@ + + [1;31m ¢¨¢¨[m + [1;31m ¢«[m ¡´ + [1;32m ¡¯[m¡¯ [1;33m¡´[m[1;31m ¡´¡´[m ¡´ [1;32m ¡·[m¡´ + [1;31m ¡¯[m [1;33m ¡´[m[1;35m ¡´[m [1;31m ¡´[m ¡´ ¡´ [1;31m ¢©[m + [1;32m ¡¯[m [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´[1;5;36m ¡´[m ¡´¡´ ¡´ ¡´ + ¡¯ [1;33m ¡´[m[1;35m ¡´[m [1;34m¡´[m ¡´ [1;5;36m ¡´ ¡´[m¡´ + ¡¯[1;5;32m ¡¯[m [1;33m¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ + [1;31m ¡¯[m ¡¯ [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ + [1;5;32m¡¯[m [1;5;31m ¡¯[m [1;5;32m ¡¯[m [1;32m ¡´[m ¡´ [1;5;36m ¡´¡´[m ¡´ + [1;31m ¡¯[m ¡¯ ¡´¡´¡´[1;31m¢[m¡´¡´ + [1;31m ¢¬ ¢[m + [1;31m /\¢ /\¢[m + diff --git a/sample/etc/chickens/a14 b/sample/etc/chickens/a14 new file mode 100644 index 00000000..c8fc7efa --- /dev/null +++ b/sample/etc/chickens/a14 @@ -0,0 +1,17 @@ + [1;31m ¢¨¢¨[m + [1;31m ¢«[m ¡´ + [1;32m ¡¯[m[1;33m¡´[m[1;31m ¡´¡´[m ¡´ [1;31m ¡´[m¡´ + [1;31m ¡¯[m [1;33m ¡´[m[1;35m ¡´[m [1;31m ¡´[m ¡´ ¡´ [1;31m ¢©[m [1;31m±þ®ð¡I¡I[m + [1;32m ¡¯[m [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´[1;5;36m ¡´[m ¡´¡´ ¡´ ¡´ + ¡¯ [1;33m¡´[m[1;35m ¡´[m [1;34m¡´[m ¡´ [1;5;36m ¡´ ¡´[m¡´ [1;32m°«®ð¡I¡I[m + ¡¯[1;5;32m ¡¯[m [1;33m¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ [1;31m ¢ª[m + [1;31m ¡¯[m ¡¯ [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ [1;31m¢©[m[31m¡´[m[1;32m-[m + [1;5;32m¡¯[m [1;5;31m ¡¯[m [1;5;32m ¡¯[m [1;32m ¡´[m ¡´ [1;5;36m ¡´¡´[m ¡´ [1;32m|[m¡´[m[1;32m-[m + [1;31m ¡¯[m ¡¯ ¡´¡´¡´[1;31m¢[m¡´¡´ [1;32m|[m[31m¡´[m[1;32m/ / /[m + [1;31m ¢¬ ¢[m [1;32m|[m[31m ¡´¡´¡´[m[1;31m<[m + [1;31m /\¢ /\¢[m [1;32m\ \ \[m + + + + + diff --git a/sample/etc/chickens/a15 b/sample/etc/chickens/a15 new file mode 100644 index 00000000..79457982 --- /dev/null +++ b/sample/etc/chickens/a15 @@ -0,0 +1,15 @@ + + [1;5;35m¼K¼K¡II CATCH YOU¡I¡I[m [1;31m¢¨¢¨[m [1;32m/[m + [1;31m¢«[m ¡´ [1;32m|[m[31m ¡´[m[1;31m<[m + [1;32m ¡¯[m [1;33m¡´[m[1;31m ¡´¡´[m ¡´ [1;32m¡ä[m¡´ [1;32m|[m[31m¡´[m[1;32m\ \[m + [1;31m ¡¯[m [1;33m ¡´[m[1;35m ¡´[m [1;31m ¡´[m ¡´ ¡´ [1;31m¢©[m[31m¡´[m[1;32m\[m + [1;32m ¡¯[m [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´[1;5;36m ¡´[m ¡´¡´ ¡´ ¡´ [1;32m/[m[31m¡´[m[1;32m\[m + ¡¯ [1;33m ¡´[m[1;35m ¡´[m [1;34m¡´[m ¡´ [1;5;36m ¡´ ¡´[m¡´ [1;32m/[m¡´[1;32m\[m + ¡¯[1;5;32m ¡¯[m [1;33m¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ [31m¡´[m[1;31m¢ª[m + [1;31m ¡¯[m ¡¯ [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ [1;31m¢©[m ¡\[1;32mhelp[m... + [1;5;32m¡¯[m [1;5;31m ¡¯[m [1;5;32m ¡¯[m [1;32m ¡´[m ¡´ [1;5;36m ¡´¡´[m ¡´ + [1;31m ¡¯[m ¡¯ ¡´¡´¡´¡´[1;31m¢[m¡´ + [1;31m¢¬ ¢[m + [1;31m /\¢ /\¢[m + + diff --git a/sample/etc/chickens/a16 b/sample/etc/chickens/a16 new file mode 100644 index 00000000..79457982 --- /dev/null +++ b/sample/etc/chickens/a16 @@ -0,0 +1,15 @@ + + [1;5;35m¼K¼K¡II CATCH YOU¡I¡I[m [1;31m¢¨¢¨[m [1;32m/[m + [1;31m¢«[m ¡´ [1;32m|[m[31m ¡´[m[1;31m<[m + [1;32m ¡¯[m [1;33m¡´[m[1;31m ¡´¡´[m ¡´ [1;32m¡ä[m¡´ [1;32m|[m[31m¡´[m[1;32m\ \[m + [1;31m ¡¯[m [1;33m ¡´[m[1;35m ¡´[m [1;31m ¡´[m ¡´ ¡´ [1;31m¢©[m[31m¡´[m[1;32m\[m + [1;32m ¡¯[m [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´[1;5;36m ¡´[m ¡´¡´ ¡´ ¡´ [1;32m/[m[31m¡´[m[1;32m\[m + ¡¯ [1;33m ¡´[m[1;35m ¡´[m [1;34m¡´[m ¡´ [1;5;36m ¡´ ¡´[m¡´ [1;32m/[m¡´[1;32m\[m + ¡¯[1;5;32m ¡¯[m [1;33m¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ [31m¡´[m[1;31m¢ª[m + [1;31m ¡¯[m ¡¯ [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ [1;5;36m ¡´ ¡´[m ¡´ [1;31m¢©[m ¡\[1;32mhelp[m... + [1;5;32m¡¯[m [1;5;31m ¡¯[m [1;5;32m ¡¯[m [1;32m ¡´[m ¡´ [1;5;36m ¡´¡´[m ¡´ + [1;31m ¡¯[m ¡¯ ¡´¡´¡´¡´[1;31m¢[m¡´ + [1;31m¢¬ ¢[m + [1;31m /\¢ /\¢[m + + diff --git a/sample/etc/chickens/a2 b/sample/etc/chickens/a2 new file mode 100644 index 00000000..6308e505 --- /dev/null +++ b/sample/etc/chickens/a2 @@ -0,0 +1,14 @@ + [1;32m ¡I¡I¡I[m [1;33m ¢[m[1;35m\[m[1;36m\[m + [1;32m ¡Ë[m [1;34m ¢k[m + ¡´¡´ [1;34m ¢i[m[1;32m¡[[m + ¡´ ¡´[1;34m ¢i[m + [1;5;33m¡¸[m ¡´[1;34m ¢k[m + [1;5;31m¡ý[m[1;5;32m\[m[1;5;33m¢[m ¡´ + + ¡´ ¡´ + ¡þ¡´ ¡´¢@ + [1;31m/|\ /|\[m [1;32m ¢¡ý¢A ¢B¡ý¢A[m + [42m ¡Ë¡Ë ¡Ë [m + + + diff --git a/sample/etc/chickens/a3 b/sample/etc/chickens/a3 new file mode 100644 index 00000000..d076a956 --- /dev/null +++ b/sample/etc/chickens/a3 @@ -0,0 +1,13 @@ + [1;33m ¡´¡´[m + [1;33m ¡´ ¡´[m + [1;33m ¡´[m [1;32m¡Ö[m[1;33m¡´[m + [1;33m ¡´[m [1;31m ¢©[m + [1;33m ¡´ ¡´[m + [1;33m ¡´ ¡´[m [1;5;35m /[m[1;5;36m/[m[1;5;33m¢¬[m + [1;33m ¡´ ¡´[m [1;5;32m ¡¸[m + [1;33m ¡´¡´¡´¡´[m¢[1;31m|/[m ¡´ + ¢¬ [1;31m |[m ¡´ ¡´¡´ + [1;31m/|\ [m ¡´ ¡´ ¡´ ¡´ + [42m ¡´¡´ ¡´ ¡´ [m + ¡Ë¡Ë + diff --git a/sample/etc/chickens/a4 b/sample/etc/chickens/a4 new file mode 100644 index 00000000..ea9d6535 --- /dev/null +++ b/sample/etc/chickens/a4 @@ -0,0 +1,13 @@ + [1;33m ¡´¡´¡´[m + [1;33m ¡´ ¡´[m [1;5;32m ¡H¡H¡H [m + [1;33m ¡´[m [1;32m¡ó[m[1;33m¡´[m + [1;33m ¡´[m [1;31m¢©[m + [1;33m ¡´ ¡´[m [1;5;36m ¡H¡H[m + [1;33m ¡´ ¡´ ¡´[m [1;35m ¡´[m [1;32m ¡å[m [1;35m ¡´[m + [1;33m ¡´ ¡ ¡´ ¡´[m [1;35m ¡´[1;33m¢y [m[1;35m ¡´[m + [1;33m ¡´¡´¡´ ¡´[m [1;35m ¡´¡´[m + [1;33m ¡´¡´¡´¡´¡´[m [32m ¢l[m + ¡þ ¢@ [32m ¡¯ ¢l ¡¯[m + [1;31m/|\ /|\[m [32m ¡¯ ¢l¡¯[m + [1;32;42m ¡¯¡¯ [m + diff --git a/sample/etc/chickens/a5 b/sample/etc/chickens/a5 new file mode 100644 index 00000000..9a014666 --- /dev/null +++ b/sample/etc/chickens/a5 @@ -0,0 +1,15 @@ + [1;36m My Brother¡H¡H[m + [1;33m ¡´¡´¡´[m + [1;33m ¡´ ¡´[m [32m ¢n[m + [1;33m ¡´ ¡´[m [31m ¡´¡´[m + [1;33m ¡´[m [1;32m ¡ó ¡ó[m [1;33m ¡´[m [31m ¡´ ¡´[m + [1;33m ¡´ ¡´[m [31m ¡´ ¡´[m + [1;33m ¡´[m [1;31m ¢ª¢«[m [1;33m ¡´[m [31m ¡´ ¡´[m + [1;33m ¡´ ¡´[m [31m ¡´ ¡´[m + [1;33m ¡´ ¡´[m [31m ¡´[m [1;33m °s[m [31m ¡´[m + / [1;33m ¡´¡´¡´¡´¡´[m \ [31m ¡´ ¡´[m + [1;31m /|\ /|\[m [31m ¡´¡´¡´¡´¡´[m + + + + diff --git a/sample/etc/chickens/a6 b/sample/etc/chickens/a6 new file mode 100644 index 00000000..e85fba5a --- /dev/null +++ b/sample/etc/chickens/a6 @@ -0,0 +1,13 @@ + [1;33m ¡´¡´¡´[m + [1;5;33m ¡´[m [1;33m ¡´ ¡´[m [1;5;33m ¡´[m + [1;5;33m ¡´ ¡´[m[1;33m ¡´ ¡´[m[1;5;33m ¡´ ¡´[m + [1;5;33m ¡´[m [1;33m ¡´[m [1;32m ¡ä ¡ä[m [1;33m ¡´[m [1;5;33m ¡´[m [1;5;33m ¡I¡I¡I¡I [m + [1;5;33m ¡´[m [1;33m ¡´ ¡´[m [1;5;33m ¡´[m + [1;5;33m ¡´[m[1;33m ¡´[m [1;31m ¢ª¢«[m [1;33m ¡´[m[1;5;33m ¡´[m [1;36m ¢@¡þ[m + [1;33m ¡´ ¡´[m [1;35m ¡·¡·[m . + [1;33m ¡´ ¡´[m [1;32m ¡´¡´[m . . + [1;33m ¡´ ¡´[m . . + [1;31m ¢¬[m[1;33m ¡´¡´¡´¡´¡´[m[1;31m ¢ [m . . . + [1;31m / | \ / | \[m . . . . . + + diff --git a/sample/etc/chickens/a7 b/sample/etc/chickens/a7 new file mode 100644 index 00000000..6b245d46 --- /dev/null +++ b/sample/etc/chickens/a7 @@ -0,0 +1,16 @@ + [1;31m ¢¨¢¨ [m + [1;31m ¢«[m ¡´ [1;5;32m I see you¡I¡I[m + ¡´ [1;32m ¡·[m¡´ + ¡´ [1;5;33m ¡û[m[1;31m¢© [m + ¡´¡´¡´ ¡´ ¡´[1;5;36m¡û[m + ¡´ ¡´¡´¡´ ¡´ ¡´ [1;5;33m¡û[m + ¡´ ¡´ [1;5;36m¡û[m + ¡´ ¡´ [1;5;33m¡û[m + ¡´ ¡´ [1;5;36m¡û[m + ¡´¡´¡´[1;31m¢[m¡´¡´ [1;32m ..[m[1;5;31m ¡I¡I¡I¡I[m + [1;31m ¢¬ ¢ [m [1;35m ¡ä[m + [1;31m /\¢ /\¢[m [1;35m ¡è¡\[m + + + + diff --git a/sample/etc/chickens/a8 b/sample/etc/chickens/a8 new file mode 100644 index 00000000..9482ca62 --- /dev/null +++ b/sample/etc/chickens/a8 @@ -0,0 +1,13 @@ + [1;31m ¢¨¢¨[m + [1;31m ¢«[m ¡´ + [1;33m ¡´[m ¡´¡´ ¡´ [1;32m ¡·[m¡´ + [1;33m ¡´[m[1;35m ¡´[m ¡´ ¡´ ¡´ [1;31m ¢©[m + [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´ ¡´¡´¡´ ¡´ ¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ + [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´ ¡´ + [1;33m ¡´[m [1;34m ¡´[m ¡´ ¡´ + ¡´¡´¡´[1;31m¢[m¡´¡´ + [1;31m ¢¬ ¢[m + [1;31m /\¢ /\¢[m + diff --git a/sample/etc/chickens/a9 b/sample/etc/chickens/a9 new file mode 100644 index 00000000..e2010a91 --- /dev/null +++ b/sample/etc/chickens/a9 @@ -0,0 +1,14 @@ + [1;31m ¢¨¢¨[m [31m ¢©¢©[m + [1;31m ¢«[m ¡´ ¡´ [31m ¢ª[m + [1;33m ¡´[m ¡´¡´ ¡´ [1;32m ¡·[m¡´ ¡´[1;32m¡·[m ¡´ + [1;33m ¡´[m[1;35m ¡´[m ¡´ ¡´ ¡´ [1;31m ¢© ¢¨[m ¡´ + [1;33m ¡´[m [1;35m ¡´[m[1;34m ¡´[m ¡´ ¡´¡´¡´ ¡´ ¡´ ¡´ ¡´ ¡´¡´¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ ¡´ ¡´ ¡´¡´ ¡´ + [1;33m ¡´[m[1;35m ¡´[m [1;34m ¡´[m ¡´ ¡´ ¡´ ¡´ + [1;32m ¡´[m [1;35m ¡´[m[1;32m ¡´[m ¡´ ¡´ ¡´ ¡´ + [1;32m ¡´[m [1;32m ¡´[m ¡´ ¡´ ¡´ ¡´ + ¡´¡´¡´[1;31m¢[m¡´¡´ ¡´¡´[1;31m¢¬[m¡´¡´ + [1;31m ¢¬ ¢[m [1;31m ¢¬ ¢ [m + [1;31m /\¢ /\¢[m [1;31m ¢¬/\ ¢¬/\[m + + diff --git a/sample/etc/chickens/b0 b/sample/etc/chickens/b0 new file mode 100644 index 00000000..5df42752 --- /dev/null +++ b/sample/etc/chickens/b0 @@ -0,0 +1,9 @@ + + + + + [41m [m + [41m [31;47m¢« ¢ª[41m [m + [41m [5;34;47m ¬ü [0;41m [m + [41m [37m¢ª[47m [37;41m¢« [m + [41m [m diff --git a/sample/etc/chickens/b1 b/sample/etc/chickens/b1 new file mode 100644 index 00000000..0f6bb405 --- /dev/null +++ b/sample/etc/chickens/b1 @@ -0,0 +1,9 @@ + + + [41m [m + [41m [31;46m¢«[30m ¢c[31m¢ª[41m [m + [41m [46m [30;43m¢d ¢d[46m [41m [m + [41m [46m [33m¢ª[5;31;43mO[0;33;46m¢« [41m [m + [41m [33;46m ¡´ ¡´ [41m [m + [41m [36m¢ª[46m [36;41m¢« [m + [41m [m diff --git a/sample/etc/chickens/b10 b/sample/etc/chickens/b10 new file mode 100644 index 00000000..920fd9a9 --- /dev/null +++ b/sample/etc/chickens/b10 @@ -0,0 +1,14 @@ + + [41m [m + [41m [31;40m¢«¢c¢c ¢ª[41m [m + [41m [m [30;43m¡_ ¡_[m [41m [m + [41m [m [30;43m¡´ ¡o[m [5;41m ¡X¡¸ [m + [41m [m [33m¢ª[31;43m ¡¿[33;40m¢«[41m [m + [41m [30;47m¢«[33m¡¿[30m¢ª[41m [m + [41m [43m [30;47m¤f¤f[43m [41m [m + [41m [43m [30;47m [43m [41m [m + [41m [33;44m¢«[30m/II\[33m¢ª[41m [m + [41m [43m [41m [m + [41m [43m [41m [m + [41m [40m [30;41m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/b11 b/sample/etc/chickens/b11 new file mode 100644 index 00000000..920fd9a9 --- /dev/null +++ b/sample/etc/chickens/b11 @@ -0,0 +1,14 @@ + + [41m [m + [41m [31;40m¢«¢c¢c ¢ª[41m [m + [41m [m [30;43m¡_ ¡_[m [41m [m + [41m [m [30;43m¡´ ¡o[m [5;41m ¡X¡¸ [m + [41m [m [33m¢ª[31;43m ¡¿[33;40m¢«[41m [m + [41m [30;47m¢«[33m¡¿[30m¢ª[41m [m + [41m [43m [30;47m¤f¤f[43m [41m [m + [41m [43m [30;47m [43m [41m [m + [41m [33;44m¢«[30m/II\[33m¢ª[41m [m + [41m [43m [41m [m + [41m [43m [41m [m + [41m [40m [30;41m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/b12 b/sample/etc/chickens/b12 new file mode 100644 index 00000000..0519b4ed --- /dev/null +++ b/sample/etc/chickens/b12 @@ -0,0 +1,15 @@ + + [41m [31;40m¢«¢c¢c¢ª[41m [m + [41m [40m [30;43m¡_¡_[m [41m [m + [41m [40m [5;30;43m¡´¡´[m [41m [m + [41m [40m [33m¢ª[31;43m¡¿[33;40m¢« [41m [m + [41m [40m [30;44m¢«[33m¡¿[30m¢ª[m [41m [m + [41m [40m [34;47m ¢ª¢« [m [41m [m + [41m [40m [43m [33;47m [43m [m [41m [m + [41m [43m [30;44mIIII[43m [41m [m + [41m [30;44mI[33m¡´¡´[30mI[41m [m + [41m [30;44mIIIIIIII[41m [m + [41m [30;44mIIIIIIII[41m [m + [41m [30;44mIIIIIIII[41m [m + [41m [43m [41m [m + [41m [m [30;41m¢e[m [41m [m diff --git a/sample/etc/chickens/b13 b/sample/etc/chickens/b13 new file mode 100644 index 00000000..84f408bf --- /dev/null +++ b/sample/etc/chickens/b13 @@ -0,0 +1,17 @@ + [41m [m + [41m [31;40m¢«¢c¢c¢ª[5;30;41m e [m + [41m [m [30;43m¡_¡_[m [5;30;41m [m + [41m [m [30;43m¡o¡o[m [41m [m + [41m [30m¢ª[33;40m¢ª¢«[30;41m¢« [m + [41m [31;44m¢«[33;47m¡¿[31;44m¢ª[41m [m + [41m [37;44m ¡¿ [41m [m + [41m [44m : [5;30;41m [m + [41m [44m : [41m [m + [41m [44m : [41m [m + [41m [43m [30;44m¡ü¡ü[43m [41m [m + [41m [30;44m¡ü¡ü[41m [m + [41m [30;44m¡ü¡ü[41m [m + [41m [30;44m¡ü¡ü[41m [m + [41m [30;43m¡U[41m [m + [41m [m [30;44m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/b14 b/sample/etc/chickens/b14 new file mode 100644 index 00000000..1c7cd389 --- /dev/null +++ b/sample/etc/chickens/b14 @@ -0,0 +1,16 @@ + + [41m [35m¡´[30;41m¢f¢f[35;41m¡´ [m + [41m [31;40m¢«[41m [40m [30;43m¡_¡_[m [41m [31;40m¢ª[41m [m + [41m [40m [41m [40m [5;30;43m¡´¡´[m [41m [40m [41m [m + [41m [30;41m¢ª [33m¢ª[31;43m¡¿[33;41m¢« [30;41m¢« [m + [41m [31;47m¢«[33m¡¿[31m¢ª[41m [m + [41m [30;47m ] [41m [m + [33;41m ¢e [43m [30;47m [43m [33;41m ¢e [m + [41m [31;43m¢e¢e[30;44mIIII[31;43m¢e¢e[41m [m + [41m [30;44mIIIIII[41m [m + [41m [30;44mIIIIIIII[41m [m + [41m [30;44mIIIIIIII[41m [m + [41m [30;44mIIIIIIII[41m [m + [41m [30;43m¡U[41m [m + [41m [m [30;41m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/b15 b/sample/etc/chickens/b15 new file mode 100644 index 00000000..0e325c1c --- /dev/null +++ b/sample/etc/chickens/b15 @@ -0,0 +1,17 @@ + + [41m [31;40m¢« ¢ª[41m [m + [41m [m [30;43m¡_[m [41m [m + [41m [m [30;43m¢«¡´[m [41m [m + [41m [m [33m¢ª¢«[m [5;30;41m¢m [m + [41m [5;31;40m¢m[0;30;47m¢«[33m¡¿[30m¢ª[5;30;41m¢m [m + [41m [5;31;40m¢m[0;1;34;47m p [5;30;41m¢m [m + [41m [5;31;40m¢m[43m [33;47m [43m [5;30;41m¢m [m + [41m [m [43m [34;46mIIII[43m [41m [m + [41m [43m [34;46mIIIIII[43m [41m [m + [41m [34;46mIIIIIIII[41m [m + [41m [34;46mIIIIIIII[41m [m + [41m [34;46mIIIIIIII[41m [m + [41m [34;46mIIIIIIII[41m [m + [41m [43m [41m [m + [41m [m [30;44m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/b16 b/sample/etc/chickens/b16 new file mode 100644 index 00000000..b25212a0 --- /dev/null +++ b/sample/etc/chickens/b16 @@ -0,0 +1,18 @@ + [41m [m + [41m [31;47m¢« ¢ª[41m [m + [41m [47m [30;43m¡_[47m [41m [m + [41m [47m [37;43m¢«[30m¡o[47m [41m [m + [41m [47m [33m¢ª¢«[47m [5;37;41m¢m [m + [41m [5;31;47m¢m[0;37;44m¢«[33m¡¿[37m¢ª[5;37;41m¢m [m + [41m [5;31;47m¢m[0;1;37;44m W [0;5;37;41m¢m [m + [41m [5;31;47m¢m[43m [44m [0;30;43m¡U[44m [43m [5;37;41m¢m [m + [41m [5;31;47m¢m[43m [0;33;44m¢«¢ª[43m [5;37;41m¢m [m + [41m [5;31;47m¢m [0;36;44mIIII[5;37;41m¢i [m + [41m [5;31;47m¢m [0;36;44mIIII[5;37;41m¢i [m + [41m [36;44mIIII[41m [m + [41m [36;44mIIII[41m [m + [41m [36;44mIIII[41m [m + [41m [30;43m¡U[41m [m + [41m [m [30;44m¢e[m [41m [m + [41m [m + diff --git a/sample/etc/chickens/b2 b/sample/etc/chickens/b2 new file mode 100644 index 00000000..ffbe656a --- /dev/null +++ b/sample/etc/chickens/b2 @@ -0,0 +1,11 @@ + + + [41m [m + [41m [31;40m¢«[31m ¢ª[41m [m + [41m [m [30;43m. .[m [5;41m §r [m + [41m [33;40m¢ª[5;31;43mO[0;33;40m¢«[41m [m + [41m [33m¡´[33;47m [33;41m¡´ [m + [41m [31;44m¢« ¢ª[41m [m + [30;41m _[43m [41m_ [m + [41m [m + diff --git a/sample/etc/chickens/b3 b/sample/etc/chickens/b3 new file mode 100644 index 00000000..68a81361 --- /dev/null +++ b/sample/etc/chickens/b3 @@ -0,0 +1,10 @@ + + + [41m [m + [41m [31;40m¢«[31m¢c¢c¢ª[41m [m + [41m [m [30;43m¡_¡_[m [41m [m + [41m [33;40m ¢ª[5;31;43m¡¿[0;33;40m¢« [41m [m + [41m [33m¡´[33;47m [33;41m¡´ [m + [41m [31;44m¢« ¢ª[41m [m + [41m [30;43m¢d[41m [m + [41m [m diff --git a/sample/etc/chickens/b4 b/sample/etc/chickens/b4 new file mode 100644 index 00000000..fde65f4c --- /dev/null +++ b/sample/etc/chickens/b4 @@ -0,0 +1,11 @@ + + + [41m [m + [41m [31;40m¢«[31m¢c¢c¢ª[41m [m + [41m [m [30;43m¡_¡_[m [41m [m + [41m [33;40m ¢ª[5;31;43m¡¿[0;33;40m¢« [41m [m + [41m [33m¡´[33;47m [33;41m¡´ [m + [41m [31;44m¢« ¢ª[41m [m + [41m [30;43m [41m [m + [41m [30;43m¢d[41m [m + [41m [m diff --git a/sample/etc/chickens/b5 b/sample/etc/chickens/b5 new file mode 100644 index 00000000..b74b0bfb --- /dev/null +++ b/sample/etc/chickens/b5 @@ -0,0 +1,12 @@ + + + [41m [m + [41m [31;40m¢«[31m¢c¢c¢ª[41m [m + [41m [m [30;43m¡_¡_[m [41m [m + [41m [33;40m ¢ª[5;31;43m¡¿[0;33;40m¢« [41m [m + [41m [43m [33;47m¢ª¢«[43m [41m [m + [41m [43m [33;47m [43m [41m [m + [41m [33;44m¢« ¢ª[41m [m + [41m [30;43m [41m [m + [41m [30;43m¢d[41m [m + [41m [m diff --git a/sample/etc/chickens/b6 b/sample/etc/chickens/b6 new file mode 100644 index 00000000..279b0c2a --- /dev/null +++ b/sample/etc/chickens/b6 @@ -0,0 +1,12 @@ + + + [41m [m + [41m [31;40m¢«[31m¢c¢c¢ª[41m [m + [41m [m [30;43m¡_¡_[m [41m [m + [41m [33;40m ¢ª[5;31;43m¡¿[0;33;40m¢« [41m [m + [41m [43m [34;47m¢ª¢«[43m [41m [m + [41m [43m [30;47m : [43m [41m [m + [41m [33;44m¢« ¢ª[41m [m + [41m [30;43m [41m [m + [41m [30;43m¢d[41m [m + [41m [m diff --git a/sample/etc/chickens/b7 b/sample/etc/chickens/b7 new file mode 100644 index 00000000..279b0c2a --- /dev/null +++ b/sample/etc/chickens/b7 @@ -0,0 +1,12 @@ + + + [41m [m + [41m [31;40m¢«[31m¢c¢c¢ª[41m [m + [41m [m [30;43m¡_¡_[m [41m [m + [41m [33;40m ¢ª[5;31;43m¡¿[0;33;40m¢« [41m [m + [41m [43m [34;47m¢ª¢«[43m [41m [m + [41m [43m [30;47m : [43m [41m [m + [41m [33;44m¢« ¢ª[41m [m + [41m [30;43m [41m [m + [41m [30;43m¢d[41m [m + [41m [m diff --git a/sample/etc/chickens/b8 b/sample/etc/chickens/b8 new file mode 100644 index 00000000..0b429152 --- /dev/null +++ b/sample/etc/chickens/b8 @@ -0,0 +1,13 @@ + + + [41m [m + [41m [31;40m¢«¢c¢c ¢ª[41m [m + [41m [m [30;43m¡_ ¡_[m [41m [m + [41m [m [30;43m¡´ ¡o[m [5;41m ¡X¡¸ [m + [41m [m [33m¢ª[31;43m ¡¿[33;40m¢«[41m [m + [41m [30;47m¢«[33m¡¿[30m¢ª[41m [m + [41m [43m [30;47m¤f¤f[43m [41m [m + [41m [31;44m¢«[30m/II\[31m¢ª[41m [m + [41m [43m [41m [m + [41m [40m [30;41m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/b9 b/sample/etc/chickens/b9 new file mode 100644 index 00000000..0b429152 --- /dev/null +++ b/sample/etc/chickens/b9 @@ -0,0 +1,13 @@ + + + [41m [m + [41m [31;40m¢«¢c¢c ¢ª[41m [m + [41m [m [30;43m¡_ ¡_[m [41m [m + [41m [m [30;43m¡´ ¡o[m [5;41m ¡X¡¸ [m + [41m [m [33m¢ª[31;43m ¡¿[33;40m¢«[41m [m + [41m [30;47m¢«[33m¡¿[30m¢ª[41m [m + [41m [43m [30;47m¤f¤f[43m [41m [m + [41m [31;44m¢«[30m/II\[31m¢ª[41m [m + [41m [43m [41m [m + [41m [40m [30;41m¢e[m [41m [m + [41m [m diff --git a/sample/etc/chickens/buymedicine b/sample/etc/chickens/buymedicine new file mode 100644 index 00000000..5fe11de7 --- /dev/null +++ b/sample/etc/chickens/buymedicine @@ -0,0 +1,14 @@ + + + + + + + [31;42m W R I G L E Y'S [43;30m¢ª[m + [42;30m £r¡m[0;1;37m¢Ò¢Ý¢ã¢Ð¢Ú¢Ó¢Û¢×¢Ü¢â[0;42;30m¡n [43m [1;32;42m¢v¢v¢v¢v¢v[0;1;37m¢l[m + [31;42m CHEWING GUM [43m [0;1;37m¢×¢Ü¢â[30;42m¡n [0;1;37m¢l[m + [36m¢ª[46;33m ¢ª[42m [0;1;37m¢l[m +[1;32m ¢v¢v¢v¢v¢v¢v¢v¢v¢v¢v¢v¢v¢v¢v¢v[m + + + ¶R¤f»¿}·í·P«_ÃÄ... diff --git a/sample/etc/chickens/buyoo b/sample/etc/chickens/buyoo new file mode 100644 index 00000000..21d5f32a --- /dev/null +++ b/sample/etc/chickens/buyoo @@ -0,0 +1,14 @@ + +[1;37m ¢x ¢x[m + [1;37m ¡¶____________________¡¶[m + [1;37;47m¢» ¢¨¢© [0;34;47m¢q[1;37m ¢¨¢© ¢»[m + [1;47;33m¡Ý ¥Ð¥Ð ¥Ð¥Ð ¡Ý[m + [1;33m¡¶ [33;47m¢i====¥Ð¥Ð====¥Ð¥Ð====[0;1;33m¢i ¡¶[m + [1;33m¢i[36m£Z£Z£Z£Z[33;47m¢i[36m£S£S£S£S£S£S£S£S£S£S[0;1;33m¢i[36m£Z£Z£Z£Z[33m¢i[m + [1;37m¢y[47m¢v¢v¢v[33m¢ª¡·¢«¢v¢v¢v¢v¢v¢v¢v¢v¢ª¡·¢«¢v¢v¢v[0;1;37m¢j[m + [1;37m¢y[33;46m ¥Ð¥Ð ¢i ¥Ð¥Ð ¥Ð¥Ð ¥Ð¥Ð ¢i ¥Ð¥Ð [0;1;37m¢j[m + [1;37m ¢y[33;46m ¥Ð¥Ð ¢i ¥Ð¥Ð[34m¡±¢p¢p¡±[33m¥Ð¥Ð ¢i ¥Ð¥Ð [0;1;37m¢j[m + [1;33m ¢y[43m¡°¡°¡°¡°¡°¢i¡°¡°¡°¡°[34m¢p¢p[33m¡°¡°¡°¡°¢i¡°¡°¡°¡°¡°[0;1;37m¢j[m + [1;36;46m¡½¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¨ùùùùùùùù¢©¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¤¢¤¡½[m + + ¨ì±Ð°ó¨D±o¯«©_¤j¸É¤Y¤@Áû diff --git a/sample/etc/chickens/c0 b/sample/etc/chickens/c0 new file mode 100644 index 00000000..388926ab --- /dev/null +++ b/sample/etc/chickens/c0 @@ -0,0 +1,8 @@ + + + [1;33;40m¢¨¢i¢©[m + [0;30;43m \[0;33;40m¢i[0;30;43m/ [0;36;40m «z¡ã«z¡ã[m + [0;33;46m¢ª[5;30;43m¢Ý[0;33;46m¢«[m + [0;30;46m¡þ[0;30;46m¢¬[0;36;40m¢i[m + [0;30;46m¢¬[0;36;40m¢i¢i[m + [0;36;40m¢ª¢i¢«[m diff --git a/sample/etc/chickens/c1 b/sample/etc/chickens/c1 new file mode 100644 index 00000000..8311a4af --- /dev/null +++ b/sample/etc/chickens/c1 @@ -0,0 +1,9 @@ + + [1m[33;40m¢¨[m + [1;33;40m¢i¢i¢i¢i [0;36;40m¤°»ò¬O«i¤h°Ú¡H[m + [1;33;43m¢i¢«[0;30;43m¡_[1;33;43m¢ª[1;33;40m¢©[m + [1m[33;40m¢ª¢i[0;33;40m¢i[0;30;43m[5;30;43m¢[5;33;40mi[0;33;40m[0;33;40m¢i[m + [0;33;40m¢ª¢i¢i¢«[m + [1;35;40m¢¨[1;31;46m ¡¿ [1;35;40m¢©[m + [1;35;46m¢i [0;30;46m¡· [1;35;40m¢i[m + diff --git a/sample/etc/chickens/c10 b/sample/etc/chickens/c10 new file mode 100644 index 00000000..bfafeffc --- /dev/null +++ b/sample/etc/chickens/c10 @@ -0,0 +1,11 @@ + [1;33m¢©[m + [1;33m¢i¢i¢i¢i [0;36m´Â¯u¼Ç°°½Ö¯à¿ë[m + [1;33;43m¢i¢i¢«¢ª¢i[m + [1;33;43m¢i¢«[0;30;43m¢m[0;33m¢i[1;33m¢i¢« [0;36m´¼·M¥Ã¬O¨â¤½¥[m + [1;33m¢«[0;33m¢ª¢i¢i¢«[m + [0;35m¢ª¢i[1;31;45m¡·[0;36;47m¢«¡¿¢ª[1;31;45m¡·[0;35;40m¢i¢«[m + [0;35;43m¢ª¢i[0;30;47m ¢® [0;35;43m¢i¢«[m + [0;33m¢i[0;35;40m¢ª[0;35;47m è [0;35;40m¢«[0;33m¢i[m + [1;31m¢ª¢i¢© ¢i[0;34m¢¨ [1;31m¢i[m + [0;34m¢i¢i[0;33m¢i[1;33;44m¡´[1;37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[1;37;40m¢«[m + [0;30;43m¢n[0;34;40m¢ª[m diff --git a/sample/etc/chickens/c11 b/sample/etc/chickens/c11 new file mode 100644 index 00000000..0170493b --- /dev/null +++ b/sample/etc/chickens/c11 @@ -0,0 +1,10 @@ + + [1;33m¢ª¢i¢© ¢¨[m + [1;33m¢i¢i¢i¢i [0;36m¤HºÙ¤@¬y¤M¤@¬y[m + [0;31m¢ª¢©[0;33m¢l [1;33;43m¢i¢«¢ª¢i¢i[m +[1;37m¢¨¢i¢i¢i¢i¢i¢i¢i¢i¢i¢i¢i¢i[1;31;41m¡´[0;33m¢i[0;31m¢i [1;33m¢ª¢i[0;33m¢i¢m[1;33;43m¢ª¢i[m [0;36m¤MºÙ¤@¬y¤H¤@¬y[m + [0;31m¢¨¢«[1;36m¢i [0;33m¢ª¢i¢i¢«[1;33m¢ª[m + [0;33m¢i¢i[0;33;42m¢© [0;34;42m¢ª[1;31;44m ¡¿ [0;34;42m¢« [0;33;42m¢¨¢i¢i[1;36m¢i[0;33m¢i[0;30;43m¢f[m + [0;31m¢i[0;31;42m¢© [0;34;42m¢ª¢« [0;31;42m¢¨¢i[m + [0;31m¢i¢i[0;36;42m¢© ¢¨[31m¢i¢i[m + [31m¢i¢i [37mªZ [31m¢i¢i[m diff --git a/sample/etc/chickens/c12 b/sample/etc/chickens/c12 new file mode 100644 index 00000000..020ae4ca --- /dev/null +++ b/sample/etc/chickens/c12 @@ -0,0 +1,12 @@ + + [1;33m¢© ¢¨¢i¢«[m + [1;33m¢i¢i¢i¢i [0;36mªF·§j¿ô^¶¯¹Ú[m + [1;33;43m¢i¢i¢«¢ª¢i[m + [1;33;43m¢i¢«[0;30;43m¢m[0;33m¢i[1;33m¢i¢« [0;36m¯º¹ï¤d¤s¸U«¤Ñ[m + [1;33m¢«[0;33m¢ª¢i¢i¢«[m + [0;37;46m¢©[0;31;46m¢ª¢i[1;36;41m¡·[1;35;47m¢«¡¿¢ª[1;36;41m¡·[0;31;46m¢i¢«[37;46m¢¨[m + [37;46m¢©[31;43m¢ª¢i[31;47m ¢® ¢i[31;43m¢«[37;46m¢¨[m +[1;31m¢¨¢i¢© [0;33m¢i[0;31;46m¢ª[31;47m ±þ [31;46m¢«[33m¢i[m +[1;31m¢« ¢ª¢i¢© [1;35m¢i[0;35m¢¨¢« [1;35m¢i[m + [0;35m¢i¢i[33m¢i[1;32;45m¡´[1;37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[1;37;40m¢«[m + [0;30;43m¢n[0;35;40m¢ª¢©[m diff --git a/sample/etc/chickens/c13 b/sample/etc/chickens/c13 new file mode 100644 index 00000000..f842255c --- /dev/null +++ b/sample/etc/chickens/c13 @@ -0,0 +1,11 @@ + [1;33m¢ª¢i¢© ¢¨[m + [1;33m¢i¢i¢i¢i [0;36m´H¼CÀqÅ¥§g¤l·N[m + [1;33;43m¢i¢«¢ª¢i¢i[m + [1;33m¢ª¢i[0;33m¢i¢m[1;33;43m¢ª¢i[0;36m ¶Æµø¤H¶¡¯º¬õ¹Ð[m + [0;33m¢ª¢i¢i¢«[1;33m¢ª[m + [34m¢ª[35;44m¢ª[36;45m ¡¾ [35;44m¢«[34;47m¢«¡¿¢ª[35;44m¢ª[36;45m ¡¾ [35;44m¢«[34;40m¢«[m + [34;41m¢ª[35;44m¢ª¢«[34;43m¢«[30;47m ¡ý [34;43m¢ª[35;44m¢ª¢«[34;41m¢«[m + [34;41m [34m¢ª[34;41m¢«[33m¢i[31;47m ¤Ñ [33m¢i[34;41m¢ª¢« [m + [34;41m ¢ª[34;40m¢© ¢i[36;41m¢¨¢« [m + [34;41m [34;40m¢ª[33m¢i[36m¢i[33m¢i[1;36;46m¡´[1;37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[1;37;40m¢«[m + [41m [37;40m [0;31;43m¢n[36;41m¢ª¢© [m diff --git a/sample/etc/chickens/c14 b/sample/etc/chickens/c14 new file mode 100644 index 00000000..35636ed9 --- /dev/null +++ b/sample/etc/chickens/c14 @@ -0,0 +1,12 @@ + [1m[33m¢ª¢i¢© ¢¨[m + [1;33m¢i¢i¢i¢i [0;36m¤@¤@¼C¥¥Í·N[m + [1;33;43m¢i¢«¢ª¢i¢i[m [0;33m¢l[m + [1;33m¢ª¢i[0;33m¢i¢m[1;33;43m¢ª¢i[0;33;40m ¢i [0;36mtºÉ¨g¦W¤Q¤¦~[m + [0;33m¢ª¢i¢i¢«[1;33m¢ª [1;31m¢i[m + [0;30;45m¢©[32;45m¢ª[31;42m¢ª¢«[32;45m¢«[1;31m¡¿[0;32;45m¢ª[31;42m¢ª¢«[32;45m¢«[33;45m¢¨¢i[m + [31;45m¢©[32;43m¢ª¢i[37;45m¡¼¢®¡¼[32;45m¢i¢«[31;45m¢¨[m + [1;31m¢¨¢i¢© [0;33;41m ¢i[32;45m¢ª[34;45m¢©[37;45m¢® [32;45m¢«[31;45m¢¨[37;41m [m + [1;31m¢« ¢ª¢i¢© [1;31;41m ¢i[0;34;41m¢¨[34;40m¢«[1;31m®© [37;41m [m + [34m¢i¢i[33m¢i[1;34;44m¡´[1;37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[1;37;40m¢«[m + [37;41m [31;43m¢n[34;41m¢ª[34;46m¢©[30m¡ý [37;41m [m + [34;41m [34;46m¢«[30m¡ý [37;41m [m diff --git a/sample/etc/chickens/c15 b/sample/etc/chickens/c15 new file mode 100644 index 00000000..89822c4f --- /dev/null +++ b/sample/etc/chickens/c15 @@ -0,0 +1,12 @@ + [m[5;31;40m[1m ¢© ¢© ¢¨ + [1m[5;31;40m¢ª ¢ª ¢« ¢¨ [0;36;40m¤¤©¶µÂìX±¡[m + [1m[5;31;40m¢©[m[1;33m¢ª¢i¢© [1;33;40m¢¨ [1m[5;31;40m¢« [0;36;40m¼C¤U¸{¦å°O«ë¤³[m + [1m[5;31;40m¢ª¢© ¢ª[m [1;33;40m¢i¢i¢i¢i [1m[5;31;40m¢¨ ¢¨¢« ¢¨¢« [0;36;40m¨Ó¦ó¬¤´é»Ý´§¼C[m + [1m[5;31;40m¢ª¢© ¢© [m [1;33;43m¢i¢«¢ª¢i¢i[m [1m[5;31;40m¢« ¢¨¢« ¢¨¢« [0;36;40m¥h¦VÄñºø¥i´_Â[m + [1m[5;31;40m¢ª [m [1;33;40m¢ª¢i[0;33;40m¢i¢m[1;33;43m¢ª¢i[m [0;31;40m¢©[m + [1m[5;31;40m¢ª¢© [0;30;44m¢©¢ª[m [0;33;40m¢ª¢i¢i¢«[1;33;40m¢ª [0;30;44m¢«¢¨[m [0;31;40m¢¨¢«[m + [0;30;44m¢©[35m¢ª¢i¢i[1;35;42m¢«¡¿¢ª[0;35;44m¢i¢i¢«[33;44m¢¨¢i¢i[35;40m¢i[33;40m¢i[1;32;41m¡´[37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[40m¢«[m + [0;31;40m¢¨[31;44m¢©[35;44m¢ª[1;35;45m¡Ñ[0;37;42m¡¼¢®¡¼[1;35;45m¡Ñ[0;35;44m¢«[31;44m¢¨[40m¢© [0;30;43m¢g[31;40m¢ª[31;40m¢©[m + [0;31;40m¢¨[31;41m [33;44m¢©[35m¢ª[37;42m ¢® [35;44m¢«[0;31;44m¢¨[0;31;41m [0;31m¢© ¢«[m + [0;31;40m¢¨[0;31;41m [0;33;44m¢i[31m¢©[m «ã [0;31;44m¢¨[0;31;41m [0;31;40m¢©[m + [0;31;40m¢¨[35;41m ¢i ¢i¢i[35;41m¢i [31;40m¢©[m diff --git a/sample/etc/chickens/c16 b/sample/etc/chickens/c16 new file mode 100644 index 00000000..93b54373 --- /dev/null +++ b/sample/etc/chickens/c16 @@ -0,0 +1,11 @@ + + [m[36m·R¸¨¬õ¹Ð¤ß¤w¦º [m¢¨[m + ¢¨¢i¢i¢i¢i[m + [36m«ù¤M©ê¼C¤F¤@¥Í [37;43m¢i¢i¢«¢ª¢i¢i[m + [34m¢¨ [37;43m¢i¢i [33;40m¢m[37;43m¢ª¢i[m + [34m¢ª¢© [30;44m¢©¢ª[37;40m ¢¨¢i¢i[33m¢i¢i¢«[m¢ª [30;44m¢«¢¨[m +[1m¢ª[37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[1;34;44m¡´[0;33m¢i[35m¢i[33m¢i¢i[33;44m¢©[35;44m¢ª¢i¢i¢«¡¿¢ª¢i¢i¢«[30;44m¢¨[m + [34m¢¨¢«[30;43m¢g[m [31;44m¢©[35;44m¢ª¢i ¢® ¢i¢«[31;44m¢¨[40m¢©[m + [34m¢ª [31;44m¢i¢©[35;44m¢ª ¢® ¢«[33;44m¢¨[31;41m ¢i[31;40m¢©[m + [36m¡ã¤M¨g¼C·ö¡ã [31;44m¢i¢i¢©[m Áô [31;44m¢¨[33m¢i[31;41m ¢i¢i[31;40m¢©[m + [31m¢i¢i¢i[36m¢i¢i¢i[35;41m ¢i [31;40m¢i¢i¢i¢©[m diff --git a/sample/etc/chickens/c2 b/sample/etc/chickens/c2 new file mode 100644 index 00000000..19901098 --- /dev/null +++ b/sample/etc/chickens/c2 @@ -0,0 +1,9 @@ + + [1;33;40m¢©[m + [1;33;40m¢i¢i¢i¢i[m + [1;33;40m¢¨[1;33;43m¢«[0;30;43m¡_[1;33;43m¢ª¢i[m + [0;33;40m¢i[5;30;43m¢[5;33;40mi[0;33;40m¢i[1;33;40m¢i¢«[m + [0;33;40m¢ª¢i¢i¢«[m + [m[1m[31;40m¢¨[1;31;42m ¡¿ [1;31;40m¢©[m + [1;31;40m¢¨[1;31;43m¢«[1;31;42m ¡· [1;31;43m¢ª[1;31;40m¢©[m + [0;33;40m¢i ¢i[m diff --git a/sample/etc/chickens/c3 b/sample/etc/chickens/c3 new file mode 100644 index 00000000..362d06f0 --- /dev/null +++ b/sample/etc/chickens/c3 @@ -0,0 +1,8 @@ + + [1;33;40m¢©[m + [1;33;40m¢i¢i¢i¢i[m + [1;33;40m¢¨[1;33;43m¢«[0;30;43m¡_[1;33;43m¢ª¢i[m + [0;33;40m¢i[5;30;43m¢[5;33;40mi[0;33;40m¢i[1;33;40m¢i¢«[m + [0;33;40m¢ª¢i¢i¢«[m + [0;33;40m¢i[0;37;40m¢i[0;33;40m¢i[0;34;43m¢ª[1;31;44m ¡¿ [0;34;43m¢«[0;33;40m¢i[0;37;40m¢i[0;33;40m¢i[m + [0;34;41m [0;34;41m[0;34;43m¢ª¢«[0;34;41m [m diff --git a/sample/etc/chickens/c4 b/sample/etc/chickens/c4 new file mode 100644 index 00000000..88095521 --- /dev/null +++ b/sample/etc/chickens/c4 @@ -0,0 +1,11 @@ + + [1;37;40m¢[0;37;40m¨[m + [1;37;40m¢[0;37;40mi[m + [1;37;40m¢[mi [1;33;40m¢¨ [0;36;40m§A¡I´±±µ¨ü§Úªº¬D¾Ô¶Ü¡H[m + [1;37;40m¢[mi [1;33;40m¢i¢i¢i¢i[m + [1;37;40m¢[mi [1;33;40m¢i[1;33;43m¢«[0;30;43m¡_[1;33;43m¢ª¢i[m + [1;37;40m¢[mi [1;33;40m¢ª¢i[0;33;40m¢i[5;30;43m¢[5;33;40mi[0;33;40m¢i[1;33;40m¢ª[m + [0;32;40m¢ª[1;36;42m¡´[0;32;40m¢« [0;33;40m¢ª¢i¢i¢«[m + [0;33;40m¢i[1;34;40m¢i[0;33;40m¢i[0;34;43m¢ª¢i[1;31;47m¡¿[0;34;43m¢i¢«[0;33;40m¢i[1;34;40m¢i[0;33;40m¢i[0;30;43m¢f[m + [0;32;40m¢i [0;31;40m¢¨[0;34;41m ¢i[0;37;47m¢i[0;34;41m¢i [0;31;40m¢©[m + [0;31;40m¢¨[0;34;41m ¢i[0;30;46m«i[0;34;41m¢i [0;31;40m¢©[m diff --git a/sample/etc/chickens/c5 b/sample/etc/chickens/c5 new file mode 100644 index 00000000..ad2311ba --- /dev/null +++ b/sample/etc/chickens/c5 @@ -0,0 +1,12 @@ + + + [1;37;40m¢[0;37;40m¨[m + [1;37;40m¢[0;37;40mi[m + [1;37;40m¢[mi [1;33;40m¢¨ [0;36;40m§A¡I´±±µ¨ü§Úªº¬D¾Ô¶Ü¡H[m + [1;37;40m¢[mi [1;33;40m¢i¢i¢i¢i[m + [1;37;40m¢[mi [1;33;40m¢i[1;33;43m¢«[0;30;43m¡_[1;33;43m¢ª¢i[m + [1;37;40m¢[mi [1;33;40m¢ª¢i[0;33;40m¢i[5;30;43m¢[5;33;40mi[0;33;40m¢i[1;33;40m¢ª[m + [0;32;40m¢ª[1;36;42m¡´[0;32;40m¢« [0;33;40m¢ª¢i¢i¢«[m + [0;33;40m¢i[1;34;40m¢i[0;33;40m¢i[0;34;43m¢ª¢i[1;31;47m¡¿[0;34;43m¢i¢«[0;33;40m¢i[1;34;40m¢i[0;33;40m¢i[0;30;43m¢f[m + [0;32;40m¢i [0;31;40m¢¨[0;34;41m ¢i[0;37;47m¢i[0;34;41m¢i [0;31;40m¢©[m + [0;31;40m¢¨[0;34;41m ¢i[0;30;46m«i[0;34;41m¢i [0;31;40m¢©[m diff --git a/sample/etc/chickens/c6 b/sample/etc/chickens/c6 new file mode 100644 index 00000000..ee018e38 --- /dev/null +++ b/sample/etc/chickens/c6 @@ -0,0 +1,10 @@ + + [1;37;40m¢[m¨ [1;33;40m¢©[m + [1;37;40m¢[mi [1;33;40m¢i¢i¢i¢i [0;36m©ñ°¨¹L¨Ó¡I[m + [1;37;40m¢[mi [1;33;43m¢i¢«[0;30;43m¡_[1;33;43m¢i¢i[m + [1;37m¢[mi [1;33m¢«[0;33m¢i[5;30;43m¢[5;33;40mi[m[1;33;43m¢ª¢i[1;33;40m¢«[m + [1;37m¢[mi [0;33m¢ª¢i[0;33;40m¢i¢«[m + [1;37m¢[mi [1;31m¢¨¢i[1;31;45m¢«¡¿¢ª¢i[1;31;40m¢©[m + [0;32;40m ¢ª[1;36;42m¡´[0;32;40m¢« [0;33;40m¢¨[0;33;41m¢«[0;35m¢i[0;30;45m¢®[0;35m¢i[0;33m¢i[0;31;40m¢©[m + [0;30;43m¢g[0;33m¢i[0;35m¢i[0;33m¢i¢«[0;31m¢i[1;32;40m §Ô [0;33;41m¢i [0;31;40m¢©[m + [0;32m¢i [31;44m¢i [35m¢i[0;31;41m ¢i[m diff --git a/sample/etc/chickens/c7 b/sample/etc/chickens/c7 new file mode 100644 index 00000000..0db89687 --- /dev/null +++ b/sample/etc/chickens/c7 @@ -0,0 +1,12 @@ + + [1;37m¢[m¨[m + [1;37m¢[mi [36m§O ¤H ªº ¥¢ ±Ñ ´N ¬O §Ú ªº §Ö ¼Ö °Õ ¡I[m + [1;37m¢[mi [1;33m¢©[m + [1;37m¢[mi [1;33m¢i¢i¢i¢i[m + [1;37m¢[mi [1;33;43m¢i¢«[0;30;43m¡_[1;33;43m¢ª¢i[m + [1;37m¢[mi [1;33m¢«[0;33m¢i[5;30;43m¢[5;33;40mi[0;33m¢i[1m¢i¢«[m + [1;37m¢[mi [0;33m¢ª¢i[0;33;40m¢i¢«[m + [1;37m¢[mi [0;32m¢ª¢i[32;46m¢©¡¿¢¨¢i[32;40m¢«[m + [34m¢ª[1;31;44m¡´[0;34;40m¢« [33m¢¨[33;41m¢«[32;46m¢ª¢i¢«[33m¢i[31;40m¢©[m + [33m¢i[36m¢i[33m¢i¢«[31m¢i[33;46m ¢i[31;41m [31;40m¢©[m + [34m¢i [31m¢i [1;33m©R [0;36m¢i[37;41m [31m¢i[m diff --git a/sample/etc/chickens/c8 b/sample/etc/chickens/c8 new file mode 100644 index 00000000..22be6bab --- /dev/null +++ b/sample/etc/chickens/c8 @@ -0,0 +1,12 @@ + [1;33;40m¢¨[m + [1;33;40m¢i¢i¢i¢i [0;36;40mÂù¸}½ð½¹Ð¥@®ö[m + [1;33;43m¢i¢«¢ª[1;33;40m¢i¢i[m + [1;33;40m¢ª¢i[0;33;40m¢i¢m[1;33;43m¢ª[1;33;40m¢i [0;36;40m¤@ªÓ¾áºÉ¥j¤µ·T[m + [0;33;40m¢ª¢i¢i¢«[1;33;40m¢ª[m + [0;35;40m¢i[1;32;45m¡Û[0;35;44m¢«¡¿¢ª[1;32;45m¡Û[0;35;40m¢i[m + [0;35;40m¢i[0;35;43m¢«[0;37;44m [0;35;43m¢ª[0;35;40m¢i[m + [0;35;40m¢«[0;33;44m¢i[0;34;40m ¨g [0;33;40m¢i[0;35;40m¢ª[m + [0;33;40m[1;34;40m¢ª[1;34;40m¢© [1;34;40m¢i[0;31;40m¢¨[m + [0;33;40m[1;34;40m¢ª[0;33;40m¢i[0;31;40m¢i[0;33;40m¢i[1;31;41m¡´[1;37;47m¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e[37;40m¢«[m + [1m[1;31;40m¢¨ [0;30;43m¢n[0;31;40m¢ª[m + [1;31;40m¢«[m diff --git a/sample/etc/chickens/c9 b/sample/etc/chickens/c9 new file mode 100644 index 00000000..676a0da9 --- /dev/null +++ b/sample/etc/chickens/c9 @@ -0,0 +1,11 @@ + [1;37m¢©[m + [1;37m¢ª¢©[m + [1;37m¢ª¢© [1;33m¢©[m + [1;37m¢ª¢© [1;33m¢i¢i¢i¢i [0;36m©º¦ç¬õ¹Ð¤Æ¶³·Ï[m + [1;37m¢ª¢© [1;33;43m¢i¢i¢«¢ª¢i[m + [1;37m¢ª¢© [1;33;43m¢i¢«[0;30;43m¢m[33m¢i[1m¢i[1;33;40m¢« [0;36m¦¿´ò¸¨©Ý¤£ª¾¦~[m + [1;37m¢ª¢© [1;33m¢«[0m[33m¢ª¢i¢i¢«[m + [1;37m¢ª¢© [1;31m¢¨¢i¢i[31;44m¢© ¡¿ ¢¨¢i¢i[31;40m¢©[m + [1;37m¢ª¢© [0;33;41m¢¨¢«[1;31;44m¢ª[31;44m¢©¢¨¢«[0;33;41m¢ª¢©[m + [0;32m¢ª¢i¢©[1;34m¢¨[41m¢« [1;31;44m¢©¢ª¢«¢¨[1;34;41m ¢i[m + [0;30;43m¢g[0;33;40m¢i[1;34m¢«[41m [1;31m¢ª[1;33;44m ¼C [1;31;41m¢« [0;33m¢i[m diff --git a/sample/etc/chickens/clean b/sample/etc/chickens/clean new file mode 100644 index 00000000..9d9118a3 --- /dev/null +++ b/sample/etc/chickens/clean @@ -0,0 +1,14 @@ + [1;33m ùúùùùáùý_____________________¢y¢v¢v¢j_______¢y¢@___ + [1;31m ùøùúùáùû______________ ¡þ¢j ¡´ ¡´_________¡´¢y___ + [1;37m ùøùüùøùø______________¢y ¡´ _________¢y ¡^____¡´___ + [1;36m ùüùùùáùý______________¡´_____________¡´____________ +[1;36m ùüùý ùúùùùùùùùû[m +[1;33m ¡y[37m¢i¢i¢i¢i[m +[1;37m ¢i¢i¢i¢i[m +[1;37m ¢b¢b¢b¢b¢b¢b¢b¢b[32m¡·[37m¢i¢i¢i¢i[m +[37m ¢g¢g¢g¢g¢g¢g¢g¢g¢p[1;37m¢i¢i¢i¢i[m +[37m ¢ªùþùþùþùþùþùþùþùþ[1;33m ùø[m +[36m ¢ª¢i¢i¢i¢i¢i[1;33mùùùý[m +[1;36m ¢¨ùþùþùþùþùþ[m + [1;37m ¢v¢v¢v¢v¢v¢v[m + ¬~¬~¾þ..²M°£«K«K.. diff --git a/sample/etc/chickens/d0 b/sample/etc/chickens/d0 new file mode 100644 index 00000000..ea818c4d --- /dev/null +++ b/sample/etc/chickens/d0 @@ -0,0 +1,10 @@ + + [1;5;32m|[m[1;5;33m/[m[1;5;35m¢¬[m + [1;5;31m¡¸[m + [41m [m + [41m [m[1;33;41m¡´[m[1;34;41m¡´[m[41m [m + [41m [m[1;32;41m¡´[m[1;5;36mµï[m[1;35;41m¡´[m[41m [m + [41m [m[1;34;41m¡´[m[1;33;41m¡´[m[41m [m + [41m [m + + diff --git a/sample/etc/chickens/d1 b/sample/etc/chickens/d1 new file mode 100644 index 00000000..91e04a2f --- /dev/null +++ b/sample/etc/chickens/d1 @@ -0,0 +1,9 @@ + + [1;32m¥Í©R[m[1;5;33m¡H¡H[m + ¡\ + [1;5;31m¢[m[1;5;32m\[m[1;5;33m|[m ¡´[1;31m¡´[m + [1;5;35m¡¹[m [1;31m¡´[m¡[ [1;36m¡¹[m + [1;5;34m¡I¡I[m ¡´ [32m¢¨¢k[m + ¡´ ¡´ [32m¢©[m + [1;31m¡´¡´[m [1;32m\|/[m [32m¢k[m[1;32m\|/ \|/[m + [42m ¡Ë [m diff --git a/sample/etc/chickens/d10 b/sample/etc/chickens/d10 new file mode 100644 index 00000000..714254ea --- /dev/null +++ b/sample/etc/chickens/d10 @@ -0,0 +1,11 @@ + + [32m¡´¡´ ¡´[m [1;5;31m¡I¡I¡I¡I[m + [32m¡´ ¡´[m [1;33m¡ä\[m + [1;32m¡´[m [1;31m¡¸[m [1;32m¡´[m [32m¡´¡´[m[1;34m\\[m [1;5;32m¡I¡I¡I¡I[m [1;33m||¡ý[m + [32m¡´[m [1;36m¡¹[m [32m¡´[m [1;32m¡ó[m [1;33m||¡ý[m + [32m¡´[m[1;31m¡´ ¡´ ¡´ ¡´[m [1;35m¢©[m [1;31m¡ó[m[1;32m___________[m + [1;31m¡´/[m[32m_[m[1;31m¡´[m[32m¡È[m[1;31m¡´[m [1;31m¡´\[m_ [1;34m¡l[m¡p [1;31m¡ó[m[1;32m---¡`¡`¡`¡`[m . . . . . . + [1;31m¡´\ ¡´\ ¡´/ ¡´/[m [1;33m||¡ý[m + [1;35m¢ª ¢ª ¡¿ ¢«[m [1;33m¡å/[m + + diff --git a/sample/etc/chickens/d11 b/sample/etc/chickens/d11 new file mode 100644 index 00000000..b7e86634 --- /dev/null +++ b/sample/etc/chickens/d11 @@ -0,0 +1,15 @@ + + [1;5;36mµ¥µ¥§Ú¡I¡I[m [1;31m¢¨¢©¢¨¢©[m + [1;31m¢i¢i¢i¢i[m + [1;31m¢ª¢i¢i¢«[m + [32m¡´¡´ ¡´[m [1;31m¢ª¢«[m + [1;32m¡´[m [1;5;31m¡¸[m [1;32m¡´[m + [32m¡´[m [1;32m¡¹[m [32m¡´ ¡´¡´[m[1;33m\\[m [1;33m¡´¡´[m + [32m¡´[m [1;5;34m¡¸[m [32m¡´[m [1;32m¡ä[m [31m¡´ ¡´ ¡´¡´[m[1;35m\[m + [32m¡´[m [1;31m¡´ ¡´ ¡´¡´[m [1;35m¢©[m [31m¡´ ¡´[m [1;32m¡ä[m + [1;31m¡´[m[32m¢f[m[1;31m¡´[m[32m¢f[m[1;31m¡´[m[32m¢f--[m[1;31m¡´[m¢d[1;34m¡l¡p[m [31m¢f¡´¢f¡´¢f ¡´¢d[m [1;36m¢©[m + [1;31m¡´/ ¡´/ ¡´/ \¡´[m [1;35m// // // \\[m + [1;31m¢ª\ ¢ª\ ¢ª\ |¢«[m [1;35m\| \| \| |/[m + [42m [m + + diff --git a/sample/etc/chickens/d12 b/sample/etc/chickens/d12 new file mode 100644 index 00000000..ab421653 --- /dev/null +++ b/sample/etc/chickens/d12 @@ -0,0 +1,13 @@ + [32m¢c¢¨¢c ¢c¢¨¢c ¢c¢k[m + [32m¢ª . ¢ª ¢k[m + . [33m¢k[m + [35m¡´¡´ ¡´[m . [33m¢k[m + [1;32m¡´[m [1;5;31m¡¸[m [32m¡´[m [1;31m¡Ö[m[1;34m¡´¡´[m[1;31m¡ç[m [33m¢k[m + [32m¡´[m [1;33m¡¹[m [32m¡´ ¡´¡´[m[1;36m\\[m [1;31m¡X[m[1;33m¡´¡´[m[1;31m¡Ð[m [33m¢k[m + [32m¡´[m [1;5;34m¡¸[m [1;32m¡´[m [1;32m¡ä[m [1;31m/[m [1;32mOO[m [1;31m\[m [33m¢k[m + [32m¡´[m [1;31m¡´ ¡´ ¡´¡´[m [1;35m¢©[m [33m¢k[m + [1;31m¡´[m[32m¢f[m[1;31m¡´[m[32m¢f[m[1;31m¡´[m[32m¢f--[m[1;31m¡´[m[1;34m¢d¡l[m¡p [33m¢k[m + [1;31m¡´/ ¡´/ ¡´/ ¡´/[m [33m¢k[m + [1;31m¢ª\ ¢ª\ ¢ª\ ¢«[m + [42m [m + diff --git a/sample/etc/chickens/d13 b/sample/etc/chickens/d13 new file mode 100644 index 00000000..48cef654 --- /dev/null +++ b/sample/etc/chickens/d13 @@ -0,0 +1,13 @@ + [1;5;33m¤pÅ]¬P¡H¡H[m + [1;31m¡´ ¡´ ¡´[m + [1;31m¡´[m [1;5;32m¡¯[m [1;31m¡´[m + [1;31m¡´[m [1;33m¡¯[m [1;31m¡´ ¡´¡´[m[1;36m\\[m + [1;31m¡´[m [1;35m¡¯[m [1;31m¡´¡´[m [1;33m¡_[m[1;31m¡´[m + [1;31m¡´[m [1;5;34m¡¯[m [1;32m¡ä[m [1;31m¡´[m + [1;31m¡´[m [1;36m¡´[m¡¯ [1;36m¡´ ¡¯¡´¡´[m[1;31m¡´[m [1;35m¢©[m + [1;36m¡´ ¡´/[m |[1;36m¡´[m[1;31m¢¬[m [1;36m¡´\[m [1;31m¡´ ¡´¡´[m[1;34m¡l[m + [1;36m¡´/[m[1;31m¡X[m[1;36m¡´/[m[1;31m¡X[m[1;36m¡´\ ¡´\[m + [36m¡´\ ¡´\ ¡´\ ¡´\[m + [1;35m¢« ¢ª ¢ª ¢ª[m [1;32m\|/ \|/[m + [42m [m + diff --git a/sample/etc/chickens/d14 b/sample/etc/chickens/d14 new file mode 100644 index 00000000..02f91a47 --- /dev/null +++ b/sample/etc/chickens/d14 @@ -0,0 +1,13 @@ + [1;5;34m¡_[m [1;33m¡_[m + [1;5;35m°«¡I¡I[m ¢¢¬ [1;5;34m/ |[m[1;33m¢¬ |[m ¡[ + [1;31m¡´ ¡´ ¡´[m [1;36m¡·¡·[m[1;5;34m/[m [1;33m¢¬ /[m ¡[ + [1;31m¡´[m [33m¡¯[m [1;31m¡´[m [1;33m¡¿[m[1;35m¡´[m[1;33m¢¬ ¡þ/[m + [1;31m¡´[m[1;5;32m¡¯ ¡¯ ¡¯ ¡¯[m [1;31m¡´ ¡´¡´[m[1;36m\\[m [1;31m/ /[m ¡n[1;33m_¢¬ ¢¬[m + [1;31m¡´[m [33m¡¯ ¡¯[m [1;31m¡´¡´[m [1;36m¡_[m[1;31m¡´[m [1;31m/ /[m¡³ [1;33m_¢¬[m + [1;31m¡´[m [1;5;35m¡¯ ¡¯ ¡¯ ¡¯[m [1;32m¡´[m [1;31m¡´[m [1;31m/¡þ[m [33m¡´[m ¡\ + [1;31m¡´[m[1;36m¡¯¡´ ¡¯¡´ ¡´¡´[m [1;35m¢©[m [1;33m¡´ ¡´[m + [36m¡´ ¡´/ /¡´ ¡´\[m [1;31m¢¡´[m[1;34m¡p[m¡l [1;33m¡´¡´[m + [36m¡´/[m[1;31m¡X[m[36m¡´/[m[1;31m¡X[m[36m\¡´[m¡Æ [1;36m¡´\[m [1;32m¢¬[m + [1;36m\¡´ \¡´ \¡´ \¡´[m [1;5;35m¡¸[m + [1;35m¢ª ¢ª ¢ª ¢ª[m + diff --git a/sample/etc/chickens/d15 b/sample/etc/chickens/d15 new file mode 100644 index 00000000..2c305cb5 --- /dev/null +++ b/sample/etc/chickens/d15 @@ -0,0 +1,11 @@ + [1;31m¡´ ¡´ ¡´¡´\\[m + [1;31m¡´[m [1;32m¡¯[m [1;31m¡´¡´[m [1;33m¡o[m[1;31m¡´[m + [1;31m¡´[m [1;35m¡¯[m [1;32m¡¿[m [1;31m¡´[m + [1;31m¡´ ¡¯[m [1;36m¡´|[m [1;31m¡´[m [1;35m¢©[m + [1;31m¡´[m [1;32m¡¯[m [1;36m¡´|[m[1;31m¢¬ ¡´¡´[m[1;34m¡l[m/ + [1;31m¡´[m [1;36m¡´¡¯ ¡´ ¡´[m [1;31m//[m[1;36m¡´\[m [1;34m_______[m [1;33m¢@¡þ[m + [1;36m¡´/ ¡´/ ¡´/[m[1;31m_¡þ[m [1;36m¡´\[m [1;33m< ¡È/¡È/¢\[m[1;36m¡Ö¡Õ[m + [1;36m¡´/[m[1;31m--[m[1;36m¡´/[m[1;31m--[m[1;36m¡´\[m [1;35m¢ª[m[1;33m¡´[m[1;34m\_\_ ¢¬[m[33m¡³¡´[m[1;33m¡¿/[m + [36m¡´\ ¡´\ ¡´\[m [1;33m¡´¡´¡´[m[1;31m£[ £[ £[[m + [1;35m¢ª ¢ª ¢ª[m [1;32m¢¬[m + diff --git a/sample/etc/chickens/d16 b/sample/etc/chickens/d16 new file mode 100644 index 00000000..2c305cb5 --- /dev/null +++ b/sample/etc/chickens/d16 @@ -0,0 +1,11 @@ + [1;31m¡´ ¡´ ¡´¡´\\[m + [1;31m¡´[m [1;32m¡¯[m [1;31m¡´¡´[m [1;33m¡o[m[1;31m¡´[m + [1;31m¡´[m [1;35m¡¯[m [1;32m¡¿[m [1;31m¡´[m + [1;31m¡´ ¡¯[m [1;36m¡´|[m [1;31m¡´[m [1;35m¢©[m + [1;31m¡´[m [1;32m¡¯[m [1;36m¡´|[m[1;31m¢¬ ¡´¡´[m[1;34m¡l[m/ + [1;31m¡´[m [1;36m¡´¡¯ ¡´ ¡´[m [1;31m//[m[1;36m¡´\[m [1;34m_______[m [1;33m¢@¡þ[m + [1;36m¡´/ ¡´/ ¡´/[m[1;31m_¡þ[m [1;36m¡´\[m [1;33m< ¡È/¡È/¢\[m[1;36m¡Ö¡Õ[m + [1;36m¡´/[m[1;31m--[m[1;36m¡´/[m[1;31m--[m[1;36m¡´\[m [1;35m¢ª[m[1;33m¡´[m[1;34m\_\_ ¢¬[m[33m¡³¡´[m[1;33m¡¿/[m + [36m¡´\ ¡´\ ¡´\[m [1;33m¡´¡´¡´[m[1;31m£[ £[ £[[m + [1;35m¢ª ¢ª ¢ª[m [1;32m¢¬[m + diff --git a/sample/etc/chickens/d2 b/sample/etc/chickens/d2 new file mode 100644 index 00000000..b256f5e5 --- /dev/null +++ b/sample/etc/chickens/d2 @@ -0,0 +1,11 @@ + [31m¢g¢g¢g¢g¢g¢g¢g[m + . + . + . + . + [1;31m¡Ö[m[1;35m¡´¡´[m[1;31m¡ç[m \[1;31m¡¹[m/ \[1;36m¡¹[m/ + [1;31m¡X[m¡´¡´[1;31m¡Ð[m [1;5;33m³á¡H[m [32m¢¨¢k ¢¨¢k[m + [1;31m/[m [1;32mOO[m [1;31m\[m [32m¢© ¢©[m + [1;32m\|/[m [32m¢k[m[1;32m\|/[m [32m¢k[m [1;32m\|/[m + [42m [m + diff --git a/sample/etc/chickens/d3 b/sample/etc/chickens/d3 new file mode 100644 index 00000000..c0dacb46 --- /dev/null +++ b/sample/etc/chickens/d3 @@ -0,0 +1,16 @@ + [31m¢g¢g¢g¢g¢g¢g¢g¢g[m + . + . + . + . [1;31m¼K¼K¡I[m[1;5;33mdinner¡H[m + [1;31m¡Ö[m[1;35m¡´¡´[m[1;31m¡Õ[m + [1;31m¡X[m¡´¡´[1;31m¡X[m + [1;31m/[m[1;32m¡ó¡ó[m[1;31m\[m + [1;36m\/[m [1;5;33m¡H¡H[m + + [1;32m>[m[1;31m¡ò[m¡\¡\ [1;32m\|/ \|/[m + [42m [m + + + + diff --git a/sample/etc/chickens/d4 b/sample/etc/chickens/d4 new file mode 100644 index 00000000..a11683f0 --- /dev/null +++ b/sample/etc/chickens/d4 @@ -0,0 +1,12 @@ + [31m¢g¢g¢g¢g¢g¢g¢g¢g[m + . + . + . + . [1;31m¼K¼K¡I[m[1;5;33mBIG DINNER¡I¡I[m + [1;31m¡X[m[1;33m¡´¡´[m[1;31m¡X[m + [1;31m¡Ö[m [1;34m¡´[m [1;31m¡Õ[m + [1;31m¡þ[m[1;32m¡ä¡ä[m[1;31m¢@[m [1;5;36m¡H¡H¡H[m + [1;36m¡]¡^[m + [1;32m>[m[1;35m¡´O¡´[m ¡\¡\ + [42m ^ ^ ^ [m + diff --git a/sample/etc/chickens/d5 b/sample/etc/chickens/d5 new file mode 100644 index 00000000..30ca6a2c --- /dev/null +++ b/sample/etc/chickens/d5 @@ -0,0 +1,14 @@ + [31m¢g¢g¢g¢g¢g¢g¢g¢g[m + . + . + . + [1;31m\[m . [1;31m/[m [1;5;32m¡¸[m + [1;31m¢[m[1;33m¢¨¢©[m[1;31m¢¬[m [1;5;35m¡¹[m + [1;31m\¡X[m[1;34m¢i¢i[m[1;31m¡X/[m + [1;5;32m¡¸[m [1;31m/¡X[m[1;33m¢i¢i[m[1;31m¡X\[m [1;36m˦Q¤Ó¤[[m[1;32m·|¤£·|[m[1;5;35m¸£¥R¦å[m[1;36m°Ú¡H¡H[m + [1;31m¢¬[m[1;32m¡¯¡¯[m[1;31m¢[m + [1;31m/[m [1;36m¡]¡^[m [1;31m\[m [1;5;34m¡¸[m + [1;5;31m¡¹[m + + + diff --git a/sample/etc/chickens/d6 b/sample/etc/chickens/d6 new file mode 100644 index 00000000..7e30c6b6 --- /dev/null +++ b/sample/etc/chickens/d6 @@ -0,0 +1,12 @@ + + [32m¡´¡´[m [1;5;35m¥i©È¶Ü¡H¡H[m + [1;31m\[m [32m¡´[m[41m [m[32m¡´[m [1;31m/[m + [1;31m¢¡Ä[m[32m¡´ ¡´[m[1;31m¡Ä¢¬[m [1;5;36m§Ö°{¡I¡I¡I[m + [1;31m¡Ä[m[1;32m¡´ ¡´[m[1;31m¡Ä[m + [1;31m\¢¬ ¡Ä[m[1;32m¡´ ¡´[m[1;31m¡Ä ¢/[m [1;33m¡·[m[1;31m¡´[m¡þ + [1;31m¢¬[m [32m¡´ ¡´[m [1;31m¢[m . . [1;31m¡´[m[1;33m¡·[m¢@ + [1;31m¢¬[m¡Â[32m¡´[m[1;36m¡_¡_[m[32m¡´[m¡Â[1;31m¢[m . . + [1;31m/[m [1;33m¢ª[m[1;32m¡·¡·[m[1;33m¢«[m [1;31m\[m . . + [1;35m¡][m [1;35m¡^[m . . + . . . + diff --git a/sample/etc/chickens/d7 b/sample/etc/chickens/d7 new file mode 100644 index 00000000..535e5503 --- /dev/null +++ b/sample/etc/chickens/d7 @@ -0,0 +1,16 @@ + . + . [1;5;35m³´¨À¡H¡H¡H[m + [32m¡´¡´[m + [1;31m\[m [32m¡´[m[41m [m[32m¡´[m [1;31m/[m + [1;31m¢¡Ä[m[32m¡´ ¡´[m[1;31m¡Ä¢¬[m [32m¢d¢d¢¨¢d¢d¢d¢¨¢d[m + [1;31m¡Ä[m[1;32m¡´ ¡´[m[1;31m¡Ä[m ¢æ¢æ¢æ¢æ¢æ[32m¢ª[m¢æ¢æ¢æ¢æ + [1;31m\¢¬ ¡Ä[m[32m¡´ ¡´[m[1;31m¡Ä ¢/[m¢æ¢æ¢æ¢æ¢æ [1;33m\/[m ¢æ¢æ [1;5;36mhelp¡\[m + [1;31m¢¬[m [32m¡´ ¡´[m [1;31m¢[m ¢æ¢æ¢æ¢æ [1;32m¡·[m[1;35m¡´[m¡[¢æ¢æ[32m¢k[m + [1;31m¢¬[m¡Â[32m¡´[m[1;36m¡_¡_[m[1;32m¡´[m¡Â[1;31m¢[m [32m¢ª[m¢æ¢æ [1;35m¡´[m[1;32m¡·[m ¢æ¢æ[32m¢«[m + [1;31m/[m [1;33m¢ª[m[1;32m¡ä¡ä[m[1;33m¢«[m [1;31m\[m [32m¢ª[m¢æ¢æ¡Ë ¢æ¢æ [32m¢k[m + [1;35m¡] ¡^[m [32m¢ª[m¢æ¢æ¢æ¢æ¢æ[32m¢ª[m + [32m¢ª[m¢æ¢æ¢æ [32m¢k[m[1;32m¢¡ý/ \|¢¬[m + + + + diff --git a/sample/etc/chickens/d8 b/sample/etc/chickens/d8 new file mode 100644 index 00000000..ed46f5e9 --- /dev/null +++ b/sample/etc/chickens/d8 @@ -0,0 +1,14 @@ + + [1;5;31m/[m[1;5;32m/[m[1;5;33m¢¬[m [1;35m¬y¬P¡I¡I[m + [1;5;36m¡¸[m + [32m¡´ ¡´[m + [32m¡´[m[41m [m[32m¡´ ¡´¡´[m[1;33m\\[m + [32m¡´ ¡´[m [1;32m¡ä[m [1;35m³\ÓÄ@§a¡I[m + [32m¡´ ¡´[m [1;31m¢©[m [1;5;33m§Ö§Öªø¤j¡I¡I[m + [1;31m¢f[m¡´[1;31m¢f[m¡´[1;31m¢f[m ¡´[1;31m¢d[m[1;34m¡p[m + [1;31m// // // \\[m + [1;31m\| \| \| |/[m [1;32m\|/ \|¢¬ \|¡þ[m + [43m [m + + + diff --git a/sample/etc/chickens/d9 b/sample/etc/chickens/d9 new file mode 100644 index 00000000..409ae520 --- /dev/null +++ b/sample/etc/chickens/d9 @@ -0,0 +1,13 @@ + + [1;5;31m/[m[1;5;32m/[m[1;5;33m ¢¬[m + [32m¡´¡´ ¡´[m [1;5;31m/[m[1;5;32m/[m[1;5;33m¢¬[m [1;35m¹k¥Û¡H¡H[m + [32m¡´[m [1;31m£Y[m [32m¡´[m [1;5;35m¡¹[m + [1;32m¡´[m [1;33m£Y[m [1;32m¡´[m [32m¡´¡´[m[1;36m\\[m + [32m¡´[m [1;35m£Y[m [32m¡´[m [1;32m¡Ö[m + [32m¡´[m [1;31m¡´ ¡´ ¡´[m [1;35m¢©[m [1;33m³\Ä@ªº¥N»ù¡H[m + [1;31m¡´/[m[32m¢f[m[1;31m¡´[m[32m¢f[m[1;31m¡´/[m[32m¢f[m[1;31m¡´[m [1;34m¡l¡p[m + [1;31m¡´\ ¡´\ ¡´\ ¡´\[m + [1;31m¢ª ¢ª ¢ª ¢ª[m [1;32m\|¡þ \|/ \|/[m + [43m [m + + diff --git a/sample/etc/chickens/deadth b/sample/etc/chickens/deadth new file mode 100644 index 00000000..ff9b3687 --- /dev/null +++ b/sample/etc/chickens/deadth @@ -0,0 +1,15 @@ + + + + [34m[1m¢~¢¡¡\¡\{{[0m + [34m¢ª¢i¢i¢i¢«[0m + [42m[30m@`[5m@[0m[42m[30m`¡©[0m + [42m[30m "_ [0m + [33m[1m¢e[0m[42m[1m[33m¢e[0m + [5m[32mÆТi[34m¢i¢i[44m [0m + [44m[5m[30m¢i [0m + [44m [0m + [44m [0m + [1m[33m ¢~¢} ¢x[0m [35m + [1m[33m¢|¢w-¢}[0m + ¶ã ¦ºÂ¼Â¼¤F ¤U¦¸¦A¨Ó§a~~~~ diff --git a/sample/etc/chickens/e0 b/sample/etc/chickens/e0 new file mode 100644 index 00000000..b66f2972 --- /dev/null +++ b/sample/etc/chickens/e0 @@ -0,0 +1,6 @@ + + + [32m¡´[1m¡´ + ¡´¡´[0m[32m¡´ + ¡´¡´[0m + diff --git a/sample/etc/chickens/e1 b/sample/etc/chickens/e1 new file mode 100644 index 00000000..b66f2972 --- /dev/null +++ b/sample/etc/chickens/e1 @@ -0,0 +1,6 @@ + + + [32m¡´[1m¡´ + ¡´¡´[0m[32m¡´ + ¡´¡´[0m + diff --git a/sample/etc/chickens/e10 b/sample/etc/chickens/e10 new file mode 100644 index 00000000..72d37fd8 --- /dev/null +++ b/sample/etc/chickens/e10 @@ -0,0 +1,12 @@ + + [1;32m¢©¢©¢¨¢¨ + ¢©¢©¢©¢©¢©¢¨[0m + [32m¡´¡´¡´¡´¡´¡´¡´¡´[0m + [1;31mùü[0m [32m¡´¡´¡´[1;33m¢®[0m[32m¡´¡´[1;33m¢®[0m[32m¡´¡´¡´[1;31m ùý + ùüùùùù [0m[32m ¡´¡´[1;37;41m¡¿¡¿¡¿¡¿¡¿¡¿¡¿[0m[32m¡´¡´[1;31m ùùùùùý + ùúùù[0m[32m ¡´¡´[41m [0m[32m¡´¡´[1;31m ùùùûû [32m ¢« + [0m[32m¡´¡´[1;37;41m¡¶¡¶¡¶¡¶¡¶[0m[32m¡´¡´[1;31m ùû[37m[0m[32m¡´[1;32m¢«¢«¢«[0m + [32m¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ [1m¢«[0m[32m¡´¡´ [1m¢«[0m + [32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ [1m¢«¢«[0m + [32m¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢«¢«[0m[32m¡´[0m « + [32m ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[0m diff --git a/sample/etc/chickens/e11 b/sample/etc/chickens/e11 new file mode 100644 index 00000000..1579e557 --- /dev/null +++ b/sample/etc/chickens/e11 @@ -0,0 +1,14 @@ + + [1;32m¢¨¢¨¢¨ + ¢¨¢¨¢¨¢¨¢¨¢¨ + [31mùúùû [0m[32m¡´¡´¡´¡´¡´¡´[1m¢¨¢¨¢¨ [37m ¢¨ + [31mùüùùùù [0m[32m¡´¡´[1;33m¢¨¢©[0m[32m¡´¡´¡´[1m¢¨¢¨ [1;37m¡·¡· + [31mùú [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨[37m¡·¡·¡· + [31mùúùû ùüùùùù [37;41m¡¿¡¿¡¿¡¿¡¿¡¿[0m[32m¡´¡´[1m¢¨[37m¡·¡·¡·¡· + [31mùü ùüùù [41m [0m[32m¡´¡´¡´[1;37m¡·¡· + [31mùúùùùùùù [0m[32m¡´ [1;37;41m¡¶¡¶¡¶¡¶¡¶¡¶[0m[32m¡´¡´¡´[1m¢¨¢¨¢¨ + [31mùü [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ ¢¨ + [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ ¢¨¢¨ + [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢©¢©¢¨¢¨¢¨ + [0m[32m¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢©¢¨[0m + diff --git a/sample/etc/chickens/e12 b/sample/etc/chickens/e12 new file mode 100644 index 00000000..0a05bc8a --- /dev/null +++ b/sample/etc/chickens/e12 @@ -0,0 +1,15 @@ + + [1;31m ¡· ¡· [32m ¢©¢© [31m ¡· + [32m ¢©¢©¢©¢© + [37m¢©[32m ¢©¢©[0m[32m¡´¡´¡´¡´¡´ [1;31m ¡·[33m ¢¨¢¨ + [37m¡·¡· [32m ¢©[0m[32m¡´¡´¡´¡´¡´¡´ [1;33m¢¨¢¨¢¨¢¨ + [37m¡·¡·¡·[32m¢©¢©[0m[32m¡´¡´¡´¡´[1;33mùúùû[0m[32m¡´ [1;35m¡´¡´¡´¡´[33m¢¨ + [37m¡·¡·¡·¡·[32m¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´[1;31m ¡· [35m¡´[33mùúùû[35m¡´¡´[33m¢¨¢¨ [37m ¢¨ + [31m ¡· [37m ¡·¡·[32m¢©¢©[0m[32m¡´¡´¡´¡´¡´[1;37m¢ª¢ª¢ª¢ª [1;35m¡´¡´¡´¡´¡´¡´[33m¢¨ [37m ¡·¡· + ¡·[32m¢©¢©¢©[0m[32m¡´¡´¡´¡´¡´ [1;37m¢«¢«[35m¡´¡´¡´¡´[33m¢¨¢¨[37m¡·¡· [31m ¡· + [32m¢©¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´ [1;35m¡´¡´¡´¡´[33m¢¨¢¨[37m¡· + [32m¢© ¢©¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´[1;37m¢¨ ¢©[35m¡´¡´¡´¡´¡´¡´[33m¢¨¢¨ + [32m¢©¢© ¢¨¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ [1;35m¡´¡´¡´¡´¡´¡´¡´¡´[33m¢¨¢¨ ¢¨ + [32m¢©¢©¢¨¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ [1;35m¡´¡´¡´¡´¡´¡´¡´¡´[1;35m¢©¢©¢¨¢¨[0m + + diff --git a/sample/etc/chickens/e13 b/sample/etc/chickens/e13 new file mode 100644 index 00000000..7fcee5e0 --- /dev/null +++ b/sample/etc/chickens/e13 @@ -0,0 +1,14 @@ + + [1;32m¢¨¢¨¢¨ [37m ¢¨ + [32m¢¨¢¨¢¨¢¨¢¨¢¨ [37m ¡·¡·¡· + [31m ùúùû [0m[32m¡´¡´¡´¡´¡´¡´[1m¢¨¢¨¢¨ [37m¡·¡·¡·¡· + [31mùüùùùù [0m[32m ¡´¡´[1;33m¢®[0m[32m¡´¡´¡´¡´[1m¢¨¢¨ [37m ¡·¡·¡·¡·¡· + [31mùú [0m[32m ¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨[37m¡·¡·¡·¡·¡· + [31m ùúùû ùú ùüùùùù [37;41m¡¿¡¿¡¿¡¿¡¿¡¿[0m[32m¡´¡´[1m¢¨[37m¡·¡·¡·¡·¡·¡· + [31mùü ùüùù [31;41m¡´¡´¡´ [0m[32m¡´¡´¡´[1;37m¡·¡·¡·¡·¡· + [31mùúùùùùùù [0m[32m¡´ [1;31;41m ¡´¡´ [0m[32m¡´¡´¡´[1m¢¨¢¨[37m¡·¡· + [31mùü [0m[32m¡´¡´¡´ [1;37;41m¡¶¡¶¡¶¡¶¡¶¡¶¡¶[0m[32m¡´¡´¡´[1m¢¨¢¨ + [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ ¢¨¢¨ + [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢©¢©¢¨¢¨¢¨ + [0m[32m¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢©¢¨[0m + diff --git a/sample/etc/chickens/e14 b/sample/etc/chickens/e14 new file mode 100644 index 00000000..5685534b --- /dev/null +++ b/sample/etc/chickens/e14 @@ -0,0 +1,13 @@ + + [1;32m¢¨¢¨¢¨ [37m¢¨ + [32m ¢¨¢¨¢¨¢¨¢¨ [37m ¡·¡· + [0m[32m¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ [37m ¡·¡·¡· + [0m[32m¡´¡´¡´¡´¡´¡´¡´[1m¢¨ ¡ [37m¡·¡·¡·¡· + [0m[32m¡´[1;33mùúùû[0m[32m¡´¡´¡´¡´¡´[1m¢¨¢¨ [37m ¡·¡·¡·¡·¡· + [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨[37m ¡·¡·¡·¡·¡· + ¢«¢«¢«¢«¢«¢«[0m[32m¡´¡´¡´¡´[1m¢¨¢¨[37m¡·¡·¡·¡· + [31m¡´¡´¡´ [0m[32m ¡´¡´¡´¡´[1m¢¨¢¨[37m¡·¡·¡· + [0m[32m ¡´[1m¡´ [0m[32m¡´ [1;31m¡´¡´ [0m[32m ¡´¡´¡´¡´[1m¢¨¢¨[37m¡·¡· + [32m¡´¡´[0m[32m¡´ ¡´[1m¡´ [0m[32m¡´ [1;37m¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨¢¨ ¢¨ + [0m[32m¡´¡´ [1m¡´¡´[0m[32m¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢© ¢¨¢¨ + [0m[32m¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢¨¢¨¢¨[0m diff --git a/sample/etc/chickens/e15 b/sample/etc/chickens/e15 new file mode 100644 index 00000000..b1c406be --- /dev/null +++ b/sample/etc/chickens/e15 @@ -0,0 +1,13 @@ + + [1;37m¢© [32m¢©¢©¢© [31mùúùû + [37m ¡·¡· [32m ¢©¢©¢©¢©¢© [31m ùüùø ùúùû + [37m ¡·¡·¡·¡· [32m ¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´ [1;31m ùø ùùùùùý + [37m ¡·¡·¡·¡·¡· [32m ¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´ [1;31mùúùû + [37m ¡·¡·¡·¡·¡·[32m ¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´[1;33m¢®[0m[32m¡´¡´ [1;31m ùùùùùùùý û + [37m¡·¡·¡·¡· [32m ¢©[0m[32m¡´¡´¡´¡´[1;37;41m¢ª¢ª¢ª¢ª¢ª¢ª[0m[1;31m ¡´ ùû ùúùû + · [37m ¡·¡· [32m¢©¢©[0m[32m¡´¡´¡´¡´¡´[1;31;41m¡ ¡´¡´¡´¡´[0m[1;31m¡´ ùùùý ùý + [37m¡·¡·[32m¢©¢©¢©[0m[32m¡´¡´¡´¡´[1;31;41m ¡´¡´ [0m[1;31m ùùùùùùùùùùùû + [32m ¢© [37m ¡·[32m¢©¢©¢©[0m[32m¡´¡´¡´¡´¡´[1;37;41m¢¨¢¨¢¨¢¨¢¨[0m [32m ¡´ [1;31m ùüùý + [32m¢©¢© ¢©¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ [1;31m ùø ùùùû + [32m¢©¢© ¢¨¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1;31m ùúùø ùüùý + [32m ¢©¢©¢¨¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1;31m ùüùý[0m diff --git a/sample/etc/chickens/e16 b/sample/etc/chickens/e16 new file mode 100644 index 00000000..c607a360 --- /dev/null +++ b/sample/etc/chickens/e16 @@ -0,0 +1,14 @@ + + [1;32m¢¨¢¨¢¨ ¢¨ + [32m ¢¨¢¨¢¨¢¨¢¨[0m[32m ¡´¡´[1m¢¨ [1;37m ¢¨ + [0m[32m¡´¡´¡´¡´¡´¡´[1m¢¨¢¨[0m[32m¡´[1;33m¡o[0m[32m¡´[1m¢¨[1;37m ¡·¡· + [0m[32m¡´¡´¡´¡´¡´¡´¡´[1m¢¨ [0m[32m¡´¡´[1m¢¨ [37m ¡·¡·¡· + [0m[32m¡´[1;33mùúùû[0m[32m¡´¡´¡´¡´¡´[1m¢¨¢¨ [0m[32m¡´[1m¢© [37m ¡·¡·¡·¡· + [0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ [0m[32m¡´[1m¢¨ [37m¡·¡·¡·¡· + [32m ¢© [37m¢«[30m¢«[1;37m¢«[0m[32m¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ [37m ¡·¡·¡· + [32m ¢©[0m[32m¡´¡´ [33m¡´ [0m[32m¡´¡´¡´¡´¡´¡´[1m¢¨¢¨ [37m ¡·¡·¡·¡· + [32m ¢©[0m[32m¡´[1;33m¡´[0m[32m¡´ [1m¢© [0m[33m¡´ [0m[32m¡´¡´¡´¡´¡´¡´[1m¢¨¢¨[37m¡·¡·¡· +[32m¢¨¢¨[0m[32m¡´¡´¡´¡´ [1m¢©[0m[32m¡´¡´´ ¡´ [33m¡´ [1;37m¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢¨¢¨¢¨ + [1;32m¢©[0m[32m¡´[1;33m¡o[0m[32m¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢© ¢¨ + ¢¨¢¨[0m[32m¡´¡´¡´¡´ [33m¡´[32m ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢¨¢¨[0m + diff --git a/sample/etc/chickens/e2 b/sample/etc/chickens/e2 new file mode 100644 index 00000000..d975147c --- /dev/null +++ b/sample/etc/chickens/e2 @@ -0,0 +1,6 @@ + + + [32m¡´¡´[1m¢¨[0m + [32m¡´[1;33m¡´[0m[32m¡´[1m¢¨[0m + [32m¡´¡´¡´¡´[1m¢©¢©[0m + diff --git a/sample/etc/chickens/e3 b/sample/etc/chickens/e3 new file mode 100644 index 00000000..244f71d2 --- /dev/null +++ b/sample/etc/chickens/e3 @@ -0,0 +1,6 @@ + [1;32m¢¨¢¨[0m + [32m¡´¡´¡´[1m¢¨[0m + [32m¡´[1;33m¡o¡o[0m[32m¡´[1m¢¨[0m + [32m¡´¡´¡´¡´[1m¢¨¢¨[0m + [32m¡´¡´¡´¡´¡´[1m¢©¢©¢¨[0m + diff --git a/sample/etc/chickens/e4 b/sample/etc/chickens/e4 new file mode 100644 index 00000000..d6b05b44 --- /dev/null +++ b/sample/etc/chickens/e4 @@ -0,0 +1,8 @@ + + [1;32m¢¨¢¨¢¨[0m + [32m¡´¡´¡´¡´[1m¢¨[0m + [32m¡´[1;33m¡´[0m[32m¡´[1;33m¡´[0m[32m¡´[1m¢¨[0m + [32m¡´¡´[1;37m¡¿¡¿[0m[32m¡´[1m¢¨¢¨[0m + [32m¡´¡´[1;37m¡¶[0m[32m¡´¡´¡´[1m¢¨¢¨ ¢¨[0m + [32m¡´¡´¡´¡´¡´¡´¡´[1m¢©¢©¢¨[0m + diff --git a/sample/etc/chickens/e5 b/sample/etc/chickens/e5 new file mode 100644 index 00000000..a78b2df8 --- /dev/null +++ b/sample/etc/chickens/e5 @@ -0,0 +1,9 @@ + + [1;32m¢¨¢¨¢¨[0m + [32m¡´¡´¡´¡´[1m¢¨[0m + [32m¡´[1;33m¢©[0m[32m¡´[1;33m¢¨[0m[32m¡´[1m¢¨¢¨[0m + [32m¡´¡´¡´¡´¡´¡´[1m¢¨[0m + [32m¡´¡´[1;37m¡¿¡¿¡¿[0m[32m¡´¡´[1m¢¨¢¨[0m + [32m¡´¡´[1;37m¡¶¡¶[0m[32m¡´¡´¡´¡´[1m¢¨¢¨ ¢¨[0m + [32m¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢©¢¨¢¨¢¨[0m + diff --git a/sample/etc/chickens/e6 b/sample/etc/chickens/e6 new file mode 100644 index 00000000..66af6938 --- /dev/null +++ b/sample/etc/chickens/e6 @@ -0,0 +1,9 @@ + + [1;32m ¢¨¢¨¢¨¢¨[0m + [32m¡´¡´¡´¡´[1m¢¨¢¨[0m + [32m¡´[1;33m¡o[0m[32m¡´[1;33m¡o[0m[32m¡´¡´[1m¢¨¢¨[0m + [32m¡´¡´¡´¡´¡´¡´¡´[1m¢¨[0m + [32m¡´[1;37m¡¿¡¿¡¿¡¿[0m[32m¡´¡´[1m¢¨¢¨¢¨[0m + [32m¡´¡´[1;37m¡¶¡¶[0m[32m¡´¡´¡´¡´[1m¢¨ ¢¨[0m + [32m¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢© ¢¨¢¨[0m + [32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[1m¢©¢¨¢¨[0m diff --git a/sample/etc/chickens/e7 b/sample/etc/chickens/e7 new file mode 100644 index 00000000..fc0b8270 --- /dev/null +++ b/sample/etc/chickens/e7 @@ -0,0 +1,11 @@ + + [1;32m¢©¢©¢©¢© + ¢©¢©[0m[32m¡´¡´¡´¡´¡´ [1;31m ùúùû + [32m¢©¢©[0m[32m¡´¡´¡´¡´[1;33mùúùû[0m[32m¡´ [1;31mùüùý ùúùû + [32m¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´ [1;31m ùúùû ùüùý + [32m¢©¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´[1;37m¢ª¢ª [31m ùùùùùý ¡· + [32m¢©¢©[0m[32m¡´¡´¡´¡´¡´ [1;31m ùùùùùùùùùû ¡· + [32m¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´[1;37m¢¨[31m ùùùû ùüùý + [32m¢© ¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[1;31m ùüùý ¡· + [32m¢©¢©¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[0m + diff --git a/sample/etc/chickens/e8 b/sample/etc/chickens/e8 new file mode 100644 index 00000000..6841430c --- /dev/null +++ b/sample/etc/chickens/e8 @@ -0,0 +1,11 @@ + + [1;32m¢©¢© + ¢©¢©¢©¢© + ¢©¢©[0m[32m¡´¡´¡´¡´¡´ + [1m¢©[0m[32m¡´[1;33m¢©[0m[32m¡´¡´[1;33m¢¨[0m[32m¡´ + [1m¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´ + [1m¢©¢©[0m[32m¡´[1;37m¡¿¡¿¡¿¡¿¡¿[0m[32m¡´ + [1m¢©¢©¢©[0m[32m¡´¡´[1;37m¡¶¡¶¡¶¡¶[0m[32m¡´ + [1m¢© ¢©¢©[0m[32m¡´¡´[1mùÝùá[0m[32m¡´¡´[1mùÝùá + ¢©¢©¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´ + [1m¢©¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´[0m´ diff --git a/sample/etc/chickens/e9 b/sample/etc/chickens/e9 new file mode 100644 index 00000000..1c475487 --- /dev/null +++ b/sample/etc/chickens/e9 @@ -0,0 +1,12 @@ + + [1;32m¢©¢© + ¢©¢©¢©¢©¢© + ¢©[0m[32m¡´¡´¡´¡´¡´ + [1m¢©[0m[32m¡´¡´¡´[1;33m¢ª¢«[0m[32m¡´¡´ + [1m¢©¢©[0m[32m¡´¡´[1;37;41m¡¿¡¿¡¿¢ª¢ª¢ª[0m [1;31mùùùý + [1;32m¢©¢©[0m[32m¡´¡´[41m [0m[1;31mùùùýùû + [1;32m¢© ¢©¢©[0m[32m¡´¡´¡´¡´[1;37;41m¡¶¡¶¡¶¡¶¡¶¡¶[0m [1;31mùùùû + [1;32m¢© ¢©¢©[0m[32m¡´¡´¡´¡´¡´¡´¡´[1mùæùùùá + ¢©¢©¢©¢¨¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + [1m¢©¢©¢¨[0m[32m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[0m + diff --git a/sample/etc/chickens/eat b/sample/etc/chickens/eat new file mode 100644 index 00000000..03f3a578 --- /dev/null +++ b/sample/etc/chickens/eat @@ -0,0 +1,14 @@ + + + + +[1;33m _._ ¢A[m + [1;33m ¢¡ [31m ¢b [0;37m ¡[46m» [0;1;35m¢¡[31m ¡¿ [33m ¡@¢~[m + [1;37m ¡]¡^ [[43m¡Ý[0;1;35m [42m###[0;1;35m/ [37m ¢x ¡]¡^[m + [1;34m ¡ü [37m ¢y[47m ¢v ¢v [0;1;37m¢j[34m ¡ü[m +[33m ¢x [1;37m ¢y[45;35m¡o¡o¡o¡o¡o¡o¡o¡o¡o¡o[0;1;37m¢j¡@ [0;33m ¢x[m +[33m ¢¢ùùùçùù [1;34m ùò| [0;33m ¡@ ùùùçùù¢£[m +[1;33m ¡ü ¡Ý ¡@ ¡ü[m + [33m ¢~¢r¢¡ ¢~¢r¢¡ ¡@ ¢~¢r¢¡[m + [33m ¢v ¢v ¢v ¢v ¢v ¢v[m + ¦Y¶ºÅo~~~~~~~~ diff --git a/sample/etc/chickens/f0 b/sample/etc/chickens/f0 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/f0 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/f1 b/sample/etc/chickens/f1 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/f1 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/f10 b/sample/etc/chickens/f10 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/f10 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/f11 b/sample/etc/chickens/f11 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/f11 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/f12 b/sample/etc/chickens/f12 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/f12 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/f13 b/sample/etc/chickens/f13 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/f13 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/f14 b/sample/etc/chickens/f14 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/f14 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/f15 b/sample/etc/chickens/f15 new file mode 100644 index 00000000..df160353 --- /dev/null +++ b/sample/etc/chickens/f15 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/f16 b/sample/etc/chickens/f16 new file mode 100644 index 00000000..100d4260 --- /dev/null +++ b/sample/etc/chickens/f16 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/f2 b/sample/etc/chickens/f2 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/f2 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/f3 b/sample/etc/chickens/f3 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/f3 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/f4 b/sample/etc/chickens/f4 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/f4 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/f5 b/sample/etc/chickens/f5 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/f5 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/f6 b/sample/etc/chickens/f6 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/f6 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/f7 b/sample/etc/chickens/f7 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/f7 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/f8 b/sample/etc/chickens/f8 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/f8 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/f9 b/sample/etc/chickens/f9 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/f9 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/food b/sample/etc/chickens/food new file mode 100644 index 00000000..bb686d2f --- /dev/null +++ b/sample/etc/chickens/food @@ -0,0 +1,14 @@ + + [42m [m + [42m [31;47;1m ¢e¢e¢e [42m [m + [42m [31;47m [37;41m¢«[31;47m¢« [42m [0m + [42m [32;47;1m ELEVEN [42m [m + [42m [31;47m ¢i [42m [0m + [32;47m¢i¢d¢d¢d¢d¢i[0m + ////// + [1m ¡@ [47m [m + [m[1m (((((( [30m ¡´¡´[37m- > [1;44m¢Ûa¢ús¢ða¢ót[m +[1m [34m ¢e¢e¢e¡Å[37m ¢¢[31m¡¿[37m ¢£ [1;46m §®¤Ñ¤p¼p®v [m +[1m \¡Ð[30;47m¡D [m[1m>> + [30;47m¡G [m +[37;40m[0m ¨Ó¶R¹ª«°Õ.... diff --git a/sample/etc/chickens/g0 b/sample/etc/chickens/g0 new file mode 100644 index 00000000..1ed07519 --- /dev/null +++ b/sample/etc/chickens/g0 @@ -0,0 +1,5 @@ + + [1;33m¡´¡´ + ¡´[0m[33m¡´[1m¡´ + ¡´¡´[0m[33m¢£[0m£ + diff --git a/sample/etc/chickens/g1 b/sample/etc/chickens/g1 new file mode 100644 index 00000000..1ed07519 --- /dev/null +++ b/sample/etc/chickens/g1 @@ -0,0 +1,5 @@ + + [1;33m¡´¡´ + ¡´[0m[33m¡´[1m¡´ + ¡´¡´[0m[33m¢£[0m£ + diff --git a/sample/etc/chickens/g10 b/sample/etc/chickens/g10 new file mode 100644 index 00000000..cf4c0f14 --- /dev/null +++ b/sample/etc/chickens/g10 @@ -0,0 +1,13 @@ + + [34m¢© ¢¨ [33m ¢© ¢¨ [35m ¢© ¢¨ + [1;34m¡´¡´¡´¡´¡´ [33m ¡´¡´¡´¡´¡´ [35m ¡´¡´¡´¡´¡´ + [32m¡ó[31m¡¯[33m¡ò[37m¡¸ [1;34m¡´ ¡´ [33m ¡´ ¡´ [35m ¡´ ¡´ + [37m¡¸[31m¡¯[32m¡ó[31m¡¯¡¯ [1;34m¡´[36m ¢® ¢®[34m ¡´ [33m ¡´ [36m¡o ¡o [33m¡´ [35m ¡´ [36m¢Ç ¢Ç[35m ¡´ + [31m¡¯[33m¡ò[31m¡¯[32m¡ó[31m¡¯ [0m[34mùû[1m ¡´ ¡´ [33m ¡´ ¡´ [35m ¡´ ¡´ + [31m¡¯[33m¡ò[31m¡¯[37m¡¸ [0m[34mùø [1m ¡´ ¡´ [33m ¡´ ¡´ [35m ¡´ ¡´ + [36mùüùùùÞùùùýý [0m[34mùø[1m ¡´ ¡´ [33m ¡´ ¡´[0m[33m ùúùá[35mùû[1m¡´ ¡´ + [36m ùø ý [0m[34mùø[1m¡´ ¡´ [33m ¡´ ¡´[0m[33m ùø[35m ùø[1m¡´´ ¡´ + [36m ùø [0m[34mùü[1m¡´ ¡´ [33m ¡´ ¡´[0m[33mùý[35m ùü[1m¡´ ¡´ + [36m ùùùäùù [34m¡´¡´¡´¡´¡´¡´ [33m ¡´¡´¡´¡´¡´ [35m ¡´¡´¡´¡´[0m + + diff --git a/sample/etc/chickens/g11 b/sample/etc/chickens/g11 new file mode 100644 index 00000000..0c6390f8 --- /dev/null +++ b/sample/etc/chickens/g11 @@ -0,0 +1,15 @@ + + [33m ¢© ¢¨ + [1m¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ [37m + [33m ¡´ [36m ¡\ ¡\ [33m¡´ + ¡´ [37m¢¤[0m[31m ¡´[1;37m ¢¤ [33m¡´ + ¡´[31m ¡Ë [33m ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´[0m[33m ùúùûùúùûùúùûùúùû + [1m¡´ ¡´[0m[33mùýùüùýùüùýùüùýùü + [1m ¡´¡´¡´¡´¡´¡´¡´ [0m + + diff --git a/sample/etc/chickens/g12 b/sample/etc/chickens/g12 new file mode 100644 index 00000000..326c650d --- /dev/null +++ b/sample/etc/chickens/g12 @@ -0,0 +1,15 @@ + + [33m ¢© ¢¨ [1;35m ¡´¡´¡´¡´¡´¡´¡´ + [33m¡´¡´¡´¡´¡´¡´[35m¡´¡´¡´¡´¡´¡´¡´¡´ + [33m¡´ ¡´ [35m ¡´¡´¡´¡´¡´¡´¡´ + [33m¡´ [36m¢Ç ¢Ç[33m ¡´ [35m ¡´¡´¡´¡´¡´¡´ + [33m¡´ [37m¢¤[0m[31m ¡´[1;37m ¢¤[33m ¡´ [0m ¡´[1;35m ¡´¡´¡´¡´ + [33m¡´ [31m ¡ã [33m ¡´[0m ¡´ + [1;33m ¡´ ¡´ [0m ¡´ + [1;33m ¡´ ¡´ [0m ¡´[33mùúø + [1;35m¡´¡´¡´¡´¡´¡´¡´[0m¡´ [33mùø + [1;35m¡´¡´¡´¡´¡´¡´¡´¡´[0m[33mùúùý + [1m ¡´ [0m[33m ¢® [1m ¡´[0m[33mùý + [1m¡´¡´¡´¡´¡´¡´¡´[0m + + diff --git a/sample/etc/chickens/g13 b/sample/etc/chickens/g13 new file mode 100644 index 00000000..0b6e8b53 --- /dev/null +++ b/sample/etc/chickens/g13 @@ -0,0 +1,14 @@ + [34m¡´ ¡´ + [1m¡´¡´¡´¡´¡´¡´ [0m [33m ¢© ¢© + [1;34m ¡´ ¡´ [33m ¡´¡´¡´¡´¡´ + [34m¡´ [36m ¡o ¡o[34m ¡´[33m ¡´ ¡´ + [34m ¡´ [37m¡Ö[0m[31m¡´[1;37m¡Õ[34m ¡´ [33m ¡´[36m ¡o ¡o[33m ¡´ + [34m ¡´ ¡´ [33m ¡´[37m¡Ö[0m[31m¡´[1;37m¡Õ[33m¡´ + [32m ¡´¡´¡½¡´¡´ [35m ¡´¡´¡´¡´ + [0m[34mùúùû [1m¡´ [32m ¡½ [34m ¡´ [33m ¡´´ ¡´ + [0m[34m ùø[1m ¡´ [32m ¡½ [34m¡´ [33m ¡´ ¡´ [0m[33mùúùû + [34m ùø[1m¡´ [32m ¡¿ [34m ¡´ [33m ¡´ ¡´[0m[33mùø + [34m ùü[1m¡´ ¡´ [33m ¡´ ¡´[0m[33mùý + [1;34m ¡´¡´¡´¡´¡´¡´¡´ [33m ¡´¡´¡´¡´¡´¡´[0m´ + + diff --git a/sample/etc/chickens/g14 b/sample/etc/chickens/g14 new file mode 100644 index 00000000..12c177ea --- /dev/null +++ b/sample/etc/chickens/g14 @@ -0,0 +1,14 @@ + + [34m¡´ ¡´ + [1m¡´¡´¡´¡´¡´¡´ [0m[33m ¢© ¢¨ + [1;34m¡´ ¡´ [33m ¡´¡´¡´¡´¡´ + [34m¡´ [36m¡´ ¡´[34m ¡´[33m ¡´ ¡´ + [34m¡´ [37m¡Ö[0m[31m ¡´[1;37m ¡Õ[34m ¡´[0m[33m ¡´[34m¡´[1;33m¡´ [36m¢Ç ¢Ç[33m ¡´ +¡ [34m¡´ [31m¡ã [34m ¡´ [0m[34m¡´[33m¡´[1m ¡´[37m¢¤[0m[31m¡»[1;37m¢¤[33m¡´ + [0m[32m¢© ¢¨ [36m ¢¤¡´¡´¢¤ [0m[33m ¡´[34m¡´ [1;35m ¡´¡´¡´ + [32m ¡´¡´¡´¡´ [34m ¡´ ¡´ [0m[34m¡´[33m¡´[1m ¡´ý ¡´ + [32m¡´ ¡ ¡´ [34m ¡´ ¡´[0m[33m¡´[34m¡´[1;33m¡´ ¡´ [31m¢©¢¨ + [32m¡´ [36m¡ó¡ó[32m ¡´ [34m ¡´ ¡´[0m[34m¡´[1;33m¡´ ¡´[37m¡´[31m¢«¢ª´ + [32m¡´ ¡´ [34m ¡´ ¡´[0m[33m¡´[1m¡´ ¡´[36m ¡ó¡ó[37m¡´ + [0m[32mùü[1m¡´¡´¡´¡´¡´ [34m ¡´¡´¡´¡´¡´¡´¡´¡´ [33m ¡´¡´¡´¡´¡´¡´¡´[37m¡´¡´¡´[0mùý + diff --git a/sample/etc/chickens/g15 b/sample/etc/chickens/g15 new file mode 100644 index 00000000..05757960 --- /dev/null +++ b/sample/etc/chickens/g15 @@ -0,0 +1,14 @@ + + + [33m¡´ ¡´ + ¡´[1m¡´¡´¡´¡´[0m[33m¡´¡´ + [1m ¡´ ¡´¡´¡´¡´¡´ [37m Âù¤U¤Ú³£¶]¥X¨Ó¤F©O¡I + [33m¡´ [30m¡ ¡ [33m ¡´ + ¡´ [37m¢¤[0m[31m¡´[1;37m¢¤ [33m ¡´ + ¡´ [31m¡_ [33m ¡´ + ¡´ ¡´ + ¡´ [0m[33m ¡p [1m ¡´ + ¡´ ¡´[0m[33m¡´ + [1m ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[0m[33m ¡´¡´¡´¡´¡´¡´¡´[0m + + diff --git a/sample/etc/chickens/g16 b/sample/etc/chickens/g16 new file mode 100644 index 00000000..03e4ebaa --- /dev/null +++ b/sample/etc/chickens/g16 @@ -0,0 +1,14 @@ + + [33m¡´¡´ + [1;34m¢¡ [0m[33m¡´ ¡´ ¡´¡´ + [1m¡´¡´¡´ [34m¢¢¢¡[33m¡´ ¡´ [0m[33m ¡´ ¡´ + ¡´¡´¡´[1m¡´ ¡´ [34m¢¢¢¡ [33m ¡´¡´ ¡´[0m[33m¡´¡´ ¡´ + ¡´[1m¡´ [36m ¡] [37m ¡ü [41m¢« [0m[1;34m¢¢¢w¢w¢¡[0m[33m ¡´ ¡´ ¡´ + [1m¡´ [0m[31m ¡´ [37;41m [0m[33m¡´¡´ [1;34m ¢¢¢¡[33m ¡´ ¡´ [0m[33m ¡´ + ¡´¡´[1m¡´ [36m ¡] [37m ¡ü [41m¢© [0m[33m¡´ ¡´ [1;34m¢¢¢¡[33m¡´ ¡´ [0m [33m¡´ [1;34m ¡´¡´¡´¡´ + [0m[33m¡´¡´ [1m ¡´ ¡´ [34m ¢¢¢¡[33m ¡´ [0m[33m ¡´ [1;34m ¡´¡´¡´¡´¡´ + [0m[33m¡´ [1;34m ¢x [33m ¡´ [0m[33m ¡´ [1;34m ¡´¡´¡´¡´¡´¡´ + [33m¡´ [34m ¢¢¢¡[33m¡´ [0m[33m¡´¡´ [1;34m ¡´¡´¡´¡´¡´ + [33m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ [34m¢¢¢w¢w¢w¢w¢w¢w¢w¢w¢w¡´¡´¡´¡´[0m + + diff --git a/sample/etc/chickens/g2 b/sample/etc/chickens/g2 new file mode 100644 index 00000000..032a3e61 --- /dev/null +++ b/sample/etc/chickens/g2 @@ -0,0 +1,5 @@ + + [1;33m¡´¡´¡´ + ¡´[36m¢Ý¢Ý[33m¡´ + ¡´¡´¡´[0m[33mùý[0m + diff --git a/sample/etc/chickens/g3 b/sample/etc/chickens/g3 new file mode 100644 index 00000000..5e65b34d --- /dev/null +++ b/sample/etc/chickens/g3 @@ -0,0 +1,6 @@ + + [33m¢© ¢¨ + [1m¡´¡´¡´ + ¡´[36m¢Ý¢Ý[33m¡´[0m[33mùú + [1m¡´¡´¡´¡´[0m[33mùý[0mý + diff --git a/sample/etc/chickens/g4 b/sample/etc/chickens/g4 new file mode 100644 index 00000000..5e8a7520 --- /dev/null +++ b/sample/etc/chickens/g4 @@ -0,0 +1,6 @@ + + [33m¢© ¢¨ + [1m¡´¡´¡´¡´ + ¡´[36m£R £R[33m¡´[0m[33mùú + [1m¡´[37m¡Ý[0m[31m¡»[1;37m¡Ý[33m¡´[0m[33mùø + [1m¡´¡´¡´¡´[0m[33m ùý[0m diff --git a/sample/etc/chickens/g5 b/sample/etc/chickens/g5 new file mode 100644 index 00000000..7bd2bea7 --- /dev/null +++ b/sample/etc/chickens/g5 @@ -0,0 +1,8 @@ + + [33m¢© ¢¨ + [1m¡´¡´¡´¡´¡´[0m [33m ùú + [1m¡´[36m £[ £[ [33m¡´[0m[33m ùø + [1m¡´ [37m¡Ù[0m[31m¡»[1;37m¡Ø [33m¡´[0m[33mùúùý + [1m¡´¡´¡´¡´¡´ [0m[33mùý + ¡´ ¡´[0m + diff --git a/sample/etc/chickens/g6 b/sample/etc/chickens/g6 new file mode 100644 index 00000000..87477217 --- /dev/null +++ b/sample/etc/chickens/g6 @@ -0,0 +1,10 @@ + + [33m¢©´ ¢¨ + [1m¡´¡´¡´¡´¡´¡´ [0m[33m ùúùûý + [1m¡´ [36m¢Ç ¢Ç [33m¡´ [0m[33m ùøùý + [1m¡´ [37m¡Ö[0m[31m ¡´ [1;37m¡Õ [33m¡´[0m [33m ùø + [1m¡´ [31m ¡t [33m¡´[0m [33m ùø + [1m¡´¡´¡´¡´¡´¡´¡´¡´ + [0m[33m¡´[1m¡´¡´[0m[33m¡´¡´[1m¡´¡´[0m + + diff --git a/sample/etc/chickens/g7 b/sample/etc/chickens/g7 new file mode 100644 index 00000000..08e1a435 --- /dev/null +++ b/sample/etc/chickens/g7 @@ -0,0 +1,11 @@ + + [33m¡´ ¡´ + ¡´[1m¡´¡´¡´[0m[33m¡´¡´ + [1m¡´ ¡´¡´¡´ + ¡´ [36m¢Ç ¢Ç [33m ¡´[0m [33m ¡´ + [1m¡´[37m ¡Ö[0m[31m¡´[1;37m¡Õ [33m ¡´ [0m[33m ¡´¡´ ¡´ + [1m¡´ [31m ¡å [33m ¡´[0m[33m ¡´ ¡´¡´ + [1m¡´ ¡´[0m[33m ¡´ + [1m¡´¡´¡´¡´¡´¡´¡´¡´¡´ + [0m[33m¡´¡´ ¡´¡´¡´¡´¡´[0m + diff --git a/sample/etc/chickens/g8 b/sample/etc/chickens/g8 new file mode 100644 index 00000000..3de22b49 --- /dev/null +++ b/sample/etc/chickens/g8 @@ -0,0 +1,14 @@ + + [33m¡´ + ¡´ + ¢©¡ ¢© ¡ [1m¡´¡´¡´ [0m[33m¡´ + ¡´[1m¡´¡´¡´[0m[33m¡´¡´[1m¡´ ¡´[0m[33m ¡´ + [1m¡´ ¡´[0m[33m¡´ + [1m¡´ [31m¢© ¢¨ [33m¡´[0m[33m¡´ ¡ + [1m¡´ [37m¡Ö[0m[31m¡´[1;37m¡Õ [33m ¡´[0m[33m¡´ + [1m¡´ [37;41m¢« ¢ª[0m [1;33m¡´¡´ + ¡´ [37;41m¢© ¢¨[0m [1;33m¡´¡´[0m[33m¢«¢« + [1m¡´¡´¡´¡´¡´¡´¡´[0m[33m¢«¢« + ¢«¢« ¢«¢«[0m + + diff --git a/sample/etc/chickens/g9 b/sample/etc/chickens/g9 new file mode 100644 index 00000000..c0274032 --- /dev/null +++ b/sample/etc/chickens/g9 @@ -0,0 +1,14 @@ + [33m¢¨ ¢¨ + [1m¡´¡´¡´¡´[0m[33m ¡´ + [1m¡´ ¡´ [0m[33m ¡´ + [1m¡´[36m ¡´ [33m ¡´[0m[33m ¡´ + [31m¡´[1;37m¢¤ [33m ¡´[0m[33m ¡´ + ¡´[1m¡´¡´ ¡´ [0m[33m ¡´ + [1;34m¡´¡´ ¡´¡´ [33m¡´ ¡´[0m[33m ¡´ + [1;34m¡´[35;46m ¢¨ [0m[1;34m¡´ [33m ¡´ ¡´[0m[33m¡´ + [1;34m¡´[35;46m ¢¨¡½¢¨ [0m[1;34m¡´[33m ¡´ ¡´ + [34m¡´[35;46m ¡ ¢ª¡½¢ª [0m[1;34m¡´ [33m ¡´ ¡´ + [34m¡´[35;46m ¢ª [0m[1;34m¡´ [0m[33m ¡´ [1m ¡´ + [34m¡´¡´¡´¡´¡´¡´¡´¡´[0m[33m ¡´¡´[1m¡´[0m + + diff --git a/sample/etc/chickens/h0 b/sample/etc/chickens/h0 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/h0 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/h1 b/sample/etc/chickens/h1 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/h1 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/h10 b/sample/etc/chickens/h10 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/h10 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/h11 b/sample/etc/chickens/h11 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/h11 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/h12 b/sample/etc/chickens/h12 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/h12 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/h13 b/sample/etc/chickens/h13 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/h13 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/h14 b/sample/etc/chickens/h14 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/h14 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/h15 b/sample/etc/chickens/h15 new file mode 100644 index 00000000..df160353 --- /dev/null +++ b/sample/etc/chickens/h15 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/h16 b/sample/etc/chickens/h16 new file mode 100644 index 00000000..100d4260 --- /dev/null +++ b/sample/etc/chickens/h16 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/h2 b/sample/etc/chickens/h2 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/h2 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/h3 b/sample/etc/chickens/h3 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/h3 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/h4 b/sample/etc/chickens/h4 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/h4 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/h5 b/sample/etc/chickens/h5 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/h5 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/h6 b/sample/etc/chickens/h6 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/h6 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/h7 b/sample/etc/chickens/h7 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/h7 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/h8 b/sample/etc/chickens/h8 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/h8 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/h9 b/sample/etc/chickens/h9 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/h9 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/hit b/sample/etc/chickens/hit new file mode 100644 index 00000000..2fe4b736 --- /dev/null +++ b/sample/etc/chickens/hit @@ -0,0 +1,14 @@ + + + + + + [43;33;1m¢« [0;30;43m"[0m [43;30m >< [0m + [37;1m ¢[43md[43m¢d [0m [41;5;30m¢i[0m [43;31;1;5m ¡Ë [0m + [44m [5;30m¢i¢i[47m¢i[0m [41;5;30m¢i[0m [43;5;30m¢i[0m [0;32m¢[43mf¢[0;32mf[0m [43;5;30m¢i[0m + [44;5;1;34m `` [0;5m¢o [31;1m¡´."[0m [41;30;5m¢i[0m [42;5;30m¢i [33m¢o [30m¢i[0m + [34m ¢¨¢h¢ª¢©[0m [32m ¢¨ ¢h¢©[0m + .¢[1mo [0m .¢[1mo[0m ¢[1mo,[0m ¢[1mo[0;1m,[0m + + + ¼K ¥´¬[½m¨Åé.. diff --git a/sample/etc/chickens/i0 b/sample/etc/chickens/i0 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/i0 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/i1 b/sample/etc/chickens/i1 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/i1 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/i10 b/sample/etc/chickens/i10 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/i10 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/i11 b/sample/etc/chickens/i11 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/i11 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/i12 b/sample/etc/chickens/i12 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/i12 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/i13 b/sample/etc/chickens/i13 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/i13 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/i14 b/sample/etc/chickens/i14 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/i14 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/i15 b/sample/etc/chickens/i15 new file mode 100644 index 00000000..df160353 --- /dev/null +++ b/sample/etc/chickens/i15 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/i16 b/sample/etc/chickens/i16 new file mode 100644 index 00000000..100d4260 --- /dev/null +++ b/sample/etc/chickens/i16 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/i2 b/sample/etc/chickens/i2 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/i2 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/i3 b/sample/etc/chickens/i3 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/i3 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/i4 b/sample/etc/chickens/i4 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/i4 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/i5 b/sample/etc/chickens/i5 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/i5 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/i6 b/sample/etc/chickens/i6 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/i6 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/i7 b/sample/etc/chickens/i7 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/i7 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/i8 b/sample/etc/chickens/i8 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/i8 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/i9 b/sample/etc/chickens/i9 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/i9 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/j0 b/sample/etc/chickens/j0 new file mode 100644 index 00000000..0aeb9433 --- /dev/null +++ b/sample/etc/chickens/j0 @@ -0,0 +1,8 @@ + + + + ¡´¡´ + ¡´¡´¡´ ¡¶ + ¡´¡´ ¡´¡´¡´ + + ¦³§À¤Úªº´cÅ]§Z diff --git a/sample/etc/chickens/j1 b/sample/etc/chickens/j1 new file mode 100644 index 00000000..2f5324a9 --- /dev/null +++ b/sample/etc/chickens/j1 @@ -0,0 +1,9 @@ + + + + ¡¶ + ¡¿¡´¡´¡´ + ¡¶ ¡´¡´[1;31m¡´[0m¡´ + ¡´¡´ ¡´¡´¡´ + ¡´¡´¡´ + diff --git a/sample/etc/chickens/j10 b/sample/etc/chickens/j10 new file mode 100644 index 00000000..ca0238c3 --- /dev/null +++ b/sample/etc/chickens/j10 @@ -0,0 +1,12 @@ + ¡¶ + ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡¿ + ¡´¡´[1;5;31m¢¨[m¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡¶ + ¡¿ ¡´¡´¡´¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´ + ¡¶ ¡´¡´¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´¡´ diff --git a/sample/etc/chickens/j11 b/sample/etc/chickens/j11 new file mode 100644 index 00000000..67acda5c --- /dev/null +++ b/sample/etc/chickens/j11 @@ -0,0 +1,12 @@ + + [33m§Ú¦³¤â¤F¡IÀ~¦º§A¡I[m + ¡¶ ¡¶ + ¡´ ¡´¡´ ¡´¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ ¡¶ + ¡´¡´[1;5;31m¢©[m¡´¡´¡´[1;5;31m¢¨[m¡´¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´¡¿¡¿¡¿¡¿¡¿¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´¡´ diff --git a/sample/etc/chickens/j12 b/sample/etc/chickens/j12 new file mode 100644 index 00000000..f5368760 --- /dev/null +++ b/sample/etc/chickens/j12 @@ -0,0 +1,11 @@ + + ¡¶ ¡¶ + ¡´ ¡´¡´ ¡´¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ ¡¶ + ¡´¡´[1;5;31m¢©[m¡´¡´¡´[1;5;31m¢¨[m¡´¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´¡¿¡¿¡¿¡¿¡¿¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´¡´ diff --git a/sample/etc/chickens/j13 b/sample/etc/chickens/j13 new file mode 100644 index 00000000..22721b27 --- /dev/null +++ b/sample/etc/chickens/j13 @@ -0,0 +1,12 @@ + ¡´ ¡´ ¡¶ ¡¶ + ¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´[1;5;31m¢©[m¡´¡´¡´¡´¡´[1;5;31m¢¨[m¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡´¡´ + ¡´¡´¡´¡´ ¡´ ¡´ ¡´ +¡¶¡´¡´ ¡´ ¡´¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡´ ¡´ + ¡´¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ ¡´ ¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/j14 b/sample/etc/chickens/j14 new file mode 100644 index 00000000..774d0ce2 --- /dev/null +++ b/sample/etc/chickens/j14 @@ -0,0 +1,13 @@ + + ¡¶ ¡¶ + ¡´¡´¡´ ¡´¡´ ¡´¡´ ¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ ¡´¡´ + ¡¿¡¿ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡¿¡¿ + ¡´¡´[1;5;31m¢©[m¡´¡´¡´¡´¡´[1;5;31m¢¨[m¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´ ¡´¡´¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡´¡´ + ¡´¡´¡´¡´ ¡´ ¡´ + ¡¶¡´¡´ ¡´ ¡´¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡´ + ¡´¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/j15 b/sample/etc/chickens/j15 new file mode 100644 index 00000000..774d0ce2 --- /dev/null +++ b/sample/etc/chickens/j15 @@ -0,0 +1,13 @@ + + ¡¶ ¡¶ + ¡´¡´¡´ ¡´¡´ ¡´¡´ ¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ ¡´¡´ + ¡¿¡¿ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡¿¡¿ + ¡´¡´[1;5;31m¢©[m¡´¡´¡´¡´¡´[1;5;31m¢¨[m¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´ ¡´¡´¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡´¡´ + ¡´¡´¡´¡´ ¡´ ¡´ + ¡¶¡´¡´ ¡´ ¡´¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡´ + ¡´¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/j16 b/sample/etc/chickens/j16 new file mode 100644 index 00000000..788ee97b --- /dev/null +++ b/sample/etc/chickens/j16 @@ -0,0 +1,13 @@ + [33m§q¡I¡I¡I§Ú¬O¤jÅ]¤ý¡I¡I¡I[m + ¡¶ ¡¶ + ¡´¡´¡´¡´ ¡´¡´ ¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´ ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ ¡´¡´¡´ + ¡´¡´¡´ ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´ ¡´¡´¡´ + ¡¿¡¿¡¿ ¡´¡´[1;5;31m¢©[m¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´[1;5;31m¢¨[m¡´¡´ ¡¿¡¿¡¿ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡¿¡´¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡¶¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ ¡´¡´¡¿ + ¡´¡´ ¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´ ¡´¡´¡´¡´¡´ ¡´ diff --git a/sample/etc/chickens/j2 b/sample/etc/chickens/j2 new file mode 100644 index 00000000..03ef58fc --- /dev/null +++ b/sample/etc/chickens/j2 @@ -0,0 +1,7 @@ + + + ¡¶ ¡¶ + ¡´¡´¡´¡´ + ¡´[1;31m¡´[0m¡´[1;31m¡´[0m¡´ + ¡´ ¡´¡´¡´¡´ + ¡¶¡´¡´¡´ diff --git a/sample/etc/chickens/j3 b/sample/etc/chickens/j3 new file mode 100644 index 00000000..593a726b --- /dev/null +++ b/sample/etc/chickens/j3 @@ -0,0 +1,10 @@ + + ¡¶¡¶ + ¡´¡´¡´ + ¡´¡´¡´¡´ ¡¶ + ¡´[1;31m¢¨[0m¡´[1;31m¢©[0m¡´ ¡´¡´ + ¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´ ¡´ + ¡´¡´¡´¡´ ¡´ ¡´ + ¡´¡´ + diff --git a/sample/etc/chickens/j4 b/sample/etc/chickens/j4 new file mode 100644 index 00000000..e2e31934 --- /dev/null +++ b/sample/etc/chickens/j4 @@ -0,0 +1,9 @@ + + + ¡¶ ¡¶ + ¡´¡´¡´¡´¡´ ¡¶ + ¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´¡´[1;31m¡´[m¡´[1;31m¡´[0m¡´¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´¡´¡´¡´¡´ ¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/j5 b/sample/etc/chickens/j5 new file mode 100644 index 00000000..2554d000 --- /dev/null +++ b/sample/etc/chickens/j5 @@ -0,0 +1,12 @@ + ¡¶ ¡¶ + ¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´[1;31m¡o[m¡´[1;31m¡o[m¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´ + ¡´ + ¡´ + ¡´ + ¡´¡´¡´ + ¡´¡´ + ¡¿ diff --git a/sample/etc/chickens/j6 b/sample/etc/chickens/j6 new file mode 100644 index 00000000..79484d50 --- /dev/null +++ b/sample/etc/chickens/j6 @@ -0,0 +1,9 @@ + + + ¡¶ ¡¶ + ¡¶ ¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´ ¡´¡´[1;5;31m¢©[m¡´[1;5;31m¢¨[m¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/j7 b/sample/etc/chickens/j7 new file mode 100644 index 00000000..93ffcac6 --- /dev/null +++ b/sample/etc/chickens/j7 @@ -0,0 +1,10 @@ + + + ¡¶ ¡¶ ¡¶ + ¡´¡´¡´¡´¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´¡´[1;5;31m¢©[m¡´[1;5;31m¢¨[m¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´¡´ diff --git a/sample/etc/chickens/j8 b/sample/etc/chickens/j8 new file mode 100644 index 00000000..c86b6f4a --- /dev/null +++ b/sample/etc/chickens/j8 @@ -0,0 +1,10 @@ + + + ¡¶ ¡¶ + ¡´¡´¡´¡´¡´¡¿ ¡´¡´ + ¡´¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´¡´[1;5;31m¢©[m¡´[1;5;31m¢¨[m¡´¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´¡´ ¡´¡´¡´¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ diff --git a/sample/etc/chickens/j9 b/sample/etc/chickens/j9 new file mode 100644 index 00000000..a902e57c --- /dev/null +++ b/sample/etc/chickens/j9 @@ -0,0 +1,11 @@ + + ¡¶ ¡¶ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡¶ ¡´¡´[1;5;31m¢©[m¡´¡´¡´[1;5;31m¢¨[m¡´¡´ + ¡´¡´ ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´ ¡´¡¿¡¿¡¿¡¿¡¿¡´ + ¡´ ¡´ ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´¡´¡´ diff --git a/sample/etc/chickens/k0 b/sample/etc/chickens/k0 new file mode 100644 index 00000000..2c1f12a0 --- /dev/null +++ b/sample/etc/chickens/k0 @@ -0,0 +1,13 @@ + +(1)§Ún¦¨¬°§ÔªÌ! + [0;34;40m¢¨[m + [0;34;40m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [0;30;43m ¢m ¢m [0;34;40m¢ª[m + [0;30;43m¢© ¢¨[m + [32;47m¢© [0;30;47m¢ª¢« [32;47m¢¨[m + [32m¢i [0;35m¢i¢i [32m¢i[m + [32m¢i [0;35m¢i¢i [32m¢i[m + [0;35m¢i¢i[m + [0;32m¢¨[0;32;47m¢«¢ª[0;32;40m¢©[m + diff --git a/sample/etc/chickens/k1 b/sample/etc/chickens/k1 new file mode 100644 index 00000000..836976bd --- /dev/null +++ b/sample/etc/chickens/k1 @@ -0,0 +1,11 @@ +¤j®v!½Ð¦¬§Ú¬°®{§a! + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [0;30;43m ¢m ¢m [0;34m¢ª[m + [0;30;43m¢© ¢¨[m + [0;32;47m¢© [0;30;47m¢ª¢« [0;32;47m¢¨[m + [0;32m¢i¢i¢i¢i¢i[m + [0;35m¢i¢i[m + [0;35m¢i¢i[m + [0;32m¢¨[0;32;47m¢«¢ª[0;32m¢©[m diff --git a/sample/etc/chickens/k10 b/sample/etc/chickens/k10 new file mode 100644 index 00000000..6bf8c59e --- /dev/null +++ b/sample/etc/chickens/k10 @@ -0,0 +1,13 @@ +§ÔªÌ¤³N-¤ß + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [0;31;43m ¢© ¢¨ [0;34m¢«[m + [0;35m¢ª¢i¢i¢«[m + [0;32;47m¢© [0;30;47m¢ª¢« [0;32;47m¢¨[m + [0;32;47m¢i¢© ¢¨¢i[m + [0;32m¢i[m¢i¢i[0;32m¢i[m + ¢i[0;32m¢i¢i[m¢i[m + + [0;36m¢¨¢i¢i¢©[m + [0;36m¢ª¢i¢i¢«[m diff --git a/sample/etc/chickens/k11 b/sample/etc/chickens/k11 new file mode 100644 index 00000000..bc2a19cc --- /dev/null +++ b/sample/etc/chickens/k11 @@ -0,0 +1,13 @@ +¤ô¤g·¤ô¤ß...¦XÅé!! + [0;34m¢¨ ¢©[m + [0;34m¢¨¢¨¢i¢i¢© ¢¨¢i¢i¢©¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m [0;34;43m¢i¢«¢ª¢«¢ª[m + [0;31;43m ¢© ¢¨ [0;34m¢ª ¢«[0;31;43m ¢© ¢¨ [m + [0;35m¢ª¢i¢i¢« ¢ª¢i¢i¢«[m + [0;32m¢i¢i[0;30;42m [0;30;47m¢« [0;32;47m¢¨¢i¢i[m [0;32;47m¢i¢i¢© [0;30;47m¢ª[0;32;42m ¢i¢i[m + [30;47m¢© ¢¨[m [0;30;47m¢© ¢¨[m + ¢i¢i ¢i¢i[m + ¢i¢i¢i ¢i¢i¢i[m + ¢i¢m ¢i¢m[m + [0;32m¢¨ [m¢ª ¢« [0;32m¢©[m + [0;32m¢¨ ¢©[m diff --git a/sample/etc/chickens/k12 b/sample/etc/chickens/k12 new file mode 100644 index 00000000..4cf65887 --- /dev/null +++ b/sample/etc/chickens/k12 @@ -0,0 +1,12 @@ +¦XÅé«á¦¨¬°°ª¯Å§ÔªÌ,®ð¶ÕÀb¤H! + [0;34m¢¨¢i¢«[m + [0;34m¢ª¢¨¢i¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª[0;34m¢i¢©[m + [0;31;43m ¢© ¢¨ [0;34m¢ª¢i[m + [0;35m¢ª¢i¢i¢«[0;34m ¢«[m + [1;31m¢© [0;32;47m¢ª [0;30;47m¢ª¢« [0;32;47m¢«[m [1;31m¢¨[m + [1;31m¢ª [0;37m¢i[0;30;47m¢© ¢¨[m¢i [1;31m¢«[m + [1;31m¢ª [m¢i [0;32m¢i¢i[m ¢i [1;31m¢«[m + [1;31m¢ª¢ª [m¢i ¢i¢i¢i ¢i [1;31m¢«¢«[m + [1;31m¢ª¢ª [m¢i¢i¢i [1;31m¢«¢«[m + [1;31m¢ª¢ª¢ª [m¢i¢i [1;31m¢«¢«¢«[m diff --git a/sample/etc/chickens/k13 b/sample/etc/chickens/k13 new file mode 100644 index 00000000..faa26334 --- /dev/null +++ b/sample/etc/chickens/k13 @@ -0,0 +1,12 @@ +³t«×¶W§Ö,§A¬Ý±o¨ì¶Ü? + [0;34m¢¨¢i¢«[m + [0;34m¢ª¢¨¢i¢i¢i¢i¢i¢i¢« ¢«[m + [0;34;43m¢«¢ª¢«¢ª[0;34m¢i¢i¢« ¢«[m + [0;31;43m ¢© ¢¨ [0;34m¢«[m + [0;35m¢ª¢i¢i¢«[m + ¢i¢i¢i[0;32;47m¢ª[0;30;47m¢ª¢« [0;32;47m¢«[m¢i¢i¢i ¢i[m + [0;30;47m¢© ¢¨[m + [0;32m¢i¢i[m + ¢i¢i ¢i ¢i[m + ¢i¢i ¢i ¢i[m + ¢i¢i ¢i ¢i[m diff --git a/sample/etc/chickens/k14 b/sample/etc/chickens/k14 new file mode 100644 index 00000000..4d875ce4 --- /dev/null +++ b/sample/etc/chickens/k14 @@ -0,0 +1,12 @@ +³o¬O§Ú¦Û³ÐªºªZ¾¹-¤Q¦r¤M! + [0;34m¢¨¢i¢«[m + [0;34m¢ª¢¨¢i¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª[0;34m¢i¢©[m + [1;33m¢¨ [0;31;43m ¢© ¢¨ [0;34m¢ª¢i [1;33m¢©[m + [1;33m¢i [0;35m¢ª¢i¢i¢«[0;34m ¢« [1;33m¢i[m + [1;33m¢ª¢i[0;32m¢i[1;33m¢i¢©[0;32m¢ª[0;30;47m ¢ª[0;30;40m [0;30;47m¢« [0;32m¢«[1;33m¢¨¢i[0;32m¢i[1;33m¢i¢«[m + [1;33m¢i[0;32m¢i¢i[0;32;42m [0;32;47m¢© [0;30;47m¢ª¢« [0;32;47m¢¨[0;32;42m [0;32m¢i¢i[1;33m¢i[m + [1;33m¢« [0;32m¢i¢i [1;33m¢ª[m + ¢i¢i¢i[m + ¢i¢i¢i[m + ¢i¢i[m diff --git a/sample/etc/chickens/k15 b/sample/etc/chickens/k15 new file mode 100644 index 00000000..d2b7f59b --- /dev/null +++ b/sample/etc/chickens/k15 @@ -0,0 +1,14 @@ +¦¨¬°²×·¥¤§-¥Õ§Ô! + ¢¨¢i¢i¢i¢« + [1;31m¢© [m¢i¢i¢i¢i¢© [1;31m¢¨[m +[1;31m ¢¨ [m¢¨[0;37;43m¢«¢ª¢«¢ª[m¢i¢© [1;31m¢©[m +[1;31m ¢© [0;31;43m ¢© ¢¨ [m¢i¢i [1;31m¢¨[m +[1;31m ¢©¢¨ [m¢ª¢i¢i¢«¢i¢« [1;31m¢©¢¨[m + [0;32m¢ª[0;37;47m [0;30;47m¢ª[0;30;40m [0;30;47m¢« [0;37;47m¢«[0;32;40m¢«[m + [0;32m¢i ¢i[0;33m¢i¢i¢i [0;30;47m¢© ¢ª¢« ¢¨[0;33;40m ¢i¢i¢i[0;32m¢i ¢i[m +[0;33m ¢i [0;32m¢i¢i¢i[0;33m ¢i[m +[0;33m ¢i [m¢i¢i¢i[0;33m ¢i[m +[0;33m ¢i [m¢i¢i¢i¢i[0;33m ¢i[m + ¢i¢i¢i¢i[m +[1;32m³Ð ¥@ ©_ «L ±Ñ ¸} ¤U[0m[1;34m ¾È ¦t ªZ ¨å ´¤ ¤â ¤¤[0m +[1;35m ¤Ñ ¤U µL ¼Ä ²Ä ¤@ ¤H[0m[1;5;33m «¢![0m diff --git a/sample/etc/chickens/k16 b/sample/etc/chickens/k16 new file mode 100644 index 00000000..d2b7f59b --- /dev/null +++ b/sample/etc/chickens/k16 @@ -0,0 +1,14 @@ +¦¨¬°²×·¥¤§-¥Õ§Ô! + ¢¨¢i¢i¢i¢« + [1;31m¢© [m¢i¢i¢i¢i¢© [1;31m¢¨[m +[1;31m ¢¨ [m¢¨[0;37;43m¢«¢ª¢«¢ª[m¢i¢© [1;31m¢©[m +[1;31m ¢© [0;31;43m ¢© ¢¨ [m¢i¢i [1;31m¢¨[m +[1;31m ¢©¢¨ [m¢ª¢i¢i¢«¢i¢« [1;31m¢©¢¨[m + [0;32m¢ª[0;37;47m [0;30;47m¢ª[0;30;40m [0;30;47m¢« [0;37;47m¢«[0;32;40m¢«[m + [0;32m¢i ¢i[0;33m¢i¢i¢i [0;30;47m¢© ¢ª¢« ¢¨[0;33;40m ¢i¢i¢i[0;32m¢i ¢i[m +[0;33m ¢i [0;32m¢i¢i¢i[0;33m ¢i[m +[0;33m ¢i [m¢i¢i¢i[0;33m ¢i[m +[0;33m ¢i [m¢i¢i¢i¢i[0;33m ¢i[m + ¢i¢i¢i¢i[m +[1;32m³Ð ¥@ ©_ «L ±Ñ ¸} ¤U[0m[1;34m ¾È ¦t ªZ ¨å ´¤ ¤â ¤¤[0m +[1;35m ¤Ñ ¤U µL ¼Ä ²Ä ¤@ ¤H[0m[1;5;33m «¢![0m diff --git a/sample/etc/chickens/k2 b/sample/etc/chickens/k2 new file mode 100644 index 00000000..5ed4647f --- /dev/null +++ b/sample/etc/chickens/k2 @@ -0,0 +1,10 @@ +¬Ó«Ò¥l¨£,¦¨¬°¥¿¦¡§ÔªÌ! + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [0;30;43m ¢m ¢m [0;34m¢ª[m + [0;30;43m¢© ¢¨[m + [0;32;47m¢© ¢ª¢« ¢¨[m + [0;32m¢i [0;35;45m¢i [0;32m¢i¢i[m + [0;32m¢i [0;35m¢i [0;35m¢i[m + [0;30;42m¢«[0;35m¢i [0;32;47m¢ª[0;32m¢©[m diff --git a/sample/etc/chickens/k3 b/sample/etc/chickens/k3 new file mode 100644 index 00000000..aa8a6519 --- /dev/null +++ b/sample/etc/chickens/k3 @@ -0,0 +1,11 @@ +¤°»ò?¥un»X±´N¥i¥H¤F? + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m[m + [0;30;43m ¢m ¢m [0;34m¢ª[m + [0;35m¢ª¢i¢i¢«[m + [0;32;47m¢© [0;30;47m¢ª¢« [0;32;47m¢¨[m + [0;32m¢i¢i [0;35m¢i¢i [0;32m¢i¢i[m + [0;35m¢i¢i[m + [0;35m¢i¢i[m + [0;32m¢¨[0;32;47m¢«¢ª[0;32m¢©[m diff --git a/sample/etc/chickens/k4 b/sample/etc/chickens/k4 new file mode 100644 index 00000000..b7e0c1c8 --- /dev/null +++ b/sample/etc/chickens/k4 @@ -0,0 +1,12 @@ +«¢!Åܦ¨¤¤¯Å§ÔªÌ¤F,¦n¯«®ð! + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [31;43m ¢© ¢¨ [0;34;40m¢ª[m + [0;32m¢i [0;35m¢ª¢i¢i¢« [0;32m¢i[m + [0;32;47m¢i¢© [0;30;47m¢ª¢« [0;32;47m¢¨¢i[m + [0;30;47m¢© ¢¨[m + ¢¨¢i¢i¢©[m + ¢i¢«¢ª¢i[m + ¢i ¢i[m + [0;32m¢¨ ¢©[m diff --git a/sample/etc/chickens/k5 b/sample/etc/chickens/k5 new file mode 100644 index 00000000..120b52ac --- /dev/null +++ b/sample/etc/chickens/k5 @@ -0,0 +1,12 @@ +³Ì²³æªº-Áô¨³N... + [0;34m ¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [0;31;43m ¢© ¢¨ [0;34m¢ª[m + [0;35m¢ª¢i¢i¢«[m + [0;32;44m ¢i ¢i [m + [0;30;44m ¢¨¢« [m + [0;30;44m ¢i[0;30;47m ¢i[0;30;44m¢« [m + [0;30;44m ¢i[0;30;47m [0;30;44m¢i¢« [m + [0;30;44m ¢i[0;30;47m ¡´ [0;30;44m¢i¢« ¢¨¢i¢« [m + [0;30;44m ¢i[0;30;47m [0;30;44m¢i¢i¢i¢i¢« [m diff --git a/sample/etc/chickens/k6 b/sample/etc/chickens/k6 new file mode 100644 index 00000000..0d869ccc --- /dev/null +++ b/sample/etc/chickens/k6 @@ -0,0 +1,13 @@ +§ÔªÌ¤³N-¤õ + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;34;43m¢«¢ª¢«¢ª¢i[m + [0;31;43m ¢© ¢¨ [0;34m¢ª[m + [1;31m¢© [0;35m¢ª¢i¢i¢« [1;31m¢¨[m + [0;32;47m¢i¢i¢© [0;30;47m¢ª¢« [0;32;47m¢¨¢i¢i[m + [0;30;47m¢© ¢¨[m + ¢i¢i[m + [1;31m¢© [m¢i¢i¢i [1;31m¢¨[m + [1;31m¢© [m¢i¢i [1;31m¢¨[m + [1;31m¢© ¢©¢© [m¢ª¢« [1;31m¢¨¢¨ ¢¨[m + [1;31m¢©¢©¢©[0;32m¢¨¢©[1;31m¢¨¢¨¢¨[m diff --git a/sample/etc/chickens/k7 b/sample/etc/chickens/k7 new file mode 100644 index 00000000..fb24da23 --- /dev/null +++ b/sample/etc/chickens/k7 @@ -0,0 +1,14 @@ +§ÔªÌ¤³N-¤g + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;32m¢© [0;34;43m¢«¢ª¢«¢ª¢i[0;32m¢¨[m + [0;32m¢©[0;31;43m ¢© ¢¨ [0;34m¢ª[m + [0;32m¢i[0;35m¢ª¢i¢i¢«[0;32m¢i[m + [0;32;47m¢© [0;30;47m¢ª¢« [0;32;47m¢¨[m + [0;30;47m¢© ¢¨[m + ¢i¢i[m + ¢i¢i¢i[m + ¢i¢i[m + [0;31m¢© [m¢ª¢« [0;31m¢¨[m + [0;31m¢©[0;32m¢ª¢«[0;31m¢¨[m + [0;31m¢©¢¨[m diff --git a/sample/etc/chickens/k8 b/sample/etc/chickens/k8 new file mode 100644 index 00000000..4e73a12c --- /dev/null +++ b/sample/etc/chickens/k8 @@ -0,0 +1,10 @@ +§ÔªÌ¤³N-· + [0;34m¢¨[m + [0;34m¢¨¢¨¢i¢i¢©[m + [0;32m¢¨¢© [0;34;43m¢«¢ª¢«¢ª¢i[0;32m ¢¨¢©[m + [0;32m¢¨¢i¢i¢© [0;31;43m ¢© ¢¨ [0;34m¢ª [0;32m¢¨¢i¢i¢©[m + [0;32m¢¨¢i¢i¢i¢i¢© [0;35m¢ª¢i¢i¢« [0;32m¢¨¢i¢i¢i¢i¢©[m + [0;32m¢ª[0;32;47m¢i¢© [0;30;47m¢ª¢« [0;32;47m¢¨¢i[0;32m¢«[m + [0;32m¢i [0;30;47m¢© ¢¨[0;32m ¢i[m + [0;32m¢i [m¢i¢i [0;32m¢i[m + [0;32m¢« ¢ª[m diff --git a/sample/etc/chickens/k9 b/sample/etc/chickens/k9 new file mode 100644 index 00000000..cda73fd8 --- /dev/null +++ b/sample/etc/chickens/k9 @@ -0,0 +1,11 @@ +§ÔªÌ¤³N-¤ô + [1;37;44m ¡´ [1;34;44m¢¨ [1;37;44m¢w¢w¢w¢w [m + [1;37;44m ¡´ [1;34;44m¢¨¢¨¢i¢i¢© [1;37;44m¢w¢w [m + [1;37;44m ¡´ [1;34;43m¢«¢ª¢«¢ª¢i[1;34;44m¢« [1;37;44m¢w¢w [m + [1;37;44m ¡´[0;31;43m ¢© ¢¨ [1;37;44m ¢w¢w¢w [m + [0;35;44m ¢ª¢i¢i¢«[0;32;44m¢i¢i [1;37;44m¢w¢w [m + [0;32;44m ¢i¢i[0;32;47m¢©[0;30;47m¢ª¢« [0;32;47m¢¨[0;32;44m¢« [1;37;44m¢w¢w¢w¢w [m + [0;34;44m [0;34;47m¢© [0;37;47m¢¨¢i[0;37;44m ¢¨¢i[0;32;44m¢ª [1;37;44m¢w¢w¢w[m + [0;37;44m ¢i¢i¢i¢i¢i [1;37;44m¢w¢w¢w [m + [0;37;44m ¢i¢i¢i [1;37;44m¢w¢w¢w¢w¢w [m + [0;32;44m ¢ª ¢w¢w¢w [m diff --git a/sample/etc/chickens/kiss b/sample/etc/chickens/kiss new file mode 100644 index 00000000..fdf155ee --- /dev/null +++ b/sample/etc/chickens/kiss @@ -0,0 +1,14 @@ + + + [1;31m oo$$$$oooo ooo$$$$$$oo + [;31m o$$$$$$$$$$$$$$$$$$$$$$$$$$o + [1;31m o$$$$$$$$$$$$$$$$$$$$$$$$$$$$o + [1;31m $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ + [1;31m $$$$$$$$$$$$$$$$$$$$$$$$$$$$$" + [1;31m "$$$$$$$$$$$$$$$$$$$$$$$$$$$" + [1;31m "$$$$$$$$$$$$$$$$$$$$$$$$$" + [1;31m "$$$$$$$$$$$$$$$$$$$$$" + [1;31m ""$$$$$$$$$$$$$$$$" + [1;31m ""$$$$$$$$$"" + [1;31m ""$"" [m + ¨Ó...¿Ë¤@Ó!! diff --git a/sample/etc/chickens/l0 b/sample/etc/chickens/l0 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/l0 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/l1 b/sample/etc/chickens/l1 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/l1 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/l10 b/sample/etc/chickens/l10 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/l10 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/l11 b/sample/etc/chickens/l11 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/l11 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/l12 b/sample/etc/chickens/l12 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/l12 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/l13 b/sample/etc/chickens/l13 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/l13 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/l14 b/sample/etc/chickens/l14 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/l14 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/l15 b/sample/etc/chickens/l15 new file mode 100644 index 00000000..df160353 --- /dev/null +++ b/sample/etc/chickens/l15 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/l16 b/sample/etc/chickens/l16 new file mode 100644 index 00000000..100d4260 --- /dev/null +++ b/sample/etc/chickens/l16 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/l2 b/sample/etc/chickens/l2 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/l2 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/l3 b/sample/etc/chickens/l3 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/l3 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/l4 b/sample/etc/chickens/l4 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/l4 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/l5 b/sample/etc/chickens/l5 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/l5 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/l6 b/sample/etc/chickens/l6 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/l6 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/l7 b/sample/etc/chickens/l7 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/l7 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/l8 b/sample/etc/chickens/l8 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/l8 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/l9 b/sample/etc/chickens/l9 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/l9 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/m0 b/sample/etc/chickens/m0 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/m0 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/m1 b/sample/etc/chickens/m1 new file mode 100644 index 00000000..36f55c21 --- /dev/null +++ b/sample/etc/chickens/m1 @@ -0,0 +1,9 @@ + + + ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ diff --git a/sample/etc/chickens/m10 b/sample/etc/chickens/m10 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/m10 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/m11 b/sample/etc/chickens/m11 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/m11 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/m12 b/sample/etc/chickens/m12 new file mode 100644 index 00000000..8646bce2 --- /dev/null +++ b/sample/etc/chickens/m12 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/m13 b/sample/etc/chickens/m13 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/m13 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/m14 b/sample/etc/chickens/m14 new file mode 100644 index 00000000..ba9d1d34 --- /dev/null +++ b/sample/etc/chickens/m14 @@ -0,0 +1,14 @@ + ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´¡´ ¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/m15 b/sample/etc/chickens/m15 new file mode 100644 index 00000000..df160353 --- /dev/null +++ b/sample/etc/chickens/m15 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´¡´¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ diff --git a/sample/etc/chickens/m16 b/sample/etc/chickens/m16 new file mode 100644 index 00000000..100d4260 --- /dev/null +++ b/sample/etc/chickens/m16 @@ -0,0 +1,15 @@ + ¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´¡´¡´ + ¡´ ¡´ ¡´ ¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´ ¡´ ¡´ + ¡´ ¡´¡´¡´¡´¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´¡´¡´ ¡´¡´ diff --git a/sample/etc/chickens/m2 b/sample/etc/chickens/m2 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/m2 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/m3 b/sample/etc/chickens/m3 new file mode 100644 index 00000000..6714c9d2 --- /dev/null +++ b/sample/etc/chickens/m3 @@ -0,0 +1,12 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/m4 b/sample/etc/chickens/m4 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/m4 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/m5 b/sample/etc/chickens/m5 new file mode 100644 index 00000000..723291ae --- /dev/null +++ b/sample/etc/chickens/m5 @@ -0,0 +1,13 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´¡´¡´ ¡´¡´ ¡´¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/m6 b/sample/etc/chickens/m6 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/m6 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/m7 b/sample/etc/chickens/m7 new file mode 100644 index 00000000..d3edcf12 --- /dev/null +++ b/sample/etc/chickens/m7 @@ -0,0 +1,14 @@ + + + + ¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´¡´¡´¡´¡´¡´ diff --git a/sample/etc/chickens/m8 b/sample/etc/chickens/m8 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/m8 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/m9 b/sample/etc/chickens/m9 new file mode 100644 index 00000000..b5c8367f --- /dev/null +++ b/sample/etc/chickens/m9 @@ -0,0 +1,15 @@ + ¡´¡´ ¡´¡´ + ¡´¡´¡´¡´ ¡´¡´¡´¡´ + ¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´ ¡´ ¡´ + ¡´¡´ ¡´¡´¡´ + ¡´ ¡´ + ¡´ ¡´ + ¡´ ¡´¡´¡´ ¡´ + ¡´ ¡´ ¡´ + ¡´ diff --git a/sample/etc/chickens/medicine b/sample/etc/chickens/medicine new file mode 100644 index 00000000..2bde35ed --- /dev/null +++ b/sample/etc/chickens/medicine @@ -0,0 +1,14 @@ + + + +[1;36 ùúùùùû[m +[1;36m ùúùý[m + [1;33m ¢b¢b¢b¢d[36m ùø[37m ¢b¢b¢b¢d[m + [43;1;33m¢¤¢¤[0;1;32m¡ó[36m ùø [46;37m¢¤¢¤[0;1;31m¡·[m + [43;30m¢« ¢ª[0;1;36m ùø [0;47;30m¢« ¢ª[m + [1;36m ¢~[43m¢w¢w¢w¢w[0;1;36m¢wùó¢w[47m¢w¢w¢w¢w[0;1;36m¢¡[m + [1;36m ¢x[43;33m pepper [0;1;36m ùø [47;37m salt [0;1;36m¢x[m +[1;36m ¢x[33m¢ªùþùþ¢«[36m ùø[37m ¢ªùþùþ¢«[36m¢x[m +[1;36m \ùíùùùùùùùùùùùäùùùùùùùùùùùí/[m + + ¦YÃÄÅo~~~ diff --git a/sample/etc/chickens/nofood b/sample/etc/chickens/nofood new file mode 100644 index 00000000..d784c9e0 --- /dev/null +++ b/sample/etc/chickens/nofood @@ -0,0 +1,18 @@ + + [31;1m¢B ¢A[0m [30;44m¢« ¡þ¢ª[0m [1m¡´¡´¡´[0m + [1;31m¡X ¡´ ¡X[0m [44;34m [43m¢«¢ª[44m [0m [1m¡´¡´¡´¡´[0m + [31;1m¢A ¢B[0m [1;43m¡´[30m-[37m¡´[30m¢w[0;44m [0m [1m¡´¡´¡´[0m¡´ + [31m¡[43mÆ ¡Æ[33m¡[44m´[0m[30;43;5m¢i[0m ¡´¡´¡´ + [43;30;5m¢i[0m [33;43;5m¢[1;37;41mi¢[43mi[43m¢« [40m [0m[30;46;5m¢i[0m + [46;30;5m¢i[0m [30;42m¢«[33m¢ª[30;43m¡Å¡þ[33;42m¢[30m«[32;46;5m¢i[0;42;30m¢ª[0m + [33;5m¢i[36m¢i[0;36m¢i¢i[0;42m [1m¢[0mi[1m¢[0mi[1m¢[0mi[42m [46;32;5m¢i[42m [0m + [32m¢ª[41m ¢ª[42;36;5m¢i[0;32m¢«[0m + [7;5m¢ª[43m [33;47m¢«[0;30;43m¢ª[0m [30m¢[31mª[41m [33;5m¢i[36m¢i¢i[0m + [30m¢[7m« [33m¢ª[43;30m¢ª[30;1m¢i[41m[33m¡´[30m¢i¢i¢i[0m + [7m¡ó ¡ó [33m¢ª[43;32m¢ª[46m¢«¢ª[42m [40m¢« + [42;30m ¢ª[7m [44m [45m [46m [32m¢ª[47m[45m¢[44m«[47m [33;5m¡[40m´[0;32m¢b¢c¢d¢e + [42m [7m [44m [45m [46;31m¢d[45m [44m [47m [42m [0m + [42m [7m [34;41m¢« [47m[44m [47m [42m [0m + [42m [30;1mùþ[0;42m¢«¢i[47m [42m [0m + [43m [5m¢i[7;33m¢i[0;5;43m¢i[7;33m¢i[0;43m [5;7;33m¢i[0;5;43m¢i[7;33m¢i[0;43;5m¢i[0;43m ,,.....[0m + ¾j¹LÀY¤F Â÷®a¥X¨«... diff --git a/sample/etc/chickens/nohp b/sample/etc/chickens/nohp new file mode 100644 index 00000000..474f9c63 --- /dev/null +++ b/sample/etc/chickens/nohp @@ -0,0 +1,16 @@ + + [1m¢g¢i¢i¢i¢i¢i¢i¢i¢g[m + [m¢[1mi¢i¢i¢i¢i¢i¢i¢i¢i¢i¢i[m + [1;30m¢[mi[1m¢i¢i¢i¢i¢i¢i¢i¢i¢i¢i¢i[m + [1m¢l[m [1;30m¢[mi[1m¢i¢i ¢i¢i ¢i¢i¢i[m + [1m¢l¢l¢l[m [0;30m¢[1mi[m¢[1mi¢i [1m¢i [m¢[1mi¢i¢[0;30mi[m +[1m¢l¢l¢l¢l¢l[m [1;30m¢[mi[1m¢i [m¢[1mi [m¢[1mi¢i[m +[1m¢l¢l¢l¢l¢l[m [m¢[1mi¢b ¢X [m¢[1mi ¢X ¢b¢i[m +[1m¢i¢i¢i¢i¢[0;30mi[m [0;30m¢[mf [1m¢i¢f¢i¢i¢f¢i ¢[0;30mf[m +[1m¢i¢i¢i¢i¢[0;30mi[m [m¢[1mi[0;30m¢[0;1mi¢i¢c¢i¢c¢i¢[0;30mi[0;1m¢i[m + [1m¢i¢i¢i¢[0;30mi[m [m¢[1mi [m¢[1mn¢m¢n¢n¢m¢o ¢i[m + [1m¢i¢i¢[0;30mi[m [m¢[1mi ¢i[m + [m¢[1mo¢m[m [1m¢i ¢i[m + [m¢[1mo¢m[m [m¢[1md [1m¢[mm¢[1mm¢m¢m¢m¢m¢i ¢c[m + [m¢[1mo¢m[m [m¢[1md¢d¢d ¢i¢i¢i¢i¢i¢i[m [0;1m¢d¢d¢d[m +[31m Åé¤O(HP)¯ÓºÉ ¦º±¼¤F :~~[m diff --git a/sample/etc/chickens/nosatis b/sample/etc/chickens/nosatis new file mode 100644 index 00000000..c8495275 --- /dev/null +++ b/sample/etc/chickens/nosatis @@ -0,0 +1,6 @@ + +ó + +§Ú¤£º¡·N§A³oÓÄê«O¥À + +Byebye diff --git a/sample/etc/chickens/oo b/sample/etc/chickens/oo new file mode 100644 index 00000000..e316b055 --- /dev/null +++ b/sample/etc/chickens/oo @@ -0,0 +1,14 @@ + + + + + + + + [32m £f + [35m ¡´¡´ + ¡´¡´¡´ + ¡´¡´ + ¡´ [0m + + ¦Y¤j¸É¤Y¸Ñ°£¯h³Ò§a diff --git a/sample/etc/chickens/read b/sample/etc/chickens/read new file mode 100644 index 00000000..e4060357 --- /dev/null +++ b/sample/etc/chickens/read @@ -0,0 +1,14 @@ + + + + + +[1;37m ¢d¢d¢d¢d[m + [1;35m ùø[36m |/[37m ¡Ä¡Ä[m + [1;31m ¢b¢g¢c[32m ¢h [37m¢y[47m::::[0;1;37m¢j[m + [1;33m ùÝùùùùùùùùùùùùùÞùùùùùùùß[m + [1;33m ¢x[43m ¡× [0;1;33m¢x[43m ¡× [0;1;33m¢x[m + [1;33m ¢u¢w¢w¢w¢w¢w¢w¢q¢w¢w¢w¢t[m + [1;33m ¢x ¢x[43m ¡×¡@[0;1;33m¢x[m +[1;33m ¢x¡@¡@¡@¡@¡@¡@¢u¢w¢w¢w¢t[m + ¥Î¥\®É¶¡Åo..... diff --git a/sample/etc/chickens/sell b/sample/etc/chickens/sell new file mode 100644 index 00000000..e253e3d0 --- /dev/null +++ b/sample/etc/chickens/sell @@ -0,0 +1,23 @@ + + [1;36;5m * [1;37m ¡W [m *[m + [1;37;5m¡@¢@ ¡W ¡þ¡@ [m + [1;34m¡U [37;5m ¡@¢@ ¡U ¡þ[0;32;1m¡@ ¡¯ [m + [1;35m ¢@¡U¡þ[37;5m ¡@¢@ ¢x ¡@¡þ¡@ [m + [1;37m ¡Ð¡ÐÆæ¡Ð¡Ð¡@ [33m ¢¨¢i¢i¢i¢i¢i¢© [m + [1;35m ¡þ¡U¢@ [33m ¢i¢«[37;5m¢@¢x¡þ[0;1;33m¢ª¢i [m + [1;34m ¡U [37;5m - - ----¡Ð[0;1;33m¢ª[37;5m¡Ð¢w[33m¡¯[1;37;5m¢w¡Ð[0;1;33m¢i[37;5m¡Ð---- - - [m + [1;37;5m ¡þ¢x¢@[0;1;33m ¢i[36m¡@ ¡¯ [m + [1;31m¡¯ [37;5m ¡þ ¡U [0;1;33m¢¨¢« [m + [1;37;5m ¡þ[0;1m¡a[45m¢P¡¹¢P[0;1;37m¡b[5m¢@ [m + [1;37;5m ¡þ [0;1m ([46;36m¢e¢e[0;1m) [37;5m ¢@ [m + [1;33m ¡¯ [37;5m ¡þ [0;1;31m ¢g¢g [37;5m ¢@ [m + [1;31m ¢i¢i [m + [1;32m ¢x [31m ¢i¢i [36m * [33m ¡@ ¡U [m + [1;32m ¢@ ¢x ¡þ [31m ¢i¢i ¢@¡U¡þ [m + [1;32m ¡þ¡U¢@ [31m ¢i¢i [33m -----[37m¢q[33m----- [m + [1;36m ¡K¡K¡][5;37m¡°[0;1;36m¡^¡K¡K [31m ¢i¢i ¡þ¡U¢@ [m + [1;32m¢@¡U¡þ [31m ¢i¢i [33m ¡U [m +[1;32m ¡þ ¢x ¢@ [31m ¢i¢i [m + [1;35m * [32m ¢x [37m ([47mùùùù[0;1;37m) [5m * [m +[1;37m ¢v¢v[m ²×©ó¸Ñ²æ¤F ^_^.... + diff --git a/sample/etc/chickens/toofat b/sample/etc/chickens/toofat new file mode 100644 index 00000000..b20a502e --- /dev/null +++ b/sample/etc/chickens/toofat @@ -0,0 +1,17 @@ + + + +[33m + .-., ,.-. + '-. /:::\\ //:::\ .-' + '-.\|':':' `"` ':':'|/.-' + `-./`. .-=-. .-=-. .`\.-` + /=- / | \ -=\ + ; | | | ; + |=-.|______|______|.-=| + |== \ 0 /_\ 0 / ==| + |= /'---( )---'\ =| + \ \: .'. :/ / + `\= '--` `--' =/' + `-=._ _.=-' + `"""` [m ªÎD¹L«×..¼µ¦º¤F.. diff --git a/sample/etc/chickens/tootired b/sample/etc/chickens/tootired new file mode 100644 index 00000000..a1f0429f --- /dev/null +++ b/sample/etc/chickens/tootired @@ -0,0 +1,15 @@ + + + [33;42m¢q¢q¢q¢q¢q¢q¢q¢q¢q [47;37;1m¢b¢c¢d[0;42m [33m¢q¢q¢q¢q¢q[m + [33;42m¢q¢q¢q¢q¢q[1;30m¢e¢i¢e [43;30m¡»¡»¢y[42m [43;32m¢« ¢ª[0;42;33m¢ª¢q[m + [33;42m¢q¢q¢q¢q/ [30;47m ¡ó¡ó [42;33m ¢ªùþ¢« [30;45m ¢÷¢÷ [42;33m \¢q[m + [37;1;42m¢d__[0;32;43m¢«[30m ¡ã[37m¢ª[44m¢g¢c[42m¢m[32;47m¢« [30;43mo[47m¢j [35;42m ¢ªùþ¢« [33m¢q[m + [42;33m ¢v¢ª[43;30m ¡ã[33;41m¢«[1m¢ª¢ª¢ª[37;47m¢i[30m¢y[0;30;43mO[47m¢k[37;42m¢m[44m [35m¢d¢d[33;42m¢q[m + [43;37m-------[41;1;33m¢ª¢ª¢ª¢ª¢ª[37m¢ª¢i[0;30;43m¢÷[37;42m¢« [34;45m¢i¡´ ¢«¢i[m + [44;1;37m ¢ª[46m____[33;41m¢ª[30m¢g¢g[33m¢ª¢ª[30;47m ¡Ý¡Ý¡Ý¡Ý[0;1;37m¢m¢m¢m¢m¢m¢m[m + [43;1;37m¢¨ ¢ª¢i[0;43;36mùÝùùùùùùùùùùùùùùùù[42m¢« [34m¢g¢g¢o¢d [m + [1;36;42m¢e¢e ¢ª[0;43;36mùø[41;33;1m¢ª[42m [41m¢ª[0;42;37m ¢g¢i[33m ¢o[37m¢i [34m¢i ¢o [m + [1;36;42m¢m [0;33;42m¢ª[1;41;33m¢ª[42m [41m¢ª[0;42;37m ¢i [33m ¢o[37m ¢m[34m¢i ¢o¢i [m + [1;36;42m¢m [31m¢¨ùþ¢« ¢ª¢©[37m¢« [0;33;42m¢o[37m ¢m[34m¢i ¢ª [m + + ¾Þ³Ò¹L«×.....²ÖˤF...... diff --git a/sample/etc/domain_name_query b/sample/etc/domain_name_query new file mode 100644 index 00000000..cc3a05f2 --- /dev/null +++ b/sample/etc/domain_name_query @@ -0,0 +1,256 @@ +# '#'¦Û¤§«á¥i¥H¥[µù¸Ñ +# +# ¤U±³o'@'¦æ¤£¥i®³±¼ +# ¬dµL˽¦í§} +@@@@@@@@@@@@@@ ---------- + +# 255.255.255.255 ¦U¤H±MÄݽЩñ³oÃä + +# ¾Ç®Õ ©Î ¹ÎÅé +# ¸s²Õ½Ð¥Ñ¤p¨ì¤j±Æ¦C + +pclab&csie bcªºpclab +.ee.ntu. ¥x¤j¹q¾÷¾Ç°| +jan.csie.ntu ¥x¤j¸ê°T¦a¤U¤@¤ë +feb.csie.ntu ¥x¤j¸ê°T¦a¤U¤G¤ë +mar.csie.ntu ¥x¤j¸ê°T¦a¤U¤T¤ë +apr.csie.ntu ¥x¤j¸ê°T¦a¤U¥|¤ë +may.csie.ntu ¥x¤j¸ê°T¦a¤U¤¤ë +jun.csie.ntu ¥x¤j¸ê°T¦a¤U¤»¤ë +sep.csie.ntu ¥x¤j¸ê°T¦a¤U¤E¤ë +snoopy.csie ¥v¥£¤ñ¤u§@¯¸ +csie.ntu ¥x¤j¸ê°T¨t +140.112.28. ¥x¤j¸ê°T¨t +140.112.29. ¥x¤j¸ê°T¨t +140.112.30. ¥x¤j¸ê°T¨t +140.112.31. ¥x¤j¸ê°T¨t +#140.112.4 ¥x¤j¸ê°T¨t +phys.ntu ¥x¤jª«²z¨t +scorpio.im.ntu ¥x¤j¸êºÞscorpio +im.ntu ¥x¤jºÞ°| +ccnet1.ntu ¥x¤j±JªÙDNS +cc.ntu. ¥x¤jpºâÂû¤¤¤ß +140.112.3. ¥x¤jpºâÂû¤¤¤ß + +140.112.10. ¥x¤j¤g¤ì¨t +140.112.11. ¥x¤j¤g¤ì¨t +140.112.12. ¥x¤j¤g¤ì¨t +140.112.13. ¥x¤j¤g¤ì¨t +ce.ntu ¥x¤j¤g¤ì¨t + +140.112.15. ¥x¤j§ÓÂEÀ] + +140.112.16. ¥x¤j·s¤u¾Ç°|¤j¼Ó +140.112.17. ¥x¤j¹q¾÷¾Ç°| +140.112.18. ¥x¤j¹q¾÷¾Ç°| +140.112.19. ¥x¤j¹q¾÷¾Ç°| +140.112.20. ¥x¤j¹q¾÷¾Ç°| +140.112.21. ¥x¤j¹q¾÷¾Ç°| + +140.112.22. ¥x¤j¤Æ¤u¨t +140.112.23. ¥x¤j¤Æ¤u¨t +140.112.26. ¥x¤j³y²î¨t + +140.112.169. ¥x¤j¬ã¤G¤p®M©Ð +140.112.174. ¥x¤j¤k¤E¯½´Ö§{ +140.112.216. ¥x¤j¤k¤T²¢»eºÛ +140.112.220. ¥x¤j¤k¤@¤j»Ó©Ð +140.112.221. ¥x¤j¤k¤@¤j»Ó©Ð +140.112.224. ¥x¤j¤k¤C¦¨¦ç³õ +140.112.225. ¥x¤j¤k¤°w´«Ç +140.112.239. ¥x¤j¨k¤@ºÛ +140.112.240. ¥x¤j¨k¤@ºÛ +140.112.241. ¥x¤j¨k¤@ºÛ +140.112.242. ¥x¤j¨k¤@ºÛ +140.112.243. ¥x¤j¨k¤T«Î +140.112.244. ¥x¤j¨k¤T«Î +140.112.245. ¥x¤j¨k¤©Ð +140.112.246. ¥x¤j¨k¤©Ð +140.112.247. ¥x¤j¨k¤»²² +140.112.248. ¥x¤j¨k¤»²² +140.112.249. ¥x¤j¨k¤C½` +140.112.250. ¥x¤j¨k¤C½` +140.112.251. ¥x¤j¨k¤K§O¹Ö +140.112.252. ¥x¤j¨k¤K§O¹Ö +140.112.253. ¥x¤j¨k¤K§O¹Ö + +.m1.ntu ¥x¤j¨k¤@ºÛ +.m2.ntu ¥x¤j¨k¤GÀ] +.m3.ntu ¥x¤j¨k¤T«Î +.m4.ntu ¥x¤j¨k¥|©Ò +.m5.ntu ¥x¤j¨k¤©Ð +.m6.ntu ¥x¤j¨k¤»²² +.m7.ntu ¥x¤j¨k¤C½` +.m8.ntu ¥x¤j¨k¤K²ø +.g2.ntu ¥x¤j¬ã¤G¤p®M©Ð +.f1.ntu ¥x¤j¤k¤@¤j»Ó©Ð +.f2.ntu ¥x¤j¤k¤G»e¤ë«Î +.f3.ntu ¥x¤j¤k¤T²¢»eºÛ +.f4.ntu ¥x¤j¤k¥|°ª±^«Î +.f5.ntu ¥x¤j¤k¤°w´«Ç +.f6.ntu ¥x¤j¤k¤»±B¯½´Y +.f7.ntu ¥x¤j¤k¤C¦¨¦ç³õ +.f8.ntu ¥x¤j¤k¤K¬V¦ç¶í +.f9.ntu ¥x¤j¤k¤E¯½´Ö§{ + +green.ev.ntu. ¥x¤jÀô¤u©Ò +.ie.ntu.edu.tw ¥x¤j¤u¤u©Ò +140.112.36. ¥x¤j¤u¤u©Ò(·s¤u¼Ó) +140.112.38. ¥x¤jÀ³¤O©Ò +140.112.39. ¥x¤j«°¶m©Ò +140.112.40. ¥x¤j¤ô¤u©Ò(·s¤u¼Ó) +140.112.42. ¥x¤j¹q¾÷ÂÂÀ] +140.112.43. ¥x¤j¾÷±ñ¨t +140.112.44. ¥x¤j¾÷±ñ¨t +140.112.46. ¥x¤j¾÷±ñ¨t +math.ntu ¥x¤j¼Æ¾Ç¨t +140.112.50. ¥x¤j¼Æ¾ÇÀ] +140.112.52. ¥x¤jª«²z¨t +140.112.54. ¥x¤j¤Æ¾Ç¨t +140.112.56. ¥x¤j¦a½è¨t +140.112.58. ¥x¤j°Êª«¨t +140.112.60. ¥x¤j´Óª«¨t +140.112.61. ¥x¤j´Ó¬ã¤j¼Ó +psy.ntu ¥x¤j¤ß²z¨t +140.112.62. ¥x¤j¤ß²z¨t +140.112.64. ¥x¤j¦a²z¨t +140.112.65. ¥x¤j¥þ²yÅܾE/¾®ºA¤¤¤ß +140.112.66. ¥x¤j¤j®ð¨t +140.112.67. ¥x¤j¤j®ð¨t +140.112.68. ¥x¤j®ü¬v©Ò +140.112.69. ¥x¤j®ü¬v©Ò +140.112.70. ¥x¤jº®¬ì©Ò +140.112.72. ¥x¤j¥Í¤Æ©Ò +140.112.74. ¥x¤j¹AÃÀ¨t +140.112.75. ¥x¤j¥Í²Î±Ð«Ç +140.112.76. ¥x¤j¹A¤u¨t +140.112.78. ¥x¤j¹A¤Æ¨t +140.112.80. ¥x¤j´Ó¯f¨t +140.112.81. ¥x¤j©øÂÎÀ] +140.112.82. ¥x¤j´ËªL¨t +140.112.84. ¥x¤j¯b²£¨t +140.112.86. ¥x¤j¹A¸g¨t +140.112.88. ¥x¤j¶éÃÀ¨t +140.112.89. ¥x¤j¤u¼t +140.112.92. ¥x¤j¹A±À¨t +140.112.94. ¥x¤j¹A¾÷¨t +140.112.96. ¥x¤jÃ~Âå¨t +140.112.99. ¥x¤j½Ã¥Í²Õ +140.112.111. ¥x¤j¬¡°Ê¤¤¤ß +140.112.120. ¥x¤j¬¡°Ê¤¤¤ß +140.112.100. ¥x¤j´Ó¯f¨t¾iÂÎÀ] +140.112.106. ¥x¤j¸êºÞ¨t +140.112.108. ¥x¤jºÞ°|p¤¤ +140.112.110. ¥x¤jºÞ°|p¤¤ +140.112.120. ¥x¤jÂå¾Ç®Õ°Ï +140.112.136. ¥x¤j¤½½Ã¨t +140.112.141. ¥x¤j¤¤¤å¨t/¥~¤å¨t +140.112.142. ¥x¤j¾ú¥v¨t/ÃÀ³N¥v©Ò +140.112.143. ¥x¤jõ¾Ç¨t/¹A·~³¯¦C¼s +140.112.145. ¥x¤jÁò³õ¤Î´¶³q±Ð«Ç +140.112.146. ¥x¤j¤é¤å¨t/À¸¨è©Ò/»y¨¥©Ò +140.112.150. ¥x¤jªk¾Ç°|,ªk¹Ï +140.112.153. ¥x¤j·s»D©Ò +140.112.155. ¥x¤j¤T¬ã©Ò +140.112.156. ¥x¤jªÀ·|¨t +140.112.157. ¥x¤jªÀ·|¨t +140.112.160. ¥x¤j¦æ¬F¤j¼Ó +140.112.178. ¥x¤j¾Ç¥Í¦í±JªA°È²Õ +140.112.181. ¥x¤jºÞ²z¾Ç°| +140.112.182. ¥x¤j·s¤u¼Ó +140.112.183. ¥x¤j¹A·~¦Û°Ê¤Æ±Ð«Ç +lib.ntu. ¥x¤jÁ`¹Ï + +.admin.yzu ¤¸´¼ºô±À +.dorm.ccu.e ¤¤¥¿¤j®ÈªÀ +.mayju.com ±ö¦Ë¤s²ø +as.ntu. ¥x¤j¤j®ð¨t +csie.nctu. ¥æ¤j¸ê¤u +www.nia. °ê¥ßÃÀ³N¾Ç°|www +nia.edu.tw °ê¥ßÃÀ³N¾Ç°| +163.18. °ª¶¯¥Ì½©¶é +203.64.3. °ê¥ßÃÀ³N¾Ç°| +140.119. ¬Fªv¤j¾Ç +cc.ntnu. ®v¤jp¤¤ +140.122. ®v½d¤j¾Ç +k2.dorm.nc ¦¨¤j¥ú¤G8ªÙ +cc.nctu. ¥æ¤jp¤¤ +php&cc.nctu. ¥æ¤jp¤¤ +nchu ¤¤¿³¤j¾Ç +linux.na.ntu. ¥x¤j³y²î¤¤¤ß +140.112.8. ¥x¤jpºâÂû¤¤¤ß +140.112.7. ¥x¤jp¤¤PC«Ç +cc.ncku. ¦¨¤jp¤¤ +stmail.fju. »²¤jp¤¤ +IP&dialup.ntu. p¤¤¼·±µ¨t²Î +im.ntu.edu. ¥x¤j¸êºÞ +med.mc.ntu. ¥x¤jÂå°|ºô¸ô³¡ +mc.ntu. ¥x¤jÂå°|ºô¸ô³¡ +139.175. SeedNet +.seed.net.tw SeedNet +210.64. HiNet +168.95. Hinet +.ts.hin HiNet +.hinet. HiNet +cc.chpi. ¤¤µØ¤u¾Ç°| +.nctu. ¥æ³q¤j¾Ç +.cc.nccu.edu.tw ¬F¤jp¤¤ +.nccu.edu.tw ¬Fªv¤j¾Ç +.AB. ²M¤j±JªÙ +.ncku. ¦¨¤j +.seeder. ªüªiù¸ê°Tºô +iis. ¤¤¬ã°|¸ê°T©Ò +sinica. ¤¤¥¡¬ã¨s°| +ntust. ¥x¬ì¤j +scu. ªF§d¤j¾Ç +fju. »²¤¯¤j¾Ç +nthu. ²MµØ¤j¾Ç +thu. ªF®ü¤j¾Ç +ntu.edu ¥xÆW¤j¾Ç +ntut.edu ¥x¥_¬ì§Þ¤j¾Ç +140.112 ¥xÆW¤j¾Ç +cgu. ªø©°¤j¾Ç +ntou. ®ü¬v¤j¾Ç +NTOU. ®ü¬v¤j¾Ç +NCTU. ¥æ³q±JªÙ +140.125 ¶³ªL¬ì§Þ¤j¾Ç +tpml.edu.tw ¥x¥_¥«¥ß¹Ï®ÑÀ] +ntnu. ®v½d¤j¾Ç +ficnet.net ¤j²³ºô¸ô +tku. ²H¦¿¤j¾Ç +shu. ¥@·s¤j¾Ç +ncue. ¹ü¤Æ®v½d¤j¾Ç +ncu. ¤¤¥¡¤j¾Ç +ntnu. ®v½d¤j¾Ç +140.115 ¤¤¥¡¤j¾Ç +ndhu. ªFµØ¤j¾Ç +iii ¸êµ¦·| +nsysu. ¤¤¤s¤j¾Ç +ethome ªF´Ë¼eÀW +tmc.edu.tw ¥x¥_Âå¾Ç°| +ym.edu.tw ¶§©ú¤j¾Ç +chu.edu.tw ¤¤µØ¤j¾Ç +140.138 ¤¸´¼¤j¾Ç +140.128 ªF®ü¤j¾Ç +140.120 ¤¤¿³¤j¾Ç +ntpu. ¥x¥_¤j¾Ç +yzu.edu.tw ¤¸´¼¤j¾Ç +cyut.edu.tw ´Â¶§¬ì§Þ¤j¾Ç +fg.tp. ¥_¤@¤k +nhltc. ªá½¬®v½d¾Ç°| +tceb. ¥x¤¤¥«©²±Ð¨|§½ +ntcic. ¥x¤¤§Þ³N¾Ç°| +jhnc.tp. ¥_¥«¸Û¥¿°ê¤¤ +dyu. ¤j¸¤j¾Ç +ilc.edu. ©yÄõ¿¤±Ð¨|¸ê°Tºô +ks.edu. °ª¶¯¿¤±Ð¨|ºô +cma. ³°x©x®Õ +ssvs.tp. ªQ¤s®a°Ó +csmc. ¤¤¤sÂå¾Ç°| +ttu. ¤j¦P¤j¾Ç +cmc. ¤¤°êÂåÃľǰ| +kmu. °ª¶¯Âå¾Ç¤j¾Ç +tmtc. ¥_¥«®v½d¾Ç°| +140.117. ¤¤¤s¤j¾Ç +210.208. SayHiNetµL¼·±µ +ck.tp.edu.tw «Ø°ê¤¤¾Ç diff --git a/sample/etc/feast b/sample/etc/feast new file mode 100644 index 00000000..29473341 --- /dev/null +++ b/sample/etc/feast @@ -0,0 +1,47 @@ +01 01 ¤¸¥¹©ñ°² +01 02 ¤¸¥¹¤S©ñ°² +01 11 ¥qªk¸` +01 23 ¦Û¥Ñ¤é +02 14 ±¡¤H¸` +02 28 ¤G¤G¤K¬ö©À +03 01 §L§Ð¸` +03 05 µ£x¸` +03 12 ´Ó¾ð¸` +03 14 ¥Õ¦â±¡¤H¸` +03 17 °êÂå¸` +03 21 ®ð¶H¸` +03 29 «C¦~¸` +04 01 ·M¤H¸` +04 04 °ü¥®¸` +04 04 ¨àµ£¸` +04 05 ²M©ú¸` +05 01 ³Ò°Ê¸` +05 04 ¤åÃÀ¸` +06 03 ¸T·Ï¸` +06 09 ÅK¸ô¸` +06 06 ¤uµ{®v¸` +06 15 ĵ¹î¸` +07 01 ¤½¸ô¸` +07 03 ¦X§@¸` +07 04 ¬ü°ê¿W¥ß¬ö©À¤é +07 11 ¯è®ü¸` +07 14 ªk°ê°ê¼y +08 08 ¤K¤K¤÷¿Ë¸` +08 14 ªÅx¸` +09 01 °OªÌ¸` +09 03 x¤H¸` +09 09 ª¯ª¯¸` +09 18 ¤E¤@¤K¨ÆÅÜ +09 28 ±Ð®v¸` +10 10 °ê¼y¤é +10 21 µØ¹´¸` +10 25 ¥xÆW¥ú´_¸` +10 31 ½±¤½½Ï¨° +11 11 ¤u·~¸` +11 12 °ê¤÷½Ï¨° +11 15 ¥xÆW¤j¾Ç®Õ¼y +12 01 ¥@¬É·R´þ¤é +12 10 ¥@¬É¤HÅv¸` +12 13 ¤T°Ó¶g¦~¼y +12 24 X'masEve +12 25 ¸t½Ï¸` diff --git a/sample/etc/goodbye b/sample/etc/goodbye new file mode 100644 index 00000000..38f8aac9 --- /dev/null +++ b/sample/etc/goodbye @@ -0,0 +1,19 @@ +[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +[33m¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A +[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[33;44m¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{[31;40m¦A¨£¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[33;44m¢x[37m ½Ð¥J²Ó¦^¾Ð±zªº±K½X¡A [33m ¢x[31;45m¢w¢{[40m¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[33;44m¢x[37m ¦pªG¯uªº§Ñ°O±K½X¤F¡A [33m ¢x[31;45m ¢x[40m¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[33;44m¢x[37m ½Ð¥Î[new]«·sµù¥U§a¡I[33m ¢x[31;45m ¢x[40m¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[33;44m¢x[37m ¶Ã¿å±K½X·|¯d¤U°O¿ý³á¡C[33m ¢x[31;45m ¢x[40m¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[33;44m¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}[31;45m ¢x[40m¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£[45m¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}[40m¦A¨£[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A +¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A¨£¦A[33m¦A[31m¦A¨£¦A¨£¦A¨£¦A¨£¦A[m +[1;33m¦pªG±zµo²{±zªºID¤£¨£¤F, ¦Ó¥B¤£¬O¦]¬°¤Ó¤[¨S¨Ó³Q¬åªÌ +½Ð³qª¾¯¸°ÈºÞ²zû, ¤Á¤Å«·snew ì¨ÓªºID, §_«h©Ò¦³°O +¿ý©Mª÷¿ú±N·|Âk¹s[m diff --git a/sample/etc/register b/sample/etc/register new file mode 100644 index 00000000..53b5e2d6 --- /dev/null +++ b/sample/etc/register @@ -0,0 +1,17 @@ +¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{ +¢x ½Ð°Ñ¦Ò¤U¦Cªº½d¨Ò¶ñ¼g±zªºµù¥U¸ê®Æ¡G ¢x +¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t +¢x½Ð¿é¤J¥N¸¹: [36mpiggy[m ¢x ¿é¤J±z·Q¥Îªº^¤å¥N¸¹ ¢x +¢x½Ð³]©w±K½X: [36mI'mPig[m ¢x ½Ð³]©w±K½X¡A¤£¹L¿Ã¹õ¤WÀ³¸Ó¬Ý¤£¨£ ¢x +¢x½ÐÀˬd±K½X: [36mI'mPig[m ¢x ½Ð¦A¦¸¿é¤J±K½X¡A¥H¥Ü½T©w ¢x +¢x ¢x Kermit ¨Ï¥ÎªÌ½Ð¥´ vt320 ¢x +¢x±zªº¼ÊºÙ: [36m½Þ¦~¥Íªº¬ü¬Ü[m ¢x ±zµoªí¤å³¹¥Îªºµ§¦W©Îºï¸¹ ¢x +¢x¯u¹ê©m¦W: [36m¦¶¾å´A[m ¢x ±zªº[1;31;40m¯u¹ê©m¦W[m ¢x +¢x¥Ø«e¦í§}: [36m·s¦Ë¿¤¤lµê¶m¯Q¦³§ø543¸¹[m ¢x ±z¥Ø«eªº[1;31;40mÁpµ¸¦a§}(¸Ô²Ó¶ñ¼g)[m ¢x +¢xºô¸ô¶l¥ó¦a§}: [36mwhoami@cs.ntnu.edu.tw[m ¢x ±zªº E-Mail address ¢x +¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢} + ¡° ¦b¥»¯¸µù¥UªÌ¡A¥NªíÄ@·N´L±q¥»¯¸¨î«×»P¯¸³W¡A§_«h½ÐÂ÷¶}¡C + ¡° ¥N¸¹ [ID] ¦Ü¤Ön¨âÓ¦r¡A¤£©y±Ä¥Î¼Æ¦r¡C + ¡° ±K½X ¦Ü¤Ön¥|Ó¦r¡A¤£¥i»P [ID] ¹p¦P¡A¤£©y¥þ³¡¤p¼g¡C + ¡° ½Ð½T¹ê«ö·Ó³W©w[1;31m¸Ô²Ó¶ñ¼g[m¡A§_«h¤£¤©³q¹L¡I + ¡° ¥H¤W¸ê®Æ[1;31m¯Ê¤@¤£¥i[m¡[mA·q½Ð¦X§@¡I diff --git a/sample/etc/registered b/sample/etc/registered new file mode 100644 index 00000000..1b52a301 --- /dev/null +++ b/sample/etc/registered @@ -0,0 +1,21 @@ +[1;33m ùÝùùùûùÝùùùûùúùùùû +[0;33m ùàùùùûùàùùùûùüùùùû[1;37;41m ¼f®Ö³q¹L [m +[1;36m¡º[32m¢w¢w[1;37m ùãùùùýùãùùùýùüùùùý[32m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w[36m¡º[m + + ¶Ù¶Ù¡A*s§A¦n¡G + + §Ú¿Ë¦ÛÀ°§A¼f®Ö³q¹LÅo ^o^ + + YÁÙ¤£¯àPost[1;33m½Ð«·slogin¤@¦¸[m ^_^ (n´«¨¥÷Åo) + + + + ¯¬ ¨Ï¥Î´r§Ö + + °O±o±`±`¨Óª±³á.... ^_^ + + + + + ¯¸ªø~~ +[1;36m¡º[32m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w[36m¡º[m diff --git a/sample/etc/today_boring b/sample/etc/today_boring new file mode 100644 index 00000000..12e39ce2 --- /dev/null +++ b/sample/etc/today_boring @@ -0,0 +1,22 @@ + [ ¨d¦Ï®É ] + [ ¨d¦Ï®É ] + [ ª÷¤û®É ] + [ ª÷¤û®É ] + [ Âù¤l®É ] + [ Âù¤l®É ] + [ ¥¨ÃÉ®É ] + [ ¥¨ÃÉ®É ] + [ ·à¤l®É ] + [ ·à¤l®É ] + [ ³B¤k®É ] + [ ³B¤k®É ] + [ ¤Ñ¯¯®É ] + [ ¤Ñ¯¯®É ] + [ Âù³½®É ] + [ Âù³½®É ] + [ ®g¤â®É ] + [ ®g¤â®É ] + [ Å]½~®É ] + [ Å]½~®É ] + [ ¤ô²~®É ] + [ ¤ô²~®É ] diff --git a/sample/etc/ve.hlp b/sample/etc/ve.hlp new file mode 100644 index 00000000..c1688bf2 --- /dev/null +++ b/sample/etc/ve.hlp @@ -0,0 +1,127 @@ +[m [37;45m¡i¤@¯ë«ü¥O¡j[m + ^X Àɮ׳B²z ^L «·sÅã¥Üµe± + ^V ¤Á´«ANSI¦â±m ^Z Åã¥Ü¥»¨D§Uµe± + ^Q ¤£¦sÀÉÂ÷¶} [1;32m ^G ´¡¤J¹Ï¤ù¤å¦r®w[m + [37;45m¡i´å¼Ð²¾°Ê«ü¥O¡j[m + ¡ö ©¹«á²¾°Ê¤@®æ ^A,Home ²¾¨ì¦¹¦æ¶}ÀY + ¡÷ ©¹«e²¾°Ê¤@®æ ^E,End ²¾¨ì¦¹¦æµ²§À + ¡ô,^P ©¹¤W²¾°Ê¤@¦æ (ESC-,) ²¾¨ìÀɮ׶}ÀY + ¡õ ©¹¤U²¾°Ê¤@¦æ (ESC-.),^T ²¾¨ìÀÉ®×µ²§À + ^B,PgUp ©¹¤W²¾°Ê¤@¶ ^F,PgDn ©¹¤U²¾°Ê¤@¶ + ^S ´M§ä¦r¦ê (ESC-L) ¸õ¦Ü«ü©w¦æ + (ESC-n) ¦A©¹«á§ä (ESC-p) ¦A©¹«e§ä + (ESC-]) ´M§ä¹ïºÙ¬A©· (ESC-x) ¦^¨ì«e¤@¦ì¸m + (ESC-f) ©¹«e¤@¦r (ESC-b) «á°h¤@¦r + [37;45m¡i§R°£´¡¤J«ü¥O¡j[m + ^D,Del §R°£¥Ø«eªº¦r¤¸ ^H,BS §R°£«e¤@Ó¦r¤¸ + ^K §R°£´å¼Ð¤§«á¦Ü¦æ§À ^Y §R°£¥Ø«e³o¦æ + ^O,Ins ¤Á´« ´¡¤J/Âл\ + (ESC-d) §R°£¤@¦r (ESC-0~9) ¶K¤W¼È¦sÀÉ 0-9 + + [37;45m¡iANSI¢x¶Â¬õºñ¶ÀÂŵµÀQ¥Õ¡j[m + + «e´º¢x[47;30;1m30[31m31[32m32[33m33[34m34[35m35[36m36[37m37[0m + I´º¢x[40;33;1m40[41m41[42m42[43m43[44m44[45m45[46m46[47m47[0m + [33;44mCtrl-V: ¤Á´« ANSI-color ¼Ò¦¡¡A¡u©Ò¨£§Y©Ò±o¡v¡A¥i¥ß§Y½s×[m + [33;44mCtrl-C: ¡uª½Ä±¦¡¡v´¡¤J±m¦â½X¡A¥i»´©ö¬°¤å¦r¡uµÛ¦â¡v (in ANSI-color mode)[m + ¤ä´© ANSI color ½s¿è¼Ò¦¡... ¤£¥u¬O¹wÄý¦Ó¤w + ¦P®É, ctrl-C ¦b ANSI mode ¤U¥i¥H¿é¤JÃC¦â... + ¦³¤TºØ¼Ò¦¡.... + w ¥Nªí ¥Õ¦r + wb ¥Nªí¥Õ¦r¶Â©³ + 1wb ¥Nªí°ª«G¥Õ¦r¶Â©³.. + ¤ä´© overwrite & insert , ¥i»´©ö½s¿èÃþ¦ü Welcome µe± + ¦]¬YºØì¦], ¨ú®ø¦b ansi editing ¤Uªº backspace¥\¯à:P[m + [37;45m¡i°Ï¶ô³B²z©R¥O¡j[m + (ESC-l), (ESC-SPACE) ³]©w¼Ð°O°Ï + ^W Cut, §â¼Ð°O°Ï°Å¦Ü¼È¦sÀÉ 0 + (ESC-c) Copy, §â¼Ð°O°Ï«þ¨©¦Ü¼È¦sÀÉ 0 + ©ÎªÌ¦A«ö¤@¦¸(ESC-SPACE)½T©w¼Ð°O°Ï½d³ò¡A½T©w½d³ò«á: + 0: Cut, §â¼Ð°O°Ï°Å¦Ü¼È¦sÀÉ 0 + 5: Copy, §â¼Ð°O°Ï«þ¨©¦Ü¼È¦sÀÉ 5 + 6-9: Cut or Copy + q: ¨ú®ø + ·í»Ýn§R¡u«Ü¦h¡v¦æ®É¡A¸Õ¸Õ ESC-SPC §a :> + Y»Ýn§â¤å³¹ùتº¡u³¡¤À¡v¨ú¥X®É¡AESC-SPC ¤]¾A¥Î¡C + (ESC-0/5) Paste, ª½±µ¶K¤W¼È¦sÀÉ 0/5 + (ESC-6-9) ¶K¤W¼È¦sÀÉ 6-9 ¡A¶K¤W«e¥ý¹wÄý + (ESC-j) ±N¼Ð°O°Ï©¹¥ª²¾ + (ESC-k) ±N¼Ð°O°Ï©¹¥k²¾ + (ESC-u) ¨ú®ø¼Ð°O°Ï + [37;45m¡i¯S®í«ü¥O¡j[m + ^U ¿é¤J ESC ½X(¥H * ªí¥Ü) ^C ÁÙì/³]©w ANSI ¦â±m + (ESC-y) ±Ï¦^»~§R¦æ ^_(Ctrl-/),(ESC--) ´_ì¥Ø«e¦æ + (ESC-A) ¤Á´«ANSI±m¦â¼Ò¦¡ (ESC-I) ¤Á´«ÁY±Æ(indent)¼Ò¦¡ + (ESC-P) ¤Á´«ª`µª½±µ¥´¼Ò¦¡ (ESC-R) ¤Á´« modem ASCII ¤W¶Ç¼Ò¦¡ + ^R Åã¥Ü¤W¦¸¦©À³°T®§ (ESC-U) ¨Ï¥ÎªÌ¦Cªí + (ESC-i) ¶i¤Jµo§b¼Ò¦¡ + + +> -------------------------------------------------------------------------- < + + ASC¢º¤W¦â°ò¦±Ð¾Ç + + [1;36m<<<<<<<<<<<<<<<<<<<<<<<< $ ±Ð ¾Ç ¶} ©l $ >>>>>>>>>>>>>>>>>>>>>>>>>>>>[m + [1m º¥ý¡A§i¶D§A¤@¥ó³Ì«nªº¨Æ¡A¦b©¹«áªº±Ð¾Ç¤¤©Ò¦³ªº * ¸¹³£¬O«ö Esc Áä + [1m ¨â¦¸²£¥Íªº¡A¥H¨ä¥L¤è¦¡¡A¦p¡Gª½±µ«ö * ¸¹¡A©Ò²£¥Íªº³£µLªk°õ¦æ¡C + [1m ¹ï¤F¡A * ¸¹²£¥Íªº¤è¦¡¦bÁp¤u¬O«ö Esc ¨â¦¸¡A¦ý¦b¨ä¥L¦a¤è¥i´N¤£¤@©w¤F + [1m ¡A¥i¯à¬O Ctrl + U ²£¥Íªº¡AÁ`¤§¡AY¤£²M·¡¡A«ö Ctrl + Z ½u¤W»²§U»¡©ú¬Ý¬Ý + [1m ´Nª¾¹D¤F¡A¤Ï¥¿¡A²{¦bªº§A¡AÀ³¸Ó¬O¥u¦³¦bÁp¤u¤Wª±§a¡I©Ò¥H¡A´N¥HÁp¤uªº¤è¦¡ + [1m ±Ð§A¡A¥H«á¦³¨ì§O¯¸®É¡A¦A±Ð§A§a¡I + [1m ¥ý§i¶D§A¤@¨Ç°ò¥»ªº¦â±m±±¨î°Ñ¼Æ¡G[31m(°O¦í¡Im ¤@©w¬O¤p¼g¡I¡I) + [1;34m°Ñ ¼Æ ¦â±m Á| ¨Ò »¡ ©ú + [32m--------- ------ ---------------------------------------------- + [1;33m ############ ¥H¤U¬°·t¦â¨t¦Cªº«e´º¦â±m ############[m + *[0;30m [1m ¶Â¦â [m *[0;30;47m´ú¸Õ¤@¤U ==> [0;30;47m´ú¸Õ¤@¤U[m + *[0;31m [1m ¬õ¦â [m *[0;31m´ú¸Õ¤@¤U ==> [0;31m´ú¸Õ¤@¤U[m + *[0;32m [1m ºñ¦â [m *[0;32m´ú¸Õ¤@¤U ==> [0;32m´ú¸Õ¤@¤U[m + *[0;33m [1m ¤g´Ä¦â[m *[0;33m´ú¸Õ¤@¤U ==> [0;33m´ú¸Õ¤@¤U[m + *[0;34m [1m ²`ÂÅ [m *[0;34m´ú¸Õ¤@¤U ==> [0;34m´ú¸Õ¤@¤U[m + *[0;35m [1m µµ¦â [m *[0;35m´ú¸Õ¤@¤U ==> [0;35m´ú¸Õ¤@¤U[m + *[0;36m [1m ²LÂÅ [m *[0;36m´ú¸Õ¤@¤U ==> [0;36m´ú¸Õ¤@¤U[m + *[0;37m [1m ¥Õ¦â [m *[0;37m´ú¸Õ¤@¤U ==> [0;37m´ú¸Õ¤@¤U[m + [1;33m ############ ¥H¤U¬°«G¦â¨t¦Cªº«e´º¦â±m ############[m + *[1;30m [1m ²`¦Ç¦â[m *[1;30m´ú¸Õ¤@¤U ==> [1;30m´ú¸Õ¤@¤U[m + *[1;31m [1m «G¬õ¦â[m *[1;31m´ú¸Õ¤@¤U ==> [1;31m´ú¸Õ¤@¤U[m + *[1;32m [1m «Gºñ¦â[m *[1;32m´ú¸Õ¤@¤U ==> [1;32m´ú¸Õ¤@¤U[m + *[1;33m [1m ¶À¦â [m *[1;33m´ú¸Õ¤@¤U ==> [1;33m´ú¸Õ¤@¤U[m + *[1;34m [1m «G²`ÂÅ[m *[1;34m´ú¸Õ¤@¤U ==> [1;34m´ú¸Õ¤@¤U[m + *[1;35m [1m «Gµµ¦â[m *[1;35m´ú¸Õ¤@¤U ==> [1;35m´ú¸Õ¤@¤U[m + *[1;36m [1m «G²LÂÅ[m *[1;36m´ú¸Õ¤@¤U ==> [1;36m´ú¸Õ¤@¤U[m + *[1;37m [1m «G¥Õ¦â[m *[1;37m´ú¸Õ¤@¤U ==> [1;37m´ú¸Õ¤@¤U[m + [1;33m ############## ¥H ¤U ¬° I ´º ¦â ±m ##############[m + [1;33m ############# ©Ò¦³¤å¦rÃC¦â¬Ò¥H¶À¦âÅã¥Ü ###########[m + *[1;33;40m [1m¶Â¦â [m *[1;33;40m´ú¸Õ¤@¤U ==> [1;33;40m´ú¸Õ¤@¤U[m + *[1;33;41m [1m¬õ¦â [m *[1;33;41m´ú¸Õ¤@¤U ==> [1;33;41m´ú¸Õ¤@¤U[m + *[1;33;42m [1mºñ¦â [m *[1;33;42m´ú¸Õ¤@¤U ==> [1;33;42m´ú¸Õ¤@¤U[m + *[1;33;43m [1m´Ä¦â [m *[1;33;43m´ú¸Õ¤@¤U ==> [1;33;43m´ú¸Õ¤@¤U[m + *[1;33;44m [1m²`ÂÅ [m *[1;33;44m´ú¸Õ¤@¤U ==> [1;33;44m´ú¸Õ¤@¤U[m + *[1;33;45m [1mµµ¦â [m *[1;33;45m´ú¸Õ¤@¤U ==> [1;33;45m´ú¸Õ¤@¤U[m + *[1;33;46m [1m²LÂÅ [m *[1;33;46m´ú¸Õ¤@¤U ==> [1;33;46m´ú¸Õ¤@¤U[m + *[1;33;47m [1m¥Õ¦â [m *[1;33;47m´ú¸Õ¤@¤U ==> [1;33;47m´ú¸Õ¤@¤U[m + [1m ¥H¤Wªº©Ò¦³Á|¨Ò¬Ò¬O×¹¢¹L«áªºµ²ªG¡AY¯u·ÓÁ|¨Ò¼g¡A¤£¦ý¨S¹F¨ìì¥ý¹w´Á + [1m ®ÄªG¡A¤Ï¦Ó¥i¯à·|¾ÉP¤Ñ¤U¤j¶Ã¡C«e´º[m(§Y¤å¦r³¡¥÷)[1m©MI´º[m(§Y©³¦â)[1mªº×¹¢¤è¦¡ + [1m ¤£¤@¼Ë¡A¥ý»¡«e´ºªº×¹¢¤è¦¡¡C + [1m ¦AÁ|Ó¨Ò§a¡I±N "´ú¸Õ¤@¤U" ¤W¦â¡A¤§«áªº³£¤£¤W¦â¡AY *[1;33m´ú¸Õ¤@¤U + [1m ³oºØ¼gªk¡A¨ä«á±©Ò¦³ªº¤å¦r³£·|Åܦ¨¶À¦â¡G + [m + *[1;33m´ú¸Õ¤@¤Uxxxx ==> [1;33m´ú¸Õ¤@¤Uxxxx[m + [1m ·|²£¥Í¦p¤Wµ²ªG¡AYn±N xxxx Åܦ^ì¦â¡A«h¥i¡G + [m + *[1;33m´ú¸Õ¤@¤U*[mxxxx ==> [1;33m´ú¸Õ¤@¤U[mxxxx + [1m ¥[Ó *[m ©Î *[0m ´N¥i¥H¸Ñ¨M¡A¦ýY·Q§â xxxx Åܦ¨¨ä¥LÃC¦â¡A«h¡G + [m + *[1;33m´ú¸Õ¤@¤U*[0;36mxxxx ==> [1;33m´ú¸Õ¤@¤U[0;36mxxxx[m + [1m Á`¤§¡A¦b·Q§ïÅܦâ±mªº³¡¥÷¥[¤W·Q§ïÅܪº¦â±m°Ñ¼Æ¡F¦b·Q°±¤î¤W¦âªº¦a¤è¥[ + [1m ¤W *[m ©Î *[0m §Y¥i¡I + [1m ¥H¤W¡A¬°«e´º¦âªº×¹¢¤è¦¡¡A±µµÛ¡A»¡»¡I´º¦âªº×¹¢¤è¦¡¡A»¡§¹´N¤U½Ò¤F + [1m ò¡I + [1m I´º¦âªº¼gªk«Ü©_©Ç¡A¥H¤UÁ|¨Ò»¡©ú¤@¤U¡G + [m + *[1;33;43m´ú¸Õ¤@¤U*[m ==> [1;33;43m´ú¸Õ¤@¤U[m + *[1;33;43m ´ú¸Õ¤@¤U*[m ==> [1;33;43m ´ú¸Õ¤@¤U[m + *[1;33;43m ´ú¸Õ¤@¤U *[m ==> [1;33;43m ´ú¸Õ¤@¤U [m + [1m ¥¦·|¦]¬°§A°Ñ¼Æªº¦ì¸m¤£¦P¡A¦Ó²£¥Í¤£¦Pªºµ²ªG¡A¥H¦¹¯S©Ê¡A±NI´º¦â¦h¥[¬¡ + [1m ¥Î¡A§A¤]¯à°µ¥X¥X¦âªºÃ±¦WÀÉ¡BpµeÀÉ....µ¥¡C + [1m ¦n°Õ¡I¤U½ÒÅo¡I¶}©l°µ¨Ç¸ÕÅç§a¡I¬Ý¬Ý¦³þ¸ÌÁÙ¤£À´ªº¡A¦A§i¶D§Ú¡I^_^ + [1;36m<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $ E N D $ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[m diff --git a/sample/innd/Makefile b/sample/innd/Makefile new file mode 100644 index 00000000..853ba0db --- /dev/null +++ b/sample/innd/Makefile @@ -0,0 +1,9 @@ +BBSHOME?=$(HOME) +TARGET=$(BBSHOME)/innd/ +FILES=bbsname.bbs newsfeeds.bbs nodelist.bbs ntu.active + +all: + +install: + install -d $(TARGET) + install -c -m 644 $(FILES) $(TARGET) diff --git a/sample/innd/bbsname.bbs b/sample/innd/bbsname.bbs new file mode 100644 index 00000000..72db534d --- /dev/null +++ b/sample/innd/bbsname.bbs @@ -0,0 +1 @@ +ptt2 diff --git a/sample/innd/newsfeeds.bbs b/sample/innd/newsfeeds.bbs new file mode 100644 index 00000000..c32b8042 --- /dev/null +++ b/sample/innd/newsfeeds.bbs @@ -0,0 +1,3 @@ +# newsgroups board news server +#------------------------------------- -------------- ----------- +#tw.bbs.test test ntu diff --git a/sample/innd/nodelist.bbs b/sample/innd/nodelist.bbs new file mode 100644 index 00000000..d5784970 --- /dev/null +++ b/sample/innd/nodelist.bbs @@ -0,0 +1,4 @@ +# name hostname & domainname full name +#------- ---------------------------------- ------------ +#ptt2 ptt2.csie.ntu.edu.tw IHAVE(7777) Ptt2 +#ntu news.ntu.edu.tw POST(119) NTU News Server diff --git a/sample/innd/ntu.active b/sample/innd/ntu.active new file mode 100644 index 00000000..3825d9ea --- /dev/null +++ b/sample/innd/ntu.active @@ -0,0 +1 @@ +tw.bbs.chat 0000000000 0000000000 y diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf new file mode 100644 index 00000000..343c0299 --- /dev/null +++ b/sample/pttbbs.conf @@ -0,0 +1,10 @@ +/* ©w¸q BBS ¯¸¦W¦ì§} */ + +#define BBSNAME "·s§å½ð½ð" /* ¤¤¤å¯¸¦W */ +#define MYHOSTNAME "ptt2.twbbs.org.tw" /* ºô¸ô¦ì§} */ +#define MYIP "140.112.8.192" /* IP¦ì§} */ +#define BBSUSER "bbs" +#define BBSUID 9999 +#define BBSGID 99 + +#define MAX_USERS 10000 diff --git a/sample/rc.local b/sample/rc.local new file mode 100644 index 00000000..8fd6c714 --- /dev/null +++ b/sample/rc.local @@ -0,0 +1,4 @@ +#!/bin/sh +/usr/bin/su bbsadm -c /home/bbs/bin/uhash_loader +/usr/bin/su bbsadm -c /home/bbs/bin/outmail& +/usr/bin/su bbsadm -c /home/bbs/innd/innbbsd 7777 diff --git a/util/.cvsignore b/util/.cvsignore new file mode 100644 index 00000000..e7408563 --- /dev/null +++ b/util/.cvsignore @@ -0,0 +1,42 @@ +bbsmail +BM_money +post +account +birth +deluserfile +expire +mandex +horoscope +openvice +parse_news +openticket +bmda +uhash_loader +poststat +showboard +topusr +yearsold +cutpasswd +inndBM +antispam +countalldice +webgrep +bbsrf +initbbs +outmail +xchatd +userlist +tunepasswd +buildir +reaper +shmsweep +merge_passwd +merge_board +cpdeadbrd +rmuid +buildAnnounce +toplazyBBM +toplazyBM +jungo +bbsctl +daymandex diff --git a/util/BM_money.c b/util/BM_money.c new file mode 100644 index 00000000..51e24c38 --- /dev/null +++ b/util/BM_money.c @@ -0,0 +1,117 @@ +/* $Id: BM_money.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ + +/* µ¹ª©¥D¿úªºµ{¦¡ */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "common.h" + +#define FUNCTION (2100 - c*5) + +extern int numboards; +extern boardheader_t *bcache; +extern struct UCACHE *uidshm; + +int c, n; +extern userec_t xuser; + + + +int Link(char *src, char *dst) { + char cmd[200]; + + if (link(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + + +int main() { + FILE *fp = fopen(BBSHOME "/etc/topboardman", "r"); + char buf[201], bname[20], BM[90], *ch; + boardheader_t *bptr = NULL; + int nBM; + + resolve_boards(); + if(passwd_mmap()) + exit(1); + if (!fp) + return 0; + + c = 0; + fgets(buf, 200, fp); /* ²Ä¤@¦æ®³±¼ */ + + printf( + " \033[1;44m ¼úÀyÀu¨}ª©¥D ¨C¶gªáÁ~ ¨ÌºëµØ°Ï±Æ¦W¤À°t \033[m\n\n" + "\033[33m (±Æ¦W¤Ó«á±©Î´X¥G¨S¦³ºëµØ°ÏªÌ¤£¦C¤J)\033[m\n" + " ¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\n" + "\n\n"); + + while (fgets(buf, 200, fp) != NULL) + { + buf[24] = 0; + sscanf(&buf[9], "%s", bname); + for (n = 0; n < numboards; n++) + { + bptr = &bcache[n]; + if (!strcmp(bptr->brdname, bname)) + break; + } + if (n == numboards) + continue; + strcpy(BM, bptr->BM); + printf(" (%d) %-15.15s %s \n", c + 1, bptr->brdname, bptr->title); + + if (BM[0] == 0 || BM[0] == ' ') + continue; + + ch = BM; + for (nBM = 1; (ch = strchr(ch, '/')) != NULL; nBM++) + { + ch++; + }; + ch = BM; + + if (FUNCTION <= 0) + break; + + printf(" ¼úª÷ \033[32m%6d \033[m ¤Àµ¹ \033[33m%s\033[m \n", + FUNCTION, bptr->BM); + + for (n = 0; n < nBM; n++) + { + fileheader_t mymail; + char *ch1,uid ; + if((ch1 = strchr(ch, '/'))) + *ch1 = 0; + if ((uid=getuser(ch))!=0) + { + + char genbuf[200]; + deumoney(uid,FUNCTION / nBM); + sprintf(genbuf, BBSHOME "/home/%c/%s", ch[0], ch); + stampfile(genbuf, &mymail); + + strcpy(mymail.owner, "[Á~¤ô³U]"); + sprintf(mymail.title, + "\033[32m %s \033[mª©ªºÁ~¤ô ¢C\033[33m%d\033![m", bptr->brdname, FUNCTION / nBM); + mymail.savemode = 0; + unlink(genbuf); + Link(BBSHOME "/etc/BM_money", genbuf); + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", ch[0], ch); + append_record(genbuf, &mymail, sizeof(mymail)); + } + ch = ch1 + 1; + } + c++; + } + return 0; +} diff --git a/util/BM_money.sh b/util/BM_money.sh new file mode 100644 index 00000000..8bef4fc9 --- /dev/null +++ b/util/BM_money.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id: BM_money.sh,v 1.1 2002/03/07 15:13:45 in2 Exp $ + +bin/BM_money > etc/BM_money +bin/post Record ¬P´Á¤' 'ª©¥DµoÁ~¤é [°]ª÷®ø®§] etc/BM_money diff --git a/util/BOARDS.bid b/util/BOARDS.bid Binary files differnew file mode 100644 index 00000000..8d0312e5 --- /dev/null +++ b/util/BOARDS.bid diff --git a/util/DEADJOE b/util/DEADJOE new file mode 100644 index 00000000..a0793f05 --- /dev/null +++ b/util/DEADJOE @@ -0,0 +1,9 @@ + +*** Modified files in JOE when it aborted on Thu Nov 22 19:30:21 2001 +*** JOE was aborted by signal 1 + +*** Modified files in JOE when it aborted on Mon Nov 26 09:50:15 2001 +*** JOE was aborted because the terminal closed + +*** File '(Unnamed)' +BBSNAME diff --git a/util/LocalVars.pm.sample b/util/LocalVars.pm.sample new file mode 100644 index 00000000..67157009 --- /dev/null +++ b/util/LocalVars.pm.sample @@ -0,0 +1,22 @@ +#!/usr/bin/perl +package LocalVars; +require Exporter; +@ISA = qw/Exporter/; +@EXPORT = qw/ + $hostname $FQDN $SMTPSERVER + $BBSHOME $JOBSPOOL $TMP + $TAR/; + +# host +$hostname = 'ptt'; +$FQDN = 'ptt.csie.ntu.edu.tw'; +$SMTPSERVER = 'ptt2.csie.ntu.edu.tw'; + +# dir +$BBSHOME = '/home/bbs'; +$JOBSPOOL = "$BBSHOME/jobspool"; +$TMP = '/tmp'; + +# program +$TAR = '/bin/tar'; + diff --git a/util/Makefile b/util/Makefile new file mode 100644 index 00000000..eeacad38 --- /dev/null +++ b/util/Makefile @@ -0,0 +1,167 @@ +# $Id: Makefile,v 1.1 2002/03/07 15:13:45 in2 Exp $ + +BBSHOME?=$(HOME) +OSTYPE=linux + +# FreeBSD +CC_FreeBSD= gcc +CFLAGS_FreeBSD= -pipe -Wall -g -O3 -DHAVE_SETPROCTITLE -DBBSHOME='"$(BBSHOME)"' -I../include +LIBS_FreeBSD= +LIBMAIL_FreeBSD=-lutil +LIBCHAT_FreeBSD= + +# Linux +CC_linux= gcc +CFLAGS_linux= -pipe -Wall -g -O3 -DHAVE_DES_CRYPT -DBBSHOME='"$(BBSHOME)"' -I../include +LIBS_linux= -lresolv +LIBMAIL_linux= +LIBCHAT_linux= -lcrypt + +CC= $(CC_$(OSTYPE)) +CFLAGS= $(CFLAGS_$(OSTYPE)) +LDFLAGS=$(LDFLAGS_$(OSTYPE)) +LIBMAIL=$(LIBMAIL_$(OSTYPE)) +LIBCHAT=$(LIBCHAT_$(OSTYPE)) + +OBJS= util_cache.o util_record.o util_passwd.o + +CPROGS= bbsmail BM_money post account birth deluserfile expire mandex\ + horoscope openvice parse_news openticket topusr yearsold uhash_loader\ + poststat showboard antispam countalldice webgrep bbsrf\ + initbbs outmail xchatd userlist tunepasswd buildir reaper shmsweep\ + merge_passwd merge_board inndBM buildAnnounce rmuid cpdeadbrd \ + toplazyBM jungo toplazyBBM daymandex + +PROGS= $(CPROGS) BM_money.sh backpasswd.sh mailog.sh opendice.sh\ + openticket.sh stock.sh topsong.sh weather.sh stock.perl weather.perl\ + toplazyBM.sh toplazyBBM.sh dailybackup.pl tarqueue.pl waterball.pl + +all: $(PROGS) + +bbsmail: bbsmail.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +BM_money: BM_money.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +post: post.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +jungo: jungo.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +account: account.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +birth: birth.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +deluserfile: deluserfile.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +expire: expire.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +mandex: mandex.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +daymandex: daymandex.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +rmuid: rmuid.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +cpdeadbrd: cpdeadbrd.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +horoscope: horoscope.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +openvice: openvice.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +parse_news: parse_news.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +openticket: openticket.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +topusr: topusr.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +yearsold: yearsold.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +xchatd: xchatd.c $(OBJS) descrypt.c + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) descrypt.c $(LIBCHAT) + +toplazyBM: toplazyBM.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +toplazyBBM: toplazyBBM.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +smtest: smtest.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +reaper: reaper.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +buildAnnounce: buildAnnounce.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +inndBM: inndBM.c $(OBJS) + $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) + +shmsweep: shmsweep.c + $(CC) $(CFLAGS) -o $@ $@.c + +uhash_loader: uhash_loader.c + $(CC) $(CFLAGS) -o $@ $@.c + +showboard: showboard.c + $(CC) $(CFLAGS) -o $@ $@.c + +antispam: antispam.c + $(CC) $(CFLAGS) -o $@ $@.c + +countalldice: countalldice.c + $(CC) $(CFLAGS) -o $@ $@.c + +webgrep: webgrep.c + $(CC) $(CFLAGS) -o $@ $@.c + +bbsrf: bbsrf.c + $(CC) $(CFLAGS) -o $@ $@.c + +initbbs: initbbs.c + $(CC) $(CFLAGS) -o $@ $@.c + +outmail: outmail.c + $(CC) $(CFLAGS) -o $@ $@.c $(LIBMAIL) + +userlist: userlist.c + $(CC) $(CFLAGS) -o $@ $@.c + +tunepasswd: tunepasswd.c + $(CC) $(CFLAGS) -o $@ $@.c + +buildir: buildir.c + $(CC) $(CFLAGS) -o $@ $@.c + +merge_passwd: merge_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c + +merge_board : merge_board.c + $(CC) $(CFLAGS) -o $@ $@.c + +bbsctl: bbsctl.c + $(CC) $(CFLAGS) -o $@ $@.c + +install: $(PROGS) + install -d $(BBSHOME)/bin/ + install -c -m 755 $(PROGS) $(BBSHOME)/bin/ + chmod 4755 $(BBSHOME)/bin/post + +clean: + rm -f *.o $(CPROGS) diff --git a/util/Makefile.save b/util/Makefile.save new file mode 100644 index 00000000..2d0651b1 --- /dev/null +++ b/util/Makefile.save @@ -0,0 +1,152 @@ +# $Id: Makefile.save,v 1.1 2002/03/07 15:13:45 in2 Exp $ + +BBSHOME?=$(HOME) +OSTYPE=linux + +# FreeBSD +CC_FreeBSD= gcc +CFLAGS_FreeBSD= -pipe -Wall -g -O3 -DHAVE_SETPROCTITLE -DBBSHOME='"$(BBSHOME)"' -I../include +LIBS_FreeBSD= +LIBMAIL_FreeBSD=-lutil +LIBCHAT_FreeBSD= + +# Linux +CC_linux= gcc +CFLAGS_linux= -pipe -Wall -g -O3 -DHAVE_DES_CRYPT -DBBSHOME='"$(BBSHOME)"' -I../include +LIBS_linux= -lresolv +LIBMAIL_linux= +LIBCHAT_linux= -lcrypt + +CC= $(CC_$(OSTYPE)) +CFLAGS= $(CFLAGS_$(OSTYPE)) +LDFLAGS=$(LDFLAGS_$(OSTYPE)) +LIBMAIL=$(LIBMAIL_$(OSTYPE)) +LIBCHAT=$(LIBCHAT_$(OSTYPE)) + +CPROGS= bbsmail BM_money post account birth deluserfile expire mandex\ + horoscope openvice parse_news openticket topusr yearsold uhash_loader\ + poststat showboard antispam countalldice webgrep bbsrf\ + initbbs outmail xchatd userlist tunepasswd buildir reaper shmsweep\ + merge_passwd merge_board inndBM buildAnnounce cpdeadbrd toplazyBM\ + jungo +PROGS= $(CPROGS) BM_money.sh backpasswd.sh mailog.sh opendice.sh\ + openticket.sh stock.sh topsong.sh weather.sh stock.perl weather.perl\ + cvslog.sh toplazyBM.sh + +all: $(PROGS) + +bbsmail: bbsmail.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +BM_money: BM_money.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +post: post.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +account: account.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +birth: birth.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +deluserfile: deluserfile.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +expire: expire.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +mandex: mandex.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +cpdeadbrd: cpdeadbrd.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +horoscope: horoscope.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +openvice: openvice.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +parse_news: parse_news.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +openticket: openticket.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +topusr: topusr.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +yearsold: yearsold.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +xchatd: xchatd.c util_cache.c util_record.c util_passwd.c descrypt.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c descrypt.c $(LIBCHAT) + +toplazyBM: toplazyBM.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +jungo: jungo.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +smtest: smtest.c util_cache.c util_record.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c + +reaper: reaper.c util_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c util_passwd.c util_cache.c util_passwd.c + +buildAnnounce: buildAnnounce.c + $(CC) $(CFLAGS) -o $@ $@.c util_record.c util_cache.c util_passwd.c + +inndBM: inndBM.c + $(CC) $(CFLAGS) -o $@ $@.c util_record.c util_cache.c util_passwd.c + +shmsweep: shmsweep.c + $(CC) $(CFLAGS) -o $@ $@.c + +uhash_loader: uhash_loader.c + $(CC) $(CFLAGS) -o $@ $@.c + +showboard: showboard.c + $(CC) $(CFLAGS) -o $@ $@.c + +antispam: antispam.c + $(CC) $(CFLAGS) -o $@ $@.c + +countalldice: countalldice.c + $(CC) $(CFLAGS) -o $@ $@.c + +webgrep: webgrep.c + $(CC) $(CFLAGS) -o $@ $@.c + +bbsrf: bbsrf.c + $(CC) $(CFLAGS) -o $@ $@.c + +initbbs: initbbs.c + $(CC) $(CFLAGS) -o $@ $@.c + +outmail: outmail.c + $(CC) $(CFLAGS) -o $@ $@.c $(LIBMAIL) + +userlist: userlist.c + $(CC) $(CFLAGS) -o $@ $@.c + +tunepasswd: tunepasswd.c + $(CC) $(CFLAGS) -o $@ $@.c + +buildir: buildir.c + $(CC) $(CFLAGS) -o $@ $@.c + +merge_passwd: merge_passwd.c + $(CC) $(CFLAGS) -o $@ $@.c + +merge_board : merge_board.c + $(CC) $(CFLAGS) -o $@ $@.c + +install: $(PROGS) + install -d $(BBSHOME)/bin/ + install -c -m 755 $(PROGS) $(BBSHOME)/bin/ + chmod 4755 $(BBSHOME)/bin/post + +clean: + rm -f $(CPROGS) diff --git a/util/a.out b/util/a.out Binary files differnew file mode 100644 index 00000000..f4032dc4 --- /dev/null +++ b/util/a.out diff --git a/util/account.c b/util/account.c new file mode 100644 index 00000000..e4166092 --- /dev/null +++ b/util/account.c @@ -0,0 +1,414 @@ +/* $Id: account.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#define MAX_LINE 16 +#define ADJUST_M 6 /* adjust back 5 minutes */ + +extern struct pttcache_t *ptt; + +void + reset_garbage() +{ + if (ptt == NULL) + { + ptt = attach_shm(PTTSHM_KEY, sizeof(*ptt)); + if (ptt->touchtime == 0) + ptt->touchtime = 1; + } + +/* ¤£¾ãÓreload? + for(n=0;n<=ptt->max_film;n++) + printf("\n**%d**\n %s \n",n,ptt->notes[n]); + */ + ptt->uptime = 0; + reload_pttcache(); + + printf("\n°ÊºA¬ÝªO¼Æ[%d]\n", ptt->max_film); +/* + for(n=0; n<MAX_MOVIE_SECTION; n++) + printf("sec%d=> °_ÂI:%d ¤U¦¸n´«ªº:%d\n ",n,ptt->n_notes[n], + ptt->next_refresh[n]); + printf("\n"); +*/ +} + +void +keeplog(fpath, board, title) + char *fpath; + char *board; + char *title; +{ + fileheader_t fhdr; + int bid; + char genbuf[256], buf[256]; + + if (!board) + board = "Record"; + + + sprintf(genbuf, "boards/%s", board); + stampfile(genbuf, &fhdr); + sprintf(buf, "mv %s %s", fpath, genbuf); + system(buf); +/* + printf("keep record:[%s][%s][%s][%s]\n",fpath, board, title,genbuf); +*/ + strcpy(fhdr.title, title); + strcpy(fhdr.owner, "[¾ú¥v¦Ñ®v]"); + sprintf(genbuf, "boards/%s/.DIR", board); + append_record(genbuf, &fhdr, sizeof(fhdr)); + if((bid = getbnum(board)) > 0)touchbtotal(bid); + +} + + +static void +my_outs(fp, buf, mode) + FILE *fp; + char buf[], mode; +{ + static char state = '0'; + + if (state != mode) + fprintf(fp, "[3%cm", state = mode); + if (buf[0]) + { + fprintf(fp, buf); + buf[0] = 0; + } +} + + +void gzip(source, target, stamp) + char *source, *target, *stamp; +{ + char buf[128]; + sprintf(buf, "gzip -f9n adm/%s%s", target, stamp); + rename(source, &buf[14]); + system(buf); +} + +extern struct fromcache_t *fcache; +extern uhash_t *uhash; + +int main() { + int hour, max, item, total, i, j, mo, da, max_user = 0, max_login = 0, + max_reg = 0, mahour = 0, k; + char *act_file = ".act"; + char *log_file = "usies"; + char buf[256], buf1[256], *p; + FILE *fp, *fp1; + int act[27]; /* ¦¸¼Æ/²Öp®É¶¡/pointer */ + time_t now; + struct tm *ptime; + + now = time(NULL) - ADJUST_M * 60; /* back to ancent */ + ptime = localtime(&now); + + memset(act, 0, sizeof(act)); + printf("¦¸¼Æ/²Öp®É¶¡\n"); + if ((ptime->tm_hour != 0) && (fp = fopen(act_file, "r"))) + { + fread(act, sizeof(act), 1, fp); + fclose(fp); + } + if ((fp = fopen(log_file, "r")) == NULL) + { + printf("cann't open usies\n"); + return 1; + } + if (act[26]) + fseek(fp, act[26], 0); + while (fgets(buf, 256, fp)) + { + buf[11+2]=0; + hour = atoi(buf + 11); + if (hour < 0 || hour > 23) + { + continue; + } +//"09/06/1999 17:44:58 Mon " +// 012345678901234567890123 + if (strstr(buf + 20, "ENTER")) + { + act[hour]++; + continue; + } + if ((p = (char *) strstr(buf + 40, "Stay:"))) + { + if((hour = atoi(p + 5))) { + act[24] += hour; + act[25]++; + } + continue; + } + } + act[26] = ftell(fp); + fclose(fp); + for (i = max = total = 0; i < 24; i++) + { + total += act[i]; + if (act[i] > max) + { + max_user = max = act[i]; + mahour = i; + } + } + item = max / MAX_LINE + 1; + + if (!ptime->tm_hour) + { + keeplog("etc/today", "Record", "¤W¯¸¤H¦¸²Îp"); + keeplog("etc/money", "Security", "¥»¤éª÷¿ú©¹¨Ó°O¿ý"); + keeplog("etc/illegal_money", "Security", "¥»¤é¹HªkÁÈ¿ú°O¿ý"); + keeplog("etc/chicken", "Record", "Âû³õ³ø§i"); + } + + printf("¤W¯¸¤H¦¸²Îp\n"); + if ((fp = fopen("etc/today", "w")) == NULL) + { + printf("cann't open etc/today\n"); + return 1; + } + fprintf(fp, "\t\t\t[1;33;46m ¨C¤p®É¤W¯¸¤H¦¸²Îp [%02d/%02d/%02d] [40m\n\n", ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday); + for (i = MAX_LINE + 1; i > 0; i--) + { + strcpy(buf, " "); + for (j = 0; j < 24; j++) + { + max = item * i; + hour = act[j]; + if (hour && (max > hour) && (max - item <= hour)) + { + my_outs(fp, buf, '3'); + fprintf(fp, "%-3d", hour / 10); + } + else if (max <= hour) + { + my_outs(fp, buf, '4'); + fprintf(fp, "¢i "); + } + else + strcat(buf, " "); + } + fprintf(fp, "\n"); + } + fprintf(fp, " [32m" + "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23\n\n" + "\t [34m³æ¦ì: [37m10[34m ¤H"); + fprintf(fp, " Á`¦@¤W¯¸¤H¦¸¡G[37m%-7d[34m¥§¡¨Ï¥Î¤H¼Æ¡G[37m%d\n", total, total / 24); + fclose(fp); + + if((fp = fopen(act_file, "w"))) { + fwrite(act, sizeof(act), 1, fp); + fclose(fp); + } + +/* -------------------------------------------------------------- */ + + sprintf(buf, "-%02d%02d%02d", + ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday); + + now += ADJUST_M * 60; /* back to future */ + + + printf("¾ú¥v¨Æ¥ó³B²z\n"); +/* Ptt ¾ú¥v¨Æ¥ó³B²z */ + if((fp = fopen("etc/history.data", "r"))) { /*³Ì¦h¦P®É¤W½u */ + if (fscanf(fp, "%d %d %d %d", &max_login, &max, &max_reg, &k)) + { + int a; + resolve_fcache(); + printf("¦¹®É¬q³Ì¦h¦P®É¤W½u:%d ¹L¥h:%d\n", a = fcache->max_user, k); + fclose(fp); + if (a > k) + { + ptime = localtime(&fcache->max_time); + if((fp1 = fopen("etc/history", "a"))) + { + fprintf(fp1, + "¡· ¡i%02d/%02d/%02d %02d:%02d¡j" + "[32m¦P®É¦b§{¤º¤H¼Æ[mº¦¸¹F¨ì [1;36m%d[m ¤H¦¸\n", + ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, + ptime->tm_hour, ptime->tm_min, a); + fclose(fp1); + } + if((fp = fopen("etc/history.data", "w"))) + { + fprintf(fp, "%d %d %d %d", max_login, max, max_reg, a); + fclose(fp); + } + } + } + else + fclose(fp); + } + ptime = localtime(&now); + + if (ptime->tm_hour) + { + /* rotate one line in today_is */ + puts("¦hÓ¸`¤é³B²z"); + if((fp1 = fopen("etc/today_is", "r"))) { + char tod[100][20]; + + i = 0; + while(i < 100 && fgets(tod[i], sizeof(tod[0]), fp1)) + i++; + fclose(fp1); + + fp1 = fopen("etc/today_is", "w"); + for(j = 0; j < i; j++) + fputs(tod[j + 1 < i ? j + 1 : 0], fp1); + fclose(fp1); + } + } + + + if (!ptime->tm_hour) + { + keeplog(".note", "Record", "¤ß±¡¯d¨¥ª©"); + system("/bin/cp etc/today etc/yesterday"); +/* system("rm -f note.dat"); */ +/* Ptt */ + sprintf(buf1, "[¤½¦w³ø§i] ¨Ï¥ÎªÌ¤W½uºÊ±± [%02d/%02d:%02d]" + ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour); + keeplog("usies", "Security", buf1); + printf("[¤½¦w³ø§i] ¨Ï¥ÎªÌ¤W½uºÊ±±\n"); + gzip(log_file, "usies", buf); + printf("À£ÁY¨Ï¥ÎªÌ¤W½uºÊ±±\n"); +/* Ptt ¾ú¥v¨Æ¥ó³B²z */ + now = time(NULL) - ADJUST_M * 60; /* back to ancent */ + ptime = localtime(&now); + + attach_uhash(); + if((fp = fopen("etc/history.data", "r"))) + { /* ³æ¤é³Ì¦h¦¸¤H¦¸,¦P®É¤W½u,µù¥U */ + if (fscanf(fp, "%d %d %d %d", &max_login, &max, &max_reg, &k)) + { + fp1 = fopen("etc/history", "r+"); + fseek(fp1, 0, 2); + if (max_user > max) + { + fprintf(fp1, "¡º ¡i%02d/%02d/%02d %02d¡j " + "[1;32m³æ¤@¤p®É¤W½u¤H¦¸[mº¦¸¹F¨ì [1;35m%d[m ¤H¦¸ \n" + ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, mahour, max_user); + max = max_user; + } + if (total > max_login) + { + fprintf(fp1, "¡» ¡i%02d/%02d/%02d¡j " + "[1;32m³æ¤é¤W½u¤H¦¸[mº¦¸¹F¨ì[1;33m %d[m ¤H¦¸ \n" + ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, total); + max_login = total; + } + + if (uhash->number > max_reg + max_reg / 10) + { + fprintf(fp1, "¡¹ ¡i%02d/%02d/%02d¡j " + "[1;32mÁ`µù¥U¤H¼Æ[m´£¤É¨ì[1;31m %d[m ¤H \n" + ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, uhash->number); + max_reg = uhash->number; + } + + fclose(fp1); + } + fclose(fp); + fp = fopen("etc/history.data", "w"); + fprintf(fp, "%d %d %d %d", max_login, max, max_reg, k); + fclose(fp); + } + now += ADJUST_M * 60; /* back to future */ + ptime = localtime(&now); + + /* Ptt ¸`¤é³B²z */ + printf("¸`¤é³B²z\n"); + if((fp1 = fopen("etc/today_is", "w"))) { + i = 0; + if((fp = fopen("etc/feast", "r"))) { + while(fgets(buf1, sizeof(buf1), fp)) { + if(buf[0] != '#' && + sscanf(buf1, "%d %d ", &mo, &da) == 2) { + if(ptime->tm_mday == da && ptime->tm_mon + 1 == mo) { + i = 1; + fprintf(fp1, "%-14.14s", &buf1[6]); + } + } + } + fclose(fp); + } + printf("¸`¤é³B²z1\n"); + if(i == 0) { + if((fp = fopen("etc/today_boring", "r"))) { + while(fgets(buf1, sizeof(buf1), fp)) + if(strlen(buf) > 3) + fprintf(fp1, "%s", buf1); + fclose(fp); + } else + fprintf(fp1, "¥»¤é¸`¤é¼x¨D¤¤"); + } + fclose(fp1); + } + + /* Ptt Åwªïµe±³B²z */ + printf("Åwªïµe±³B²z\n"); + + if((fp = fopen("etc/Welcome.date", "r"))) + { + char temp[50]; + while (fscanf(fp, "%d %d %s\n", &mo, &da, buf1) != EOF) + { + if (ptime->tm_mday == da && ptime->tm_mon + 1 == mo) + { + strcpy(temp, buf1); + sprintf(buf1, "cp -f etc/Welcomes/%s etc/Welcome", temp); + system(buf1); + break; + } + } + fclose(fp); + } + printf("Åwªïµe±³B²z\n"); + if (ptime->tm_wday == 0) + { + keeplog("etc/week", "Record", "¥»¶g¼öªù¸ÜÃD"); + + gzip("bbslog", "bntplink", buf); + gzip("innd/bbslog", "innbbsd", buf); + gzip("etc/mailog", "mailog", buf); + } + + if (ptime->tm_mday == 1) + keeplog("etc/month", "Record", "¥»¤ë¼öªù¸ÜÃD"); + + if (ptime->tm_yday == 1) + keeplog("etc/year", "Record", "¦~«×¼öªù¸ÜÃD"); + } + else if (ptime->tm_hour == 3 && ptime->tm_wday == 6) + { + char *fn1 = "tmp"; + char *fn2 = "suicide"; + rename(fn1, fn2); + mkdir(fn1, 0755); + sprintf(buf, "tar cfz adm/%s-%02d%02d%02d.tgz %s", + fn2, ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday, fn2); + system(buf); + sprintf(buf, "/bin/rm -fr %s", fn2); + system(buf); + } +/* Ptt reset Ptt's share memory */ + printf("«³]Pttcache »Pfcache\n"); + + fcache->uptime = 0; + resolve_fcache(); + reset_garbage(); + return 0; +} diff --git a/util/antispam.c b/util/antispam.c new file mode 100644 index 00000000..f7b77569 --- /dev/null +++ b/util/antispam.c @@ -0,0 +1,122 @@ +/* $Id: antispam.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ +/* §ì¼s§i«Hªºµ{¦¡ */ +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" + +#define WINDOW 100 /* ¤@¦¸window¦h¤ÖÓserver */ +#define LEVEL 21 /* Y´X¦¸«´_´Nºâ¼s§i«H */ + +#define mailog BBSHOME "/etc/mailog" +#define spamlog BBSHOME "/etc/spam" + +typedef struct sendinfo +{ + char time[18]; + char from[50]; + char userid[20]; + int count; +} +sendinfo; + +int + main() +{ + char buf[200], *from, *userid; + int num = -1, numb = -1, n, nb; + FILE *fp = fopen(mailog, "r"), *fo; + sendinfo data[WINDOW]; + sendinfo bad[WINDOW]; + + unlink(spamlog); + fo = fopen(spamlog, "a"); + memset(data, 0, sizeof(data)); + memset(bad, 0, sizeof(bad)); + + if (!fp || !fo) + return 0; + + while (fgets(buf, 200, fp)) + { + strtok(buf, "\r\n"); + from = strchr(buf, '>') + 2; + userid = strstr(buf, " =>"); + + if (!from || !userid) + continue; + + *userid = 0; + userid += 4; + + if (strstr(from, "MAILER-DAEMON") + || strstr(from, userid)) + continue; /* °h«H³qª¾¤£ºÞ */ + /* ¬O§_¤w¬Obadhost */ + + for (nb = 0; nb < WINDOW && bad[nb].from[0]; nb++) + if (!strcmp(bad[nb].from, from)) + break; + + if (nb < WINDOW && bad[nb].from[0]) + { + bad[nb].count++; + continue; + } + + /* ²¬d¹L¥h°O¿ý */ + + for (n = 0; n < WINDOW && data[n].from[0]; n++) + if (!strcmp(data[n].from, from)) + break; + + if (n < WINDOW && data[n].from[0]) + { + if (!strncmp(data[n].userid, userid, 20)) + continue; + /* Â൹¦P¤@Ó¤H´N¤£ºÞ */ + strncpy(data[n].userid, userid, 20); + if (++data[n].count >= LEVEL) + { + /* Åܦ¨bad ²¾data¨ìbad ªÅ¯Ê¥Ñ«á¤@µ§¸ê®Æ¸É¤W */ + if (nb >= WINDOW) + { + numb = (numb + 1) % WINDOW; + nb = numb; + fprintf(fo, "%s %s «ÂбH %d ¦¸\n", + bad[nb].time, bad[nb].from, bad[nb].count); +/* printf(" %s send %d times\n", + bad[nb].from, bad[nb].count); */ + } + memcpy(&bad[nb], &data[n], sizeof(sendinfo)); + memcpy(&data[n], &data[n + 1], sizeof(sendinfo) * (WINDOW - n - 1)); + if (num > n) + num--; + } + } + else + { + if (n >= WINDOW) + { + num = (num + 1) % WINDOW; + n = num; + } +/* printf("[%s] to [%s]\n", from, userid); */ + buf[17] = 0; + strncpy(data[n].time, buf, 17); + strncpy(data[n].from, from, 50); + strncpy(data[n].userid, userid, 20); + } + } + + for (nb = 0; nb < WINDOW && bad[nb].from[0]; nb++) + { + fprintf(fo, "%s %s «ÂбH %d ¦¸\n", bad[nb].time, + bad[nb].from, bad[nb].count); +/* printf(" %s send %d times\n", bad[nb].from, bad[nb].count); */ + } + fclose(fp); + fclose(fo); + return 0; +} diff --git a/util/backpasswd.sh b/util/backpasswd.sh new file mode 100644 index 00000000..5ec11abd --- /dev/null +++ b/util/backpasswd.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# $Id: backpasswd.sh,v 1.1 2002/03/07 15:13:45 in2 Exp $ + +mv PASSWDS.NEW5 PASSWDS.NEW6 +mv PASSWDS.NEW4 PASSWDS.NEW5 +mv PASSWDS.NEW3 PASSWDS.NEW4 +mv PASSWDS.NEW2 PASSWDS.NEW3 +mv PASSWDS.NEW1 PASSWDS.NEW2 +mv PASSWDS.NEW PASSWDS.NEW1 +cp .PASSWDS PASSWDS.NEW + diff --git a/util/bbsctl.c b/util/bbsctl.c new file mode 100644 index 00000000..bf66df35 --- /dev/null +++ b/util/bbsctl.c @@ -0,0 +1,63 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +void usage(void) +{ + printf("usage: bbsctl [start|stop|restart]\n"); + exit(0); +} + +void startbbs(void) +{ + if( setuid(0) < 0 ){ + perror("setuid(0)"); + exit(1); + } + puts("starting mbbsd: 23"); system("/home/bbs/bin/mbbsd 23"); + puts("starting mbbsd:3000"); system("/home/bbs/bin/mbbsd 3000"); + puts("starting mbbsd:3001"); system("/home/bbs/bin/mbbsd 3001"); + puts("starting mbbsd:3002"); system("/home/bbs/bin/mbbsd 3002"); + puts("starting mbbsd:3003"); system("/home/bbs/bin/mbbsd 3003"); + puts("starting mbbsd:3004"); system("/home/bbs/bin/mbbsd 3004"); + puts("starting mbbsd:3005"); system("/home/bbs/bin/mbbsd 3005"); + puts("starting mbbsd:3006"); system("/home/bbs/bin/mbbsd 3006"); + puts("starting mbbsd:3007"); system("/home/bbs/bin/mbbsd 3007"); + puts("starting mbbsd:3008"); system("/home/bbs/bin/mbbsd 3008"); + puts("starting mbbsd:3009"); system("/home/bbs/bin/mbbsd 3009"); + puts("starting mbbsd:3010"); system("/home/bbs/bin/mbbsd 3010"); +} + +void stopbbs(void) +{ + char buf[1024]; + int pid; + FILE *fp = popen("/bin/ps -ax | /usr/bin/grep mbbsd | " + "/usr/bin/grep listen", "r"); + while( fgets(buf, sizeof(buf), fp) != NULL ){ + sscanf(buf, "%d", &pid); + printf("stopping %d\n", pid); + kill(pid, 1); + } +} + +void restartbbs(void) +{ + stopbbs(); + startbbs(); +} + +int main(int argc, char **argv) +{ + if( argc == 1 ) + usage(); + if( strcmp(argv[1], "start") == 0 ) + startbbs(); + else if( strcmp(argv[1], "stop") == 0 ) + stopbbs(); + else if( strcmp(argv[1], "restart") == 0 ) + restartbbs(); + return 0; +} diff --git a/util/bbsmail.c b/util/bbsmail.c new file mode 100644 index 00000000..48f74c63 --- /dev/null +++ b/util/bbsmail.c @@ -0,0 +1,239 @@ +/* $Id: bbsmail.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ + +#define _BBS_UTIL_C_ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" + +#define LOG_FILE (BBSHOME "/etc/mailog") + +#ifdef HMM_USE_ANTI_SPAM +extern char *notitle[], *nofrom[], *nocont[]; +#endif + +extern userec_t xuser; + +int mailalertuid(int tuid) +{ + userinfo_t *uentp=NULL; + if(tuid>0 && (uentp = (userinfo_t *)search_ulist(tuid)) ) + uentp->mailalert=1; + return 0; +} + +void +mailog(msg) + char *msg; +{ + FILE *fp; + + if ((fp = fopen(LOG_FILE, "a"))) + { + time_t now; + struct tm *p; + + time(&now); + p = localtime(&now); + fprintf(fp, "%02d/%02d/%02d %02d:%02d:%02d <bbsmail> %s\n", + p->tm_year % 100, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, + msg); + fclose(fp); + } +} + + +int +mail2bbs(userid) + char *userid; +{ + int uid; + fileheader_t mymail; + char genbuf[256], title[80], sender[80], filename[80], *ip, *ptr; + time_t tmp_time; + struct stat st; + FILE *fout; +/* check if the userid is in our bbs now */ + if (!(uid=getuser(userid)) ) + { + sprintf(genbuf, "BBS user <%s> not existed", userid); + puts(genbuf); + mailog(genbuf); + return -1;//EX_NOUSER; + } + + if(xuser.userlevel&PERM_NOOUTMAIL) + return -1; + + sprintf(filename, BBSHOME "/home/%c/%s", userid[0], userid); + + if (stat(filename, &st) == -1) + { + if (mkdir(filename, 0755) == -1) + { + printf("mail box create error %s \n", filename); + return -1; + } + } + else if (!(st.st_mode & S_IFDIR)) + { + printf("mail box error\n"); + return -1; + } + + // printf("dir: %s\n", filename); + +/* allocate a file for the new mail */ + + stampfile(filename, &mymail); + // printf("file: %s\n", filename); + +/* copy the stdin to the specified file */ + +/* parse header */ + + while (fgets(genbuf, 255, stdin)) + { + if (!strncmp(genbuf, "From", 4)) + { + if ((ip = strchr(genbuf, '<')) && (ptr = strrchr(ip, '>'))) + { + *ptr = '\0'; + if (ip[-1] == ' ') + ip[-1] = '\0'; + ptr = (char *) strchr(genbuf, ' '); + while (*ptr == ' ') ptr++; + sprintf(sender, "%s (%s)", ip + 1, ptr); + } + else + { + strtok(genbuf, " \t\n\r"); + ptr= strtok(NULL, " \t\n\r"); + if(ptr) + strcpy(sender, ptr); + } + continue; + } + if (!strncmp(genbuf, "Subject: ", 9)) + { + strcpy(title, genbuf + 9); + continue; + } + if (genbuf[0] == '\n') + break; + } + + if ((ptr = strchr(sender, '\n'))) + *ptr = '\0'; + + if ((ptr = strchr(title, '\n'))) + *ptr = '\0'; + + if (strchr(sender, '@') == NULL) /* ¥Ñ local host ±H«H */ + { + strcat(sender, "@" MYHOSTNAME); + } + + time(&tmp_time); + +#ifdef HMM_USE_ANTI_SPAM + for (n = 0; notitle[n]; n++) + if (strstr(title, notitle[n])) + { + sprintf(genbuf, "Title <%s> not accepted", title); + puts(genbuf); + mailog(genbuf); + return -1; + } + for (n = 0; nofrom[n]; n++) + if (strstr(sender, nofrom[n])) + { + sprintf(genbuf, "From <%s> not accepted", sender); + puts(genbuf); + mailog(genbuf); + return -1; + } +#endif + + if ((fout = fopen(filename, "w")) == NULL) + { + printf("Cannot open %s\n", filename); + return -1; + } + + if (!title[0]) + sprintf(title, "¨Ó¦Û %.64s", sender); + title[TTLEN] = 0; + fprintf(fout, "§@ªÌ: %s\n¼ÐÃD: %s\n®É¶¡: %s\n", + sender, title, ctime(&tmp_time)); + + while (fgets(genbuf, 255, stdin)) + { +#ifdef HMM_USE_ANTI_SPAM + for (n = 0; nocont[n]; n++) + if (strstr(genbuf, nocont[n])) + { + fclose(fout); + unlink(filename); + sprintf(genbuf, "Content <%s> not accepted", nocont[n]); + puts(genbuf); + mailog(genbuf); + return -1; + } +#endif + fputs(genbuf, fout); + } + fclose(fout); + + sprintf(genbuf, "%s => %s", sender, userid); + mailog(genbuf); + +/* append the record to the MAIL control file */ + + strcpy(mymail.title, title); + + if (strtok(sender, " .@\t\n\r")) + strcat(sender, "."); + sender[IDLEN + 1] = '\0'; + strcpy(mymail.owner, sender); + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", userid[0], userid); + mailalertuid(uid); + return append_record(genbuf, &mymail, sizeof(mymail)); +} + + +int +main(int argc, char* argv[]) +{ + char receiver[256]; + +/* argv[1] is userid in bbs */ + + if (argc < 2) + { + printf("Usage:\t%s <bbs_uid>\n", argv[0]); + exit(-1); + } + (void) setgid(BBSGID); + (void) setuid(BBSUID); + + if(passwd_mmap()) exit(-1); + strcpy(receiver, argv[1]); + + strtok(receiver,"."); + if (mail2bbs(receiver)) + { + /* eat mail queue */ + while (fgets(receiver, sizeof(receiver), stdin)) ; + } + return 0; +} diff --git a/util/bbsrf.c b/util/bbsrf.c new file mode 100644 index 00000000..66f6cee0 --- /dev/null +++ b/util/bbsrf.c @@ -0,0 +1,148 @@ +/* $Id: bbsrf.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/param.h> +#include <sys/types.h> +#include <utmp.h> +#include <pwd.h> +#include <syslog.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/uio.h> +#include "config.h" + +/* fill the hid with from hostname */ +void gethid(char *hid, char *tty) +{ + int fd; + char *tp; + struct utmp data; + + gethostname(hid, MAXHOSTNAMELEN); + hid[MAXHOSTNAMELEN] = '\0'; + tp = strrchr(tty, '/') + 1; + if (tp && strlen(tp) == 5) + { + fd = open(_PATH_UTMP, O_RDONLY); + if (fd < 0) + syslog(LOG_ERR, "%s: %m", _PATH_UTMP); + else + { + while (read(fd, &data, sizeof(data)) == sizeof(data)) + if (strcmp(data.ut_line, tp) == 0) + { + if (data.ut_host[0]) { +#if MAXHOSTNAMELEN < UT_HOSTSIZE + strncpy(hid, data.ut_host, MAXHOSTNAMELEN); + hid[MAXHOSTNAMELEN] = '\0'; +#else + strncpy(hid, data.ut_host, UT_HOSTSIZE); + hid[UT_HOSTSIZE] = '\0'; +#endif + } + break; + } + close(fd); + } + } +} + +/* + get system load averages + return 0 if success; otherwise, return -1. + */ +int getload(double load[3]) +{ + int rtv = -1; +#if defined(linux) + FILE *fp; + + fp = fopen(LOAD_FILE, "r"); + if (fp) + { + if (fscanf(fp, "%lf %lf %lf", &load[0], &load[1], &load[2]) == 3) + rtv = 0; + fclose(fp); + } +#elif defined(__FreeBSD__) + if (getloadavg(load, 3) == 3) + rtv = 0; +#endif + return rtv; +} + +/* + show ban file + if filename exist, print it out, sleep 1 second, and return 0; + otherwise, return -1. + */ +int showbanfile(char *filename) +{ + FILE *fp; + char buf[256]; + + fp = fopen(filename, "r"); + if (fp) + { + while (fgets(buf, sizeof(buf), fp)) + fputs(buf, stdout); + printf("\n=============================" + "=============================\n"); + fclose(fp); + sleep(1); + } + return fp ? 0 : -1; +} + +int main(void) +{ + int uid, rtv = 0; + char *tty, ttybuf[32], hid[MAXHOSTNAMELEN + 1]; + + openlog("bbsrf", LOG_PID | LOG_PERROR, LOG_USER); + chdir(BBSHOME); + uid = getuid(); + + while (1) + { + if (!showbanfile(BAN_FILE)) + { + rtv = 1; + break; + } + else if (uid != BBSUID) + { + syslog(LOG_ERR, "UID DOES NOT MATCH"); + rtv = -1; + break; + } + else if (!getpwuid(uid)) + { + syslog(LOG_ERR, "YOU DONT EXIST"); + rtv = -1; + break; + } + else + { + tty = ttyname(0); + if (tty) + { + strcpy(ttybuf, tty); + gethid(hid, ttybuf); + } + else + { + strcpy(ttybuf, "notty"); + strcpy(hid, "unknown"); + } + execl(BBSPROG, "mbbsd", hid, ttybuf, NULL); + syslog(LOG_ERR, "execl(): %m"); + rtv = -1; + } + break; + } + return rtv; +} diff --git a/util/birth.c b/util/birth.c new file mode 100644 index 00000000..899bf9ee --- /dev/null +++ b/util/birth.c @@ -0,0 +1,99 @@ +/* ¹Ø¬Pµ{¦¡ 96 10/11 */ + +#include <stdio.h> +#include <sys/types.h> +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "common.h" + +#define OUTFILE BBSHOME "/etc/birth.today" + +struct userec_t cuser; + +int bad_user_id() { + register char ch; + int j; + if (strlen(cuser.userid) < 2 || !isalpha(cuser.userid[0])) + return 1; + if (cuser.numlogins == 0 || cuser.numlogins > 15000) + return 1; + if (cuser.numposts > 15000) + return 1; + for (j = 1; (ch = cuser.userid[j]); j++) + { + if (!isalnum(ch)) + return 1; + } + return 0; +} + +int Link(char *src, char *dst) { + char cmd[200]; + + if (link(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +int main(argc, argv) + int argc; + char **argv; +{ + FILE *fp1; + fileheader_t mymail; + int i, day = 0; + time_t now; + struct tm *ptime; + int j; + + now = time(NULL); /* back to ancent */ + ptime = localtime(&now); + + if(passwd_mmap()) + exit(1); + + printf("*»sªí\n"); + fp1 = fopen(OUTFILE, "w"); + + fprintf(fp1, "\n " + "[1m¡¹[35m¡¹[34m¡¹[33m¡¹[32m¡¹[31m¡¹[45;33m ¹Ø¬P¤jÆ[ " + "[40m¡¹[32m¡¹[33m¡¹[34m¡¹[35m¡¹[1m¡¹[m \n\n"); + fprintf(fp1, "[33m¡i[1;45m¥»¤é¹Ø¬P[40;33m¡j[m \n"); + for(j = 1; j <= MAX_USERS; j++) { + passwd_query(j, &cuser); + if (bad_user_id()) + continue; + if (cuser.month == ptime->tm_mon + 1) + { + if (cuser.day == ptime->tm_mday) + { + char genbuf[200]; + sprintf(genbuf, BBSHOME "/home/%c/%s", cuser.userid[0], cuser.userid); + stampfile(genbuf, &mymail); + strcpy(mymail.owner, BBSNAME); + strcpy(mymail.title, "!! ¥Í¤é§Ö¼Ö !!"); + mymail.savemode = 0; + unlink(genbuf); + Link(BBSHOME "/etc/Welcome_birth", genbuf); + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", cuser.userid[0], cuser.userid); + append_record(genbuf, &mymail, sizeof(mymail)); + if ((cuser.numlogins + cuser.numposts) < 20) + continue; + + fprintf(fp1, + " [33m[%2d/%-2d] %-14s[0m %-24s login:%-5d post:%-5d\n", + ptime->tm_mon + 1, ptime->tm_mday, cuser.userid, + cuser.username, cuser.numlogins, cuser.numposts); + } + } + } + fclose(fp1); + return 0; +} diff --git a/util/buildAnnounce.c b/util/buildAnnounce.c new file mode 100644 index 00000000..0e754f22 --- /dev/null +++ b/util/buildAnnounce.c @@ -0,0 +1,69 @@ +/* «Ø¥ß©Ò¦³¬ÝªOºëµØ°Ïªº³sµ² */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include "config.h" +#include "pttstruct.h" +#define GROUPROOT BBSHOME"/man/group" + +extern bcache_t *brdshm; +extern boardheader_t *bcache; +extern void resolve_boards(); + +void buildchilds(int level,char *path,boardheader_t *bptr) +{ + char newpath[512]; + boardheader_t *ptr; + fileheader_t item; + + if(bptr->firstchild[1]==(boardheader_t*)~0 || bptr->firstchild[1]==NULL) + return; + for(ptr =(void*) bptr->firstchild[1]; + ptr!=(boardheader_t*)~0 ;ptr=ptr->next[1]) + { + + if( + (ptr->brdattr&(BRD_BAD | BRD_GROUPBOARD | BRD_NOCOUNT | BRD_HIDE))!=0 + || + (ptr->level && !(ptr->brdattr & BRD_POSTMASK))) continue; + printf("%*.*s+-%-14s %-s \n",level*2,level*2,"| | | | | | | | |", + ptr->brdname, ptr->title); + if(ptr->brdattr & BRD_GROUPBOARD) + { + sprintf(newpath,"%s/%s",path,ptr->brdname); + mkdir(newpath,0766); + buildchilds(level+1,newpath,ptr); + } + else + { + printf("%s4\n",ptr->brdname); + sprintf(newpath,"/bin/ln -s "BBSHOME"/man/boards/%s %s/%s", + ptr->brdname,path,ptr->brdname); + system(newpath); + } + printf("%s5\n",ptr->brdname); + sprintf(newpath,"%s/.DIR",path); + strcpy(item.owner,ptr->BM); + strtok(item.owner,"/"); + strcpy(item.title,ptr->title+7); + item.savemode = 'D'; + sprintf(item.filename,ptr->brdname); + append_record(newpath, &item, sizeof(item)); + } +} + + +int main() +{ + char path[512]; + setsid(); + strcpy(path,GROUPROOT); + system("rm -rf "GROUPROOT); + mkdir(GROUPROOT,0766); + resolve_boards(); + buildchilds(0,path,&bcache[0]); + return 0; +} diff --git a/util/buildAnnounce.sh b/util/buildAnnounce.sh new file mode 100644 index 00000000..d43f420b --- /dev/null +++ b/util/buildAnnounce.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id: buildAnnounce.sh,v 1.1 2002/03/07 15:13:45 in2 Exp $ +# +bin/buildAnnounce > etc/ALLBRDLIST +bin/post Record ¥þ¯¸¬ÝªO¦Cªí [¦Û°Ê¯¸ªø] etc/ALLBRDLIST diff --git a/util/buildir.c b/util/buildir.c new file mode 100644 index 00000000..381a657d --- /dev/null +++ b/util/buildir.c @@ -0,0 +1,124 @@ +/* $Id: buildir.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <dirent.h> +#include <fcntl.h> +#include <time.h> +#include <string.h> +#include <unistd.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" + +int dirselect(struct dirent *dir) { + return strchr("MDSGH", dir->d_name[0]) && dir->d_name[1] == '.'; +} + +int mysort(const struct dirent **a,const struct dirent **b) +{ + return atoi(((*a)->d_name+2))-atoi(((*b)->d_name+2)); +} + +int main(int argc, char **argv) { + int k; + + if(argc < 2) { + fprintf(stderr, "Usage: %s <path1> [<path2> ...]\n", argv[0]); + return 1; + } + + for(k = 1; k < argc; k++) { + int fdir, count, total; + char *ptr, path[MAXPATHLEN]; + struct dirent **dirlist; + + sprintf(path, "%s/.DIR", argv[k]); + if((fdir = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { + perror(path); + continue; + } + + if((total = scandir(argv[k], &dirlist, dirselect, mysort)) == -1) { + fprintf(stderr, "scandir failed!\n"); + close(fdir); + continue; + } + + ptr = strrchr(path, '.'); + for(count = 0; count < total; count++) { + FILE *fp; + struct stat st; + + strcpy(ptr, dirlist[count]->d_name); + if(stat(path, &st) == 0 && st.st_size > 0 && + (fp = fopen(path, "r")) != NULL) { + char buf[512]; + time_t filetime; + fileheader_t fhdr; + + memset(&fhdr, 0, sizeof(fhdr)); + /* set file name */ + strcpy(fhdr.filename, dirlist[count]->d_name); + + /* set file time */ + filetime = atoi(dirlist[count]->d_name + 2); + if(filetime > 740000000) { + struct tm *ptime = localtime(&filetime); + sprintf(fhdr.date, "%2d/%02d", ptime->tm_mon + 1, + ptime->tm_mday); + } else + strcpy(fhdr.date, " "); + + /* set file mode */ + fhdr.filemode = FILE_READ; + + /* set article owner */ + fgets(buf, sizeof(buf), fp); + if(strncmp(buf, "§@ªÌ: ", 6) == 0 || + strncmp(buf, "µo«H¤H: ", 8) == 0) { + int i, j; + + for(i = 5; buf[i] != ' '; i++); + for(; buf[i] == ' '; i++); + for(j = i + 1; buf[j] != ' '; j++); + j -= i; + if(j > IDLEN + 1) + j = IDLEN + 1; + strncpy(fhdr.owner, buf + i, j); + fhdr.owner[IDLEN + 1] = '\0'; + strtok(fhdr.owner, " .@\t\n\r"); + if(strtok(NULL, " .@\t\n\r")) + strcat(fhdr.owner, "."); + + /* set article title */ + while(fgets(buf, sizeof(buf), fp)) + if(strncmp(buf, "¼ÐÃD: ", 6) == 0 || + strncmp(buf, "¼Ð ÃD: ", 8) == 0) { + for(i = 5; buf[i] != ' '; i++); + for(; buf[i] == ' '; i++); + strtok(buf + i-1, "\n"); + strncpy(fhdr.title, buf + i, TTLEN); + fhdr.title[TTLEN] = '\0'; + break; + } + } else if(strncmp(buf, "¡ó Åwªï¥úÁ{", 11) == 0) { + strcpy(fhdr.title, "·|ij°O¿ý"); + } else if(strncmp(buf, "\33[1;33;46m¡¹", 12) == 0|| + strncmp(buf, "To", 2) == 0) { + strcpy(fhdr.title, "¼ö½u°O¿ý"); + } +// if(!fhdr.title[0]) +// strcpy(fhdr.title, dirlist[count]->d_name); + fclose(fp); + write(fdir, &fhdr, sizeof(fhdr)); + } + } + close(fdir); + for(total--; total >= 0; total--) + free(dirlist[total]); + free(dirlist); + } + return 0; +} diff --git a/util/countalldice.c b/util/countalldice.c new file mode 100644 index 00000000..badd4bad --- /dev/null +++ b/util/countalldice.c @@ -0,0 +1,95 @@ +/* $Id: countalldice.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ + +/**********************************************/ +/*³oÓµ{¦¡¬O¥Î¨Ópºâ½ä»ë¤lÁȱo¿ú¸ò½ßªº¿úªºµ{¦¡ */ +/*¥Îªk´N¬Oª½±µ¥´ countalldice ´N¥i¥H°w¹ï©Ò¦³¤H */ +/*¨Ópºâ¥LÁ`¦@ÁȤF¦h¤Ö ½ß¤F¦h¤Ö............... */ +/*§@ªÌ:Heat ©ó1997/10/2 */ +/**********************************************/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" + +#define DICE_WIN BBSHOME "/etc/windice.log" +#define DICE_LOST BBSHOME "/etc/lostdice.log" + +int total = 0; + +typedef struct dice +{ + char id[14]; + int win; + int lost; +} +dice; + +dice table[1024]; + +int find(char *name) +{ + int i = 0; + if (total == 0) + { + total++; + return 0; + } + for (i = 0; i < total; i++) + if (!strcmp(name, table[i].id)) + return i; + memset(&table[total++], 0, sizeof(dice)); + return total - 1; +} + +int main() { + int index, win = 0, lost = 0; + FILE *fpwin, *fplost; + char buf[256], *ptr, buf0[256], *name = (char *) malloc(15), *mon = (char *) malloc(5); + + fpwin = fopen(DICE_WIN, "r"); + fplost = fopen(DICE_LOST, "r"); + + if (!fpwin || !fplost) + perror("error open file"); + + while (fgets(buf, 255, fpwin)) + { + strcpy(buf0, buf); + name = strtok(buf, " "); + mon = strstr(buf0, "²bÁÈ:"); + if ((ptr = strchr(mon, '\n'))) + *ptr = 0; + index = find(name); + strcpy(table[index].id, name); + table[index].win += atoi(mon + 5); + } + fclose(fpwin); + + while (fgets(buf, 255, fplost)) + { + strcpy(buf0, buf); + name = strtok(buf, " "); + mon = strstr(buf0, "¿é¤F "); + if ((ptr = strchr(mon, '\n'))) + *ptr = 0; + if ((index = find(name)) == total - 1) + strcpy(table[index].id, name); + table[index].lost += atoi(mon + 5); + } + + for (index = 0; index < total; index++) + { + printf("%-15s ŤF %-8d ¶ô¿ú¡A ¿é±¼ %-8d ¶ô¿ú\n", table[index].id + ,table[index].win, table[index].lost); + win += table[index].win; + lost += table[index].lost; + } + index = win + lost; + printf("\n¤H¼Æ: %d\nÁ`Ĺ¿ú=%d Á`¿é¿ú=%d Á`ª÷ÃB:%d\n", total, win, lost, index); + printf("Ĺªº¤ñ¨Ò:%f ¿éªº¤ñ¨Ò:%f\n", (float) win / index, (float) lost / index); + printf("\n³Æµù¡G¿éŬO¥H¨Ï¥ÎªÌªºÆ[ÂI¨Ó¬Ý\n"); + fclose(fplost); + return 0; +} diff --git a/util/cpdeadbrd.c b/util/cpdeadbrd.c new file mode 100644 index 00000000..12c5827e --- /dev/null +++ b/util/cpdeadbrd.c @@ -0,0 +1,41 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +extern int numboards; +extern boardheader_t *bcache; +int main(int argc, char* argv[]){ +struct stat st; +boardheader_t *bptr; + int n; + char pathname[1024]; + + resolve_boards(); + for (n=numboards-1;n>0;n--) + { + + bptr = &bcache[n]; + if(!strcmp(bptr->brdname,"ck53rd316"))continue; + sprintf(pathname,"/home/bbs/boards/%s/.DIR",bptr->brdname); + if(stat(pathname, &st) == -1) + { + printf("%s is dead\n",pathname); + sprintf (pathname,"cp -R /mnt/bbs/boards/%s /home/bbs/boards/%s",bptr->brdname,bptr->brdname); + } + } +} + + + + + + + diff --git a/util/dailybackup.pl b/util/dailybackup.pl new file mode 100644 index 00000000..76943887 --- /dev/null +++ b/util/dailybackup.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +use lib '/home/bbs/bin/'; +use LocalVars; +use strict; +use vars qw/$BACKHOME $MANROOT $HOMEROOT $BOARDROOT/; + +$BACKHOME = "$BBSHOME/backup"; +$MANROOT = "man/boards"; +$HOMEROOT = "home"; +$BOARDROOT= "boards"; + +chdir $BBSHOME; +my @baktable = (['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'], + ['I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'], + ['Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X'], + ['Y', 'Z', 'a', 'b', 'c', 'd', 'e'], + ['f', 'g', 'h', 'i', 'j', 'k', 'l'], + ['m', 'n', 'o', 'p', 'q', 'r', 's'], + ['t', 'u', 'v', 'w', 'x', 'y', 'z']); +my (undef,undef,undef,undef,undef,undef,$wday) = localtime(time); +my $week = defined($ARGV[0]) ? $ARGV[0] : $wday; + +no strict 'subs'; +setpriority(PRIO_PROCESS, $$, 20); +use strict subs; + +my($orig, $to); +foreach $orig ( <$BACKHOME/*new*> ){ + $to = $orig; + $to =~ s/\.new//g; + docmd("mv $orig $to"); +} + +foreach( @{$baktable[$week]} ){ + docmd("$TAR zcf $BACKHOME/man.$_.new.tgz $MANROOT/$_*"); + docmd("$TAR zcf $BACKHOME/home.$_.new.tgz $HOMEROOT/$_/*"); + docmd("$TAR zcf $BACKHOME/board.$_.new.tgz $BOARDROOT/$_*"); +} + +if( $week == 0 ){ + docmd("$TAR zcf $BACKHOME/general.new.tgz .act .crontab .note .polling .post bin cron etc innd note.ans note.dat out out.going pttbbs pttbbs.conf upgrade.sh usies ussong"); +} + +sub docmd +{ + print "@_\n"; + `@_`; +} diff --git a/util/daymandex.c b/util/daymandex.c new file mode 100644 index 00000000..d2921d07 --- /dev/null +++ b/util/daymandex.c @@ -0,0 +1,269 @@ +/* $Id: daymandex.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ + +/* + target : ºëµØ°Ï¯Á¤Þµ{¦¡ (man index) + + syntax : mandex [board] + [board] ¦³È ==> ¥u¶]¸Ó board + ªÅªº ==> ©Ò¦³ªº boards ³£¶] +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +extern int numboards; +extern boardheader_t *bcache; + +char color[4][10] = +{"[1;33m", "[1;32m", "[1;36m", "[1;37m"}; +char fn_index[] = ".index"; +char fn_new[] = ".index.new"; +char index_title[] = "¡· ºëµØ°Ï¥Ø¿ý¯Á¤Þ"; +FILE *fndx; +int ndir; +int nfile; +int index_pos; +char topdir[128], pgem[512], pndx[512]; + +int nb = 0; /* board ¼Æ */ + +struct boardinfo +{ + char bname[40]; + int ndir; + int nfile; + int k; +}; +typedef struct boardinfo boardinfo; + +boardinfo +board[MAX_BOARD]; + +int k_cmp(b, a) + boardinfo *b, *a; +{ + return ((a->k / 100 + a->ndir + a->nfile) - (b->k / 100 + b->ndir + b->nfile)); +} + +int dashd(fname) + char *fname; +{ + struct stat st; + + return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); +} + + +/* visit the hierarchy recursively */ + +void +mandex(level, num_header, fpath) + int level; + char *fpath, *num_header; +{ + FILE *fgem; + char *fname, buf[256]; + struct stat st; + int count; + fileheader_t fhdr; + + fgem = fopen(fpath, "r+"); + if (fgem == NULL) + return; + + fname = strrchr(fpath, '.'); + if (!level) + { + + printf("%s\r\n",fpath); + strcpy(pgem, fpath); + + strcpy(fname, fn_new); + fndx = fopen(fpath, "w"); + if (fndx == NULL) + { + fclose(fgem); + return; + } + fprintf(fndx, "[1;32m§Ç¸¹\t\t\tºëµØ°Ï¥DÃD[m\n" + "[36m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w[m\n"); + strcpy(pndx, fpath); + ndir = nfile = 0; + index_pos = -1; + } + + count = 0; + while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1) + { + strcpy(fname, fhdr.filename); + if (!fname[0]) continue; + if (!level && !strncmp(fhdr.title, index_title, strlen(index_title)) + && index_pos < 0) + { + index_pos = count; + unlink(fpath); + } + st.st_size = 0; + stat(fpath, &st); + + sprintf(buf, "%.*s%s%3d. %s [m\n", + + 11 * level, num_header, color[level % 4], ++count, fhdr.title); /* Ptt */ + fputs(buf, fndx); + if (dashd(fpath)) + { + ++ndir; + if (*fhdr.title != '#' && level < 10) + { + strcat(fpath, "/.DIR"); + mandex(level + 1, buf, fpath); + } + } + else + ++nfile; + } + + if (!level) + { + char lpath[MAXPATHLEN]; + + fclose(fndx); + strcpy(fname, fn_index); + rename(pndx, fpath); + strcpy(pndx, fpath); + + sprintf(buf, "%s.new", pgem); + if (index_pos >= 0 || (fndx = fopen(buf, "w"))) + { + fname[-1] = 0; + stamplink(fpath, &fhdr); + unlink(fpath); + strcpy(fhdr.owner, "¨C¤Ñ¦Û°Ê§ó·s"); + sprintf(lpath, "%s/%s", topdir, pndx); + st.st_size = 0; + stat(lpath, &st); + sprintf(fhdr.title, "%s (%.1fk)", index_title, st.st_size / 1024.); + board[nb].k = st.st_size; /* Ptt */ + printf("(%d)[%dK]", nb, board[nb].k); + symlink(lpath, fpath); + if (index_pos < 0) + { + fwrite(&fhdr, sizeof(fhdr), 1, fndx); + rewind(fgem); + while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1) + fwrite(&fhdr, sizeof(fhdr), 1, fndx); + fclose(fndx); + fclose(fgem); + rename(buf, pgem); + } + else + { + fseek(fgem, index_pos * sizeof(fhdr), 0); + fwrite(&fhdr, sizeof(fhdr), 1, fgem); + fclose(fgem); + } + return; + } + } + fclose(fgem); +} + + +int main(int argc, char* argv[]){ + boardheader_t *bptr; + DIR *dirp; + struct dirent *de; + int ch, n; + int place = 0; + char *fname, fpath[MAXPATHLEN]; + + resolve_boards(); + nb = 0; + if(argc == 1){ + puts("Creating the whole index..."); + chdir(strcpy(topdir, BBSHOME)); + strcpy(fpath, "man/.DIR"); + mandex(0, "", fpath); + } + + + chdir(strcpy(topdir, BBSHOME "/man/boards")); + + if(argc > 1) { + sprintf(fpath, "%s/.DIR", argv[1]); + mandex(0, "", fpath); + exit(0); + } + + /* process all boards */ + + if(!(dirp = opendir(topdir))) { + printf("## unable to enter [man/boards]\n"); + exit(-1); + } + + while((de = readdir(dirp))){ + fname = de->d_name; + ch = fname[0]; + if (ch != '.'){ + board[nb].k = 0; + strcpy(board[nb].bname, fname); + sprintf(fpath, "%s/.rebuild", fname); + if( access(fpath, 0) >= 0 ){ + unlink(fpath); + + sprintf(fpath, "%s/.DIR", fname); + mandex(0, "", fpath); + printf("%-14sd: %d\tf: %d\n", fname, ndir, nfile); + /* report */ + board[nb].ndir = ndir; + board[nb].nfile = nfile; + if (board[nb].k) + nb++; + } + } + } + closedir(dirp); + + qsort(board, nb, sizeof(boardinfo), k_cmp); + + if (!(fndx = fopen(BBSHOME "/etc/topboardman", "w"))) + exit(0); + + fprintf(fndx, "[1;44m±Æ¦W[47;30m ¬Ý ª© ¥Ø¿ý¼Æ ÀÉ®×¼Æ" + " byte¼Æ [30m Á` ¤À ª© ¥D [m\n"); + + for (ch = 0; ch < nb; ch++){ + for (n = 0; n < numboards; n++){ + bptr = &bcache[n]; + if (!strcmp(bptr->brdname, board[ch].bname)) + break; + } + if (n >= numboards || + (bptr->brdattr & (BRD_BAD | BRD_NOCOUNT | BRD_HIDE))) + continue; + if (board[ch].ndir + board[ch].nfile < 5) + break; + fprintf(fndx, "%3d.[33m%15s[m %5d %7d %10d %6d [31m%-24.24s[m\n", + ++place, + board[ch].bname, + board[ch].ndir, board[ch].nfile, board[ch].k + ,board[ch].k / 100 + board[ch].nfile + board[ch].ndir + ,bptr->BM); + } + fclose(fndx); + exit(0); +} diff --git a/util/deluserfile.c b/util/deluserfile.c new file mode 100644 index 00000000..63cfefba --- /dev/null +++ b/util/deluserfile.c @@ -0,0 +1,147 @@ +/* $Id: deluserfile.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ +/* ¦Û°Ê¬åuser¥Ø¿ýÀÉ®×µ{¦¡ */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <dirent.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#define HOLDWRITELOG +#define DELZEROFILE +#define USERHOME BBSHOME "/home" + +int bad_user_id(char *userid) +{ + register char ch; + + if (strlen(userid) < 2) + return 1; + + if (!isalpha(*userid)) + return 1; + + if (!strcasecmp(userid, "new")) + return 1; + + while ((ch = *(++userid))) + if (!isalnum(ch)) + return 1; + return 0; +} + +void del_file(char *userid) +{ + char buf[200], buf1[200]; + struct dirent *de; + DIR *dirp; + char *ptr; + + sprintf(buf, BBSHOME "/home/%c/%s", userid[0], userid); + + if (chdir(buf) == -1) + return; + + if (!(dirp = opendir(buf))) + return; + + while ((de = readdir(dirp))) + { + ptr = de->d_name; + if (ptr[0] > ' ' && ptr[0] != '.') + { + if (strstr(ptr, "writelog")) +#ifdef HOLDWRITELOG + { + fileheader_t mymail; + + stampfile(buf, &mymail); + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, userid); + strcpy(mymail.title, "¼ö½u°O¿ý"); + sprintf(buf1, BBSHOME "/home/%c/%s/writelog", + userid[0], userid); + rename(buf1, buf); + sprintf(buf1, BBSHOME "/home/%c/%s/.DIR", userid[0], userid); + append_record(buf1, &mymail, sizeof(mymail)); + } +#else + unlink(ptr); +#endif + else if (strstr(ptr, "chat_")) + unlink(ptr); + else if (strstr(ptr, "ve_")) + unlink(ptr); + else if (strstr(ptr, "SR.")) + unlink(ptr); + else if (strstr(ptr, ".old")) + unlink(ptr); + else if (strstr(ptr, "talk_")) + unlink(ptr); + } + } + closedir(dirp); +} + +void mv_user_home(char *ptr) +{ + char buf[200]; + + printf("move user %s to tmp\n", ptr); + sprintf(buf, "cp -R " BBSHOME "/home/%c/%s " BBSHOME "/tmp", ptr[0], ptr); +// sprintf(buf,"rm -rf " BBSHOME "/home/%c/%s",ptr[0],ptr); + if (!system(buf)) + { //Copy success + + sprintf(buf, "rm -rf " BBSHOME "/home/%c/%s", ptr[0], ptr); + system(buf); + } +} + +int main(int argc, char **argv) +{ + struct dirent *de; + DIR *dirp; + char *ptr, buf[200], ch; + int count = 0; +/* visit all users */ + + printf("new version, deleting\n"); + + for (ch = 'A'; ch <= 'z'; ch++) + { + if(ch > 'Z' && ch < 'a') + continue; + printf("Cleaning %c\n", ch); + sprintf(buf, USERHOME "/%c", ch); + if (!(dirp = opendir(buf))) + { + printf("unable to open %s\n", buf); + continue; + } + + while ((de = readdir(dirp))) + { + ptr = de->d_name; + + /* ¹w¨¾¿ù»~ */ + if (!bad_user_id(ptr)) + { + if (!(count++ % 300)) + printf(".\n"); + if (!searchuser(ptr)) + mv_user_home(ptr); + else + del_file(ptr); + } + } + closedir(dirp); + } + return 0; +} diff --git a/util/descrypt.c b/util/descrypt.c new file mode 100644 index 00000000..97475c1a --- /dev/null +++ b/util/descrypt.c @@ -0,0 +1,616 @@ +/* $Id: descrypt.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */ + +/* + * FreeSec: libcrypt for NetBSD + * + * Copyright (c) 1994 David Burren + * All rights reserved. + * + * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet + * crypt.c should now *only* export crypt(), in order to make + * binaries of libcrypt exportable from the USA + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/secure/lib/libcrypt/crypt.c,v 1.11 1999/08/28 01:30:24 peter Exp $ + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren <davidb@werj.com.au>. + * + * An excellent reference on the underlying algorithm (and related + * algorithms) is: + * + * B. Schneier, Applied Cryptography: protocols, algorithms, + * and source code in C, John Wiley & Sons, 1994. + * + * Note that in that book's description of DES the lookups for the initial, + * pbox, and final permutations are inverted (this has been brought to the + * attention of the author). A list of errata for this book has been + * posted to the sci.crypt newsgroup by the author and is available for FTP. + * + * ARCHITECTURE ASSUMPTIONS: + * This code assumes that u_longs are 32 bits. It will probably not + * operate on 64-bit machines without modifications. + * It is assumed that the 8-byte arrays passed by reference can be + * addressed as arrays of u_longs (ie. the CPU is not picky about + * alignment). + */ + +#ifndef HAVE_DES_CRYPT + +#include <sys/types.h> +#include <sys/param.h> +#include <pwd.h> +#include <string.h> + +static unsigned char IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static unsigned char inv_key_perm[64]; +static unsigned char u_key_perm[56]; +static unsigned char key_perm[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +static unsigned char key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static unsigned char inv_comp_perm[56]; +static unsigned char comp_perm[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static unsigned char u_sbox[8][64]; +static unsigned char sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static unsigned char un_pbox[32]; +static unsigned char pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +static unsigned long bits32[32] = { + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +static unsigned long saltbits; +static long old_salt; +static unsigned long *bits28, *bits24; +static unsigned char init_perm[64], final_perm[64]; +static unsigned long en_keysl[16], en_keysr[16]; +static unsigned long de_keysl[16], de_keysr[16]; +static int des_initialised = 0; +static unsigned char m_sbox[4][4096]; +static unsigned long psbox[4][256]; +static unsigned long ip_maskl[8][256], ip_maskr[8][256]; +static unsigned long fp_maskl[8][256], fp_maskr[8][256]; +static unsigned long key_perm_maskl[8][128], key_perm_maskr[8][128]; +static unsigned long comp_maskl[8][128], comp_maskr[8][128]; +static unsigned long old_rawkey0, old_rawkey1; + +static unsigned char ascii64[] = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +/* 0000000000111111111122222222223333333333444444444455555555556666 */ +/* 0123456789012345678901234567890123456789012345678901234567890123 */ + +static int ascii_to_bin(char ch) { + if(ch > 'z') + return 0; + if(ch >= 'a') + return ch - 'a' + 38; + if(ch > 'Z') + return 0; + if(ch >= 'A') + return ch - 'A' + 12; + if(ch > '9') + return 0; + if(ch >= '.') + return ch - '.'; + return 0; +} + +static void des_init() { + int i, j, b, k, inbit, obit; + unsigned long *p, *il, *ir, *fl, *fr; + + old_rawkey0 = old_rawkey1 = 0L; + saltbits = 0L; + old_salt = 0L; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for(i = 0; i < 8; i++) + for(j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for(b = 0; b < 4; b++) + for(i = 0; i < 64; i++) + for(j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]; + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for(i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = i; + inv_key_perm[i] = 255; + } + + /* + * Invert the key permutation and initialise the inverted key + * compression permutation. + */ + for(i = 0; i < 56; i++) { + u_key_perm[i] = key_perm[i] - 1; + inv_key_perm[key_perm[i] - 1] = i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for(i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = i; + } + + /* + * Set up the OR-mask arrays for the initial and final permutations, + * and for the key initial and compression permutations. + */ + for(k = 0; k < 8; k++) { + for(i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0L; + *(ir = &ip_maskr[k][i]) = 0L; + *(fl = &fp_maskl[k][i]) = 0L; + *(fr = &fp_maskr[k][i]) = 0L; + for(j = 0; j < 8; j++) { + inbit = 8 * k + j; + if(i & bits8[j]) { + if((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for(i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0L; + *(ir = &key_perm_maskr[k][i]) = 0L; + for(j = 0; j < 7; j++) { + inbit = 8 * k + j; + if(i & bits8[j + 1]) { + if((obit = inv_key_perm[inbit]) == 255) + continue; + if(obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0L; + *(ir = &comp_maskr[k][i]) = 0L; + for(j = 0; j < 7; j++) { + inbit = 7 * k + j; + if(i & bits8[j + 1]) { + if((obit=inv_comp_perm[inbit]) == 255) + continue; + if(obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } + + /* + * Invert the P-box permutation, and convert into OR-masks for + * handling the output of the S-box arrays setup above. + */ + for(i = 0; i < 32; i++) + un_pbox[pbox[i] - 1] = i; + + for(b = 0; b < 4; b++) + for(i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } + + des_initialised = 1; +} + +static void setup_salt(long salt) { + unsigned long obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0L; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + +static int des_setkey(const char *key) { + unsigned long k0, k1, rawkey0, rawkey1; + int shifts, round; + + if(!des_initialised) + des_init(); + + rawkey0 = ntohl(*(unsigned long *) key); + rawkey1 = ntohl(*(unsigned long *) (key + 4)); + + if((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return 0; + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * Do key permutation and split into two 28-bit subkeys. + */ + k0 = key_perm_maskl[0][rawkey0 >> 25] + | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskl[4][rawkey1 >> 25] + | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; + k1 = key_perm_maskr[0][rawkey0 >> 25] + | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskr[4][rawkey1 >> 25] + | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; + /* + * Rotate subkeys and do compression permutation. + */ + shifts = 0; + for(round = 0; round < 16; round++) { + unsigned long t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + + de_keysl[15 - round] = + en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] + | comp_maskl[1][(t0 >> 14) & 0x7f] + | comp_maskl[2][(t0 >> 7) & 0x7f] + | comp_maskl[3][t0 & 0x7f] + | comp_maskl[4][(t1 >> 21) & 0x7f] + | comp_maskl[5][(t1 >> 14) & 0x7f] + | comp_maskl[6][(t1 >> 7) & 0x7f] + | comp_maskl[7][t1 & 0x7f]; + + de_keysr[15 - round] = en_keysr[round] = + comp_maskr[0][(t0 >> 21) & 0x7f] + | comp_maskr[1][(t0 >> 14) & 0x7f] + | comp_maskr[2][(t0 >> 7) & 0x7f] + | comp_maskr[3][t0 & 0x7f] + | comp_maskr[4][(t1 >> 21) & 0x7f] + | comp_maskr[5][(t1 >> 14) & 0x7f] + | comp_maskr[6][(t1 >> 7) & 0x7f] + | comp_maskr[7][t1 & 0x7f]; + } + return 0; +} + +static int do_des(unsigned long l_in, unsigned long r_in, unsigned long *l_out, + unsigned long *r_out, int count) { + /* + * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. + */ + unsigned long l, r, *kl, *kr, *kl1, *kr1; + unsigned long f, r48l, r48r; + int round; + + if(count == 0) { + return 1; + } else if(count > 0) { + /* + * Encrypting + */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* + * Decrypting + */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* + * Do initial permutation (IP). + */ + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; + + while(count--) { + /* + * Do each round. + */ + kl = kl1; + kr = kr1; + round = 16; + while(round--) { + /* + * Expand R to 48 bits (simulate the E-box). + */ + r48l = ((r & 0x00000001) << 23) + | ((r & 0xf8000000) >> 9) + | ((r & 0x1f800000) >> 11) + | ((r & 0x01f80000) >> 13) + | ((r & 0x001f8000) >> 15); + + r48r = ((r & 0x0001f800) << 7) + | ((r & 0x00001f80) << 5) + | ((r & 0x000001f8) << 3) + | ((r & 0x0000001f) << 1) + | ((r & 0x80000000) >> 31); + /* + * Do salting for crypt() and friends, and + * XOR with the permuted key. + */ + f = (r48l ^ r48r) & saltbits; + r48l ^= f ^ *kl++; + r48r ^= f ^ *kr++; + /* + * Do sbox lookups (which shrink it back to 32 bits) + * and do the pbox permutation at the same time. + */ + f = psbox[0][m_sbox[0][r48l >> 12]] + | psbox[1][m_sbox[1][r48l & 0xfff]] + | psbox[2][m_sbox[2][r48r >> 12]] + | psbox[3][m_sbox[3][r48r & 0xfff]]; + /* + * Now that we've permuted things, complete f(). + */ + f ^= l; + l = r; + r = f; + } + r = l; + l = f; + } + /* + * Do final permutation (inverse of IP). + */ + *l_out = fp_maskl[0][l >> 24] + | fp_maskl[1][(l >> 16) & 0xff] + | fp_maskl[2][(l >> 8) & 0xff] + | fp_maskl[3][l & 0xff] + | fp_maskl[4][r >> 24] + | fp_maskl[5][(r >> 16) & 0xff] + | fp_maskl[6][(r >> 8) & 0xff] + | fp_maskl[7][r & 0xff]; + *r_out = fp_maskr[0][l >> 24] + | fp_maskr[1][(l >> 16) & 0xff] + | fp_maskr[2][(l >> 8) & 0xff] + | fp_maskr[3][l & 0xff] + | fp_maskr[4][r >> 24] + | fp_maskr[5][(r >> 16) & 0xff] + | fp_maskr[6][(r >> 8) & 0xff] + | fp_maskr[7][r & 0xff]; + return 0; +} + +char *crypt(char *key, char *setting) { + unsigned long count, salt, l, r0, r1, keybuf[2]; + unsigned char *p, *q; + static unsigned char output[21]; + + if(!des_initialised) + des_init(); + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (unsigned char *)keybuf; + while(q - (unsigned char *)keybuf - 8) { + if((*q++ = *key << 1)) + key++; + } + if(des_setkey((unsigned char *)keybuf)) + return NULL; + + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + salt = (ascii_to_bin(setting[1]) << 6) + | ascii_to_bin(setting[0]); + + output[0] = setting[0]; + /* + * If the encrypted password that the salt was extracted from + * is only 1 character long, the salt will be corrupted. We + * need to ensure that the output string doesn't have an extra + * NUL in it! + */ + output[1] = setting[1] ? setting[1] : output[0]; + + p = output + 2; + + setup_salt(salt); + /* + * Do it. + */ + if(do_des(0L, 0L, &r0, &r1, count)) + return NULL; + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return output; +} +#endif diff --git a/util/expire.c b/util/expire.c new file mode 100644 index 00000000..d6f3e2b9 --- /dev/null +++ b/util/expire.c @@ -0,0 +1,226 @@ +/* $Id: expire.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* ¦Û°Ê¬å«H¤u¨ãµ{¦¡ */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#define QCAST int (*)(const void *, const void *) + +#define DEF_DAYS 50 +#define DEF_MAXP 2000 +#define DEF_MINP 300 + +#define EXPIRE_CONF BBSHOME "/etc/expire.conf" +extern boardheader_t *bcache; +char *bpath = BBSHOME "/boards"; + +struct life +{ + char bname[16]; /* board ID */ + int days; /* expired days */ + int maxp; /* max post */ + int minp; /* min post */ +}; +typedef struct life life; + + +void + expire(brd) +life *brd; +{ + fileheader_t head; + struct stat state; + char lockfile[128], tmpfile[128], bakfile[128]; + char fpath[128], index[128], *fname; + int total, bid; + int fd, fdr, fdw, done, keep; + int duetime, ftime; + + printf("%s\n", brd->bname); + if((bid = getbnum(brd->bname)) == 0 || + strcmp(brd->bname, bcache[bid-1].brdname)) + { + printf("no such board?: %s\n", brd->bname); + return; + } +#ifdef VERBOSE + if (brd->days < 1) + { + printf(":Err: expire time must more than 1 day.\n"); + return; + } + else if (brd->maxp < 100) + { + printf(":Err: maxmum posts number must more than 100.\n"); + return; + } +#endif + + sprintf(index, "%s/%s/.DIR", bpath, brd->bname); + sprintf(lockfile, "%s.lock", index); + if ((fd = open(lockfile, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1) + return; + flock(fd, LOCK_EX); + + strcpy(fpath, index); + fname = (char *) strrchr(fpath, '.'); + + duetime = time(NULL) - brd->days * 24 * 60 * 60; + done = 0; + if ((fdr = open(index, O_RDONLY, 0)) > 0) + { + fstat(fdr, &state); + total = state.st_size / sizeof(head); + sprintf(tmpfile, "%s.new", index); + unlink(tmpfile); + if ((fdw = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0644)) > 0) + { + while (read(fdr, &head, sizeof head) == sizeof head) + { + done = 1; + ftime = atoi(head.filename + 2); + if (head.owner[0] == '-') + keep = 0; + else if (head.filemode & FILE_MARKED || total <= brd->minp) + keep = 1; + else if (ftime < duetime || total > brd->maxp) + keep = 0; + else + keep = 1; + + if (keep) + { + if (write(fdw, (char *)&head, sizeof head) == -1) + { + done = 0; + break; + } + } + else + { + strcpy(fname, head.filename); + unlink(fpath); + printf("\t%s\n", fname); + total--; + } + } + close(fdw); + } + close(fdr); + } + + if (done) + { + sprintf(bakfile, "%s.old", index); + if (rename(index, bakfile) != -1) + { + rename(tmpfile, index); + touchbtotal(bid); + } + } + flock(fd, LOCK_UN); + close(fd); +} + + +int main(argc, argv) +char *argv[]; +{ + FILE *fin; + int number, count; + life db, table[MAX_BOARD], *key; + struct dirent *de; + DIR *dirp; + char *ptr, *bname, buf[256]; + + resolve_boards(); + db.days = ((argc > 1) && (number = atoi(argv[1])) > 0) ? number : DEF_DAYS; + db.maxp = ((argc > 2) && (number = atoi(argv[2])) > 0) ? number : DEF_MAXP; + db.minp = ((argc > 3) && (number = atoi(argv[3])) > 0) ? number : DEF_MINP; + +/* --------------- */ +/* load expire.ctl */ +/* --------------- */ + + count = 0; + if((fin = fopen(EXPIRE_CONF, "r"))) + { + while (fgets(buf, 256, fin)) + { + if (buf[0] == '#') + continue; + + bname = (char *) strtok(buf, " \t\r\n"); + if (bname && *bname) + { + ptr = (char *) strtok(NULL, " \t\r\n"); + if (ptr && (number = atoi(ptr)) > 0) + { + key = &(table[count++]); + strcpy(key->bname, bname); + key->days = number; + key->maxp = db.maxp; + key->minp = db.minp; + + ptr = (char *) strtok(NULL, " \t\r\n"); + if (ptr && (number = atoi(ptr)) > 0) + { + key->maxp = number; + + ptr = (char *) strtok(NULL, " \t\r\n"); + if (ptr && (number = atoi(ptr)) > 0) + { + key->minp = number; + } + } + } + } + } + fclose(fin); + } + + if (count > 1) + { + qsort(table, count, sizeof(life), (QCAST)strcasecmp); + } + +/* ---------------- */ +/* visit all boards */ +/* ---------------- */ + + if (!(dirp = opendir(bpath))) + { + printf(":Err: unable to open %s\n", bpath); + return -1; + } + + while((de = readdir(dirp))) + { + ptr = de->d_name; + if (ptr[0] > ' ' && ptr[0] != '.') + { + if (count) + key = (life *) bsearch(ptr, table, count, sizeof(life), (QCAST)strcasecmp); + else + key = NULL; + if (!key) + key = &db; + strcpy(key->bname, ptr); + expire(key); + } + } + closedir(dirp); + return 0; +} diff --git a/util/horoscope.c b/util/horoscope.c new file mode 100644 index 00000000..c91db7cd --- /dev/null +++ b/util/horoscope.c @@ -0,0 +1,157 @@ +/* $Id: horoscope.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "common.h" + +struct userec_t cuser; + +int main() { + int i, j, k; + FILE *fp; + int max, item, maxhoroscope; + + int act[12]; + + char *name[13] = + {"¨d¦Ï", + "ª÷¤û", + "Âù¤l", + "¥¨ÃÉ", + "·à¤l", + "³B¤k", + "¤Ñ¯¯", + "¤ÑÃÈ", + "®g¤â", + "¼¯½~", + "¤ô²~", + "Âù³½", + "" + }; + char *blk[10] = + { + " ", "¢j", "¢k", "¢l", "¢m", + "¢n", "¢o", "¢p", "¢i", "¢i", + }; + + memset(act, 0, sizeof(act)); + if(passwd_mmap()) + exit(1); + for(k = 1; k <= MAX_USERS; k++) { + passwd_query(k, &cuser); + if(!cuser.userid[0]) + continue; + switch (cuser.month) + { + case 1: + if (cuser.day <= 19) + act[9]++; + else + act[10]++; + break; + case 2: + if (cuser.day <= 18) + act[10]++; + else + act[11]++; + break; + case 3: + if (cuser.day <= 20) + act[11]++; + else + act[0]++; + break; + case 4: + if (cuser.day <= 19) + act[0]++; + else + act[1]++; + break; + case 5: + if (cuser.day <= 20) + act[1]++; + else + act[2]++; + break; + case 6: + if (cuser.day <= 21) + act[2]++; + else + act[3]++; + break; + case 7: + if (cuser.day <= 22) + act[3]++; + else + act[4]++; + break; + case 8: + if (cuser.day <= 22) + act[4]++; + else + act[5]++; + break; + case 9: + if (cuser.day <= 22) + act[5]++; + else + act[6]++; + break; + case 10: + if (cuser.day <= 23) + act[6]++; + else + act[7]++; + break; + case 11: + if (cuser.day <= 22) + act[7]++; + else + act[8]++; + break; + case 12: + if (cuser.day <= 21) + act[8]++; + else + act[9]++; + break; + } + } + + for (i = max = maxhoroscope = 0; i < 12; i++) + { + if (act[i] > max) + { + max = act[i]; + maxhoroscope = i; + } + } + + item = max / 30 + 1; + + if ((fp = fopen(BBSHOME"/etc/horoscope", "w")) == NULL) + { + printf("cann't open etc/horoscope\n"); + return 1; + } + + for (i = 0; i < 12; i++) + { + fprintf(fp, " [1;37m%s®y [0;36m", name[i]); + for (j = 0; j < act[i] / item; j++) + { + fprintf(fp, "%2s", blk[9]); + } + /* ¬°¤Fè¦n¤@¶ */ + if (i != 11) + fprintf(fp, "%2s [1;37m%d[m\n\n", blk[(act[i] % item) * 10 / item], + act[i]); + else + fprintf(fp, "%2s [1;37m%d[m\n", blk[(act[i] % item) * 10 / item], + act[i]); + } + fclose(fp); + return 0; +} diff --git a/util/in2outmail b/util/in2outmail Binary files differnew file mode 100644 index 00000000..686944c1 --- /dev/null +++ b/util/in2outmail diff --git a/util/in2outmail.c b/util/in2outmail.c new file mode 100644 index 00000000..fce9cc59 --- /dev/null +++ b/util/in2outmail.c @@ -0,0 +1,288 @@ +/* $Id: in2outmail.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "pttstruct.h" + + +#ifdef HAVE_SETPROCTITLE + +#include <sys/types.h> +#include <libutil.h> + +void initsetproctitle(int argc, char **argv, char **envp) { +} + +#else + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ +extern char **environ; + +void initsetproctitle(int argc, char **argv, char **envp) { + register int i; + + /* Move the environment so setproctitle can use the space at + the top of memory. */ + for(i = 0; envp[i]; i++); + environ = malloc(sizeof(char *) * (i + 1)); + for(i = 0; envp[i]; i++) + environ[i] = strdup(envp[i]); + environ[i] = NULL; + + /* Save start and extent of argv for setproctitle. */ + Argv = argv; + if(i > 0) + LastArgv = envp[i - 1] + strlen(envp[i - 1]); + else + LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); +} + +static void do_setproctitle(const char *cmdline) { + char buf[256], *p; + int i; + + strncpy(buf, cmdline, 256); + buf[255] = '\0'; + i = strlen(buf); + if(i > LastArgv - Argv[0] - 2) { + i = LastArgv - Argv[0] - 2; + } + strcpy(Argv[0], buf); + p = &Argv[0][i]; + while(p < LastArgv) + *p++='\0'; + Argv[1] = NULL; +} + +void setproctitle(const char* format, ...) { + char buf[256]; + + va_list args; + va_start(args, format); + vsprintf(buf, format,args); + do_setproctitle(buf); + va_end(args); +} +#endif + + + + + +#define SPOOL BBSHOME "/out" +#define INDEX SPOOL "/.DIR" +#define NEWINDEX SPOOL "/.DIR.sending" +#define FROM ".bbs@" MYHOSTNAME +#define SMTPPORT 25 + +int waitReply(int sock) { + char buf[256]; + + if(read(sock, buf, sizeof(buf)) <= 0) + return -1; + else + return buf[0] - '0'; +} + +int sendRequest(int sock, char *request) { + return write(sock, request, strlen(request)) < 0 ? -1 : 0; +} + +int connectMailServer(char *host) { + int sock; + struct sockaddr_in addr; + + if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); +#ifdef FreeBSD + addr.sin_len = sizeof(addr); +#endif + addr.sin_family = AF_INET; + addr.sin_port = htons(SMTPPORT); + addr.sin_addr.s_addr = inet_addr(host); + + if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror(RELAY_SERVER_IP); + close(sock); + return -1; + } + + if(waitReply(sock) != 2) { + close(sock); + return -1; + } + + if(sendRequest(sock, "helo " MYHOSTNAME "\n") || waitReply(sock) != 2) { + close(sock); + return -1; + } else + return sock; +} + +void disconnectMailServer(int sock) { + sendRequest(sock, "quit\n"); + /* drop the reply :p */ + close(sock); +} + +void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) { + int n; + char buf[2048]; + + n = snprintf(buf, sizeof(buf), "From: %s\nTo: %s\nSubject: %s\n\n", + from, to, subject); + write(sock, buf, n); + + while(fgets(buf, sizeof(buf), fp)) { + if(buf[0] == '.' && buf[1] == '\n') + strcpy(buf, "..\n"); + write(sock, buf, strlen(buf)); + } +} + +void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { + char buf[256]; + + snprintf(buf, sizeof(buf), "mail from: %s\n", from); + if(sendRequest(sock, buf) || waitReply(sock) != 2) + return; + + snprintf(buf, sizeof(buf), "rcpt to: %s\n", to); + if(sendRequest(sock, buf) || waitReply(sock) != 2) + return; + + if(sendRequest(sock, "data\n") || waitReply(sock) != 3) + return; + + doSendBody(sock, fp, from, to, subject); + + if(sendRequest(sock, "\n.\n") || waitReply(sock) != 2) + return; +} + +void sendMail() { + int fd, sockPTT2, sockHinet; + MailQueue mq; + + if(access(NEWINDEX, R_OK | W_OK)) { + if(link(INDEX, NEWINDEX) || unlink(INDEX)) + /* nothing to do */ + return; + } + + if( (sockPTT2 = connectMailServer("140.112.30.143")) < 0 ){ + fprintf(stderr, "connect server failed...\n"); + return; + } + sockHinet = connectMailServer("61.218.59.183"); + + fd = open(NEWINDEX, O_RDONLY); + flock(fd, LOCK_EX); + while(read(fd, &mq, sizeof(mq)) > 0) { + FILE *fp; + char buf[256]; + + snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM); + if((fp = fopen(mq.filepath, "r"))) { + setproctitle("outmail: sending %s", mq.filepath); + if( strstr(mq.rcpt, ".edu.tw") || + strstr(mq.rcpt, ".twbbs.org") || + strstr(mq.rcpt, "ptt.cc") || + strstr(mq.rcpt, "ptt2.cc") ){ + printf("relay server: ptt2, to %s\n", mq.rcpt); + doSendMail(sockPTT2, fp, buf, mq.rcpt, mq.subject); + } + else{ + printf("relay server: ezmain, to %s\n", mq.rcpt); + doSendMail( (sockHinet > 0) ? sockHinet : sockPTT2, + fp, buf, mq.rcpt, mq.subject); + } + fclose(fp); + unlink(mq.filepath); + } else { + perror(mq.filepath); + } + } + flock(fd, LOCK_UN); + close(fd); + unlink(NEWINDEX); + + if( sockHinet > 0 ) + disconnectMailServer(sockHinet); + disconnectMailServer(sockPTT2); +} + +void listQueue() { + int fd; + + if((fd = open(INDEX, O_RDONLY)) >= 0) { + int counter = 0; + MailQueue mq; + + flock(fd, LOCK_EX); + while(read(fd, &mq, sizeof(mq)) > 0) { + printf("%s:%s -> %s:%s\n", mq.filepath, mq.username, mq.rcpt, + mq.subject); + counter++; + } + flock(fd, LOCK_UN); + close(fd); + printf("\nTotal: %d mails in queue\n", counter); + } else { + perror(INDEX); + } +} + +void usage() { + fprintf(stderr, "usage: outmail [-qh]\n"); +} + +void wakeup(int s) { +} + +int main(int argc, char **argv, char **envp) { + int ch; + + signal(SIGHUP, wakeup); + initsetproctitle(argc, argv, envp); + + if(chdir(BBSHOME)) + return 1; + while((ch = getopt(argc, argv, "qh")) != -1) { + switch(ch) { + case 'q': + listQueue(); + return 0; + default: + usage(); + return 0; + } + } + for(;;) { + sendMail(); + setproctitle("outmail: sleeping"); + sleep(60 * 3); /* send mail every 3 minute */ + } + return 0; +} diff --git a/util/initbbs.c b/util/initbbs.c new file mode 100644 index 00000000..ce6c4361 --- /dev/null +++ b/util/initbbs.c @@ -0,0 +1,223 @@ +/* $Id: initbbs.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" + +static void initDir() { + mkdir("adm", 0755); + mkdir("boards", 0755); + mkdir("etc", 0755); + mkdir("man", 0755); + mkdir("man/boards", 0755); + mkdir("out", 0755); + mkdir("tmp", 0755); +} + +static void initHome() { + int i; + char buf[256]; + + mkdir("home", 0755); + strcpy(buf, "home/?"); + for(i = 0; i < 26; i++) { + buf[5] = 'A' + i; + mkdir(buf, 0755); + buf[5] = 'a' + i; + mkdir(buf, 0755); + } +} + +static void initPasswds() { + int i; + userec_t u; + FILE *fp = fopen(".PASSWDS", "w"); + + memset(&u, 0, sizeof(u)); + if(fp) { + for(i = 0; i < MAX_USERS; i++) + fwrite(&u, sizeof(u), 1, fp); + fclose(fp); + } +} + +static void newboard(FILE *fp, boardheader_t *b) { + char buf[256]; + + fwrite(b, sizeof(boardheader_t), 1, fp); + sprintf(buf, "boards/%s", b->brdname); + mkdir(buf, 0755); + sprintf(buf, "man/boards/%s", b->brdname); + mkdir(buf, 0755); +} + +static void initBoards() { + FILE *fp = fopen(".BOARDS", "w"); + boardheader_t b; + + if(fp) { + memset(&b, 0, sizeof(b)); + + strcpy(b.brdname, "SYSOP"); + strcpy(b.title, "¼Tù ¡·¯¸ªø¦n!"); + b.brdattr = BRD_POSTMASK | BRD_NOTRAN | BRD_NOZAP; + b.level = 0; + b.gid = 2; + + newboard(fp, &b); + strcpy(b.brdname, "1..........."); + strcpy(b.title, ".... £U¤¤¥¡¬F©² ¡m°ªÀ£¦MÀI,«D¤H¥i¼Ä¡n"); + b.brdattr = BRD_GROUPBOARD; + b.level = PERM_SYSOP; + b.gid = 1; + newboard(fp, &b); + + strcpy(b.brdname, "junk"); + strcpy(b.title, "µo¹q ¡·Âø¤CÂø¤Kªº©U§£"); + b.brdattr = BRD_NOTRAN; + b.level = PERM_SYSOP; + b.gid = 2; + newboard(fp, &b); + + strcpy(b.brdname, "Security"); + strcpy(b.title, "µo¹q ¡·¯¸¤º¨t²Î¦w¥þ"); + b.brdattr = BRD_NOTRAN; + b.level = PERM_SYSOP; + b.gid = 2; + newboard(fp, &b); + + strcpy(b.brdname, "2..........."); + strcpy(b.title, ".... £U¥«¥Á¼s³õ ³ø§i ¯¸ªø £¡I"); + b.brdattr = BRD_GROUPBOARD; + b.level = 0; + b.gid = 1; + newboard(fp, &b); + + strcpy(b.brdname, "ALLPOST"); + strcpy(b.title, "¼Tù ¡·¸óªO¦¡LOCAL·s¤å³¹"); + b.brdattr = BRD_POSTMASK | BRD_NOTRAN; + b.level = PERM_SYSOP; + b.gid = 5; + newboard(fp, &b); + + strcpy(b.brdname, "deleted"); + strcpy(b.title, "¼Tù ¡·¸ê·½¦^¦¬µ©"); + b.brdattr = BRD_NOTRAN; + b.level = PERM_BM; + b.gid = 5; + newboard(fp, &b); + + strcpy(b.brdname, "Note"); + strcpy(b.title, "¼Tù ¡·°ÊºA¬ÝªO¤Îºq¦±§ë½Z"); + b.brdattr = BRD_NOTRAN; + b.level = 0; + b.gid = 5; + newboard(fp, &b); + + strcpy(b.brdname, "Record"); + strcpy(b.title, "¼Tù ¡·§Ú̪º¦¨ªG"); + b.brdattr = BRD_NOTRAN | BRD_POSTMASK; + b.level = 0; + b.gid = 5; + newboard(fp, &b); + + + strcpy(b.brdname, "WhoAmI"); + strcpy(b.title, "¼Tù ¡·¨þ¨þ¡A²q²q§Ú¬O½Ö¡I"); + b.brdattr = BRD_NOTRAN; + b.level = 0; + b.gid = 5; + newboard(fp, &b); + + strcpy(b.brdname, "EditExp"); + strcpy(b.title, "¼Tù ¡·½d¥»ºëÆF§ë½Z°Ï"); + b.brdattr = BRD_NOTRAN; + b.level = 0; + b.gid = 5; + newboard(fp, &b); + + fclose(fp); + } +} + +static void initMan() { + FILE *fp; + fileheader_t f; + time_t t = time(NULL); + struct tm *tm = localtime(&t); + + memset(&f, 0, sizeof(f)); + f.savemode = 0; + strcpy(f.owner, "SYSOP"); + sprintf(f.date, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday); + f.money = 0; + f.filemode = 0; + + if((fp = fopen("man/boards/Note/.DIR", "w"))) { + strcpy(f.filename, "SONGBOOK"); + strcpy(f.title, "¡» ¡iÂI ºq ºq ¥»¡j"); + fwrite(&f, sizeof(f), 1, fp); + mkdir("man/boards/Note/SONGBOOK", 0755); + + strcpy(f.filename, "SONGO"); + strcpy(f.title, "¡» <ÂIºq> °ÊºA¬ÝªO"); + fwrite(&f, sizeof(f), 1, fp); + mkdir("man/boards/Note/SONGO", 0755); + + strcpy(f.filename, "SYS"); + strcpy(f.title, "¡» <¨t²Î> °ÊºA¬ÝªO"); + fwrite(&f, sizeof(f), 1, fp); + mkdir("man/boards/Note/SYS", 0755); + + strcpy(f.filename, "AD"); + strcpy(f.title, "¡» <¼s§i> °ÊºA¬ÝªO"); + fwrite(&f, sizeof(f), 1, fp); + mkdir("man/boards/Note/AD", 0755); + + strcpy(f.filename, "NEWS"); + strcpy(f.title, "¡» <·s»D> °ÊºA¬ÝªO"); + fwrite(&f, sizeof(f), 1, fp); + mkdir("man/boards/Note/NEWS", 0755); + + fclose(fp); + } + +} + +static void initSymLink() { + symlink(BBSHOME "/man/boards/Note/SONGBOOK", BBSHOME "/etc/SONGBOOK"); + symlink(BBSHOME "/man/boards/Note/SONGO", BBSHOME "/etc/SONGO"); + symlink(BBSHOME "/man/boards/EditExp", BBSHOME "/etc/editexp"); +} + +static void initHistory() { + FILE *fp = fopen("etc/history.data", "w"); + + if(fp) { + fprintf(fp, "0 0 0 0"); + fclose(fp); + } +} + +int main() { + if(chdir(BBSHOME)) { + perror(BBSHOME); + exit(1); + } + + initDir(); + initHome(); + initPasswds(); + initBoards(); + initMan(); + initSymLink(); + initHistory(); + + return 0; +} diff --git a/util/inndBM.c b/util/inndBM.c new file mode 100644 index 00000000..426fa6f5 --- /dev/null +++ b/util/inndBM.c @@ -0,0 +1,194 @@ +/* ¨Ì¾Ú .BOARDÀÉ & newsfeeds.bbs ¦C¥X°Ñ»PÂà«Hªº©Ò¦³ªO¸ê®Æ */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include "config.h" +#include "pttstruct.h" +#define INNDHOME BBSHOME"/innd" + +#define INND_NEWSFEED INNDHOME "/newsfeeds.bbs" +#define INND_NODELIST INNDHOME "/nodelist.bbs" +#define INND_SCRIPT INNDHOME "/bbsnnrpall.auto.sh" + +extern bcache_t *brdshm; +extern boardheader_t *bcache; +extern int numboards; +int istran[MAX_BOARD]; + +typedef +struct newssvr_t +{ + char name[30]; + char address[256]; + char type[10]; +}newssvr_t; + +typedef +struct newsfeed_t +{ + char group[128]; + char board[15]; + char server[30]; +}newsfeed_t; + +newssvr_t server[128]; +newsfeed_t feedline[MAX_BOARD]; +int servercount; +int feedcount; + +int newsfeed_cmp(newsfeed_t *a,newsfeed_t *b) +{ + int i; + i=strcasecmp(a->server,b->server); + if(i) return i; + return strcasecmp(a->board,b->board); +} + +int get_server(char *name) +{ + int i; + for(i=0;i<servercount;i++) + if(!strcasecmp(server[i].name,name)) + {return i;} + return -1; +} + +int load_server() +{ + FILE *fp; + char str[128]; + + if (!(fp = fopen(INND_NODELIST, "r"))) + { + return 0; + } + + for(servercount=0; fgets(str, 128, fp); servercount++) + { + if(str[0]=='#') continue; + sscanf(str,"%s %s %s",server[servercount].name, + server[servercount].address, + server[servercount].type); + } + fclose(fp); + return servercount; +} + +int load_newsfeeds() +{ + int bid; + FILE *fp; + char str[128]; + if (!(fp = fopen(INND_NEWSFEED, "r"))) + { + return 0; + } + + for(feedcount=0; fgets(str, 128, fp); feedcount++) + { + if(str[0]=='#') continue; + sscanf(str,"%s %s %s", + feedline[feedcount].group,feedline[feedcount].board, + feedline[feedcount].server); + bid=getbnum(feedline[feedcount].board); + if(!bid) {feedcount--;continue; /*²¾°£¨S¦³ªº¬ÝªOi*/} + strcpy(feedline[feedcount].board,bcache[bid-1].brdname); + /*®Õ¥¿¤j¤p¼g */ + + istran[bid-1]=1; + + } + fclose(fp); + qsort(feedline, feedcount, sizeof(newsfeed_t), newsfeed_cmp); + return feedcount; +} +int dobbsnnrp(char *serverstr, int serverid,FILE *fpscript) +{ + char buf[256]; + printf("set %s\r\n",serverstr); + strtok(serverstr,";\r\n"); + strtok(server[serverid].address,";\r\n"); //¨¾hack + sprintf(buf,INNDHOME"/bbsnnrp -c %s " + INNDHOME"/active/%s.auto.active >>" + INNDHOME"/log/inndBM.log 2>>" + INNDHOME"/log/inndBM.log.err &\r\n", + server[serverid].address, + serverstr); + system(buf); + if(fpscript) + fprintf(fpscript,INNDHOME"/bbsnnrp %s " + INNDHOME"/active/%s.auto.active >>" + INNDHOME"/log/inndBM.log 2>>" + INNDHOME"/log/inndBM.log.err &\r\n", + server[serverid].address,serverstr); + return 0; +} +int main() +{ + int i,serverid=0; + FILE *fp=NULL,*fpscript=fopen(INND_SCRIPT,"w"); + char buf[256],serverstr[30]=""; + resolve_boards(); + memset(istran,0,sizeof(int)*MAX_BOARD); + load_server(); + load_newsfeeds(); + + for(i=0;i<feedcount;i++) + { + if(strcasecmp(serverstr,feedline[i].server)) + { + if(get_server(feedline[i].server)==-1) continue; + if(fp) { + fclose(fp); + dobbsnnrp(serverstr,serverid,fpscript); + } + strcpy(serverstr,feedline[i].server); + serverid=get_server(feedline[i].server); + sprintf(buf,INNDHOME"/active/%s.auto.active",serverstr); + fp=fopen(buf,"w"); + } + if(fp) + fprintf(fp,"%-35s 0000000000 0000000000 y\r\n",feedline[i].group); + } + if(fp) + { + dobbsnnrp(serverstr,serverid,fpscript); + fclose(fp); + } + if(fpscript) + { + fclose(fpscript); + chmod(INND_SCRIPT,0700); + } + + // «³]Âà«H»P¤£Âà«Hª©¼Ð°O + for(i=0;i<numboards;i++) + { + if(bcache[i].brdname[0]=='\0' || + (bcache[i].brdattr & BRD_GROUPBOARD) ) continue; + if((bcache[i].brdattr & BRD_NOTRAN )&& istran[i]) + { + while(brdshm->busystate) {safe_sleep(1);} + brdshm->busystate = 1; + bcache[i].brdattr = bcache[i].brdattr & ~BRD_NOTRAN; + strncpy(bcache[i].title + 5, "¡´", 2); + brdshm->busystate = 0; + + substitute_record(BBSHOME"/.BOARDS", &bcache[i],sizeof(boardheader_t),i+1); + } + else if(!(bcache[i].brdattr & BRD_NOTRAN) && !istran[i]) + { + while(brdshm->busystate) {safe_sleep(1);} + brdshm->busystate = 1; + bcache[i].brdattr = bcache[i].brdattr | BRD_NOTRAN; + strncpy(bcache[i].title + 5, "¡·", 2); + brdshm->busystate = 0; + substitute_record(BBSHOME"/.BOARDS", &bcache[i],sizeof(boardheader_t),i+1); + } + + } + return 0; +} diff --git a/util/jungo.c b/util/jungo.c new file mode 100644 index 00000000..15096b30 --- /dev/null +++ b/util/jungo.c @@ -0,0 +1,202 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" + +#define OUTFILE BBSHOME "/etc/toplazyBBM" +#define FIREFILE BBSHOME "/etc/topfireBBM" + +extern boardheader_t *bcache; +extern int numboards; + +boardheader_t allbrd[MAX_BOARD]; +extern userec_t xuser; +typedef struct lostbm { + char *bmname; + char *title; + char *ctitle; + int lostdays; +} lostbm; +lostbm lostbms[MAX_BOARD]; + +typedef struct BMarray{ + char *bmname; + int flag; +} BMArray; +BMArray bms[3]; + +int bmlostdays_cmp(const void *va, const void *vb) +{ + lostbm *a=(lostbm *)va, *b=(lostbm *)vb; + if (a->lostdays > b->lostdays) return -1; + else if (a->lostdays == b->lostdays) return 0; + else return 1; +} + +int LINK(char* src, char* dst){ + char cmd[200]; + if(symlink(src,dst) == -1) + { + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int bmid, i, j=0; + FILE *inf, *firef; + + resolve_boards(); + + if(passwd_mmap()) + exit(1); + + memcpy(allbrd,bcache,numboards*sizeof(boardheader_t)); + + /* write out the target file */ + + inf = fopen(OUTFILE, "w+"); + if(inf == NULL){ + printf("open file error : %s\n", OUTFILE); + exit(1); + } + firef = fopen(FIREFILE, "w+"); + if(firef == NULL){ + printf("open file error : %s\n", FIREFILE); + fclose(inf); + exit(1); + } + + fprintf(inf, "ĵ§i: ¤p²ÕªøY©ó¤@Ӥ를¤W¯¸,±N¤©©ó§K¾\n"); + fprintf(inf, + "¬ÝªO¦WºÙ " + " ¤p²Õªø ´X¤Ñ¨S¨Ó°Õ\n" + "---------------------------------------------------" + "-------------------\n"); + + fprintf(firef, "§K¾¤p²Õªø\n"); + fprintf(firef, + "¬ÝªO¦WºÙ " + " ¤p²Õªø ´X¤Ñ¨S¨Ó°Õ\n" + "---------------------------------------------------" + "-------------------\n"); + + + j = 0 ; + for (i = 0; i < numboards; i++) { + char *p, bmbuf[IDLEN * 3 + 3]; + int index = 0, flag = 0, k, n; + p=strtok(allbrd[i].BM,"/ "); + if(p) + do + { + if(allbrd[i].brdname[0] == '\0' || (allbrd[i].brdattr & BRD_GROUPBOARD) ==0 ) continue; + if (*p == '[' ){p[strlen(p)-1]='\0'; p++;} + bmid=getuser(p); + bms[index].bmname = p; + bms[index].flag = 0; + if (((((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24))>=7) + //&& isalpha(allbrd[i].brdname[0]) + && isalpha(allbrd[i].BM[0]) + && !(xuser.userlevel & PERM_SYSOP)) + { + lostbms[j].bmname = p; + lostbms[j].title = allbrd[i].brdname; + lostbms[j].ctitle = allbrd[i].title; + lostbms[j].lostdays = + ((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24); + + printf("%s\n", lostbms[j].title); + //¶W¹L¤»¤Q¤Ñ §K¾ + if(lostbms[j].lostdays > 30){ + xuser.userlevel &= ~PERM_BM; + bms[index].flag = 1; + flag = 1; + } + j++; + } + index++; + } while((p=strtok(NULL,"/ "))!=NULL); + + //±qª©¥D¦W³æ®³±¼¦W¦r + + if(flag == 1){ + bmbuf[0] = '\0'; + for(k = 0 , n = 0; k < index; k++){ + if(!bms[k].flag){ + if( n++ != 0) strcat(bmbuf, "/"); + strcat(bmbuf, bms[k].bmname); + } + } + strcpy(bcache[i].BM, bmbuf); + } + + } + qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp); + + //write to the etc/toplazyBBM + for ( i=0; i<j; i++) + { + if( lostbms[i].lostdays > 7){ + fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + }else{ + fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + } + } + fclose(inf); + fclose(firef); + + //printf("Total %d boards.\n", count); + + //mail to the users + for( i=0; i<j; i++) + { + fileheader_t mymail; + char genbuf[200]; + int lostdays; + + lostdays = lostbms[i].lostdays; + + if( (lostdays != 14) || (lostdays != 21) ) // 14 21 ¤Ñ¤£µo«H + continue; + + sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname); + stampfile(genbuf, &mymail); + + strcpy(mymail.owner, "[PTTĵ¹î§½]"); + + if(lostdays <= 60){ + sprintf(mymail.title, + "\033[32m [¤p²Õªø§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + }else{ + sprintf(mymail.title, + "\033[32m [¤p²Õªø§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + } + mymail.savemode = 0 ; + unlink(genbuf); + if(lostdays <= 60){ + LINK(OUTFILE, genbuf); + }else{ + LINK(FIREFILE, genbuf); + } + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); + append_record(genbuf, &mymail, sizeof(mymail)); + } + + return 0; +} diff --git a/util/kenben.c b/util/kenben.c new file mode 100644 index 00000000..5733f4da --- /dev/null +++ b/util/kenben.c @@ -0,0 +1,44 @@ +#include <stdio.h> + + +void main() +{ + FILE * fin, * fout; + char line[255], line2[255]; + int i; + char genbuf[255], tok[20]; + fin = fopen("M.1006277896.A","r"); + while(!feof(fin)) + { + fgets(line,255,fin); + line[12] = '\0'; + + sprintf(genbuf, "cd ~/boards/%s;grep " + "¶W¹L¤@Ó¤ëµL¼s§i¥H¥~ªº¥»¯¸¤å³¹µoªí¡C" + " *.A > ~/pttbbs/util/kenken.txt",line); + system(genbuf); + + fout = fopen("kenken.txt","r"); + while(!feof(fout)) + { + line2[0] = '\0'; + fgets(line2,255,fout); + if(strlen(line2) <= 10) break; + sscanf(line2,"%s:",tok); + for(i = 0; i < 20;i++) + { + if(tok[i] == ':') + { + tok[i] = '\0'; + break; + } + } + sprintf(genbuf, "cd ~/boards/%s;rm %s",line, tok); +// printf("%s \n", genbuf); + system(genbuf); + } + } + + fclose(fin); + +} diff --git a/util/mailog.sh b/util/mailog.sh new file mode 100644 index 00000000..da89ae3d --- /dev/null +++ b/util/mailog.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# $Id: mailog.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $ +# +# ¾ã²z¥X¼s§i«H¦W³æ + +bin/antispam +bin/post Record ¤µ¤é¹Hªk¼s§i«H¦W³æ [Pttĵ¹î§½] etc/spam +bin/post Security ¯¸¥~¨Ó«H¬ö¿ýmailog [¨t²Î¦w¥þ§½] etc/mailog +rm etc/mailog diff --git a/util/mandex.c b/util/mandex.c new file mode 100644 index 00000000..9373f814 --- /dev/null +++ b/util/mandex.c @@ -0,0 +1,263 @@ +/* $Id: mandex.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ + +/* + target : ºëµØ°Ï¯Á¤Þµ{¦¡ (man index) + + syntax : mandex [board] + [board] ¦³È ==> ¥u¶]¸Ó board + ªÅªº ==> ©Ò¦³ªº boards ³£¶] +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +extern int numboards; +extern boardheader_t *bcache; + +char color[4][10] = +{"[1;33m", "[1;32m", "[1;36m", "[1;37m"}; +char fn_index[] = ".index"; +char fn_new[] = ".index.new"; +char index_title[] = "¡· ºëµØ°Ï¥Ø¿ý¯Á¤Þ"; +FILE *fndx; +int ndir; +int nfile; +int index_pos; +char topdir[128], pgem[512], pndx[512]; + +int nb = 0; /* board ¼Æ */ + +struct boardinfo +{ + char bname[40]; + int ndir; + int nfile; + int k; +}; +typedef struct boardinfo boardinfo; + +boardinfo +board[MAX_BOARD]; + +int k_cmp(b, a) + boardinfo *b, *a; +{ + return ((a->k / 100 + a->ndir + a->nfile) - (b->k / 100 + b->ndir + b->nfile)); +} + +int dashd(fname) + char *fname; +{ + struct stat st; + + return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); +} + + +/* visit the hierarchy recursively */ + +void +mandex(level, num_header, fpath) + int level; + char *fpath, *num_header; +{ + FILE *fgem; + char *fname, buf[256]; + struct stat st; + int count; + fileheader_t fhdr; + + fgem = fopen(fpath, "r+"); + if (fgem == NULL) + return; + + fname = strrchr(fpath, '.'); + if (!level) + { + + printf("%s\r\n",fpath); + strcpy(pgem, fpath); + + strcpy(fname, fn_new); + fndx = fopen(fpath, "w"); + if (fndx == NULL) + { + fclose(fgem); + return; + } + fprintf(fndx, "[1;32m§Ç¸¹\t\t\tºëµØ°Ï¥DÃD[m\n" + "[36m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w[m\n"); + strcpy(pndx, fpath); + ndir = nfile = 0; + index_pos = -1; + } + + count = 0; + while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1) + { + strcpy(fname, fhdr.filename); + if (!fname[0]) continue; + if (!level && !strncmp(fhdr.title, index_title, strlen(index_title)) + && index_pos < 0) + { + index_pos = count; + unlink(fpath); + } + st.st_size = 0; + stat(fpath, &st); + + sprintf(buf, "%.*s%s%3d. %s [m\n", + + 11 * level, num_header, color[level % 4], ++count, fhdr.title); /* Ptt */ + fputs(buf, fndx); + if (dashd(fpath)) + { + ++ndir; + if (*fhdr.title != '#' && level < 10) + { + strcat(fpath, "/.DIR"); + mandex(level + 1, buf, fpath); + } + } + else + ++nfile; + } + + if (!level) + { + char lpath[MAXPATHLEN]; + + fclose(fndx); + strcpy(fname, fn_index); + rename(pndx, fpath); + strcpy(pndx, fpath); + + sprintf(buf, "%s.new", pgem); + if (index_pos >= 0 || (fndx = fopen(buf, "w"))) + { + fname[-1] = 0; + stamplink(fpath, &fhdr); + unlink(fpath); + strcpy(fhdr.owner, "¨C¤Ñ¦Û°Ê§ó·s"); + sprintf(lpath, "%s/%s", topdir, pndx); + st.st_size = 0; + stat(lpath, &st); + sprintf(fhdr.title, "%s (%.1fk)", index_title, st.st_size / 1024.); + board[nb].k = st.st_size; /* Ptt */ + printf("(%d)[%dK]", nb, board[nb].k); + symlink(lpath, fpath); + if (index_pos < 0) + { + fwrite(&fhdr, sizeof(fhdr), 1, fndx); + rewind(fgem); + while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1) + fwrite(&fhdr, sizeof(fhdr), 1, fndx); + fclose(fndx); + fclose(fgem); + rename(buf, pgem); + } + else + { + fseek(fgem, index_pos * sizeof(fhdr), 0); + fwrite(&fhdr, sizeof(fhdr), 1, fgem); + fclose(fgem); + } + return; + } + } + fclose(fgem); +} + + +int main(int argc, char* argv[]){ + boardheader_t *bptr; + DIR *dirp; + struct dirent *de; + int ch, n; + int place = 0; + char *fname, fpath[MAXPATHLEN]; + + resolve_boards(); + nb = 0; + if(argc == 1){ + puts("Creating the whole index..."); + chdir(strcpy(topdir, BBSHOME)); + strcpy(fpath, "man/.DIR"); + mandex(0, "", fpath); + } + + + chdir(strcpy(topdir, BBSHOME "/man/boards")); + + if(argc > 1) { + sprintf(fpath, "%s/.DIR", argv[1]); + mandex(0, "", fpath); + exit(0); + } + + /* process all boards */ + + if(!(dirp = opendir(topdir))) { + printf("## unable to enter [man/boards]\n"); + exit(-1); + } + + while((de = readdir(dirp))){ + fname = de->d_name; + ch = fname[0]; + if (ch != '.'){ + board[nb].k = 0; + strcpy(board[nb].bname, fname); + sprintf(fpath, "%s/.DIR", fname); + mandex(0, "", fpath); + printf("%-14sd: %d\tf: %d\n", fname, ndir, nfile); /* report */ + board[nb].ndir = ndir; + board[nb].nfile = nfile; + if (board[nb].k) + nb++; + } + } + closedir(dirp); + + qsort(board, nb, sizeof(boardinfo), k_cmp); + + if (!(fndx = fopen(BBSHOME "/etc/topboardman", "w"))) + exit(0); + + fprintf(fndx, "[1;44m±Æ¦W[47;30m ¬Ý ª© ¥Ø¿ý¼Æ ÀÉ®×¼Æ" + " byte¼Æ [30m Á` ¤À ª© ¥D [m\n"); + + for (ch = 0; ch < nb; ch++){ + for (n = 0; n < numboards; n++){ + bptr = &bcache[n]; + if (!strcmp(bptr->brdname, board[ch].bname)) + break; + } + if (n >= numboards || + (bptr->brdattr & (BRD_BAD | BRD_NOCOUNT | BRD_HIDE))) + continue; + if (board[ch].ndir + board[ch].nfile < 5) + break; + fprintf(fndx, "%3d.[33m%15s[m %5d %7d %10d %6d [31m%-24.24s[m\n", + ++place, + board[ch].bname, + board[ch].ndir, board[ch].nfile, board[ch].k + ,board[ch].k / 100 + board[ch].nfile + board[ch].ndir + ,bptr->BM); + } + fclose(fndx); + exit(0); +} diff --git a/util/merge_board.c b/util/merge_board.c new file mode 100644 index 00000000..743ffc14 --- /dev/null +++ b/util/merge_board.c @@ -0,0 +1,106 @@ +/* $Id: merge_board.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" + +typedef struct hash_t { + char *brdname; + struct hash_t *next; +} hash_t; + +FILE *fout; +hash_t *hash_tbl[65536]; +int counter; + +void usage() { + fprintf(stderr, "Usage:\n\n" + "merge_board <output file> [input file1] [input file2] ...\n"); +} + +unsigned int string_hash(unsigned char *s) { + unsigned int v=0; + + while(*s) { + v = (v << 8) | (v >> 24); + v ^= toupper(*s++); /* note this is case insensitive */ + } + return (v * 2654435769UL) >> (32 - 16); +} + +int is_exist(char *brdname) { + int i; + hash_t *n; + + i = string_hash(brdname); + for(n = hash_tbl[i]; n != NULL; n = n->next) + if(strcasecmp(brdname, n->brdname) == 0) + return 1; + return 0; +} + +void add_hash(char *brdname) { + int i; + hash_t *n; + + i = string_hash(brdname); + + n = malloc(sizeof(*n)); + n->brdname = strdup(brdname); + n->next = hash_tbl[i]; + hash_tbl[i] = n; +} + +void merge_board(boardheader_t *b) { + if(!is_exist(b->brdname)) { + fwrite(b, sizeof(*b), 1, fout); + add_hash(b->brdname); + ++counter; + } +} + +void merge_file(char *fname) { + FILE *fin; + boardheader_t b; + + if((fin = fopen(fname, "r")) == NULL) { + perror(fname); + return; + } + + counter = 0; + while(fread(&b, sizeof(b), 1, fin) == 1) + if(b.brdname[0]) + merge_board(&b); + + printf("merge from %s: %d boards\n", fname, counter); + + fclose(fin); +} + +int main(int argc, char **argv) { + int i; + + if(argc < 2) { + usage(); + return 1; + } + + bzero(hash_tbl, sizeof(hash_tbl)); + + if((fout = fopen(argv[1], "w")) == NULL) { + perror(argv[1]); + return 2; + } + + for(i = 2; i < argc; ++i) + merge_file(argv[i]); + + fclose(fout); + printf("Done\n"); + + return 0; +} diff --git a/util/merge_passwd.c b/util/merge_passwd.c new file mode 100644 index 00000000..d27c473b --- /dev/null +++ b/util/merge_passwd.c @@ -0,0 +1,106 @@ +/* $Id: merge_passwd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" + +typedef struct hash_t { + char *userid; + struct hash_t *next; +} hash_t; + +FILE *fout; +hash_t *hash_tbl[65536]; +int counter; + +void usage() { + fprintf(stderr, "Usage:\n\n" + "merge_passwd <output file> [input file1] [input file2] ...\n"); +} + +unsigned int string_hash(unsigned char *s) { + unsigned int v=0; + + while(*s) { + v = (v << 8) | (v >> 24); + v ^= toupper(*s++); /* note this is case insensitive */ + } + return (v * 2654435769UL) >> (32 - 16); +} + +int is_exist(char *userid) { + int i; + hash_t *n; + + i = string_hash(userid); + for(n = hash_tbl[i]; n != NULL; n = n->next) + if(strcasecmp(userid, n->userid) == 0) + return 1; + return 0; +} + +void add_hash(char *userid) { + int i; + hash_t *n; + + i = string_hash(userid); + + n = malloc(sizeof(*n)); + n->userid = strdup(userid); + n->next = hash_tbl[i]; + hash_tbl[i] = n; +} + +void merge_user(userec_t *u) { + if(!is_exist(u->userid)) { + fwrite(u, sizeof(*u), 1, fout); + add_hash(u->userid); + ++counter; + } +} + +void merge_file(char *fname) { + FILE *fin; + userec_t u; + + if((fin = fopen(fname, "r")) == NULL) { + perror(fname); + return; + } + + counter = 0; + while(fread(&u, sizeof(u), 1, fin) == 1) + if(u.userid[0]) + merge_user(&u); + + printf("merge from %s: %d users\n", fname, counter); + + fclose(fin); +} + +int main(int argc, char **argv) { + int i; + + if(argc < 2) { + usage(); + return 1; + } + + bzero(hash_tbl, sizeof(hash_tbl)); + + if((fout = fopen(argv[1], "w")) == NULL) { + perror(argv[1]); + return 2; + } + + for(i = 2; i < argc; ++i) + merge_file(argv[i]); + + fclose(fout); + printf("Done\n"); + + return 0; +} diff --git a/util/opendice.sh b/util/opendice.sh new file mode 100644 index 00000000..767e213a --- /dev/null +++ b/util/opendice.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id: opendice.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $ + +bin/countalldice > etc/dice.dis +bin/post Record "»ë¤l¤¤¼ú¦W³æ" "[»ë¤l³ø§i]" etc/windice.log +bin/post Security "»ë¤l¥¢±Ñ¦W³æ" "[»ë¤l³ø§i]" etc/lostdice.log +bin/post Security "»ë¤l´Á±æÈ" "[»ë¤l³ø§i]" etc/dice.dis +rm -f etc/windice.log +rm -f etc/lostdice.log +rm -f etc/dice.dis diff --git a/util/openticket.c b/util/openticket.c new file mode 100644 index 00000000..69b9ab2a --- /dev/null +++ b/util/openticket.c @@ -0,0 +1,198 @@ +/* $Id: openticket.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* ¶}¼úªº utility */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "util.h" + + +static char *betname[8] = {"Ptt", "Jaky", "Action", "Heat", + "DUNK", "Jungo", "waiting", "wofe"}; + +#define MAX_DES 7 /* ³Ì¤j«O¯d¼ú¼Æ */ + +extern userec_t xuser; + +int Link(char *src, char *dst) +{ + char cmd[200]; + + if (link(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +char * + Cdatelite(clock) +time_t *clock; +{ + static char foo[18]; + struct tm *mytm = localtime(clock); + + strftime(foo, 18, "%D %T", mytm); + return (foo); +} + + +int main() +{ + int money, bet, n, total = 0, ticket[8] = + {0, 0, 0, 0, 0, 0, 0, 0}; + FILE *fp; + time_t now = time(NULL); + char des[MAX_DES][200] = + {"", "", "", ""}; + extern struct utmpfile_t *utmpshm; + + if(passwd_mmap()) + exit(1); + + rename(BBSHOME "/etc/" FN_TICKET_RECORD, + BBSHOME "/etc/" FN_TICKET_RECORD ".tmp"); + rename(BBSHOME "/etc/" FN_TICKET_USER, + BBSHOME "/etc/" FN_TICKET_USER ".tmp"); + + if (!(fp = fopen(BBSHOME "/etc/"FN_TICKET_RECORD ".tmp", "r"))) + return 0; + fscanf(fp, "%9d %9d %9d %9d %9d %9d %9d %9d\n", + &ticket[0], &ticket[1], &ticket[2], &ticket[3], + &ticket[4], &ticket[5], &ticket[6], &ticket[7]); + for (n = 0; n < 8; n++) + total += ticket[n]; + fclose(fp); + + if (!total) + return 0; + + if((fp = fopen(BBSHOME "/etc/" FN_TICKET , "r"))) + { + for (n = 0; n < MAX_DES && fgets(des[n], 200, fp); n++) ; + fclose(fp); + } + +/* + *srandom(33); // ©T©w¤@Ó seed ¦ýºÉ¶qnÁקK¸ò§O¤Hªºseed¦P + * + *for( n = (now / (60*60*3)) - 62820; n >0; n--) random(); + */ + +/* + * ¥¿½Tªºrandom number generatorªº¥Îªk + * ¬O¥Î¦P¤@Ó seed«á¨ú ²Ä¤@Ó ²Ä¤GÓ ¦a¤TÓ.... ¼Æ + * srand() ³]§¹seed«á + * ¨C©I¥s¤@¦¸rand()´N¨ú¤U¤@Ó¼Æ + * + * ¦ý¦]¬°§Ų́S¦³°O¿ý¤W¦¸¨ú¨ì²Ä´XÓ + * ©Ò¥H¥Î¨C¼W¥|¤p®É()´N¦h¨ú¤@¦¸ => now / (60*60*4) (¨C¤¤p®É¶}¤@¦¸¼ú) + * (´î 61820 ¬O´î¤Ö loop ¼Æ) + * + * ¥»¨Ó¬O¥Îsrand(time(0)) ¤£¬O¥¿½Tªº¥Îªk + * ¦]¬°¶}¼ú®É¶¡¦³³W²v ©Ò¥H·|³Q§ä¥X³W«ß + * + * ~Ptt + */ +/* + *bet=random() % 8; + */ + + resolve_utmp(); + bet = utmpshm->number % 8; + +/* + + * ¦bC¤¤ srand ¸ò srandom ¤@¼Ë rand ¸ò random ¤@¼Ë + * ¤£¦Pªº¬O rand ¬O¶Ç¦^¤@Ó double µ¹«D¾ã¼Æªº¶Ã¼Æ¥Î + * random ¬O¶Ç¦^¤@Ó int µ¹¾ã¼Æªº¶Ã¼Æ¥Î + * + * Yn¥Hrand inplement ¾ã¼Æªº¶Ã¼Æ nª`·N¥H¤U (man page¤¤¦³) + * + * In Numerical Recipes in C: The Art of Scientific Computing + * (William H. Press, Brian P. Flannery, Saul A. Teukolsky, + * William T. Vetterling; New York: Cambridge University + * Press, 1990 (1st ed, p. 207)), the following comments are + * made: + * "If you want to generate a random integer between 1 + * and 10, you should always do it by + * + * j=1+(int) (10.0*rand()/(RAND_MAX+1.0)); + * + * and never by anything resembling + * + * j=1+((int) (1000000.0*rand()) % 10); + * + * (which uses lower-order bits)." + * + * Random-number generation is a complex topic. The Numeri- + * cal Recipes in C book (see reference above) provides an + * excellent discussion of practical random-number generation + * issues in Chapter 7 (Random Numbers). + * ~ Ptt + */ + + + money = ticket[bet] ? total * 95 / ticket[bet] : 9999999; + + if((fp = fopen(BBSHOME "/etc/" FN_TICKET, "w"))) + { + if (des[MAX_DES - 1][0]) + n = 1; + else + n = 0; + + for (; n < MAX_DES && des[n][0] != 0; n++) + { + fprintf(fp, des[n]); + } + + printf("\n\n¶}¼ú®É¶¡¡G %s \n\n" + "¶}¼úµ²ªG¡G %s \n\n" + "¤Uª`Á`ª÷ÃB¡G %d00 ¤¸ \n" + "¤¤¼ú¤ñ¨Ò¡G %d±i/%d±i (%f)\n" + "¨C±i¤¤¼ú±m²¼¥i±o %d ªT¢Þ¹ô \n\n", + Cdatelite(&now), betname[bet], total, ticket[bet], total, + (float) ticket[bet] / total, money); + + fprintf(fp, "%s ½ä½L¶}¥X:%s Á`ª÷ÃB:%d00 ¤¸ ¼úª÷/±i:%d ¤¸ ¾÷²v:%1.2f\n", + Cdatelite(&now), betname[bet], total, money, + (float) ticket[bet] / total); + fclose(fp); + + } + + if (ticket[bet] && (fp = fopen(BBSHOME "/etc/" FN_TICKET_USER ".tmp", "r"))) + { + int mybet, num, uid; + char userid[20], genbuf[200]; + fileheader_t mymail; + + while (fscanf(fp, "%s %d %d\n", userid, &mybet, &num) != EOF) + { + if (mybet == bet) + { + printf("®¥³ß %-15s¶R¤F%9d ±i %s, Àò±o %d ªT¢Þ¹ô\n" + ,userid, num, betname[mybet], money * num); + if((uid=getuser(userid))==0) continue; + deumoney(uid, money * num); + sprintf(genbuf, BBSHOME "/home/%c/%s", userid[0], userid); + stampfile(genbuf, &mymail); + strcpy(mymail.owner, BBSNAME); + sprintf(mymail.title, "[%s] ¤¤¼úÅo! $ %d", Cdatelite(&now), money * num); + mymail.savemode = 0; + unlink(genbuf); + Link(BBSHOME "/etc/ticket", genbuf); + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", userid[0], userid); + append_record(genbuf, &mymail, sizeof(mymail)); + } + } + } + unlink(BBSHOME "/etc/" FN_TICKET_RECORD ".tmp"); + unlink(BBSHOME "/etc/" FN_TICKET_USER ".tmp"); + return 0; +} diff --git a/util/openticket.sh b/util/openticket.sh new file mode 100644 index 00000000..8274e5c3 --- /dev/null +++ b/util/openticket.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# $Id: openticket.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $ + +bin/openticket > etc/jackpot +bin/post Record "±m¨é¤¤¼ú¦W³æ" "[½ä³õ³ø§i]" etc/jackpot +bin/post Record "²q¼Æ¦r¤¤¼ú¦W³æ" "[²q¼Æ¦r³ø§i]" etc/winguess.log +bin/post Record "¶Â¥Õ´Ñ¹ï¾Ô°O¿ý" "[²q¼Æ¦r³ø§i]" etc/othello.log +rm -f etc/winguess.log +rm -f etc/loseguess.log +rm -f etc/othello.log diff --git a/util/openvice.c b/util/openvice.c new file mode 100644 index 00000000..9b5e438f --- /dev/null +++ b/util/openvice.c @@ -0,0 +1,54 @@ +/* $Id: openvice.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* µo²¼¶}¼ú¤pµ{¦¡ */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#define VICE_SHOW BBSHOME "/etc/vice.show1" +#define VICE_BINGO BBSHOME "/etc/vice.bingo" +#define VICE_NEW "vice.new" +#define VICE_DATA "vice.data" +#define MAX_BINGO 99999999 + +int main() +{ + char TABLE[5][3] = + {"¤@", "¤G", "¤T", "¥|", "¤"}; + + int i = 0, bingo, base = 0; + + + FILE *fp = fopen(VICE_SHOW, "w"), *fb = fopen(VICE_BINGO, "w"); + + extern struct utmpfile_t *utmpshm; + resolve_utmp(); + + srand(utmpshm->number); + + if (!fp || !fb ) + perror("error open file"); + + + bingo = rand() % MAX_BINGO; + fprintf(fp, "%1c[1;33m²Î¤@µo²¼¤¤¼ú¸¹½X[m\n", ' '); + fprintf(fp, "%1c[1;37m================[m\n", ' '); + fprintf(fp, "%1c[1;31m¯S§O¼ú[m: [1;31m%08d[m\n\n", ' ', bingo); + fprintf(fb, "%d\n", bingo); + + while (i < 5) + { + bingo = (base + rand()) % MAX_BINGO; + fprintf(fp, "%1c[1;36m²Ä%s¼ú[m: [1;37m%08d[m\n", ' ', TABLE[i], bingo); + fprintf(fb, "%08d\n", bingo); + i++; + } + fclose(fp); + fclose(fb); + return 0; +} diff --git a/util/outmail.c b/util/outmail.c new file mode 100644 index 00000000..d6b19bb4 --- /dev/null +++ b/util/outmail.c @@ -0,0 +1,274 @@ +/* $Id: outmail.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "pttstruct.h" + + +#ifdef HAVE_SETPROCTITLE + +#include <sys/types.h> +#include <libutil.h> + +void initsetproctitle(int argc, char **argv, char **envp) { +} + +#else + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ +extern char **environ; + +void initsetproctitle(int argc, char **argv, char **envp) { + register int i; + + /* Move the environment so setproctitle can use the space at + the top of memory. */ + for(i = 0; envp[i]; i++); + environ = malloc(sizeof(char *) * (i + 1)); + for(i = 0; envp[i]; i++) + environ[i] = strdup(envp[i]); + environ[i] = NULL; + + /* Save start and extent of argv for setproctitle. */ + Argv = argv; + if(i > 0) + LastArgv = envp[i - 1] + strlen(envp[i - 1]); + else + LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); +} + +static void do_setproctitle(const char *cmdline) { + char buf[256], *p; + int i; + + strncpy(buf, cmdline, 256); + buf[255] = '\0'; + i = strlen(buf); + if(i > LastArgv - Argv[0] - 2) { + i = LastArgv - Argv[0] - 2; + } + strcpy(Argv[0], buf); + p = &Argv[0][i]; + while(p < LastArgv) + *p++='\0'; + Argv[1] = NULL; +} + +void setproctitle(const char* format, ...) { + char buf[256]; + + va_list args; + va_start(args, format); + vsprintf(buf, format,args); + do_setproctitle(buf); + va_end(args); +} +#endif + + + + + +#define SPOOL BBSHOME "/out" +#define INDEX SPOOL "/.DIR" +#define NEWINDEX SPOOL "/.DIR.sending" +#define FROM ".bbs@" MYHOSTNAME +#define SMTPPORT 25 + +int waitReply(int sock) { + char buf[256]; + + if(read(sock, buf, sizeof(buf)) <= 0) + return -1; + else + return buf[0] - '0'; +} + +int sendRequest(int sock, char *request) { + return write(sock, request, strlen(request)) < 0 ? -1 : 0; +} + +int connectMailServer() { + int sock; + struct sockaddr_in addr; + + if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); +#ifdef FreeBSD + addr.sin_len = sizeof(addr); +#endif + addr.sin_family = AF_INET; + addr.sin_port = htons(SMTPPORT); + addr.sin_addr.s_addr = inet_addr(RELAY_SERVER_IP); + + if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror(RELAY_SERVER_IP); + close(sock); + return -1; + } + + if(waitReply(sock) != 2) { + close(sock); + return -1; + } + + if(sendRequest(sock, "helo " MYHOSTNAME "\n") || waitReply(sock) != 2) { + close(sock); + return -1; + } else + return sock; +} + +void disconnectMailServer(int sock) { + sendRequest(sock, "quit\n"); + /* drop the reply :p */ + close(sock); +} + +void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) { + int n; + char buf[2048]; + + n = snprintf(buf, sizeof(buf), "From: %s\nTo: %s\nSubject: %s\n\n", + from, to, subject); + write(sock, buf, n); + + while(fgets(buf, sizeof(buf), fp)) { + if(buf[0] == '.' && buf[1] == '\n') + strcpy(buf, "..\n"); + write(sock, buf, strlen(buf)); + } +} + +void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) { + char buf[256]; + + snprintf(buf, sizeof(buf), "mail from: %s\n", from); + if(sendRequest(sock, buf) || waitReply(sock) != 2) + return; + + snprintf(buf, sizeof(buf), "rcpt to: %s\n", to); + if(sendRequest(sock, buf) || waitReply(sock) != 2) + return; + + if(sendRequest(sock, "data\n") || waitReply(sock) != 3) + return; + + doSendBody(sock, fp, from, to, subject); + + if(sendRequest(sock, "\n.\n") || waitReply(sock) != 2) + return; +} + +void sendMail() { + int fd, sock; + MailQueue mq; + + if(access(NEWINDEX, R_OK | W_OK)) { + if(link(INDEX, NEWINDEX) || unlink(INDEX)) + /* nothing to do */ + return; + } + + if((sock = connectMailServer()) < 0) { + fprintf(stderr, "connect server failed...\n"); + return; + } + + fd = open(NEWINDEX, O_RDONLY); + flock(fd, LOCK_EX); + while(read(fd, &mq, sizeof(mq)) > 0) { + FILE *fp; + char buf[256]; + + snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM); + if((fp = fopen(mq.filepath, "r"))) { + setproctitle("outmail: sending %s", mq.filepath); + doSendMail(sock, fp, buf, mq.rcpt, mq.subject); + fclose(fp); + unlink(mq.filepath); + } else { + perror(mq.filepath); + } + } + flock(fd, LOCK_UN); + close(fd); + unlink(NEWINDEX); + + disconnectMailServer(sock); +} + +void listQueue() { + int fd; + + if((fd = open(INDEX, O_RDONLY)) >= 0) { + int counter = 0; + MailQueue mq; + + flock(fd, LOCK_EX); + while(read(fd, &mq, sizeof(mq)) > 0) { + printf("%s:%s -> %s:%s\n", mq.filepath, mq.username, mq.rcpt, + mq.subject); + counter++; + } + flock(fd, LOCK_UN); + close(fd); + printf("\nTotal: %d mails in queue\n", counter); + } else { + perror(INDEX); + } +} + +void usage() { + fprintf(stderr, "usage: outmail [-qh]\n"); +} + +void wakeup(int s) { +} + +int main(int argc, char **argv, char **envp) { + int ch; + + signal(SIGHUP, wakeup); + initsetproctitle(argc, argv, envp); + + if(chdir(BBSHOME)) + return 1; + while((ch = getopt(argc, argv, "qh")) != -1) { + switch(ch) { + case 'q': + listQueue(); + return 0; + default: + usage(); + return 0; + } + } + for(;;) { + sendMail(); + setproctitle("outmail: sleeping"); + sleep(60 * 3); /* send mail every 3 minute */ + } + return 0; +} diff --git a/util/parse_news.c b/util/parse_news.c new file mode 100644 index 00000000..bebed3f4 --- /dev/null +++ b/util/parse_news.c @@ -0,0 +1,78 @@ +/* $Id: parse_news.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +#define NEWSDIRECT BBSHOME "/boards/newspaper" +#define MOVIEDIRECT BBSHOME "/etc/NEWS" + +int main() { + int fd; + fileheader_t fh, news; + struct stat st; + register int numfiles, n; + FILE *fp = NULL; + char buf[200]; + + if (stat(NEWSDIRECT "/.DIR", &st) < 0) + return 0; + + system("rm -f " MOVIEDIRECT "/*"); + system("rm -f " MOVIEDIRECT "/.DIR"); + + numfiles = st.st_size / sizeof(fileheader_t); + n = 0; + if ((fd = open(NEWSDIRECT "/.DIR", O_RDONLY)) > 0) + { + lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET); + while (numfiles-- && n < 100) + { + read(fd, &fh, sizeof(fileheader_t)); + if (!strcmp(fh.owner, "CNA-News.")) + { + if (!strstr(fh.title, "¬¡°Ê¹w§i") && !strstr(fh.title, "¤¤¥¡®ð¶H§½") + && !strstr(fh.title, "¾ú¥v¤Wªº¤µ¤Ñ") && !strstr(fh.title, "ÀY±ø·s»D¼ÐÃD") + && !strstr(fh.title, "Summary") && !strstr(fh.title, "¥þ²y®ð¶H¤@Äý") + && !strstr(fh.title, "®Õ¥¿¤½¹q")) + { + if (!(n % 10)) + { + if (n) + { + fclose(fp); + append_record(MOVIEDIRECT "/.DIR", &news, sizeof(news)); + } + strcpy(buf, MOVIEDIRECT); + stampfile(buf, &news); + sprintf(news.title, "¤¤¥¡ªÀ§Y®É·s»D %s", fh.date); + strcpy(news.owner, "CNA-News."); + news.savemode = 0; + if (!(fp = fopen(buf, "w"))) + return (0); + fprintf(fp, "[34m ¢w¢w¢w¢w¢w¢w¢w¢w¢w[47;30m ¤¤¥¡ªÀ§Y®É·s»D[31m (%s)[m[34m¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\n", + fh.date); + } + fprintf(fp, " ¢w¢w¢w¢w¢w[33m¡º[m [1;3%dm%s [m[34m%.*s\n", + (n % 6 + 4) % 7 + 1, fh.title, + (int)(46 - strlen(fh.title)), + "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w"); + n++; + printf("[%d]\n", n); + + } + } + lseek(fd, -(off_t) 2 * sizeof(fileheader_t), SEEK_CUR); + } + close(fd); + fclose(fp); + append_record(MOVIEDIRECT "/.DIR", &news, sizeof(news)); + } + return 0; +} diff --git a/util/post.c b/util/post.c new file mode 100644 index 00000000..efec797f --- /dev/null +++ b/util/post.c @@ -0,0 +1,61 @@ +/* $Id: post.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <time.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +void keeplog(FILE *fin, char *fpath, char *board, char *title, char *owner) { + fileheader_t fhdr; + char genbuf[256], buf[512]; + FILE *fout; + int bid; + + sprintf(genbuf, BBSHOME "/boards/%s", board); + stampfile(genbuf, &fhdr); + + if(!(fout = fopen(genbuf, "w"))) { + perror(genbuf); + return; + } + + while(fgets(buf, 512, fin)) + fputs(buf, fout); + + fclose(fin); + fclose(fout); + + strncpy(fhdr.title, title, sizeof(fhdr.title) - 1); + fhdr.title[sizeof(fhdr.title) - 1] = '\0'; + + strcpy(fhdr.owner, owner); + sprintf(genbuf, BBSHOME "/boards/%s/.DIR", board); + append_record(genbuf, &fhdr, sizeof(fhdr)); + if((bid = getbnum(board)) > 0) + touchbtotal(bid); + +} + +int main(int argc, char **argv) { + FILE *fp; + + resolve_boards(); + if(argc != 5) { + printf("usage: %s <board name> <title> <owner> <file>\n", argv[0]); + return 0; + } + + if(strcmp(argv[4], "-") == 0) + fp = stdin; + else { + fp = fopen(argv[4], "r"); + if(!fp) { + perror(argv[4]); + return 1; + } + } + keeplog(fp, argv[4], argv[1], argv[2], argv[3]); + return 0; +} diff --git a/util/poststat.c b/util/poststat.c new file mode 100644 index 00000000..3aa3cc94 --- /dev/null +++ b/util/poststat.c @@ -0,0 +1,497 @@ +/* $Id: poststat.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* ²Îp¤µ¤é¡B¶g¡B¤ë¡B¦~¼öªù¸ÜÃD */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#ifdef __FreeBSD__ +#include <machine/param.h> +#endif + +#include "config.h" +#include "pttstruct.h" + +char *myfile[] = +{"day", "week", "month", "year"}; +int mycount[4] = +{7, 4, 12}; +int mytop[] = +{10, 50, 100, 100}; +char *mytitle[] = +{"¤é¤Q", "¶g¤¤Q", "¤ë¦Ê", "¦~«×¦Ê"}; + + +#define HASHSIZE 1024 +#define TOPCOUNT 200 + + +struct postrec +{ + char author[13]; /* author name */ + char board[13]; /* board name */ + char title[66]; /* title name */ + time_t date; /* last post's date */ + int number; /* post number */ + struct postrec *next; /* next rec */ +} +*bucket[HASHSIZE]; + + +/* 100 bytes */ +struct posttop +{ + char author[13]; /* author name */ + char board[13]; /* board name */ + char title[66]; /* title name */ + time_t date; /* last post's date */ + int number; /* post number */ +} +top[TOPCOUNT], *tp; + + + +/* + woju + Cross-fs rename() + */ + +int Rename(char *src, char *dst) +{ + + if (rename(src, dst) == 0) + return 0; +/* + sprintf(cmd, "/bin/mv %s %s", src, dst); + return system(cmd); +*/ + return 0; +} + + + +/*-------------------------------------------------------*/ +/* .BOARDS cache */ +/*-------------------------------------------------------*/ + +struct bcache_t *brdshm; +boardheader_t *bcache; +int numboards = -1; + + +static void +attach_err(shmkey, name) + int shmkey; + char *name; +{ + fprintf(stderr, "[%s error] key = %x\n", name, shmkey); + exit(1); +} + + +static void * +attach_shm(shmkey, shmsize) + int shmkey, shmsize; +{ + void *shmptr; + int shmid; + + shmid = shmget(shmkey, shmsize, 0); + if (shmid < 0) + { + shmid = shmget(shmkey, shmsize, IPC_CREAT | 0600); + if (shmid < 0) + attach_err(shmkey, "shmget"); + shmptr = (void *) shmat(shmid, NULL, 0); + if (shmptr == (void *) -1) + attach_err(shmkey, "shmat"); + memset(shmptr, 0, shmsize); + } + else + { + shmptr = (void *) shmat(shmid, NULL, 0); + if (shmptr == (void *) -1) + attach_err(shmkey, "shmat"); + } + return shmptr; +} + + + +void +resolve_boards() +{ + if (brdshm == NULL) + { + brdshm = attach_shm(BRDSHM_KEY, sizeof(*brdshm)); + if (brdshm->touchtime == 0) + brdshm->touchtime = 1; + bcache = brdshm->bcache; + } + + while (brdshm->uptime < brdshm->touchtime) + { + if (brdshm->busystate) + { + sleep(1); + } + else + { + int fd; + + brdshm->busystate = 1; + + if ((fd = open(".BOARDS", O_RDONLY)) > 0) + { + brdshm->number = read(fd, bcache, MAX_BOARD * sizeof(boardheader_t)) + / sizeof(boardheader_t); + close(fd); + } + + /* µ¥©Ò¦³ boards ¸ê®Æ§ó·s«á¦A³]©w uptime */ + + brdshm->uptime = brdshm->touchtime; + brdshm->busystate = 0; + } + } + numboards = brdshm->number; +} + + +int +ci_strcmp(s1, s2) + register char *s1, *s2; +{ + register int c1, c2, diff; + + do + { + c1 = *s1++; + c2 = *s2++; + if (c1 >= 'A' && c1 <= 'Z') + c1 |= 32; + if (c2 >= 'A' && c2 <= 'Z') + c2 |= 32; + if((diff = c1 - c2)) + return (diff); + } + while (c1); + return 0; +} + +int +get_record(fpath, rptr, size, id) + char *fpath; + char *rptr; + int size, id; +{ + int fd; + + if ((fd = open(fpath, O_RDONLY, 0)) != -1) + { + if (lseek(fd, size * (id - 1), SEEK_SET) != -1) + { + if (read(fd, rptr, size) == size) + { + close(fd); + return 0; + } + } + close(fd); + } + return -1; +} + + +int +getbnum(bname) + char *bname; +{ + register int i; + register boardheader_t *bhdr; + + resolve_boards(); + for (i = 0, bhdr = bcache; i++ < numboards; bhdr++) + /* if (Ben_Perm(bhdr)) */ + if (!ci_strcmp(bname, bhdr->brdname)) + return i; + return 0; +} + + +int +hash(key) + char *key; +{ + int i, value = 0; + + for (i = 0; key[i] && i < 80; i++) + value += key[i] < 0 ? -key[i] : key[i]; + + value = value % HASHSIZE; + return value; +} + + +/* ---------------------------------- */ +/* hash structure : array + link list */ +/* ---------------------------------- */ + + +void +search(t) + struct posttop *t; +{ + struct postrec *p, *q, *s; + int i, found = 0; + + i = hash(t->title); + q = NULL; + p = bucket[i]; + while (p && (!found)) + { + if (!strcmp(p->title, t->title) && !strcmp(p->board, t->board)) + found = 1; + else + { + q = p; + p = p->next; + } + } + if (found) + { + p->number += t->number; + if (p->date < t->date) /* ¨ú¸ûªñ¤é´Á */ + p->date = t->date; + } + else + { + s = (struct postrec *) malloc(sizeof(struct postrec)); + memcpy(s, t, sizeof(struct posttop)); + s->next = NULL; + if (q == NULL) + bucket[i] = s; + else + q->next = s; + } +} + + +int +sort(pp, count) + struct postrec *pp; +{ + int i, j; + + for (i = 0; i <= count; i++) + { + if (pp->number > top[i].number) + { + if (count < TOPCOUNT - 1) + count++; + for (j = count - 1; j >= i; j--) + memcpy(&top[j + 1], &top[j], sizeof(struct posttop)); + + memcpy(&top[i], pp, sizeof(struct posttop)); + break; + } + } + return count; +} + + +void +load_stat(fname) + char *fname; +{ + FILE *fp; + + if((fp = fopen(fname, "r"))) + { + int count = fread(top, sizeof(struct posttop), TOPCOUNT, fp); + fclose(fp); + while (count) + search(&top[--count]); + } +} + + +int +filter(board) + char *board; +{ + boardheader_t bh; + int bid; + + bid = getbnum(board); + if (get_record(".BOARDS", &bh, sizeof(bh), bid) == -1) + return 1; + if (bh.brdattr & BRD_NOCOUNT) + return 1; +/* + if (bh.brdattr & BRD_POSTMASK) + return 0; + return (bh.brdattr & ~BRD_POSTMASK) || + >= 32; +*/ + return 0; +} + + +void +poststat(mytype) + int mytype; +{ + static char *logfile = ".post"; + static char *oldfile = ".post.old"; + + FILE *fp; + char buf[40], curfile[40] = "etc/day.0", *p; + struct postrec *pp; + int i, j; + + if (mytype < 0) + { + /* --------------------------------------- */ + /* load .post and statictic processing */ + /* --------------------------------------- */ + + remove(oldfile); + Rename(logfile, oldfile); + if ((fp = fopen(oldfile, "r")) == NULL) + return; + mytype = 0; + load_stat(curfile); + + while (fread(top, sizeof(struct posttop), 1, fp)) + search(top); + fclose(fp); + } + else + { + /* ---------------------------------------------- */ + /* load previous results and statictic processing */ + /* ---------------------------------------------- */ + + i = mycount[mytype]; + p = myfile[mytype]; + while (i) + { + sprintf(buf, "etc/%s.%d", p, i); + sprintf(curfile, "etc/%s.%d", p, --i); + load_stat(curfile); + Rename(curfile, buf); + } + mytype++; + } + +/* ---------------------------------------------- */ +/* sort top 100 issue and save results */ +/* ---------------------------------------------- */ + + memset(top, 0, sizeof(top)); + for (i = j = 0; i < HASHSIZE; i++) + { + for (pp = bucket[i]; pp; pp = pp->next) + { +#ifdef DEBUG + printf("Title : %s, Board: %s\nPostNo : %d, Author: %s\n" + ,pp->title + ,pp->board + ,pp->number + ,pp->author); +#endif + + j = sort(pp, j); + } + } + + p = myfile[mytype]; + sprintf(curfile, "etc/%s.0", p); + if((fp = fopen(curfile, "w"))) + { + fwrite(top, sizeof(struct posttop), j, fp); + fclose(fp); + } + + sprintf(curfile, "etc/%s", p); + if((fp = fopen(curfile, "w"))) + { + int max, cnt; + + fprintf(fp, "\t\t[1;34m-----[37m=====[41m ¥»%s¤j¼öªù¸ÜÃD [40m=====[34m-----[0m\n\n", mytitle[mytype]); + + max = mytop[mytype]; + p = buf + 4; + for (i = cnt = 0; (cnt < max) && (i < j); i++) + { + tp = &top[i]; + if (filter(tp->board)) + continue; + + strcpy(buf, ctime(&(tp->date))); + buf[20] = 0; + fprintf(fp, + "[1;31m%3d. [33m¬ÝªO : [32m%-16s[35m¡m %s¡n[36m%4d ½g[33m%16s\n" + " [33m¼ÐÃD : [0;44;37m%-60.60s[40m\n" + ,++cnt, tp->board, p, tp->number, tp->author, tp->title); + } + fclose(fp); + } + +/* free statistics */ + + for (i = 0; i < HASHSIZE; i++) + { + struct postrec *pp0; + + pp = bucket[i]; + while (pp) + { + pp0 = pp; + pp = pp->next; + free(pp0); + } + + bucket[i] = NULL; + } +} + + +int main(argc, argv) + char *argv[]; +{ + time_t now; + struct tm *ptime; + + if (argc < 2) + { + printf("Usage:\t%s bbshome [day]\n", argv[0]); + return (-1); + } + chdir(argv[1]); + + if (argc == 3) + { + poststat(atoi(argv[2])); + return (0); + } + time(&now); + ptime = localtime(&now); + if (ptime->tm_hour == 0) + { + if (ptime->tm_mday == 1) + poststat(2); + + if (ptime->tm_wday == 0) + poststat(1); + poststat(0); + } + poststat(-1); + return 0; +} diff --git a/util/reaper.c b/util/reaper.c new file mode 100644 index 00000000..925ea11b --- /dev/null +++ b/util/reaper.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <time.h> +#include <syslog.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "util.h" + +time_t now; + +int invalid(char *userid) { + int i; + + if(!isalpha(userid[0])) + return 1; + + for(i = 1; i < IDLEN && userid[i]; i++) + if(!isalpha(userid[i]) && !isdigit(userid[i])) + return 1; + return 0; +} + +int check(int n, userec_t *u) { + time_t d; + char buf[256]; + + if(u->userid[0] != '\0') { + if(invalid(u->userid)) { + syslog(LOG_ERR, "bad userid(%d): %s", n, u->userid); + u->userid[0] = '\0'; + } else { + d = now - u->lastlogin; + if((d > MAX_GUEST_LIFE && (u->userlevel & PERM_LOGINOK) == 0) || + (d > MAX_LIFE && (u->userlevel & PERM_XEMPT) == 0)) { + /* expired */ + int unum; + + unum = searchuser(u->userid); + strcpy(buf, ctime(&u->lastlogin)); + strtok(buf, "\n"); + syslog(LOG_NOTICE, "kill user(%d): %s %s", unum, u->userid, buf); + sprintf(buf, "mv home/%c/%s tmp/", u->userid[0], u->userid); + if(system(buf)) + syslog(LOG_ERR, "can't move user home: %s", u->userid); + u->userid[0] = '\0'; + setuserid(unum, u->userid); + } + } + } + return 0; +} + +int main() { + now = time(NULL); + openlog("reaper", LOG_PID | LOG_PERROR, SYSLOG_FACILITY); + chdir(BBSHOME); + + if(passwd_mmap()) + exit(1); + passwd_apply2(check); + + return 0; +} diff --git a/util/rmuid.c b/util/rmuid.c new file mode 100644 index 00000000..cc6e12cb --- /dev/null +++ b/util/rmuid.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" + +extern int numboards; +extern boardheader_t *bcache; + +int getbidofuid(int uid) +{ + register int n; boardheader_t *bh; + if(!uid) return 1; + for (n=0;n<numboards;n++) + { + bh = &bcache[n]; + if(bh->unused == uid) + return n+1; + } + return 1; +} + +int main(int argc, char* argv[]){ +struct stat st; + int n; + boardheader_t bh; + char pathname[1024]; + + resolve_boards(); + for (n=0;n<numboards;n++) + { + memcpy( &bh, &bcache[n], sizeof(bh)); + bh.gid=getbidofuid(bh.gid); + //printf("%14.14s%14.14s \r\n",bh.brdname, bh.title); + substitute_record("BOARDS.bid", &bh, sizeof(bh), n+1); + } +} + + + + + + + diff --git a/util/shmsweep.c b/util/shmsweep.c new file mode 100644 index 00000000..01acb26b --- /dev/null +++ b/util/shmsweep.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" + +int main() { + int i, shm, counter; + struct utmpfile_t *utmpshm; + + + shm = shmget(UTMPSHM_KEY, USHM_SIZE, SHM_R | SHM_W); + if(shm == -1) { + perror("shmget"); + exit(0); + } + + utmpshm = shmat(shm, NULL, 0); + if(utmpshm == (struct utmpfile_t *)-1) { + perror("shmat"); + exit(0); + } + + for(i = counter = 0; i < USHM_SIZE; i++) + if(utmpshm->uinfo[i].pid) { + char buf[256]; + userinfo_t *f; + struct stat sb; + + f = &utmpshm->uinfo[i]; + sprintf(buf, "/proc/%d", f->pid); + if(stat(buf, &sb)) { + f->pid = 0; + utmpshm->number--; + counter++; + } + } + printf("clear %d slots\n", counter); + return 0; +} diff --git a/util/showboard.c b/util/showboard.c new file mode 100644 index 00000000..3801dbb1 --- /dev/null +++ b/util/showboard.c @@ -0,0 +1,70 @@ +/* $Id: showboard.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* ¬ÝªO¤@Äýªí(sorted) */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "config.h" +#include "pttstruct.h" + +boardheader_t allbrd[MAX_BOARD]; + +int +board_cmp(a, b) + boardheader_t *a, *b; +{ + return (strcasecmp(a->brdname, b->brdname)); +} + + +int main(argc, argv) + int argc; + char *argv[]; +{ + int inf, i, count; + + if (argc < 2) + { + printf("Usage:\t%s .BOARDS [MAXUSERS]\n", argv[0]); + exit(1); + } + + + inf = open(argv[1], O_RDONLY); + if (inf == -1) + { + printf("error open file\n"); + exit(1); + } + +/* read in all boards */ + + i = 0; + memset(allbrd, 0, MAX_BOARD * sizeof(boardheader_t)); + while (read(inf, &allbrd[i], sizeof(boardheader_t)) == sizeof(boardheader_t)) + { + if (allbrd[i].brdname[0] ) + { + i++; + } + } + close(inf); + +/* sort them by name */ + count = i; + qsort(allbrd, count, sizeof(boardheader_t), board_cmp); + +/* write out the target file */ + + printf( + "¬ÝªO¦WºÙ ªO¥D Ãþ§O ¤¤¤å±Ôz\n" + "----------------------------------------------------------------------\n"); + for (i = 0; i < count; i++) + { + printf("%-13s%-25.25s%s\n", allbrd[i].brdname, allbrd[i].BM, allbrd[i].title); + } + return 0; +} diff --git a/util/smtest.c b/util/smtest.c new file mode 100644 index 00000000..16a2360d --- /dev/null +++ b/util/smtest.c @@ -0,0 +1,296 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +#define WARNFILE BBSHOME "/etc/DeleteBoard.warn" +#define EXECFILE BBSHOME"/etc/DeleteBoard.exec" +#define WARNLIST BBSHOME"/etc/DeleteBoardList.warn" +#define EXECLIST BBSHOME"/etc/DeleteBoardList.exec" + +extern boardheader_t *bcache; +extern int numboards; + +boardheader_t allbrd[MAX_BOARD]; +extern userec_t xuser; + + +int LINK(char* src, char* dst){ + char cmd[200]; + + if( link(src, dst) == 0){ + return 0; + } + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +int outofdate(char *hdrdate, char thedate[], int *zf) +{ + int k = 0; + char *dd; + char latestdate[6]; + int date1[2], date2[2],datetemp; + *zf = 0; + + strcpy(latestdate, thedate); + + dd = strtok(hdrdate,"/"); + if(dd == NULL) return 2; + if(dd) + k = 0; + do{ + if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;} + date1[k] = atoi(dd); + k++; + } while((dd=strtok(NULL,"/ "))!=NULL); + + dd = strtok(latestdate,"/"); + if(dd) + k = 0; + do{ + if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;} + date2[k] = atoi(dd); + k++; + } while((dd=strtok(NULL,"/ "))!=NULL); + + if(date2[0] == date1[0] && date2[1] >= date1[1]) + return 0; + + datetemp = date2[0]; + + for(k = 1;k <= 5;k++) + { + datetemp -= 1; + if((datetemp) <= 0){ + datetemp = 12; + } + if(k < 3 && datetemp == date1[0]) return 0; + if(k == 3 && datetemp == date1[0] && date2[1] <= date1[1]) return 0; + if(k == 3 && datetemp == date1[0] && date2[1] > date1[1]) return 1; + if(k == 4 && datetemp == date1[0] && date2[1] > date1[1]) return 1; + } + *zf = 1; + return 1; +} + +void mailtouser(char *bmname, char *bname, int zf) +{ + fileheader_t mymail; + char genbuf[200]; + + sprintf(genbuf, BBSHOME "/home/%c/%s", bmname[0], bmname); + stampfile(genbuf, &mymail); + strcpy(mymail.owner, "[PTTĵ¹î§½]"); + + if(zf == 0){ + sprintf(mymail.title,"\033[32m [¼oª©Äµ§i³qª¾]" + "\033[m %sª©(BM:%s)",bname, bmname); + }else{ + sprintf(mymail.title,"\033[32m [¼oª©³qª¾] " + "\033[m %sª©(BM:%s)",bname, bmname); + } + mymail.savemode = 0 ; + unlink(genbuf); + if(zf == 0){ + LINK(WARNFILE, genbuf); + }else{ + LINK(EXECFILE, genbuf); + } + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", bmname[0], bmname); + append_record(genbuf, &mymail, sizeof(mymail)); +} + +int main() +{ + int bmid, i, j, k, rd, ood, flag, zapflag = 0,warncount = 0,execcount = 0; + char *p, *bmsname[3], fname[256], hdrdatetemp[6],thedate[6]; + char bname[32],genbuf[200]; + fileheader_t hdr; + FILE *inf, *def; + + ///// set date ////// + time_t t = time(NULL); + struct tm *tm = localtime(&t); + sprintf(thedate, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday); + + ////// board ////// + + resolve_boards(); + if(passwd_mmap()) + exit(1); + memcpy(allbrd,bcache,numboards*sizeof(boardheader_t)); + + ////// write out the target file ////// + inf = fopen(WARNLIST, "w+"); + if(inf == NULL){ + printf("open file error : %s\n", WARNLIST); + exit(1); + } + + def = fopen(EXECLIST, "w+"); + if(def == NULL) + { + printf("open file error : %s\n", EXECLIST); + exit(1); + } + + ////// fprint table title ///// + fprintf(inf,"\n[¼oª©Äµ§i]§Y¤é°_¤@Ӥ뤺Y¬ÝªO" + "¨Ï¥Î²v¤´µM¹L§C¡A«h¤©¥H¼o°£¡C\n\n" + "^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ¤é´Á " + " ª©¥D¦W³æ\n\n"); + + fprintf(def,"\n[¼oª©¤½§i]¤U¦C¬ÝªO¦]¨Ï¥Î²v¤´µM¹L§C¡A¬G¤©¥H¼o°£¡C\n\n" + "^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ¤é´Á " + " ª©¥D¦W³æ\n\n"); + + ////// start process ///// + j = 0 ; + for (i = 0; i < numboards; i++) { + rd = 0; + if(allbrd[i].brdname[0] == '\0') continue; + if((allbrd[i].brdattr & BRD_NOZAP) || + (allbrd[i].brdattr & BRD_GROUPBOARD) || + (allbrd[i].brdattr & BRD_WARNDEL) || + (allbrd[i].brdattr & BRD_HIDE) || + (allbrd[i].brdattr & BRD_POSTMASK) || + (allbrd[i].brdattr & BRD_VOTEBOARD) || + (allbrd[i].brdattr & BRD_BAD) || + (allbrd[i].level != 0)) continue; + + sprintf(fname, BBSHOME "/boards/%s/.DIR",allbrd[i].brdname); + + /* get date to choose junk board */ + /* exception when ood == 2 */ + flag = 30; + rd = get_num_records(fname, sizeof(fileheader_t)); + if(rd <= 30) + { + get_record(fname, &hdr, sizeof (hdr), 1); + strcpy(hdrdatetemp, hdr.date); + ood = outofdate(hdrdatetemp,thedate, &zapflag); + } + else + { + do{ + if(rd == 0) + { + ood = 0; + break; + } + get_record(fname, &hdr, sizeof (hdr), rd - flag); + strcpy(hdrdatetemp, hdr.date); + ood = outofdate(hdrdatetemp,thedate, &zapflag); + flag += 5; + }while(ood == 2 && flag < 60); + } + if(ood == 0) continue; + + warncount++; + /* print to file */ + fprintf(inf,"%-*.*s%-*.*s %-*.*s%-*.*s\n", IDLEN, IDLEN, + allbrd[i].brdname, BTLEN-26, BTLEN-26, allbrd[i].title, + IDLEN - 5, IDLEN-5,hdr.date, IDLEN * 3, IDLEN * 3, allbrd[i].BM); + + /* post warn file to each board */ + sprintf(genbuf,"~/bin/post %s [¼oª©Äµ§i³qª¾]" + " [PTTĵ¹î§½] %s",allbrd[i].brdname,WARNFILE); + system(genbuf); + + /* user extract to mail */ + p=strtok(allbrd[i].BM,"/ "); + if(p){ + k = 0; + do + { + if (*p == '[' ){p[strlen(p)-1]='\0'; p++;} + bmid=getuser(p); + bmsname[k] = p; + if(isalpha(allbrd[i].BM[0])&& !(xuser.userlevel &PERM_SYSOP)) + { + mailtouser(bmsname[k],allbrd[i].title, zapflag); + } + k++; + } while((p=strtok(NULL,"/ "))!=NULL); + } + /* set attribute of DeleteBoardWarn Flag */ + bcache[i].brdattr = allbrd[i].brdattr | BRD_WARNDEL; + + /* zap boards */ + if (zapflag == 1) + { + execcount++; + /* print to file */ + fprintf(def,"%-*.*s%-*.*s %-*.*s%-*.*s\n", IDLEN, IDLEN, + allbrd[i].brdname, BTLEN-26, BTLEN-26, allbrd[i].title, + IDLEN - 5, IDLEN-5,hdr.date, IDLEN * 3, IDLEN * 3, allbrd[i].BM); + +// strcpy(bname, allbrd[i].brdname); +// sprintf(genbuf, +// "/bin/tar zcvf ~/tmp/board_%s.tgz boards/%s man/%s>/dev/null 2>&1;" +// "/bin/rm -fr ~/boards/%s man/%s",bname, bname, bname, bname,bname); +// system(genbuf); + +// memset(&allbrd[i], 0, sizeof(allbrd[i])); +// sprintf(allbrd[i].title, "[%s] deleted by System", bname); +// substitute_record(fn_board, &bh, sizeof(allbrd[i]), bid); +// reset_board(bid); + } + + } + + /* post to Record, ViolateLaw */ + if(warncount > 0){ + sprintf(genbuf,"~/bin/post Record [¼oª©Äµ§i³qª¾]" + " [PTTĵ¹î§½] %s",WARNLIST); + system(genbuf); + sprintf(genbuf,"~/bin/post ViolateLaw [¼oª©Äµ§i³qª¾]" + " [PTTĵ¹î§½] %s",WARNLIST); + system(genbuf); + } + if(execcount > 0){ + sprintf(genbuf,"~/bin/post Record [¼oª©¤½§i]" + " [PTTĵ¹î§½] %s",EXECLIST); + system(genbuf); + sprintf(genbuf,"~/bin/post ViolateLaw [¼oª©¤½§i]" + " [PTTĵ¹î§½] %s",EXECLIST); + system(genbuf); + } + + +/* Below is for test only */ +/* + mailtouser("Smile","test", 1); + mailtouser("Smile","test", 0); + + strcpy(bname, "Test"); + sprintf(genbuf,"~/bin/post %s test Smile ~/etc/test.fileaaa",bname); + system(genbuf); + + + bid = getbnum(bname); + strcpy(bname,"jourslamdunk"); + sprintf(genbuf, + "/bin/tar zcvf ~/tmp/board_%s.tgz boards/%s man/%s>/dev/null 2>&1;" + "/bin/rm -fr ~/boards/%s man/%s",bname, bname, bname,bname,bname); + system(genbuf); + + memset(&bh, 0, sizeof(bh)); + sprintf(bh.title, "[%s] deleted by %s", bname,cuser.userid); + substitute_record(fn_board, &bh, sizeof(bh), bid); + reset_board(bid); +*/ + return 0; +} diff --git a/util/smtest.c.save b/util/smtest.c.save new file mode 100644 index 00000000..7e678881 --- /dev/null +++ b/util/smtest.c.save @@ -0,0 +1,172 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +#define OUTFILE BBSHOME "/pttbbs/util/smtest.result1" +#define FIREFILE BBSHOME "/pttbbs/util/smtest.result2" + +extern boardheader_t *bcache; +extern int numboards; + +boardheader_t allbrd[MAX_BOARD]; +struct userec_t xuser; + +int getuser(char *userid) { + int uid; + if((uid = searchuser(userid))) + passwd_query(uid, &xuser); + return uid; +} + +int LINK(char* src, char* dst){ + char cmd[200]; + + if( link(src, dst) == 0){ + return 0; + } + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +int main() +{ + int bmid, i, j, k, rd; + char *p, *bmsname[3], bmbuf[IDLEN * 3 + 3], fname[256]; + fileheader_t hdr; + FILE *inf; + + resolve_boards(); + if(passwd_mmap()) + exit(1); + memcpy(allbrd,bcache,numboards*sizeof(boardheader_t)); + + /* write out the target file */ + inf = fopen(OUTFILE, "w+"); + if(inf == NULL){ + printf("open file error : %s\n", OUTFILE); + exit(1); + } + + /*the ouput table title*/ + fprintf(inf,"^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ª©¥D¦W³æ" + " ¤é´Á ³Æµù \n"); + + j = 0 ; + for (i = 0; i < 30; i++) { + rd = 0; + if(allbrd[i].brdname[0] == '\0') continue; + + sprintf(fname, BBSHOME "/boards/%s/.DIR",allbrd[i].brdname); + + rd = get_num_records(fname, sizeof(fileheader_t)); + get_record(fname, &hdr, sizeof (hdr), rd - 30); +// printf(" %s %s\n",hdr.title,hdr.date); + + printf("%-*.*s%-*s%s", IDLEN, IDLEN, allbrd[i].brdname, BTLEN, + allbrd[i].title,allbrd[i].BM); + + p=strtok(allbrd[i].BM,"/ "); + if(p){ + int k = 0; + do + { + if (*p == '[' ){p[strlen(p)-1]='\0'; p++;} + bmid=getuser(p); + bmsname[k] = p; + if(isalpha(allbrd[i].BM[0])&& !(xuser.userlevel &PERM_SYSOP)) + { + // printf("%s", bmsname[k]); + } + k++; + } while((p=strtok(NULL,"/ "))!=NULL); + } + + printf("\n"); + +} + + +/* + + + + if(flag == 1){ + bmbuf[0] = '\0'; + for(k = 0 , n = 0; k < index; k++){ + if(!bms[k].flag){ + if( n++ != 0) strcat(bmbuf, "/"); + strcat(bmbuf, bms[k].bmname); + } + } + strcpy(bcache[i].BM, bmbuf); + } + } + qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp); + + //write to the etc/toplazyBM + for ( i=0; i<j; i++) + { + if( lostbms[i].lostdays > 60){ + fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, + lostbms[i].title, BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + }else{ + fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + } + } + fclose(inf); + fclose(firef); + + //printf("Total %d boards.\n", count); + + //mail to the users + for( i=0; i<j; i++) + { + fileheader_t mymail; + char genbuf[200]; + int lostdays; + + lostdays = lostbms[i].lostdays; + + if( (lostdays != 30) && (lostdays != 45) && (lostdays <= 60)) + continue; + + sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname); + stampfile(genbuf, &mymail); + + strcpy(mymail.owner, "[PTTĵ¹î§½]"); + + if(lostdays <= 60){ + sprintf(mymail.title, + "\033[32m [ª©¥D§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + }else{ + sprintf(mymail.title, + "\033[32m [ª©¥D§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + } + mymail.savemode = 0 ; + unlink(genbuf); + if(lostdays <= 60){ + LINK(OUTFILE, genbuf); + }else{ + LINK(FIREFILE, genbuf); + } + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); + append_record(genbuf, &mymail, sizeof(mymail)); + } +*/ + return 0; +} diff --git a/util/smtest.result1 b/util/smtest.result1 new file mode 100644 index 00000000..6dee45ff --- /dev/null +++ b/util/smtest.result1 @@ -0,0 +1,191 @@ +^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ¤é´Á ª©¥D¦W³æ +ck48th301 «Ø¤¤ ¡·¤jºjÀ°¤§§Ö¼Ö¤Ñ° 3/21 ching/carl/Prosecuted +Bowling ¹B°Ê ¡´¨«¹L2000,ÁÚ¦V30 7/18 Genson/chiche +NTUCH-89 ¤Æ¾Ç ¡·²¦·~°Õ¡I¡I 7/10 badora/furtwangler +SetupBBS BBS ¡·TEST://140.112. 8/08 Libra +Fei-cat ¹Ï¤å ¡·23:56 ·L»Ä¨ý 8/07 tears +CKAWE «Ø¤¤ ¡´«Ø¤¤®Õ¤ÍºÞ¼Ö¹Îª 7/04 ckb/papl/trumpet +jourslamdunk«Ý¼o ¡·¬F¤j·s»D¨tÄx²y¶ 7/04 ¼x¨D¤¤ +ck48th308 «Ø¤¤ ¡·¤Sn²¦·~¤F¡I 7/15 honest +CS84Her ¤¤¤s ¡·¦U©bªF¦è ¤]n©M 7/20 +VM ¬P°¨ ¡´¯k¥ú¨}«~«aªº³d¥ 7/20 zoo +E-Diagrams ®Õ¶é ¡·¤@°_¤K¨ö¤¤d¦~. 6/29 Benjamin +ck48th313 «Ø¤¤ ¡´ª©¥D¤£ºÞ¤F,¨ÓÄé 6/08 fantastic +ck48th324 «Ø¤¤ ¡·«¢«¢«¢... 7/10 +B853023XX ¬Fªv ¡·¤½¦æ·s¥@¬ö 8/15 FireKing +ck48th303 «Ø¤¤ ¡·§Lªº¥@¬É 6/05 Roses999/henrry/flyingdog +CS85ee ¤¤¤s ¡·¤j®a¸q°_©¯ºÖ 8/08 admin/MVPgirl +CS85simple ¤¤¤s ¡·Â²¯Z¤H-¤£Â²³æ 3/29 bbeellaa +TFG95TRUE ¥_¤@ ¡·¯u¯ZªGµæ¶é 3/29 deceanna +ck46th318 «Ø¤¤ ¡· ¯¬ ºÖ ¤j ® 3/16 FengX/barkjor +PTGS50th301 ¤¤¤k ¡·¤Ñ¤U²Ä¤@¯Z--¤¤¤ 8/09 cocoduck/youki +CS85ming ¤¤¤s ¡·"©ú"¤ß¤p¶é 8/08 shan/lovehook/JWR +ck47th333 «Ø¤¤ ¡·³o¼Ë·|¤£·|¼oª©? 7/17 diezoo/Express +TFG97SHOT ¥_¤@ ¡·¦Ì¨º®á¡@¾¾¥Ì°_¤ 8/07 chili/atlantis +Taichung ªA°È ¡·³Ì³Ì²M·s¥i·R°·± 8/09 Jahon +southdoor «nªù ¡·«nªù¤»¥Òªºµ£¨¥µ 8/09 happyjoy +ck47th301 «Ø¤¤ ¡·ÁٳѽְڡH¡H 5/22 huskie/flutii +hsntu ªþ¤¤ ¡´¥x¤jªþ¤Í·| ¨Ó 11/29 koku/Crony +JH23th301 °ê¤¤ ¡·§AÁÙ¬¡µÛ¶Ü? 7/25 momi/mvpman +money ¾Ç³N ¡´Show me the 5/02 kagh +HSNU_807 ªþ¤¤ ¡·®Ã¨Õ¹s¬m¯Z 7/16 yijean/joj +ntubbsops µo¹q ¡´¥x¤j³s½u¯¸°ÈªO 3/23 Ptt +ntuACCT90 ·|p ¡´³o¬O¥Ã»·ªº¥x¤j· 7/19 blackman/aathena +geography90 ¦a²z ¡· 5/23 cog/uray +TFG97Juang ¥_¤@ ¡·§ÚÌ·|¤£·|ª½¨ì± 8/09 seabreeze/notorious/Ving +JHArt10th °ê¤¤ ¡·¶Â¦âªº©ñ®öx 8/14 sadness/noyes +ChanAn26-303ªø¦w ¡·¥s§Ú²Ä¤@¦W 8/07 HunterX +FashionClub ¶h½ì ¡´¶W«lÃz¤§--¥x¤j¦ 1/17 demure/Woodywang/wiki +TFG97KIND ¥_¤@ ¡·³o¸Ì¥i¬O¤¯¶¡¤Ñ° 1/17 Channy +AADIA ¥xÆW ¡·¿Nºuºuªº³Ì¨Î¨kº 8/13 CATHYSHU/dyw +Sunrise12 ¹ÎÅé ¡·´Â¶§¦P¾Ç·|¤Q¤G© 8/14 waiting/doggy +cksh75th09 ¦¨¥\ ¡·¤Í½Ë¾ú"¤E"¤@¼Ë¿ 8/08 chiahei/WeThree/berserk +Evangelion ¤é¥» ¡´¸Û¼xª©¥D:) 6/15 ¼x¨D¤¤ +NTUba87 ¤uºÞ ¡·¤uºÞ¤@¥X ½Ö»P 8/09 ukj/littlewin +ck49th109 «Ø¤¤ ¡·ª©¥Dn¤W¤s«ô®v¥ 3/24 edvi +CS86Honest ¤¤¤s ¡·³o¸Ì¬O¸Û¯Z¡I¸Û¯ 5/24 Nakai/vicke +YP86-307 ©µ¥ ¡·¨È¬w²Ä¤@°Õ! 8/08 DRAGONS/longman +jackstudio µ¼Ö ¡·ªN§J·nºuµ¼Ö¾Ç 8/13 gigimusic +CS85MadWiser¤¤¤s ¡··¬¨g´¼¼z¤H 12/06 NED +LiZin ¸É²ß ¡·¥ß¤H¸É²ß¯Z 6/10 success/adket/foster +HP_86_310 ©M¥ ¡·©M¥°ª¤¤²Ä¤@©¡ 11/26 beautyegg/oops/kyte +Terry ¥xÆW ¡·ªL§Ó¬¯¡uÀ¿Án¦Ó¹ 8/10 jane +Julia ¥xÆW ¡· ¤@¥Í³Ì·Rªº´^¨Î 8/07 esa +PTGS50th305 ¤¤¤k ¡·¦³¹Ú¦³ªB¤Í---¤¤ 8/07 gm +ck49th111 «Ø¤¤ ¡´¥´À»§Å±C¯S§ð¶¤ 3/15 ERWILSON/firebat +ck49th131 «Ø¤¤ ¡·§Ṳ́S²¦·~¤F... 12/26 lanzi/Cliche +Wallace »´ä ¡·¤p¤Ó¶§Áéº~¨}--¥ 8/07 karencc +KJ25MC ¥ú¤¯ ¡·¥ú¤¯«lÃz¬ü¤kª© 7/09 pm +ADS ¨ä¥L ¡´¼s§i¯S°Ï 7/09 chwang/sourit/elixirs +TFSHS57th310¤@¤¤ ¡´§Ṳ́@®a³£¬O¤H 7/09 difficult/lpp/juwu +B84305XXX ªÀ·| ¡·84¯ÅªÀ·|¤H 7/12 ridley +Jeff ¥xÆW ¡·¤Q¤G¤ëªì--±¡ºq¤ 7/24 MisaTanaca/gambol +EricMoo ¬P°¨ ¡·§Å±Ò½åªº·P°Ê 11/27 piercec +NTUIB-PHD °ê¥ø ¡·¥x¤j°ê¥ø©Ò³Õ¤h¯ 5/22 yi03 +cksh75th19 ¦¨¥\ ¡·¤µ¤Ñªº§A,¹L±o¦n 8/17 shiii/eegg +MINGDAO ©ú¹D ¡·ªï±µ·s¥@¬öªº¨ì¨ 3/10 apache/kaening +NTUMBA-87 °Ó¬ã ¡·¥ø·~®aªººÛ 8/13 jonah +ck49th324 «Ø¤¤ ¡´¤@©u®L©]ªº¤ß°Ê 4/03 jase/uuuuuu/brita +TFG96Chung ¥_¤@ ¡·²{¦bµ²±B«Ü¤£¦Eº 8/12 astroboy +Kinmen ÒO¤Í ¡·¥x¤jÒO¤Í·| 4/26 spurs +BANYAN ¥_ªù ¡·¥_ªù°ª¤¤46TH 30 7/09 lusa/wangstar +BADTWINS ¤¤¤Í ¡·¤j¼w°ê¤¤ 7/16 Chilong/ggn/xlight +TFG96WILL ¥_¤@ ¡·¼Ý°ê·±¡ 8/17 because/Galong +HSNU_924 ªþ¤¤ ¡´ºÆ¨g´c¶Õ¤O 7/16 Dukedream +Cyndi ¥xÆW ¡·¨S¦³"¾ÖµØ"¡A´N¥ 1/11 Melinda +test2 +CS86Smile ¤¤¤s ¡´¯º¶Æ¤¤¤s 12/20 HsinYu/sunspring +JI3thN3-3 ¥¿¸q ¡·¥¿¸q°ª¤¤´¶¤T¤T 7/13 screamer/stingypig +CS87KUNG ¤¤¤s ¡·¤½¤§·¶³ 8/12 hayashi/yjiou +NTUBA-837011¥øºÞ ¡·ª©½Þ¬O°¦¤jÃi½Þ 3/10 eemil +TW-explorer ¼v¶° ¡·¤p¤ß³QÅQ¤ýÀs«r³ 8/06 honu +NTUIMA ªZ³N ¡·¤º®a®±ªÀ ³¯¤ó¤Ó 8/16 shadowpen/fu6xjp6 +NthuPhi õ¾Ç ¡·®µ²ø©P¥H¾C¹C 8/07 cerberus +FreeNight ¥xÆW ¡·TROUBLE ±i¾_À® 5/24 gonna/holybell +GlobalECON «Ý¼o ¡·¬F¸g¤K¦Ê(°]¸g°Ý 12/12 ali8/martinboy +cvslog µo¹q ¡·cvs commit mess 4/16 +Momentum «Ý¼o ¡·°Ê¶q¥\³õ¤u§@«Ç 12/03 adnova/chestnut +chess ®T¼Ö ¡·¤]¹ï ³£¬O³s±N 2/01 miserable +ChthoniC ¥xÆW ¡´°{ÆF¼Ö¹Îª© 8/07 Iverigma +shisong304 ¦èªQ ¡·¦èªQ304 5/15 JawTing/JSmoltz +NCCU97_MAT ·|¬ã ¡·¨Ó§a.....¦P¾Ç·| 5/15 kemling/A1997 +ck49th331 «Ø¤¤ ¡·¨g¨F³¥±æ¡C 7/12 MDP/den +HCGH-306 ¦Ë¤k ¡·¦³¤K¨ö¡I¡I¡I 4/19 jennywen/molly +Foolshome ¹ÎÅé ¡·CCC~~~¤dÁH¦~ 1/06 truth/citizen/nathon +MARIAH ¬ü°ê ¡· ¡¹¡¹DON'T STOP 8/11 woowa +KHCHS-87-306·s²ø ¡·³£¶]¨ìþ¸Ì¥h¤F 6/10 +Delphi µ{³] ¡·Delphi¨g·Q¦± 2/13 cying +ciacia_Her ¥xÆW ¡·ciacia¥Î¤å¦r¬D³ 7/26 sherbet +KS86-323 ¶¯¤¤ ¡´§Ú̬O¥Ã»·ªºªüµ 7/05 fayemimi/hanawa +test2 +KS86-322 ¶¯¤¤ ¡·¤j®a¦^¨ÓÄé¤ô§a¡ 8/10 Vygotsky/SpermTiger +35WHOteam ¹ÎÅé ¡·ÂåÀø¥~¥æÀç¤T¤¤ 5/12 winonamars +test2 +ck49th306 «Ø¤¤ ¡·ernesto¡G 306ª 7/18 pongo/dearyou +WuLing40-301«Ý¼o ¡·¦³¹Ú¦³ªB¤Í 10/ 8/11 quert +NTUACCT88 ·|p ¡·¤Ñ ¹D ¹S ¶Ô 6/12 Abbado/yenjui +NTUDRC ¬ã¨s ¡·©Î³\©p¬O¹ïªº 8/10 Kymco/plockock/Jimmyplus +NTUWRC ³°¤W ¡·¥x¤jºL¨¤¬ã¨sªÀ 8/07 BigRed +TFSHS59th318¤@¤¤ ¡´¹L¤F¤@¤Ñ¤S¤@¤Ñ 8/07 prodigy/kinoo/frisk +86literarts ¤å¾Ç ¡·86®v¤j¤åÃÀÀç 8/07 stupidbear/bengthek +NTPU-SOC87 ªÀ·| ¡·«z«¨...·sª©¦¨¥ß 8/12 nettaigyo +NTU94FLLD ¥~¤å ¡·B83102's Wonder 3/27 poppet +ToriAmos ¬ü°ê ¡·SLG¼ö½æ¤¤ 8/14 CornflakeBoy +Bjork ¬ü°ê ¡·¤å³¹³£¤£¨£¤F § 8/09 lunaticlace/sjon +SCU-BM-87C Æ[¹î ¡· ¤Í½Ë¾ú¤[¤@¼Ë¿@ 4/17 joeyoung/linging/YADY +CC-304 ¤¤¥¿ ¡·¤¤¥¿¶W´Î 304 8/14 betty0804/daystar +Robin-Willia«Ý¼o ¡·¥Ã»·¤£¦ÑªºÃ¹»«« 8/09 ¼x¨D¤¤ +NTUEEice ¹ÎÅé ¡·á -- µ² 8/10 hiei81/shouhou +tu-tuoz ¹ÎÅé ¡·¦R¼Ñ°ê¥Á¤p¾Ç 8/10 galilei/seethesky +WesleyS3H-32½Ã²z ¡·³Ì«á¤@Ó´»°²°Õ¡ 8/15 esm +Romi ¥xÆW ¡·§Qºö¡ã¡ãÅé¶K 8/16 flyawayhome/holina +EEacademic ¹q¾÷ ¡´n´Á¤¤¦ÒÅo¡I¡I 5/11 ccchen +ck-newboard ¥Ó½Ð ¡·«Ø¤¤²Õ±M¥Î³s¸pª 2/09 Pets +NTUspecial µLê ¡·¡¸¥xÆW¤j¾ÇµL»Ùà 4/28 t6768 +chienchen §@®a ¡·¤å¦rºëÆF¡X¡XÂ²Ø 8/09 curioussoul/ECOSEED +test2 +test2 +test2 +NTUmed-SC Âå¾Ç ¡·¡¸¤È¶¡µ¼Ö·|µ¥§ 8/13 Evan/boo24 +Visual_Basicµ{³] ¡·«z«z..§A¤£¯à¦Û¤ 8/14 glans +test2 +test2 +AngelicaLee ¬P°¨ ¡·¶W¥i·R§õ¤ß¼ä *^ 8/11 CaptainL +Jackie_Lui »´ä ¡´«L°©¤¯¤ß--§f¹|½ 8/14 pipo/YCJ +HSNU_888 ªþ¤¤ ¡´888¬¾¨ß²Ä¤G¸] 8/10 Viggeran/cidi +ClassicMusicµ¼Ö ¡´§ÚÌ£x°ê¼Ö 8/13 kuger/mml +CM34th03 ´º¬ü ¡·:) 8/13 Snorkel +CS88Jang ¤¤¤s ¡·§Ú̳£¬O¥¿ÂI¬ü¤ 8/08 YANIYANI/cfchien +TFG99JUANG ¥_¤@ ¡·µM«á¤S¬O¬î¤Ñ°Õ. 8/11 yumeko +SrcDiscuss ¯¸ªø ¡·PTT ¥¼¨Óµ{¦¡µo® 5/13 CharlieL/DavidYu +WL-AFFAIRS ¨Æ°È ¡·½Ð¦UªO¥Dª`·N¸s² 6/09 PaiBingTran +SMGJS-80-302¾å©ú ¡·¥Ã»·ªºªì¤T¤A 8/09 chifang +ck51st332 «Ø¤¤ ¡·±¥ Â÷§Ú̦ӥhªº 8/13 JeffreyS/jimmycat/Kampuchea/JIROO +HORT-90 ¶éÃÀ ¡´²¦·~¤F... 8/16 sorng +NCHUPPSB ¨tÂS ¡·«s«s«s «áÄ~µL¤H 4/14 LCUTE/AMDKX +TAE ®õ°ê ¡·¦A¨£,¥[¦{®üÅy 4/14 TulipChiu +LePoete ¥xÆW ¡·¥Ð¶é¸Ö¤H³¯©ú³¹( 4/14 doomcat +NTUPOD ¬ã¨s ¡· 8/16 Galong +ck53rd211 «Ø¤¤ ¡·´«Ó¦W¦r§a.. 8/07 shanvic/BBD +NCHU-SES ¤gÀô ¡·¤j®a¨Óªï·s³á~~ 4/18 yenjan +Tin-Tin ¥xÆW ¡´´@´@·Rªº³Ó§Q 8/09 shinoo +PTGS48th318 ¤¤¤k ¡·ºñ¦âÁ½¸ºÛ 8/15 yungfang +KF302 ¥ú´_ ¡·¶ë¨®¤¤ 8/15 ingela/cadillac +HuangLei ¤j³° ¡·¶À½U¤å¾Çµ¼Ö¤jº 8/09 ssr +NCCU99_EDU «Ý¼o ¡·~±Ð¨|Ä_Ä_ªº_§§ 8/14 ¼x¨D¤¤ +NCHU_zoo °Êª« ¡´¤£¨}¤û¤H¤ñ¸û¦h 4/24 sengir/GENETICS/velella +Bull ¾´Î ¡´¤G¤Q¤@¥@¬ö³Ì«i² 4/24 Nicky41/georgey +KS88-309 ¶¯¤¤ ¡´°¸§i¶D§A...§Ú§@ 4/24 daviy +cksh77th20 ¦¨¥\ ¡·§A§Ú³£¬O·Ï¤õ¤¤ª 8/06 bergee +TFG99Dance ¥_¤@ ¡·µL¬×Jazz«ax 8/07 Tinabear/hee +TFG99Love ¥_¤@ ¡· ¨ä ¹ê 8/07 kelala/SpiceB +Nedio ´CÅé ¡·§Ö¤Whttp://nedi 8/08 SpiceB/Sophia33 +TYHS88-306 ¥ªÀç ¡´¤T¤Ñ¤T©]¨ì¤T§ó¥ 8/09 niniway/Jey +BCT-88 ¬ì§Þ ¡·¤@¸s¦b¥Íª«§Þ³N¤ 8/15 physik/avkao +CARNEGIE0917¹ÎÅé ¡·***ªï±µ°{«Gªº21 8/07 blackmail/mistletoe/tsg +NCCU_PT ªÀ¹Î ¡·¨S¦³¬¡°Êªº«Ì¤Í· 8/11 mib345/randying +NCHU-SKATING·È¦B ¡·¨Ó¥h...¨Ó¥h...¤ 3/18 kaoasaki/littlehome +Tun-Hua-Elem´°¤Æ ¡·TunHua_²Ä32©¡_6 8/07 pup +CS88jing ¤¤¤s ¡·§Ö²¦·~¤FC ·Q 8/08 yianne +LeneMarlin ¬ü°ê ¡·µ¼ÖºëÆF--µY®¦º 8/08 janetwang +KS88-304 ¶¯¤¤ ¡·¤j®a¨ÓÄé¤ô³á~ 8/12 ahwa/oldya/BabyHam +Summer ¥xÆW ¡·§â¼v¤l¯d¤U¡A¦b® 8/08 powerpeople/FINNCHE +Slayers ¤é¥» ¡·¨q³rÅ]¾É¤h ²ú® 8/07 Zelgandes/marcal/Naga +NTU-SwimCamp¤ô¤W ¡·¥x¤j´åªaÀç 6/22 sunnyl +red-sun ªÀ¹Î ¡·¸¨¥Û¨ÓÅo 8/09 renaissance +1995-JH-325 ª÷µØ ¡·ª÷µØ°ê¤¤¤T¦~¤G¤ 8/13 ThisWayIn/Raistlin/ifq +X-game ¹B°Ê ¡··¥¹B°Ê 8/08 rbaggio +88leadercamp¹ÎÅé ¡´ ²×©ó¶}ª©ªº88ªÀ 8/12 elbert/aaati +Curse ¥xÆW ¡·¶A©G¼Ö¹Î(¤Q¤K¤~ 8/07 anticrist +Joi ¬P°¨ ¡·²E²b¨Îµ 8/08 leon19/crazykiller +SHENA-RINGO ¤é¥» ¡·´Õ¦WªLìþ ³Ó¶Dªº 8/08 MayMV +CCJH-FS-27th¤¤¥¿ ¡·£¯ §N²M²M..... 8/12 Ariyari/YehMay +PH-Service ¤½½Ã ¡·¥ÃÄò¸gÀ窺¤½½Ãª 8/07 piayyc/yuskay +1995-JH-309 «Ý¼o ¡·ª÷µØ309°ê¤¤¦P¾Ç 2/11 ¼x¨D¤¤ +Peter ¥xÆW ¡·¨C¦¸·Q¨ì"¦ó¼íªF 3/05 Haas +IPIS µá°ê ¡·Á½¸-§Ñ¤F§Ú¬O½Ö 5/30 +cksh76th22 ¦¨¥\ ¡·¦a²y«Ü¦MÀIªº!©p 8/15 lunasoul +Stella ¬P°¨ ¡·µ¼Ö²¢¤ß-¶À´ð©É 7/12 gutai309/crazykiller +Law-Skate ªk«ß ¡·ªkbª½±Æ½üªÀ ·È 6/12 Rainsalt/gwenlin +cksh78th08 ¦¨¥\ ¡·¤»¦rÀY 308 3/17 smilefacer +ntucomga ºÞ·| ¡·ºÞ°|¬ã¨s¥Í¾Ç¥Í· 5/08 handsome diff --git a/util/smtest.result2 b/util/smtest.result2 new file mode 100644 index 00000000..b84133c2 --- /dev/null +++ b/util/smtest.result2 @@ -0,0 +1,3 @@ +§K¾ª©¥D +¬ÝªO¦WºÙ ªO¥D ´X¤Ñ¨S¨Ó°Õ +---------------------------------------------------------------------- diff --git a/util/smtest.temp b/util/smtest.temp new file mode 100644 index 00000000..7daa12ce --- /dev/null +++ b/util/smtest.temp @@ -0,0 +1,231 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +#define OUTFILE BBSHOME "/pttbbs/util/smtest.result1" +#define FIREFILE BBSHOME "/pttbbs/util/smtest.result2" + +extern boardheader_t *bcache; +extern int numboards; + +boardheader_t allbrd[MAX_BOARD]; +struct userec_t xuser; + +int getuser(char *userid) { + int uid; + if((uid = searchuser(userid))) + passwd_query(uid, &xuser); + return uid; +} + +int LINK(char* src, char* dst){ + char cmd[200]; + + if( link(src, dst) == 0){ + return 0; + } + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +int outofdate(char *hdrdate, char latestdate[]) +{ + int k,rr; + char *dd; + + dd = strtok(hdrdate,"/"); + + if(dd){ + k = 0; + do + { + if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;} + rr = atoi(dd); + printf("%d/", rr); + } while((dd = strtok(NULL,"/")) != NULL); + } + + printf("\n"); + + if(1) + return 1; + else + return 0; +} + +int main() +{ + int bmid, i, j, k, rd,rr; + char *p, *bmsname[3], fname[256], *dd; + fileheader_t hdr; + FILE *inf; + + /* set date */ + char thedate[5]; + time_t t = time(NULL); + struct tm *tm = localtime(&t); + + sprintf(thedate, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday); + + resolve_boards(); + if(passwd_mmap()) + exit(1); + memcpy(allbrd,bcache,numboards*sizeof(boardheader_t)); + /* write out the target file */ + inf = fopen(OUTFILE, "w+"); + if(inf == NULL){ + printf("open file error : %s\n", OUTFILE); + exit(1); + } + + /*the ouput table title*/ + fprintf(inf,"^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ª©¥D¦W³æ" + " ¤é´Á ³Æµù \n"); + + j = 0 ; + for (i = 0; i < 30; i++) { + rd = 0; + if(allbrd[i].brdname[0] == '\0') continue; + if((allbrd[i].brdattr & BRD_NOZAP) == 1) continue; + + sprintf(fname, BBSHOME "/boards/%s/.DIR",allbrd[i].brdname); + + /* get date to choose junk board */ + + rd = get_num_records(fname, sizeof(fileheader_t)); + get_record(fname, &hdr, sizeof (hdr), rd - 30); + + + if(outofdate(hdr.date,thedate)) printf("yest\n"); + +/* + dd = strtok(hdr.date,"/"); + + if(dd){ + k = 0; + do + { + if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;} + rr = atoi(dd); + printf("%d/", rr); + + } while((dd = strtok(NULL,"/")) != NULL); + } + printf("\n"); +*/ + /* print to file */ + printf("%-*.*s%-*.*s%-*.*s%-*.*s", IDLEN, IDLEN, allbrd[i].brdname, + BTLEN-24, BTLEN-26, allbrd[i].title, IDLEN - 5, IDLEN-5,hdr.date, + IDLEN * 3, IDLEN * 3, allbrd[i].BM); + + /* post to board */ + + + + /* user extract to mail */ + + p=strtok(allbrd[i].BM,"/ "); + if(p){ + k = 0; + do + { + if (*p == '[' ){p[strlen(p)-1]='\0'; p++;} + bmid=getuser(p); + bmsname[k] = p; + if(isalpha(allbrd[i].BM[0])&& !(xuser.userlevel &PERM_SYSOP)) + { + // printf("%s", bmsname[k]); + } + k++; + } while((p=strtok(NULL,"/ "))!=NULL); + } + + printf("\n"); + +} + + +/* + + + + if(flag == 1){ + bmbuf[0] = '\0'; + for(k = 0 , n = 0; k < index; k++){ + if(!bms[k].flag){ + if( n++ != 0) strcat(bmbuf, "/"); + strcat(bmbuf, bms[k].bmname); + } + } + strcpy(bcache[i].BM, bmbuf); + } + } + qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp); + + //write to the etc/toplazyBM + for ( i=0; i<j; i++) + { + if( lostbms[i].lostdays > 60){ + fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + }else{ + fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + } + } + fclose(inf); + fclose(firef); + + //printf("Total %d boards.\n", count); + + //mail to the users + for( i=0; i<j; i++) + { + fileheader_t mymail; + char genbuf[200]; + int lostdays; + + lostdays = lostbms[i].lostdays; + + if( (lostdays != 30) && (lostdays != 45) && (lostdays <= 60)) + continue; + + sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname); + stampfile(genbuf, &mymail); + + strcpy(mymail.owner, "[PTTĵ¹î§½]"); + + if(lostdays <= 60){ + sprintf(mymail.title, + "\033[32m [ª©¥D§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + }else{ + sprintf(mymail.title, + "\033[32m [ª©¥D§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + } + mymail.savemode = 0 ; + unlink(genbuf); + if(lostdays <= 60){ + LINK(OUTFILE, genbuf); + }else{ + LINK(FIREFILE, genbuf); + } + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); + append_record(genbuf, &mymail, sizeof(mymail)); + } +*/ + return 0; +} diff --git a/util/stock.perl b/util/stock.perl new file mode 100644 index 00000000..568c2d86 --- /dev/null +++ b/util/stock.perl @@ -0,0 +1,31 @@ +#!/usr/bin/perl +# $Id: stock.perl,v 1.1 2002/03/07 15:13:46 in2 Exp $ +# +# ¤£¯à¶]ªº¸Ü¡A¬Ý¬Ý bbspost ªº¸ô®|¬O§_¥¿½T¡C +# ¦pªGµo¥Xªº post ¨S¦³®ð¶H³ø§i¦Ó¬O»¡ URL §ä¤£¨ì¡A«h½T©w¤@¤U¯à¤£¯à¬Ý¨ì +# ¤¤¥¡®ð¶H§½ªº WWW ¤Î URL ¬O§_¥¿½T¡C +# ²z½×¤W¾A¥Î©Ò¦³ Eagle BBS ¨t¦C¡C +# -- Beagle Apr 13 1997 +open(BBSPOST, "| bin/webgrep >etc/stock.tmp"); +# ¤é´Á +open(DATE, "date +'%a %b %d %T %Y' |"); +$date = <DATE>; +chop $date; +close DATE; + +# Header +# ¤º®e +#open(WEATHER, "/usr/local/bin/lynx -dump http://www.dashin.com.tw/bulletin_board/today_stock_price.htm |"); while (<WEATHER>) { +open(WEATHER, "/usr/bin/lynx -dump http://quotecenter.jpc.com.tw/today_stock_price.htm |"); while(<WEATHER>) { + print BBSPOST if ($_ ne "\n"); +} +close WEATHER; + +# ñ¦WÀÉ +print BBSPOST "\n--\n"; +print BBSPOST "§Ú¬Obeagle©Ò¦³¥i·Rªº¤p»æ°®...¸ó®ü¬°PttªA°È\n"; +print BBSPOST "--\n"; +print BBSPOST "¡¸ [Origin: ¡·ªGÂæ¤p¯¸¡·] [From: [ÂŲùÃP»æ«Î] ] "; + +close BBSPOST; + diff --git a/util/stock.sh b/util/stock.sh new file mode 100644 index 00000000..907ddb73 --- /dev/null +++ b/util/stock.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id: stock.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $ +# +bin/stock.perl +bin/post Record ¤µ¤éªÑ²¼¦¬½L»ù [ªÑ¥«¤p©j] etc/stock.tmp diff --git a/util/tarqueue.pl b/util/tarqueue.pl new file mode 100644 index 00000000..20bda9f1 --- /dev/null +++ b/util/tarqueue.pl @@ -0,0 +1,75 @@ +#!/usr/bin/perl +use lib '/home/bbs/bin/'; +use LocalVars; +use strict; +use Mail::Sender; +use POSIX; + +no strict 'subs'; +setpriority(PRIO_PROCESS, $$, 20); +use strict subs; +chdir $BBSHOME; +open LOG, ">> log/tarqueue.log"; + +foreach my $board ( <$JOBSPOOL/tarqueue.*> ){ + $board =~ s/.*tarqueue\.//; + ProcessBoard($board); + unlink "$JOBSPOOL/tarqueue.$board"; +} +close DIR; +close LOG; + +sub ProcessBoard +{ + my($board)= @_; + my($cmd, $owner, $email, $bakboard, $bakman, $now); + + $now = substr(POSIX::ctime(time()), 0, -1); + open FH, "< $JOBSPOOL/tarqueue.$board"; + chomp($owner = <FH>); + chomp($email = <FH>); + chomp(($bakboard, $bakman) = split(/,/, <FH>)); + close FH; + + print LOG sprintf("%-28s %-12s %-12s %d %d %s\n", + $now, $owner, $board, $bakboard, $bakman, $email); + + MakeMail({tartarget => "$TMP/$board.tgz", + tarsource => "boards/$board/* boards/$board/.DIR", + mailto => "$boardªºª©¥D$owner <$email>", + subject => "$boardªº¬Ýª©³Æ¥÷", + body => + "\n\n\t $owner ±z¦n¡A¦¬¨ì³o«Ê«H¡Aªí¥Ü±z¤w¸g¦¬¨ì¬ÝªO³Æ¥÷¡C\n\n". + "\tÁÂÁ±zªº@¤ßµ¥«Ý¡A¥H¤Î¨Ï¥Î $hostnameªº¬ÝªO³Æ¥÷¨t²Î¡A\n\n". + "\t¦p¦³¥ô¦óºÃ°Ý¡AÅwªï±H«Hµ¹¯¸ªø¡A§ÚÌ·|«Ü¼Ö©óµ¹¤©¨ó§U¡C\n\n\n". + "\t³Ì«á¡A¯¬ $owner ¥¦w§Ö¼Ö¡I ^_^\n\n\n". + "\t $hostname¯¸ªø¸s. \n\t$now" + }) if( $bakboard ); + + MakeMail({tartarget => "$TMP/man.$board.tgz", + tarsource => "man/boards/$board/* man/boards/$board/.DIR", + mailto => "$boardªºª©¥D$owner <$email>", + subject => "$boardªººëµØ°Ï³Æ¥÷", + body => + "\n\n\t $owner ±z¦n¡A¦¬¨ì³o«Ê«H¡Aªí¥Ü±z¤w¸g¦¬¨ìºëµØ°Ï³Æ¥÷¡C\n\n". + "\tÁÂÁ±zªº@¤ßµ¥«Ý¡A¥H¤Î¨Ï¥Î $hostnameªº¬ÝªO³Æ¥÷¨t²Î¡A\n\n". + "\t¦p¦³¥ô¦óºÃ°Ý¡AÅwªï±H«Hµ¹¯¸ªø¡A§ÚÌ·|«Ü¼Ö©óµ¹¤©¨ó§U¡C\n\n\n". + "\t³Ì«á¡A¯¬ $owner ¥¦w§Ö¼Ö¡I ^_^\n\n\n". + "\t $hostname¯¸ªø¸s. \n\t$now" + }) if( $bakman ); + +} + +sub MakeMail +{ + my($arg) = @_; + my $sender; + `$TAR zcf $arg->{tartarget} $arg->{tarsource}`; + $sender = new Mail::Sender{smtp => $SMTPSERVER, + from => 'pttadmin <in2@ptt2.csie.ntu.edu.tw>'}; + $sender->MailFile({to => $arg->{mailto}, + subject => $arg->{subject}, + msg => $arg->{body}, + file => $arg->{tartarget}}); + unlink $arg->{tartarget}; +} diff --git a/util/testkenben.txt b/util/testkenben.txt new file mode 100644 index 00000000..df3893d3 --- /dev/null +++ b/util/testkenben.txt @@ -0,0 +1,11 @@ +HCGH-306 ¦Ë¤k ¡·¦³¤K¨ö¡I¡I¡I 7/24 jennywen/molly +Foolshome ¹ÎÅé ¡·CCC~~~¤dÁH¦~ 1/14 truth/citizen/nathon +KHCHS-87-306·s²ø ¡·³£¶]¨ìþ¸Ì¥h¤F 6/12 +TGHS8714 «n¤k ¡·²z©Ê¤Ñ®ð¡F·P©Ê¥ 8/07 grassflying/EPOCH +PttDoc ¼Tù ¡·Ptt Document Pr 8/07 +Delphi µ{³] ¡·Delphi¨g·Q¦± 3/09 cying +ciacia_Her ¥xÆW ¡·ciacia¥Î¤å¦r¬D³ 8/16 sherbet +CS87Love ¤¤¤s ¡··R©O! 8/08 sylna/fancydream +Wanfang ¥xÆW ¡·´Nȱo¤F·R¸UªÚ 8/07 zkkk +KS87-308 ¶¯¤¤ ¡´¶¯¤¤¤K±¾¯Z¡m¤@¤ 8/07 SBT/shouhou + diff --git a/util/toplazyBBM.c b/util/toplazyBBM.c new file mode 100644 index 00000000..08c07448 --- /dev/null +++ b/util/toplazyBBM.c @@ -0,0 +1,203 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" + +#define OUTFILE BBSHOME "/etc/toplazyBBM" +#define FIREFILE BBSHOME "/etc/topfireBBM" + +extern boardheader_t *bcache; +extern int numboards; + +boardheader_t allbrd[MAX_BOARD]; +extern userec_t xuser; +typedef struct lostbm { + char *bmname; + char *title; + char *ctitle; + int lostdays; +} lostbm; +lostbm lostbms[MAX_BOARD]; + +typedef struct BMarray{ + char *bmname; + int flag; +} BMArray; +BMArray bms[3]; + +int bmlostdays_cmp(const void *va, const void *vb) +{ + lostbm *a=(lostbm *)va, *b=(lostbm *)vb; + if (a->lostdays > b->lostdays) return -1; + else if (a->lostdays == b->lostdays) return 0; + else return 1; +} + + +int LINK(char* src, char* dst){ + char cmd[200]; + if(symlink(src,dst) == -1) + { + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int bmid, i, j=0; + FILE *inf, *firef; + + resolve_boards(); + + if(passwd_mmap()) + exit(1); + + memcpy(allbrd,bcache,numboards*sizeof(boardheader_t)); + + /* write out the target file */ + printf("Starting Checking\n"); + inf = fopen(OUTFILE, "w+"); + if(inf == NULL){ + printf("open file error : %s\n", OUTFILE); + exit(1); + } + firef = fopen(FIREFILE, "w+"); + if(firef == NULL){ + printf("open file error : %s\n", FIREFILE); + exit(1); + } + + fprintf(inf, "ĵ§i: ª©¥DY©ó¨âӤ를¤W¯¸,±N¤©©ó§K¾\n"); + fprintf(inf, + "¬ÝªO¦WºÙ " + " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n" + "---------------------------------------------------" + "-------------------\n"); + + fprintf(firef, "§K¾ª©¥D\n"); + fprintf(firef, + "¬ÝªO¦WºÙ " + " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n" + "---------------------------------------------------" + "-------------------\n"); + + + j = 0 ; + for (i = 0; i < numboards; i++) { + char *p, bmbuf[IDLEN * 3 + 3]; + int index = 0, flag = 0, k, n; + p=strtok(allbrd[i].BM,"/ "); + if(p) + do + { + if(allbrd[i].brdname[0] == '\0' || (allbrd[i].brdattr & BRD_GROUPBOARD) ==0 ) continue; + if (*p == '[' ){p[strlen(p)-1]='\0'; p++;} + bmid=getuser(p); + bms[index].bmname = p; + bms[index].flag = 0; + if (((((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24))>=7) + //&& isalpha(allbrd[i].brdname[0]) + //&& isalpha(allbrd[i].BM[0]) + && !(xuser.userlevel & PERM_SYSOP)) + { + lostbms[j].bmname = p; + lostbms[j].title = allbrd[i].brdname; + lostbms[j].ctitle = allbrd[i].title; + lostbms[j].lostdays = + ((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24); + + printf("%s\n", lostbms[j].title); + //¶W¹L¤»¤Q¤Ñ §K¾ + if(lostbms[j].lostdays > 30){ + xuser.userlevel &= ~PERM_BM; + bms[index].flag = 1; + flag = 1; + } + j++; + } + index++; + } while((p=strtok(NULL,"/ "))!=NULL); + + //±qª©¥D¦W³æ®³±¼¦W¦r + + if(flag == 1){ + bmbuf[0] = '\0'; + for(k = 0 , n = 0; k < index; k++){ + if(!bms[k].flag){ + if( n++ != 0) strcat(bmbuf, "/"); + strcat(bmbuf, bms[k].bmname); + } + } + strcpy(allbrd[i].BM, bmbuf); + } + + } + qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp); + + printf("Starting to mail\n"); + //write to the etc/toplazyBBM + for ( i=0; i<j; i++) + { + if( lostbms[i].lostdays > 30){ + fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + }else{ + fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + } + } + fclose(inf); + fclose(firef); + + printf("Total %d boards.\n", j); + + //mail to the users + for( i=0; i<j; i++) + { + fileheader_t mymail; + char genbuf[200]; + int lostdays; + + lostdays = lostbms[i].lostdays; + + if( (lostdays != 14) || (lostdays != 21) ) // 14 21 ¤Ñ¤£µo«H + continue; + + sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname); + stampfile(genbuf, &mymail); + + strcpy(mymail.owner, "[PTTĵ¹î§½]"); + + if(lostdays <= 30){ + sprintf(mymail.title, + "\033[32m [¤p²Õªø§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + }else{ + sprintf(mymail.title, + "\033[32m [¤p²Õªø§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + } + mymail.savemode = 0 ; + unlink(genbuf); + if(lostdays <= 30){ + LINK(OUTFILE, genbuf); + }else{ + LINK(FIREFILE, genbuf); + } + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); + append_record(genbuf, &mymail, sizeof(mymail)); + } + + return 0; +} diff --git a/util/toplazyBBM.sh b/util/toplazyBBM.sh new file mode 100644 index 00000000..d1d94229 --- /dev/null +++ b/util/toplazyBBM.sh @@ -0,0 +1,3 @@ +bin/toplazyBBM +bin/post Record Ãi´k¤p²Õªø±Æ¦æº] [Pttĵ¹î§½] etc/toplazyBBM +bin/post ViolateLaw ¤µ¤é§K¾¤p²Õªø [Pttªk°|] etc/firelazyBBM diff --git a/util/toplazyBM.c b/util/toplazyBM.c new file mode 100644 index 00000000..ec9319c2 --- /dev/null +++ b/util/toplazyBM.c @@ -0,0 +1,211 @@ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" +#include "proto.h" +#include "modes.h" + + +#define OUTFILE BBSHOME "/etc/toplazyBM" +#define FIREFILE BBSHOME "/etc/firelazyBM" + +extern boardheader_t *bcache; +extern int numboards; + +boardheader_t allbrd[MAX_BOARD]; +extern userec_t xuser; +typedef struct lostbm { + char *bmname; + char *title; + char *ctitle; + int lostdays; +} lostbm; +lostbm lostbms[MAX_BOARD]; + +typedef struct BMarray{ + char *bmname; + int flag; +} BMArray; +BMArray bms[3]; + + +int bmlostdays_cmp(const void *va, const void *vb) +{ + lostbm *a=(lostbm *)va, *b=(lostbm *)vb; + if (a->lostdays > b->lostdays) return -1; + else if (a->lostdays == b->lostdays) return 0; + else return 1; +} + +int LINK(char* src, char* dst){ + char cmd[200]; + if(symlink(src,dst) == -1) + { + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int bmid, i, j=0; + FILE *inf, *firef; + + resolve_boards(); + + if(passwd_mmap()) + exit(1); + + memcpy(allbrd,bcache,numboards*sizeof(boardheader_t)); + + /* write out the target file */ + inf = fopen(OUTFILE, "w+"); + if(inf == NULL){ + printf("open file error : %s\n", OUTFILE); + exit(1); + } + + firef = fopen(FIREFILE, "w+"); + if(firef == NULL){ + printf("open file error : %s\n", FIREFILE); + exit(1); + } + + fprintf(inf, "ĵ§i: ª©¥DY©ó¨âӤ를¤W¯¸,±N¤©©ó§K¾\n"); + fprintf(inf, + "¬ÝªO¦WºÙ " + " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n" + "---------------------------------------------------" + "-------------------\n"); + + fprintf(firef, "§K¾ª©¥D\n"); + fprintf(firef, + "¬ÝªO¦WºÙ " + " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n" + "---------------------------------------------------" + "-------------------\n"); + + + j = 0 ; + for (i = 0; i < numboards; i++) { + char *p, bmbuf[IDLEN * 3 + 3]; + int index = 0, flag = 0, k, n; + p=strtok(allbrd[i].BM,"/ "); + if(p) + do + { + if(allbrd[i].brdname[0] == '\0') continue; + if (*p == '[' ){p[strlen(p)-1]='\0'; p++;} + bmid=getuser(p); + bms[index].bmname = p; + bms[index].flag = 0; + if (((((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24))>=31) + && isalpha(allbrd[i].brdname[0]) + && isalpha(allbrd[i].BM[0]) + && !(xuser.userlevel & PERM_SYSOP)) + { + lostbms[j].bmname = p; + lostbms[j].title = allbrd[i].brdname; + lostbms[j].ctitle = allbrd[i].title; + lostbms[j].lostdays = + ((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24); + + + //¶W¹L¤»¤Q¤Ñ §K¾ + if(lostbms[j].lostdays > 60){ + xuser.userlevel &= ~PERM_BM; + bms[index].flag = 1; + flag = 1; + passwd_update(bmid, &xuser); + } + j++; + } + index++; + } while((p=strtok(NULL,"/ "))!=NULL); + + if(flag == 1){ + boardheader_t *fhp = 0; + printf("%s %s\n", lostbms[j-1].title, lostbms[j-1].bmname); + bmbuf[0] = '\0'; + for(k = 0 , n = 0; k < index; k++){ + if(!bms[k].flag){ + if( n++ != 0) strcat(bmbuf, "/"); + strcat(bmbuf, bms[k].bmname); + } + } + + strcpy(allbrd[i].BM, bmbuf); + if( substitute_record(FN_BOARD, &allbrd[i], sizeof(boardheader_t), i) == -1){ + printf("Update Board Faile : %s\n", allbrd[i].brdname); + } + reset_board(i); + } + } + + qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp); + + //write to the etc/toplazyBM + for ( i=0; i<j; i++) + { + if( lostbms[i].lostdays > 60){ + fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + }else{ + fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title, + BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN, + lostbms[i].bmname,lostbms[i].lostdays); + } + } + fclose(inf); + fclose(firef); + + //printf("Total %d boards.\n", count); + + //mail to the users + for( i=0; i<j; i++) + { + fileheader_t mymail; + char genbuf[200]; + int lostdays; + + lostdays = lostbms[i].lostdays; + + if( (lostdays != 30) && (lostdays != 45) && (lostdays <= 60)) + continue; + + sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname); + stampfile(genbuf, &mymail); + + strcpy(mymail.owner, "[PTTĵ¹î§½]"); + + if(lostdays <= 60){ + sprintf(mymail.title, + "\033[32m [ª©¥D§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + }else{ + sprintf(mymail.title, + "\033[32m [ª©¥D§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname); + } + mymail.savemode = 0 ; + unlink(genbuf); + if(lostdays <= 60){ + LINK(OUTFILE, genbuf); + }else{ + LINK(FIREFILE, genbuf); + } + + sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); + append_record(genbuf, &mymail, sizeof(mymail)); + } + + return 0; +} diff --git a/util/toplazyBM.sh b/util/toplazyBM.sh new file mode 100644 index 00000000..033e545f --- /dev/null +++ b/util/toplazyBM.sh @@ -0,0 +1,3 @@ +bin/toplazyBM +bin/post Record Ãi´kª©¥D±Æ¦æº] [Pttĵ¹î§½] etc/toplazyBM +bin/post ViolateLaw ¤µ¤é§K¾ª©¥D [Pttªk°'|'] etc/firelazyBM diff --git a/util/topsong.sh b/util/topsong.sh new file mode 100644 index 00000000..19e9663a --- /dev/null +++ b/util/topsong.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id: topsong.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $ +# +bin/post Record "¤W¥bÓ¤ëÂIºq±Æ¦æº]" "[Ptt¬y¦æºô]" etc/topsong +mv ussong tmp diff --git a/util/topusr.c b/util/topusr.c new file mode 100644 index 00000000..22b95e94 --- /dev/null +++ b/util/topusr.c @@ -0,0 +1,205 @@ +/* $Id: topusr.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* ¨Ï¥ÎªÌ ¤W¯¸°O¿ý/¤å³¹½g¼Æ ±Æ¦æº] */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "util.h" + +#define REAL_INFO +struct manrec +{ + char userid[IDLEN + 1]; + char username[23]; + int values[3]; +}; +typedef struct manrec manrec; +struct manrec *allman[3]; + +userec_t aman; +manrec theman; +int num; +FILE *fp; + +#define TYPE_POST 0 +#define TYPE_LOGIN 1 +#define TYPE_MONEY 2 + + +void + top(type) +{ + static char *str_type[3] = + {"µoªí¦¸¼Æ", "¶i¯¸¦¸¼Æ", " ¤j´I¯Î "}; + int i, j, rows = (num + 1) / 2; + char buf1[80], buf2[80]; + + if (type != 2) + fprintf(fp, "\n\n"); + + fprintf(fp, "\ +[1;36m ¢~¢w¢w¢w¢w¢w¢¡ [%dm %8.8s±Æ¦æº] [36;40m ¢~¢w¢w¢w¢w¢w¢¡[m\n\ +[1;36m ¦W¦¸¢w¥N¸¹¢w¢w¢w¼ÊºÙ¢w¢w¢w¢w¢w¢w¼Æ¥Ø¢w¢w¦W¦¸¢w¥N¸¹¢w¢w¢w¼ÊºÙ¢w¢w¢w¢w¢w¢w¼Æ¥Ø[m\ +", type + 44, str_type[type]); + for (i = 0; i < rows; i++) + { + char ch=' '; + int value; + + if(allman[type][i].values[type] > 1000000000) + { value=allman[type][i].values[type]/1000000; ch='M';} + else if(allman[type][i].values[type] > 1000000) + { value=allman[type][i].values[type]/1000; ch='K';} + else {value=allman[type][i].values[type]; ch=' ';} + sprintf(buf1, "[%2d] %-11.11s%-16.16s%5d%c", + i + 1, allman[type][i].userid, allman[type][i].username, + value, ch); + j = i + rows; + if(allman[type][j].values[type] > 1000000000) + { value=allman[type][j].values[type]/1000000; ch='M';} + else if(allman[type][j].values[type] > 1000000) + { value=allman[type][j].values[type]/1000; ch='K';} + else {value=allman[type][j].values[type]; ch=' ';} + + sprintf(buf2, "[%2d] %-11.11s%-16.16s%4d%c", + j + 1, allman[type][j].userid, allman[type][j].username, + value, ch); + if (i < 3) + fprintf(fp, "\n [1;%dm%-40s[0;37m%s", 31 + i, buf1, buf2); + else + fprintf(fp, "\n %-40s%s", buf1, buf2); + } +} + + +#ifdef HAVE_TIN +int + post_in_tin(char *name) +{ + char buf[256]; + FILE *fh; + int counter = 0; + + sprintf(buf, "%s/home/%c/%s/.tin/posted", home_path, name[0], name); + fh = fopen(buf, "r"); + if (fh == NULL) + return 0; + else + { + while (fgets(buf, 255, fh) != NULL) + counter++; + fclose(fh); + return counter; + } +} +#endif /* HAVE_TIN */ +int + not_alpha(ch) +register char ch; +{ + return (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z'); +} + +int + not_alnum(ch) +register char ch; +{ + return (ch < '0' || (ch > '9' && ch < 'A') || + (ch > 'Z' && ch < 'a') || ch > 'z'); +} + +int + bad_user_id(userid) +char *userid; +{ + register char ch; + if (strlen(userid) < 2) + return 1; + if (not_alpha(*userid)) + return 1; + while((ch = *(++userid))) + { + if (not_alnum(ch)) + return 1; + } + return 0; +} + +int main(argc, argv) +int argc; +char **argv; +{ + int i, j; + + if (argc < 3) + { + printf("Usage: %s <num_top> <out-file>\n", argv[0]); + exit(1); + } + + num = atoi(argv[1]); + if (num == 0) + num = 30; + + if(passwd_mmap()) + { + printf("Sorry, the data is not ready.\n"); + exit(0); + } + for(i=0; i<3; i++) + { + allman[i]=malloc(sizeof(manrec) * num); + memset(allman[i],0,sizeof(manrec) * num); + } + for(j = 1; j <= MAX_USERS; j++) { + passwd_query(j, &aman); + aman.userid[IDLEN]=0; + aman.username[22]=0; + if((aman.userlevel & PERM_NOTOP) || !aman.userid[0] || + bad_user_id(aman.userid) || + strchr(aman.userid, '.')) + { + continue; + } + else { + strcpy(theman.userid, aman.userid); + strcpy(theman.username, aman.username); + theman.values[TYPE_LOGIN] = aman.numlogins; + theman.values[TYPE_POST] = aman.numposts; + theman.values[TYPE_MONEY] = aman.money; + for(i=0; i<3; i++) + { + int k,l; + for(k=num-1; k>=0 && allman[i][k].values[i]<theman.values[i]; + k--); + k++; + if(k<num) + { + for(l=num-1; l>k; l--) + memcpy(&allman[i][l], &allman[i][l-1], + sizeof(manrec)); + memcpy(&allman[i][k], &theman, sizeof(manrec)); + } + } + } + } + + + if ((fp = fopen(argv[2], "w")) == NULL) + { + printf("cann't open topusr\n"); + return 0; + } + + top(TYPE_MONEY); + top(TYPE_POST); + top(TYPE_LOGIN); + + fclose(fp); + return 0; +} diff --git a/util/tunepasswd.c b/util/tunepasswd.c new file mode 100644 index 00000000..15a3fe1f --- /dev/null +++ b/util/tunepasswd.c @@ -0,0 +1,77 @@ +/* $Id: tunepasswd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" + +int tune(int num) { + int i, j, fin, fout; + userec_t u; + + if((fin = open(FN_PASSWD, O_RDONLY)) == -1) { + perror(FN_PASSWD); + return 1; + } + if(flock(fin, LOCK_EX)) { + printf("Lock failed!\n"); + return 1; + } + if((fout = open(FN_PASSWD ".tune" , O_WRONLY | O_CREAT, 0600)) == -1) { + perror(FN_PASSWD ".tune"); + flock(fin, LOCK_UN); + close(fin); + return 1; + } + + for(i = j = 0; i < num; i++) { + read(fin, &u, sizeof(u)); + if(u.userid[0]) { + if(j == MAX_USERS) { + printf("MAX_USERS is too small!\n"); + close(fout); + unlink(FN_PASSWD ".tune"); + flock(fin, LOCK_UN); + close(fin); + return 1; + } + write(fout, &u, sizeof(u)); + j++; + } + } + for(memset(&u, 0, sizeof(u)); j < MAX_USERS; j++) { + write(fout, &u, sizeof(u)); + } + close(fout); + + /* backup */ + unlink(FN_PASSWD "~"); + link(FN_PASSWD, FN_PASSWD "~"); + unlink(FN_PASSWD); + link(FN_PASSWD ".tune", FN_PASSWD); + unlink(FN_PASSWD ".tune"); + + flock(fin, LOCK_UN); + close(fin); + return 0; +} + +int main() { + struct stat sb; + + if(stat(FN_PASSWD, &sb)) { + perror("stat"); + return 1; + } + if(sb.st_size != sizeof(userec_t) * MAX_USERS) { + printf("size and MAX_USERS do not match!\n"); + if(tune(sb.st_size / sizeof(userec_t)) == 0) + printf(FN_PASSWD " has been tuned successfully!\n"); + } else + printf("Nothing to do.\n"); + return 0; +} diff --git a/util/uhash_loader.c b/util/uhash_loader.c new file mode 100644 index 00000000..2d88dd06 --- /dev/null +++ b/util/uhash_loader.c @@ -0,0 +1,129 @@ +/* $Id: uhash_loader.c,v 1.1 2002/03/07 15:13:47 in2 Exp $ */ +/* standalone uhash loader -- jochang */ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#ifdef __FreeBSD__ +#include <machine/param.h> +#endif + +#include "config.h" +#include "pttstruct.h" +#include "common.h" + +unsigned string_hash(unsigned char *s); +void add_to_uhash(int n, userec_t *id); +void fill_uhash(void); +void load_uhash(void); + +uhash_t *uhash; + +int main() { + setgid(BBSGID); + setuid(BBSUID); + chdir(BBSHOME); + load_uhash(); + return 0; +} + +void load_uhash(void) { + int shmid; + shmid = shmget(UHASH_KEY, sizeof(uhash_t), IPC_CREAT | 0600); +/* note we didn't use IPC_EXCL here. + so if the loading fails, + (like .PASSWD doesn't exist) + we may try again later. +*/ + if (shmid < 0) + { + perror("shmget"); + exit(1); + } + + uhash = (void *) shmat(shmid, NULL, 0); + if (uhash == (void *) -1) + { + perror("shmat"); + exit(1); + } + +/* in case it's not assumed zero, this becomes a race... */ + uhash->loaded = 0; + + fill_uhash(); + +/* ok... */ + uhash->loaded = 1; +} + +void fill_uhash(void) +{ + int fd, usernumber; + usernumber = 0; + + for (fd = 0; fd < (1 << HASH_BITS); fd++) + uhash->hash_head[fd] = -1; + + if ((fd = open(FN_PASSWD, O_RDONLY)) > 0) + { + struct stat stbuf; + caddr_t fimage, mimage; + + fstat(fd, &stbuf); + fimage = mmap(NULL, stbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (fimage == (char *) -1) + { + perror("mmap"); + exit(1); + } + close(fd); + fd = stbuf.st_size / sizeof(userec_t); + if (fd > MAX_USERS) + fd = MAX_USERS; + + for (mimage = fimage; usernumber < fd; mimage += sizeof(userec_t)) + { + add_to_uhash(usernumber, mimage); + usernumber++; + } + munmap(fimage, stbuf.st_size); + } + else + { + perror("open"); + exit(1); + } + uhash->number = usernumber; + printf("total %d names loaded.\n", usernumber); +} +unsigned string_hash(unsigned char *s) +{ + unsigned int v = 0; + while (*s) + { + v = (v << 8) | (v >> 24); + v ^= toupper(*s++); /* note this is case insensitive */ + } + return (v * 2654435769UL) >> (32 - HASH_BITS); +} + +void add_to_uhash(int n, userec_t *user) +{ + int *p, h = string_hash(user->userid); + strcpy(uhash->userid[n], user->userid); + uhash->money[n] = user->money; + p = &(uhash->hash_head[h]); + + while (*p != -1) + p = &(uhash->next_in_hash[*p]); + + uhash->next_in_hash[*p = n] = -1; +} diff --git a/util/userlist.c b/util/userlist.c new file mode 100644 index 00000000..9a142926 --- /dev/null +++ b/util/userlist.c @@ -0,0 +1,48 @@ +/* $id:$ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include "config.h" +#include "pttstruct.h" + +struct utmpfile_t *u; + +int main(int argc, char **argv) { + int i, shm, counter; + + shm = shmget(UTMPSHM_KEY, USHM_SIZE, SHM_R | SHM_W); + if(shm == -1) { + perror("shmget"); + exit(0); + } + + u = shmat(shm, NULL, 0); + if(u == (struct utmpfile_t *)-1) { + perror("shmat"); + exit(0); + } + + if(argc > 1) { + for(i = 1; i < argc; i++) + u->uinfo[atoi(argv[i])].pid = 0; + } else { + for(i = counter = 0; i < USHM_SIZE; i++) + if(u->uinfo[i].pid) { + userinfo_t *f; + + f = &u->uinfo[i]; + printf( + "%4d(%d) p[%d] i[%d] u[%s] n[%s] f[%s] m[%d] d[%d] t[%ld]\n", + ++counter, i, f->pager, f->invisible, f->userid, + f->username, f->from, f->mode, f->mind, f->lastact); + } + printf("\nTotal: %d(%d)\n", counter, u->number); + if(counter != u->number) { + u->number = counter; + printf("adjust user number!\n"); + } + } + return 0; +} diff --git a/util/util.h b/util/util.h new file mode 100644 index 00000000..9128e575 --- /dev/null +++ b/util/util.h @@ -0,0 +1,31 @@ +/* $Id: util.h,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#ifndef INCLUDE_UTIL_H +#define INCLUDE_UTIL_H + +int searchuser(char *userid); +int stampfile(char *fpath, fileheader_t *fh); +int append_record(char *fpath, fileheader_t *record, int size); +int get_record(char *fpath, void *rptr, int size, int id); +int substitute_record(char *fpath, void *rptr, int size, int id); +void resolve_boards(); +int getbnum(char *bname); +void inbtotal(int bid, int add); +void *attach_shm(int shmkey, int shmsize); +void reload_pttcache(); +void resolve_fcache(); +void attach_uhash(); +void stamplink(char *fpath, fileheader_t *fh); +void resolve_utmp(); +void remove_from_uhash(int n); +void setuserid(int num, char *userid); + +int passwd_mmap(); +int passwd_update(int num, userec_t *buf); +int passwd_query(int num, userec_t *buf); +int passwd_apply(int (*fptr)(userec_t *)); +int passwd_apply2(int (*fptr)(int, userec_t *)); +void passwd_lock(); +void passwd_unlock(); + +#endif + diff --git a/util/util_cache.c b/util/util_cache.c new file mode 100644 index 00000000..12a01994 --- /dev/null +++ b/util/util_cache.c @@ -0,0 +1,518 @@ +/* $Id: util_cache.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> +#include <sys/types.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> + +#ifdef __FreeBSD__ +#include <machine/param.h> +#endif + +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +int fcache_semid; + +/* the reason for "safe_sleep" is that we may call sleep during + SIGALRM handler routine, while SIGALRM is blocked. + if we use the original sleep, we'll never wake up. */ +unsigned int safe_sleep(unsigned int seconds) { + /* jochang sleep¦³°ÝÃD®É¥Î*/ + sigset_t set,oldset; + + sigemptyset(&set); + sigprocmask(SIG_BLOCK, &set, &oldset); + if(sigismember(&oldset, SIGALRM)) { + unsigned long retv; + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_UNBLOCK,&set,NULL); + retv=sleep(seconds); + sigprocmask(SIG_BLOCK,&set,NULL); + return retv; + } + return sleep(seconds); +} + +void setapath(char *buf, char *boardname) { + sprintf(buf, "man/boards/%s", boardname); +} + +static char *str_dotdir = ".DIR"; + +void setadir(char *buf, char *path) { + sprintf(buf, "%s/%s", path, str_dotdir); +} + +static void attach_err(int shmkey, char *name) { + fprintf(stderr, "[%s error] key = %x\n", name, shmkey); + fprintf(stderr, "errno = %d: %s\n", errno, strerror(errno)); + exit(1); +} + +void *attach_shm(int shmkey, int shmsize) { + void *shmptr; + int shmid; + + char *empty_addr; + /* set up one page in-accessible -- jochang */ + { + int fd = open("/dev/zero",O_RDONLY); + int size = ((shmsize + 4095) / 4096) * 4096; + + munmap( + (empty_addr=mmap(0,4096+size,PROT_NONE,MAP_PRIVATE,fd,0))+4096 + ,size); + + close(fd); + } + + shmid = shmget(shmkey, shmsize, 0); + if(shmid < 0) { + shmid = shmget(shmkey, shmsize, IPC_CREAT | 0600); + if(shmid < 0) + attach_err(shmkey, "shmget"); + shmptr = (void *)shmat(shmid, NULL, 0); + if(shmptr == (void *)-1) + attach_err(shmkey, "shmat"); + } else { + shmptr = (void *)shmat(shmid, NULL, 0); + if(shmptr == (void *)-1) + attach_err(shmkey, "shmat"); + } + + /* unmap the page -- jochang */ + { + munmap(empty_addr,4096); + } + return shmptr; +} + +#ifndef __FreeBSD__ +/* according to X/OPEN we have to define it ourselves */ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ + unsigned short int *array; /* array for GETALL, SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif + +#define SEM_FLG 0600 /* semaphore mode */ + +/* ----------------------------------------------------- */ +/* semaphore : for critical section */ +/* ----------------------------------------------------- */ +void sem_init(int semkey,int *semid) { + union semun s; + + s.val=1; + *semid = semget(semkey, 1, 0); + if(*semid == -1) { + *semid = semget(semkey, 1, IPC_CREAT | SEM_FLG); + if(*semid == -1) + attach_err(semkey, "semget"); + semctl(*semid, 0, SETVAL, s); + } +} + +void sem_lock(int op,int semid) { + struct sembuf sops; + + sops.sem_num = 0; + sops.sem_flg = SEM_UNDO; + sops.sem_op = op; + semop(semid, &sops, 1); +} + +/* uhash *******************************************/ +/* the design is this: + we use another stand-alone program to create and load data into the hash. + (that program could be run in rc-scripts or something like that) + after loading completes, the stand-alone program sets loaded to 1 and exits. + + the bbs exits if it can't attach to the shared memory or + the hash is not loaded yet. +*/ +uhash_t *uhash; + +int setumoney(int uid, int money) { + uhash->money[uid-1]=money; + passwd_update_money(uid); + return uhash->money[uid-1]; +} + +int deumoney(int uid, int money) { + if(money<0 && uhash->money[uid-1]<-money) + return setumoney(uid,0); + else + return setumoney(uid,uhash->money[uid-1]+money); +} +int moneyof(int uid){ /* ptt §ï¶iª÷¿ú³B²z®Ä²v */ + return uhash->money[uid-1]; +} +/* attach_uhash should be called before using uhash */ +void attach_uhash() { + uhash = attach_shm(UHASH_KEY, sizeof(*uhash)); + if(!uhash->loaded) /* assume fresh shared memory is zeroed */ + exit(1); +} + + +static unsigned string_hash(unsigned char *s) { + unsigned int v=0; + while(*s) { + v = (v << 8) | (v >> 24); + v ^= toupper(*s++); /* note this is case insensitive */ + } + return (v * 2654435769UL) >> (32 - HASH_BITS); +} + +void add_to_uhash(int n, char *id) { + int *p, h = string_hash(id); + strcpy(uhash->userid[n], id); + + p = &(uhash->hash_head[h]); + + while(*p != -1) + p = &(uhash->next_in_hash[*p]); + + uhash->next_in_hash[*p = n] = -1; +} + +/* note: after remove_from_uhash(), you should add_to_uhash() + (likely with a different name) */ +void remove_from_uhash(int n) { + int h = string_hash(uhash->userid[n]); + int *p = &(uhash->hash_head[h]); + + while(*p != -1 && *p != n) + p = &(uhash->next_in_hash[*p]); + if(*p == n) + *p = uhash->next_in_hash[n]; +} + +int searchuser(char *userid) { + int h,p; + + if(uhash == NULL) + attach_uhash(); /* for sloopy util programs */ + + h = string_hash(userid); + p = uhash->hash_head[h]; + + while(p != -1) { + if(strcasecmp(uhash->userid[p],userid) == 0) { + strcpy(userid,uhash->userid[p]); + return p + 1; + } + p = uhash->next_in_hash[p]; + } + return 0; +} +userec_t xuser; + +int getuser(char *userid) { + int uid; + if((uid = searchuser(userid))) + passwd_query(uid, &xuser); + return uid; +} +void setuserid(int num, char *userid) { + if(num > 0 && num <= MAX_USERS) { + if(num > uhash->number) + uhash->number = num; + else + remove_from_uhash(num-1); + add_to_uhash(num-1,userid); + } +} + +/*-------------------------------------------------------*/ +/* .UTMP cache */ +/*-------------------------------------------------------*/ +struct utmpfile_t *utmpshm=NULL; + +void resolve_utmp() { + if(utmpshm == NULL) { + utmpshm = attach_shm(UTMPSHM_KEY, sizeof(*utmpshm)); + if(utmpshm->uptime == 0) + utmpshm->uptime = utmpshm->number = 1; + } +} + +userinfo_t *currutmp = NULL; + +void getnewutmpent(userinfo_t *up) { + extern int errno; + register int i; + register userinfo_t *uentp; + + resolve_utmp(); + + for(i = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(!(uentp->pid)) { + memcpy(uentp, up, sizeof(userinfo_t)); + currutmp = uentp; + utmpshm->number++; + return; + } + } + exit(1); +} + +int apply_ulist(int (*fptr)(userinfo_t *)) { + register userinfo_t *uentp; + register int i, state; + + resolve_utmp(); + for(i = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(uentp->pid && (PERM_HIDE(currutmp) || !PERM_HIDE(uentp))) + if((state = (*fptr) (uentp))) + return state; + } + return 0; +} + +userinfo_t *search_ulist(int uid) { + register int i; + register userinfo_t *uentp; + + resolve_utmp(); + for(i = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(uid==uentp->uid) + return uentp; + } + return 0; +} + +/*-------------------------------------------------------*/ +/* .BOARDS cache */ +/*-------------------------------------------------------*/ +char *fn_board=FN_BOARD; +bcache_t *brdshm; +boardheader_t *bcache; + +static void reload_bcache() { + if(brdshm->busystate) { + safe_sleep(1); + } +} + +int numboards = -1; + +void resolve_boards() { + if(brdshm == NULL) { + brdshm = attach_shm(BRDSHM_KEY, sizeof(*brdshm)); + if(brdshm->touchtime == 0) + brdshm->touchtime = 1; + bcache = brdshm->bcache; + } + + while(brdshm->uptime < brdshm->touchtime) + reload_bcache(); + numboards = brdshm->number; +} + +void touch_boards() { + time(&(brdshm->touchtime)); + numboards = -1; + resolve_boards(); +} +void reset_board(int bid) +{ + int fd; + if(--bid<0)return; + if(brdshm->busystate==0) + { + brdshm->busystate = 1; + if((fd = open(fn_board, O_RDONLY)) > 0) { + lseek(fd, (off_t)(bid * sizeof(boardheader_t)), SEEK_SET); + read(fd, &bcache[bid], sizeof(boardheader_t)); + close(fd); + } + brdshm->busystate = 0; + } +} +boardheader_t *getbcache(int bid) { /* Ptt§ï¼g */ + return bcache + bid - 1; +} + +void touchbtotal(int bid) { + brdshm->total[bid - 1] = 0; + brdshm->lastposttime[bid - 1] = 0; +} + + +int getbnum(char *bname) { + register int i; + register boardheader_t *bhdr; + + for(i = 0, bhdr = bcache; i++ < numboards; bhdr++) + if( + !strcasecmp(bname, bhdr->brdname)) + return i; + return 0; +} + +/*-------------------------------------------------------*/ +/* PTT cache */ +/*-------------------------------------------------------*/ +/* cachefor °ÊºA¬Ýª© */ +struct pttcache_t *ptt; + +void reload_pttcache() { + if(ptt->busystate) + safe_sleep(1); + else { /* jochang: temporary workaround */ + fileheader_t item, subitem; + char pbuf[256], buf[256], *chr; + FILE *fp, *fp1, *fp2; + int id, section = 0; + + ptt->busystate = 1; + ptt->max_film = 0; + bzero(ptt->notes, sizeof ptt->notes); + setapath(pbuf, "Note"); + setadir(buf, pbuf); + id = 0; + if((fp = fopen(buf, "r"))) { + while(fread(&item, sizeof(item), 1, fp)) { + if(item.title[3]=='<' && item.title[8]=='>') { + sprintf(buf,"%s/%s", pbuf, item.filename); + setadir(buf, buf); + if(!(fp1 = fopen(buf, "r"))) + continue; + ptt->next_refresh[section] = ptt->n_notes[section] = id; + section ++; + while(fread(&subitem, sizeof(subitem), 1, fp1)) { + sprintf(buf,"%s/%s/%s", pbuf, item.filename , + subitem.filename); + if(!(fp2=fopen(buf,"r"))) + continue; + fread(ptt->notes[id],sizeof(char), 200*11, fp2); + ptt->notes[id][200*11 - 1]=0; + id++; + fclose(fp2); + if(id >= MAX_MOVIE) + break; + } + fclose(fp1); + if(id >= MAX_MOVIE || section >= MAX_MOVIE_SECTION) + break; + } + } + fclose(fp); + } + ptt->next_refresh[section] = -1; + ptt->n_notes[section] = ptt->max_film = id-1; + ptt->max_history = ptt->max_film - 2; + if(ptt->max_history > MAX_HISTORY - 1) + ptt->max_history = MAX_HISTORY - 1; + if(ptt->max_history <0) ptt->max_history=0; + + fp = fopen("etc/today_is","r"); + if(fp) { + fgets(ptt->today_is,15,fp); + if((chr = strchr(ptt->today_is,'\n'))) + *chr = 0; + ptt->today_is[15] = 0; + fclose(fp); + } + + /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */ + + ptt->uptime = ptt->touchtime ; + ptt->busystate = 0; + } +} + +void resolve_garbage() { + int count=0; + + if(ptt == NULL) { + ptt = attach_shm(PTTSHM_KEY, sizeof(*ptt)); + if(ptt->touchtime == 0) + ptt->touchtime = 1; + } + while(ptt->uptime < ptt->touchtime) { /* ¤£¥Îwhileµ¥ */ + reload_pttcache(); + if(count ++ > 10 && ptt->busystate) { +/* Ptt: ³oÃä·|¦³°ÝÃD load¶W¹L10 ¬í·|©Ò¦³¶iloopªºprocess³£Åý busystate = 0 + ³o¼Ë·|©Ò¦³prcosee³£·|¦bload °ÊºA¬ÝªO ·|³y¦¨load¤j¼W + ¦ý¨S¦³¥Î³oÓfunctionªº¸Ü ¸U¤@load passwdÀɪºprocess¦º¤F ¤S¨S¦³¤H§â¥L + ¸Ñ¶} ¦P¼Ëªº°ÝÃDµo¥Í¦breload passwd +*/ + ptt->busystate = 0; + } + } +} + +/*-------------------------------------------------------*/ +/* PTT's cache */ +/*-------------------------------------------------------*/ +/* cachefor from host »P³Ì¦h¤W½u¤H¼Æ */ +struct fromcache_t *fcache; + +static void reload_fcache() { + if(fcache->busystate) + safe_sleep(1); + else { + FILE *fp; + + fcache->busystate = 1; + bzero(fcache->domain, sizeof fcache->domain); + if((fp = fopen("etc/domain_name_query","r"))) { + char buf[101],*po; + + fcache->top=0; + while(fgets(buf,100,fp)) { + if(buf[0] && buf[0] != '#' && buf[0] != ' ' && + buf[0] != '\n') { + sscanf(buf,"%s",fcache->domain[fcache->top]); + po = buf + strlen(fcache->domain[fcache->top]); + while(*po == ' ') + po++; + strncpy(fcache->replace[fcache->top],po,49); + fcache->replace[fcache->top] + [strlen(fcache->replace[fcache->top])-1] = 0; + (fcache->top)++; + } + } + } + + fcache->max_user=0; + + /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */ + fcache->uptime = fcache->touchtime; + fcache->busystate = 0; + } +} + +void resolve_fcache() { + if(fcache == NULL) { + fcache = attach_shm(FROMSHM_KEY, sizeof(*fcache)); + if(fcache->touchtime == 0) + fcache->touchtime = 1; + } + while(fcache->uptime < fcache->touchtime) + reload_fcache(); +} diff --git a/util/util_passwd.c b/util/util_passwd.c new file mode 100644 index 00000000..07a79351 --- /dev/null +++ b/util/util_passwd.c @@ -0,0 +1,139 @@ +/* $Id: util_passwd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" + +#ifndef SEM_R +#define SEM_R 0400 +#endif + +#ifndef SEM_A +#define SEM_A 0200 +#endif + +#ifndef __FreeBSD__ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + u_short *array; /* array for GETALL & SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif + +static userec_t *passwd_image = NULL; +static int passwd_image_size; +static int semid = -1; + +int passwd_mmap() { + int fd; + + if(passwd_image!=NULL) return 0; + fd = open(FN_PASSWD, O_RDWR); + if(fd > 0) { + struct stat st; + + fstat(fd, &st); + passwd_image_size = st.st_size; + passwd_image = mmap(NULL, passwd_image_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if(passwd_image == (userec_t *)-1) { + perror("mmap"); + return -1; + } + close(fd); + semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A | IPC_CREAT | IPC_EXCL); + if(semid == -1) { + if(errno == EEXIST) { + semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A); + if(semid == -1) { + perror("semget"); + exit(1); + } + } else { + perror("semget"); + exit(1); + } + } else { + union semun s; + + s.val = 1; + if(semctl(semid, 0, SETVAL, s) == -1) { + perror("semctl"); + exit(1); + } + } + } else { + perror(FN_PASSWD); + return -1; + } + return 0; +} +int passwd_update_money(int num) { + int money; + if(num < 1 || num > MAX_USERS) + return -1; + money = moneyof(num); + memcpy(&passwd_image[num - 1].money, &money, sizeof(int)); + return 0; +} + +int passwd_update(int num, userec_t *buf) { + if(num < 1 || num > MAX_USERS) + return -1; + buf->money = moneyof(num); + memcpy(&passwd_image[num - 1], buf, sizeof(userec_t)); + return 0; +} + +int passwd_query(int num, userec_t *buf) { + if(num < 1 || num > MAX_USERS) + return -1; + memcpy(buf, &passwd_image[num - 1], sizeof(userec_t)); + return 0; +} + +int passwd_apply(int (*fptr)(userec_t *)) { + int i; + + for(i = 0; i < MAX_USERS; i++) + if((*fptr)(&passwd_image[i]) == QUIT) + return QUIT; + return 0; +} + +int passwd_apply2(int (*fptr)(int, userec_t *)) { + int i; + + for(i = 0; i < MAX_USERS; i++) + if((*fptr)(i, &passwd_image[i]) == QUIT) + return QUIT; + return 0; +} + +void passwd_lock() { + struct sembuf buf = { 0, -1, SEM_UNDO }; + + if(semop(semid, &buf, 1)) { + perror("semop"); + exit(1); + } +} + +void passwd_unlock() { + struct sembuf buf = { 0, 1, SEM_UNDO }; + + if(semop(semid, &buf, 1)) { + perror("semop"); + exit(1); + } +} diff --git a/util/util_record.c b/util/util_record.c new file mode 100644 index 00000000..ad129638 --- /dev/null +++ b/util/util_record.c @@ -0,0 +1,245 @@ +/* $Id: util_record.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "proto.h" + +#undef HAVE_MMAP +#define BUFSIZE 512 + +extern char *str_reply; + +static void PttLock(int fd, int size, int mode) { + static struct flock lock_it; + int ret; + + lock_it.l_whence = SEEK_CUR; /* from current point */ + lock_it.l_start = 0; /* -"- */ + lock_it.l_len = size; /* length of data */ + lock_it.l_type = mode; /* set exclusive/write lock */ + lock_it.l_pid = 0; /* pid not actually interesting */ + while((ret = fcntl(fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR); +} + +#define safewrite write + +int get_num_records(char *fpath, int size) { + struct stat st; + if(stat(fpath, &st) == -1) + return 0; + return st.st_size / size; +} + +int get_sum_records(char* fpath, int size) { + struct stat st; + long ans = 0; + FILE* fp; + fileheader_t fhdr; + char buf[200], *p; + + if(!(fp = fopen(fpath, "r"))) + return -1; + + strcpy(buf, fpath); + p = strrchr(buf, '/') + 1; + + while(fread(&fhdr, size, 1, fp) == 1) { + strcpy(p, fhdr.filename); + if(stat(buf, &st) == 0 && S_ISREG(st.st_mode) && st.st_nlink == 1) + ans += st.st_size; + } + fclose(fp); + return ans / 1024; +} + +int get_record(char *fpath, void *rptr, int size, int id) { + int fd = -1; + + if(id < 1 || (fd = open(fpath, O_RDONLY, 0)) != -1) { + if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) != -1) { + if(read(fd, rptr, size) == size) { + close(fd); + return 0; + } + } + close(fd); + } + return -1; +} + +int get_records(char *fpath, void *rptr, int size, int id, int number) { + int fd; + + if(id < 1 || (fd = open(fpath, O_RDONLY, 0)) == -1) + return -1; + + if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) == -1) { + close(fd); + return 0; + } + if((id = read(fd, rptr, size * number)) == -1) { + close(fd); + return -1; + } + close(fd); + return id / size; +} + +int substitute_record(char *fpath, void *rptr, int size, int id) { + int fd; + +#ifdef POSTBUG + if(size == sizeof(fileheader) && (id > 1) && ((id - 1) % 4 == 0)) + saverecords(fpath, size, id); +#endif + + if(id < 1 || (fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) + return -1; + +#ifdef HAVE_REPORT + if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) == -1) + report("substitute_record failed!!! (lseek)"); + PttLock(fd, size, F_WRLCK); + if(safewrite(fd, rptr, size) != size) + report("substitute_record failed!!! (safewrite)"); + PttLock(fd, size, F_UNLCK); +#else + lseek(fd, (off_t) (size * (id - 1)), SEEK_SET); + PttLock(fd, size, F_WRLCK); + safewrite(fd, rptr, size); + PttLock(fd, size, F_UNLCK); +#endif + close(fd); + +#ifdef POSTBUG + if(size == sizeof(fileheader) && (id > 1) && ((id - 1) % 4 == 0)) + restorerecords(fpath, size, id); +#endif + + return 0; +} + +int apply_record(char *fpath, int (*fptr)(), int size) { + char abuf[BUFSIZE]; + FILE* fp; + + if(!(fp = fopen(fpath, "r"))) + return -1; + + while(fread(abuf, 1, size, fp) == size) + if((*fptr) (abuf) == QUIT) { + fclose(fp); + return QUIT; + } + fclose(fp); + return 0; +} + +/* mail / post ®É¡A¨Ì¾Ú®É¶¡«Ø¥ßÀɮסA¥[¤W¶lÂW */ +int stampfile(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + int fp = 0; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while (*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "M.%ld.A", ++dtime ); + if(fp == -1 && errno != EEXIST) + return -1; + } while((fp = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644)) == -1); + close(fp); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); + return 0; +} + +void stampdir(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while(*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "D%lX", ++dtime & 07777); + } while(mkdir(fpath, 0755) == -1); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); +} + +void stamplink(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while(*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "S%lX", ++dtime ); + } while(symlink("temp", fpath) == -1); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); +} + +int do_append(char *fpath, fileheader_t *record, int size) { + int fd; + + if((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) { + perror("open"); + return -1; + } + flock(fd, LOCK_EX); + lseek(fd, 0, SEEK_END); + + safewrite(fd, record, size); + + flock(fd, LOCK_UN); + close(fd); + return 0; +} + +int append_record(char *fpath, fileheader_t *record, int size) { +#ifdef POSTBUG + int numrecs = (int)get_num_records(fpath, size); + + bug_possible = 1; + if(size == sizeof(fileheader) && numrecs && (numrecs % 4 == 0)) + saverecords(fpath, size, numrecs + 1); +#endif + do_append(fpath,record,size); + +#ifdef POSTBUG + if(size == sizeof(fileheader) && numrecs && (numrecs % 4 == 0)) + restorerecords(fpath, size, numrecs + 1); + bug_possible = 0; +#endif + return 0; +} diff --git a/util/waterball.pl b/util/waterball.pl new file mode 100644 index 00000000..7f49d3c5 --- /dev/null +++ b/util/waterball.pl @@ -0,0 +1,149 @@ +#!/usr/bin/perl +use lib '/home/bbs/bin/'; +use LocalVars; +use Time::Local; +use POSIX; +use FileHandle; +use strict; +use Mail::Sender; + +my($fndes, $fnsrc, $userid, $mailto, $outmode); +foreach $fndes ( <$JOBSPOOL/water.des.*> ){ #des: userid, mailto, outmode + (open FH, "< $fndes") or next; + chomp($userid = <FH>); + chomp($mailto = <FH>); + chomp($outmode= <FH>); + close FH; + next if( !$userid ); + print "$userid, $mailto, $outmode\n"; + `rm -Rf $TMP/water`; + `mkdir $TMP/water`; + + $fnsrc = $fndes; + $fnsrc =~ s/\.des\./\.src\./; + eval{ + process($fnsrc, "$TMP/water/", $outmode, $userid); + }; + if( $@ ){ + print "$@\n"; + } + else{ + chdir "$TMP/water"; + if( $mailto eq '.' || $mailto =~ /\.bbs/ ){ + $mailto = "$userid.bbs\@$hostname" if( $mailto eq '.' ); + foreach my $fn ( <$TMP/water/*> ){ + my $who = substr($fn, rindex($fn, '/') + 1); + my $content = ''; + open FH, "< $fn";while( <FH> ){chomp;$content .= "$_\n";} + if( !MakeMail({mailto => $mailto, + subject => "©M $who ªº¤ô²y°O¿ý", + body => $content, + }) ){ print "fault\n"; } + } + unlink $fnsrc; + unlink $fndes; + } + else{ + if( MakeMail({tartarget => "$TMP/$userid.waterball.tgz", + tarsource => "*", + mailto => "$userid <$mailto>", + subject => "¤ô²y¬ö¿ý", + body => + "\n ptt2 ¯¸ªø¸s ". POSIX::ctime(time())} + ) ){ + unlink $fnsrc; + unlink $fndes; + } + } + } +} + +sub process +{ + my($fn, $outdir, $outmode, $me) = @_; + my($cmode, $who, $time, $say, $orig, %FH, %LAST, $len); + open DIN, "< $fn"; + while( <DIN> ){ + chomp; + next if( !(($cmode, $who, $time, $say, $orig) = parse($_)) ); + next if( !$who ); + + if( ! $FH{$who} ){ + $FH{$who} = new FileHandle "> $outdir/$who"; + } + if( $outmode == 0 ){ + next if( $say =~ /<<¤U¯¸³qª¾>> -- §Ú¨«Åo¡I/ || + $say =~ /<<¤W¯¸³qª¾>> -- §Ú¨Ó°Õ¡I/ ); + if( $time - $LAST{$who} > 1800 ){ + if( $LAST{$who} != 0 ){ + ($FH{$who})->print( POSIX::ctime($LAST{$who}) , "\n"); + } + ($FH{$who})->print( POSIX::ctime($time) ); + $LAST{$who} = $time; + } + $len = (length($who) > length($me) ? length($who) : length($me))+1; + ($FH{$who})->printf("%-${len}s %s\n", ($cmode?$who:$me).':', $say); + } + elsif( $outmode == 1 ){ + ($FH{$who})->print("$orig\n"); + } + } + if( $outmode == 0 ){ + foreach( keys %FH ){ + ($FH{$_})->print( POSIX::ctime($LAST{$_}) ); + } + } + foreach( keys %FH ){ + ($FH{$_})->close(); + } + close DIN; +} + +sub parse +{ + my $dat = $_[0]; + my($cmode, $who, $year, $month, $day, $hour, $min, $sec, $say); + if( $dat =~ /^To/ ){ + $cmode = 0; + ($who, $say, $month, $day, $year, $hour, $min, $sec) = + $dat =~ m|^To (\w+):\s*(.*)\[(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)\]|; + } + else{ + $cmode = 1; + ($who, $say, $month, $day, $year, $hour, $min, $sec) = + $dat =~ m|¡¹(\w+?)\[37;45m\s*(.*)\[m \[0m\[(\w+)/(\w+)/(\w+) (\w+):(\w+):(\w+)\]|; + + } +# $time = timelocal($sec,$min,$hours,$mday,$mon,$year); + + return undef if( $month == 0 ); + return ($cmode, $who, timelocal($sec, $min, $hour, $day, $month - 1, $year), $say, $_[0]); +} + +sub MakeMail +{ + my($arg) = @_; + my $sender; + `$TAR zcf $arg->{tartarget} $arg->{tarsource}` + if( $arg->{tarsource} ); + $sender = new Mail::Sender{smtp => $SMTPSERVER, + from => "$hostname¤ô²y¾ã²zµ{¦¡ <in2\@ptt2.csie.ntu.edu.tw>"}; + foreach( 0..3 ){ + if( (!$arg->{tartarget} && + $sender->MailMsg({to => $arg->{mailto}, + subject => $arg->{subject}, + msg => $arg->{body} + }) ) || + ($arg->{tartarget} && + $sender->MailFile({to => $arg->{mailto}, + subject => $arg->{subject}, + msg => $arg->{body}, + file => $arg->{tartarget}})) ){ + unlink $arg->{tartarget} if( $arg->{tartarget} ); + return 1; + } + } + print "fault\n"; + unlink $arg->{tartarget} if( $arg->{tartarget} ); + return 0; +} diff --git a/util/weather.perl b/util/weather.perl new file mode 100644 index 00000000..c9a35406 --- /dev/null +++ b/util/weather.perl @@ -0,0 +1,31 @@ +#!/usr/bin/perl +# $Id: weather.perl,v 1.1 2002/03/07 15:13:46 in2 Exp $ +# +# ¤£¯à¶]ªº¸Ü¡A¬Ý¬Ý bbspost ªº¸ô®|¬O§_¥¿½T¡C +# ¦pªGµo¥Xªº post ¨S¦³®ð¶H³ø§i¦Ó¬O»¡ URL §ä¤£¨ì¡A«h½T©w¤@¤U¯à¤£¯à¬Ý¨ì +# ¤¤¥¡®ð¶H§½ªº WWW ¤Î URL ¬O§_¥¿½T¡C +# ²z½×¤W¾A¥Î©Ò¦³ Eagle BBS ¨t¦C¡C +# -- Beagle Apr 13 1997 +open(BBSPOST, "| bin/webgrep>etc/weather.tmp"); +# ¤é´Á +open(DATE, "date +'%a %b %d %T %Y' |"); +$date = <DATE>; +chop $date; +close DATE; + +# Header +# ¤º®e +open(WEATHER, "/usr/bin/lynx -dump http://www.cwb.gov.tw/V3.0/weather/text/Data/W03.txt |"); +while (<WEATHER>) { + print BBSPOST if ($_ ne "\n"); +} +close WEATHER; + +# ñ¦WÀÉ +print BBSPOST "\n--\n"; +print BBSPOST "§Ú¬Obeagle©Ò¦³¥i·Rªº¤p»æ°®...¸ó®ü¬°PttªA°È\n"; +print BBSPOST "--\n"; +print BBSPOST "¡¸ [Origin: ¡·ªGÂæ¤p¯¸¡·] [From: [ÂŲùÃP»æ«Î] ] "; + +close BBSPOST; + diff --git a/util/weather.sh b/util/weather.sh new file mode 100644 index 00000000..315b0ec3 --- /dev/null +++ b/util/weather.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# $Id: weather.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $ +# +bin/weather.perl +bin/post Record ¥þ¬Ù¦U¦a¤Ñ®ð¹w³ø [®ð¶H¤p©j] etc/weather.tmp diff --git a/util/webgrep.c b/util/webgrep.c new file mode 100644 index 00000000..07089bb6 --- /dev/null +++ b/util/webgrep.c @@ -0,0 +1,46 @@ +/* $Id: webgrep.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +int main() +{ + char genbuf[256], *str, *buf; + while (fgets(genbuf, 255, stdin)) + { + register int ansi; + if (!strncmp(genbuf, "References", 10)) + break; + str = genbuf; + buf = genbuf; + if (!strncmp(genbuf, "lynx: Can't access", 18)) + { + printf("®ð¶H³ø¾É¤p©j¥ð°²¤¤,½Ð¨ìRecordª©Â½¹L¥h¸ê®Æ."); + break; + } + for (ansi = 0; *str; str++) + { + if (*str == '[' && strchr("0123456789", *(str + 1))) + { + ansi = 1; + } + else if (ansi) + { + if (!strchr("0123456789]", *str)) + { + ansi = 0; + if (str) + *buf++ = *str; + } + } + else + { + if (str) + *buf++ = *str; + } + } + *buf = 0; + printf(genbuf); + } + return 0; +} diff --git a/util/xchatd.c b/util/xchatd.c new file mode 100644 index 00000000..46fba147 --- /dev/null +++ b/util/xchatd.c @@ -0,0 +1,3504 @@ +/* $Id: xchatd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <time.h> +#include <sys/resource.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "pttstruct.h" +#include "util.h" +#include "perm.h" +#include "common.h" +#include "xchatd.h" + +#define SERVER_USAGE +#define WATCH_DOG +#undef MONITOR /* ºÊ·þ chatroom ¬¡°Ê¥H¸Ñ¨MªÈ¯É */ +#undef DEBUG /* µ{¦¡°£¿ù¤§¥Î */ + +#ifdef DEBUG +#define MONITOR +#endif + +static int gline; + +#ifdef WATCH_DOG +#define MYDOG gline = __LINE__ +#else +#define MYDOG /* NOOP */ +#endif + + + +#define CHAT_PIDFILE "log/chat.pid" +#define CHAT_LOGFILE "log/chat.log" +#define CHAT_INTERVAL (60 * 30) +#define SOCK_QLEN 1 + + +/* name of the main room (always exists) */ + + +#define MAIN_NAME "main" +#define MAIN_TOPIC "²i¯ù¥i°^¦è¤Ñ¦ò" + + +#define ROOM_LOCKED 1 +#define ROOM_SECRET 2 +#define ROOM_OPENTOPIC 4 +#define ROOM_HANDUP 8 +#define ROOM_ALL (NULL) + + +#define LOCKED(room) (room->rflag & ROOM_LOCKED) +#define SECRET(room) (room->rflag & ROOM_SECRET) +#define OPENTOPIC(room) (room->rflag & ROOM_OPENTOPIC) +#define RHANDUP(room) (room->rflag & ROOM_HANDUP) + +#define RESTRICTED(usr) (usr->uflag == 0) /* guest */ +#define CHATSYSOP(usr) (usr->uflag & ( PERM_SYSOP | PERM_CHATROOM)) +/* Thor: SYSOP »P CHATROOM³£¬O chatÁ`ºÞ */ +#define PERM_ROOMOP PERM_CHAT /* Thor: É PERM_CHAT¬° PERM_ROOMOP */ +#define PERM_HANDUP PERM_BM /* É PERM_BM ¬°¦³¨S¦³Á|¤â¹L */ +#define PERM_SAY PERM_NOTOP /* É PERM_NOTOP ¬°¦³¨S¦³µoªíÅv */ + +/* ¶i¤J®É»Ý²MªÅ */ +/* Thor: ROOMOP¬°©Ð¶¡ºÞ²zû */ +#define ROOMOP(usr) (usr->uflag & ( PERM_ROOMOP | PERM_SYSOP | PERM_CHATROOM)) +#define CLOAK(usr) (usr->uflag & PERM_CLOAK) +#define HANDUP(usr) (usr->uflag & PERM_HANDUP) +#define SAY(usr) (usr->uflag & PERM_SAY) +/* Thor: ²á¤Ñ«ÇÁô¨³N */ + + +/* ----------------------------------------------------- */ +/* ChatRoom data structure */ +/* ----------------------------------------------------- */ + +typedef struct ChatRoom ChatRoom; +typedef struct ChatUser ChatUser; +typedef struct UserList UserList; +typedef struct ChatCmd ChatCmd; +typedef struct ChatAction ChatAction; + +struct ChatUser +{ + struct ChatUser *unext; + int sock; /* user socket */ + int talksock; /* talk socket */ + ChatRoom *room; + UserList *ignore; + int userno; + int uflag; + int clitype; /* Xshadow: client type. 1 for common client, + * 0 for bbs only client */ + time_t uptime; /* Thor: unused */ + char userid[IDLEN + 1]; /* real userid */ + char chatid[9]; /* chat id */ + char lasthost[30]; /* host address */ + char ibuf[80]; /* buffer for non-blocking receiving */ + int isize; /* current size of ibuf */ +}; + + +struct ChatRoom +{ + struct ChatRoom *next, *prev; + char name[IDLEN]; + char topic[48]; /* Let the room op to define room topic */ + int rflag; /* ROOM_LOCKED, ROOM_SECRET, ROOM_OPENTOPIC */ + int occupants; /* number of users in room */ + UserList *invite; +}; + + +struct UserList +{ + struct UserList *next; + int userno; + char userid[IDLEN + 1]; +}; + + +struct ChatCmd +{ + char *cmdstr; + void (*cmdfunc) (); + int exact; +}; + + +static ChatRoom mainroom; +static ChatUser *mainuser; +static fd_set mainfds; +static int maxfds; /* number of sockets to select on */ +static int totaluser; /* current number of connections */ +static struct timeval zerotv; /* timeval for selecting */ +static char chatbuf[256]; /* general purpose buffer */ +static int common_client_command; + +static char msg_not_op[] = "¡» ±z¤£¬O³o¶¡²á¤Ñ«Çªº Op"; +static char msg_no_such_id[] = "¡» ¥Ø«e¨S¦³¤H¨Ï¥Î [%s] ³oÓ²á¤Ñ¥N¸¹"; +static char msg_not_here[] = "¡» [%s] ¤£¦b³o¶¡²á¤Ñ«Ç"; + + +#define FUZZY_USER ((ChatUser *) -1) + + +typedef struct userec_t ACCT; + +/* ----------------------------------------------------- */ +/* acct_load for check acct */ +/* ----------------------------------------------------- */ + +int +acct_load(acct, userid) + ACCT *acct; + char *userid; +{ + int id; + if((id=searchuser(userid))<0) + { + return -1; + } + else + { + return get_record(FN_PASSWD, acct, sizeof(ACCT), id); + } +} + + +/* ----------------------------------------------------- */ +/* str_lower for check acct */ +/* ----------------------------------------------------- */ +void +str_lower(dst, src) + char *dst, *src; +{ + register int ch; + + do + { + ch = *src++; + if (ch >= 'A' && ch <= 'Z') + ch |= 0x20; + *dst++ = ch; + } while (ch); +} + +/* + * str_ncpy() - similar to strncpy(3) but terminates string always with '\0' + * if n != 0, and doesn't do padding + */ + +void +str_ncpy(dst, src, n) + char *dst; + char *src; + int n; +{ + char *end; + + end = dst + n; + + do + { + n = (dst == end) ? 0 : *src++; + *dst++ = n; + } while (n); +} + + +/* ----------------------------------------------------- */ +/* usr_fpath for check acct */ +/* ----------------------------------------------------- */ +char *str_home_file = "home/%c/%s/%s"; + +void +usr_fpath(buf, userid, fname) + char *buf, *userid, *fname; +{ + sprintf(buf, str_home_file, userid[0], userid, fname); +} + +/* ----------------------------------------------------- */ +/* chkpasswd for check passwd */ +/* ----------------------------------------------------- */ +char *crypt(); +static char pwbuf[PASSLEN]; + +int +chkpasswd(passwd, test) + char *passwd, *test; +{ + char *pw; + + str_ncpy(pwbuf, test, PASSLEN); + pw = crypt(pwbuf, passwd); + return (!strncmp(pw, passwd, PASSLEN)); +} + +/* ----------------------------------------------------- */ +/* operation log and debug information */ +/* ----------------------------------------------------- */ + + +static int flog; /* log file descriptor */ + + +static void +logit(key, msg) + char *key; + char *msg; +{ + time_t now; + struct tm *p; + char buf[512]; + + time(&now); + p = localtime(&now); + sprintf(buf, "%02d/%02d %02d:%02d:%02d %-13s%s\n", + p->tm_mon + 1, p->tm_mday, + p->tm_hour, p->tm_min, p->tm_sec, key, msg); + write(flog, buf, strlen(buf)); +} + + +static void +log_init() +{ + flog = open(CHAT_LOGFILE, O_WRONLY | O_CREAT | O_APPEND, 0644); + logit("START", "chat daemon"); +} + + +static void +log_close() +{ + close(flog); +} + + +#ifdef DEBUG +static void +debug_user() +{ + register ChatUser *user; + int i; + char buf[80]; + + i = 0; + for (user = mainuser; user; user = user->unext) + { + sprintf(buf, "%d) %s %s", ++i, user->userid, user->chatid); + logit("DEBUG_U", buf); + } +} + + +static void +debug_room() +{ + register ChatRoom *room; + int i; + char buf[80]; + + i = 0; + room = &mainroom; + + do + { + sprintf(buf, "%d) %s %d", ++i, room->name, room->occupants); + logit("DEBUG_R", buf); + } while (room = room->next); +} +#endif /* DEBUG */ + + +/* ----------------------------------------------------- */ +/* string routines */ +/* ----------------------------------------------------- */ + + +static int valid_chatid(register char *id) { + register int ch, len; + + for(len = 0; (ch = *id); id++) { + /* Thor: check for endless */ + MYDOG; + + if(ch == '/' || ch == '*' || ch == ':') + return 0; + if(++len > 8) + return 0; + } + return len; +} + +/* Case Independent strcmp : 1 ==> euqal */ + + +static int +str_equal(s1, s2) + register unsigned char *s1, *s2; /* Thor: ¥[¤W unsigned, + * ÁקK¤¤¤åªº°ÝÃD */ +{ + register int c1, c2; + + for (;;) + { /* Thor: check for endless */ + MYDOG; + + c1 = *s1; + if (c1 >= 'A' && c1 <= 'Z') + c1 |= 32; + + c2 = *s2; + if (c2 >= 'A' && c2 <= 'Z') + c2 |= 32; + + if (c1 != c2) + return 0; + + if (!c1) + return 1; + + s1++; + s2++; + } +} + + +/* ----------------------------------------------------- */ +/* match strings' similarity case-insensitively */ +/* ----------------------------------------------------- */ +/* str_match(keyword, string) */ +/* ----------------------------------------------------- */ +/* 0 : equal ("foo", "foo") */ +/* -1 : mismatch ("abc", "xyz") */ +/* ow : similar ("goo", "good") */ +/* ----------------------------------------------------- */ + + +static int +str_match(s1, s2) + register unsigned char *s1, *s2; /* Thor: ¥[¤W unsigned, + * ÁקK¤¤¤åªº°ÝÃD */ +{ + register int c1, c2; + + for (;;) + { /* Thor: check for endless */ + MYDOG; + + c2 = *s2; + c1 = *s1; + if (!c1) + { + return c2; + } + + if (c1 >= 'A' && c1 <= 'Z') + c1 |= 32; + + if (c2 >= 'A' && c2 <= 'Z') + c2 |= 32; + + if (c1 != c2) + return -1; + + s1++; + s2++; + } +} + + +/* ----------------------------------------------------- */ +/* search user/room by its ID */ +/* ----------------------------------------------------- */ + + +static ChatUser * +cuser_by_userid(userid) + char *userid; +{ + register ChatUser *cu; + + for (cu = mainuser; cu; cu = cu->unext) + { + MYDOG; + + if (str_equal(userid, cu->userid)) + break; + } + return cu; +} + + +static ChatUser * +cuser_by_chatid(chatid) + char *chatid; +{ + register ChatUser *cu; + + for (cu = mainuser; cu; cu = cu->unext) + { + MYDOG; + + if (str_equal(chatid, cu->chatid)) + break; + } + return cu; +} + + +static ChatUser * +fuzzy_cuser_by_chatid(chatid) + char *chatid; +{ + register ChatUser *cu, *xuser; + int mode; + + xuser = NULL; + + for (cu = mainuser; cu; cu = cu->unext) + { + MYDOG; + + mode = str_match(chatid, cu->chatid); + if (mode == 0) + return cu; + + if (mode > 0) + { + if (xuser == NULL) + xuser = cu; + else + return FUZZY_USER; /* ²Å¦XªÌ¤j©ó 2 ¤H */ + } + } + return xuser; +} + + +static ChatRoom *croom_by_roomid(char *roomid) { + register ChatRoom *room; + + room = &mainroom; + do { + MYDOG; + + if(str_equal(roomid, room->name)) + break; + } while((room = room->next)); + return room; +} + + +/* ----------------------------------------------------- */ +/* UserList routines */ +/* ----------------------------------------------------- */ + + +static void +list_free(list) + UserList *list; +{ + UserList *tmp; + + while (list) + { + MYDOG; + + tmp = list->next; + + free(list); + MYDOG; + list = tmp; + } +} + + +static void +list_add(list, user) + UserList **list; + ChatUser *user; +{ + UserList *node; + + MYDOG; + + if((node = (UserList *) malloc(sizeof(UserList)))) { + /* Thor: ¨¾¤îªÅ¶¡¤£°÷ */ + strcpy(node->userid, user->userid); + node->userno = user->userno; + node->next = *list; + *list = node; + } + MYDOG; +} + + +static int +list_delete(list, userid) + UserList **list; + char *userid; +{ + UserList *node; + + while((node = *list)) { + MYDOG; + + if (str_equal(node->userid, userid)) + { + *list = node->next; + MYDOG; + free(node); + MYDOG; + return 1; + } + list = &node->next; /* Thor: listn¸òµÛ«e¶i */ + } + + return 0; +} + + +static int +list_belong(list, userno) + UserList *list; + int userno; +{ + while (list) + { + MYDOG; + + if (userno == list->userno) + return 1; + list = list->next; + } + return 0; +} + + +/* ------------------------------------------------------ */ +/* non-blocking socket routines : send message to users */ +/* ------------------------------------------------------ */ + + +static void +do_send(nfds, wset, msg, number) + int nfds; + fd_set *wset; + char *msg; + int number; +{ + int sr; + + /* Thor: for future reservation bug */ + + zerotv.tv_sec = 0; + zerotv.tv_usec = 16384; /* Ptt: §ï¦¨16384 ÁקK¤£«ö®Éfor loop¦Ycpu time + 16384 ¬ù¨C¬í64¦¸ */ + + MYDOG; + + sr = select(nfds + 1, NULL, wset, NULL, &zerotv); + + MYDOG; + + if (sr > 0) + { + register int len; + + len = strlen(msg) + 1; + while (nfds >= 0) + { + MYDOG; + + if (FD_ISSET(nfds, wset)) + { + MYDOG; + send(nfds, msg, len, 0);/* Thor: ¦pªGbufferº¡¤F, ¤´·| block */ + MYDOG; + if (--sr <= 0) + return; + } + nfds--; + } + } +} + + +static void +send_to_room(room, msg, userno, number) + ChatRoom *room; + char *msg; + int userno; + int number; +{ + ChatUser *cu; + fd_set wset, *wptr; + int sock, max; + static char sendbuf[256]; + int clitype; /* ¤À¬° bbs client ¤Î common client ¨â¦¸³B²z */ + + for (clitype = (number == MSG_MESSAGE || !number) ? 0 : 1; clitype < 2; clitype++) + { + + FD_ZERO(wptr = &wset); + max = -1; + + for (cu = mainuser; cu; cu = cu->unext) + { + MYDOG; + + if (room == cu->room || room == ROOM_ALL) + { + if (cu->clitype == clitype && (!userno || !list_belong(cu->ignore, userno))) + { + sock = cu->sock; + FD_SET(sock, wptr); + if (max < sock) + max = sock; + } + } + } + + if (max < 0) + continue; + + if (clitype) + { + if (strlen(msg)) + sprintf(sendbuf, "%3d %s", number, msg); + else + sprintf(sendbuf, "%3d", number); + + do_send(max, wptr, sendbuf); + } + else + do_send(max, wptr, msg); + } +} + + +static void +send_to_user(user, msg, userno, number) + ChatUser *user; + char *msg; + int userno; + int number; +{ + if (!user->clitype && number && number != MSG_MESSAGE) + return; + + if (!userno || !list_belong(user->ignore, userno)) + { + fd_set wset, *wptr; + int sock; + static char sendbuf[256]; + + sock = user->sock; + FD_ZERO(wptr = &wset); + FD_SET(sock, wptr); + + if (user->clitype) + { + if (strlen(msg)) + sprintf(sendbuf, "%3d %s", number, msg); + else + sprintf(sendbuf, "%3d", number); + do_send(sock, wptr, sendbuf); + } + else + do_send(sock, wptr, msg); + } +} + +#if 0 +static void +send_to_sock(sock, msg) /* Thor: unused */ + int sock; + char *msg; +{ + fd_set wset, *wptr; + + FD_ZERO(wptr = &wset); + FD_SET(sock, wptr); + do_send(sock, wptr, msg); +} +#endif + +/* ----------------------------------------------------- */ + +static void +room_changed(room) + ChatRoom *room; +{ + if (!room) + return; + + sprintf(chatbuf, "= %s %d %d %s", room->name, room->occupants, room->rflag, room->topic); + send_to_room(ROOM_ALL, chatbuf, 0, MSG_ROOMNOTIFY); +} + +static void +user_changed(cu) + ChatUser *cu; +{ + if (!cu) + return; + + sprintf(chatbuf, "= %s %s %s %s", cu->userid, cu->chatid, cu->room->name, cu->lasthost); + if (ROOMOP(cu)) + strcat(chatbuf, " Op"); + send_to_room(cu->room, chatbuf, 0, MSG_USERNOTIFY); +} + +static void +exit_room(user, mode, msg) + ChatUser *user; + int mode; + char *msg; +{ + ChatRoom *room; + + if((room = user->room)) { + user->room = NULL; + user->uflag &= ~PERM_ROOMOP; + + if (--room->occupants > 0) + { + char *chatid; + + chatid = user->chatid; + switch (mode) + { + case EXIT_LOGOUT: + + sprintf(chatbuf, "¡» %s Â÷¶}¤F ...", chatid); + if (msg && *msg) + { + strcat(chatbuf, ": "); + msg[79] = 0; /* Thor:¨¾¤î¤Óªø */ + strncat(chatbuf, msg, 80); + } + break; + + case EXIT_LOSTCONN: + + sprintf(chatbuf, "¡» %s ¦¨¤FÂ_½uªº·ºåÅo", chatid); + break; + + case EXIT_KICK: + + sprintf(chatbuf, "¡» «¢«¢¡I%s ³Q½ð¥X¥h¤F", chatid); + break; + } + if (!CLOAK(user)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(room, chatbuf, 0, MSG_MESSAGE); + + sprintf(chatbuf, "- %s", user->userid); + send_to_room(room, chatbuf, 0, MSG_USERNOTIFY); + room_changed(room); + + return; + } + + else if (room != &mainroom) + { /* Thor: ¤H¼Æ¬°0®É,¤£¬Omainroom¤~free */ + register ChatRoom *next; + +#ifdef DEBUG + debug_room(); +#endif + + sprintf(chatbuf, "- %s", room->name); + send_to_room(ROOM_ALL, chatbuf, 0, MSG_ROOMNOTIFY); + + room->prev->next = room->next; + if((next = room->next)) + next->prev = room->prev; + list_free(room->invite); + + MYDOG; + free(room); + MYDOG; + +#ifdef DEBUG + debug_room(); +#endif + } + } +} + + +/* ----------------------------------------------------- */ +/* chat commands */ +/* ----------------------------------------------------- */ + +/* ----------------------------------------------------- */ +/* (.ACCT) ¨Ï¥ÎªÌ±b¸¹ (account) subroutines */ +/* ----------------------------------------------------- */ + +static char datemsg[32]; + +char * +Ctime(clock) + time_t *clock; +{ + struct tm *t = localtime(clock); + static char week[] = "¤é¤@¤G¤T¥|¤¤»"; + + sprintf(datemsg, "%d¦~%2d¤ë%2d¤é%3d:%02d:%02d ¬P´Á%.2s", + t->tm_year - 11, t->tm_mon + 1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec, &week[t->tm_wday << 1]); + return (datemsg); +} + +static void +chat_query(cu, msg) + ChatUser *cu; + char *msg; +{ + char str[256]; + int i; + ACCT xuser; + FILE *fp; + + if (acct_load(&xuser, msg) >= 0) + { + sprintf(chatbuf, "%s(%s) ¦@¤W¯¸ %d ¦¸¡A¤å³¹ %d ½g", + xuser.userid, xuser.username, xuser.numlogins, xuser.numposts); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + + sprintf(chatbuf, "³Ìªñ(%s)±q(%s)¤W¯¸", Ctime(&xuser.lastlogin), + (xuser.lasthost[0] ? xuser.lasthost : "¥~¤ÓªÅ")); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + + usr_fpath(chatbuf, xuser.userid, "plans"); + fp = fopen(chatbuf, "rt"); + i = 0; + while (fp && fgets(str, 256, fp)) + { + if (!strlen(str)) + continue; + + str[strlen(str) - 1] = 0; + send_to_user(cu, str, 0, MSG_MESSAGE); + if (++i >= MAX_QUERYLINES) + break; + } + fclose(fp); + } + else + { + sprintf(chatbuf, msg_no_such_id, msg); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + } +} + +static void +chat_clear(cu, msg) + ChatUser *cu; + char *msg; +{ + if (cu->clitype) + send_to_user(cu, "", 0, MSG_CLRSCR); + else + send_to_user(cu, "/c", 0, MSG_MESSAGE); +} + +static void +chat_date(cu, msg) + ChatUser *cu; + char *msg; +{ + time_t thetime; + + time(&thetime); + sprintf(chatbuf, "¡» ¼Ð·Ç®É¶¡: %s", Ctime(&thetime)); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_topic(cu, msg) + ChatUser *cu; + char *msg; +{ + ChatRoom *room; + char *topic; + + if (!ROOMOP(cu) && !OPENTOPIC(cu->room)) + { + send_to_user(cu, msg_not_op, 0, MSG_MESSAGE); + return; + } + + if (*msg == '\0') + { + send_to_user(cu, "¡° ½Ð«ü©w¸ÜÃD", 0, MSG_MESSAGE); + return; + } + + room = cu->room; + topic = room->topic; /* Thor: room ¦³¥i¯à NULL¶Ü?? */ + strncpy(topic, msg, 47); + topic[47] = '\0'; + + if (cu->clitype) + send_to_room(room, topic, 0, MSG_TOPIC); + else + { + sprintf(chatbuf, "/t%s", topic); + send_to_room(room, chatbuf, 0, 0); + } + + room_changed(room); + + sprintf(chatbuf, "¡» %s ±N¸ÜÃD§ï¬° [1;32m%s[m", cu->chatid, topic); + if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(room, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_version(cu, msg) + ChatUser *cu; + char *msg; +{ + sprintf(chatbuf, "%d %d", XCHAT_VERSION_MAJOR, XCHAT_VERSION_MINOR); + send_to_user(cu, chatbuf, 0, MSG_VERSION); +} + +static void +chat_nick(cu, msg) + ChatUser *cu; + char *msg; +{ + char *chatid, *str; + ChatUser *xuser; + + chatid = nextword(&msg); + chatid[8] = '\0'; + if (!valid_chatid(chatid)) + { + send_to_user(cu, "¡° ³oÓ²á¤Ñ¥N¸¹¬O¤£¥¿½Tªº", 0, MSG_MESSAGE); + return; + } + + xuser = cuser_by_chatid(chatid); + if (xuser != NULL && xuser != cu) + { + send_to_user(cu, "¡° ¤w¸g¦³¤H±¶¨¬¥ýµnÅo", 0, MSG_MESSAGE); + return; + } + + str = cu->chatid; + + sprintf(chatbuf, "¡° %s ±N²á¤Ñ¥N¸¹§ï¬° [1;33m%s[m", str, chatid); + if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE); + + strcpy(str, chatid); + + user_changed(cu); + + if (cu->clitype) + send_to_user(cu, chatid, 0, MSG_NICK); + else + { + sprintf(chatbuf, "/n%s", chatid); + send_to_user(cu, chatbuf, 0, 0); + } +} + +static void +chat_list_rooms(cuser, msg) + ChatUser *cuser; + char *msg; +{ + ChatRoom *cr, *room; + + if (RESTRICTED(cuser)) + { + send_to_user(cuser, "¡° ±z¨S¦³Åv¦C¥X²{¦³ªº²á¤Ñ«Ç", 0, MSG_MESSAGE); + return; + } + + if (common_client_command) + send_to_user(cuser, "", 0, MSG_ROOMLISTSTART); + else + send_to_user(cuser, "[7m ½Í¤Ñ«Ç¦WºÙ ¢x¤H¼Æ¢x¸ÜÃD [m", 0, MSG_MESSAGE); + + room = cuser->room; + cr = &mainroom; + do + { + MYDOG; + + + if (!SECRET(cr) || CHATSYSOP(cuser) || (cr == room && ROOMOP(cuser))) + { + if (common_client_command) + { + sprintf(chatbuf, "%s %d %d %s", cr->name, cr->occupants, cr->rflag, cr->topic); + send_to_user(cuser, chatbuf, 0, MSG_ROOMLIST); + } + else + { + sprintf(chatbuf, " %-12s¢x%4d¢x%s", cr->name, cr->occupants, cr->topic); + if (LOCKED(cr)) + strcat(chatbuf, " [Âê¦í]"); + if (SECRET(cr)) + strcat(chatbuf, " [¯µ±K]"); + if (OPENTOPIC(cr)) + strcat(chatbuf, " [¸ÜÃD]"); + send_to_user(cuser, chatbuf, 0, MSG_MESSAGE); + } + + } + } while((cr = cr->next)); + + if (common_client_command) + send_to_user(cuser, "", 0, MSG_ROOMLISTEND); +} + + +static void +chat_do_user_list(cu, msg, theroom) + ChatUser *cu; + char *msg; + ChatRoom *theroom; +{ + ChatRoom *myroom, *room; + ChatUser *user; + + int start, stop, curr = 0; + start = atoi(nextword(&msg)); + stop = atoi(nextword(&msg)); + + myroom = cu->room; + +#ifdef DEBUG + logit(cu->chatid, "do user list"); +#endif + + if (common_client_command) + send_to_user(cu, "", 0, MSG_USERLISTSTART); + else + send_to_user(cu, "[7m ²á¤Ñ¥N¸¹¢x¨Ï¥ÎªÌ¥N¸¹ ¢x²á¤Ñ«Ç [m", 0, MSG_MESSAGE); + + for (user = mainuser; user; user = user->unext) + { + MYDOG; + + + room = user->room; + if ((theroom != ROOM_ALL) && (theroom != room)) + continue; + + if (myroom != room) + { + if (RESTRICTED(cu) || + (room && SECRET(room) && !CHATSYSOP(cu))) + continue; + } + + if (CLOAK(user)) /* Thor: Áô¨³N */ + continue; + + + curr++; + if (start && curr < start) + continue; + else if (stop && (curr > stop)) + break; + + if (common_client_command) + { + if (!room) + continue; /* Xshadow: ÁÙ¨S¶i¤J¥ô¦ó©Ð¶¡ªº´N¤£¦C¥X */ + + sprintf(chatbuf, "%s %s %s %s", user->chatid, user->userid, room->name, user->lasthost); + if (ROOMOP(user)) + strcat(chatbuf, " Op"); + } + else + { + sprintf(chatbuf, " %-8s¢x%-12s¢x%s", user->chatid, user->userid, room ? room->name : "[¦bªù¤f±r«Þ]"); + if (ROOMOP(user)) + strcat(chatbuf, " [Op]"); + } + +#ifdef DEBUG + logit("list_U", chatbuf); +#endif + + send_to_user(cu, chatbuf, 0, common_client_command ? MSG_USERLIST : MSG_MESSAGE); + } + if (common_client_command) + send_to_user(cu, "", 0, MSG_USERLISTEND); +} + +static void +chat_list_by_room(cu, msg) + ChatUser *cu; + char *msg; +{ + ChatRoom *whichroom; + char *roomstr; + + roomstr = nextword(&msg); + if (*roomstr == '\0') + whichroom = cu->room; + else + { + if ((whichroom = croom_by_roomid(roomstr)) == NULL) + { + sprintf(chatbuf, "¡° ¨S¦³ [%s] ³oÓ²á¤Ñ«Ç", roomstr); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + if (whichroom != cu->room && SECRET(whichroom) && !CHATSYSOP(cu)) + { /* Thor: n¤£n´ú¦P¤@roomÁöSECRET¦ý¥i¥H¦C? + * Xshadow: §Ú§ï¦¨¦P¤@ room ´N¥i¥H¦C */ + send_to_user(cu, "¡° µLªk¦C¥X¦b¯µ±K²á¤Ñ«Çªº¨Ï¥ÎªÌ", 0, MSG_MESSAGE); + return; + } + } + chat_do_user_list(cu, msg, whichroom); +} + + +static void +chat_list_users(cu, msg) + ChatUser *cu; + char *msg; +{ + chat_do_user_list(cu, msg, ROOM_ALL); +} + +static void +chat_chatroom(cu, msg) + ChatUser *cu; + char *msg; +{ + if (common_client_command) + send_to_user(cu, "§å½ð½ð¯ùÃÀÀ] 4 21", 0, MSG_CHATROOM); +} + +static void +chat_map_chatids(cu, whichroom) + ChatUser *cu; /* Thor: ÁÙ¨S¦³§@¤£¦P¶¡ªº */ + ChatRoom *whichroom; +{ + int c; + ChatRoom *myroom, *room; + ChatUser *user; + + /* myroom = cu->room; */ + myroom = whichroom; + send_to_user(cu, + "[7m ²á¤Ñ¥N¸¹ ¨Ï¥ÎªÌ¥N¸¹ ¢x ²á¤Ñ¥N¸¹ ¨Ï¥ÎªÌ¥N¸¹ ¢x ²á¤Ñ¥N¸¹ ¨Ï¥ÎªÌ¥N¸¹ [m", 0, MSG_MESSAGE); + + c = 0; + + for (user = mainuser; user; user = user->unext) + { + MYDOG; + + room = user->room; + MYDOG; + if (whichroom != ROOM_ALL && whichroom != room) + continue; + MYDOG; + if (myroom != room) + { + if (RESTRICTED(cu) || /* Thor: n¥ýcheck room ¬O¤£¬OªÅªº */ + (room && SECRET(room) && !CHATSYSOP(cu))) + continue; + } + MYDOG; + if (CLOAK(user)) /* Thor:Áô¨³N */ + continue; + sprintf(chatbuf + (c * 24), " %-8s%c%-12s%s", + user->chatid, ROOMOP(user) ? '*' : ' ', + user->userid, (c < 2 ? "¢x" : " ")); + MYDOG; + if (++c == 3) + { + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + c = 0; + } + MYDOG; + } + if (c > 0) + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_map_chatids_thisroom(cu, msg) + ChatUser *cu; + char *msg; +{ + chat_map_chatids(cu, cu->room); +} + + +static void +chat_setroom(cu, msg) + ChatUser *cu; + char *msg; +{ + char *modestr; + ChatRoom *room; + char *chatid; + int sign; + int flag; + char *fstr = NULL; + + if (!ROOMOP(cu)) + { + send_to_user(cu, msg_not_op, 0, MSG_MESSAGE); + return; + } + + modestr = nextword(&msg); + sign = 1; + if (*modestr == '+') + modestr++; + else if (*modestr == '-') + { + modestr++; + sign = 0; + } + if (*modestr == '\0') + { + send_to_user(cu, + "¡° ½Ð«ü©wª¬ºA: {[+(³]©w)][-(¨ú®ø)]}{[l(Âê¦í)][s(¯µ±K)][t(¶}©ñ¸ÜÃD)}", 0, MSG_MESSAGE); + return; + } + + room = cu->room; + chatid = cu->chatid; + + while (*modestr) + { + flag = 0; + switch (*modestr) + { + case 'l': + case 'L': + flag = ROOM_LOCKED; + fstr = "Âê¦í"; + break; + + case 's': + case 'S': + flag = ROOM_SECRET; + fstr = "¯µ±K"; + break; + + case 't': + case 'T': + flag = ROOM_OPENTOPIC; + fstr = "¶}©ñ¸ÜÃD"; + break; + case 'h': + case 'H': + flag = ROOM_OPENTOPIC; + fstr = "Á|¤âµo¨¥"; + break; + + default: + sprintf(chatbuf, "¡° ª¬ºA¿ù»~¡G[%c]", *modestr); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + } + + /* Thor: check room ¬O¤£¬OªÅªº, À³¸Ó¤£¬OªÅªº */ + if (flag && (room->rflag & flag) != sign * flag) + { + room->rflag ^= flag; + sprintf(chatbuf, "¡° ¥»²á¤Ñ«Ç³Q %s %s [%s] ª¬ºA", + chatid, sign ? "³]©w¬°" : "¨ú®ø", fstr); + if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(room, chatbuf, 0, MSG_MESSAGE); + } + modestr++; + } + room_changed(room); +} + +static char *chat_msg[] = +{ + "[//]help", "MUD-like ªÀ¥æ°Êµü", + "[/h]elp op", "½Í¤Ñ«ÇºÞ²zû±M¥Î«ü¥O", + "[/a]ct <msg>", "°µ¤@Ӱʧ@", + "[/b]ye [msg]", "¹D§O", + "[/c]lear [/d]ate", "²M°£¿Ã¹õ ¥Ø«e®É¶¡", + /* "[/d]ate", "¥Ø«e®É¶¡", *//* Thor: «ü¥O¤Ó¦h */ + +#if 0 + "[/f]ire <user> <msg>", "µo°e¼ö°T", /* Thor.0727: ©M flag ½Äkey */ +#endif + + "[/i]gnore [user]", "©¿²¤¨Ï¥ÎªÌ", + "[/j]oin <room>", "«Ø¥ß©Î¥[¤J½Í¤Ñ«Ç", + "[/l]ist [start [stop]]", "¦C¥X½Í¤Ñ«Ç¨Ï¥ÎªÌ", + "[/m]sg <id|user> <msg>", "¸ò <id> »¡®¨®¨¸Ü", + "[/n]ick <id>", "±N½Í¤Ñ¥N¸¹´«¦¨ <id>", + "[/p]ager", "¤Á´«©I¥s¾¹", + "[/q]uery <user>", "¬d¸ßºô¤Í", + "[/r]oom", "¦C¥X¤@¯ë½Í¤Ñ«Ç", + "[/t]ape", "¶}Ãö¿ýµ¾÷", + "[/u]nignore <user>", "¨ú®ø©¿²¤", + +#if 0 + "[/u]sers", "¦C¥X¯¸¤W¨Ï¥ÎªÌ", +#endif + + "[/w]ho", "¦C¥X¥»½Í¤Ñ«Ç¨Ï¥ÎªÌ", + "[/w]hoin <room>", "¦C¥X½Í¤Ñ«Ç<room> ªº¨Ï¥ÎªÌ", + NULL +}; + + +static char *room_msg[] = +{ + "[/f]lag [+-][lsth]", "³]©wÂê©w¡B¯µ±K¡B¶}©ñ¸ÜÃD¡BÁ|¤âµo¨¥", + "[/i]nvite <id>", "ÁܽР<id> ¥[¤J½Í¤Ñ«Ç", + "[/kick] <id>", "±N <id> ½ð¥X½Í¤Ñ«Ç", + "[/o]p <id>", "±N Op ªºÅv¤OÂಾµ¹ <id>", + "[/topic] <text>", "´«Ó¸ÜÃD", + "[/w]all", "¼s¼½ (¯¸ªø±M¥Î)", + NULL +}; + + +static void +chat_help(cu, msg) + ChatUser *cu; + char *msg; +{ + char **table, *str; + + if (str_equal(nextword(&msg), "op")) + { + send_to_user(cu, "½Í¤Ñ«ÇºÞ²zû±M¥Î«ü¥O", 0, MSG_MESSAGE); + table = room_msg; + } + else + { + table = chat_msg; + } + + while((str = *table++)) { + sprintf(chatbuf, " %-20s- %s", str, *table++); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + } +} + + +static void +chat_private(cu, msg) + ChatUser *cu; + char *msg; +{ + char *recipient; + ChatUser *xuser; + int userno; + + userno = 0; + recipient = nextword(&msg); + xuser = (ChatUser *) fuzzy_cuser_by_chatid(recipient); + if (xuser == NULL) + { /* Thor.0724: ¥Î userid¤]¥i¶Ç®¨®¨¸Ü */ + xuser = cuser_by_userid(recipient); + } + if (xuser == NULL) + { + sprintf(chatbuf, msg_no_such_id, recipient); + } + else if (xuser == FUZZY_USER) + { /* ambiguous */ + strcpy(chatbuf, "¡° ½Ð«ü©ú²á¤Ñ¥N¸¹"); + } + else if (*msg) + { + userno = cu->userno; + sprintf(chatbuf, "[1m*%s*[m ", cu->chatid); + msg[79] = 0; /* Thor:¨¾¤î¤Óªø */ + strncat(chatbuf, msg, 80); + send_to_user(xuser, chatbuf, userno, MSG_MESSAGE); + + if (xuser->clitype) + { /* Xshadow: ¦pªG¹ï¤è¬O¥Î client ¤W¨Óªº */ + sprintf(chatbuf, "%s %s ", cu->userid, cu->chatid); + msg[79] = 0; + strncat(chatbuf, msg, 80); + send_to_user(xuser, chatbuf, userno, MSG_PRIVMSG); + } + if (cu->clitype) + { + sprintf(chatbuf, "%s %s ", xuser->userid, xuser->chatid); + msg[79] = 0; + strncat(chatbuf, msg, 80); + send_to_user(cu, chatbuf, 0, MSG_MYPRIVMSG); + } + + sprintf(chatbuf, "%s> ", xuser->chatid); + strncat(chatbuf, msg, 80); + } + else + { + sprintf(chatbuf, "¡° ±z·Q¹ï %s »¡¤°»ò¸Ü©O¡H", xuser->chatid); + } + send_to_user(cu, chatbuf, userno, MSG_MESSAGE); /* Thor: userno n§ï¦¨ 0 + * ¶Ü? */ +} + + +static void +chat_cloak(cu, msg) + ChatUser *cu; + char *msg; +{ + if (CHATSYSOP(cu)) + { + cu->uflag ^= PERM_CLOAK; + sprintf(chatbuf, "¡» %s", CLOAK(cu) ? MSG_CLOAKED : MSG_UNCLOAK); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + } +} + + + +/* ----------------------------------------------------- */ + + +static void +arrive_room(cuser, room) + ChatUser *cuser; + ChatRoom *room; +{ + char *rname; + + /* Xshadow: ¤£¥²°eµ¹¦Û¤v, ¤Ï¥¿´«©Ð¶¡´N·|«·s build user list */ + sprintf(chatbuf, "+ %s %s %s %s", cuser->userid, cuser->chatid, room->name, cuser->lasthost); + if (ROOMOP(cuser)) + strcat(chatbuf, " Op"); + send_to_room(room, chatbuf, 0, MSG_USERNOTIFY); + + cuser->room = room; + room->occupants++; + rname = room->name; + + room_changed(room); + + if (cuser->clitype) + { + send_to_user(cuser, rname, 0, MSG_ROOM); + send_to_user(cuser, room->topic, 0, MSG_TOPIC); + } + else + { + sprintf(chatbuf, "/r%s", rname); + send_to_user(cuser, chatbuf, 0, 0); + sprintf(chatbuf, "/t%s", room->topic); + send_to_user(cuser, chatbuf, 0, 0); + } + + sprintf(chatbuf, "¡° [32;1m%s[m ¶i¤J [33;1m[%s][m ¥]´[", + cuser->chatid, rname); + if (!CLOAK(cuser)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(room, chatbuf, cuser->userno, MSG_MESSAGE); +} + + +static int +enter_room(cuser, rname, msg) + ChatUser *cuser; + char *rname; + char *msg; +{ + ChatRoom *room; + int create; + + create = 0; + room = croom_by_roomid(rname); + if (room == NULL) + { + /* new room */ + +#ifdef MONITOR + logit(cuser->userid, "create new room"); +#endif + + MYDOG; + + room = (ChatRoom *) malloc(sizeof(ChatRoom)); + MYDOG; + if (room == NULL) + { + send_to_user(cuser, "¡° µLªk¦A·sÅP¥]´[¤F", 0, MSG_MESSAGE); + return 0; + } + + memset(room, 0, sizeof(ChatRoom)); + memcpy(room->name, rname, IDLEN - 1); + strcpy(room->topic, "³o¬O¤@Ó·s¤Ñ¦a"); + + sprintf(chatbuf, "+ %s 1 0 %s", room->name, room->topic); + send_to_room(ROOM_ALL, chatbuf, 0, MSG_ROOMNOTIFY); + + if (mainroom.next != NULL) + mainroom.next->prev = room; + room->next = mainroom.next; + mainroom.next = room; + room->prev = &mainroom; + + create = 1; + } + else + { + if (cuser->room == room) + { + sprintf(chatbuf, "¡° ±z¥»¨Ó´N¦b [%s] ²á¤Ñ«ÇÅo :)", rname); + send_to_user(cuser, chatbuf, 0, MSG_MESSAGE); + return 0; + } + + if (!CHATSYSOP(cuser) && LOCKED(room) && !list_belong(room->invite, cuser->userno)) + { + send_to_user(cuser, "¡° ¤º¦³´c¤ü¡A«D½Ð²ö¤J", 0, MSG_MESSAGE); + return 0; + } + } + + exit_room(cuser, EXIT_LOGOUT, msg); + arrive_room(cuser, room); + + if (create) + cuser->uflag |= PERM_ROOMOP; + + return 0; +} + + +static void +logout_user(cuser) + ChatUser *cuser; +{ + int sock; + ChatUser *xuser, *prev; + +#ifdef DEBUG + logit("before", "logout"); + debug_user(); +#endif + + sock = cuser->sock; + shutdown(sock, 2); + close(sock); + + MYDOG; + + FD_CLR(sock, &mainfds); + +#if 0 /* Thor: ¤]³\¤£®t³o¤@Ó */ + if (sock >= maxfds) + maxfds = sock - 1; +#endif + + list_free(cuser->ignore); + +#ifdef DEBUG + debug_user(); +#endif + + xuser = mainuser; + if (xuser == cuser) + { + mainuser = cuser->unext; + } + else + { + do + { + prev = xuser; + xuser = xuser->unext; + if (xuser == cuser) + { + prev->unext = cuser->unext; + break; + } + } while (xuser); + } + + MYDOG; + +#ifdef DEBUG + sprintf(chatbuf, "%p", cuser); + logit("free cuser", chatbuf); +#endif + + free(cuser); + +#ifdef DEBUG + logit("after", "logout"); + debug_user(); +#endif + +#if 0 + next = cuser->next; + prev = cuser->prev; + prev->next = next; + if (next) + next->prev = prev; + + if (cuser) + free(cuser); + MYDOG; + +#endif + + totaluser--; +} + + +static void +print_user_counts(cuser) + ChatUser *cuser; +{ + ChatRoom *room; + int num, userc, suserc, roomc, number; + + userc = suserc = roomc = 0; + + room = &mainroom; + do + { + MYDOG; + + num = room->occupants; + if (SECRET(room)) + { + suserc += num; + if (CHATSYSOP(cuser)) + roomc++; + } + else + { + userc += num; + roomc++; + } + } while((room = room->next)); + + number = (cuser->clitype) ? MSG_MOTD : MSG_MESSAGE; + + sprintf(chatbuf, + "¡ó Åwªï¥úÁ{¡i§å½ð½ð¯ùÃÀÀ]¡j¡A¥Ø«e¶}¤F [1;31m%d[m ¶¡¥]´[", roomc); + send_to_user(cuser, chatbuf, 0, number); + + sprintf(chatbuf, "¡ó ¦@¦³ [1;36m%d[m ¤H¨ÓÂ\\Àsªù°}", userc); + if (suserc) + sprintf(chatbuf + strlen(chatbuf), " [%d ¤H¦b¯µ±K²á¤Ñ«Ç]", suserc); + send_to_user(cuser, chatbuf, 0, number); +} + + +static int +login_user(cu, msg) + ChatUser *cu; + char *msg; +{ + int utent; + + char *level; + char *userid; + char *chatid; + struct sockaddr_in from; + int fromlen; + struct hostent *hp; + + + ACCT acct; + char buf[20]; + + /* + * Thor.0819: SECURED_CHATROOM : /! userid chatid passwd , userno + * el ¦bcheck§¹passwd«á¨ú±o + */ + /* Xshadow.0915: common client support : /-! userid chatid password */ + + /* ¶Ç°Ñ¼Æ¡Guserlevel, userid, chatid */ + + /* client/server ª©¥»¨Ì¾Ú userid §ì .PASSWDS §PÂ_ userlevel */ + + userid = nextword(&msg); + chatid = nextword(&msg); + + +#ifdef DEBUG + logit("ENTER", userid); +#endif + /* Thor.0730: parse space before passwd */ + level = msg; + + /* Thor.0813: ¸õ¹L¤@ªÅ®æ§Y¥i, ¦]¬°¤Ï¥¿¦pªGchatid¦³ªÅ®æ, ±K½X¤]¤£¹ï */ + /* ´Nºâ±K½X¹ï, ¤]¤£·|«ç»ò¼Ë:p */ + /* ¥i¬O¦pªG±K½X²Ä¤@Ó¦r¬OªÅ®æ, ¨º¸õ¤Ó¦hªÅ®æ·|¶i¤£¨Ó... */ + if (*level == ' ') + level++; + + /* Thor.0729: load acct */ + if (!*userid || (acct_load(&acct, userid) < 0)) + { + +#ifdef DEBUG + logit("noexist", chatid); +#endif + + if (cu->clitype) + send_to_user(cu, "¿ù»~ªº¨Ï¥ÎªÌ¥N¸¹", 0, ERR_LOGIN_NOSUCHUSER); + else + send_to_user(cu, CHAT_LOGIN_INVALID, 0, 0); + + return -1; + } + else if(strncmp(level, acct.passwd, PASSLEN) && + !chkpasswd(acct.passwd, level)) + { + +#ifdef DEBUG + logit("fake", chatid); +#endif + + if (cu->clitype) + send_to_user(cu, "±K½X¿ù»~", 0, ERR_LOGIN_PASSERROR); + else + send_to_user(cu, CHAT_LOGIN_INVALID, 0, 0); + return -1; + } + else + { + /* Thor.0729: if ok, read level. */ + sprintf(buf, "%d", acct.userlevel); + level = buf; + /* Thor.0819: read userno for client/server bbs */ + utent = searchuser(acct.userid); + } + + /* Thor.0819: for client/server bbs */ +/* + for (xuser = mainuser; xuser; xuser = xuser->unext) + { + MYDOG; + + if (xuser->userno == utent) + { + + #ifdef DEBUG + logit("enter", "bogus"); + #endif + if (cu->clitype) + send_to_user(cu, "½Ð¤Å¬£»º¤À¨¶i¤J²á¤Ñ«Ç !!", 0, ERR_LOGIN_USERONLINE); + else + send_to_user(cu, CHAT_LOGIN_BOGUS, 0, 0); + return -1; + } + } +*/ + if (!valid_chatid(chatid)) + { + +#ifdef DEBUG + logit("enter", chatid); +#endif + + if (cu->clitype) + send_to_user(cu, "¤£¦Xªkªº²á¤Ñ«Ç¥N¸¹ !!", 0, ERR_LOGIN_NICKERROR); + else + send_to_user(cu, CHAT_LOGIN_INVALID, 0, 0); + return 0; + } + +#ifdef DEBUG + debug_user(); +#endif + + if (cuser_by_chatid(chatid) != NULL) + { + /* chatid in use */ + +#ifdef DEBUG + logit("enter", "duplicate"); +#endif + + if (cu->clitype) + send_to_user(cu, "³oÓ¥N¸¹¤w¸g¦³¤H¨Ï¥Î", 0, ERR_LOGIN_NICKINUSE); + else + send_to_user(cu, CHAT_LOGIN_EXISTS, 0, 0); + return 0; + } + + cu->userno = utent; + cu->uflag = atoi(level) & ~(PERM_ROOMOP | PERM_CLOAK | PERM_HANDUP | PERM_SAY); + /* Thor: ¶i¨Ó¥ý²MªÅROOMOP(¦PPERM_CHAT), CLOAK */ + strcpy(cu->userid, userid); + memcpy(cu->chatid, chatid, 8); + cu->chatid[8] = '\0'; + + /* Xshadow: ¨ú±o client ªº¨Ó·½ */ + fromlen = sizeof(from); + if (!getpeername(cu->sock, (struct sockaddr *) & from, &fromlen)) + { + if ((hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr), from.sin_family))) + { + strcpy(cu->lasthost, hp->h_name); + } + else + strcpy(cu->lasthost, (char *) inet_ntoa(from.sin_addr)); + + } + else + { + strcpy(cu->lasthost, "[¥~¤ÓªÅ]"); + } + + if (cu->clitype) + send_to_user(cu, "¶¶§Q", 0, MSG_LOGINOK); + else + send_to_user(cu, CHAT_LOGIN_OK, 0, 0); + + arrive_room(cu, &mainroom); + + send_to_user(cu, "", 0, MSG_MOTDSTART); + print_user_counts(cu); + send_to_user(cu, "", 0, MSG_MOTDEND); + +#ifdef DEBUG + logit("enter", "OK"); +#endif + + return 0; +} + + +static void +chat_act(cu, msg) + ChatUser *cu; + char *msg; +{ + if (*msg && (!RHANDUP(cu->room) || SAY(cu) || ROOMOP(cu))) + { + sprintf(chatbuf, "%s [36m%s[m", cu->chatid, msg); + send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE); + } +} + + +static void +chat_ignore(cu, msg) + ChatUser *cu; + char *msg; +{ + + if (RESTRICTED(cu)) + { + strcpy(chatbuf, "¡° ±z¨S¦³ ignore §O¤HªºÅv§Q"); + } + else + { + char *ignoree; + + ignoree = nextword(&msg); + if (*ignoree) + { + ChatUser *xuser; + + xuser = cuser_by_userid(ignoree); + + if (xuser == NULL) + { + + sprintf(chatbuf, msg_no_such_id, ignoree); + +#if 0 + sprintf(chatbuf, "¡» ½Í¤Ñ«Ç²{¦b¨S¦³ [%s] ³o¸¹¤Hª«", ignoree); +#endif + } + else if (xuser == cu || CHATSYSOP(xuser) || + (ROOMOP(xuser) && (xuser->room == cu->room))) + { + sprintf(chatbuf, "¡» ¤£¥i¥H ignore [%s]", ignoree); + } + else + { + + if (list_belong(cu->ignore, xuser->userno)) + { + sprintf(chatbuf, "¡° %s ¤w¸g³Qáµ²¤F", xuser->chatid); + } + else + { + list_add(&(cu->ignore), xuser); + sprintf(chatbuf, "¡» ±N [%s] ¥´¤J§N®c¤F :p", xuser->chatid); + } + } + } + else + { + UserList *list; + + if((list = cu->ignore)) + { + int len; + char buf[16]; + + send_to_user(cu, "¡» ³o¨Ç¤H³Q¥´¤J§N®c¤F¡G", 0, MSG_MESSAGE); + len = 0; + do + { + sprintf(buf, "%-13s", list->userid); + strcpy(chatbuf + len, buf); + len += 13; + if (len >= 78) + { + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + len = 0; + } + } while((list = list->next)); + + if (len == 0) + return; + } + else + { + strcpy(chatbuf, "¡» ±z¥Ø«e¨Ã¨S¦³ ignore ¥ô¦ó¤H"); + } + } + } + + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_unignore(cu, msg) + ChatUser *cu; + char *msg; +{ + char *ignoree; + + ignoree = nextword(&msg); + + if (*ignoree) + { + sprintf(chatbuf, (list_delete(&(cu->ignore), ignoree)) ? + "¡» [%s] ¤£¦A³Q§A§N¸¨¤F" : + "¡» ±z¨Ã¥¼ ignore [%s] ³o¸¹¤Hª«", ignoree); + } + else + { + strcpy(chatbuf, "¡» ½Ð«ü©ú user ID"); + } + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_join(cu, msg) + ChatUser *cu; + char *msg; +{ + if (RESTRICTED(cu)) + { + send_to_user(cu, "¡° ±z¨S¦³¥[¤J¨ä¥L²á¤Ñ«ÇªºÅv", 0, MSG_MESSAGE); + } + else + { + char *roomid = nextword(&msg); + + if (*roomid) + enter_room(cu, roomid, msg); + else + send_to_user(cu, "¡° ½Ð«ü©w²á¤Ñ«Çªº¦W¦r", 0, MSG_MESSAGE); + } +} + + +static void +chat_kick(cu, msg) + ChatUser *cu; + char *msg; +{ + char *twit; + ChatUser *xuser; + ChatRoom *room; + + if (!ROOMOP(cu)) + { + send_to_user(cu, msg_not_op, 0, MSG_MESSAGE); + return; + } + + twit = nextword(&msg); + xuser = cuser_by_chatid(twit); + + if (xuser == NULL) + { + sprintf(chatbuf, msg_no_such_id, twit); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + room = cu->room; + if (room != xuser->room || CLOAK(xuser)) + { /* Thor: ²á¤Ñ«ÇÁô¨³N */ + sprintf(chatbuf, msg_not_here, twit); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + if (CHATSYSOP(xuser)) + { /* Thor: ½ð¤£¨« CHATSYSOP */ + sprintf(chatbuf, "¡» ¤£¥i¥H kick [%s]", twit); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + exit_room(xuser, EXIT_KICK, (char *) NULL); + + if (room == &mainroom) + logout_user(xuser); + else + enter_room(xuser, MAIN_NAME, (char *) NULL); +} + + +static void +chat_makeop(cu, msg) + ChatUser *cu; + char *msg; +{ + char *newop; + ChatUser *xuser; + ChatRoom *room; + + if (!ROOMOP(cu)) + { + send_to_user(cu, msg_not_op, 0, MSG_MESSAGE); + return; + } + + newop = nextword(&msg); + xuser = cuser_by_chatid(newop); + + if (xuser == NULL) + { + sprintf(chatbuf, msg_no_such_id, newop); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + if (cu == xuser) + { + sprintf(chatbuf, "¡° ±z¦´N¤w¸g¬O Op ¤F°Ú"); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + room = cu->room; + + if (room != xuser->room || CLOAK(xuser)) + { /* Thor: ²á¤Ñ«ÇÁô¨³N */ + sprintf(chatbuf, msg_not_here, xuser->chatid); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + cu->uflag &= ~PERM_ROOMOP; + xuser->uflag |= PERM_ROOMOP; + + user_changed(cu); + user_changed(xuser); + + sprintf(chatbuf, "¡° %s ±N Op Åv¤OÂಾµ¹ %s", + cu->chatid, xuser->chatid); + if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(room, chatbuf, 0, MSG_MESSAGE, MSG_MESSAGE); +} + + + +static void +chat_invite(cu, msg) + ChatUser *cu; + char *msg; +{ + char *invitee; + ChatUser *xuser; + ChatRoom *room; + UserList **list; + + if (!ROOMOP(cu)) + { + send_to_user(cu, msg_not_op, 0, MSG_MESSAGE); + return; + } + + invitee = nextword(&msg); + xuser = cuser_by_chatid(invitee); + if (xuser == NULL) + { + sprintf(chatbuf, msg_no_such_id, invitee); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + + room = cu->room; /* Thor: ¬O§_n check room ¬O§_ NULL ? */ + list = &(room->invite); + + if (list_belong(*list, xuser->userno)) + { + sprintf(chatbuf, "¡° %s ¤w¸g±µ¨ü¹LÁܽФF", xuser->chatid); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return; + } + list_add(list, xuser); + + sprintf(chatbuf, "¡° %s Áܽбz¨ì [%s] ²á¤Ñ«Ç", + cu->chatid, room->name); + send_to_user(xuser, chatbuf, 0, MSG_MESSAGE); /* Thor: n¤£n¥i¥H ignore? */ + sprintf(chatbuf, "¡° %s ¦¬¨ì±zªºÁܽФF", xuser->chatid); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_broadcast(cu, msg) + ChatUser *cu; + char *msg; +{ + if (!CHATSYSOP(cu)) + { + send_to_user(cu, "¡° ±z¨S¦³¦b²á¤Ñ«Ç¼s¼½ªºÅv¤O!", 0, MSG_MESSAGE); + return; + } + if (*msg == '\0') + { + send_to_user(cu, "¡° ½Ð«ü©w¼s¼½¤º®e", 0, MSG_MESSAGE); + return; + } + sprintf(chatbuf, "[1m¡° " BBSNAME "½Í¤Ñ«Ç¼s¼½¤¤ [%s].....[m", + cu->chatid); + send_to_room(ROOM_ALL, chatbuf, 0, MSG_MESSAGE); + sprintf(chatbuf, "¡» %s", msg); + send_to_room(ROOM_ALL, chatbuf, 0, MSG_MESSAGE); +} + + +static void +chat_goodbye(cu, msg) + ChatUser *cu; + char *msg; +{ + exit_room(cu, EXIT_LOGOUT, msg); + /* Thor: n¤£n¥[ logout_user(cu) ? */ +} + + +/* --------------------------------------------- */ +/* MUD-like social commands : action */ +/* --------------------------------------------- */ + +struct ChatAction +{ + char *verb; /* °Êµü */ + char *chinese; /* ¤¤¤å½Ķ */ + char *part1_msg; /* ¤¶µü */ + char *part2_msg; /* °Ê§@ */ +}; + + +static ChatAction party_data[] = +{ + {"aluba", "ªü¾|¤Ú", "§â", "¬[¤W¬W¤lªü¾|¤Ú!!"}, + {"aodre", "´º¥õ", "¹ï", "ªº´º¥õ¦³¦p·Ê·Ê¦¿¤ô,³sºø¤£µ´¡K¡K"}, + {"bearhug", "¼ö¾Ö", "¼ö±¡ªº¾Ö©ê", ""}, + {"blade", "¤@¤M", "¤@¤M±Òµ{§â", "°e¤W¦è¤Ñ"}, + {"bless", "¯¬ºÖ", "¯¬ºÖ", "¤ß·Q¨Æ¦¨"}, + {"board", "¥D¾÷ªO", "§â", "§ì¥h¸÷¥D¾÷ªO"}, + {"bokan", "®ð¥\\", "Âù´x·L¦X¡A»W¶Õ«Ýµo¡K¡K¬ðµM¶¡¡A¹q¥ú¥E²{¡A¹ï", "¨Ï¥X¤F¢Ðo--¢Ùan¡I"}, + {"bow", "Áù°`", "²¦°`²¦·qªº¦V", "Áù°`"}, + {"box", "¹õ¤§¤º", "¶}©l½üÂ\\¦¡²¾¦ì¡A¹ï", "§@¨xŦ§ðÀ»"}, + {"boy", "¥©³Áç", "±qI«á®³¥X¤F¥©³Áç¡A§â", "ºV©ü¤F"}, + {"bye", "ÙTÙT", "¦V", "»¡ÙTÙT!!"}, + {"call", "©I³ê", "¤jÁnªº©I³ê,°Ú~~", "°Ú~~~§A¦bþ¸Ì°Ú°Ú°Ú°Ú~~~~"}, + {"caress", "»´¼¾", "»´»´ªº¼¾ºNµÛ", ""}, + {"clap", "¹ª´x", "¦V", "¼ö¯P¹ª´x"}, + {"claw", "§ì§ì", "±q¿ß«}¼Ö¶éɤF°¦¿ß¤ö¡A§â", "§ì±o¦º¥h¬¡¨Ó"}, + {"comfort", "¦w¼¢", "·Å¨¥¦w¼¢", ""}, + {"cong", "®¥³ß", "±qI«á®³¥X¤F©Ô¬¶¡AËé¡IËé¡I®¥³ß", ""}, + {"cpr", "¤f¹ï¤f", "¹ïµÛ", "°µ¤f¹ï¤f¤H¤u©I§l"}, + {"cringe", "¤^¼¦", "¦V", "¨õ°`©}½¥¡A·n§À¤^¼¦"}, + {"cry", "¤jú", "¦V", "Àz°Þ¤jú"}, + {"dance", "¸õ»R", "©Ô¤F", "ªº¤â½¡½¡°_»R" }, + {"destroy", "·´·À", "²½°_¤F¡y·¥¤j·´·À©G¤å¡z¡AÅF¦V", ""}, + {"dogleg", "ª¯»L", "¹ï", "ª¯»L"}, + {"drivel", "¬y¤f¤ô", "¹ïµÛ", "¬y¤f¤ô"}, + {"envy", "¸r¼}", "¦V", "¬yÅS¥X¸r¼}ªº²´¥ú"}, + {"eye", "°e¬îªi", "¹ï", "ÀW°e¬îªi"}, + {"fire", "¾R°Ý", "®³µÛ¤õ¬õªºÅK´Î¨«¦V", ""}, + {"forgive", "ì½Ì", "±µ¨ü¹Dºp¡Aì½Ì¤F", ""}, + {"french", "ªk¦¡§k", "§â¦ÞÀY¦ù¨ì", "³ïÄV¸Ì¡ã¡ã¡ã«z¡I¤@Ó®öº©ªºªk°ê¤ó²`§k"}, + {"giggle", "¶Ì¯º", "¹ïµÛ", "¶Ì¶Ìªº§b¯º"}, + {"glue", "¸É¤ß", "¥Î¤T¬í½¦¡A§â", "ªº¤ßÂH¤F°_¨Ó"}, + {"goodbye", "§i§O", "²\\²´¨L¨Lªº¦V", "§i§O"}, + {"grin", "¦l¯º", "¹ï", "ÅS¥X¨¸´cªº¯º®e"}, + {"growl", "©Hý", "¹ï", "©Hý¤£¤w"}, + {"hand", "´¤¤â", "¸ò", "´¤¤â"}, + {"hide", "¸ú", "¸ú¦b", "I«á"}, + {"hospitl", "°eÂå°|", "§â", "°e¶iÂå°|"}, + {"hug", "¾Ö©ê", "»´»´¦a¾Ö©ê", ""}, + {"hrk", "ª@Às®±", "¨IäF¨§Î¡A¶×»E¤F¤º«l¡A¹ï", "¨Ï¥X¤F¤@°O¢Öo--¢àyu--¢Ùan¡I¡I¡I"}, + {"jab", "ÂW¤H", "·Å¬XªºÂWµÛ", ""}, + {"judo", "¹LªÓºL", "§ì¦í¤F", "ªº¦çÃÌ¡AÂਡK¡K°Ú¡A¬O¤@°O¹LªÓºL¡I"}, + {"kickout", "½ð", "¥Î¤j¸}§â", "½ð¨ì¤s¤U¥h¤F"}, + {"kick", "½ð¤H", "§â", "½ðªº¦º¥h¬¡¨Ó"}, + {"kiss", "»´§k", "»´§k", "ªºÁyÀU"}, + {"laugh", "¼J¯º", "¤jÁn¼J¯º", ""}, + {"levis", "µ¹§Ú", "»¡¡Gµ¹§Ú", "¡I¨ä¾l§K½Í¡I"}, + {"lick", "»Q", "¨g»Q", ""}, + {"lobster", "À£¨î", "¬I®i°f½¼§Î©T©w¡A§â", "À£¨î¦b¦aªO¤W"}, + {"love", "ªí¥Õ", "¹ï", "²`±¡ªºªí¥Õ"}, + {"marry", "¨D±B", "±·µÛ¤E¦Ê¤E¤Q¤E¦·ª´ºÀ¦V", "¨D±B"}, + {"no", "¤£n°Ú", "«÷©R¹ïµÛ", "·nÀY~~~~¤£n°Ú~~~~"}, + {"nod", "ÂIÀY", "¦V", "ÂIÀYºÙ¬O"}, + {"nudge", "³»¨{¤l", "¥Î¤â¨y³»", "ªºªÎ¨{¤l"}, + {"pad", "©çªÓ»H", "»´©ç", "ªºªÓ»H"}, + {"pettish", "¼»¼b", "¸ò", "ÜÝÁnÜÝ®ð¦a¼»¼b"}, + {"pili", "ÅRÆE", "¨Ï¥X §g¤l· ¤Ñ¦a®Ú ¯ëYÄb ¤T¦¡¦X¤@¥´¦V", "~~~~~~"}, + {"pinch", "À¾¤H", "¥Î¤Oªº§â", "À¾ªº¶Â«C"}, + {"roll", "¥´ºu", "©ñ¥X¦hº¸³Oªºµ¼Ö,", "¦b¦a¤Wºu¨Óºu¥h"}, + {"protect", "«OÅ@", "«OÅ@µÛ", ""}, + {"pull", "©Ô", "¦º©R¦a©Ô¦í", "¤£©ñ"}, + {"punch", "´~¤H", "¬½¬½´~¤F", "¤@¹y"}, + {"rascal", "A¿à", "¸ò", "A¿à"}, + {"recline", "¤JÃh", "Æp¨ì", "ªºÃh¸ÌºÎµÛ¤F¡K¡K"}, + {"respond", "t³d", "¦w¼¢", "»¡¡G¡y¤£nú¡A§Ú·|t³dªº¡K¡K¡z"}, + {"shrug", "ÁqªÓ", "µL©`¦a¦V", "Áq¤FÁqªÓ»H"}, + {"sigh", "¼Û®ð", "¹ï", "¼Û¤F¤@¤f®ð"}, + {"slap", "¥´¦Õ¥ú", "°Ô°Ôªº¤Ú¤F", "¤@¹y¦Õ¥ú"}, + {"smooch", "¾Ö§k", "¾Ö§kµÛ", ""}, + {"snicker", "Åѯº", "¼K¼K¼K..ªº¹ï", "Åѯº"}, + {"sniff", "¤£®h", "¹ï", "¶á¤§¥H»ó"}, + {"spank", "¥´§¾§¾", "¥Î¤Ú´x¥´", "ªºÁv³¡"}, + {"squeeze", "ºò¾Ö", "ºòºò¦a¾Ö©êµÛ", ""}, + {"sysop", "¥l³ê", "¥s¥X¤F§å½ð½ð¡A§â", "½ò«ó¤F¡I"}, + {"thank", "·PÁÂ", "¦V", "·PÁ±o¤Åé§ë¦a"}, + {"tickle", "·kÄo", "©B¼T!©B¼T!·k", "ªºÄo"}, + {"wake", "·n¿ô", "»´»´¦a§â", "·n¿ô"}, + {"wave", "´§¤â", "¹ïµÛ", "«÷©Rªº·n¤â"}, + {"welcome", "Åwªï", "Åwªï", "¶i¨Ó¤K¨ö¤@¤U"}, + {"what", "¤°»ò", "»¡¡G¡y", "ù¤½½M±K«zÃ÷Å¥¬Y?¡H?¡S?¡z"}, + {"whip", "Ã@¤l", "¤â¤W®³µÛÄúÀë¡A¥ÎÃ@¤lµh¥´", ""}, + {"wink", "¯w²´", "¹ï", "¯«¯µªº¯w¯w²´·ú"}, + {"zap", "²r§ð", "¹ï", "ºÆ¨gªº§ðÀ»"}, + {NULL, NULL, NULL, NULL} +}; + +static int +chicken_action(cu, cmd, party) + ChatUser *cu; + char *cmd; + char *party; +{ +return 0; +} +static int +party_action(cu, cmd, party) + ChatUser *cu; + char *cmd; + char *party; +{ + ChatAction *cap; + char *verb; + + for (cap = party_data; (verb = cap->verb); cap++) + { + MYDOG; + + if (str_equal(cmd, verb)) + { + if (*party == '\0') + { + party = "¤j®a"; + } + else + { + ChatUser *xuser; + + xuser = fuzzy_cuser_by_chatid(party); + if (xuser == NULL) + { /* Thor.0724: ¥Î userid¤]¹À³q */ + xuser = cuser_by_userid(party); + } + + if (xuser == NULL) + { + sprintf(chatbuf, msg_no_such_id, party); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return 0; + } + else if (xuser == FUZZY_USER) + { + sprintf(chatbuf, "¡° ½Ð«ü©ú²á¤Ñ¥N¸¹"); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return 0; + } + else if (cu->room != xuser->room || CLOAK(xuser)) + { + sprintf(chatbuf, msg_not_here, party); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + return 0; + } + else + { + party = xuser->chatid; + } + } + sprintf(chatbuf, "[1;32m%s [31m%s[33m %s [31m%s[m", + cu->chatid, cap->part1_msg, party, cap->part2_msg); + send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE); + return 0; /* Thor: cu->room ¬O§_¬° NULL? */ + } + } + return 1; +} + + +/* --------------------------------------------- */ +/* MUD-like social commands : speak */ +/* --------------------------------------------- */ + + +static ChatAction speak_data[] = +{ + + { + "ask", "¸ß°Ý", "°Ý", NULL + }, + { + "chant", "ºq¹|", "°ªÁnºq¹|", NULL + }, + { + "cheer", "³Üªö", "³Üªö", NULL + }, + { + "chuckle", "»´¯º", "»´¯º", NULL + }, + { + "curse", "·t·F", "·t·F", NULL + }, + /* {"curse", "©G½|", NULL}, */ + { + "demand", "n¨D", "n¨D", NULL + }, + { + "frown", "½K¬ÜÀY", "ÂÙ¬Ü", NULL + }, + { + "groan", "©D§u", "©D§u", NULL + }, + { + "grumble", "µo¨cÄÌ", "µo¨cÄÌ", NULL + }, + { + "guitar", "¼u°Û", "Ãä¼uµÛ¦N¥L¡AÃä°ÛµÛ", NULL + }, + /* {"helpme", "©I±Ï","¤jÁn©I±Ï",NULL}, */ + { + "hum", "³ä³ä", "³ä³ä¦Û»y", NULL + }, + { + "moan", "«è¹Ä", "«è¹Ä", NULL + }, + { + "notice", "±j½Õ", "±j½Õ", NULL + }, + { + "order", "©R¥O", "©R¥O", NULL + }, + { + "ponder", "¨H«ä", "¨H«ä", NULL + }, + { + "pout", "äþ¼L", "äþµÛ¼L»¡", NULL + }, + { + "pray", "¬èë", "¬èë", NULL + }, + { + "request", "Àµ¨D", "Àµ¨D", NULL + }, + { + "shout", "¤j½|", "¤j½|", NULL + }, + { + "sing", "°Ûºq", "°Ûºq", NULL + }, + { + "smile", "·L¯º", "·L¯º", NULL + }, + { + "smirk", "°²¯º", "°²¯º", NULL + }, + { + "swear", "µo»}", "µo»}", NULL + }, + { + "tease", "¼J¯º", "¼J¯º", NULL + }, + { + "whimper", "¶ã«|", "¶ã«|ªº»¡", NULL + }, + { + "yawn", "«¢¤í", "Ã䥴«¢¤íÃ仡", NULL + }, + { + "yell", "¤j³Û", "¤j³Û", NULL + }, + { + NULL, NULL, NULL, NULL + } +}; + + +static int +speak_action(cu, cmd, msg) + ChatUser *cu; + char *cmd; + char *msg; +{ + ChatAction *cap; + char *verb; + + for (cap = speak_data; (verb = cap->verb); cap++) + { + MYDOG; + + if (str_equal(cmd, verb)) + { + sprintf(chatbuf, "[1;32m%s [31m%s¡G[33m %s[m", + cu->chatid, cap->part1_msg, msg); + send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE); + return 0; /* Thor: cu->room ¬O§_¬° NULL? */ + } + } + return 1; +} + + +/* -------------------------------------------- */ +/* MUD-like social commands : condition */ +/* -------------------------------------------- */ + + +static ChatAction condition_data[] = +{ + { + "applaud", "©ç¤â", "°Ô°Ô°Ô°Ô°Ô°Ô°Ô....", NULL + }, + { + "ayo", "üËç³Þ", "üËç³Þ~~~", NULL + }, + { + "back", "§¤¦^¨Ó", "¦^¨Ó§¤¥¿Ä~Äò¾Ä¾Ô", NULL + }, + { + "blood", "¦b¦å¤¤", "˦b¦åªy¤§¤¤", NULL + }, + { + "blush", "Áy¬õ", "Áy³£¬õ¤F", NULL + }, + { + "broke", "¤ß¸H", "ªº¤ß¯}¸H¦¨¤@¤ù¤@¤ùªº", NULL + }, /* Thor.0731:À³Æ[²³n¨D */ + /* {"bokan", "Bo Kan! Bo Kan!", NULL}, */ + { + "careles", "¨S¤H²z", "¶ã¡ã¡ã³£¨S¦³¤H²z§Ú :~~~~", NULL + }, + { + "chew", "¶ß¥Ê¤l", "«Ü±y¶¢ªº¶ß°_¥Ê¤l¨Ó¤F", NULL + }, + { + "climb", "ª¦¤s", "¦Û¤vºCºCª¦¤W¤s¨Ó¡K¡K", NULL + }, + { + "cold", "·P«_¤F", "·P«_¤F,¶ý¶ý¤£Åý§Ú¥X¥hª± :~~~(", NULL + }, + { + "cough", "«y¹Â", "«y¤F´XÁn", NULL + }, + { + "die", "¼ÉÀÅ", "·í³õ¼ÉÀÅ", NULL + }, + { + "faint", "©üË", "·í³õ©üË", NULL + }, + { + "flop", "»¿¼¥Ö", "½ò¨ì»¿¼¥Ö... ·ÆË¡I", NULL + }, + { + "fly", "ÄÆÄƵM", "ÄÆÄƵM", NULL + }, + { + "frown", "ÂÙ¬Ü", "ÂÙ¬Ü", NULL + }, + { + "gold", "®³ª÷µP", "°ÛµÛ¡G¡yª÷£|£±£½ª÷£|£±£½ ¥X°ê¤ñÁÉ! ±o«ax¡A®³ª÷µP¡A¥úºa˾H¨Ó¡I¡z", NULL + }, + { + "gulu", "¨{¤l¾j", "ªº¨{¤lµo¥X©BÂP~~~©BÂP~~~ªºÁnµ", NULL + }, + { + "haha", "«z«¢«¢", "«z«¢«¢«¢.....^o^", NULL + }, + /* {"haha", "¤j¯º","«z«¢«¢«¢«¢«¢«¢«¢«¢~~~~!!!!!", NULL}, */ + { + "helpme", "¨D±Ï", "¤j³Û~~~±Ï©R°Ú~~~~", NULL + }, + { + "hoho", "¨þ¨þ¯º", "¨þ¨þ¨þ¯ºÓ¤£°±", NULL + }, + { + "happy", "°ª¿³", "°ª¿³±o¦b¦a¤W¥´ºu", NULL + }, + /* {"happy", "°ª¿³", "¢ç¢Ï¡I *^_^*", NULL}, */ + /* {"happy", "", "r-o-O-m....Å¥¤F¯u²n¡I", NULL}, */ + /* {"hurricane", "¢Ö¢÷---¢à£B¢ý--¢Ù¢é¢ö¡I¡I¡I", NULL}, */ + { + "idle", "§b¦í¤F", "§b¦í¤F", NULL + }, + { + "jacky", "®Ì®Ì", "µl¤l¯ëªº®Ì¨Ó®Ì¥h", NULL + }, + +#if 0 + /* Thor.0729: ¤£ª¾¨ä·N */ + { + "lag", "ºô¸ôºC", "lllllllaaaaaaaaaaaagggggggggggggg.................", NULL + }, +#endif + + { + "luck", "©¯¹B", "«z¡IºÖ®ð°Õ¡I", NULL + }, + { + "macarn", "¤@ºØ»R", "¶}©l¸õ°_¤F¢Ûa¢Ña¢àe¢Üa¡ã¡ã¡ã¡ã", NULL + }, + { + "miou", "ØpØp", "ØpØp¤f]¤f]¡ã¡ã¡ã¡ã¡ã", NULL + }, + { + "mouth", "«ó¼L", "«ó¼L¤¤!!", NULL + }, + { + "nani", "«ç»ò·|", "¡G©`£®°Ú®º??", NULL + }, + { + "nose", "¬y»ó¦å", "¬y»ó¦å", NULL + }, + { + "puke", "¹Ã¦R", "¹Ã¦R¤¤", NULL + }, + /* {"puke", "¯uäú¤ß¡A§ÚÅ¥¤F³£·Q¦R", NULL}, */ + { + "rest", "¥ð®§", "¥ð®§¤¤¡A½Ð¤Å¥´ÂZ", NULL + }, + { + "reverse", "½¨{", "½¨{", NULL + }, + { + "room", "¶}©Ð¶¡", "r-o-O-m-r-O-¢Ý-Mmm-rR¢à........", NULL + }, + { + "shake", "·nÀY", "·n¤F·nÀY", NULL + }, + { + "sleep", "ºÎµÛ", "w¦bÁä½L¤WºÎµÛ¤F¡A¤f¤ô¬y¶iÁä½L¡A³y¦¨·í¾÷¡I", NULL + }, + /* {"sleep", "Zzzzzzzzzz¡A¯uµL²á¡A³£§ÖºÎµÛ¤F", NULL}, */ + { + "so", "´NÂæ¤l", "´NÂæ¤l!!", NULL + }, + { + "sorry", "¹Dºp", "¶ã°Ú!!§Ú¹ï¤£°_¤j®a,§Ú¹ï¤£°_°ê®aªÀ·|~~~~~~¶ã°Ú~~~~~", NULL + }, + { + "story", "Á¿¥j", "¶}©lÁ¿¥j¤F", NULL + }, + { + "strut", "·nÂ\\¨«", "¤j·n¤jÂ\\¦a¨«", NULL + }, + { + "suicide", "¦Û±þ", "¦Û±þ", NULL + }, + { + "tea", "ªw¯ù", "ªw¤F³ý¦n¯ù", NULL + }, + { + "think", "«ä¦Ò", "¬nµÛÀY·Q¤F¤@¤U", NULL + }, + { + "tongue", "¦R¦Þ", "¦R¤F¦R¦ÞÀY", NULL + }, + { + "wall", "¼²Àð", "¶]¥h¼²Àð", NULL + }, + { + "wawa", "«z«z", "«z«z«z~~~~~!!!!! ~~~>_<~~~", NULL + }, + /* {"wawa","«z«z«z......>_<",NULL}, */ + { + "www", "¨L¨L", "¨L¨L¨L!!!", NULL + }, + { + "zzz", "¥´©I", "©IÂP~~~~ZZzZz£C¢èZZzzZzzzZZ...", NULL + }, + + { + NULL, NULL, NULL, NULL + } +}; + + +static int +condition_action(cu, cmd) + ChatUser *cu; + char *cmd; +{ + ChatAction *cap; + char *verb; + + for (cap = condition_data; (verb = cap->verb); cap++) + { + MYDOG; + + if (str_equal(cmd, verb)) + { + sprintf(chatbuf, "[1;32m%s [31m%s[m", + cu->chatid, cap->part1_msg); + send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE); + return 1; /* Thor: cu->room ¬O§_¬° NULL? */ + } + } + return 0; +} + + +/* --------------------------------------------- */ +/* MUD-like social commands : help */ +/* --------------------------------------------- */ + + +static char *dscrb[] = +{ + "[1;37m¡i Verb + Nick¡G °Êµü + ¹ï¤è¦W¦r ¡j[36m ¨Ò¡G//kick piggy[m", + "[1;37m¡i Verb + Message¡G°Êµü + n»¡ªº¸Ü ¡j[36m ¨Ò¡G//sing ¤Ñ¤Ñ¤ÑÂÅ[m", + "[1;37m¡i Verb¡G°Êµü ¡j ¡ô¡õ¡G¸ܫ´£[m", NULL +}; +ChatAction *catbl[] = +{ + party_data, speak_data, condition_data, NULL +}; + +static void +chat_partyinfo(cu, msg) + ChatUser *cu; + char *msg; +{ + if (!common_client_command) + return; /* only allow common client to retrieve it */ + + sprintf(chatbuf, "3 °Ê§@ ¥æ½Í ª¬ºA"); + send_to_user(cu, chatbuf, 0, MSG_PARTYINFO); +} + +static void +chat_party(cu, msg) + ChatUser *cu; + char *msg; +{ + int kind, i; + ChatAction *cap; + + if (!common_client_command) + return; + + kind = atoi(nextword(&msg)); + if (kind < 0 || kind > 2) + return; + + sprintf(chatbuf, "%d %s", kind, kind == 2 ? "I" : ""); + + /* Xshadow: ¥u¦³ condition ¤~¬O immediate mode */ + send_to_user(cu, chatbuf, 0, MSG_PARTYLISTSTART); + + cap = catbl[kind]; + for (i = 0; cap[i].verb; i++) + { + sprintf(chatbuf, "%-10s %-20s", cap[i].verb, cap[i].chinese); + /* for (j=0;j<1000000;j++); */ + send_to_user(cu, chatbuf, 0, MSG_PARTYLIST); + } + + sprintf(chatbuf, "%d", kind); + send_to_user(cu, chatbuf, 0, MSG_PARTYLISTEND); +} + + +#define SCREEN_WIDTH 80 +#define MAX_VERB_LEN 8 +#define VERB_NO 10 + +static void +view_action_verb(cu, cmd) /* Thor.0726: ·s¥[°Êµü¤ÀÃþÅã¥Ü */ + register ChatUser *cu; + char cmd; +{ + register int i; + register char *p, *q, *data, *expn; + register ChatAction *cap; + + send_to_user(cu, "/c", 0, MSG_CLRSCR); + + data = chatbuf; + + if (cmd < '1' || cmd > '3') + { /* Thor.0726: ¼g±o¤£¦n, ·Q¿ìªk§ï¶i... */ + for (i = 0; (p = dscrb[i]); i++) + { + sprintf(data, " [//]help %d - MUD-like ªÀ¥æ°Êµü ²Ä %d Ãþ", i + 1, i + 1); + MYDOG; + send_to_user(cu, data, 0, MSG_MESSAGE); + send_to_user(cu, p, 0, MSG_MESSAGE); + send_to_user(cu, " ", 0, MSG_MESSAGE); /* Thor.0726: ´«¦æ, »Ýn " " + * ¶Ü? */ + } + } + else + { + i = cmd - '1'; + + send_to_user(cu, dscrb[i], 0, MSG_MESSAGE); + + expn = chatbuf + 100; /* Thor.0726: À³¸Ó¤£·|overlap§a? */ + + *data = '\0'; + *expn = '\0'; + + cap = catbl[i]; + + for (i = 0; (p = cap[i].verb); i++) + { + MYDOG; + q = cap[i].chinese; + + strcat(data, p); + strcat(expn, q); + + if (((i + 1) % VERB_NO) == 0) + { + send_to_user(cu, data, 0, MSG_MESSAGE); + send_to_user(cu, expn, 0, MSG_MESSAGE); /* Thor.0726: Åã¥Ü¤¤¤åµù¸Ñ */ + *data = '\0'; + *expn = '\0'; + } + else + { + strncat(data, " ", MAX_VERB_LEN - strlen(p)); + strncat(expn, " ", MAX_VERB_LEN - strlen(q)); + } + } + if (i % VERB_NO) + { + send_to_user(cu, data, 0, MSG_MESSAGE); + send_to_user(cu, expn, 0, MSG_MESSAGE); /* Thor.0726: Åã¥Ü¤¤¤åµù¸Ñ */ + } + } + /* send_to_user(cu, " ",0); *//* Thor.0726: ´«¦æ, »Ýn " " ¶Ü? */ +} + +void view_chicken_help(cu) /* Ptt: °«Âûµ{¦¡ ªºhelp */ + register ChatUser *cu; +{ + +} + +/* ----------------------------------------------------- */ +/* chat user service routines */ +/* ----------------------------------------------------- */ + + +static ChatCmd chatcmdlist[] = +{ + {"act", chat_act, 0}, + {"bye", chat_goodbye, 0}, + {"chatroom", chat_chatroom, 1}, /* Xshadow: for common client */ + {"clear", chat_clear, 0}, + {"cloak", chat_cloak, 2}, + {"date", chat_date, 0}, + {"flags", chat_setroom, 0}, + {"help", chat_help, 0}, + {"ignore", chat_ignore, 1}, + {"invite", chat_invite, 0}, + {"join", chat_join, 0}, + {"kick", chat_kick, 1}, + {"msg", chat_private, 0}, + {"nick", chat_nick, 0}, + {"operator", chat_makeop, 0}, + {"party", chat_party, 1}, /* Xshadow: party data for common client */ + {"partyinfo", chat_partyinfo, 1}, /* Xshadow: party info for common + * client */ + + {"query", chat_query, 0}, + + {"room", chat_list_rooms, 0}, + {"unignore", chat_unignore, 1}, + {"whoin", chat_list_by_room, 1}, + {"wall", chat_broadcast, 2}, + + {"who", chat_map_chatids_thisroom, 0}, + {"list", chat_list_users, 0}, + {"topic", chat_topic, 1}, + {"version", chat_version, 1}, + + {NULL, NULL, 0} +}; + +/* Thor: 0 ¤£¥Î exact, 1 n exactly equal, 2 ¯µ±K«ü¥O */ + + +static int +command_execute(cu) + ChatUser *cu; +{ + char *cmd, *msg; + ChatCmd *cmdrec; + int match, ch; + + msg = cu->ibuf; + match = *msg; + + /* Validation routine */ + + if (cu->room == NULL) + { + /* MUST give special /! or /-! command if not in the room yet */ + + if (match == '/' && ((ch = msg[1]) == '!' || (ch == '-' && msg[2] == '!'))) + { + cu->clitype = (ch == '-') ? 1 : 0; + return (login_user(cu, msg + 2 + cu->clitype)); + } + else + return -1; + } + + /* If not a /-command, it goes to the room. */ + + if (match != '/') + { + if (match) + { + char buf[16]; + + sprintf(buf, "%s:", cu->chatid); + sprintf(chatbuf, "%-10s%s", buf, msg); + if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨³N */ + send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE); + /* Thor: n check cu->room NULL¶Ü? */ + + } + return 0; + } + + msg++; + cmd = nextword(&msg); + match = 0; + + if (*cmd == '/') + { + cmd++; + if (!*cmd || str_equal(cmd, "help")) + { + /* Thor.0726: °Êµü¤ÀÃþ */ + cmd = nextword(&msg); + view_action_verb(cu, *cmd); + match = 1; + } + else if (party_action(cu, cmd, msg) == 0) + match = 1; + else if (speak_action(cu, cmd, msg) == 0) + match = 1; + else + match = condition_action(cu, cmd); + } + else if(*cmd == '.') + { + cmd++; + if (!*cmd || str_equal(cmd, "help")) + { + view_chicken_help(cu); + match = 1; + } + else match = chicken_action(cu, cmd, msg); + } + else + { + char *str; + + common_client_command = 0; + if((*cmd == '-')) { + if(cu->clitype) { + cmd++; /* Xshadow: «ü¥O±q¤U¤@Ó¦r¤¸¤~¶}©l */ + common_client_command = 1; + } + } + for(cmdrec = chatcmdlist; (str = cmdrec->cmdstr); cmdrec++) + { + MYDOG; + + switch (cmdrec->exact) + { + case 1: /* exactly equal */ + match = str_equal(cmd, str); + break; + case 2: /* Thor: secret command */ + if (CHATSYSOP(cu)) + match = str_equal(cmd, str); + break; + default: /* not necessary equal */ + match = str_match(cmd, str) >= 0; + break; + } + + if (match) + { + cmdrec->cmdfunc(cu, msg); + break; + } + } + } + + if (!match) + { + sprintf(chatbuf, "¡» «ü¥O¿ù»~¡G/%s", cmd); + send_to_user(cu, chatbuf, 0, MSG_MESSAGE); + } + return 0; +} + + +/* ----------------------------------------------------- */ +/* serve chat_user's connection */ +/* ----------------------------------------------------- */ + + +static int +cuser_serve(cu) + ChatUser *cu; +{ + register int ch, len, isize; + register char *str, *cmd; + static char buf[80]; + + str = buf; + len = recv(cu->sock, str, sizeof(buf) - 1, 0); + if (len <= 0) + { + /* disconnected */ + + exit_room(cu, EXIT_LOSTCONN, (char *) NULL); + return -1; + } + +#if 0 + /* Xshadow: ±N°e¹Fªº¸ê®Æ©¾¹ê¬ö¿ý¤U¨Ó */ + memcpy(logbuf, buf, sizeof(buf)); + for (ch = 0; ch < sizeof(buf); ch++) + if (!logbuf[ch]) + logbuf[ch] = '$'; + + logbuf[len + 1] = '\0'; + logit("recv: ", logbuf); +#endif + +#if 0 + logit(cu->userid, str); +#endif + + isize = cu->isize; + cmd = cu->ibuf + isize; + while (len--) + { + MYDOG; + + ch = *str++; + + if (ch == '\r' || !ch) + continue; + if (ch == '\n') + { + *cmd = '\0'; + + isize = 0; + cmd = cu->ibuf; + + if (command_execute(cu) < 0) + return -1; + + continue; + } + if (isize < 79) + { + *cmd++ = ch; + isize++; + } + } + cu->isize = isize; + return 0; +} + + +/* ----------------------------------------------------- */ +/* chatroom server core routines */ +/* ----------------------------------------------------- */ + +static int +start_daemon() +{ + int fd, value; + char buf[80]; + struct sockaddr_in fsin; + struct linger ld; + struct rlimit limit; + time_t dummy; + struct tm *dummy_time; + + /* + * More idiot speed-hacking --- the first time conversion makes the C + * library open the files containing the locale definition and time zone. + * If this hasn't happened in the parent process, it happens in the + * children, once per connection --- and it does add up. + */ + + time(&dummy); + dummy_time = gmtime(&dummy); + dummy_time = localtime(&dummy); + strftime(buf, 80, "%d/%b/%Y:%H:%M:%S", dummy_time); + + /* --------------------------------------------------- */ + /* speed-hacking DNS resolve */ + /* --------------------------------------------------- */ + + gethostname(buf, sizeof(buf)); + + /* Thor: ¸U¤@server©|¥¼±µ¨üconnection, ´N¦^¥hªº¸Ü, client ²Ä¤@¦¸·|¶i¤J¥¢±Ñ */ + /* ©Ò¥H²¾¦Ü listen «á */ + + /* --------------------------------------------------- */ + /* detach daemon process */ + /* --------------------------------------------------- */ + + close(0); + close(1); + close(2); + + if (fork()) + exit(0); + + chdir(BBSHOME); + + setsid(); + + /* --------------------------------------------------- */ + /* adjust the resource limit */ + /* --------------------------------------------------- */ + + getrlimit(RLIMIT_NOFILE, &limit); + limit.rlim_cur = limit.rlim_max; + setrlimit(RLIMIT_NOFILE, &limit); + +#if 0 + while (fd) + { + close(--fd); + } + + value = getpid(); + setpgrp(0, value); + + if ((fd = open("/dev/tty", O_RDWR)) >= 0) + { + ioctl(fd, TIOCNOTTY, 0); /* Thor : ¬°¤°»òÁÙn¥Î tty? */ + close(fd); + } +#endif + + fd = open(CHAT_PIDFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd >= 0) + { + /* sprintf(buf, "%5d\n", value); */ + sprintf(buf, "%5d\n", getpid()); + write(fd, buf, 6); + close(fd); + } + +#if 0 + /* ------------------------------ */ + /* trap signals */ + /* ------------------------------ */ + + for (fd = 1; fd < NSIG; fd++) + { + + signal(fd, SIG_IGN); + } +#endif + + fd = socket(PF_INET, SOCK_STREAM, 0); + +#if 0 + value = fcntl(fd, F_GETFL, 0); + fcntl(fd, F_SETFL, value | O_NDELAY); +#endif + + value = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(value)); + +#if 0 + setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &value, sizeof(value)); + + value = 81920; + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &value, sizeof(value)); +#endif + + ld.l_onoff = ld.l_linger = 0; + setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld)); + + memset((char *) &fsin, 0, sizeof(fsin)); + fsin.sin_family = AF_INET; + fsin.sin_port = htons(NEW_CHATPORT); + fsin.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(fd, (struct sockaddr *) & fsin, sizeof(fsin)) < 0) + exit(1); + + listen(fd, SOCK_QLEN); + + return fd; +} + + +static void +free_resource(fd) + int fd; +{ + static int loop = 0; + register ChatUser *user; + register int sock, num; + + num = 0; + for (user = mainuser; user; user = user->unext) + { + MYDOG; + + num++; + sock = user->sock; + if (fd < sock) + fd = sock; + } + + sprintf(chatbuf, "%d, %d user (%d -> %d)", ++loop, num, maxfds, fd); + logit("LOOP", chatbuf); + + maxfds = fd + 1; +} + + +#ifdef SERVER_USAGE +static void +server_usage() +{ + struct rusage ru; + char buf[2048]; + + if (getrusage(RUSAGE_SELF, &ru)) + return; + + sprintf(buf, "\n[Server Usage]\n\n" + "user time: %.6f\n" + "system time: %.6f\n" + "maximum resident set size: %lu P\n" + "integral resident set size: %lu\n" + "page faults not requiring physical I/O: %ld\n" + "page faults requiring physical I/O: %ld\n" + "swaps: %ld\n" + "block input operations: %ld\n" + "block output operations: %ld\n" + "messages sent: %ld\n" + "messages received: %ld\n" + "signals received: %ld\n" + "voluntary context switches: %ld\n" + "involuntary context switches: %ld\n" + "gline: %d\n\n", + + (double) ru.ru_utime.tv_sec + (double) ru.ru_utime.tv_usec / 1000000.0, + (double) ru.ru_stime.tv_sec + (double) ru.ru_stime.tv_usec / 1000000.0, + ru.ru_maxrss, + ru.ru_idrss, + ru.ru_minflt, + ru.ru_majflt, + ru.ru_nswap, + ru.ru_inblock, + ru.ru_oublock, + ru.ru_msgsnd, + ru.ru_msgrcv, + ru.ru_nsignals, + ru.ru_nvcsw, + ru.ru_nivcsw, + gline); + + write(flog, buf, strlen(buf)); +} +#endif + + +static void +abort_server() +{ + log_close(); + exit(1); +} + + +static void +reaper() +{ + int state; + + while (waitpid(-1, &state, WNOHANG | WUNTRACED) > 0) + { + MYDOG; + } +} + + +int +main() +{ + register int msock, csock, nfds; + register ChatUser *cu; + register fd_set *rptr, *xptr; + fd_set rset, xset; + struct timeval tv; + time_t uptime, tmaintain; + + msock = start_daemon(); + + setgid(BBSGID); + setuid(BBSUID); + + log_init(); + + signal(SIGBUS, SIG_IGN); + signal(SIGSEGV, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGURG, SIG_IGN); + + signal(SIGCHLD, reaper); + signal(SIGTERM, abort_server); + +#ifdef SERVER_USAGE + signal(SIGPROF, server_usage); +#endif + + /* ----------------------------- */ + /* init variable : rooms & users */ + /* ----------------------------- */ + + mainuser = NULL; + memset(&mainroom, 0, sizeof(mainroom)); + strcpy(mainroom.name, MAIN_NAME); + strcpy(mainroom.topic, MAIN_TOPIC); + + /* ----------------------------------- */ + /* main loop */ + /* ----------------------------------- */ + +#if 0 + /* Thor: ¦blisten «á¤~¦^client, ¨C¦¸¶i¨Ó´N·|¦¨¥\ */ + if (fork()) + exit(0); +#endif + + FD_ZERO(&mainfds); + FD_SET(msock, &mainfds); + rptr = &rset; + xptr = &xset; + maxfds = msock + 1; + + tmaintain = time(0) + CHAT_INTERVAL; + + for (;;) + { + uptime = time(0); + if (tmaintain < uptime) + { + tmaintain = uptime + CHAT_INTERVAL; + + /* client/server ª©¥»§Q¥Î ping-pong ¤èªk§PÂ_ user ¬O¤£¬OÁÙ¬¡µÛ */ + /* ¦pªG client ¤w¸gµ²§ô¤F¡A´NÄÀ©ñ¨ä resource */ + + free_resource(msock); + } + + MYDOG; + + memcpy(rptr, &mainfds, sizeof(fd_set)); + memcpy(xptr, &mainfds, sizeof(fd_set)); + + /* Thor: for future reservation bug */ + + tv.tv_sec = CHAT_INTERVAL; + tv.tv_usec = 0; + + MYDOG; + + nfds = select(maxfds, rptr, NULL, xptr, &tv); + + MYDOG; + /* free idle user & chatroom's resource when no traffic */ + + if (nfds == 0) + { + continue; + } + + /* check error condition */ + + if (nfds < 0) + { + csock = errno; + continue; + } + + /* accept new connection */ + + if (FD_ISSET(msock, rptr)) + { + for (;;) + { + MYDOG; /* Thor: check for endless */ + csock = accept(msock, NULL, NULL); + + if (csock >= 0) + { + MYDOG; + if((cu = (ChatUser *) malloc(sizeof(ChatUser)))) + { + memset(cu, 0, sizeof(ChatUser)); + cu->sock = csock; + + cu->unext = mainuser; + mainuser = cu; + +#if 0 + if (mainuser.next) + mainuser.next->prev = cu; + cu->next = mainuser.next; + mainuser.next = cu; + cu->prev = &mainuser; +#endif + + totaluser++; + FD_SET(csock, &mainfds); + if (csock >= maxfds) + maxfds = csock + 1; + +#ifdef DEBUG + logit("accept", "OK"); +#endif + } + else + { + close(csock); + logit("accept", "malloc fail"); + } + MYDOG; + + break; + } + + csock = errno; + if (csock != EINTR) + { + break; + } + } + + FD_CLR(msock, rptr); + + if (--nfds <= 0) + continue; + } + + for (cu = mainuser; cu; cu = cu->unext) + { + MYDOG; + + csock = cu->sock; + + if (FD_ISSET(csock, xptr)) + { + logout_user(cu); + FD_CLR(csock, xptr); + } + else if (FD_ISSET(csock, rptr)) + { + if (cuser_serve(cu) < 0) + logout_user(cu); + } + else + { + continue; + } + + FD_CLR(csock, rptr); + if (--nfds <= 0) + break; + } + + /* end of main loop */ + } +} diff --git a/util/xchatd.h b/util/xchatd.h new file mode 100644 index 00000000..d0a6e1e4 --- /dev/null +++ b/util/xchatd.h @@ -0,0 +1,111 @@ +/* $Id: xchatd.h,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ + +#ifndef _XCHAT_H_ +#define _XCHAT_H_ + +#define XCHAT_VERSION_MAJOR 3 +#define XCHAT_VERSION_MINOR 0 + +/* ----------------------------------------------------- */ +/* XCHAT response code : RFI 3-digit */ +/* ----------------------------------------------------- */ +/* Response : */ +/* 1xx Informative message */ +/* 2xx Command ok */ +/* 3xx Command ok so far, send the rest of it */ +/* 4xx Command correct, but NG for some reason */ +/* 5xx Command unimplemented, incorrect, or serious */ +/* program error occurred */ +/* Function : */ +/* x0x Connection, setup, and miscellaneous messages */ +/* x1x Newsgroup selection */ +/* x2x Article selection */ +/* x3x Distribution functions */ +/* x4x Posting */ +/* x8x Nonstandard extensions (AUTHINFO, XGTITLE) */ +/* x9x Debugging output */ +/* Information : */ +/* No defined semantics */ +/* ----------------------------------------------------- */ + +/* ¨Ñ·sª© client ¨Ï¥Î */ + +#define MSG_LOGINOK 100 +#define MSG_VERSION 103 +#define MSG_MESSAGE 106 + +#define MSG_CHATROOM 110 +#define MSG_TOPIC 113 +#define MSG_ROOM 116 +#define MSG_NICK 118 +#define MSG_CLRSCR 120 + +#define MSG_MOTDSTART 130 +#define MSG_MOTD 330 +#define MSG_MOTDEND 230 + +#define MSG_ROOMLISTSTART 133 +#define MSG_ROOMLIST 333 +#define MSG_ROOMLISTEND 233 +#define MSG_ROOMNOTIFY 134 + +#define MSG_USERLISTSTART 136 +#define MSG_USERLIST 336 +#define MSG_USERLISTEND 236 +#define MSG_USERNOTIFY 137 + +#define MSG_PARTYINFO 140 +#define MSG_PARTYLISTSTART 340 +#define MSG_PARTYLIST 240 +#define MSG_PARTYLISTEND 141 + +#define MSG_PRIVMSG 145 +#define MSG_MYPRIVMSG 146 + +#define ERR_LOGIN_NICKINUSE 501 +#define ERR_LOGIN_NICKERROR 502 +#define ERR_LOGIN_USERONLINE 503 +#define ERR_LOGIN_NOSUCHUSER 504 +#define ERR_LOGIN_PASSERROR 505 + +static int +Isspace (ch) + int ch; +{ + return (ch == ' ' || ch == '\t' || ch == 10 || ch == 13); +} + +static char * +nextword (str) + char **str; +{ + char *head, *tail; + int ch; + + head = *str; + for (;;) { + + ch = *head; + if (!ch) { + *str = head; + return head; + } + if (!Isspace (ch)) + break; + head++; + } + + tail = head + 1; + while((ch = *tail)) { + if(Isspace (ch)) { + *tail++ = '\0'; + break; + } + tail++; + } + *str = tail; + + return head; +} + +#endif /* _XCHAT_H_ */ diff --git a/util/yearsold.c b/util/yearsold.c new file mode 100644 index 00000000..74e711ee --- /dev/null +++ b/util/yearsold.c @@ -0,0 +1,112 @@ +/* $Id: yearsold.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */ +/* ¯¸¤W¦~ÄÖ²Îp */ + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "util.h" + +#define MAX_LINE 16 + +struct userec_t cuser; + +void + outs(fp, buf, mode) +FILE *fp; +char buf[], mode; +{ + static char state = '0'; + + if (state != mode) + fprintf(fp, "[3%cm", state = mode); + if (buf[0]) + { + fprintf(fp, buf); + buf[0] = 0; + } +} + +int main() +{ + int i, j, k; + char buf[256]; + FILE *fp; + int year, max, item, maxyear; + long totalyear; + int act[25]; + time_t now; + struct tm *ptime; + + now = time(NULL); + ptime = localtime(&now); + + if(passwd_mmap()) + exit(1); + + memset(act, 0, sizeof(act)); + for(k = 1; k <= MAX_USERS; k++) { + passwd_query(k, &cuser); + if (((ptime->tm_year - cuser.year) < 10) || ((ptime->tm_year - cuser.year) > + 33)) + continue; + + act[ptime->tm_year - cuser.year - 10]++; + act[24]++; + } + + for (i = max = totalyear = maxyear = 0; i < 24; i++) + { + totalyear += act[i] * (i + 10); + if (act[i] > max) + { + max = act[i]; + maxyear = i; + } + } + + item = max / MAX_LINE + 1; + + if ((fp = fopen(BBSHOME"/etc/yearsold", "w")) == NULL) + { + printf("cann't open etc/yearsold\n"); + return 1; + } + + fprintf(fp, "\t\t\t [1;33;45m " BBSNAME + " ¦~ÄÖ²Îp [%02d/%02d/%02d] [40m\n\n", + ptime->tm_year % 100, ptime->tm_mon, ptime->tm_mday); + for (i = MAX_LINE + 1; i > 0; i--) + { + strcpy(buf, " "); + for (j = 0; j < 24; j++) + { + max = item * i; + year = act[j]; + if (year && (max > year) && (max - item <= year)) + { + outs(fp, buf, '7'); + fprintf(fp, "%-3d", year); + } + else if (max <= year) + { + outs(fp, buf, '4'); + fprintf(fp, "¢i "); + } + else + strcat(buf, " "); + } + fprintf(fp, "\n"); + } + + + fprintf(fp, " [32m" + "10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33\n\n" + "\t\t [36m¦³®Ä²Îp¤H¦¸¡G[37m%-9d[36m¥§¡¦~ÄÖ¡G[37m%d[40;0m\n" + ,act[24], (int)totalyear / act[24]); + fclose(fp); + return 0; +} |