commit 9002c02abc587664acb357c6879d8ca08664dd0b Author: Rodney W. Grimes Date: Sat Jun 12 14:49:13 1993 +0000 Initial import, 0.1 + pk 0.2.4-B1 Notes: svn path=/cvs2svn/branches/tcpdump/; revision=2 diff --git a/gnu/games/chess/DOCUMENTATION/ARTICLE b/gnu/games/chess/DOCUMENTATION/ARTICLE new file mode 100644 index 000000000000..b2ab331d21d5 --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/ARTICLE @@ -0,0 +1,66 @@ +[This article was reproduced from a GNU Bulletin.] + + GNU Chess + by Stuart Cracraft + copyright 1987 Stuart Cracraft + + + GNU Chess is a communal chess program. Contributors donate their +time and effort in order to make it a stronger, better, sleeker program. +Contributions take many forms: interfaces to high-resolution displays, +opening book treatises, speedups of the underlying algorithms, additions +of extra heuristics. These contributions are then distributed to the +large user-base so that all may enjoy the fruits of our labor. The +original and continuing purpose of this project is to permanently end +the rampant hoarding of computer chess software that has been the +case for the past 20 years. + + Many people have contributed to GNU Chess. Their contributions have +improved the program from being a patzer (weak program) to being a +grandpatzer (decently strong program). In its growth since initial +release, GNU Chess has gone from approximately class D to expert +strength. It beats the Fidelity Excel commercial unit rather handily. + + GNU Chess's structure is a hybrid of the Shannon Type-A and +Type-B methods. It conducts a full-width search to a fixed-depth +and then continues with a quiescence search for many more ply. +This quiescence search helps the program find positions which +can be safely evaluated and which are not too turbulent. If +a terminal position is too turbulent, the evaluation will be +highly inaccurate. Additional searching by investigating series +of captures, checks, and other potentially imbalance-producing +moves is quite helpful. + + GNU Chess will sacrifice pieces in order to reach known winning +endings. Also, it uses a trade-down bonus to encourage the stronger +side to trade off certain types of pieces thus reaching a more +simplified and therefore ostensibly "clearer" position. + + GNU Chess has certain types of knowledge regarding easier endgames. +This allows it to play these endings somewhat better than might be +expected. + + GNU Chess has time heuristics that it uses to improve its handling +of time-controls and hasten its making of "obvious" moves. + + GNU Chess is interfaced to the SUN Windows and X Windows +display protocols and can display its pieces in elaborate format, +similar to chess diagrams. + + GNU Chess has an opening book which consists of many variations +from MCO (Modern Chess Openings). + + For comparison purposes, GNU Chess running on a VAX 8650 is +stronger than the famous Chess 4.5 running on a CDC 6400. + + We wish to acknowledge the contributions of the following +individuals: (in alphabetical order) Jim Aspnes, Wayne Christopher, +Steve Dougherty, David Goldberg, Richard Greenblatt, David Kittinger, +Richard Stallman, John Stanback, and Ken Thompson. + + Contact information: The author may be reached by a variety of +methods. Via U.S. mail: Stuart Cracraft, 5 Via Amistosa, Suite G, +Rancho Santa Margarita, Ca. 92688 USA. + By Internet: 'cracraft at wheaties.ai.mit.edu' +The author may also be contacted via the Free Software Foundation, Inc. +675 Massachusetts Ave.,Cambridge MA 02139. diff --git a/gnu/games/chess/DOCUMENTATION/ARTICLE.2 b/gnu/games/chess/DOCUMENTATION/ARTICLE.2 new file mode 100644 index 000000000000..031ae18f9e4b --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/ARTICLE.2 @@ -0,0 +1,123 @@ + + + GNU Chess: Experiences Learned + with Communal Sharing + by Stuart Cracraft + (and contributors to the GNU Project) + + +Limited sharing has characterized the computer chess community +for the past two decades. Occasional research articles give hints +and suggestions for useful features, but rarely reveal the real +details of the critically important advances. We will here +describe an effort underway (titled "GNU Chess") to create a more +open and friendly environment of sharing. + +GNU Chess is part of Project GNU, a large-scale effort in which +the philosophical goals are far-reaching. We will not go into any +great depth about these goals as they relate to the larger pro- +ject, because these are described elsewhere [1]. However, we will +mention the basic issues and the changes we hope to encourage. + +The start of the GNU Chess project was a natural result of the +experiences gleaned in writing a chess program. While the author +was at a progressive academic location [2], he was able to con- +ceive the idea of a communal chess program only after much heart- +ache. During the period of writing the initial version (which +has since undergone many improvements and whole revisions), it +became clear that the best features and most useful hints, the +very best of the heuristics, were hidden and difficult to find in +the literature. + +Sprinkled across many books, research papers, magazine articles, +accumulated in the community, during the past 25 years, there was +literally a void of true, empirical programs. Locating usable +programs was difficult. Many programs were the result of academic +work in "ivory towers", and hence were inaccessible to the common +man. Other programs were sequestered in research think-tanks. Na- +turally, developers of commercial programs carefully guarded +their source in order to protect their investment. On the other +hand, a few chess program source listings had actually been pub- +lished, but these were not really very strong, often written in a +non-general language, and frequently more pedantic than practi- +cal. + +The idea of a reasonably strong communal program solidified. +When we refer to a communal program, we do not regard this as +public-domain software. Rather, we refer to a program which is +under the shared authority of a number of individuals, the prin- +cipal contributors. These individuals have experienced and real- +ized the positive results of a sharing community and the rapid +improvements that come through contributing in such a community. +Further, these individuals devote time and energy to coordinating +the contributions of other individuals. While they exercise a +certain editorial right, this is usually not exercised arbitrari- +ly; instead, a discussion is often undertaken. + +Eventually, a working C program that played chess was available. +The coordinating institution for Project GNU [3], accepted our +suggestion of inclusion of a chess program in the GNU distribu- +tion. Initial distribution of GNU Chess commenced in October of +1986. Interest in the project increased rapidly. + +Contributions came in from many places and people. Interfaces to +X-windows and SUN-windows were donated, thus allowing very fancy +chess fonts on bit-mapped screens. Also, contributions involving +large portions of opening books such as MCO and collections of +master games were added to the distribution. Additionally, +tree-search modifications and heuristics were provided, and occa- +sionally even entire rewrites. + +The program advanced in strength by several USCF class intervals +during a period of less than one year. During this time, many +unusual features and enhancements were added to the program, usu- +ally under the coordination of two or more people, with one work- +ing in a distant-advisory capacity to the other. Frequently, gra- +duate students would give up significant time from their thesis +work to devote energy to contributing. Their corporate counter- +parts would often give up project time to make their donation. + +Contributors would often enter the project in a very forceful way +and then having made their contribution, learn the viability of +communal sharing once others had stepped in and contributed to +them, thus providing considerable reinforcement. Frequently, con- +tributors would then go into "hibernation" for a long period of +time, but most of them remained open to contributing and were +helpful when asked to reprogram their particular contribution in +a more recent version. + +GNU Chess has made great strides in relatively little time. It +has run on many different hardware architectures and has been +compiled by a number of C compilers [4]. A sampling of the com- +puters on which the program has run is: National 32032, Vax +11/750, 8550, 8600, 8650, Motorola 68020, CCI 5/32, CCI 6/32 +(tahoe), Cray XMP. + +It is our belief that GNU Chess will stimulate graduate research +in computer chess theory and practice. When students are able to +easily obtain a state-of-the-art program in order to test out +their ideas, they will no longer need to reinvent the wheel. The +students will be able to investigate their research areas much +more thoroughly, because they will spend more time on the specif- +ic research areas they are concerned about. Basically, GNU Chess +"frees up" time in order to get on to more fundamental issues. + +We also feel that as other researchers gain trust in the GNU +Chess project, they will be more likely to release their results +directly and rapidly, through journal articles, or directly to +the GNU project, and in fact become contributors and join the +present list [5]. At the very least, a communal, ever-growing +program will encourage the few "closeted" researchers to be some- +what more open in their approach to disseminating advances. + +In whatever form it takes, the progress toward elaboration of +machine chess is ongoing, and we hope that GNU chess will be +helpful to the community. Copies of GNU Chess source and "book", +as well as additional experimental code are available from the +Free Software Foundation [3] or the author [6]. + + +[1] The GNU Manifesto, Richard Stallman, Free Software Foundation, Inc. + +[2] University of Southern California, Information Sciences Institute. + diff --git a/gnu/games/chess/DOCUMENTATION/CHANGES b/gnu/games/chess/DOCUMENTATION/CHANGES new file mode 100644 index 000000000000..9866075ab8a8 --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/CHANGES @@ -0,0 +1,362 @@ + GNU CHESS HISTORY + (#include "../version.h") + +August 1, 1989 -- Jay Scott +He proofread the opening book and made +corrections. + +June 21, 1989 -- Hes @log-se.sv +He contributed new move generation routines (move.c move.h) to speedup +move generation and the overall program, by about 15-30% + +June 9, 1989 -- Tim Radzy (unet!nplab4!radz@ames.arc.nasa.gov) +He fixed a bug in xchess/board.c. In a post-game new-game situation, +castling wouldn't be permitted under circumstances. Tim made +it possible to castle again. + +May 12, 1989 -- Joe Garbarini (garbarini%kegger@circus.llnl.gov) +Recommended changes to documentation vis a vis chesstool usage. + +May 5, 1989 -- Jouko Holopainen (jhol@tolsun.oulu.fi) +Wrote code to support underpromotion. +Changed interface to accept ECO/Informator style moves. + +April 30, 1989 -- Various GNU contributors +setlinebuf() modification for xchess/chesstool. +check for zero division in time printout. + +January 17, 1989 -- Anders Thulin +Provided extensive addition to the opening book for his +favorite opening the Vienna Game. This was drawn from ECO. + +November 23, 1988 -- Stuart Cracraft +Installed new version of Xchess that is better debugged, works on +the next version of X. Thanks to Wayne Christopher and Arturo Perez. + +August 28, 1988 -- Stuart Cracraft +Removed a sacrifice line from the Giuoco Piano entry in the opening +book; the program didn't seem to like the positions it got from this line. + +December 30, 1987 -- John Stanback +Wrote a short blurb on the heuristics contained in GNU Chess. It resides +in the subdirectory DOCUMENTATION as the file HEURISTICS. + +December 17, 1987 -- John Stanback +Modified criteria for positional evaluation in quiescence search +to include positions in which the estimated score lies within +the alpha-beta window; fixed a bug in the king proximity to pawns heuristic; +fixed a bug involving passed pawn heuristics; + +December 16, 1987 -- Stuart Cracraft +Added automatic 'list' upon exit (both in display, non-display, and +chesstool mode); command-line setting of tournament time controls +bug fixed. + +December 14, 1987 -- John Stanback +GNU defeated the commercial product 'Fidelity Excellence' 5.5-4.5 in +a 10-game match. It was running at about 500 nodes per second (typical +of its speed on a VAX 8650) and this would indicate its strength +would be about USCF 1875-1900. + +December 4, 1987 -- John Stanback +Man page added. Command line arguments now specify regular clock +settings if so desired (useful for SUN players). Thinking +on opponent's time is now disabled by default. Estimated +rating is 1850 at 500 nodes per second. + +October 20, 1987 -- Stuart Cracraft +Fixed GNU/SUN interaction. Chesstool and its features now +seem to fully work. + +October 5, 1987 -- Ken Thompson +GNU beat Belle (actually drew due to a bug, but +Ken kept GNU playing through to the win) while +running on a Cray XMP-48. In this 3-1 time handicap game +Belle outsearched Cray GNU by 10-1 (even with the handicap). + +September 26, 1987 -- John Stanback at HP +Hash table functioning. Thinking on opponent's +time functioning. + +August 20, 1987 -- Mike Meyer at Berkeley +Mike ran GNU Chess on a Cray 1 supercomputer. +The system was very heavily loaded, so the +program was not as speedy as with the Cray below. + +August 16, 1987 -- David Goldberg at SUN +He added "chesstool" support so that this +version of GNU Chess can run under the +display manager "chesstool". + +August 15, 1987 -- John Stanback at HP +Hash tables, more heuristics, a modified +search which is more efficient. He also +discovered a bug in the piece-exchanger. This +would cause the program to exchange pieces suboptimally. +With this fix, the program should play much +more strongly. + +August 13, 1987 -- Ken Thompson at Bell Labs +Ken ran GNU Chess on a Cray XMP supercomputer + (among other processors). The program got + about 3000-4000 chess positions per second + which is comprable to today's fastest bit-slice + commercial machines. Also, he had GNU Chess + play two games against Belle. + +July 19, 1987 -- Jay Scott & John Stanback + Many positional heuristics have been added. + +July 18, 1987 -- Stuart Cracraft + Improvements have been made to the opening + book. It is mostly an MCO book, containing + major variations from many of the major openings + and particularly in-depth on Sicilian. + +May 11, 1987 -- John Stanback at HP + He donated his chess program, a fairly mature + and strong program. + +May 1, 1987 -- Stuart Cracraft + He added several bug fixes various people + had reported. He also changed makemove() so that + the calling syntax is makemove(movelist,index,board) + rather than makemove(move,board). Having the latter + tickled a bug in at least one manufacturer's C-compiler, + so rather than write fancy code, we simplified it. + +April 25, 1987-- Jim Aspnes at MIT +He added all sorts of useful capabilities, +including positional evaluation in the tree +search using a table-driven algorithm, +modifying transposition table code in order +to work properly, though it doesn't improve +speed too much, checkmates/stalemates detected +in the search, en passant captures allowed, +detect repeated positions, iterative deepening, +quicker quiescence search, tournament time controls, +sqattacked sped up by a factor of 4, compile-time +debugging options. + +January 2, 1987 -- Stuart Cracraft + He added a few more Tal games to the collection. + +January 2, 1987 -- Jim Aspnes at MIT + He contributed MCO variations for the Catalan, + Queen's Indian, and Reti openings. + +December 29, 1986 -- Jim Aspnes at MIT + He contributed all MCO variations of the Najdorf + to the opening book. He also contributed a LISP + macro (written in GNU Emacs Lisp) to convert + xchess game formats to GNU Chess opening book + format. + +December 14, 1986 -- Ken Thompson at Bell Labs + He contributed almost 200 games by Tal to + our collection of Tal-games, bringing the + total number of Tal positions in the book + to 10,692. Total book positions now 13,207. + These reside in bookin, bookin.bdg, bookin.tal. + Note that presently, only bookin and bookin.tal + can be used. The new Tal positions came in a + slightly different format, which we have chosen + to adopt as our standard format. All book + games in bookin and bookin.bdg will gradually + change into the new standard format. + +December 11, 1986 -- Stuart Cracraft + Added "averages" for node-count per move, + cpu per move, rate per move to list_history + and write_history. + New version of Xchess installed. + Started typing in Tal games into "bookin.tal". + Added "total book positions" printout to "book" + and "enter" statistics printout. + +December 10, 1986 -- Stuart Cracraft + Implemented aspiration search in normal + alpha-beta search. Speedups of 3% to 40% + have been noticed in most positions. + Occasionally a slower search will result, + but it is thought these are worth the + usual speedups. + +December 9, 1986 -- Stuart Cracraft + Fixed minor bug in write_history() + Added another Tal game, 2nd game of 1st world + championship match with Botvinnik, a Benoni. + +December 9, 1986 -- Stuart Cracraft + Enhanced parallelism. All parallel processors + now communicate via a shared data file and + are kept running (in idle loops watching the + shared data file). This saves us a few seconds + on each move since the 'rsh' need not be invoked + more than once (at the beginning). Since the + shared data file is now implemented, we will + next work towards a "parallel anarchy" in which + any processor can use any other processor in + order to reduce its search. The current scheme + with the program being only as fast as its slowest + processor, is quite inefficient. + +December 1, 1986 -- Jim Aspnes at MIT + Added a couple of Master games from + Modern Chess Openings 12 (a Fischer game, + and a Matanovic game). + +November 30, 1986 -- Stuart Cracraft + Added parallelism. Can now handle multiple + processors (sharing same disk). Later we will + add the capability to use processors not sharing + the same disk. Modified README and MAN-PAGE. + +November 26, 1986 -- Stuart Cracraft + Fixed a few bugs in book-mailing mechanism. + Fixed a bug regarding situations where only + one move is available. + Fixed a bug in read_history() that caused + Black queenside castles to be mishandled. + +November 25, 1986 -- Stuart Cracraft + Added two pawn heuristics. Reward pawns moving into + a phalanx of pawns. A phalanx is two or more + horizontally-connected pawns. Likewise, penalize + pawns leaving a phalanx of pawns. The penalty for + leaving is a little more than the reward for + entering. + +November 24, 1986 -- Stuart Cracraft + A user reported an unbelievable bug. Investigation + of this bug led to the discovery that GNU Chess was + not picking the move judged best by the tree search + in all cases. This resulted in the bug showing + itself which further showed that the program was + selecting an inferior move. This may result in an + improvement to the program's play. + +November 24, 1986 -- Stuart Cracraft + Added two heuristics. Penalize king moves if + the king hasn't castled yet. Also, penalize pawn + moves which produce doubled pawns. Should + probably have something for isolated pawns + too. + +November 23, 1986 -- Wayne Christopher at Berkeley + New version of X chess display front-end. + Fixed bugs include multiple pieces, runs + on SUNS & Bobcats, loads saved games. + +November 23, 1986 -- Stuart Cracraft + Cleaned up some minor bugs regarding history. + Added "Illegal command" error message at Wayne's + request. + +November 22, 1986 -- David Goldberg at SUN Microsystems + He complained that GNU Chess was memory-hungry. + A few minor modifications to hash.c reduced + uninitialized data space 87% and text space + 12%. This should make it easier for GNU Chess + to run on small computers. + +November 22, 1986 -- Stuart Cracraft + "read" command was working, but needed + additional tweaking so that history + array would be printed by list_history(). + +November 19, 1986 -- Stuart Cracraft + Added "read" command which reads a history + file (game listing) and restores the board + to as if the person was still playing that. + particular game. Generally cleaned up + history mechanism, made it more orthogonal. + Revised README. Added doc to MAN-PAGE. + +November 16, 1986 -- Stuart Cracraft + More opening book bugs found and fixed. + Added capability to accept abbreviated-algebraic notation + for entering "book" games from files. + Added approximately 2500 new positions to + opening book from games involving the + opening called Blackmar-Diemer Gambit, + a hoary line developed by Diemer in + Germany years ago. + +November 15, 1986 -- Wayne Christopher at Berkeley + He modified the move generator, resulting in + a 28% speedup. + +November 14, 1986 -- Stuart Cracraft + He documented a lot of the GNU Chess modules + with brief comments for each function. More + extensive internal documentation may go in + later. + +November 14, 1986 -- Wayne Christopher at Berkeley + He created the Xchess interface for + GNU Chess to have windowing with X windows. + +November 14, 1986 -- Stuart Cracraft + He added a "randomization" feature to + the opening book. This will cause the + program to select randomly from alternate + variations whenever -DBEST is removed + from Makefile's CFLAGS. If this is not + removed, the opening play selects the + first move found in the book as it appears + "in order" in the human-readable book. + +November 14, 1986 -- David Goldberg at SUN Microsystems + He responded to a query about dbm(3) which + eventually resulted in the fixing of a subtle + bug in the book code which was causing the + program to sometimes hash to the incorrect + address and thereby produce a book move which + didn't even exist in the book. Thanks David! + +November 14, 1986 -- Stuart Cracraft + He added the "oboard" routine in util.c. This + is the reverse of the already extant "iboard" + (same module). These two routines translate + between GNU Chess internal format and + Forsythe notation. + +November 10, 1986 -- Stuart Cracraft + He added the "enter" command. This causes + the current game to be entered in the book. + Then, GNU Chess tries to mail this new entry + to the book maintainers (for inclusion in + the master copy of the book). + +November 9, 1986 -- Stuart Cracraft +He added code for an opening book. MAN-PAGE +and README were modified accordingly. + +November 8, 1986 -- Stuart Cracraft +Checks and mates are now noticed at ply-1. +This is a more complete fix to the Oct 31 fix. + +October 31, 1986 -- Stuart Cracraft +First attempt at fix to bug which causes +program to check human's king when program +itself is in check. + +October 31, 1986 -- Mly at MIT +Reported a bug which caused program to crash +when an illegal human move was played. Fixed. +Also, program was unable to play as White. Fixed. + +October 22, 1986 -- Stuart Cracraft +Pps now rewards moves which liberate bishops. + +October 19, 1986 -- Stuart Cracraft +Added bitmapper routines to distribution. +Added version notice. + +October 19, 1986 -- David Goldberg at SUN Microsystems +Interfaced GNU Chess with SUN's chesstool. + +October 18, 1986 -- Initial release date. + + diff --git a/gnu/games/chess/DOCUMENTATION/COPYING b/gnu/games/chess/DOCUMENTATION/COPYING new file mode 100644 index 000000000000..17847b71307f --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/COPYING @@ -0,0 +1,123 @@ + GNU CHESS GENERAL PUBLIC LICENSE + + Copyright (C) 1986,1987 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license, but changing it is not allowed. + + The license agreements of most software companies keep you at the +mercy of those companies. By contrast, our general public license is +intended to give everyone the right to share GNU Chess. To make +sure that you get the rights we want you to have, we need to make +restrictions that forbid anyone to deny you these rights or to ask you +to surrender the rights. Hence this license agreement. + + Specifically, we want to make sure that you have the right to give +away copies of GNU Chess, that you receive source code or else can get it +if you want it, that you can change GNU Chess or use pieces of it in new +free programs, and that you know you can do these things. + + To make sure that everyone has such rights, we have to forbid you to +deprive anyone else of these rights. For example, if you distribute +copies of GNU Chess, 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 tell them their rights. + + Also, for our own protection, we must make certain that everyone +finds out that there is no warranty for GNU Chess. If GNU Chess is +modified by someone else and passed on, we want its recipients to know +that what they have is not what we distributed, so that any problems +introduced by others will not reflect on our reputation. + + Therefore the Free Software Foundation, Inc. makes the following +terms which say what you must do to be allowed to distribute or change +GNU Chess. + + COPYING POLICIES + + 1. You may copy and distribute verbatim copies of GNU Chess source +code as you receive it, in any medium, provided that you conspicuously +and appropriately publish on each file a valid copyright notice +"Copyright (C) 1986,1987 Free Software Foundation, Inc.", containing the +year of last change for the file in question; keep intact the notices +on all files that refer to this License Agreement and to the absence +of any warranty; and give any other recipients of the GNU Chess +program a copy of this License Agreement along with the program. + + 2. You may modify your copy or copies of GNU Chess source code or +any portion of it, and copy and distribute such modifications under +the terms of Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + who last changed such files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of GNU Chess + or any part thereof, to be freely distributed + and licensed to all third parties on terms identical to those + contained in this License Agreement (except that you may choose + to grant more extensive warranty protection to third parties, + at your option). + + c) if the modified program serves as a text editor, cause it + when started running in the simplest and usual way, to print + an announcement including a valid copyright notice ("Copyright + (C)", the year of authorship, and all copyright owners' names), + saying 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 Agreement. + + 3. You may copy and distribute GNU Chess or any portion of it in +compiled, executable or object code form under the terms of Paragraphs +1 and 2 above provided that you do the following: + + a) cause each such copy of GNU Chess to be accompanied by the + corresponding machine-readable source code; or + + b) cause each such copy of GNU Chess to be accompanied by a + written offer, with no time limit, to give any third party + free (except for a nominal shipping charge) machine readable + copy of the corresponding source code; or + + c) in the case of a recipient of GNU Chess in compiled, executable + or object code form (without the corresponding source code) you + shall cause copies you distribute to be accompanied by a copy + of the written offer of source code which you received along + with the copy of GNU Chess. + + 4. You may not copy, sublicense, distribute or transfer GNU Chess +except as expressly provided under this License Agreement. Any attempt +otherwise to copy, sublicense, distribute or transfer GNU Chess is void and +your rights to use GNU Chess under this License agreement shall be +automatically terminated. However, parties who have received computer +software programs from you with this License Agreement will not have +their licenses terminated so long as such parties remain in full compliance. + +Your comments and suggestions about our licensing policies and our +software are welcome! Please contact the Free Software Foundation, Inc., +1000 Mass Ave, Cambridge, MA 02138, or call (617) 876-3296. + + NO WARRANTY + + BECAUSE GNU CHESS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY +NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, +AND/OR OTHER PARTIES PROVIDE GNU CHESS "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 GNU CHESS PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE +FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND +REDISTRIBUTE GNU CHESS AS PERMITTED ABOVE, BE LIABLE TO YOU FOR +DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY +FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY +OTHER PARTY. +====================================================================== diff --git a/gnu/games/chess/DOCUMENTATION/GENERAL b/gnu/games/chess/DOCUMENTATION/GENERAL new file mode 100644 index 000000000000..aafb7ed335e3 --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/GENERAL @@ -0,0 +1,34 @@ + GNU Chess + +Copyright (C) 1987 Stuart Cracraft + (Copying permission notice at the end.) + +GNU Chess is your program (as long as you follow the copyright and +licensing rules listed in the file COPYING). Your contributioinspire current and future software +developers. + +This document +------------- +This document is not meant to be a an introduction to computer chess. +The following books are excellent introductions and treatises. +They are listed in order of difficulty: + + Computer Chess (2nd edition), by David Welsh and Boris Bazcynski + The Joy of Computer Chess, by David Levy + Chess Skill in Man and Machine (2nd edition), by Peter Frey + + +Current Distribution +-------------------- +The most recent distribution of GNU Chess contains the following +main-level files and directories: + + Filename Purpose + ------------------------------------------------------ + README Pointer to main README below. + gnuchess.c Most recent version of GNU Chess + nondsp.c Non-display interface, and chesstool/xchess interface + uxdsp.c Unix (curses) display interface + ansidsp.c ANSI display interface + gnuchess.book Most recent version of opening book + diff --git a/gnu/games/chess/DOCUMENTATION/HEURISTICS b/gnu/games/chess/DOCUMENTATION/HEURISTICS new file mode 100644 index 000000000000..254b34472abe --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/HEURISTICS @@ -0,0 +1,122 @@ +This file contains a description of GNU's heuristics. + Copyright (C) 1986, 1987 Free Software Foundation, Inc. + +This file is part of CHESS. + +CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +CHESS, but only under the conditions described in the +CHESS General Public License. A copy of this license is +supposed to have been given to you along with CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + -- requested by main author +Heuristic descriptions for CHESS. + +Revision: 12-16-87 + +Copyright (c) 1987 by John Stanback + + Here is a brief description of the heuristics used in the positional + evaluator of the GNU Chess program. Many heuristics are functions of the + stage of the game which is based on the total non-pawn material remaining + for both sides. + + +PAWNS + The material value of a pawn is 100 points. Isolated pawns get a + penalty depending on which file they occupy: + (12,14,16,20,20,16,14,12) for files (a..h). + Doubled pawns (which are not also isolated) get a penalty of 12 + points. Backward pawns (defined simply as not being defended by a + pawn with the square in front also not defended by a a pawn) are + penalized 6 points. A 4 point penalty is also invoked for each attack + by the opponent to a backward pawn and for a backward pawn on a + half-open file. Pawn Advancement in the centre is given a bonus of + about 4 points per rank in the opening increasing to about 8 points + per rank in the ending. Advancement on the edges is given a lower + bonus. Pawns on the e and d files and on the 2nd rank are given a 10 + point penalty. An additional penalty of 15 points is invoked if these + pawns are also blocked. Pawns within 2 squares of the king are given + a 10 point bonus. Passed pawns are given a bonus for increasing rank + which is a function of stage of the game and of whether the opponent + blocks or attacks one or more squares in front of the pawn or if the + opponents king is in the square of the pawn. This bonus ranges from + about 15 points for a pawn on the second rank up to about 300 points + for a passed pawn on the 7th rank which can't be stopped from + queening. + + +KNIGHTS + The material value of a knight is 330 points. The main heuristic for + knights is a bonus for proximity to the centre. This varies from 0 + points in the corners to 30 points in the centre. Knights are also + given a bonus for being within 2 squares of each enemy piece. This + bonus is a function of the stage of the game, equalling 4 points in + the end game. A penalty of 1 point per square is given for distance + from either king. A bonus of up to 8 points (depends on stage) is + given for knights which can't be driven away by enemy pawns. + + +BISHOPS + The material value of a bishop is 330 points. Bishops are given a + bonus as material falls off the board equalling 10 points in the end + game. Bishops get a bonus for mobility and Xray mobility thru pieces + but not pawns. This bonus ranges from -4 points for a totally blocked + bishop up to 18 points for a bishop attacking 12 or more squares. + Xray attacks on an enemy R,Q,K or any undefended piece are given an 8 + point bonus. Bishops are given a bonus of 14 points if they lie on + the edge of the board up to 22 points if the lie in the centre. A + bishop is given a bonus of up to 5 points for each attack to a square + adjacent to the enemy king. + + +ROOKS + The material value of a rook is 520 points. Rook mobility is handled + similiarly to bishops with a bonus of 0 points if blocked up to 20 + points if attacking 12 squares or more. A bonus of 8 points for Xray + attacks is handled as it is for bishops. Rooks are given a bonus of + 10 points for occupying a file with no friendly pawns and a bonus of + 4 points if no enemy pawns lie on that file. After the opening Rooks + are penalized slightly depending on "taxicab" distance to the enemy + king. + + +QUEENS + The material value of a queen is 980 points. The only heuristic for a + queen is that after the opening it is penalized slightly for + "taxicab" distance to the enemy king. + + +KINGS + Kings are given a penalty for proximity to the centre in the opening + and a bonus for proximity to the centre in the endgame. The penalty + is about 24 points for being in the centre in the opening with a + bonus of about 36 points for being in the centre in the endgame. + Kings are penalized for lying on an open or half-open file or if the + adjacent file closest to the corner is open or half-open. This + penalty is up to 23 points in the opening and goes to zero in the end + game. The King is penalized up to 8 points if there are no pawns + immediately adjacent. A penalty is invoked depending on the number of + "safe" checks available by the opponent. This penalty ranges from 6 + points for one such check to 50 points for 4 or more. Depending on + game stage, Kings are given up to 10 points for castling and a + penalty of up to 40 points for moving before castling. + + +SPECIAL + If more than one piece is "hung" (attacked and not defended or + attacked by an enemy piece of lower value) an extra penalty of 10 + points is invoked for that side and the search may be extended one + ply. Pinned or trapped pieces are treated similarly. A special mating + routine is used if one side has only a king and the other has mating + material. + diff --git a/gnu/games/chess/DOCUMENTATION/MAN-PAGE b/gnu/games/chess/DOCUMENTATION/MAN-PAGE new file mode 100644 index 000000000000..bbf0aa4abf98 --- /dev/null +++ b/gnu/games/chess/DOCUMENTATION/MAN-PAGE @@ -0,0 +1,161 @@ +.TH Chess GNU +.SH NAME +Chess \- GNU Chess +.SH SYNOPSIS +.B Chess +[ +.B arg1 arg2 +] +.SH DESCRIPTION +.I Chess +plays a game of chess against the user or it plays against itself. +.PP +.I Chess +has a simple alpha-numeric board display or it can be compiled for +use with the CHESSTOOL program on a SUN workstation. +The program gets its opening moves from the file gnuchess.book which +should be located in the same directory as gnuchess. +To invoke the prgram, type 'gnuchess' or type 'chesstool gnuchess' +on a SUN workstation where 'CHESSTOOL' is installed. +The 'gnuchess' command can be followed by up to 2 command line arguments. +If one argument is given it determines the programs search time in +seconds. If two arguments are given, they will be used to set tournament +time controls with the first argument being the number of moves and the second +being the total clock time in minutes. Thus, entering 'chess 60 5' will set +the clocks for 5 minutes (300 seconds) for the first 60 moves. +If no argument is given the program will prompt the user for level of +play. +For use with CHESSTOOL, see the documentation on that program. +.PP +Once +.I Chess +is invoked, the program will display the board and prompt the user +for a move. To enter a move, use the notation 'e2e4' where the first +letter-number pair indicates the origination square +and the second letter-number pair indicates the destination square. +An alternative is to use the notation 'nf3' where +the first letter indicates the piece type (p,n,b,r,q,k). +To castle, type the origin and destination squares +of the king just as you would do for a regular move, or type +"o-o" for kingside castling and "o-o-o" for queenside. +.SH COMMANDS +.PP +In addition to legal moves, the following commands are available as responses. +.PP +.I beep +-- causes the program to beep after each move. +.PP +.I bd +-- updates the current board position on the display. +.PP +.I book +-- turns off use of the opening library. +.PP +.I both +-- causes the computer to play both sides of a chess game. +.PP +.I black +-- causes the computer to take the black pieces with the move +and begin searching. +.PP +.I level +-- allows the user to set time controls such as +60 moves in 5 minutes etc. In tournament mode, the program will +vary the time it takes for each +move depending on the situation. If easy mode is disabled (using +the 'easy' command), the program +will often respond with its move immediately, saving time on +its clock for use later on. +.PP +.I depth +-- allows the user to change the +search depth of the program. The maximum depth is 29 ply. +Normally the depth is set to 29 and the computer terminates +its search based on elapsed time rather than depth. +Using the depth command allows setting depth to say +4 ply and setting response time to a large number such as +9999 seconds. The program will then search until all moves +have been examined to a depth of 4 ply (with extensions up +to 11 additional ply for sequences of checks and captures). +.PP +.I easy +-- toggles easy mode (thinking on opponents time) +on and off. The default is easy mode ON. If easy mode is disabled, +the user must enter a 'break' or '^C' to get the programs +attention before entering each move. +.PP +.I edit +-- allows the user to set up a board position. +In this mode, the '#' command will clear the board, the 'c' +command will toggle piece color, and the '.' command will exit +setup mode. Pieces are entered by typing a letter (p,n,b,r,q,k) for +the piece followed by the coordinate. For example "pb3" would +place a pawn on square b3. +.PP +.I force +-- allows the user to enter moves for both +sides. To get the program to play after a sequence of moves +has been entered use the 'white' or 'black' commands. +.PP +.I get +-- retrieves a game from disk. The program will +prompt the user for a file name. +.PP +.I help +-- displays a short description of the commands. +.PP +.I hint +-- causes the program to supply the user with +its predicted move. +.PP +.I list +-- writes the game moves and some statistics +on search depth, nodes, and time to the file 'chess.lst'. +.PP +.I new +-- starts a new game. +.PP +.I post +-- causes the program to display the principle +variation and the score during the search. A score of +100 is equivalent to a 1 pawn advantage for the computer. +.PP +.I random +-- causes the program to randomize its move +selection slightly. +.PP +.I reverse +-- causes the board display to be reversed. That +is, the white pieces will now appear at the top of the board. +.PP +.I quit +-- exits the game. +.PP +.I save +-- saves a game to disk. The program will prompt +the user for a file name. +.PP +.I switch +-- causes the program to switch places with +the opponent and begin searching. +.PP +.I undo +-- undoes the last move whether it was the computer's +or the human's. You may also type "remove". This is equivalent +to two "undo's" (e.g. retract one move for each side). +.PP +.I white +-- causes the computer to take the white pieces +with the move and begin searching. +.SH BUGS +.PP +Pawn promotion to pieces other than a queen is not allowed. +En-Passant does not work properly with CHESSTOOOL. +The transposition table may not work properly in some +positions so the default is to turn this off. +.fi +.SH SEE ALSO +.nf +chesstool(6) +.fi + diff --git a/gnu/games/chess/Makefile b/gnu/games/chess/Makefile new file mode 100644 index 000000000000..d5fa6f48f53c --- /dev/null +++ b/gnu/games/chess/Makefile @@ -0,0 +1,15 @@ +# @(#)Makefile 5.4 (Berkeley) 5/11/90 + +PROG= chess +SRCS= gnuchess.c uxdsp.c move.c +CFLAGS+=-DNEWMOVE=12 +MAN6= chess.0 +DPADD= ${LIBCURSES} ${LIBTERM} +LDADD= -lcurses -ltermlib +HIDEGAME=hidegame + +beforeinstall: + install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/gnuchess.book \ + ${DESTDIR}/usr/share/games + +.include diff --git a/gnu/games/chess/Xchess/COPYING b/gnu/games/chess/Xchess/COPYING new file mode 100644 index 000000000000..5905c3292de1 --- /dev/null +++ b/gnu/games/chess/Xchess/COPYING @@ -0,0 +1,124 @@ + + GNU X-CHESS GENERAL PUBLIC LICENSE + + Copyright (C) 1986 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license, but changing it is not allowed. + + The license agreements of most software companies keep you at the +mercy of those companies. By contrast, our general public license is +intended to give everyone the right to share GNU X-Chess. To make +sure that you get the rights we want you to have, we need to make +restrictions that forbid anyone to deny you these rights or to ask you +to surrender the rights. Hence this license agreement. + + Specifically, we want to make sure that you have the right to give +away copies of GNU X-Chess, that you receive source code or else can get it +if you want it, that you can change GNU X-Chess or use pieces of it in new +free programs, and that you know you can do these things. + + To make sure that everyone has such rights, we have to forbid you to +deprive anyone else of these rights. For example, if you distribute +copies of GNU X-Chess, 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 tell them their rights. + + Also, for our own protection, we must make certain that everyone +finds out that there is no warranty for GNU X-Chess. If GNU X-Chess is +modified by someone else and passed on, we want its recipients to know +that what they have is not what we distributed, so that any problems +introduced by others will not reflect on our reputation. + + Therefore the Free Software Foundation, Inc. makes the following +terms which say what you must do to be allowed to distribute or change +GNU X-Chess. + + COPYING POLICIES + + 1. You may copy and distribute verbatim copies of GNU X-Chess source +code as you receive it, in any medium, provided that you conspicuously +and appropriately publish on each file a valid copyright notice +"Copyright (C) 1986 Free Software Foundation, Inc.", containing the +year of last change for the file in question; keep intact the notices +on all files that refer to this License Agreement and to the absence +of any warranty; and give any other recipients of the GNU X-Chess +program a copy of this License Agreement along with the program. + + 2. You may modify your copy or copies of GNU X-Chess source code or +any portion of it, and copy and distribute such modifications under +the terms of Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + who last changed such files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of GNU X-Chess + or any part thereof, to be freely distributed + and licensed to all third parties on terms identical to those + contained in this License Agreement (except that you may choose + to grant more extensive warranty protection to third parties, + at your option). + + c) if the modified program serves as a text editor, cause it + when started running in the simplest and usual way, to print + an announcement including a valid copyright notice ("Copyright + (C)", the year of authorship, and all copyright owners' names), + saying 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 Agreement. + + 3. You may copy and distribute GNU X-Chess or any portion of it in +compiled, executable or object code form under the terms of Paragraphs +1 and 2 above provided that you do the following: + + a) cause each such copy of GNU X-Chess to be accompanied by the + corresponding machine-readable source code; or + + b) cause each such copy of GNU X-Chess to be accompanied by a + written offer, with no time limit, to give any third party + free (except for a nominal shipping charge) machine readable + copy of the corresponding source code; or + + c) in the case of a recipient of GNU X-Chess in compiled, executable + or object code form (without the corresponding source code) you + shall cause copies you distribute to be accompanied by a copy + of the written offer of source code which you received along + with the copy of GNU X-Chess. + + 4. You may not copy, sublicense, distribute or transfer GNU X-Chess +except as expressly provided under this License Agreement. Any attempt +otherwise to copy, sublicense, distribute or transfer GNU X-Chess is void and +your rights to use GNU X-Chess under this License agreement shall be +automatically terminated. However, parties who have received computer +software programs from you with this License Agreement will not have +their licenses terminated so long as such parties remain in full compliance. + +Your comments and suggestions about our licensing policies and our +software are welcome! Please contact the Free Software Foundation, Inc., +1000 Mass Ave, Cambridge, MA 02138, or call (617) 876-3296. + + NO WARRANTY + + BECAUSE GNU X-CHESS IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY +NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, +AND/OR OTHER PARTIES PROVIDE GNU X-CHESS "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 GNU X-CHESS PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL FREE SOFTWARE +FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND +REDISTRIBUTE GNU X-CHESS AS PERMITTED ABOVE, BE LIABLE TO YOU FOR +DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY +FREE SOFTWARE FOUNDATION, INC.) THE PROGRAM, EVEN IF YOU HAVE BEEN +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY +OTHER PARTY. +====================================================================== diff --git a/gnu/games/chess/Xchess/Makefile b/gnu/games/chess/Xchess/Makefile new file mode 100644 index 000000000000..c6afd8ffb3f2 --- /dev/null +++ b/gnu/games/chess/Xchess/Makefile @@ -0,0 +1,136 @@ +# RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:09:19 $ +# $Source: /users/faustus/xchess/RCS/Makefile,v $ +# Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +# +# Makefile for xchess. + +#CC = cc -O -m68010 -L/pub.MC68010/lib -L/usr.MC68010/lib +CC = cc -O + +CFILES =\ + board.c\ + button.c\ + clock.c\ + control.c\ + jail.c\ + message.c\ + parse.c\ + popup.c\ + program.c\ + record.c\ + std.c\ + valid.c\ + window.c\ + XCircle.c + +COBJS =\ + board.o\ + button.o\ + clock.o\ + control.o\ + jail.o\ + message.o\ + parse.o\ + popup.o\ + program.o\ + record.o\ + std.o\ + valid.o\ + window.o\ + XCircle.o + +HFILES =\ + std.h\ + xchess.h + +SOURCE = $(CFILES) + +ALLFILES = $(SOURCE) $(HFILES) + +INCLUDE = -I. + +DEFINES = -DDEF_PROGRAM=\"gnuchess\" + +CFLAGS = $(DEFINES) $(INCLUDE) +LINTFLAGS = -u -z -lc -DLINT $(DEFINES) $(INCLUDE) +LINTLIB = ../lib/llib-lX.ln +#LDFLAGS = -L/usr2/X/lib -z -lX -lm +LDFLAGS = -loldX -lX11 -z -lX -lm +GPLDFLAGS = -z -loldX -lX11 -lXMenu_p -lX -lm_p -g -pg + +.c.o: $*.c + $(CC) $(CFLAGS) -c $*.c +.s.o: $*.s + $(CC) $(CFLAGS) -c $*.s + +all: xchess scrollText.o + @echo "All done." + +everything: all tags depend lint wc + @echo "All done." + +xchess: xchess.o $(COBJS) scrollText.o + $(CC) -o xchess xchess.o $(COBJS) scrollText.o \ + $(LDFLAGS) + +scrollText.o: scrollText.h scrollText.c + +gpxchess: xchess.o $(COBJS) + $(CC) -o gpxchess xchess.o $(COBJS) scrollText/libScroll.a \ + $(GPLDFLAGS) + +lint: $(SOURCE) + lint $(LINTFLAGS) $(SOURCE) $(LINTLIB) | \ + grep -v "multiply declared" + +qgrind: $(ALLFILES) + qgrind -lc $(ALLFILES) + +vgrind: $(ALLFILES) + vgrind -lc $(ALLFILES) + +opt: all + +reopt: all + +install: all + +source: $(SOURCE) + +tags: $(ALLFILES) + ctags -w -t *.c *.h > /dev/null 2>&1 + +wc: $(ALLFILES) + @wc $(ALLFILES) + +print: $(ALLFILES) + @pr $(ALLFILES) + +clean: + rm -f *.o *.a *.out xchess tags foo tmp + +tar: + tar -cf xchess.tar Makefile *.h *.c *.bitmap *.icon *.cur *.1\ + scrollText/Makefile scrollText/*.h scrollText/*.c scrollText/*.1\ + scrollText/*.3 + +$(ALLFILES): + co $@ + +depend: $(SOURCE) + cc -M $(CFLAGS) $(CFILES) > makedep + echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + ed - Makefile < eddep + rm eddep makedep + echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile + echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile + echo '# see make depend above' >> Makefile + +#----------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- make depend uses it +# DEPENDENCIES MUST END AT END OF FILE + +xchess.o $(COBJS): $(HFILES) + diff --git a/gnu/games/chess/Xchess/ScrollText b/gnu/games/chess/Xchess/ScrollText new file mode 100644 index 000000000000..782a54f48548 --- /dev/null +++ b/gnu/games/chess/Xchess/ScrollText @@ -0,0 +1,34 @@ +Subject: File: scrollText.h + +/* + * Scrollable Text Window Header File + * + * David Harrison + * University of California, Berkeley + * 1986 + * + * This file contains definitions for a scrollable text window + * with scroll bar support. + */ + +int TxtGrab(); + /* Take hold of a previously created window */ + +#define TXT_NO_COLOR -1 + +int TxtAddFont(); + /* Loads a new font for use later */ +int TxtWinP(); + /* Returns non-zero value if the window is text window */ +int TxtClear(); + /* Clears text window and resets text buffer */ + +int TxtWriteStr(); + /* Writes a string to window with immediate update */ +int TxtJamStr(); + /* Write a string without causing update to screen */ + +int TxtRepaint(); + /* Repaints entire scrollable text window */ +int TxtFilter(); + /* Handles events related to text window */ diff --git a/gnu/games/chess/Xchess/XCircle.c b/gnu/games/chess/Xchess/XCircle.c new file mode 100644 index 000000000000..d2144bcab849 --- /dev/null +++ b/gnu/games/chess/Xchess/XCircle.c @@ -0,0 +1,162 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:04 $ + * $Source: /users/faustus/xchess/RCS/XCircle.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + */ + +#include +#include +#include +#include + +#define PI 3.1415926535897932384 + +#define MAXVERTS 1000 + +void +XCircle(win, x, y, rad, start, end, width, height, pixel, func, planes) + Window win; + int x, y, rad; + double start, end; + int pixel; + int width, height; + int func, planes; +{ + Vertex verts[MAXVERTS]; + double xp, yp, ang; + int lx, ly, xpt, ypt, i; + double gradincr = 2 / (double) rad; + int bk = 0; + + while (end >= PI * 2) + end -= PI * 2; + while (start >= PI * 2) + start -= PI * 2; + while (end < 0) + end += PI * 2; + while (start < 0) + start += PI * 2; + if (end == start) { + if (end < gradincr) + end = end + PI * 2 - gradincr / 2; + else + end -= gradincr / 2; + } + for (ang = start, i = 0; i < MAXVERTS; ) { + + xp = x + rad * cos(ang); + yp = y + rad * sin(ang); + + xpt = xp; + ypt = yp; + + if (!i || (lx != xpt) || (ly != ypt)) { + verts[i].x = xpt; + verts[i].y = ypt; + verts[i].flags = 0; + i++; + } + lx = xpt; + ly = ypt; + if (bk) + break; + if (((ang < end) && (ang + gradincr > end)) || ((end < start) + && (ang + gradincr > 2 * PI) + && (ang + gradincr - 2 * PI > end))) { + ang = end; + bk = 1; + } else if (ang == end) { + break; + } else { + ang += gradincr; + } + if (ang >= PI * 2) + ang -= PI * 2; + } + + /* Now draw the thing.. */ + XDraw(win, verts, i, width, height, pixel, func, planes); + + return; +} + +#ifdef notdef VertexCurved is screwed up + +void +XCircle(win, x, y, rad, start, end, width, height, pixel, func, planes) + Window win; + int x, y, rad; + double start, end; + int pixel; + int width, height; + int func, planes; +{ + Vertex verts[7]; + int i, j, sv, ev; + int dp = 0; + + for (i = j = 0 ; i < 4; i++) { + verts[j].x = x + rad * cos((double) (PI * i / 2)); + verts[j].y = y + rad * sin((double) (PI * i / 2)); + verts[j].flags = VertexCurved; + if ((start >= PI * i / 2) && (start < PI * (i + 1) / 2) && + (start != end)) { + j++; + verts[j].x = x + rad * cos(start); + verts[j].y = y + rad * sin(start); + verts[j].flags = VertexCurved; + sv = j; + } else if ((end >= PI * i / 2) && (end < PI * (i + 1) / 2) + && (start != end)) { + j++; + verts[j].x = x + rad * cos(end); + verts[j].y = y + rad * sin(end); + verts[j].flags = VertexCurved; + ev = j; + } + j++; + } + verts[0].flags |= VertexStartClosed; + verts[j].x = verts[0].x; + verts[j].y = verts[0].y; + verts[j].flags = (verts[0].flags & ~VertexStartClosed) | + VertexEndClosed; + for (i = 0; i < 15; i++) { + if (dp) + verts[i % 7].flags |= VertexDontDraw; + if (i % 7 == ev) + dp = 1; + else if (i % 7 == sv) + dp = 0; + } + XDraw(win, verts, j + 1, width, height, pixel, func, planes); + + return; +} + +#endif notdef + diff --git a/gnu/games/chess/Xchess/bishop.bitmap b/gnu/games/chess/Xchess/bishop.bitmap new file mode 100644 index 000000000000..dc068ddf1cfa --- /dev/null +++ b/gnu/games/chess/Xchess/bishop.bitmap @@ -0,0 +1,71 @@ + +#define bishop_width 80 +#define bishop_height 80 +static char bishop_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x9f, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x23, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x67, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xf8, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x1f, 0xc0, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0, + 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xc0, 0x5f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf8, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf8, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xfd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xf8, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x70, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x70, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfa, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xfd, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, + 0xfc, 0xfd, 0xc1, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xfd, + 0xff, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, + 0x0f, 0xf0, 0x0f, 0xc0, 0x7f, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/bishop_mask.bitmap b/gnu/games/chess/Xchess/bishop_mask.bitmap new file mode 100644 index 000000000000..ca17bb3dae0d --- /dev/null +++ b/gnu/games/chess/Xchess/bishop_mask.bitmap @@ -0,0 +1,71 @@ + +#define bishop_mask_width 80 +#define bishop_mask_height 80 +static char bishop_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xdf, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xdf, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x3f, 0xfc, 0xff, 0xe3, 0xff, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x01, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x01, 0x00, 0xe0, + 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0x1f, 0xf8, + 0x1f, 0xe0, 0xff, 0x80, 0xff, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/bishop_outline.bitmap b/gnu/games/chess/Xchess/bishop_outline.bitmap new file mode 100644 index 000000000000..9772328c2984 --- /dev/null +++ b/gnu/games/chess/Xchess/bishop_outline.bitmap @@ -0,0 +1,71 @@ + +#define bishop_outline_width 80 +#define bishop_outline_height 80 +static char bishop_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d, + 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x0f, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x98, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, + 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x22, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x05, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xe0, 0x3d, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x20, + 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe0, 0x3d, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x05, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x05, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x05, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8d, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8d, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, + 0x0c, 0x85, 0xc1, 0xff, 0x01, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x87, 0x0d, + 0x7f, 0x00, 0x07, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x08, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x70, 0x00, 0x00, 0xe0, 0x18, 0x00, 0x00, 0xe0, 0x00, + 0x00, 0xc0, 0xf8, 0x1f, 0x38, 0x70, 0xc0, 0xff, 0x31, 0x00, 0x00, 0x80, + 0x0f, 0xf0, 0x0f, 0xc0, 0x7f, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/bishop_small.bitmap b/gnu/games/chess/Xchess/bishop_small.bitmap new file mode 100644 index 000000000000..5525ecd03c2d --- /dev/null +++ b/gnu/games/chess/Xchess/bishop_small.bitmap @@ -0,0 +1,15 @@ + +#define bishop_small_width 32 +#define bishop_small_height 32 +static char bishop_small_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x70, 0x1c, 0x00, + 0x00, 0x70, 0x1c, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x60, 0x16, 0x00, + 0x00, 0x60, 0x22, 0x00, 0x00, 0xf0, 0x23, 0x00, 0x00, 0xf0, 0x21, 0x00, + 0x00, 0xf8, 0x21, 0x00, 0x00, 0xf8, 0x23, 0x00, 0x00, 0xf8, 0x23, 0x00, + 0x00, 0xf8, 0x27, 0x00, 0x00, 0x38, 0x27, 0x00, 0x00, 0x3c, 0x2f, 0x00, + 0x00, 0x0c, 0x2c, 0x00, 0x00, 0x0e, 0x3c, 0x00, 0x00, 0x3e, 0x3f, 0x00, + 0x00, 0x3e, 0x3f, 0x00, 0x00, 0x3e, 0x3f, 0x00, 0x00, 0x3e, 0x3f, 0x00, + 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, + 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, + 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/bishop_small_outline.bitmap b/gnu/games/chess/Xchess/bishop_small_outline.bitmap new file mode 100644 index 000000000000..8d29a812e29e --- /dev/null +++ b/gnu/games/chess/Xchess/bishop_small_outline.bitmap @@ -0,0 +1,15 @@ + +#define bishop_small_outline_width 32 +#define bishop_small_outline_height 32 +static char bishop_small_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x50, 0x14, 0x00, + 0x00, 0x70, 0x1c, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x60, 0x16, 0x00, + 0x00, 0x60, 0x22, 0x00, 0x00, 0xf0, 0x23, 0x00, 0x00, 0x10, 0x21, 0x00, + 0x00, 0x18, 0x21, 0x00, 0x00, 0x08, 0x23, 0x00, 0x00, 0x08, 0x22, 0x00, + 0x00, 0x08, 0x26, 0x00, 0x00, 0x08, 0x24, 0x00, 0x00, 0xcc, 0x2c, 0x00, + 0x00, 0xc4, 0x28, 0x00, 0x00, 0xf6, 0x3b, 0x00, 0x00, 0xf2, 0x23, 0x00, + 0x00, 0xc2, 0x20, 0x00, 0x00, 0xc2, 0x20, 0x00, 0x00, 0xc2, 0x20, 0x00, + 0x00, 0xc2, 0x60, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, + 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, + 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0xe0, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/board.c b/gnu/games/chess/Xchess/board.c new file mode 100644 index 000000000000..4c5b9347d8e6 --- /dev/null +++ b/gnu/games/chess/Xchess/board.c @@ -0,0 +1,179 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:15 $ + * $Source: /users/faustus/xchess/RCS/board.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Stuff to deal with the board. + */ + +#include "xchess.h" + +board *chessboard; + +void +board_setup() +{ + chessboard = alloc(board); + board_init(chessboard); + return; +} + +void +board_init(b) + board *b; +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < SIZE; j++) + b->square[i][j].color = BLACK; + for (i = 2; i < 6; i++) + for (j = 0; j < SIZE; j++) + b->square[i][j].color = NONE; + for (i = 6; i < 8; i++) + for (j = 0; j < SIZE; j++) + b->square[i][j].color = WHITE; + for (i = 0; i < SIZE; i++) + b->square[1][i].type = b->square[6][i].type = + PAWN; + b->square[0][0].type = b->square[7][0].type = ROOK; + b->square[0][1].type = b->square[7][1].type = KNIGHT; + b->square[0][2].type = b->square[7][2].type = BISHOP; + b->square[0][3].type = b->square[7][3].type = QUEEN; + b->square[0][4].type = b->square[7][4].type = KING; + b->square[0][5].type = b->square[7][5].type = BISHOP; + b->square[0][6].type = b->square[7][6].type = KNIGHT; + b->square[0][7].type = b->square[7][7].type = ROOK; + b->black_cant_castle_k = false; + b->black_cant_castle_q = false; + b->white_cant_castle_k = false; + b->white_cant_castle_q = false; + + return; +} + +void +board_drawall() +{ + int i, j; + + for (i = 0; i < SIZE; i++) + for (j = 0; j < SIZE; j++) + if (chessboard->square[i][j].color != NONE) { + win_drawpiece(&chessboard->square[i][j], i, + j, WHITE); + if (!oneboard) + win_drawpiece(&chessboard->square[i][j], + i, j, BLACK); + } + return; +} + +void +board_move(b, m) + board *b; + move *m; +{ + switch (m->type) { + + case MOVE: + case CAPTURE: + b->square[m->fromy][m->fromx].color = NONE; + b->square[m->toy][m->tox].color = m->piece.color; + b->square[m->toy][m->tox].type = m->piece.type; + if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) && + (m->toy == 7)) || ((m->piece.color == WHITE) && + (m->toy == 0)))) + b->square[m->toy][m->tox].type = QUEEN; + if (m->enpassant) + b->square[m->toy + ((m->piece.color == WHITE) ? 1 : + -1)][m->tox].color = NONE; + break; + + case KCASTLE: + if (m->piece.color == WHITE) { + b->square[7][5].color = m->piece.color; + b->square[7][5].type = ROOK; + b->square[7][6].color = m->piece.color; + b->square[7][6].type = KING; + b->square[7][4].color = NONE; + b->square[7][7].color = NONE; + } else { + b->square[0][5].color = m->piece.color; + b->square[0][5].type = ROOK; + b->square[0][6].color = m->piece.color; + b->square[0][6].type = KING; + b->square[0][4].color = NONE; + b->square[0][7].color = NONE; + } + break; + + case QCASTLE: + if (m->piece.color == WHITE) { + b->square[7][3].color = m->piece.color; + b->square[7][3].type = ROOK; + b->square[7][2].color = m->piece.color; + b->square[7][2].type = KING; + b->square[7][4].color = NONE; + b->square[7][0].color = NONE; + } else { + b->square[0][3].color = m->piece.color; + b->square[0][3].type = ROOK; + b->square[0][2].color = m->piece.color; + b->square[0][2].type = KING; + b->square[0][4].color = NONE; + b->square[0][0].color = NONE; + } + break; + + default: + fprintf(stderr, "Bad move type %d\n", m->type); + } + + if (m->piece.type == KING) { + if (m->piece.color == WHITE) + b->white_cant_castle_q = + b->white_cant_castle_k= true; + else + b->black_cant_castle_q = + b->black_cant_castle_k= true; + } else if (m->piece.type == ROOK) { + if (m->piece.color == WHITE) { + if (m->fromx == 0) + b->white_cant_castle_q = true; + else if (m->fromx == 7) + b->white_cant_castle_k = true; + } else { + if (m->fromx == 0) + b->black_cant_castle_q = true; + else if (m->fromx == 7) + b->black_cant_castle_k = true; + } + } + + return; +} + diff --git a/gnu/games/chess/Xchess/button.c b/gnu/games/chess/Xchess/button.c new file mode 100644 index 000000000000..67bf3c86942f --- /dev/null +++ b/gnu/games/chess/Xchess/button.c @@ -0,0 +1,337 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:09:41 $ + * $Source: /users/faustus/xchess/RCS/button.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Do stuff with the buttons. + * The configuration we're using is: Draw Back Pause + * Resign Fwd Flip + * Reset Save Easy (Switch) + */ + +#include "xchess.h" + +typedef enum choice { NOCHOICE, DRAW, RESIGN, REPLAY, SWITCH, FORE, SAVE, + STOP, FLIP, RESTART, EASY } choice; + +static struct but { + char *label; + int x, y; + int width, height; + choice which; +} buts[] = { + { "Draw", 0, 20, 108, 29, DRAW } , + { "Back", 109, 20, 108, 29, REPLAY } , + { "Pause", 219, 20, 108, 29, STOP } , + { "Resign", 0, 50, 108, 29, RESIGN } , + { "Fwd", 109, 50, 108, 29, FORE } , + { "Flip", 219, 50, 108, 29, FLIP } , + { "Reset", 0, 80, 108, 29, RESTART } , + { "Save", 109, 80, 108, 29, SAVE } , +#define EASY_OFFSET 8 + { "Switch", 219, 80, 108, 29, SWITCH } +/* { "NoEasy", 219, 80, 108, 29, EASY }*/ +} ; +static int easy = 1; + +void +button_draw(win) + windata *win; +{ + int i, x, numbuts = sizeof (buts) / sizeof (struct but); + + XSetState(win->display, DefaultGC(win->display, 0), + win->border.pixel, WhitePixel(win->display, 0), + GXcopy, AllPlanes); + XSetLineAttributes(win->display, DefaultGC(win->display, 0), + BORDER_WIDTH, LineSolid, CapButt, + JoinMiter); + + XDrawLine(win->display, win->buttonwin, + DefaultGC(win->display, 0), + 0, 29, BUTTON_WIDTH, 29); + XDrawLine(win->display, win->buttonwin, + DefaultGC(win->display, 0), + 0, 60, BUTTON_WIDTH, 60); + XDrawLine(win->display, win->buttonwin, + DefaultGC(win->display, 0), + 108, 0, 108, BUTTON_HEIGHT); + XDrawLine(win->display, win->buttonwin, + DefaultGC(win->display, 0), + 219, 0, 219, BUTTON_HEIGHT); + + XSetFont(win->display, DefaultGC(win->display, 0), win->large->fid); + XSetForeground(win->display, DefaultGC(win->display, 0), + win->textcolor.pixel); + XSetBackground(win->display, DefaultGC(win->display, 0), + win->textback.pixel); + + for (i = 0; i < numbuts; i++) { + x = (buts[i].width - + XTextWidth(win->large, buts[i].label, + strlen(buts[i].label))) / 2; + + XDrawImageString(win->display, win->buttonwin, + DefaultGC(win->display, 0), + buts[i].x + x, buts[i].y, buts[i].label, + strlen(buts[i].label)); + } + return; +} + +void +button_service(win, event) + windata *win; + XEvent *event; +{ + XKeyEvent *ev = &event->xkey; + choice c; + int i, numbuts = sizeof (buts) / sizeof (struct but); + char *s; + + ev->y += 15; + for (i = 0; i < numbuts; i++) + if ((ev->x >= buts[i].x) && (ev->x <= buts[i].x + + buts[i].width) && (ev->y >= buts[i].y) && + (ev->y <= buts[i].y + buts[i].height)) { + c = buts[i].which; + break; + } + if ((i == numbuts) || (c == NOCHOICE)) { + message_add(win, "Bad choice.\n", true); + return; + } + + if (loading_flag && (c != STOP)) { + message_add(win, "You can only use PAUSE now\n", true); + return; + } + + switch (c) { + case DRAW: + if (!oneboard) { + message_add(win, "Just a sec...\n", false); + if (!pop_question(((win == win1) ? win2 : win1), +"The other player wants\nto call the game a draw.\nDo you agree?\n")) { + message_add(win, + "The other player declines the draw\n", false); + return; + } + } + message_add(win1, "Draw agreed.\n", false); + if (!oneboard) + message_add(win2, "Draw agreed.\n", false); + cleanup("Draw agreed."); + break; + + case RESIGN: + if (!pop_question(win, "Are you sure\nyou want to resign?")) + return; + if ((oneboard && !progflag) || (nexttomove == win->color)) { + if (nexttomove == WHITE) + s = "White resigns."; + else + s = "Black resigns."; + if (oneboard) { + message_add(win, s, false); + message_add(win, "\n", false); + } else { + message_add(win1, s, false); + message_add(win, "\n", false); + message_add(win2, s, false); + message_add(win, "\n", false); + } + sleep(5); + cleanup(s); + } else { + message_add(win, "It's not your turn.\n", true); + } + break; + + case REPLAY: + if (!oneboard) { + message_add(win, "Just a sec...\n", false); + if (!pop_question(((win == win1) ? win2 : win1), +"The other player wants\nto take back his last move.\nDo you let him?\n")) { + message_add(win, + "The other player refuses...\n", false); + return; + } + } + if (!moves) { + message_add(win, "Can't back up...\n", true); + break; + } + message_add(win1, "Replaying...\n", false); + if (!oneboard) + message_add(win2, "Replaying...\n", false); + replay(); + if (progflag) + replay(); + break; + + case FORE: + if (!oneboard) { + message_add(win, "Just a sec...\n", false); + if (!pop_question(((win == win1) ? win2 : win1), +"The other player wants\nto do a 'fore'.\nIs that ok with you?\n")) { + message_add(win, + "The other player refuses...\n", false); + return; + } + } + if (!foremoves) { + message_add(win, "Can't go forward...\n", true); + break; + } + message_add(win1, "Moving forward...\n", false); + if (!oneboard) + message_add(win2, "Moving forward...\n", false); + forward(); + break; + + case SWITCH: + message_add(win, "You can't switch yet.\n", false); + break; + + case SAVE: + if (saveflag) { + message_add(win, + "Game is already being logged in file '", true); + message_add(win, record_file, true); + message_add(win, "'.\n", true); + } else { + message_add(win, "Saving game to file '", false); + message_add(win, record_file, false); + message_add(win, "'.\n", false); + record_save(); + } + break; + + case STOP: + if (loading_flag) { + loading_paused = (loading_paused ? false : true); + message_add(win, loading_paused ? + "Stopped.\nHit 'Pause' again to restart.\n" : + "Restarted.\n", false); + } else if (clock_started) { + if (!oneboard) { + message_add(win, "Just a sec...\n", false); + if (!pop_question(((win == win1) ? win2 : win1), +"The other player wants\nto stop the clock.\nDo you let him?\n")) { + message_add(win, + "The other player refuses to pause.\n", + false); + return; + } + } + message_add(win1, + "Clock stopped.\nHit 'Pause' again to restart.\n", + false); + if (!oneboard) + message_add(win2, + "Clock stopped.\nHit 'Pause' again to restart.\n", + false); + clock_started = false; + } else { + if (!oneboard) { + message_add(win, "Just a sec...\n", false); + if (!pop_question(((win == win1) ? win2 : win1), +"The other player wants\nto start the clock again.\nIs that ok?\n")) { + message_add(win, + "The other player refuses to resume.\n", + false); + return; + } + } + message_add(win1, "Clock restarted.\n", false); + if (!oneboard) + message_add(win2, "Clock restarted.\n", false); + clock_started = true; + } + break; + + case FLIP: + message_add(win, "Flipping window...\n", false); + win->flipped = win->flipped ? false : true; + win_redraw(win, (XEvent *) NULL); + break; + + case RESTART: + if (!oneboard) { + message_add(win, "Just a sec...\n", false); + if (!pop_question(((win == win1) ? win2 : win1), +"The other player wants\nto restart the game.\nDo you agree?\n")) { + message_add(win, + "The other player refuses to reset\n", false); + return; + } + } + message_add(win, "Restarting game.\n", false); + restart(); + break; + case EASY: + if (oneboard) { + int x; + if (easy) + easy = 0; + else + easy = 1; + + if (easy) + buts[EASY_OFFSET].label = " Easy "; + else + buts[EASY_OFFSET].label = "NoEasy"; + + program_easy(easy); + + x = (buts[EASY_OFFSET].width - + XTextWidth(win->large, + buts[EASY_OFFSET].label, + strlen(buts[EASY_OFFSET].label))) / 2; + + XSetFont(win->display, DefaultGC(win->display, + 0), win->large->fid); + XSetForeground(win->display, + DefaultGC(win->display, 0), + win->textcolor.pixel); + XSetBackground(win->display, + DefaultGC(win->display, 0), + win->textback.pixel); + + XDrawImageString(win->display, + win->buttonwin, + DefaultGC(win->display, 0), + buts[EASY_OFFSET].x + x, + buts[EASY_OFFSET].y, + buts[EASY_OFFSET].label, + strlen(buts[EASY_OFFSET].label)); + } + break; + } + return; +} + diff --git a/gnu/games/chess/Xchess/clock.c b/gnu/games/chess/Xchess/clock.c new file mode 100644 index 000000000000..a7b3c3264e3c --- /dev/null +++ b/gnu/games/chess/Xchess/clock.c @@ -0,0 +1,291 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:09:47 $ + * $Source: /users/faustus/xchess/RCS/clock.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Do stuff with the clocks. The way things work is as follows. We call + * clock_init to draw the clocks initially, but they don't actually start + * running until we call clock_switch for the first time. + */ + +#include "xchess.h" + +int movesperunit = 0; +int timeunit = 0; +bool clock_started = false; +int whiteseconds, blackseconds; + +static bool white_running = true; +static long lastwhite, lastblack; +static bool firstmove = true; + +extern void dohands(), hilight(); + +#define PI 3.1415926535897932384 + +void +clock_draw(win, col) + windata *win; + color col; +{ + int i; + char buf[BSIZE]; + int x = CLOCK_WIDTH / 2, y = CLOCK_WIDTH / 2; + int xp, yp; + int rad = CLOCK_WIDTH / 2 - 10; + Window w = ((col == WHITE) ? win->wclockwin : win->bclockwin); + + /* Draw a clock face and the hands. */ + XCircle(w, x, y, rad, 0.0, 0.0, 1, 1, win->textcolor.pixel, GXcopy, + AllPlanes); + rad -= 8; + + XSetFont(win->display, DefaultGC(win->display, 0), + win->small->fid); + XSetForeground(win->display, DefaultGC(win->display, 0), + win->textcolor.pixel); + XSetBackground(win->display, DefaultGC(win->display, 0), + win->textback.pixel); + for (i = 1; i <= 12; i++) { + xp = x + rad * cos(PI * 3 / 2 + i * PI / 6) - 4; + yp = y + rad * sin(PI * 3 / 2 + i * PI / 6) - 5; + sprintf(buf, "%d", i); + XDrawString(win->display, w, DefaultGC(win->display, 0), + xp, yp, buf, strlen(buf)); + } + + dohands(win, col); + + if (white_running) { + hilight(win, WHITE, true); + hilight(win, BLACK, false); + } else { + hilight(win, WHITE, false); + hilight(win, BLACK, true); + } + return; +} + +void +clock_init(win, col) + windata *win; + color col; +{ + whiteseconds = blackseconds = 0; + clock_started = false; + firstmove = true; + clock_draw(win, col); + + return; +} + +void +clock_update() +{ + int now = time((long *) NULL); + int i; + + if (!clock_started) { + lastwhite = lastblack = now; + return; + } + + if (white_running) { + whiteseconds += now - lastwhite; + lastwhite = now; + dohands(win1, WHITE); + if (!oneboard) + dohands(win2, WHITE); + if (timeunit) { + i = whiteseconds / timeunit; + if ((i > 0) && (whiteseconds > i * timeunit) && + (whiteseconds < i * timeunit + 10) && + (movesperunit * i > movenum)) { + message_add(win1, + "White has exceeded his time limit\n", + true); + if (!oneboard) { + message_add(win2, + "White has exceeded his time limit\n", + true); + } + timeunit = 0; + } + } + } else { + blackseconds += now - lastblack; + lastblack = now; + dohands(win1, BLACK); + if (!oneboard) + dohands(win2, BLACK); + if (timeunit) { + i = blackseconds / timeunit; + if ((i > 0) && (blackseconds > i * timeunit) && + (blackseconds < i * timeunit + 10) && + (movesperunit * i > movenum)) { + message_add(win1, + "Black has exceeded his time limit\n", + true); + if (!oneboard) { + message_add(win2, + "Black has exceeded his time limit\n", + true); + } + timeunit = 0; + } + } + } + return; +} + +void +clock_switch() +{ + if (firstmove) { + clock_started = true; + firstmove = false; + lastwhite = lastblack = time((long *) NULL); + } + if (white_running) { + white_running = false; + lastblack = time((long *) NULL); + hilight(win1, WHITE, false); + hilight(win1, BLACK, true); + if (!oneboard) { + hilight(win2, WHITE, false); + hilight(win2, BLACK, true); + } + } else { + white_running = true; + lastwhite = time((long *) NULL); + hilight(win1, WHITE, true); + hilight(win1, BLACK, false); + if (!oneboard) { + hilight(win2, WHITE, true); + hilight(win2, BLACK, false); + } + } + return; +} + +static void +dohands(win, col) + windata *win; + color col; +{ + int cx = CLOCK_WIDTH / 2, cy = CLOCK_WIDTH / 2; + double *h = (col == WHITE) ? win->whitehands : win->blackhands; + Window w = (col == WHITE) ? win->wclockwin : win->bclockwin; + long secs = (col == WHITE) ? whiteseconds : blackseconds; + int rad, x, y, i; + + /* First erase the old hands. */ + XSetState(win->display, DefaultGC(win->display, 0), + win->textback.pixel, win->textback.pixel, + GXcopy, AllPlanes); + + rad = CLOCK_WIDTH / 2 - 30; + for (i = 0; i < 3; i++) { + x = cx + rad * sin(PI - h[i]); + y = cy + rad * cos(PI - h[i]); + XSetLineAttributes(win->display, + DefaultGC(win->display, 0), + i, LineSolid, 0, 0); + XDrawLine(win->display, w, DefaultGC(win->display, 0), + cx, cy, x, y); + rad -= 8; + } + + h[0] = (secs % 60) * 2 * PI / 60; + h[1] = ((secs / 60) % 60) * 2 * PI / 60; + h[2] = ((secs / 3600) % 12) * 2 * PI / 12; + + /* Now draw the new ones. */ + + XSetState(win->display, DefaultGC(win->display, 0), + win->textcolor.pixel, win->textback.pixel, + GXcopy, AllPlanes); + + rad = CLOCK_WIDTH / 2 - 30; + for (i = 0; i < 3; i++) { + x = cx + rad * sin(PI - h[i]); + y = cy + rad * cos(PI - h[i]); + XSetLineAttributes(win->display, + DefaultGC(win->display, 0), + i, LineSolid, 0, 0); + XDrawLine(win->display, w, DefaultGC(win->display, 0), + cx, cy, x, y); + rad -= 8; + } + XFlush(win->display); + return; +} + +static void +hilight(win, col, on) + windata *win; + color col; + bool on; +{ + Window w = (col == WHITE) ? win->wclockwin : win->bclockwin; + char *s = (col == WHITE) ? " WHITE " : " BLACK "; + int x; + + + x = XTextWidth(win->large, s, strlen(s)); + if (on) + XSetState(win->display, DefaultGC(win->display, 0), + win->textback.pixel, + win->textcolor.pixel, + GXcopy, + AllPlanes); + else + XSetState(win->display, DefaultGC(win->display, 0), + win->textcolor.pixel, + win->textback.pixel, + GXcopy, AllPlanes); + + XSetLineAttributes(win->display, DefaultGC(win->display, 0), + BORDER_WIDTH, LineSolid, CapButt, JoinMiter); + XSetFont(win->display, DefaultGC(win->display, 0), + win->large->fid); + + XDrawLine(win->display, w, DefaultGC(win->display, 0), + 0, CLOCK_HEIGHT - 26, + CLOCK_WIDTH, CLOCK_HEIGHT - 26); + + XDrawImageString(win->display, w, DefaultGC(win->display, 0), + (CLOCK_WIDTH - x) / 2, CLOCK_HEIGHT, + s, strlen(s)); + + if (on) + XSetState(win->display, DefaultGC(win->display, 0), + win->textcolor.pixel, + win->textback.pixel, + GXcopy, AllPlanes); + return; +} + diff --git a/gnu/games/chess/Xchess/control.c b/gnu/games/chess/Xchess/control.c new file mode 100644 index 000000000000..ad2e1d7994fd --- /dev/null +++ b/gnu/games/chess/Xchess/control.c @@ -0,0 +1,515 @@ +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:32 $ + * $Source: /users/faustus/xchess/RCS/control.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Deal with input from the user. + */ + +#include "xchess.h" + +move *moves; +move *foremoves; +color nexttomove = WHITE; +bool noisyflag = false; + +move *lastmove; +static move *thismove; + +static void screen_move(); + +void +button_pressed(event, win) + XEvent *event; + windata *win; +{ + int x, y; + XKeyEvent *ev = (XKeyEvent *) event; + + if (!oneboard && (win->color != nexttomove)) { + message_add(win, "Wrong player!\n", true); + return; + } + if (progflag && (nexttomove == (blackflag ? WHITE : BLACK))) { + message_add(win, "Wait for the computer...\n", true); + return; + } + if (loading_flag) { + message_add(win, "You'd better not do that now...\n", true); + return; + } + + /* Figure out what piece he is pointing at. */ + x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH); + y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH); + + if (win->flipped) { + y = SIZE - y - 1; + x = SIZE - x - 1; + } + + if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) { + fprintf(stderr, "Bad coords (%d, %d)\n", x, y); + return; + } + + if (oneboard && (chessboard->square[y][x].color != nexttomove)) { + message_add(win, "Wrong player!\n", true); + return; + } else if (!oneboard && (chessboard->square[y][x].color != + win->color)) { + message_add(win, "Can't move that\n", true); + return; + } + + thismove = alloc(move); + thismove->fromx = x; + thismove->fromy = y; + thismove->piece.color = chessboard->square[y][x].color; + thismove->piece.type = chessboard->square[y][x].type; + + if (debug) + fprintf(stderr, "%s selected his %s at (%d, %d)...\n", + colornames[(int) thismove->piece.color], + piecenames[(int) thismove->piece.type], + thismove->fromy, thismove->fromx); + return; +} + +void +button_released(event, win) + XEvent *event; + windata *win; +{ + int x, y; + XKeyEvent *ev = (XKeyEvent *) event; + + if (!thismove) { + /* fprintf(stderr, "Error: button hasn't been pressed\n"); */ + return; + } + if (loading_flag) + return; + + /* Figure out what piece he is pointing at. */ + x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH); + y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH); + + if (win->flipped) { + y = SIZE - y - 1; + x = SIZE - x - 1; + } + + if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) { + fprintf(stderr, "Bad coords (%d, %d)\n", x, y); + return; + } + + if ((thismove->fromx == x) && (thismove->fromy == y)) { + message_add(win, "Hey, you touch it, you move it, buddy.\n", + true); + return; + } + if (chessboard->square[y][x].color == thismove->piece.color) { + message_add(win, "Can't put one piece on top of another\n", + true); + return; + } + + thismove->tox = x; + thismove->toy = y; + thismove->taken.color = chessboard->square[y][x].color; + thismove->taken.type = chessboard->square[y][x].type; + if (thismove->taken.color != NONE) + thismove->type = CAPTURE; + else if ((thismove->piece.type == KING) && (thismove->fromx == 4) && + (thismove->tox == 6) && + (thismove->toy == thismove->fromy)) + thismove->type = KCASTLE; + else if ((thismove->piece.type == KING) && (thismove->tox == 2) && + (thismove->fromx == 4) && + (thismove->toy == thismove->fromy)) + thismove->type = QCASTLE; + else + thismove->type = MOVE; + + /* Now check the en-passant case... */ + if ((thismove->type == MOVE) && ((thismove->tox == thismove->fromx + 1) + || (thismove->tox == thismove->fromx - 1)) && + (thismove->piece.type == PAWN) && lastmove && + (lastmove->tox == lastmove->fromx) && (lastmove->fromx + == thismove->tox) && ((lastmove->fromy + lastmove->toy) + / 2 == thismove->toy)) { + thismove->type = CAPTURE; + thismove->enpassant = true; + thismove->taken = lastmove->piece; + } + + if (!valid_move(thismove, chessboard)) { + message_add(win, "Invalid move.\n", true); + return; + } + + if (debug) + fprintf(stderr, "\t... and moved it to (%d, %d), type %s\n", + thismove->toy, thismove->tox, + movetypenames[(int) thismove->type]); + move_piece(thismove); + + if (thismove->check) { + message_add(win1, "Check.\n", true); + if (!oneboard) { + message_add(win2, "Check.\n", true); + } + } + + if (!moves) + moves = lastmove = thismove; + else + lastmove = lastmove->next = thismove; + + if (progflag) + program_send(thismove); + + thismove = NULL; + nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE); + clock_switch(); + + return; +} + +void +prog_move(m) + move *m; +{ + if (debug) + fprintf(stderr, "program moves from (%d, %d) to (%d, %d)\n", + m->fromy, m->fromx, m->toy, m->tox); + move_piece(m); + + if (!moves) + moves = lastmove = m; + else + lastmove = lastmove->next = m; + + nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE); + clock_switch(); + + return; +} + +void +move_piece(m) + move *m; +{ + /* Update the screen... */ + screen_move(m); + + /* Move the piece on the board... */ + board_move(chessboard, m); + + /* And record it... */ + record_move(m); + + if (noisyflag) { + XBell(win1->display, 50); + XBell(win2->display, 50); + } + return; +} + +static void +screen_move(m) + move *m; +{ + piece pp; + + switch (m->type) { + case CAPTURE: + jail_add(&m->taken); + /* FALLTHRU */ + + case MOVE: + win_erasepiece(m->fromy, m->fromx, WHITE); + if (win_flashmove) + win_flash(m, WHITE); + win_drawpiece(&m->piece, m->toy, m->tox, WHITE); + if (m->enpassant) + win_erasepiece(m->toy + ((m->piece.color == WHITE) ? + 1 : -1), m->tox, WHITE); + if (!oneboard) { + win_erasepiece(m->fromy, m->fromx, BLACK); + if (win_flashmove) + win_flash(m, BLACK); + win_drawpiece(&m->piece, m->toy, m->tox, BLACK); + if (m->enpassant) + win_erasepiece(m->toy + ((m->piece.color == + WHITE) ? 1 : -1), m->tox, WHITE); + } + if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) && + (m->toy == 7)) || ((m->piece.color == WHITE) && + (m->toy == 0)))) { + pp.color = m->piece.color; + pp.type = QUEEN; + win_drawpiece(&pp, m->toy, m->tox, WHITE); + if (!oneboard) + win_drawpiece(&m->piece, m->toy, m->tox, BLACK); + } + break; + + case KCASTLE: + if (m->piece.color == WHITE) { + win_erasepiece(7, 4, WHITE); + win_erasepiece(7, 7, WHITE); + if (win_flashmove) + win_flash(m, WHITE); + win_drawpiece(&m->piece, 7, 6, WHITE); + win_drawpiece(&chessboard->square[7][7], 7, 5, WHITE); + if (!oneboard) { + win_erasepiece(7, 4, BLACK); + win_erasepiece(7, 7, BLACK); + if (win_flashmove) + win_flash(m, BLACK); + win_drawpiece(&m->piece, 7, 6, BLACK); + win_drawpiece(&chessboard->square[7][7], 7, 5, + BLACK); + } + } else { + win_erasepiece(0, 4, WHITE); + win_erasepiece(0, 7, WHITE); + if (win_flashmove) + win_flash(m, WHITE); + win_drawpiece(&m->piece, 0, 6, WHITE); + win_drawpiece(&chessboard->square[0][7], 0, 5, WHITE); + if (!oneboard) { + win_erasepiece(0, 4, BLACK); + win_erasepiece(0, 7, BLACK); + if (win_flashmove) + win_flash(m, BLACK); + win_drawpiece(&m->piece, 0, 6, BLACK); + win_drawpiece(&chessboard->square[0][7], 0, 5, + BLACK); + } + } + break; + + case QCASTLE: + if (m->piece.color == WHITE) { + win_erasepiece(7, 4, WHITE); + win_erasepiece(7, 0, WHITE); + if (win_flashmove) + win_flash(m, WHITE); + win_drawpiece(&m->piece, 7, 2, WHITE); + win_drawpiece(&chessboard->square[7][0], 7, 3, WHITE); + if (!oneboard) { + win_erasepiece(7, 4, BLACK); + win_erasepiece(7, 0, BLACK); + if (win_flashmove) + win_flash(m, BLACK); + win_drawpiece(&m->piece, 7, 2, BLACK); + win_drawpiece(&chessboard->square[7][7], 7, 3, + BLACK); + } + } else { + win_erasepiece(0, 4, WHITE); + win_erasepiece(0, 0, WHITE); + if (win_flashmove) + win_flash(m, WHITE); + win_drawpiece(&m->piece, 0, 2, WHITE); + win_drawpiece(&chessboard->square[0][0], 0, 3, WHITE); + if (!oneboard) { + win_erasepiece(0, 4, BLACK); + win_erasepiece(0, 0, BLACK); + if (win_flashmove) + win_flash(m, BLACK); + win_drawpiece(&m->piece, 0, 2, BLACK); + win_drawpiece(&chessboard->square[0][7], 0, 3, + BLACK); + } + } + break; + + default: + fprintf(stderr, "Bad move type %d\n", m->type); + } + return; +} + +/* Retract the last move made... */ + +void +replay() +{ + move *m = lastmove, bm; + + memset(&bm, 0, sizeof(bm)); + switch (m->type) { + case MOVE: + bm.type = MOVE; + bm.piece = m->piece; + bm.fromx = m->tox; + bm.fromy = m->toy; + bm.tox = m->fromx; + bm.toy = m->fromy; + board_move(chessboard, &bm); + screen_move(&bm); + break; + + case CAPTURE: + bm.type = MOVE; + bm.piece = m->piece; + bm.fromx = m->tox; + bm.fromy = m->toy; + bm.tox = m->fromx; + bm.toy = m->fromy; + board_move(chessboard, &bm); + screen_move(&bm); + chessboard->square[m->toy][m->tox] = m->taken; + bm.piece = m->taken; + bm.fromx = bm.tox = m->tox; + bm.fromy = bm.toy = m->toy; + screen_move(&bm); + jail_remove(&m->taken); + break; + + case KCASTLE: + bm.type = MOVE; + bm.piece.type = KING; + bm.piece.color = m->piece.color; + bm.fromx = 6; + bm.tox = 4; + bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0; + board_move(chessboard, &bm); + screen_move(&bm); + bm.type = MOVE; + bm.piece.type = ROOK; + bm.piece.color = m->piece.color; + bm.fromx = 5; + bm.tox = 7; + bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0; + board_move(chessboard, &bm); + screen_move(&bm); + if (m->piece.color == WHITE) + chessboard->white_cant_castle_k = false; + else + chessboard->black_cant_castle_k = false; + break; + + case QCASTLE: + bm.type = MOVE; + bm.piece.type = KING; + bm.piece.color = m->piece.color; + bm.fromx = 2; + bm.tox = 4; + bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0; + board_move(chessboard, &bm); + screen_move(&bm); + bm.type = MOVE; + bm.piece.type = ROOK; + bm.piece.color = m->piece.color; + bm.fromx = 3; + bm.tox = 0; + bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0; + board_move(chessboard, &bm); + screen_move(&bm); + if (m->piece.color == WHITE) + chessboard->white_cant_castle_q = false; + else + chessboard->black_cant_castle_q = false; + break; + } + record_back(); + + nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE); + clock_switch(); + + if (!moves->next) { + moves->next = foremoves; + foremoves = moves; + moves = lastmove = NULL; + } else { + for (m = moves; m->next; m = m->next) + lastmove = m; + lastmove->next->next = foremoves; + foremoves = lastmove->next; + lastmove->next = NULL; + } + + if (progflag) + program_undo(); + + return; +} + +/* Put back the last move undone. */ + +void +forward() +{ + prog_move(foremoves); + foremoves = foremoves->next; + return; +} + +/* End the game. */ + +void +cleanup(s) + char *s; +{ + if (progflag) + program_end(); + record_end(s); + XSync(win1->display, 0); + if (!oneboard) { + XSync(win2->display, 0); + } + exit(0); +} + +void +restart() +{ + moves = lastmove = thismove = NULL; + nexttomove = WHITE; + + clock_init(win1, WHITE); + clock_init(win1, BLACK); + jail_init(win1); + if (!oneboard) { + clock_init(win2, WHITE); + clock_init(win2, BLACK); + jail_init(win2); + } + board_init(chessboard); + win_restart(); + record_reset(); + if (progflag) { + program_end(); + program_init(progname); + } + return; +} + diff --git a/gnu/games/chess/Xchess/jail.c b/gnu/games/chess/Xchess/jail.c new file mode 100644 index 000000000000..e5e60642430a --- /dev/null +++ b/gnu/games/chess/Xchess/jail.c @@ -0,0 +1,327 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.3 $ on $Date: 86/11/26 12:09:54 $ + * $Source: /users/faustus/xchess/RCS/jail.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + */ + +#include "xchess.h" + +#include "pawn_small.bitmap" +#include "rook_small.bitmap" +#include "knight_small.bitmap" +#include "bishop_small.bitmap" +#include "queen_small.bitmap" +#include "king_small.bitmap" + +#include "pawn_small_outline.bitmap" +#include "rook_small_outline.bitmap" +#include "knight_small_outline.bitmap" +#include "bishop_small_outline.bitmap" +#include "queen_small_outline.bitmap" +#include "king_small_outline.bitmap" + +static bool pos[32]; + +static piecetype pcs[] = { KING, QUEEN, ROOK, ROOK, BISHOP, BISHOP, KNIGHT, + KNIGHT, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN } ; + +extern int piecepos(); +extern char *bitsget(); + +void +jail_init(win) + windata *win; +{ + int i; + + for (i = 0; i < 32; i++) + pos[i] = false; + jail_draw(win); + return; +} + +#define JAIL_HEADER "Captured Pieces" + +void +jail_draw(win) + windata *win; +{ + int i; + char *bits; + Pixmap tmpPM; + piece p; + + i = XTextWidth(win->large, JAIL_HEADER, strlen(JAIL_HEADER)); + XSetFont(win->display, DefaultGC(win->display, 0), + win->large->fid); + XSetForeground(win->display, DefaultGC(win->display, 0), + win->textcolor.pixel); + XSetBackground(win->display, DefaultGC(win->display, 0), + win->textback.pixel); + + XDrawImageString(win->display, win->jailwin, + DefaultGC(win->display, 0), + (JAIL_WIDTH - i) / 2, 20, JAIL_HEADER, + strlen(JAIL_HEADER)); + + XSetForeground(win->display, DefaultGC(win->display, 0), + win->blackpiece.pixel); + XSetBackground(win->display, DefaultGC(win->display, 0), + win->textback.pixel); + XSetFillStyle(win->display, DefaultGC(win->display, 0), + FillSolid); + XSetFunction(win->display, DefaultGC(win->display, 0), + GXcopy); + + for (i = 0; i < 16; i++) + if (pos[i]) { + p.color = WHITE; + p.type = pcs[i]; + bits = bitsget(&p); + tmpPM = XCreateBitmapFromData(win->display, + win->jailwin, bits, + 32, 32); + + XCopyPlane(win->display, tmpPM, win->jailwin, + DefaultGC(win->display, 0), + 0, 0, 32, 32, + 5 + (i % 8) * 32, 25 + (i / 8) * 32, + 1); + XFreePixmap(win->display, tmpPM); + } else { + XFillRectangle(win->display, win->jailwin, + DefaultGC(win->display, 0), + 5 + (i % 8) * 32, + 25 + (i / 8) * 32, + 32, 32); + } + for (i = 0; i < 16; i++) + if (pos[i + 16]) { + p.color = BLACK; + p.type = pcs[i]; + bits = bitsget(&p); + tmpPM = XCreateBitmapFromData(win->display, + win->jailwin, bits, + 32, 32); + + XCopyPlane(win->display, tmpPM, win->jailwin, + DefaultGC(win->display, 0), + 0, 0, 32, 32, + 5 + (i % 8) * 32, 94 + (i / 8) * 32, + 1); + XFreePixmap(win->display, tmpPM); + } else { + XFillRectangle(win->display, win->jailwin, + DefaultGC(win->display, 0), + 5 + (i % 8) * 32, 94 + (i / 8) * 32, + 32, 32); + } + + return; +} + +void +jail_add(p) + piece *p; +{ + int i = piecepos(p, false); + char *bits; + Pixmap tmpPM; + + pos[i] = true; + + bits = bitsget(p); + + XSetState(win1->display, DefaultGC(win1->display, 0), + win1->blackpiece.pixel, + win1->textback.pixel, + GXcopy, + AllPlanes); + + tmpPM = XCreateBitmapFromData(win1->display, + win1->jailwin, bits, + 32, 32); + + XCopyPlane(win1->display, tmpPM, win1->jailwin, + DefaultGC(win1->display, 0), + 0, 0, 32, 32, + 5 + (i % 8) * 32, ((i >= 16) ? 30 : 25) + (i / 8) * 32, + 1); + XFreePixmap(win1->display, tmpPM); + + if (!oneboard) { + XSetState(win2->display, DefaultGC(win2->display, 0), + win2->blackpiece.pixel, + win2->textback.pixel, + GXcopy, + AllPlanes); + + + tmpPM = XCreateBitmapFromData(win2->display, + win2->jailwin, bits, + 32, 32); + + XCopyPlane(win2->display, tmpPM, win2->jailwin, + DefaultGC(win2->display, 0), + 0, 0, 32, 32, + 5 + (i % 8) * 32, ((i >= 16) ? 30 : 25) + (i / 8) * 32, + 1); + XFreePixmap(win2->display, tmpPM); + } + + return; +} + +void +jail_remove(p) + piece *p; +{ + int i = piecepos(p, true); + + pos[i] = false; + + + XSetForeground(win1->display, + DefaultGC(win1->display, 0), + win1->blackpiece.pixel); + XSetBackground(win1->display, + DefaultGC(win1->display, 0), + win1->textback.pixel); + XSetFillStyle(win1->display, + DefaultGC(win1->display, 0), + FillSolid); + + XFillRectangle(win1->display, win1->jailwin, + DefaultGC(win1->display, 0), + 5 + (i % 8) * 32, + ((i >= 16) ? 30 : 25) + (i / 8) * 32, + 32, 32); + + if (!oneboard) { + XSetForeground(win2->display, + DefaultGC(win2->display, 0), + win2->blackpiece.pixel); + XSetBackground(win2->display, + DefaultGC(win2->display, 0), + win2->textback.pixel); + XSetFillStyle(win2->display, + DefaultGC(win2->display, 0), + FillSolid); + + XFillRectangle(win2->display, win2->jailwin, + DefaultGC(win2->display, 0), + 5 + (i % 8) * 32, + ((i >= 16) ? 30 : 25) + (i / 8) * 32, + 32, 32); + } + + return; +} + +static char *bitsget(p) + piece *p; +{ + char *bits; + + switch (p->type) { + case PAWN: + bits = (p->color == WHITE) ? pawn_small_outline_bits : + pawn_small_bits; + break; + + case ROOK: + bits = (p->color == WHITE) ? rook_small_outline_bits : + rook_small_bits; + break; + + case KNIGHT: + bits = (p->color == WHITE) ? knight_small_outline_bits : + knight_small_bits; + break; + + case BISHOP: + bits = (p->color == WHITE) ? bishop_small_outline_bits : + bishop_small_bits; + break; + + case QUEEN: + bits = (p->color == WHITE) ? queen_small_outline_bits : + queen_small_bits; + break; + + case KING: + bits = (p->color == WHITE) ? king_small_outline_bits : + king_small_bits; + break; + } + return (bits); +} + +static int +piecepos(p, there) + piece *p; + bool there; +{ + int i, base = (p->color == WHITE) ? 0 : 16; + + switch (p->type) { + case PAWN: + for (i = base + 8; (i < base + 15) && pos[i]; i++) + ; + if (there && !pos[i]) + i--; + break; + + case KING: + /* Hmm... */ + i = base; + break; + + case QUEEN: + i = base + 1; + break; + + case ROOK: + i = base + 2; + if ((there && pos[i + 1]) || (!there && pos[i])) + i++; + break; + + case BISHOP: + i = base + 4; + if ((there && pos[i + 1]) || (!there && pos[i])) + i++; + break; + + case KNIGHT: + i = base + 6; + if ((there && pos[i + 1]) || (!there && pos[i])) + i++; + break; + } + return (i); +} diff --git a/gnu/games/chess/Xchess/king.bitmap b/gnu/games/chess/Xchess/king.bitmap new file mode 100644 index 000000000000..dd9178a2ed9e --- /dev/null +++ b/gnu/games/chess/Xchess/king.bitmap @@ -0,0 +1,71 @@ + +#define king_width 80 +#define king_height 80 +static char king_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x30, 0x18, 0x00, 0xfc, 0x1f, 0x00, + 0x00, 0xfe, 0x7f, 0x00, 0xb8, 0x3b, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, + 0xff, 0x00, 0xb8, 0x3b, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x03, + 0xb8, 0x3b, 0xe0, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0x0f, 0xb8, 0x3b, + 0xf0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x1f, 0xb8, 0x3b, 0xf8, 0xff, + 0xf8, 0x07, 0xe0, 0x1f, 0xc0, 0x3f, 0xb8, 0x3b, 0xfc, 0x07, 0xe2, 0x07, + 0xf0, 0xcf, 0x9f, 0x7f, 0x30, 0x18, 0xfe, 0xf3, 0xcf, 0x0f, 0xf0, 0xe7, + 0x3f, 0xfe, 0xf0, 0x1f, 0x7e, 0xfc, 0xdf, 0x0f, 0xf0, 0xf3, 0xff, 0xfc, + 0xf1, 0x1f, 0x3f, 0xff, 0x9f, 0x0f, 0xf8, 0xfb, 0xff, 0xfd, 0xf3, 0x9f, + 0xbf, 0xff, 0xbf, 0x1f, 0xf8, 0xf9, 0xff, 0xf9, 0xe3, 0x8f, 0xdf, 0xff, + 0x3f, 0x1f, 0xf8, 0xfd, 0xff, 0xf3, 0xef, 0xcf, 0xcf, 0xff, 0x7f, 0x1f, + 0xf8, 0xfd, 0xff, 0xe7, 0xef, 0xef, 0xef, 0xff, 0x7f, 0x1f, 0xfc, 0xfd, + 0xff, 0xcf, 0xff, 0xff, 0xe7, 0x3f, 0x7c, 0x3f, 0xfc, 0x3c, 0xfc, 0xdf, + 0xff, 0xfe, 0xf3, 0x3d, 0x7c, 0x3f, 0xfc, 0x3e, 0xfc, 0x9e, 0x7f, 0xfc, + 0xf9, 0x39, 0x7c, 0x3f, 0xfc, 0x3e, 0x7c, 0xbe, 0x3f, 0xf8, 0xf9, 0x3b, + 0x7c, 0x3f, 0xfc, 0x3e, 0x78, 0x3f, 0x7f, 0xfc, 0xfc, 0x3b, 0x7f, 0x3f, + 0xfc, 0xfe, 0x7b, 0x7f, 0xff, 0xfe, 0xfe, 0x9b, 0x7f, 0x3f, 0xf8, 0xfe, + 0xbb, 0x7f, 0xfe, 0x7f, 0xfe, 0xdb, 0x79, 0x1f, 0xf8, 0xfe, 0xb3, 0xff, + 0xfe, 0x7f, 0xff, 0xcb, 0x7c, 0x1f, 0xf8, 0x9e, 0xb7, 0xff, 0xfe, 0x7f, + 0xff, 0x2b, 0x3e, 0x1f, 0xf8, 0x3e, 0xa6, 0xff, 0xfc, 0x7f, 0xff, 0xa3, + 0xbf, 0x1f, 0xf8, 0xfe, 0xa8, 0xff, 0xfd, 0x3e, 0xff, 0xd3, 0xbf, 0x1f, + 0xf8, 0xfd, 0x83, 0xff, 0x7d, 0xbc, 0xff, 0xc3, 0xbf, 0x1f, 0xf0, 0xfd, + 0x8f, 0xff, 0x39, 0xb8, 0xff, 0xe3, 0xbf, 0x1f, 0xf0, 0xfd, 0x9f, 0xff, + 0x7b, 0xbc, 0xff, 0xf1, 0x9f, 0x0f, 0xf0, 0xf9, 0xbf, 0xff, 0xfb, 0xbe, + 0xff, 0xfd, 0xdf, 0x0f, 0xf0, 0xfb, 0x3f, 0xff, 0xf3, 0x9f, 0xff, 0xfd, + 0xdf, 0x0f, 0xf0, 0xf3, 0x7f, 0xff, 0xf7, 0xdf, 0xff, 0xfc, 0xdf, 0x0f, + 0xe0, 0xf7, 0x7f, 0xfe, 0xf7, 0xdf, 0xff, 0xfe, 0xdf, 0x07, 0xe0, 0xf7, + 0xff, 0xfe, 0xf7, 0xdf, 0x7f, 0xfe, 0xcf, 0x07, 0xe0, 0xe7, 0xff, 0xfe, + 0xf7, 0xdf, 0x7f, 0xff, 0xef, 0x07, 0xc0, 0xef, 0xff, 0xfc, 0xef, 0xee, + 0x7f, 0xff, 0xe7, 0x03, 0xc0, 0xcf, 0xff, 0xfd, 0x6f, 0xec, 0x3f, 0xff, + 0xf7, 0x03, 0x80, 0xdf, 0xff, 0xf9, 0xef, 0xee, 0xbf, 0xff, 0xf3, 0x01, + 0x80, 0x9f, 0xff, 0xfb, 0xef, 0xef, 0x9f, 0xff, 0xfb, 0x01, 0x00, 0xbf, + 0xff, 0xfb, 0xef, 0xef, 0xdf, 0xff, 0xf9, 0x00, 0x00, 0x7e, 0xff, 0xf3, + 0xef, 0xef, 0xdf, 0xff, 0x7e, 0x00, 0x00, 0x7e, 0xfe, 0xff, 0xef, 0xef, + 0xff, 0x7f, 0x7e, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xef, 0xef, 0xff, 0x7f, + 0x3f, 0x00, 0x00, 0xfc, 0xf9, 0xff, 0xef, 0xef, 0xff, 0x3f, 0x1f, 0x00, + 0x00, 0xf8, 0xfb, 0x03, 0xe0, 0x0f, 0x00, 0x9f, 0x1f, 0x00, 0x00, 0xf0, + 0x03, 0xf8, 0xff, 0xff, 0x7f, 0xc0, 0x0f, 0x00, 0x00, 0xe0, 0xff, 0xbf, + 0xf7, 0xde, 0xfb, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0x1d, 0x63, 0x8c, + 0x71, 0xff, 0x03, 0x00, 0x00, 0x80, 0xef, 0xb8, 0xf7, 0xde, 0x3b, 0xee, + 0x01, 0x00, 0x00, 0x00, 0xc7, 0xfd, 0xff, 0xff, 0x7f, 0xc7, 0x00, 0x00, + 0x00, 0x00, 0xee, 0xff, 0x00, 0x00, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x03, 0xfe, 0xff, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf8, + 0x7f, 0xfc, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xf0, + 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xff, 0x07, 0xc0, 0xff, 0x63, + 0x00, 0x00, 0x00, 0x00, 0x06, 0xff, 0x1f, 0xf0, 0xff, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x06, 0xfc, 0x7f, 0xfc, 0x3f, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xff, 0xff, 0xff, 0xff, 0x60, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xff, + 0x00, 0x00, 0xfc, 0x63, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0xfe, 0xff, + 0x01, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x06, 0xf8, 0xff, 0xff, 0x7f, 0x60, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/king_mask.bitmap b/gnu/games/chess/Xchess/king_mask.bitmap new file mode 100644 index 000000000000..e1bb523cad10 --- /dev/null +++ b/gnu/games/chess/Xchess/king_mask.bitmap @@ -0,0 +1,71 @@ + +#define king_mask_width 80 +#define king_mask_height 80 +static char king_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0xf8, 0x3f, 0x00, 0xfe, + 0x3f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xfc, 0x3f, 0x80, 0xff, 0x7f, 0x00, + 0x80, 0xff, 0xff, 0x01, 0xfc, 0x7f, 0xc0, 0xff, 0xff, 0x00, 0xc0, 0xff, + 0xff, 0x07, 0xfc, 0x7f, 0xe0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x1f, + 0xfc, 0x7f, 0xf8, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x3f, 0xfc, 0x7f, + 0xfc, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x7f, 0xfc, 0x7f, 0xfe, 0xff, + 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x07, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/king_outline.bitmap b/gnu/games/chess/Xchess/king_outline.bitmap new file mode 100644 index 000000000000..173651c28efa --- /dev/null +++ b/gnu/games/chess/Xchess/king_outline.bitmap @@ -0,0 +1,71 @@ + +#define king_outline_width 80 +#define king_outline_height 80 +static char king_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x0c, 0x60, 0x00, 0xfc, 0x1f, 0x00, + 0x00, 0x0e, 0x70, 0x00, 0x84, 0x43, 0x00, 0x07, 0x70, 0x00, 0x00, 0x03, + 0xc0, 0x00, 0xc4, 0x46, 0x80, 0x01, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x03, + 0x44, 0x44, 0xe0, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x0e, 0x44, 0x44, + 0x30, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x18, 0x44, 0x44, 0x18, 0x00, + 0x07, 0x06, 0x20, 0xe0, 0x3f, 0x30, 0xc4, 0x46, 0x0c, 0xf8, 0x1d, 0x04, + 0x30, 0x30, 0x60, 0x60, 0x8c, 0x63, 0x06, 0x0c, 0x30, 0x0c, 0x10, 0x18, + 0xc0, 0xc1, 0x08, 0x20, 0x82, 0x03, 0x20, 0x0c, 0x10, 0x0c, 0x00, 0x83, + 0x09, 0x20, 0xc3, 0x00, 0x60, 0x08, 0x18, 0x04, 0x00, 0x02, 0x8b, 0xa3, + 0x41, 0x00, 0x40, 0x18, 0x08, 0x06, 0x00, 0x06, 0x7a, 0xb6, 0x20, 0x00, + 0xc0, 0x10, 0x08, 0x02, 0x00, 0x0c, 0x3e, 0x7c, 0x30, 0x00, 0x80, 0x10, + 0x08, 0x02, 0x00, 0x18, 0x18, 0x18, 0x10, 0x00, 0x80, 0x10, 0x0c, 0x02, + 0x00, 0x30, 0x00, 0x00, 0x18, 0xc0, 0x83, 0x30, 0x04, 0xc3, 0x03, 0x20, + 0x00, 0x01, 0x0c, 0xc2, 0x83, 0x20, 0x04, 0xc1, 0x03, 0x61, 0x80, 0x03, + 0x06, 0xc6, 0x83, 0x20, 0x04, 0xc1, 0x83, 0x41, 0xc0, 0x07, 0x06, 0xc4, + 0x83, 0x20, 0x04, 0xc1, 0x87, 0xc0, 0x80, 0x03, 0x03, 0xc4, 0x80, 0x20, + 0x0c, 0x01, 0x84, 0x80, 0x00, 0x01, 0x01, 0x64, 0x80, 0x30, 0x08, 0x01, + 0x44, 0x80, 0x01, 0x80, 0x01, 0x24, 0x86, 0x10, 0x08, 0x01, 0x4c, 0x00, + 0x01, 0x80, 0x00, 0x34, 0x83, 0x10, 0x08, 0x61, 0x48, 0x00, 0x01, 0x80, + 0x00, 0xd4, 0xc1, 0x10, 0x08, 0xc1, 0x59, 0x00, 0x03, 0x80, 0x00, 0x5c, + 0x40, 0x10, 0x08, 0x01, 0x57, 0x00, 0x02, 0xc1, 0x00, 0x2c, 0x40, 0x10, + 0x18, 0x02, 0x7c, 0x00, 0x82, 0x43, 0x00, 0x3c, 0x40, 0x18, 0x10, 0x02, + 0x70, 0x00, 0xc6, 0x47, 0x00, 0x1c, 0x40, 0x18, 0x10, 0x02, 0x60, 0x00, + 0x84, 0x43, 0x00, 0x0e, 0x60, 0x08, 0x10, 0x06, 0x40, 0x00, 0x04, 0x41, + 0x00, 0x02, 0x20, 0x08, 0x10, 0x04, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x02, + 0x20, 0x0c, 0x30, 0x0c, 0x80, 0x00, 0x08, 0x20, 0x00, 0x03, 0x20, 0x0c, + 0x20, 0x08, 0x80, 0x01, 0x08, 0x20, 0x00, 0x01, 0x20, 0x04, 0x20, 0x08, + 0x00, 0x01, 0x08, 0x20, 0x80, 0x01, 0x30, 0x04, 0x60, 0x18, 0x00, 0x01, + 0x08, 0x20, 0x80, 0x00, 0x10, 0x06, 0x40, 0x10, 0x00, 0x03, 0x10, 0x11, + 0x80, 0x00, 0x18, 0x02, 0xc0, 0x30, 0x00, 0x02, 0x90, 0x13, 0xc0, 0x00, + 0x08, 0x03, 0x80, 0x20, 0x00, 0x06, 0x10, 0x11, 0x40, 0x00, 0x04, 0x01, + 0x80, 0x61, 0x00, 0x04, 0x10, 0x10, 0x60, 0x00, 0x84, 0x01, 0x00, 0x41, + 0x00, 0x04, 0x10, 0x10, 0x20, 0x00, 0xc6, 0x00, 0x00, 0x83, 0x00, 0x0c, + 0x10, 0x10, 0x20, 0x00, 0x41, 0x00, 0x00, 0x82, 0x01, 0x00, 0x10, 0x10, + 0x00, 0x80, 0x61, 0x00, 0x00, 0x06, 0x01, 0x00, 0x10, 0x10, 0x00, 0x80, + 0x30, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x10, 0x10, 0x00, 0xc0, 0x10, 0x00, + 0x00, 0x18, 0x02, 0xff, 0x1f, 0xf0, 0xff, 0x60, 0x18, 0x00, 0x00, 0x30, + 0xfe, 0x01, 0x00, 0x00, 0x80, 0x3f, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x40, + 0x08, 0x21, 0x04, 0x00, 0x06, 0x00, 0x00, 0xc0, 0x00, 0xe2, 0x9c, 0x73, + 0x8e, 0x00, 0x03, 0x00, 0x00, 0x80, 0x11, 0x47, 0x08, 0x21, 0xc4, 0x11, + 0x01, 0x00, 0x00, 0x00, 0x3b, 0x02, 0x00, 0x00, 0x80, 0xb8, 0x00, 0x00, + 0x00, 0x00, 0x12, 0x00, 0xff, 0xff, 0x03, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x02, 0xfc, 0x01, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x07, + 0x80, 0x03, 0x80, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xe0, 0x0f, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0xf8, 0x3f, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0xe0, 0x0f, 0x00, 0x5f, 0x00, 0x00, + 0x00, 0x00, 0xfa, 0x03, 0x80, 0x03, 0xc0, 0x5f, 0x00, 0x00, 0x00, 0x00, + 0xfa, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, + 0xff, 0xff, 0x03, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfc, 0x01, 0x00, + 0xfe, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x07, 0x00, 0x00, 0x80, 0x5f, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/king_small.bitmap b/gnu/games/chess/Xchess/king_small.bitmap new file mode 100644 index 000000000000..38bb2b7e88b8 --- /dev/null +++ b/gnu/games/chess/Xchess/king_small.bitmap @@ -0,0 +1,15 @@ + +#define king_small_width 32 +#define king_small_height 32 +static char king_small_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x80, 0x9f, 0x00, 0x00, 0x70, 0x20, 0x00, + 0x00, 0x0c, 0x40, 0x00, 0x00, 0x02, 0x80, 0x01, 0x80, 0x01, 0x00, 0x03, + 0x40, 0x00, 0x00, 0x06, 0x40, 0x60, 0x30, 0x08, 0x20, 0x60, 0x30, 0x10, + 0x20, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x80, + 0x10, 0x00, 0x02, 0x80, 0x10, 0x00, 0x01, 0x80, 0x10, 0x01, 0x01, 0x80, + 0x10, 0x03, 0x1f, 0x84, 0x10, 0x02, 0x00, 0x84, 0x10, 0x06, 0x00, 0x86, + 0x20, 0x1c, 0x00, 0x42, 0x20, 0xf0, 0xff, 0x43, 0x20, 0x00, 0x00, 0x40, + 0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00, 0x18, + 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/king_small_outline.bitmap b/gnu/games/chess/Xchess/king_small_outline.bitmap new file mode 100644 index 000000000000..18d569e9d7b9 --- /dev/null +++ b/gnu/games/chess/Xchess/king_small_outline.bitmap @@ -0,0 +1,15 @@ + +#define king_small_outline_width 32 +#define king_small_outline_height 32 +static char king_small_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x90, 0x00, 0x06, 0x10, 0xb1, 0x00, + 0x22, 0x12, 0xe1, 0x00, 0x24, 0x92, 0x9f, 0x00, 0x40, 0x72, 0xa0, 0x50, + 0x04, 0x0e, 0x40, 0x50, 0x40, 0x02, 0x80, 0x71, 0xc8, 0x01, 0x00, 0x73, + 0xd8, 0x00, 0x00, 0x46, 0xd8, 0x60, 0x30, 0x08, 0xa0, 0x60, 0x30, 0x10, + 0x20, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x80, + 0x10, 0x00, 0x02, 0x80, 0x10, 0x00, 0x01, 0x80, 0x10, 0x01, 0x01, 0x80, + 0x10, 0x03, 0x1f, 0x84, 0x10, 0x02, 0x00, 0x84, 0x10, 0x06, 0x00, 0x86, + 0x20, 0x1c, 0x00, 0x42, 0x20, 0xf0, 0xff, 0x43, 0x20, 0x00, 0x00, 0x40, + 0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00, 0x18, + 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/knight.bitmap b/gnu/games/chess/Xchess/knight.bitmap new file mode 100644 index 000000000000..c5b1de1997f4 --- /dev/null +++ b/gnu/games/chess/Xchess/knight.bitmap @@ -0,0 +1,71 @@ + +#define knight_width 80 +#define knight_height 80 +static char knight_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0xfe, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xf8, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x0f, 0xfc, 0xe3, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xe1, 0xf3, 0xcf, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xfd, + 0xff, 0x1f, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0xfe, 0x7f, + 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0xff, 0xfc, 0x07, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x7f, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x1f, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x03, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0x9f, 0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0xff, 0x07, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfc, 0x07, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xfd, 0x01, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xff, 0xfb, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xbf, 0xff, 0xf3, 0x03, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x9f, + 0xff, 0xf7, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xef, + 0x07, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x7f, 0xf3, 0xff, 0xcf, 0x7f, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0x1f, 0xfd, 0xff, 0xdf, 0x07, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0x83, 0xff, 0xf3, 0x9f, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x7f, + 0x80, 0xff, 0xf9, 0xbf, 0x0f, 0x00, 0xf0, 0xff, 0xff, 0x00, 0x80, 0x7f, + 0xfc, 0x7f, 0xff, 0x01, 0xf8, 0x3f, 0x7f, 0x00, 0x80, 0x81, 0xff, 0x7f, + 0x1e, 0x00, 0x18, 0x9f, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0xfe, 0x07, + 0x98, 0x8f, 0x1f, 0x00, 0xc0, 0xff, 0xcf, 0x7f, 0x3e, 0x00, 0xf8, 0x87, + 0x0f, 0x00, 0xe0, 0xff, 0xe3, 0xff, 0xfe, 0x07, 0xf0, 0xc3, 0x07, 0x00, + 0xf0, 0x1f, 0xfc, 0xff, 0x3c, 0x00, 0xf0, 0xe1, 0x03, 0x00, 0xf0, 0xc0, + 0xff, 0xff, 0xfc, 0x0f, 0x60, 0xe0, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0x7c, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xfc, 0x0f, + 0x00, 0x70, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xf9, 0x0f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xf9, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x1f, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x01, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x3f, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xf3, 0x01, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf3, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf3, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x01, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf3, 0x3f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf3, 0x01, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/knight_mask.bitmap b/gnu/games/chess/Xchess/knight_mask.bitmap new file mode 100644 index 000000000000..97d288c60554 --- /dev/null +++ b/gnu/games/chess/Xchess/knight_mask.bitmap @@ -0,0 +1,71 @@ + +#define knight_mask_width 80 +#define knight_mask_height 80 +static char knight_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf8, 0xff, 0xff, 0xff, + 0xc7, 0xff, 0xff, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0xff, 0xc1, 0xff, + 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f, + 0xfc, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xdf, + 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xef, 0x1f, 0x00, + 0xf8, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xf7, 0x0f, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xfb, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0xf0, 0xf9, 0x03, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0xf8, 0x01, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xf8, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/knight_outline.bitmap b/gnu/games/chess/Xchess/knight_outline.bitmap new file mode 100644 index 000000000000..a1ab938b773f --- /dev/null +++ b/gnu/games/chess/Xchess/knight_outline.bitmap @@ -0,0 +1,71 @@ + +#define knight_outline_width 80 +#define knight_outline_height 80 +static char knight_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf9, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x80, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xf0, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x58, 0x07, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x4c, + 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x78, 0x07, 0x00, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x23, 0xe0, 0x01, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, + 0x00, 0xc0, 0x08, 0x00, 0x00, 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, + 0x04, 0x00, 0x00, 0x40, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x30, 0x02, 0x00, + 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x20, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x07, 0x00, + 0x00, 0x26, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x1f, 0x00, 0x00, 0x09, 0x40, 0x00, + 0x00, 0x18, 0x08, 0x00, 0x02, 0x00, 0x80, 0x05, 0xc0, 0x00, 0x00, 0x0c, + 0x0c, 0x00, 0x3e, 0x00, 0x80, 0x00, 0x80, 0x00, 0xc0, 0x03, 0x06, 0x00, + 0x04, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x70, 0x01, 0xc3, 0x00, 0x7c, 0x00, + 0x60, 0x00, 0x00, 0x03, 0x1e, 0x81, 0x41, 0x00, 0x04, 0x00, 0x20, 0x00, + 0x00, 0xce, 0x83, 0x61, 0x60, 0x00, 0xfc, 0x00, 0x30, 0x00, 0x80, 0x7f, + 0x80, 0x1c, 0x30, 0x00, 0x08, 0x00, 0x10, 0xe0, 0xc1, 0x00, 0x80, 0x07, + 0x10, 0x00, 0xf8, 0x01, 0x18, 0x30, 0x61, 0x00, 0x80, 0x00, 0x08, 0x00, + 0x10, 0x00, 0x08, 0x98, 0x31, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0xf0, 0x07, + 0x08, 0x8c, 0x18, 0x00, 0x40, 0x00, 0x03, 0x00, 0x20, 0x00, 0x18, 0x86, + 0x0c, 0x00, 0x60, 0xc0, 0x01, 0x00, 0xe0, 0x07, 0x10, 0xc3, 0x06, 0x00, + 0x30, 0x30, 0x00, 0x00, 0x20, 0x00, 0xf0, 0x61, 0x02, 0x00, 0x10, 0x1e, + 0x00, 0x00, 0xe0, 0x0f, 0x60, 0x30, 0x02, 0x00, 0x98, 0x03, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x10, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xc0, 0x0f, + 0x00, 0xb0, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/knight_small.bitmap b/gnu/games/chess/Xchess/knight_small.bitmap new file mode 100644 index 000000000000..77c74517f0f6 --- /dev/null +++ b/gnu/games/chess/Xchess/knight_small.bitmap @@ -0,0 +1,15 @@ + +#define knight_small_width 32 +#define knight_small_height 32 +static char knight_small_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0xee, 0x7f, 0x02, + 0x00, 0xfe, 0x7f, 0x01, 0x00, 0xff, 0xff, 0x04, 0x00, 0xff, 0xff, 0x02, + 0x80, 0xff, 0xff, 0x09, 0xc0, 0xfc, 0xff, 0x07, 0xe0, 0xfc, 0xff, 0x11, + 0xe0, 0xff, 0xff, 0x0d, 0xe0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x3f, + 0xf0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x07, + 0xfc, 0xc7, 0xff, 0x7f, 0xfe, 0xc1, 0xff, 0x07, 0xfa, 0xc1, 0xff, 0x7f, + 0xce, 0xc0, 0xff, 0x07, 0x6c, 0xc0, 0xff, 0x7f, 0x28, 0xe0, 0xff, 0x07, + 0x00, 0xe0, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x7f, + 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0x0f, + 0x00, 0xf8, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/knight_small_outline.bitmap b/gnu/games/chess/Xchess/knight_small_outline.bitmap new file mode 100644 index 000000000000..c0e738c6db4c --- /dev/null +++ b/gnu/games/chess/Xchess/knight_small_outline.bitmap @@ -0,0 +1,15 @@ + +#define knight_small_outline_width 32 +#define knight_small_outline_height 32 +static char knight_small_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x00, 0x00, 0xee, 0x7f, 0x02, + 0x00, 0x3a, 0x40, 0x01, 0x00, 0x03, 0xc0, 0x04, 0x00, 0x01, 0x80, 0x02, + 0x80, 0x01, 0x80, 0x09, 0xc0, 0x0c, 0x00, 0x07, 0x60, 0x0c, 0x00, 0x11, + 0x20, 0x00, 0x00, 0x0d, 0x20, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x3e, + 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x7e, 0x18, 0x7c, 0x00, 0x04, + 0x0c, 0x47, 0x00, 0x7c, 0x06, 0x41, 0x00, 0x04, 0xf2, 0x41, 0x00, 0x7c, + 0xde, 0x40, 0x00, 0x04, 0x6c, 0x40, 0x00, 0x7c, 0x28, 0x60, 0x00, 0x04, + 0x00, 0x20, 0x00, 0x7c, 0x00, 0x20, 0x00, 0x08, 0x00, 0x30, 0x00, 0x78, + 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x78, 0x00, 0x18, 0x00, 0x08, + 0x00, 0x08, 0x00, 0x78, 0x00, 0x0c, 0x00, 0x08, 0x00, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/message.c b/gnu/games/chess/Xchess/message.c new file mode 100644 index 000000000000..8b85e9c77f83 --- /dev/null +++ b/gnu/games/chess/Xchess/message.c @@ -0,0 +1,101 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/26 12:10:22 $ + * $Source: /users/faustus/xchess/RCS/message.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Do stuff with the message window. Font 0 is the normal font, font 1 + * is large, and font 2 is normal red. + */ + +#include "xchess.h" + +#define MESSAGE_HEADER "\n1 XChess Messages0\n" + +void +message_init(win) + windata *win; +{ + TxtGrab(win->display, win->messagewin, "xchess", win->medium, + win->textback.pixel, win->textcolor.pixel, + win->cursorcolor.pixel); + TxtAddFont(win->display, win->messagewin, 1, win->large, win->textcolor.pixel); + TxtAddFont(win->display, win->messagewin, 2, win->medium, win->errortext.pixel); + TxtAddFont(win->display, win->messagewin, 3, win->medium, win->playertext.pixel); + + TxtWriteStr(win->display, win->messagewin, MESSAGE_HEADER); + return; +} + +void +message_add(win, string, err) + windata *win; + char *string; + bool err; +{ + if (err) { + TxtWriteStr(win->display, win->messagewin, "2"); + TxtWriteStr(win->display, win->messagewin, string); + TxtWriteStr(win->display, win->messagewin, "0"); + XBell(win->display, 50); + } else + TxtWriteStr(win->display, win->messagewin, string); + + XSync(win->display, 0); + return; +} + +void +message_send(win, event) + windata *win; + XEvent *event; +{ + XKeyEvent *ev = &event->xkey; + KeySym keysym; + windata *ow = (win == win1) ? win2 : win1; + char buf[BSIZE], *s; + int i; + + i = XLookupString(ev, buf, sizeof(buf) - 1, &keysym, &s); + buf[i] = '\0'; + for (s = buf; *s; s++) + if (*s == '\r') + *s = '\n'; + else if (*s == '\177') + *s = ''; + + TxtWriteStr(win->display, win->messagewin, "3"); + TxtWriteStr(win->display, win->messagewin, buf); + TxtWriteStr(win->display, win->messagewin, "0"); + XSync(win->display, 0); + if (ow) { + TxtWriteStr(ow->display, ow->messagewin, "3"); + TxtWriteStr(ow->display, ow->messagewin, buf); + TxtWriteStr(ow->display, ow->messagewin, "0"); + XSync(ow->display, 0); + } + return; +} + diff --git a/gnu/games/chess/Xchess/parse.c b/gnu/games/chess/Xchess/parse.c new file mode 100644 index 000000000000..c66cc38bdbfe --- /dev/null +++ b/gnu/games/chess/Xchess/parse.c @@ -0,0 +1,386 @@ +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:59 $ + * $Source: /users/faustus/xchess/RCS/parse.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Parse a sequence of chess moves... + */ + +#include "xchess.h" + +bool loading_flag = false; +bool loading_paused = false; + +static char *line; + +/* Load a record file in. This returns a number of things -- the board, the + * list of moves, and whose turn it is. + */ + +void +load_game(file) + char *file; +{ + FILE *fp; + char buf[BSIZE]; + bool eflag; + move *m; + board *tmpboard = alloc(board); + + if (eq(file, "xchess.game") && saveflag) { + message_add(win1, + "Oops, I just overwrote the\nfile xchess.game...\n", + true); + message_add(win1, "I hope you had another copy.\n", true); + return; + } + if (!(fp = fopen(file, "r"))) { + perror(file); + return; + } + + /* Get a few lines... */ + fgets(buf, BSIZE, fp); + message_add(win1, buf, false); + if (!oneboard) + message_add(win2, buf, false); + + fgets(buf, BSIZE, fp); + message_add(win1, buf, false); + if (!oneboard) + message_add(win2, buf, false); + + fgets(buf, BSIZE, fp); + if (eq(buf, "\tenglish\n")) + eflag = true; + else if (eq(buf, "\talgebraic\n")) + eflag = false; + else { + fprintf(stderr, "Can't decide whether this is english...\n"); + return; + } + + board_init(tmpboard); + line = NULL; + m = parse_file(fp, tmpboard, eflag); + tfree(tmpboard); + + /* Now apply these moves to the board we were given... */ + loading_flag = true; + while (m) { + if (!quickflag) + XSync(win1->display, 0); + win_process(true); + if (!quickflag) + sleep(1); + if (!loading_paused) { + prog_move(m); + m = m->next; + } + } + loading_flag = false; + if (line) + message_add(win1, line, false); + + while (fgets(buf, BSIZE, fp)) + message_add(win1, buf, false); + + fclose(fp); + + return; +} + +/* Given a starting position (usually the beginning board configuration), + * read in a file of moves. + */ + +move * +parse_file(fp, b, english) + FILE *fp; + board *b; + bool english; +{ + move *mvs = NULL, *end = NULL; + char buf[BSIZE], *s, *t; + + while (fgets(buf, BSIZE, fp)) { + if (*buf == '#') + continue; + s = buf; + + /* The move number... */ + if (!(t = gettok(&s))) + break; + if (!isdigit(*t)) { + line = copy(buf); + break; + } + + if (!(t = gettok(&s))) + break; + if (end) + end = end->next = (english ? parse_move(b, t, WHITE) : + parse_imove(b, t, WHITE)); + else + mvs = end = (english ? parse_move(b, t, WHITE) : + parse_imove(b, t, WHITE)); + if (!end) { + fprintf(stderr, "Can't parse %s\n", buf); + return (NULL); + } + board_move(b, end); + + if (!(t = gettok(&s))) + break; + if (end) + end = end->next = (english ? parse_move(b, t, BLACK) : + parse_imove(b, t, BLACK)); + else + mvs = end = (english ? parse_move(b, t, BLACK) : + parse_imove(b, t, BLACK)); + if (!end) { + fprintf(stderr, "Can't parse %s\n", buf); + return (NULL); + } + board_move(b, end); + } + + return (mvs); +} + +/* Parse a move. The move format accepted is as follows - + * move: spec-spec + * capture: specxspec + * kcastle: 2 o's + * qcastle: 3 o's + * A spec is either piece/pos, piece, or just pos. A pos consists of a column + * name followed by a row number. If the column name is kr, kn, kb, k, q, + * qb, qn, or qr, then the row number is according to the english system, + * or if it is a-h then it is according to the international system. + * + *** As of now the spec must include the position. + */ + +move * +parse_move(b, str, w) + board *b; + char *str; + color w; +{ + move *m = alloc(move); + char *s; + char spec1[16], spec2[16]; + int i, j; + +if (debug) fprintf(stderr, "parsing %s\n", str); + + /* Check for castles. */ + for (s = str, i = 0; *s; s++) + if ((*s == 'o') || (*s == 'O')) + i++; + if (i == 2) { + m->type = KCASTLE; + m->piece.type = KING; + m->piece.color = w; + return (m); + } else if (i == 3) { + m->type = QCASTLE; + m->piece.type = KING; + m->piece.color = w; + return (m); + } + if (index(str, '-')) + m->type = MOVE; + else if (index(str, 'x')) + m->type = CAPTURE; + else + return (NULL); + for (i = 0; str[i]; i++) + if ((str[i] == 'x') || (str[i] == '-')) + break; + else + spec1[i] = str[i]; + spec1[i] = '\0'; + for (i++, j = 0; str[i]; i++, j++) + if ((str[i] == 'x') || (str[i] == '-')) + break; + else + spec2[j] = str[i]; + spec2[j] = '\0'; + + /* Now decode the specifications. */ + s = spec1; + switch (*s) { + case 'p': case 'P': + m->piece.type = PAWN; break; + case 'r': case 'R': + m->piece.type = ROOK; break; + case 'n': case 'N': + m->piece.type = KNIGHT; break; + case 'b': case 'B': + m->piece.type = BISHOP; break; + case 'q': case 'Q': + m->piece.type = QUEEN; break; + case 'k': case 'K': + m->piece.type = KING; break; + default: + return (NULL); + } + m->piece.color = w; + s += 2; + + /* Now get the {q,k}{,b,n,r}n string... */ + if ((s[0] == 'q') && (s[1] == 'r')) + m->fromx = 0, s += 2; + else if ((s[0] == 'q') && (s[1] == 'n')) + m->fromx = 1, s += 2; + else if ((s[0] == 'q') && (s[1] == 'b')) + m->fromx = 2, s += 2; + else if ((s[0] == 'q') && isdigit(s[1])) + m->fromx = 3, s += 1; + else if ((s[0] == 'k') && isdigit(s[1])) + m->fromx = 4, s += 1; + else if ((s[0] == 'k') && (s[1] == 'b')) + m->fromx = 5, s += 2; + else if ((s[0] == 'k') && (s[1] == 'n')) + m->fromx = 6, s += 2; + else if ((s[0] == 'k') && (s[1] == 'r')) + m->fromx = 7, s += 2; + m->fromy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1)); + + if ((b->square[m->fromy][m->fromx].color != w) || + (b->square[m->fromy][m->fromx].type != m->piece.type)) { + fprintf(stderr, "Error: bad stuff\n"); + return (NULL); + } + + s = spec2; + if (m->type == CAPTURE) { + switch (*s) { + case 'p': case 'P': + m->taken.type = PAWN; break; + case 'r': case 'R': + m->taken.type = ROOK; break; + case 'n': case 'N': + m->taken.type = KNIGHT; break; + case 'b': case 'B': + m->taken.type = BISHOP; break; + case 'q': case 'Q': + m->taken.type = QUEEN; break; + case 'k': case 'K': + m->taken.type = KING; break; + default: + return (NULL); + } + m->taken.color = ((w == WHITE) ? BLACK : WHITE); + s += 2; + } + + /* Now get the {q,k}{,b,n,r}n string... */ + if ((s[0] == 'q') && (s[1] == 'r')) + m->tox = 0, s += 2; + else if ((s[0] == 'q') && (s[1] == 'n')) + m->tox = 1, s += 2; + else if ((s[0] == 'q') && (s[1] == 'b')) + m->tox = 2, s += 2; + else if ((s[0] == 'q') && isdigit(s[1])) + m->tox = 3, s += 1; + else if ((s[0] == 'k') && isdigit(s[1])) + m->tox = 4, s += 1; + else if ((s[0] == 'k') && (s[1] == 'b')) + m->tox = 5, s += 2; + else if ((s[0] == 'k') && (s[1] == 'n')) + m->tox = 6, s += 2; + else if ((s[0] == 'k') && (s[1] == 'r')) + m->tox = 7, s += 2; + m->toy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1)); + + if ((m->type == CAPTURE) && ((b->square[m->toy][m->tox].color != + m->taken.color) || (b->square[m->toy][m->tox].type != + m->taken.type))) { + fprintf(stderr, "Error: bad stuff\n"); + return (NULL); + } + + return (m); +} + +/* Parse an algebraic notation move. This is a lot easier... */ + +move * +parse_imove(b, buf, w) + board *b; + char *buf; + color w; +{ + char *s; + move *m = alloc(move); + int n; + +if (debug) fprintf(stderr, "(alg) parsing %s\n", buf); + + for (s = buf, n = 0; *s; s++) + if ((*s == 'o') || (*s == 'O')) + n++; + s = buf; + + if (n == 2) + m->type = KCASTLE; + else if (n == 3) + m->type = QCASTLE; + else { + m->fromx = *s++ - 'a'; + m->fromy = SIZE - (*s++ - '0'); + m->tox = *s++ - 'a'; + m->toy = SIZE - (*s++ - '0'); + m->piece = b->square[m->fromy][m->fromx]; + m->taken = b->square[m->toy][m->tox]; + if (m->taken.color == NONE) + m->type = MOVE; + else + m->type = CAPTURE; + /* for pawns we must account for en passant */ + if (m->piece.type == PAWN) { + if (m->type == MOVE && m->fromx != m->tox) { + m->enpassant = 1; + m->type = CAPTURE; + } + } + } + + if (m->piece.color != w) { + fprintf(stderr, "Error: parse_imove: piece of wrong color!\n"); + return (NULL); + } + if ((m->piece.type == KING) && (m->fromy == m->toy) && (m->fromx == 4) + && (m->tox == 6)) + m->type = KCASTLE; + else if ((m->piece.type == KING) && (m->fromy == m->toy) && + (m->fromx == 4) && (m->tox == 2)) + m->type = QCASTLE; + + return (m); +} + diff --git a/gnu/games/chess/Xchess/pawn.bitmap b/gnu/games/chess/Xchess/pawn.bitmap new file mode 100644 index 000000000000..5c3ff76dbf68 --- /dev/null +++ b/gnu/games/chess/Xchess/pawn.bitmap @@ -0,0 +1,71 @@ + +#define pawn_width 80 +#define pawn_height 80 +static char pawn_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/pawn_mask.bitmap b/gnu/games/chess/Xchess/pawn_mask.bitmap new file mode 100644 index 000000000000..724875c59972 --- /dev/null +++ b/gnu/games/chess/Xchess/pawn_mask.bitmap @@ -0,0 +1,71 @@ + +#define pawn_mask_width 80 +#define pawn_mask_height 80 +static char pawn_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/pawn_outline.bitmap b/gnu/games/chess/Xchess/pawn_outline.bitmap new file mode 100644 index 000000000000..0c4a3a13229a --- /dev/null +++ b/gnu/games/chess/Xchess/pawn_outline.bitmap @@ -0,0 +1,71 @@ + +#define pawn_outline_width 80 +#define pawn_outline_height 80 +static char pawn_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x78, 0xc0, 0x81, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xc0, 0x7f, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/pawn_small.bitmap b/gnu/games/chess/Xchess/pawn_small.bitmap new file mode 100644 index 000000000000..88ff7bbcd16f --- /dev/null +++ b/gnu/games/chess/Xchess/pawn_small.bitmap @@ -0,0 +1,15 @@ + +#define pawn_small_width 32 +#define pawn_small_height 32 +static char pawn_small_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, + 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xf0, 0x0f, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x80, 0xff, 0xff, 0x01, + 0x80, 0xff, 0xff, 0x01, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00, + 0x00, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/pawn_small_outline.bitmap b/gnu/games/chess/Xchess/pawn_small_outline.bitmap new file mode 100644 index 000000000000..e860f43f3d50 --- /dev/null +++ b/gnu/games/chess/Xchess/pawn_small_outline.bitmap @@ -0,0 +1,15 @@ + +#define pawn_small_outline_width 32 +#define pawn_small_outline_height 32 +static char pawn_small_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x30, 0x0c, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, + 0x00, 0x08, 0x10, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x30, 0x0c, 0x00, + 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x80, 0x3f, 0xfc, 0x01, + 0x80, 0x3f, 0xfc, 0x01, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, + 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, + 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, + 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x20, 0x04, 0x00, + 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x0c, 0x30, 0x00, + 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x01, 0x80, 0x07, 0xf0, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/popup.c b/gnu/games/chess/Xchess/popup.c new file mode 100644 index 000000000000..2e19ee5b4c35 --- /dev/null +++ b/gnu/games/chess/Xchess/popup.c @@ -0,0 +1,112 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/26 12:10:38 $ + * $Source: /users/faustus/xchess/RCS/popup.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * faustus@cad.berkeley.edu, ucbvax!faustus + * Permission is granted to modify and re-distribute this code in any manner + * as long as this notice is preserved. All standard disclaimers apply. + * + * A simple pop-up menu system. + */ + +#include "xchess.h" + +/* Open a small window with some text in it and two buttons -- yes and no. + * Use black and white pixel, and the medium font. + */ + +bool +pop_question(win, text) + windata *win; + char *text; +{ + char *s, *t; + int nlines = 1, ncols = 0, i = 0, j; + int x, y; + Window w; + bool ch; + XEvent ev; + + for (s = text; *s; s++) { + if ((*s == '\n') && s[1]) + nlines++; + if ((*s == '\n') || !s[1]) { + if (i > ncols) + ncols = i; + i = 0; + } else + i++; + } + + if (ncols < 12) + ncols = 12; + nlines += 4; + ncols += 4; + + x = (BASE_WIDTH - ncols * win->medium->max_bounds.width) / 2; + y = (BASE_HEIGHT - nlines * win->medium->max_bounds.ascent) / 2; + + w = XCreateSimpleWindow(win->display, win->basewin, + x, y, ncols * win->medium->max_bounds.width, + nlines * win->medium->ascent, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + XMapRaised(win->display, w); + XSetFont(win->display, DefaultGC(win->display, 0), + win->medium->fid); + + for (i = 0, s = text; i < nlines - 4; i++) { + for (t = s, j = 0; *t && (*t != '\n'); t++, j++) + ; + XDrawString(win->display, w, DefaultGC(win->display, 0), + (ncols - j) / 2 * win->medium->max_bounds.width, + (i + 1) * win->medium->ascent, + s, j); + s = t + 1; + } + XDrawString(win->display, w, DefaultGC(win->display, 0), + (ncols - 8) * win->medium->max_bounds.width / 4, + (nlines - 2) * win->medium->ascent, + "YES", 3); + XDrawString(win->display, w, DefaultGC(win->display, 0), + (ncols - 4) * win->medium->max_bounds.width * 3 / 4, + (nlines - 2) * win->medium->ascent, + "NO", 2); + + XSync(win->display, 0); + XSelectInput(win->display, w, ButtonPressMask); + XWindowEvent(win->display, w, ButtonPressMask, &ev); + x = ev.xkey.x; + y = ev.xkey.y; + + if (x > ncols * win->medium->max_bounds.width / 2) + ch = false; + else + ch = true; + + XDestroyWindow(win->display, w); + XSync(win->display, 0); + return (ch); +} + diff --git a/gnu/games/chess/Xchess/program.c b/gnu/games/chess/Xchess/program.c new file mode 100644 index 000000000000..876f29cb466c --- /dev/null +++ b/gnu/games/chess/Xchess/program.c @@ -0,0 +1,200 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:18:10 $ + * $Source: /users/faustus/xchess/RCS/program.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * The interface to whichever chess playing program we are using... + */ + +#include "xchess.h" +#include +#include + +static int pid; +static FILE *from; +static FILE *to; +static bool easy = 1; + +bool +program_init(name) + char *name; +{ + int toprog[2], fromprog[2]; + char buf[BSIZE]; + char time[10]; + char moves[10]; + + pipe(toprog); + pipe(fromprog); + + if (!(pid = fork())) { + /* Start up the program. */ + dup2(toprog[0], 0); + dup2(fromprog[1], 1); + close(toprog[0]); + close(toprog[1]); + close(fromprog[0]); + close(fromprog[1]); + sprintf (time, "%d", timeunit/60); + sprintf (moves, "%d", movesperunit); + if (proghost) + execl("/usr/ucb/rsh", "rsh", proghost, name, + moves, time, + (char *) NULL); + else + execl(name, name, moves, time, (char *) NULL); + perror(name); + exit(1); + } + + close(toprog[0]); + close(fromprog[1]); + + from = fdopen(fromprog[0], "r"); + setbuf(from, NULL); + to = fdopen(toprog[1], "w"); + setbuf(to, NULL); + + /* Get the first line... */ + fgets(buf, BSIZE, from); + if (debug) + fprintf(stderr, "program says %s", buf); + if (blackflag) { + fputs("switch\n", to); + fflush(to); + fgets(buf, BSIZE, from); + if (debug) + fprintf(stderr, "program says %s", buf); + message_add(win1, "GNU Chess playing white\n", false); + } else + message_add(win1, "GNU Chess playing black\n", false); + + return (true); +} + +void +program_end() +{ + fclose(from); + fclose(to); + kill(pid, SIGTERM); + return; +} + +void +program_send(m) + move *m; +{ + char buf[BSIZE]; + + if ((m->type == MOVE) || (m->type == CAPTURE)) + sprintf(buf, "%c%d%c%d\n", 'a' + m->fromx, SIZE - m->fromy, + 'a' + m->tox, SIZE - m->toy); + else if (m->type == KCASTLE) + strcpy(buf, (m->piece.color == WHITE) ? "e1g1\n" : "e8g8\n"); + else if (m->type == QCASTLE) + strcpy(buf, (m->piece.color == WHITE) ? "e1c1\n" : "e8c8\n"); + + if (debug) + fprintf(stderr, "sending program %s", buf); + if (!easy) + kill (pid, SIGINT); + + fputs(buf, to); + fflush(to); + + /* One junk line... */ + fgets(buf, BSIZE, from); + if (debug) + fprintf(stderr, "program says %s", buf); + return; +} + +move * +program_get() +{ + int rfd = (1 << fileno(from)), wfd = 0, xfd = 0; + static struct timeval notime = { 0, 0 }; + char buf[BSIZE], *s; + move *m; + int i; + + /* Do a poll... */ + + if (!(i = select(32, &rfd, &wfd, &xfd, ¬ime)) && + !from->_cnt) { /* Bad stuff... */ + if (debug) + fprintf(stderr, "poll: nothing\n"); + return (NULL); + } + if (i == -1) { + perror("select"); + return (NULL); + } + + fgets(buf, BSIZE, from); + if (*buf == '\n' || *buf == '\0') { + message_add(win1, "program died", false); + return (NULL); + } + + if (debug) + fprintf(stderr, "got from program %s", buf); + + for (s = buf; !isalpha(*s); s++) + ; + m = parse_imove(chessboard, s, nexttomove); + if (m == NULL) + return (NULL); + + if (!valid_move(m, chessboard)) { + fprintf(stderr, "Error: move %s is invalid!!\n", buf); + return (NULL); + } + + /* + fgets(buf, BSIZE, from); + if (debug) + fprintf(stderr, "program says %s", buf); + */ + message_add(win1, buf, false); + return (m); +} + +void +program_undo() +{ + fputs("undo\n", to); + return; +} +void +program_easy (mode) + bool mode; + +{ + fputs("easy\n", to); + easy = mode; +} diff --git a/gnu/games/chess/Xchess/queen.bitmap b/gnu/games/chess/Xchess/queen.bitmap new file mode 100644 index 000000000000..ab3817a123a9 --- /dev/null +++ b/gnu/games/chess/Xchess/queen.bitmap @@ -0,0 +1,71 @@ + +#define queen_width 80 +#define queen_height 80 +static char queen_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x80, 0x01, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x80, 0x01, 0x80, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x01, 0xc0, 0x03, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0xc0, 0x03, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xc0, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x03, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x03, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xc0, 0x03, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x03, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x01, 0xc0, 0x03, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, + 0xe0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xe0, 0x07, + 0xc0, 0x03, 0x00, 0x00, 0x1c, 0x00, 0xc0, 0x03, 0xe0, 0x07, 0xc0, 0x03, + 0x00, 0x00, 0x3e, 0x00, 0xc0, 0x03, 0xe0, 0x07, 0xc0, 0x03, 0x00, 0x0e, + 0x3e, 0x00, 0xc0, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0x00, 0x1f, 0x3e, 0x00, + 0xc0, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0x00, 0x1f, 0x3c, 0x00, 0xc0, 0x07, + 0xe0, 0x07, 0xe0, 0x03, 0x00, 0x1f, 0x70, 0x00, 0xc0, 0x0f, 0xe0, 0x07, + 0xf0, 0x03, 0x00, 0x0e, 0x60, 0x00, 0xc0, 0x0f, 0xe0, 0x07, 0xf0, 0x03, + 0x00, 0x03, 0xe0, 0x00, 0xc0, 0x0f, 0xf0, 0x0f, 0xf0, 0x03, 0x80, 0x03, + 0xc0, 0x01, 0xc0, 0x1f, 0xf0, 0x0f, 0xf8, 0x03, 0x80, 0x01, 0xc0, 0x01, + 0xc0, 0x1f, 0xf0, 0x0f, 0xf8, 0x03, 0xc0, 0x01, 0xc0, 0x03, 0xc0, 0x1f, + 0xf0, 0x0f, 0xf8, 0x03, 0xe0, 0x01, 0xc0, 0x07, 0xc0, 0x1f, 0xf0, 0x0f, + 0xf8, 0x03, 0xe0, 0x01, 0xc0, 0x07, 0xc0, 0x3f, 0xf0, 0x0f, 0xfc, 0x03, + 0xf0, 0x01, 0xc0, 0x0f, 0xc0, 0x3f, 0xf0, 0x0f, 0xfc, 0x03, 0xf8, 0x01, + 0x80, 0x1f, 0xc0, 0x3f, 0xf0, 0x0f, 0xfc, 0x03, 0xf8, 0x01, 0x80, 0x1f, + 0xc0, 0x7f, 0xf0, 0x0f, 0xfe, 0x03, 0xfc, 0x01, 0x80, 0x3f, 0xc0, 0x7f, + 0xf8, 0x1f, 0xfe, 0x03, 0xfc, 0x00, 0x80, 0x3f, 0xc0, 0x7f, 0xf8, 0x1f, + 0xfe, 0x03, 0xfe, 0x00, 0x80, 0x7f, 0xc0, 0xff, 0xf8, 0x1f, 0xff, 0x03, + 0xff, 0x00, 0x80, 0xff, 0xc0, 0xff, 0xf8, 0x1f, 0xff, 0x03, 0xff, 0x00, + 0x00, 0xff, 0xc0, 0xff, 0xf8, 0x1f, 0xff, 0x83, 0xff, 0x00, 0x00, 0xff, + 0xc1, 0xff, 0xf9, 0x9f, 0xff, 0x83, 0xff, 0x00, 0x00, 0xff, 0xc3, 0xff, + 0xf9, 0x9f, 0xff, 0xc3, 0xff, 0x00, 0x00, 0xff, 0xc3, 0xff, 0xf9, 0x9f, + 0xff, 0xe3, 0x7f, 0x00, 0x00, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xe3, + 0x7f, 0x00, 0x00, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x7f, 0x00, + 0x00, 0xfe, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x7f, 0x00, 0x00, 0xfe, + 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0x80, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0xff, 0x03, 0xfc, 0x3f, 0xc0, 0xff, + 0x1f, 0x00, 0x00, 0xf0, 0x01, 0xf8, 0x7f, 0xfe, 0x1f, 0x80, 0x1f, 0x00, + 0x00, 0x30, 0xfc, 0xff, 0x1f, 0xf8, 0xff, 0x3f, 0x0c, 0x00, 0x00, 0xe0, + 0xe7, 0xff, 0x07, 0xe0, 0xff, 0xe7, 0x07, 0x00, 0x00, 0xc0, 0x81, 0xff, + 0x1f, 0xf8, 0xff, 0x81, 0x03, 0x00, 0x00, 0x80, 0x00, 0xfe, 0x7f, 0xfe, + 0x7f, 0x00, 0x03, 0x00, 0x00, 0x80, 0x81, 0xff, 0xff, 0xff, 0xff, 0x81, + 0x01, 0x00, 0x00, 0x00, 0xe7, 0xff, 0x01, 0x80, 0xff, 0xe7, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x03, 0xfc, 0x3f, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x80, + 0x01, 0xf8, 0xff, 0xff, 0x1f, 0x80, 0x01, 0x00, 0x00, 0x80, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/queen_mask.bitmap b/gnu/games/chess/Xchess/queen_mask.bitmap new file mode 100644 index 000000000000..76a5904e8340 --- /dev/null +++ b/gnu/games/chess/Xchess/queen_mask.bitmap @@ -0,0 +1,71 @@ + +#define queen_mask_width 80 +#define queen_mask_height 80 +static char queen_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, + 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, 0x03, + 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xc0, 0x03, 0xc0, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x03, 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x01, 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, + 0xe0, 0x07, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xe0, 0x07, + 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xe0, 0x07, 0x80, 0x07, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0xe0, 0x07, 0x80, 0x07, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x03, 0xf0, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x07, 0xf0, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, + 0xf0, 0x0f, 0xc0, 0x07, 0x00, 0x00, 0x7e, 0x00, 0xe0, 0x07, 0xf0, 0x0f, + 0xe0, 0x07, 0x00, 0x00, 0x7f, 0x00, 0xe0, 0x0f, 0xf0, 0x0f, 0xe0, 0x07, + 0x00, 0x1f, 0x7f, 0x00, 0xe0, 0x0f, 0xf0, 0x0f, 0xe0, 0x07, 0x80, 0x3f, + 0x7f, 0x00, 0xe0, 0x0f, 0xf0, 0x0f, 0xf0, 0x07, 0x80, 0x3f, 0x7f, 0x00, + 0xe0, 0x0f, 0xf0, 0x0f, 0xf0, 0x07, 0x80, 0x3f, 0xff, 0x00, 0xe0, 0x1f, + 0xf0, 0x0f, 0xf0, 0x07, 0x80, 0x3f, 0xfe, 0x00, 0xe0, 0x1f, 0xf0, 0x0f, + 0xf8, 0x07, 0x80, 0x1f, 0xfc, 0x01, 0xe0, 0x1f, 0xf8, 0x1f, 0xf8, 0x07, + 0x80, 0x1f, 0xf0, 0x03, 0xe0, 0x3f, 0xf8, 0x1f, 0xf8, 0x07, 0xc0, 0x0f, + 0xf0, 0x07, 0xe0, 0x3f, 0xf8, 0x1f, 0xfc, 0x07, 0xe0, 0x03, 0xe0, 0x07, + 0xe0, 0x3f, 0xf8, 0x1f, 0xfc, 0x07, 0xf0, 0x03, 0xe0, 0x0f, 0xe0, 0x7f, + 0xf8, 0x1f, 0xfc, 0x07, 0xf0, 0x03, 0xe0, 0x1f, 0xe0, 0x7f, 0xf8, 0x1f, + 0xfc, 0x07, 0xf8, 0x03, 0xe0, 0x1f, 0xe0, 0x7f, 0xf8, 0x1f, 0xfe, 0x07, + 0xf8, 0x03, 0xe0, 0x3f, 0xe0, 0x7f, 0xf8, 0x1f, 0xfe, 0x07, 0xfc, 0x03, + 0xe0, 0x3f, 0xe0, 0xff, 0xf8, 0x1f, 0xfe, 0x07, 0xfe, 0x03, 0xc0, 0x7f, + 0xe0, 0xff, 0xfc, 0x3f, 0xff, 0x07, 0xfe, 0x03, 0xc0, 0xff, 0xe0, 0xff, + 0xfd, 0x3f, 0xff, 0x07, 0xff, 0x03, 0xc0, 0xff, 0xe1, 0xff, 0xfd, 0xff, + 0xff, 0x87, 0xff, 0x03, 0xc0, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0x87, + 0xff, 0x01, 0xc0, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x01, + 0xc0, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0x01, 0x80, 0xff, + 0xef, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe7, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/queen_outline.bitmap b/gnu/games/chess/Xchess/queen_outline.bitmap new file mode 100644 index 000000000000..2527216b3966 --- /dev/null +++ b/gnu/games/chess/Xchess/queen_outline.bitmap @@ -0,0 +1,71 @@ + +#define queen_outline_width 80 +#define queen_outline_height 80 +static char queen_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x80, 0x01, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x80, 0x01, 0x80, 0x0d, 0x00, 0x00, + 0x00, 0x00, 0xb0, 0x01, 0xc0, 0x03, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x40, 0x02, 0x80, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x40, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x02, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x02, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x02, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x01, 0x40, 0x02, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0x40, 0x02, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, + 0x60, 0x06, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x20, 0x04, + 0xc0, 0x02, 0x00, 0x00, 0x1c, 0x00, 0x40, 0x02, 0x20, 0x04, 0x40, 0x02, + 0x00, 0x00, 0x36, 0x00, 0x40, 0x02, 0x20, 0x04, 0x40, 0x02, 0x00, 0x0e, + 0x22, 0x00, 0x40, 0x06, 0x20, 0x04, 0x60, 0x02, 0x00, 0x1b, 0x36, 0x00, + 0x40, 0x04, 0x20, 0x04, 0x20, 0x02, 0x00, 0x11, 0x3c, 0x00, 0x40, 0x04, + 0x20, 0x04, 0x20, 0x02, 0x00, 0x1b, 0x70, 0x00, 0x40, 0x0c, 0x20, 0x04, + 0x30, 0x02, 0x00, 0x0e, 0x60, 0x00, 0x40, 0x08, 0x20, 0x04, 0x10, 0x02, + 0x00, 0x03, 0xe0, 0x00, 0x40, 0x08, 0x30, 0x0c, 0x10, 0x02, 0x80, 0x03, + 0xc0, 0x01, 0x40, 0x18, 0x10, 0x08, 0x18, 0x02, 0x80, 0x01, 0x40, 0x01, + 0x40, 0x10, 0x10, 0x08, 0x08, 0x02, 0xc0, 0x01, 0x40, 0x03, 0x40, 0x10, + 0x10, 0x08, 0x08, 0x02, 0x60, 0x01, 0x40, 0x06, 0x40, 0x10, 0x10, 0x08, + 0x08, 0x02, 0x20, 0x01, 0x40, 0x04, 0x40, 0x30, 0x10, 0x08, 0x0c, 0x02, + 0x30, 0x01, 0xc0, 0x0c, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x18, 0x01, + 0x80, 0x18, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x08, 0x01, 0x80, 0x10, + 0x40, 0x60, 0x10, 0x08, 0x06, 0x02, 0x8c, 0x01, 0x80, 0x30, 0x40, 0x40, + 0x18, 0x18, 0x02, 0x02, 0x84, 0x00, 0x80, 0x20, 0x40, 0x40, 0x08, 0x10, + 0x02, 0x02, 0x86, 0x00, 0x80, 0x60, 0x40, 0xc0, 0x08, 0x10, 0x03, 0x02, + 0x83, 0x00, 0x80, 0xc1, 0x40, 0x80, 0x08, 0x10, 0x01, 0x02, 0x81, 0x00, + 0x00, 0x81, 0x40, 0x80, 0x08, 0x10, 0x01, 0x82, 0x81, 0x00, 0x00, 0x81, + 0x41, 0x80, 0x09, 0x90, 0x01, 0x82, 0x80, 0x00, 0x00, 0x01, 0x43, 0x00, + 0x09, 0x90, 0x00, 0xc2, 0xc0, 0x00, 0x00, 0x01, 0x42, 0x00, 0x09, 0x90, + 0x00, 0x62, 0x40, 0x00, 0x00, 0x01, 0x46, 0x00, 0x0f, 0xf0, 0x00, 0x22, + 0x40, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x32, 0x40, 0x00, + 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40, 0x00, 0x00, 0x02, + 0x58, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x40, 0x00, 0x00, 0x02, 0x70, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xfe, 0x7f, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00, + 0x10, 0x00, 0x00, 0x10, 0xfe, 0x07, 0x80, 0x01, 0xe0, 0x7f, 0x18, 0x00, + 0x00, 0x30, 0x03, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x60, + 0x18, 0x00, 0xf8, 0x1f, 0x00, 0x18, 0x06, 0x00, 0x00, 0x40, 0x7e, 0x00, + 0xe0, 0x07, 0x00, 0x7e, 0x02, 0x00, 0x00, 0x40, 0xff, 0x01, 0x80, 0x01, + 0x80, 0xff, 0x02, 0x00, 0x00, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x7e, + 0x02, 0x00, 0x00, 0xc0, 0x18, 0x00, 0xfe, 0x7f, 0x00, 0x18, 0x03, 0x00, + 0x00, 0x80, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00, 0x01, 0x00, 0x00, 0x80, + 0xfe, 0x07, 0x00, 0x00, 0xe0, 0x7f, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/queen_small.bitmap b/gnu/games/chess/Xchess/queen_small.bitmap new file mode 100644 index 000000000000..d7ee50e9b820 --- /dev/null +++ b/gnu/games/chess/Xchess/queen_small.bitmap @@ -0,0 +1,15 @@ + +#define queen_small_width 32 +#define queen_small_height 32 +static char queen_small_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, + 0x80, 0x81, 0xc0, 0x00, 0x80, 0x81, 0xc0, 0x00, 0x00, 0xc1, 0x41, 0x00, + 0x00, 0xc1, 0x41, 0x00, 0x02, 0xc3, 0x61, 0x20, 0x06, 0xc3, 0x61, 0x30, + 0x04, 0xc3, 0x61, 0x10, 0x0c, 0xc3, 0x61, 0x18, 0x08, 0xc7, 0x71, 0x08, + 0x18, 0xc6, 0x31, 0x0c, 0x38, 0xc6, 0x31, 0x0e, 0x30, 0xce, 0x39, 0x06, + 0x70, 0xce, 0x39, 0x07, 0x60, 0xee, 0x3b, 0x03, 0xe0, 0xee, 0xbb, 0x03, + 0xe0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0x01, + 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x80, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/queen_small_outline.bitmap b/gnu/games/chess/Xchess/queen_small_outline.bitmap new file mode 100644 index 000000000000..0b624b9587bc --- /dev/null +++ b/gnu/games/chess/Xchess/queen_small_outline.bitmap @@ -0,0 +1,15 @@ + +#define queen_small_outline_width 32 +#define queen_small_outline_height 32 +static char queen_small_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, + 0x80, 0x81, 0xc0, 0x00, 0x80, 0x81, 0xc0, 0x00, 0x00, 0xc1, 0x41, 0x00, + 0x00, 0x41, 0x41, 0x00, 0x02, 0x43, 0x61, 0x20, 0x06, 0x43, 0x61, 0x30, + 0x04, 0x43, 0x61, 0x10, 0x0c, 0x43, 0x61, 0x18, 0x08, 0x47, 0x71, 0x08, + 0x18, 0x46, 0x31, 0x0c, 0x38, 0x46, 0x31, 0x0e, 0x30, 0x4e, 0x39, 0x06, + 0x70, 0x4e, 0x29, 0x07, 0x60, 0x6a, 0x2b, 0x03, 0xe0, 0x2a, 0xab, 0x03, + 0xe0, 0x3b, 0xee, 0x03, 0x40, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x80, 0x01, + 0x80, 0xfc, 0x9f, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x01, 0x40, 0x00, + 0x80, 0xfd, 0xdf, 0x00, 0xf0, 0x00, 0x80, 0x07, 0xf0, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/record.c b/gnu/games/chess/Xchess/record.c new file mode 100644 index 000000000000..d9459b3a64f0 --- /dev/null +++ b/gnu/games/chess/Xchess/record.c @@ -0,0 +1,315 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:18:20 $ + * $Source: /users/faustus/xchess/RCS/record.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Deal with recording moves. + */ + +#include "xchess.h" + +#undef smartass + +bool record_english = true; +char *record_file = DEF_RECORD_FILE; +int movenum = 0; +bool saveflag = false; + +static char *colnames[] = { "qr", "qn", "qb", "q", "k", "kb", "kn", "kr" } ; +static char *pcnames[] = { "P", "R", "N", "B", "Q", "K" } ; + +static char *movestring(); +static char *tstring(); +static FILE *backup; + +#define RECORD_HEADER "\n1 XChess Game Record0\n" + +void +record_init(win) + windata *win; +{ + int i; + + i = XTextWidth(win->medium, RECORD_HEADER, + sizeof(RECORD_HEADER) - 1); + i = (40 * win->small->max_bounds.width - i * + win->medium->max_bounds.width) / + win->medium->max_bounds.width / 2; + TxtGrab(win->display, win->recwin, "xchess", win->small, win->textback.pixel, + win->textcolor.pixel, win->cursorcolor.pixel); + TxtAddFont(win->display, win->recwin, 1, win->medium, win->textcolor.pixel); + for (; i > 0; i++) + TxtWriteStr(win->display, win->recwin, " "); + TxtWriteStr(win->display, win->recwin, RECORD_HEADER); + + if (saveflag) { + if (!(backup = fopen(record_file, "w"))) { + perror(record_file); + saveflag = false; + } else { + fprintf(backup, "X Chess -- %s\n", datestring()); + if (dispname2) + fprintf(backup, "\tWhite on %s, black on %s\n", + dispname1, dispname2); + else + fprintf(backup, "\tGame played on %s\n", + dispname1); + fprintf(backup, "\t%s\n", record_english ? "english" : + "algebraic"); + fflush(backup); + } + } + + movenum = 0; + return; +} + +void +record_reset() +{ + TxtWriteStr(win1->display, win1->recwin, "\n\n1 New Game0\n\n"); + if (!oneboard) { + TxtWriteStr(win2->display, win2->recwin, "\n\n1 New Game0\n\n"); + } + movenum = 0; + if (saveflag) { + fprintf(backup, "\n\nNew Game\n\n"); + fflush(backup); + } + return; +} + +void +record_end(s) + char *s; +{ + char buf[BSIZE]; + + sprintf(buf, "\n%s\n", s); + TxtWriteStr(win1->display, win1->recwin, s); + if (!oneboard) { + TxtWriteStr(win2->display, win2->recwin, s); + } + if (saveflag) { + fprintf(backup, "\n%s\n", s); + fprintf(backup, "Time: white: %s, ", tstring(whiteseconds)); + fprintf(backup, "black: %s\n", tstring(blackseconds)); + fclose(backup); + } + return; +} + +void +record_save() +{ + move *m; + FILE *fp; + int i; + char *s; + + if (!(fp = fopen(record_file, "w"))) { + perror(record_file); + return; + } + fprintf(fp, "X Chess -- %s\n", datestring()); + if (dispname2) + fprintf(fp, "\tWhite on %s, black on %s\n", + dispname1, dispname2); + else + fprintf(fp, "\tGame played on %s\n", dispname1); + fprintf(fp, "\t%s\n", record_english ? "english" : "algebraic"); + + for (m = moves, i = 1; m; i++) { + s = movestring(m); + fprintf(fp, "%2d. %-16s ", i, s); + m = m->next; + if (m) + s = movestring(m); + else + s = ""; + fprintf(fp, "%s\n", s); + if (m) + m = m->next; + } + fclose(fp); + return; +} + +void +record_move(m) + move *m; +{ + char *s, buf[BSIZE]; + + s = movestring(m); + + if (m->piece.color == WHITE) { + movenum++; + sprintf(buf, "%2d. %-16s ", movenum, s); + } else { + sprintf(buf, "%s\n", s); + } + TxtWriteStr(win1->display, win1->recwin, buf); + if (!oneboard) { + TxtWriteStr(win2->display, win2->recwin, buf); + } + if (saveflag) { + fprintf(backup, "%s", buf); + fflush(backup); + } + + return; +} + +void +record_back() +{ + extern move *lastmove; + move *m = lastmove; + char *s = movestring(m); + char buf[BSIZE]; + long i; + + if (m->piece.color == WHITE) { + sprintf(buf, "%2d. %-16s ", movenum, s); + } else { + sprintf(buf, "%s\n", s); + } + s = buf; + for (i = 0; *s != '\0'; i++) + *s++ = ''; /* control H, backspace */ + + TxtWriteStr(win1->display, win1->recwin, buf); + if (!oneboard) { + TxtWriteStr(win2->display, win2->recwin, buf); + } + + if (nexttomove == BLACK) + movenum--; + if (saveflag) { + fseek(backup, -i, 1); + fflush(backup); + } + + return; +} + +static char * +movestring(m) + move *m; +{ + int fy, ty; + static char buf[BSIZE]; + + if (!record_english || (m->piece.color == WHITE)) { + fy = SIZE - m->fromy; + ty = SIZE - m->toy; + } else { + fy = m->fromy + 1; + ty = m->toy + 1; + } + + switch (m->type) { + case MOVE: + if (record_english) + sprintf(buf, "%s/%s%d-%s%d%s", pcnames[(int) m->piece. + type], colnames[m->fromx], fy, + colnames[m->tox], ty, m->check ? "+" : + ""); + else + sprintf(buf, "%c%d%c%d", 'a' + m->fromx, fy, 'a' + + m->tox, ty); + break; + case CAPTURE: + if (record_english) + sprintf(buf, "%s/%s%dx%s/%s%d%s%s", + pcnames[(int) m->piece.type], + colnames[m->fromx], fy, + pcnames[(int) m->taken.type], + colnames[m->tox], ty, + m->enpassant ? "e.p." : "", + m->check ? "+" : ""); + else + sprintf(buf, "%c%d%c%d", 'a' + m->fromx, fy, 'a' + + m->tox, ty); + break; + + case KCASTLE: + if (record_english) + sprintf(buf, "O-O%s", m->check ? "ch" : ""); + else if (m->piece.color == WHITE) + strcpy(buf, "e1g1"); + else + strcpy(buf, "e8g8"); + break; + + case QCASTLE: + if (record_english) + sprintf(buf, "O-O-O%s", m->check ? "ch" : ""); + else if (m->piece.color == WHITE) + strcpy(buf, "e1c1"); + else + strcpy(buf, "e8c8"); + break; + + default: + sprintf(buf, "something strange"); + break; + } + if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) && + (m->toy == 7)) || ((m->piece.color == WHITE) && + (m->toy == 0)))) + strcat(buf, "(Q)"); + +#ifdef smartass + if (!(random() % 50)) + strcat(buf, "?"); + else if (!(random() % 50)) + strcat(buf, "!"); + else if (!(random() % 500)) + strcat(buf, "???"); + else if (!(random() % 500)) + strcat(buf, "!!!"); +#endif smartass + + return (buf); +} + +static char * +tstring(s) + int s; +{ + static char buf[64]; + + if (s > 3600) + sprintf(buf, "%dh %dm %ds", s / 3600, (s % 3600) / 60, s % 60); + else if (s > 60) + sprintf(buf, "%dm %ds", (s % 3600) / 60, s % 60); + else + sprintf(buf, "%ds", s); + return (buf); +} + diff --git a/gnu/games/chess/Xchess/rook.bitmap b/gnu/games/chess/Xchess/rook.bitmap new file mode 100644 index 000000000000..f274614eb9cb --- /dev/null +++ b/gnu/games/chess/Xchess/rook.bitmap @@ -0,0 +1,71 @@ + +#define rook_width 80 +#define rook_height 80 +static char rook_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xf8, 0xff, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0xf8, 0xff, 0x00, 0xfc, 0x0f, 0x00, + 0x00, 0xc0, 0xff, 0x01, 0xf8, 0xff, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xc0, + 0xff, 0x01, 0xf8, 0xff, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01, + 0xf8, 0xff, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01, 0xff, 0xff, + 0x07, 0xfc, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0x01, 0x00, 0xfc, 0xfd, + 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x07, 0xfc, 0xff, 0x01, 0xff, 0x1f, 0x00, + 0x00, 0xc0, 0x1f, 0xf0, 0xff, 0xff, 0x7f, 0xc0, 0x1f, 0x00, 0x00, 0x40, + 0xc0, 0xff, 0x07, 0x00, 0xff, 0x1f, 0x10, 0x00, 0x00, 0xc0, 0xff, 0x1f, + 0xf0, 0x7f, 0xc0, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0x7f, 0xc0, 0xfd, 0xff, + 0x1d, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, + 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x7f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xff, 0xfe, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0x0f, 0x80, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x3f, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, + 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xfd, 0xff, 0xfd, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xff, 0xfd, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xfd, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/rook_mask.bitmap b/gnu/games/chess/Xchess/rook_mask.bitmap new file mode 100644 index 000000000000..c04441655879 --- /dev/null +++ b/gnu/games/chess/Xchess/rook_mask.bitmap @@ -0,0 +1,71 @@ + +#define rook_mask_width 80 +#define rook_mask_height 80 +static char rook_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xfc, 0xff, + 0x01, 0x7e, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0xfc, 0xff, 0x01, 0xfe, + 0x1f, 0x00, 0x00, 0xe0, 0xff, 0x03, 0xfc, 0xff, 0x01, 0xfe, 0x3f, 0x00, + 0x00, 0xe0, 0xff, 0x03, 0xfc, 0xff, 0x01, 0xfe, 0x3f, 0x00, 0x00, 0xe0, + 0xff, 0x03, 0xfc, 0xff, 0x1f, 0xfe, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0x83, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/rook_outline.bitmap b/gnu/games/chess/Xchess/rook_outline.bitmap new file mode 100644 index 000000000000..f30107a3f277 --- /dev/null +++ b/gnu/games/chess/Xchess/rook_outline.bitmap @@ -0,0 +1,71 @@ + +#define rook_outline_width 80 +#define rook_outline_height 80 +static char rook_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x08, 0x80, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x08, 0x80, 0x00, 0xe4, 0x0f, 0x00, + 0x00, 0xc0, 0x00, 0x01, 0x08, 0x80, 0x00, 0x04, 0x18, 0x00, 0x00, 0x40, + 0x00, 0x01, 0x08, 0x80, 0x00, 0x04, 0x10, 0x00, 0x00, 0x40, 0x00, 0x01, + 0x08, 0x80, 0x00, 0x04, 0x10, 0x00, 0x00, 0x40, 0x00, 0x01, 0x0f, 0x80, + 0x07, 0x04, 0x10, 0x00, 0x00, 0x40, 0x00, 0xfd, 0x01, 0x00, 0xfc, 0x05, + 0x10, 0x00, 0x00, 0x40, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, + 0x00, 0x40, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x10, 0x00, 0x00, 0x40, + 0x00, 0xf0, 0x07, 0x00, 0x7f, 0x00, 0x10, 0x00, 0x00, 0x40, 0xc0, 0x1f, + 0x00, 0x00, 0xc0, 0x1f, 0x10, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x02, 0x00, + 0x02, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x80, 0xff, 0xff, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0x00, 0x01, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xf0, 0x7f, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x1f, 0xc0, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/rook_small.bitmap b/gnu/games/chess/Xchess/rook_small.bitmap new file mode 100644 index 000000000000..ddee75660d4b --- /dev/null +++ b/gnu/games/chess/Xchess/rook_small.bitmap @@ -0,0 +1,15 @@ + +#define rook_small_width 32 +#define rook_small_height 32 +static char rook_small_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x73, 0xce, 0x03, 0xc0, 0x73, 0xce, 0x03, 0xc0, 0x73, 0xce, 0x03, + 0xc0, 0x73, 0xce, 0x03, 0xc0, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, + 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/rook_small_outline.bitmap b/gnu/games/chess/Xchess/rook_small_outline.bitmap new file mode 100644 index 000000000000..523521b963b7 --- /dev/null +++ b/gnu/games/chess/Xchess/rook_small_outline.bitmap @@ -0,0 +1,15 @@ + +#define rook_small_outline_width 32 +#define rook_small_outline_height 32 +static char rook_small_outline_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x73, 0xce, 0x03, 0x40, 0x52, 0x4a, 0x02, 0x40, 0x52, 0x4a, 0x02, + 0x40, 0x52, 0x4a, 0x02, 0xc0, 0xff, 0xff, 0x03, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, + 0xe0, 0xff, 0xff, 0x07, 0x20, 0x00, 0x00, 0x04, 0xe0, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/scrollText.c b/gnu/games/chess/Xchess/scrollText.c new file mode 100644 index 000000000000..432071086d15 --- /dev/null +++ b/gnu/games/chess/Xchess/scrollText.c @@ -0,0 +1,1858 @@ +/* + * A Scrollable Text Output Window + * + * David Harrison + * University of California, Berkeley + * 1986 + * + * The following is an implementation for a scrollable text output + * system. It handles exposure events only (other interactions are + * under user control). For scrolling, a always present scroll bar + * is implemented. It detects size changes and compensates accordingly. + */ + +#include +#include +#include +#include +#include "scrollText.h" + +extern char *malloc(); +extern char *realloc(); +#define alloc(type) (type *) malloc(sizeof(type)) +#define numalloc(type, num) (type *) malloc((unsigned) (num * sizeof(type))) +#define MAXINT 2147483647 + +extern XAssocTable *XCreateAssocTable(); +extern caddr_t XLookUpAssoc(); + +static XAssocTable *textWindows = (XAssocTable *) 0; + +#define NOOPTION -1 /* Option hasn't been set yet */ +#define NORMSCROLL 0 /* Smooth scroll on LineToTop and TopToHere */ +#define JUMPSCROLL 1 /* Jump scrolling on LineToTop and TopToHere */ + +static int ScrollOption = NOOPTION; + +typedef char *Generic; + +#define DEFAULT_GC textInfo->fontGC[textInfo->curFont] + +#define BARSIZE 15 +#define BARBORDER 1 +#define MAXFONTS 8 +#define INITBUFSIZE 1024 +#define INITLINES 50 +#define INITEXPARY 50 +#define XPADDING 2 +#define YPADDING 2 +#define INTERLINE 5 +#define INTERSPACE 1 +#define CURSORWIDTH 2 +#define EXPANDPERCENT 40 +#define BUFSIZE 1024 +#define CUROFFSET 1 +#define MAXFOREIGN 250 +#define NOINDEX -1 + +/* The wrap line indicator */ +#define WRAPINDSIZE 7 +#define STEMOFFSET 5 +#define arrow_width 7 +#define arrow_height 5 +static char arrow_bits[] = { + 0x24, 0x26, 0x3f, 0x06, 0x04}; + +#define NEWLINE '\n' +#define BACKSPACE '\010' +#define NEWFONT '\006' +#define LOWCHAR '\040' +#define HIGHCHAR '\176' + +#define CHARMASK 0x00ff /* Character mask */ +#define FONTMASK 0x0700 /* Character font */ +#define FONTSHIFT 8 /* Shift amount */ + +#define WRAPFLAG 0x01 /* Line wrap flag */ + +/* + * Lines are represented by a pointer into the overall array of + * 16-bit characters. The lower eight bits is used to indicate the character + * (in ASCII), and the next two bits are used to indicate the font + * the character should be drawn in. + */ + +typedef struct txtLine { + int lineLength; /* Current line length */ + int lineHeight; /* Full height of line in pixels */ + int lineBaseLine; /* Current baseline of the line */ + int lineWidth; /* Drawing position at end of line */ + int lineText; /* Offset into master buffer */ + int lineFlags; /* Line wrap flag is here */ +}; + + +/* + * For ExposeCopy events, we queue up the redraw requests collapsing + * them into line redraw requests until the CopyExpose event arrives. + * The queue is represented as a dynamic array of the following + * structure: + */ + +typedef struct expEvent { + int lineIndex; /* Index of line to redraw */ + int ypos; /* Drawing position of line */ +}; + + +/* + * The text buffer is represented using a dynamic counted array + * of 16-bit quantities. This array expands as needed. + * For the screen representation, a dynamic counted array + * of line structures is used. This array points into the + * text buffer to denote the start of each line and its parameters. + * The windows are configured as one overall window which contains + * the scroll bar as a sub-window along its right edge. Thus, + * the text drawing space is actually w-BARSIZE. + */ + +#define NOTATBOTTOM 0x01 /* Need to scroll to bottom before appending */ +#define FONTNUMWAIT 0x02 /* Waiting for font number */ +#define COPYEXPOSE 0x04 /* Need to process a copy expose event */ +#define SCREENWRONG 0x08 /* TxtJamStr has invalidated screen contents */ + +typedef struct txtWin { + /* Basic text buffer */ + int bufAlloc; /* Allocated size of buffer */ + int bufSpot; /* Current writing position in buffer */ + short *mainBuffer; /* Main buffer of text */ + + /* Line information */ + int numLines; /* Number of display lines in buffer */ + int allocLines; /* Number of lines allocated */ + struct txtLine **txtBuffer; /* Dynamic array of lines */ + + /* Current Window display information */ + Window mainWindow; /* Text display window */ + Window scrollBar; /* Subwindow for scroll bar */ + Pixmap arrowMap; /* line wrap indicator */ + int bgPix, fgPix; /* Background and cursor */ + GC CursorGC; /* gc for the cursor */ + GC bgGC; /* gc for erasing things */ + GC fontGC[MAXFONTS]; /* gc for doing fonts */ + XFontStruct theFonts[MAXFONTS];/* Display fonts */ + int theColors[MAXFONTS]; /* foregrounds of the fonts */ + int curFont; /* current font for tracking */ + int w, h; /* Current size */ + int startLine; /* Top line in display */ + int endLine; /* Bottom line in display */ + int bottomSpace; /* Space at bottom of screen */ + int flagWord; /* If non-zero, not at end */ + + /* For handling ExposeCopy events */ + int exposeSize; /* Current size of array */ + int exposeAlloc; /* Allocated size */ + struct expEvent **exposeAry;/* Array of line indices */ + + /* Drawing position information */ + int curLine; /* Current line in buffer */ + int curX; /* Current horizontal positi */ + int curY; /* Current vertical drawing */ +}; + +/* Flags for the various basic character handling functions */ + +#define DODISP 0x01 /* Update the display */ +#define NONEWLINE 0x02 /* Dont append newline */ + + + +static int InitLine(newLine) +struct txtLine *newLine; /* Newly created line structure */ +/* + * This routine initializes a newly created line structure. + */ +{ + newLine->lineLength = 0; + newLine->lineHeight = 0; + newLine->lineBaseLine = 0; + newLine->lineWidth = XPADDING; + newLine->lineText = NOINDEX; + newLine->lineFlags = 0; + return 1; +} + + + + +int TxtGrab(display, txtWin, program, mainFont, bg, fg, cur) +Display *display; /* display window is on */ +Window txtWin; /* Window to take over as scrollable text */ +char *program; /* Program name for Xdefaults */ +XFontStruct *mainFont; /* Primary text font */ +int bg, fg, cur; /* Background, foreground, and cursor colors */ +/* + * This routine takes control of 'txtWin' and makes it into a scrollable + * text output window. It will create a sub-window for the scroll bar + * with a background of 'bg' and an bar with color 'fg'. Both fixed width + * and variable width fonts are supported. Additional fonts can be loaded + * using 'TxtAddFont'. Returns 0 if there were problems, non-zero if + * everything went ok. + */ +{ + struct txtWin *newWin; /* Text package specific information */ + XWindowAttributes winInfo; /* Window information */ + int index; + XGCValues gc_val; + + if (textWindows == (XAssocTable *) 0) { + textWindows = XCreateAssocTable(32); + if (textWindows == (XAssocTable *) 0) return(0); + } + if (XGetWindowAttributes(display, txtWin, &winInfo) == 0) return 0; + + if (ScrollOption == NOOPTION) { + /* Read to see if the user wants jump scrolling or not */ + if (XGetDefault(display, program, "JumpScroll")) { + ScrollOption = JUMPSCROLL; + } else { + ScrollOption = NORMSCROLL; + } + } + + /* Initialize local structure */ + newWin = alloc(struct txtWin); + + /* Initialize arrow pixmap */ + newWin->arrowMap = XCreatePixmapFromBitmapData(display, txtWin, + arrow_bits, + arrow_width, arrow_height, + cur, bg, + DisplayPlanes(display, 0)); + + newWin->bufAlloc = INITBUFSIZE; + newWin->bufSpot = 0; + newWin->mainBuffer = numalloc(short, INITBUFSIZE); + + newWin->numLines = 1; + newWin->allocLines = INITLINES; + newWin->txtBuffer = numalloc(struct txtLine *, INITLINES); + for (index = 0; index < INITLINES; index++) { + newWin->txtBuffer[index] = alloc(struct txtLine); + InitLine(newWin->txtBuffer[index]); + } + + /* Window display information */ + newWin->mainWindow = txtWin; + newWin->w = winInfo.width; + newWin->h = winInfo.height; + newWin->startLine = 0; + newWin->endLine = 0; + newWin->bottomSpace = winInfo.height + - YPADDING - mainFont->ascent - mainFont->descent - INTERLINE; + newWin->flagWord = 0; + newWin->bgPix = bg; + newWin->fgPix = fg; + + /* Scroll Bar Creation */ + newWin->scrollBar = XCreateSimpleWindow(display, txtWin, + winInfo.width - BARSIZE, + 0, BARSIZE - (2*BARBORDER), + winInfo.height - (2*BARBORDER), + BARBORDER, + fg, bg); + XSelectInput(display, newWin->scrollBar, ExposureMask|ButtonReleaseMask); + XMapRaised(display, newWin->scrollBar); + + /* Font and Color Initialization */ + newWin->theFonts[0] = *mainFont; + newWin->theColors[0] = fg; + gc_val.function = GXcopy; + gc_val.plane_mask = AllPlanes; + gc_val.foreground = fg; + gc_val.background = bg; + gc_val.graphics_exposures = 1; + gc_val.font = mainFont->fid; + gc_val.line_width = 1; + gc_val.line_style = LineSolid; + + newWin->fontGC[0] = XCreateGC(display, txtWin, + GCFunction | GCPlaneMask | + GCForeground | GCBackground | + GCGraphicsExposures | GCFont, + &gc_val); + + gc_val.foreground = cur; + newWin->CursorGC = XCreateGC(display, txtWin, + GCFunction | GCPlaneMask | + GCForeground | GCBackground | + GCLineStyle | GCLineWidth, + &gc_val); + + gc_val.foreground = bg; + newWin->bgGC = XCreateGC(display, txtWin, + GCFunction | GCPlaneMask | + GCForeground | GCBackground | + GCGraphicsExposures | GCFont, + &gc_val); + + + for (index = 1; index < MAXFONTS; index++) { + newWin->theFonts[index].fid = 0; + newWin->fontGC[index] = 0; + } + + + /* Initialize size of first line */ + newWin->txtBuffer[0]->lineHeight = newWin->theFonts[0].ascent + + newWin->theFonts[0].descent; + newWin->txtBuffer[0]->lineText = 0; + + /* ExposeCopy array initialization */ + newWin->exposeSize = 0; + newWin->exposeAlloc = INITEXPARY; + newWin->exposeAry = numalloc(struct expEvent *, INITEXPARY); + for (index = 0; index < newWin->exposeAlloc; index++) + newWin->exposeAry[index] = alloc(struct expEvent); + /* Put plus infinity in last slot for sorting purposes */ + newWin->exposeAry[0]->lineIndex = MAXINT; + + /* Drawing Position Information */ + newWin->curLine = 0; + newWin->curX = 0; + newWin->curY = YPADDING + mainFont->ascent + mainFont->descent; + + /* Attach it to both windows */ + XMakeAssoc(display, textWindows, (XID) txtWin, (caddr_t) newWin); + XMakeAssoc(display, textWindows, (XID) newWin->scrollBar, (caddr_t) newWin); + return 1; +} + + +int TxtRelease(display, w) +Display *display; +Window w; /* Window to release */ +/* + * This routine releases all resources associated with the + * specified window which are consumed by the text + * window package. This includes the entire text buffer, line start + * array, and the scroll bar window. However, the window + * itself is NOT destroyed. The routine will return zero if + * the window is not owned by the text window package. + */ +{ + struct txtWin *textInfo; + int index; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, + textWindows, (XID) w)) == 0) + return 0; + + for (index = 0; index < MAXFONTS; index++) + if (textInfo->fontGC[index] != 0) + XFreeGC(display, textInfo->fontGC[index]); + + free((Generic) textInfo->mainBuffer); + for (index = 0; index < textInfo->numLines; index++) { + free((Generic) textInfo->txtBuffer[index]); + } + free((Generic) textInfo->txtBuffer); + XDestroyWindow(display, textInfo->scrollBar); + for (index = 0; index < textInfo->exposeSize; index++) { + free((Generic) textInfo->exposeAry[index]); + } + free((Generic) textInfo->exposeAry); + XDeleteAssoc(display, textWindows, (XID) w); + free((Generic) textInfo); + return 1; +} + + + +static int RecompBuffer(textInfo) +struct txtWin *textInfo; /* Text window information */ +/* + * This routine recomputes all line breaks in a buffer after + * a change in window size or font. This is done by throwing + * away the old line start array and recomputing it. Although + * a lot of this work is also done elsewhere, it has been included + * inline here for efficiency. + */ +{ + int startPos, endSize, linenum; + register int index, chsize, curfont; + register short *bufptr; + register XFontStruct *fontptr; + register struct txtLine *lineptr; + char theChar; + + /* Record the old position so we can come back to it */ + for (startPos = textInfo->txtBuffer[textInfo->startLine]->lineText; + (startPos > 0) && (textInfo->mainBuffer[startPos] != '\n'); + startPos--) + /* null loop body */; + + /* Clear out the old line start array */ + for (index = 0; index < textInfo->numLines; index++) { + InitLine(textInfo->txtBuffer[index]); + } + + /* Initialize first line */ + textInfo->txtBuffer[0]->lineHeight = + textInfo->theFonts[0].ascent + textInfo->theFonts[0].descent; + textInfo->txtBuffer[0]->lineText = 0; + + /* Process the text back into lines */ + endSize = textInfo->w - BARSIZE - WRAPINDSIZE; + bufptr = textInfo->mainBuffer; + lineptr = textInfo->txtBuffer[0]; + linenum = 0; + fontptr = &(textInfo->theFonts[0]); + curfont = 0; + for (index = 0; index < textInfo->bufSpot; index++) { + theChar = bufptr[index] & CHARMASK; + + if ((bufptr[index] & FONTMASK) != curfont) { + int newFontNum, heightDiff; + + /* Switch fonts */ + newFontNum = (bufptr[index] & FONTMASK) >> FONTSHIFT; + if (textInfo->theFonts[newFontNum].fid != 0) { + /* Valid font */ + curfont = bufptr[index] & FONTMASK; + fontptr = &(textInfo->theFonts[newFontNum]); + heightDiff = (fontptr->ascent + fontptr->descent) - + lineptr->lineHeight; + if (heightDiff < 0) heightDiff = 0; + lineptr->lineHeight += heightDiff; + } + } + if (theChar == '\n') { + /* Handle new line */ + if (linenum >= textInfo->allocLines-1) + /* Expand number of lines */ + ExpandLines(textInfo); + linenum++; + lineptr = textInfo->txtBuffer[linenum]; + /* Initialize next line */ + lineptr->lineHeight = fontptr->ascent + fontptr->descent; + lineptr->lineText = index+1; + /* Check to see if its the starting line */ + if (index == startPos) textInfo->startLine = linenum; + } else { + /* Handle normal character */ + chsize = CharSize(textInfo, linenum, index); + if (lineptr->lineWidth + chsize > endSize) { + /* Handle line wrap */ + lineptr->lineFlags |= WRAPFLAG; + if (linenum >= textInfo->allocLines-1) + /* Expand number of lines */ + ExpandLines(textInfo); + linenum++; + lineptr = textInfo->txtBuffer[linenum]; + /* Initialize next line */ + lineptr->lineHeight = fontptr->ascent + fontptr->descent; + lineptr->lineText = index; + lineptr->lineLength = 1; + lineptr->lineWidth += chsize; + } else { + /* Handle normal addition of character */ + lineptr->lineLength += 1; + lineptr->lineWidth += chsize; + } + } + } + /* We now have a valid line array. Let's clean up some other fields. */ + textInfo->numLines = linenum+1; + if (startPos == 0) { + textInfo->startLine = 0; + } + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + textInfo->curLine = linenum; + /* Check to see if we are at the bottom */ + if (textInfo->endLine >= textInfo->numLines-1) { + textInfo->curY = textInfo->h - textInfo->bottomSpace - + lineptr->lineHeight; + textInfo->flagWord &= (~NOTATBOTTOM); + } else { + textInfo->flagWord |= NOTATBOTTOM; + } + return 1; +} + + + + +int TxtAddFont(display, textWin, fontNumber, newFont, newColor) +Display *display; +Window textWin; /* Scrollable text window */ +int fontNumber; /* Place to add font (0-7) */ +XFontStruct *newFont; /* Font to add */ +int newColor; /* Color of font */ +/* + * This routine loads a new font so that it can be used in a previously + * created text window. There are eight font slots numbered 0 through 7. + * If there is already a font in the specified slot, it will be replaced + * and an automatic redraw of the window will take place. See TxtWriteStr + * for details on using alternate fonts. The color specifies the foreground + * color of the text. The default foreground color is used if this + * parameter is TXT_NO_COLOR. Returns a non-zero value if + * everything went well. + */ +{ + struct txtWin *textInfo; + int redrawFlag; + XGCValues gc_val; + + if ((fontNumber < 0) || (fontNumber >= MAXFONTS)) return 0; + if ((textInfo = (struct txtWin *) + XLookUpAssoc(display, textWindows, (XID) textWin)) == 0) + return 0; + if (newColor == TXT_NO_COLOR) { + newColor = textInfo->fgPix; + } + + gc_val.font = newFont->fid; + gc_val.foreground = newColor; + gc_val.background = textInfo->bgPix; + gc_val.plane_mask = AllPlanes; + gc_val.graphics_exposures = 1; + gc_val.function = GXcopy; + + if (textInfo->fontGC[fontNumber] != 0) + { + XChangeGC(display, textInfo->fontGC[fontNumber], + GCFont | GCForeground, &gc_val); + } + else + textInfo->fontGC[fontNumber] = XCreateGC(display, textWin, + GCFont | + GCForeground | + GCBackground | + GCFunction | + GCPlaneMask | + GCGraphicsExposures, + &gc_val); + + + redrawFlag = (textInfo->theFonts[fontNumber].fid != 0) && + (((newFont) && (newFont->fid != textInfo->theFonts[fontNumber].fid)) || + (newColor != textInfo->theColors[fontNumber])); + if (newFont) { + textInfo->theFonts[fontNumber] = *newFont; + } + textInfo->theColors[fontNumber] = newColor; + + if (redrawFlag) { + RecompBuffer(textInfo); + XClearWindow(display, textWin); + TxtRepaint(display, textWin); + } + return 1; +} + + + +int TxtWinP(display, w) +Display *display; +Window w; +/* + * Returns a non-zero value if the window has been previously grabbed + * using TxtGrab and 0 if it has not. + */ +{ + if (XLookUpAssoc(display, textWindows, (XID) w)) + return(1); + else return(0); +} + + + +static int FindEndLine(textInfo, botSpace) +struct txtWin *textInfo; +int *botSpace; +/* + * Given the starting line in 'textInfo->startLine', this routine + * determines the index of the last line that can be drawn given the + * current size of the screen. If there are not enough lines to + * fill the screen, the index of the last line will be returned. + * The amount of empty bottom space is returned in 'botSpace'. + */ +{ + int index, height, lineHeight; + + height = YPADDING; + index = textInfo->startLine; + while (index < textInfo->numLines) { + lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE; + if (height + lineHeight > textInfo->h) break; + height += lineHeight; + index++; + } + if (botSpace) { + *botSpace = textInfo->h - height; + } + return index - 1; +} + + + +static int UpdateScroll(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * This routine computes the current extent of the scroll bar + * indicator and repaints the bar with the correct information. + */ +{ + int top, bottom; + + if (textInfo->numLines > 1) { + top = textInfo->startLine * (textInfo->h - 2*BARBORDER) / + (textInfo->numLines - 1); + bottom = textInfo->endLine * (textInfo->h - 2*BARBORDER) / + (textInfo->numLines - 1); + } else { + top = 0; + bottom = textInfo->h - (2*BARBORDER); + } + + /* Draw it - make sure there is a little padding */ + if (top == 0) top++; + if (bottom == textInfo->h-(2*BARBORDER)) bottom--; + + XFillRectangle(display, textInfo->scrollBar, + textInfo->bgGC, + 0, 0, BARSIZE, top-1); + XFillRectangle(display, textInfo->scrollBar, + DEFAULT_GC, top, BARSIZE - (2*BARBORDER) - 2, + bottom - top); + XFillRectangle(display, textInfo->scrollBar, DEFAULT_GC, + 0, bottom+1, BARSIZE, + textInfo->h - (2 * BARBORDER) - bottom); + + return 1; +} + + + + +int TxtClear(display, w) +Display *display; +Window w; +/* + * This routine clears a scrollable text window. It resets the current + * writing position to the upper left hand corner of the screen. + * NOTE: THIS ALSO CLEARS THE CONTENTS OF THE TEXT WINDOW BUFFER AND + * RESETS THE SCROLL BAR. Returns 0 if the window is not a text window. + * This should be used *instead* of XClear. + */ +{ + struct txtWin *textInfo; + int index; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) + return 0; + + /* Zero out the arrays */ + textInfo->bufSpot = 0; + for (index = 0; index < textInfo->numLines; index++) { + InitLine(textInfo->txtBuffer[index]); + } + textInfo->txtBuffer[0]->lineHeight = + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent; + + textInfo->numLines = 1; + textInfo->startLine = 0; + textInfo->endLine = 0; + textInfo->curLine = 0; + textInfo->curX = 0; + textInfo->curY = YPADDING + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent; + + textInfo->bottomSpace = textInfo->h - YPADDING - + textInfo->theFonts[textInfo->curFont].ascent - INTERLINE - + textInfo->theFonts[textInfo->curFont].descent; + /* Actually clear the window */ + XClearWindow(display, w); + + /* Draw the current cursor */ + XFillRectangle(display, w, textInfo->CursorGC, + XPADDING + CUROFFSET, textInfo->curY, + CURSORWIDTH, + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent); + + /* Update the scroll bar */ + UpdateScroll(display, textInfo); + return 1; +} + + +static int WarpToBottom(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text Information */ +/* + * This routine causes the specified text window to display its + * last screen of information. It updates the scroll bar + * to the appropriate spot. The implementation scans backward + * through the buffer to find an appropriate starting spot for + * the window. + */ +{ + int index, height, lineHeight; + + index = textInfo->numLines-1; + height = 0; + while (index >= 0) { + lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE; + if (height + lineHeight > textInfo->h) break; + height += lineHeight; + index--; + } + textInfo->startLine = index + 1; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + textInfo->curY = textInfo->h - textInfo->bottomSpace - + textInfo->txtBuffer[textInfo->endLine]->lineHeight; + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + return 1; +} + + + +static int UpdateExposures(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * Before a new scrolling action occurs, the text window package + * must handle all COPYEXPOSE events generated by the last scrolling + * action. This routine is called to do this. Foreign events (those + * not handled by TxtFilter) are queued up and replaced on the queue + * after the processing of the exposure events is complete. + */ +{ +#if 0 + XEvent foreignQueue[MAXFOREIGN]; + int index, lastItem = 0; + + while (textInfo->flagWord & COPYEXPOSE) { + XNextEvent(display, &(foreignQueue[lastItem])); + if (!TxtFilter(display, &(foreignQueue[lastItem]))) + lastItem++; + if (lastItem >= MAXFOREIGN) { + printf("Too many foreign events to queue!\n"); + textInfo->flagWord &= (~COPYEXPOSE); + } + } + for (index = 0; index < lastItem; index++) { + XPutBackEvent(display, &(foreignQueue[index])); + } +#endif + return 1; +} + + +static int ScrollDown(display,textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * This routine scrolls the indicated text window down by one + * line. The line below the current line must exist. The window + * is scrolled so that the line below the last line is fully + * displayed. This may cause many lines to scroll off the top. + * Scrolling is done using XCopyArea. The exposure events should + * be caught using ExposeCopy. + */ +{ + int lineSum, index, targetSpace, freeSpace, updateFlag; + + lineSum = 0; + if (textInfo->endLine + 1 >= textInfo->numLines) return 0; + targetSpace = textInfo->txtBuffer[textInfo->endLine+1]->lineHeight + + INTERLINE; + if (textInfo->bottomSpace < targetSpace) { + index = textInfo->startLine; + while (index < textInfo->endLine) { + lineSum += (textInfo->txtBuffer[index]->lineHeight + INTERLINE); + if (textInfo->bottomSpace + lineSum >= targetSpace) break; + index++; + } + + /* Must move upward by 'lineSum' pixels */ + XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow, + DEFAULT_GC, 0, lineSum, + textInfo->w - BARSIZE, textInfo->h, + 0, 0); + + textInfo->flagWord |= COPYEXPOSE; + /* Repair the damage to the structures */ + textInfo->startLine = index + 1; + updateFlag = 1; + } else { + updateFlag = 0; + } + /* More lines might be able to fit. Let's check. */ + freeSpace = textInfo->bottomSpace + lineSum - targetSpace; + index = textInfo->endLine + 1; + while (index < textInfo->numLines-1) { + if (freeSpace - textInfo->txtBuffer[index+1]->lineHeight - INTERLINE < 0) + break; + freeSpace -= (textInfo->txtBuffer[index+1]->lineHeight + INTERLINE); + index++; + } + textInfo->endLine = index; + textInfo->bottomSpace = freeSpace; + if (updateFlag) { + UpdateExposures(display, textInfo); + } + UpdateScroll(display, textInfo); + return 1; +} + + + + +static int ExpandLines(textInfo) +struct txtWin *textInfo; /* Text Information */ +/* + * This routine allocates and initializes additional space in + * the line start array (txtBuffer). The new space + * is allocated using realloc. The expansion factor is a percentage + * given by EXPANDPERCENT. + */ +{ + int newSize, index; + + newSize = textInfo->allocLines; + newSize += (newSize * EXPANDPERCENT) / 100; + + textInfo->txtBuffer = (struct txtLine **) + realloc((char *) textInfo->txtBuffer, + (unsigned) (newSize * sizeof(struct txtLine *))); + for (index = textInfo->allocLines; index < newSize; index++) { + textInfo->txtBuffer[index] = alloc(struct txtLine); + InitLine(textInfo->txtBuffer[index]); + } + textInfo->allocLines = newSize; + return 1; +} + +static int ExpandBuffer(textInfo) +struct txtWin *textInfo; /* Text information */ +/* + * Expands the basic character buffer using realloc. The expansion + * factor is a percentage given by EXPANDPERCENT. + */ +{ + int newSize; + + newSize = textInfo->bufAlloc + (textInfo->bufAlloc * EXPANDPERCENT) / 100; + textInfo->mainBuffer = (short *) + realloc((char *) textInfo->mainBuffer, (unsigned) newSize * sizeof(short)); + textInfo->bufAlloc = newSize; + return 1; +} + + + +static int HandleNewLine(display, textInfo, flagWord) +Display *display; +struct txtWin *textInfo; /* Text Information */ +int flagWord; /* DODISP or NONEWLINE or both */ +/* + * This routine initializes the next line for drawing by setting + * its height to the current font height, scrolls the screen down + * one line, and updates the current drawing position to the + * left edge of the newly cleared line. If DODISP is specified, + * the screen will be updated (otherwise not). If NONEWLINE is + * specified, no newline character will be added to the text buffer + * (this is for line wrap). + */ +{ + struct txtLine *curLine, *nextLine; + + /* Check to see if a new line must be allocated */ + if (textInfo->curLine >= textInfo->allocLines-1) + /* Expand the number of lines */ + ExpandLines(textInfo); + textInfo->numLines += 1; + + /* Then we initialize the next line */ + nextLine = textInfo->txtBuffer[textInfo->numLines-1]; + nextLine->lineHeight = + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent; + + curLine = textInfo->txtBuffer[textInfo->curLine]; + if (flagWord & DODISP) { + /* Scroll down a line if required */ + if ((textInfo->curY + curLine->lineHeight + + nextLine->lineHeight + (INTERLINE * 2)) > textInfo->h) + { + ScrollDown(display, textInfo); + } + else + { + /* Update the bottom space appropriately */ + textInfo->bottomSpace -= (nextLine->lineHeight + INTERLINE); + textInfo->endLine += 1; + } + /* Update drawing position */ + textInfo->curY = textInfo->h - + (textInfo->bottomSpace + nextLine->lineHeight); + } + + /* Move down a line */ + textInfo->curLine += 1; + if (!(flagWord & NONEWLINE)) { + /* Append end-of-line to text buffer */ + if (textInfo->bufSpot >= textInfo->bufAlloc) { + /* Allocate more space in main text buffer */ + ExpandBuffer(textInfo); + } + textInfo->mainBuffer[(textInfo->bufSpot)++] = + (textInfo->curFont << FONTSHIFT) | '\n'; + } + nextLine->lineText = textInfo->bufSpot; + textInfo->curX = 0; + return 1; +} + + + +static int CharSize(textInfo, lineNum, charNum) +struct txtWin *textInfo; /* Current Text Information */ +int lineNum; /* Line in buffer */ +int charNum; /* Character in line */ +/* + * This routine determines the size of the specified character. + * It takes in account the font of the character and whether its + * fixed or variable. The size includes INTERSPACE spacing between + * the characters. + */ +{ + register XFontStruct *charFont; + register short *theLine; + register short theChar; + + theLine = &(textInfo->mainBuffer[textInfo->txtBuffer[lineNum]->lineText]); + theChar = theLine[charNum] & CHARMASK; + charFont = &(textInfo->theFonts[(theChar & FONTMASK) >> FONTSHIFT]); + if (theChar <= charFont->min_char_or_byte2 || + theChar >= charFont->max_char_or_byte2 || + charFont->per_char == 0) + return charFont->max_bounds.width + 1; + else + return charFont->per_char[theChar].width + 1; +} + + + + + +static int HandleBackspace(display, textInfo, flagWord) +Display *display; +struct txtWin *textInfo; /* Text Information */ +int flagWord; /* DODISP or nothing */ +/* + * This routine handles a backspace found in the input stream. The + * character before the current writing position will be erased and + * the drawing position will move back one character. If the writing + * position is at the left margin, the drawing position will move + * up to the previous line. If it is a line that has been wrapped, + * the character at the end of the previous line will be erased. + */ +{ + struct txtLine *thisLine, *prevLine; + int chSize; + + thisLine = textInfo->txtBuffer[textInfo->curLine]; + /* First, determine whether we need to go back a line */ + if (thisLine->lineLength == 0) { + /* Bleep if at top of buffer */ + if (textInfo->curLine == 0) { + XBell(display, 50); + return 0; + } + + /* See if we have to scroll in the other direction */ + if ((flagWord & DODISP) && (textInfo->curY <= YPADDING)) { + /* This will display the last lines of the buffer */ + WarpToBottom(display, textInfo); + } + + /* Set drawing position at end of previous line */ + textInfo->curLine -= 1; + prevLine = textInfo->txtBuffer[textInfo->curLine]; + textInfo->numLines -= 1; + if (flagWord & DODISP) { + textInfo->curY -= (prevLine->lineHeight + INTERLINE); + textInfo->bottomSpace += (thisLine->lineHeight + INTERLINE); + textInfo->endLine -= 1; + } + + /* We are unlinewrapping if the previous line has flag set */ + if (prevLine->lineFlags & WRAPFLAG) { + /* Get rid of line wrap indicator */ + if (flagWord & DODISP) { + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + textInfo->w - BARSIZE - WRAPINDSIZE, + textInfo->curY, WRAPINDSIZE, + prevLine->lineHeight); + } + prevLine->lineFlags &= (~WRAPFLAG); + /* Call recursively to wipe out the ending character */ + HandleBackspace(display, textInfo, flagWord); + } else { + /* Delete the end-of-line in the primary buffer */ + textInfo->bufSpot -= 1; + } + } else { + /* Normal deletion of character */ + chSize = + CharSize(textInfo, textInfo->curLine, + textInfo->txtBuffer[textInfo->curLine]->lineLength - 1); + /* Move back appropriate amount and wipe it out */ + thisLine->lineWidth -= chSize; + if (flagWord & DODISP) { + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + thisLine->lineWidth, textInfo->curY, + chSize, thisLine->lineHeight); + } + /* Delete from buffer */ + textInfo->txtBuffer[textInfo->curLine]->lineLength -= 1; + textInfo->bufSpot -= 1; + } + return 1; +} + + + +static int DrawLineWrap(display, win, x, y, h, col) +Display *display; +Window win; /* What window to draw it in */ +int x, y; /* Position of upper left corner */ +int h; /* Height of indicator */ +int col; /* Color of indicator */ +/* + * This routine draws a line wrap indicator at the end of a line. + * Visually, it is an arrow of the specified height directly against + * the scroll bar border. The bitmap used for the arrow is stored + * in 'arrowMap' with size 'arrow_width' and 'arrow_height'. + */ +{ + struct txtWin *textInfo; + + textInfo = (struct txtWin *)XLookUpAssoc(display, textWindows, + (XID) win); + + /* First, draw the arrow */ + XCopyArea(display, textInfo->arrowMap, textInfo->mainWindow, + textInfo->CursorGC, + 0, 0, arrow_width, arrow_height, + x, y + h - arrow_height, 1); + + /* Then draw the stem */ + XDrawLine(display, textInfo->mainWindow, textInfo->CursorGC, + x + STEMOFFSET, y, + x + STEMOFFSET, y + h - arrow_height); + return 1; +} + + + + +static int DrawLine(display, textInfo, lineIndex, ypos) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int lineIndex; /* Index of line to draw */ +int ypos; /* Y position for line */ +/* + * This routine destructively draws the indicated line in the + * indicated window at the indicated position. It does not + * clear to end of line however. It draws a line wrap indicator + * if needed but does not draw a cursor. + */ +{ + int index, startPos, curFont, theColor, curX, saveX, fontIndex; + struct txtLine *someLine; + char lineBuffer[BUFSIZE], *glyph; + short *linePointer; + XFontStruct *theFont; + XGCValues gc; + + /* First, we draw the text */ + index = 0; + curX = XPADDING; + someLine = textInfo->txtBuffer[lineIndex]; + linePointer = &(textInfo->mainBuffer[someLine->lineText]); + while (index < someLine->lineLength) { + startPos = index; + saveX = curX; + curFont = linePointer[index] & FONTMASK; + fontIndex = curFont >> FONTSHIFT; + theFont = &(textInfo->theFonts[fontIndex]); + theColor = textInfo->theColors[fontIndex]; + glyph = &(lineBuffer[0]); + while ((index < someLine->lineLength) && + ((linePointer[index] & FONTMASK) == curFont)) + { + *glyph = linePointer[index] & CHARMASK; + index++; + curX += CharSize(textInfo, lineIndex, index); + glyph++; + } + + /* Flush out the glyphs */ + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + saveX, ypos, + textInfo->w - BARSIZE, + someLine->lineHeight + YPADDING + INTERLINE); + + XDrawString(display, textInfo->mainWindow, + textInfo->fontGC[fontIndex], + saveX, ypos, + lineBuffer, someLine->lineLength); + } + /* Then the line wrap indicator (if needed) */ + if (someLine->lineFlags & WRAPFLAG) { + DrawLineWrap(display, textInfo->mainWindow, + textInfo->w - BARSIZE - WRAPINDSIZE, + ypos, someLine->lineHeight, + textInfo->fgPix); + } + return 1; +} + + + + +static int HandleNewFont(display, fontNum, textInfo, flagWord) +Display *display; +int fontNum; /* Font number */ +struct txtWin *textInfo; /* Text information */ +int flagWord; /* DODISP or nothing */ +/* + * This routine handles a new font request. These requests take + * the form "^F". The parsing is done in TxtWriteStr. + * This routine is called only if the form is valid. It may return + * a failure (0 status) if the requested font is not loaded. + * If the new font is larger than any of the current + * fonts on the line, it will change the line height and redisplay + * the line. + */ +{ + struct txtLine *thisLine; + int heightDiff, baseDiff, redrawFlag; + + if (textInfo->theFonts[fontNum].fid == 0) { + return 0; + } else { + thisLine = textInfo->txtBuffer[textInfo->curLine]; + textInfo->curFont = fontNum; + redrawFlag = 0; + heightDiff = textInfo->theFonts[fontNum].ascent + + textInfo->theFonts[fontNum].descent - + thisLine->lineHeight; + + if (heightDiff > 0) { + redrawFlag = 1; + } else { + heightDiff = 0; + } + + if (redrawFlag) { + if (flagWord & DODISP) { + /* Clear current line */ + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + 0, textInfo->curY, textInfo->w, + thisLine->lineHeight); + + /* Check to see if it requires scrolling */ + if ((textInfo->curY + thisLine->lineHeight + heightDiff + + INTERLINE) > textInfo->h) + { + /* + * General approach: "unscroll" the last line up + * and then call ScrollDown to do the right thing. + */ + textInfo->endLine -= 1; + textInfo->bottomSpace += thisLine->lineHeight + + INTERLINE; + + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + 0, textInfo->h - textInfo->bottomSpace, + textInfo->w, textInfo->bottomSpace); + + thisLine->lineHeight += heightDiff; + ScrollDown(display, textInfo); + textInfo->curY = textInfo->h - + (textInfo->bottomSpace + INTERLINE + + thisLine->lineHeight); + } + else + { + /* Just update bottom space */ + textInfo->bottomSpace -= heightDiff; + thisLine->lineHeight += heightDiff; + } + /* Redraw the current line */ + DrawLine(display, textInfo, textInfo->curLine, textInfo->curY); + } else { + /* Just update line height */ + thisLine->lineHeight += heightDiff; + } + } + return 1; + } +} + + + +int TxtWriteStr(display, w, str) +Display *display; +Window w; /* Text window */ +register char *str; /* 0 terminated string */ +/* + * This routine writes a string to the specified text window. + * The following notes apply: + * - Text is always appended to the end of the text buffer. + * - If the scroll bar is positioned such that the end of the + * text is not visible, an automatic scroll to the bottom + * will be done before the appending of text. + * - Non-printable ASCII characters are not displayed. + * - The '\n' character causes the current text position to + * advance one line and start at the left. + * - Tabs are not supported. + * - Lines too long for the screen will be wrapped and a line wrap + * indication will be drawn. + * - Backspace clears the previous character. It will do the right + * thing if asked to backspace past a wrapped line. + * - A new font can be chosen using the sequence '^F' where + * is 0-7. The directive will be ignored if + * there is no font in the specified slot. + * Returns 0 if something went wrong. + */ +{ + register int fontIndex; + register struct txtWin *textInfo; + register struct txtLine *thisLine; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) + return 0; + + /* See if screen needs to be updated */ + if (textInfo->flagWord & SCREENWRONG) { + TxtRepaint(display, textInfo->mainWindow); + } + + /* See if we have to scroll down to the bottom */ + if (textInfo->flagWord & NOTATBOTTOM) { + WarpToBottom(display, textInfo); + textInfo->flagWord &= (~NOTATBOTTOM); + } + + /* Undraw the current cursor */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + + XFillRectangle(display, w, textInfo->bgGC, + thisLine->lineWidth + CUROFFSET, + textInfo->curY, + CURSORWIDTH, + thisLine->lineHeight); + + for ( /* str is ok */ ; (*str != 0) ; str++) { + /* Check to see if we are waiting on a font */ + if (textInfo->flagWord & FONTNUMWAIT) { + textInfo->flagWord &= (~FONTNUMWAIT); + fontIndex = *str - '0'; + if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) { + /* Handle font -- go get next character */ + if (HandleNewFont(display, fontIndex, textInfo, DODISP)) + continue; + } + } + + /* Inline code for handling normal character case */ + if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) { + register XFontStruct *thisFont; + register struct txtLine *thisLine; + register int charWidth; + int thisColor; + + /* Determine size of character */ + thisFont = &(textInfo->theFonts[textInfo->curFont]); + thisColor = textInfo->theColors[textInfo->curFont]; + if (*str <= thisFont->min_char_or_byte2 || + *str >= thisFont->max_char_or_byte2 || + thisFont->per_char == 0) + charWidth = thisFont->max_bounds.width + 1; + else + charWidth = thisFont->per_char[*str].width + 1; + + /* Check to see if line wrap is required */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + if (thisLine->lineWidth + charWidth > + (textInfo->w-BARSIZE-WRAPINDSIZE)) + { + DrawLineWrap(display, textInfo->mainWindow, + textInfo->w-BARSIZE-WRAPINDSIZE, + textInfo->curY, thisLine->lineHeight, + textInfo->fgPix); + thisLine->lineFlags |= WRAPFLAG; + /* Handle the spacing problem the same way as a newline */ + HandleNewLine(display, textInfo, DODISP | NONEWLINE); + thisLine = textInfo->txtBuffer[textInfo->curLine]; + } + + /* Ready to draw character */ + XDrawString(display, textInfo->mainWindow, + DEFAULT_GC, + textInfo->curX += charWidth, + textInfo->curY + thisLine->lineHeight, + str, 1); + + /* Append character onto main buffer */ + if (textInfo->bufSpot >= textInfo->bufAlloc) + /* Make room for more characters */ + ExpandBuffer(textInfo); + textInfo->mainBuffer[(textInfo->bufSpot)++] = + (textInfo->curFont << FONTSHIFT) | (*str); + + /* Update the line start array */ + thisLine->lineLength += 1; + thisLine->lineWidth += charWidth; + } else if (*str == NEWLINE) { + HandleNewLine(display, textInfo, DODISP); + } else if (*str == NEWFONT) { + /* Go into waiting for font number mode */ + textInfo->flagWord |= FONTNUMWAIT; + } else if (*str == BACKSPACE) { + HandleBackspace(display, textInfo, DODISP); + } else { + /* Ignore all others */ + } + } + /* Draw the cursor in its new position */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + + XFillRectangle(display, w, textInfo->CursorGC, + thisLine->lineWidth + CUROFFSET, + textInfo->curY /* + thisLine->lineHeight */, + CURSORWIDTH, thisLine->lineHeight); + + return 1; +} + + + +int TxtJamStr(display, w, str) +Display *display; +Window w; /* Text window */ +register char *str; /* NULL terminated string */ +/* + * This is the same as TxtWriteStr except the screen is NOT updated. + * After a call to this routine, TxtRepaint should be called to + * update the screen. This routine is meant to be used to load + * a text buffer with information and then allow the user to + * scroll through it at will. + */ +{ + register int fontIndex; + register struct txtWin *textInfo; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w) + ) == 0) + return 0; + + for ( /* str is ok */ ; (*str != 0) ; str++) { + /* Check to see if we are waiting on a font */ + if (textInfo->flagWord & FONTNUMWAIT) { + textInfo->flagWord &= (~FONTNUMWAIT); + fontIndex = *str - '0'; + if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) { + if (HandleNewFont(display, fontIndex, textInfo, 0)) { + /* Handled font -- go get next character */ + continue; + } + } + } + /* Inline code for handling normal character case */ + if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) { + register XFontStruct *thisFont; + register struct txtLine *thisLine; + register int charWidth; + + /* Determine size of character */ + thisFont = &(textInfo->theFonts[textInfo->curFont]); + + if (*str <= thisFont->min_char_or_byte2 || + *str >= thisFont->max_char_or_byte2 || + thisFont->per_char == 0) + charWidth = thisFont->max_bounds.width + 1; + else + charWidth = thisFont->per_char[*str].width + 1; + + /* Check to see if line wrap is required */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + if (thisLine->lineWidth + charWidth > + (textInfo->w-BARSIZE-WRAPINDSIZE)) + { + thisLine->lineFlags |= WRAPFLAG; + /* Handle the spacing problem the same way as a newline */ + HandleNewLine(display, textInfo, NONEWLINE); + thisLine = textInfo->txtBuffer[textInfo->curLine]; + } + /* Append character onto main buffer */ + if (textInfo->bufSpot >= textInfo->bufAlloc) + /* Make room for more characters */ + ExpandBuffer(textInfo); + textInfo->mainBuffer[(textInfo->bufSpot)++] = + (textInfo->curFont << FONTSHIFT) | (*str); + + /* Update the line start array */ + thisLine->lineLength += 1; + thisLine->lineWidth += charWidth; + } else if (*str == NEWLINE) { + HandleNewLine(display, textInfo, 0); + } else if (*str == NEWFONT) { + /* Go into waiting for font number mode */ + textInfo->flagWord |= FONTNUMWAIT; + } else if (*str == BACKSPACE) { + HandleBackspace(display, textInfo, 0); + } else { + /* Ignore all others */ + } + } + textInfo->flagWord |= SCREENWRONG; + return 1; +} + + + +int TxtRepaint(display,w) +Display *display; +Window w; +/* + * Repaints the given scrollable text window. The routine repaints + * the entire window. For handling exposure events, the TxtFilter + * routine should be used. + */ +{ + struct txtWin *textInfo; + int index, ypos; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w) + ) == 0) + return 0; + + /* Check to see if the screen is up to date */ + if (textInfo->flagWord & SCREENWRONG) { + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + textInfo->flagWord &= (~SCREENWRONG); + } + + ypos = YPADDING; + index = textInfo->startLine; + for (;;) { + DrawLine(display, textInfo, index, ypos); + if (index >= textInfo->endLine) break; + ypos += (textInfo->txtBuffer[index]->lineHeight + INTERLINE); + index++; + } + /* Draw the cursor (if on screen) */ + if (textInfo->endLine == textInfo->curLine) { + XFillRectangle(display, w, textInfo->CursorGC, + textInfo->txtBuffer[index]->lineWidth + CUROFFSET, + ypos /* + textInfo->txtBuffer[index]->lineHeight */, + CURSORWIDTH, textInfo->txtBuffer[index]->lineHeight); + + } + /* Update the scroll bar */ + UpdateScroll(display, textInfo); + return 1; +} + + + +static int InsertIndex(textInfo, thisIndex, ypos) +struct txtWin *textInfo; /* Text Window Information */ +int thisIndex; /* Line index of exposed line */ +int ypos; /* Drawing position of line */ +/* + * This routine inserts the supplied line index into the copy + * exposure array for 'textInfo'. The array is kept sorted + * from lowest to highest using insertion sort. The array + * is dynamically expanded if needed. + */ +{ + struct expEvent *newItem; + int newSize, index, downIndex; + + /* Check to see if we need to expand it */ + if ((textInfo->exposeSize + 3) >= textInfo->exposeAlloc) { + newSize = textInfo->exposeAlloc + + (textInfo->exposeAlloc * EXPANDPERCENT / 100); + textInfo->exposeAry = (struct expEvent **) + realloc((char *) textInfo->exposeAry, + (unsigned) (newSize * sizeof(struct expEvent *))); + for (index = textInfo->exposeAlloc; index < newSize; index++) + textInfo->exposeAry[index] = alloc(struct expEvent); + textInfo->exposeAlloc = newSize; + } + /* Find spot for insertion. NOTE: last spot has big number */ + for (index = 0; index <= textInfo->exposeSize; index++) { + if (textInfo->exposeAry[index]->lineIndex >= thisIndex) { + if (textInfo->exposeAry[index]->lineIndex > thisIndex) { + /* Insert before this entry */ + newItem = textInfo->exposeAry[textInfo->exposeSize+1]; + for (downIndex = textInfo->exposeSize; + downIndex >= index; + downIndex--) + { + textInfo->exposeAry[downIndex+1] = + textInfo->exposeAry[downIndex]; + } + /* Put a free structure at this spot */ + textInfo->exposeAry[index] = newItem; + /* Fill it in */ + textInfo->exposeAry[index]->lineIndex = thisIndex; + textInfo->exposeAry[index]->ypos = ypos; + /* Break out of loop */ + textInfo->exposeSize += 1; + } + break; + } + } + return 1; +} + + + +static int ScrollUp(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * This routine scrolls the indicated text window up by one + * line. The line above the current line must exist. The + * window is scrolled so that the line above the start line + * is displayed at the top of the screen. This may cause + * many lines to scroll off the bottom. The scrolling is + * done using XCopyArea. The exposure events should be caught + * by ExposeCopy. + */ +{ + int targetSpace; + + /* Make sure all exposures have been handled by now */ + if (textInfo->startLine == 0) return 0; + targetSpace = textInfo->txtBuffer[textInfo->startLine-1]->lineHeight + + INTERLINE; + /* Move the area downward by the target amount */ + XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow, + DEFAULT_GC, + 0, YPADDING, textInfo->w - BARSIZE, + textInfo->h, 0, targetSpace); + + textInfo->flagWord |= COPYEXPOSE; + /* Update the text window parameters */ + textInfo->startLine -= 1; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + + /* Clear out bottom space region */ + XClearArea(display, textInfo->mainWindow, + 0, textInfo->h - textInfo->bottomSpace, + textInfo->w, textInfo->bottomSpace); + + UpdateExposures(display, textInfo); + UpdateScroll(display, textInfo); + + return 1; +} + + +static int ScrollToSpot(display, textInfo, ySpot) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int ySpot; /* Button position in scroll window */ +/* + * This routine scrolls the specified text window relative to the + * position of the mouse in the scroll bar. The center of the screen + * will be positioned to correspond to the mouse position. + */ +{ + int targetLine, aboveLines; + + targetLine = textInfo->numLines * ySpot / textInfo->h; + textInfo->startLine = targetLine; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + aboveLines = 0; + /* Make the target line the *center* of the window */ + while ((textInfo->startLine > 0) && + (aboveLines < textInfo->endLine - targetLine)) + { + textInfo->startLine -= 1; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + aboveLines++; + } + if (textInfo->endLine == textInfo->numLines-1) { + WarpToBottom(display, textInfo); + } else { + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + } + return 1; +} + + + +static int LineToTop(display, textInfo, pos) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int pos; /* Y position of mouse */ +/* + * This routine scrolls the screen down until the line at the + * mouse position is at the top of the screen. It stops + * if it can't scroll the buffer down that far. If the + * global 'ScrollOption' is NORMSCROLL, a smooth scroll + * is used. Otherwise, it jumps to the right position + * and repaints the screen. + */ +{ + int index, sum; + + /* First, we find the current line */ + sum = 0; + for (index = textInfo->startLine; index <= textInfo->endLine; index++) { + if (sum + textInfo->txtBuffer[index]->lineHeight + INTERLINE> pos) break; + sum += textInfo->txtBuffer[index]->lineHeight + INTERLINE; + } + /* We always want to scroll down at least one line */ + if (index == textInfo->startLine) index++; + if (ScrollOption == NORMSCROLL) { + /* Scroll down until 'index' is the starting line */ + while ((textInfo->startLine < index) && ScrollDown(display, textInfo)) + { + /* Empty Loop Body */ + } + } else { + /* Immediately jump to correct spot */ + textInfo->startLine = index; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + if (textInfo->endLine == textInfo->numLines-1) { + WarpToBottom(display, textInfo); + } else { + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + } + } + /* Check to see if at end of buffer */ + if (textInfo->endLine >= textInfo->numLines-1) { + textInfo->flagWord &= (~NOTATBOTTOM); + } + return 1; +} + + + +static int TopToHere(display, textInfo, pos) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int pos; /* Y position of mouse */ +/* + * This routine scrolls the screen up until the top line of + * the screen is at the current Y position of the mouse. Again, + * it will stop if it can't scroll that far. If the global + * 'ScrollOption' is NORMSCROLL, a smooth scroll is used. + * If it's not, it will simply redraw the screen at the + * correct spot. + */ +{ + int sum, target, linesup, index; + + target = pos - textInfo->txtBuffer[textInfo->startLine]->lineHeight; + /* We always want to scroll up at least one line */ + if (target <= 0) target = 1; + sum = 0; + linesup = 0; + /* Check to see if we are at the top anyway */ + if (textInfo->startLine == 0) return 0; + if (ScrollOption == NORMSCROLL) { + /* Scroll up until sum of new top lines greater than target */ + while ((sum < target) && ScrollUp(display, textInfo)) { + sum += textInfo->txtBuffer[textInfo->startLine]->lineHeight; + linesup++; + } + } else { + /* Search backward to find index */ + index = textInfo->startLine - 1; + while ((index > 0) && (sum < target)) { + sum += textInfo->txtBuffer[index]->lineHeight; + linesup++; + index--; + } + /* Go directly to the index */ + textInfo->startLine = index; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + } + /* If we scrolled, assert we are not at bottom of buffer */ + if (linesup > 0) { + textInfo->flagWord |= NOTATBOTTOM; + } + return 1; +} + + + +int TxtFilter(display, evt) +Display *display; +XEvent *evt; +/* + * This routine handles events associated with scrollable text windows. + * It will handle all exposure events and any button released events + * in the scroll bar of a text window. It does NOT handle any other + * events. If it cannot handle the event, it will return 0. + */ +{ + XExposeEvent *expose = &evt->xexpose; + XButtonEvent *btEvt = &evt->xbutton; + XGraphicsExposeEvent *gexpose = &evt->xgraphicsexpose; + XNoExposeEvent *noexpose = &evt->xnoexpose; + struct txtWin *textInfo; + int index, ypos; + Window w, sw; + + if (textWindows == (XAssocTable *) 0) { + textWindows = XCreateAssocTable(32); + if (textWindows == (XAssocTable *) 0) return(0); + } + if (evt->type == Expose) { + w = expose->window; + sw = 0; + } + else if (evt->type == GraphicsExpose) { + w = gexpose->drawable; + sw = 0; + } + else if (evt->type == NoExpose) { + w = noexpose->drawable; + sw = 0; + } + else if (evt->type == ButtonRelease) { + w = btEvt->window; + sw = btEvt->subwindow; + } + else + return 0; + + if ((textInfo = (struct txtWin *) + XLookUpAssoc(display, textWindows, (XID) w)) == 0) + return 0; + + /* Determine whether it's main window or not */ + if ((w == textInfo->mainWindow) && (sw == 0)) { + /* Main Window - handle exposures */ + switch (evt->type) { + case Expose: + ypos = 0 /*YPADDING*/; + for (index = textInfo->startLine; + index <= textInfo->endLine; + index++) + { + int lh = textInfo->txtBuffer[index]->lineHeight; + + if (((ypos + lh) >= expose->y) && + (ypos <= (expose->y + expose->height))) + { + /* Intersection region */ + /* Draw line immediately */ + DrawLine(display, textInfo, index, ypos); + /* And possibly draw cursor */ + if (textInfo->curLine == index) { + XFillRectangle(display, w, textInfo->CursorGC, + textInfo->txtBuffer[index]->lineWidth + + CUROFFSET, + ypos, + CURSORWIDTH, + lh); + } + } + ypos += lh + INTERLINE; + } + break; + case GraphicsExpose: + ypos = 0 /*YPADDING*/; + for (index = textInfo->startLine; + index <= textInfo->endLine; + index++) + { + int lh = textInfo->txtBuffer[index]->lineHeight; + + if (((ypos + lh) >= gexpose->y) && + (ypos <= (gexpose->y + gexpose->height))) + { + /* Intersection region */ + /* Draw line immediately */ + DrawLine(display, textInfo, index, ypos); + /* And possibly draw cursor */ + if (textInfo->curLine == index) { + XFillRectangle(display, w, textInfo->CursorGC, + textInfo->txtBuffer[index]->lineWidth + + CUROFFSET, + ypos, + CURSORWIDTH, + lh); + } + } + ypos += lh + INTERLINE; + } + break; + case NoExpose: + break; + default: + /* Not one of our events */ + return 0; + } + } else { + switch (evt->type) { + case Expose: + UpdateScroll(display, textInfo); + break; + case ButtonRelease: + /* Find out which button */ + switch (btEvt->button) { + case Button1: + /* Scroll up until top line is at mouse position */ + TopToHere(display, textInfo, btEvt->y); + break; + case Button2: + /* Scroll to spot relative to position */ + ScrollToSpot(display, textInfo, btEvt->y); + if (textInfo->endLine >= textInfo->numLines-1) { + textInfo->flagWord &= (~NOTATBOTTOM); + } else { + textInfo->flagWord |= NOTATBOTTOM; + } + break; + case Button3: + /* Scroll down until pointed line is at top */ + LineToTop(display, textInfo, btEvt->y); + break; + } + break; + default: + /* Not one of our events */ + return 0; + } + } + return 1; +} diff --git a/gnu/games/chess/Xchess/scrollText.h b/gnu/games/chess/Xchess/scrollText.h new file mode 100644 index 000000000000..d9d05b08dc0b --- /dev/null +++ b/gnu/games/chess/Xchess/scrollText.h @@ -0,0 +1,32 @@ +/* + * Scrollable Text Window Header File + * + * David Harrison + * University of California, Berkeley + * 1986 + * + * This file contains definitions for a scrollable text window + * with scroll bar support. + */ + +int TxtGrab(); + /* Take hold of a previously created window */ + +#define TXT_NO_COLOR -1 + +int TxtAddFont(); + /* Loads a new font for use later */ +int TxtWinP(); + /* Returns non-zero value if the window is text window */ +int TxtClear(); + /* Clears text window and resets text buffer */ + +int TxtWriteStr(); + /* Writes a string to window with immediate update */ +int TxtJamStr(); + /* Write a string without causing update to screen */ + +int TxtRepaint(); + /* Repaints entire scrollable text window */ +int TxtFilter(); + /* Handles events related to text window */ diff --git a/gnu/games/chess/Xchess/scrollText/scrollText.c b/gnu/games/chess/Xchess/scrollText/scrollText.c new file mode 100644 index 000000000000..432071086d15 --- /dev/null +++ b/gnu/games/chess/Xchess/scrollText/scrollText.c @@ -0,0 +1,1858 @@ +/* + * A Scrollable Text Output Window + * + * David Harrison + * University of California, Berkeley + * 1986 + * + * The following is an implementation for a scrollable text output + * system. It handles exposure events only (other interactions are + * under user control). For scrolling, a always present scroll bar + * is implemented. It detects size changes and compensates accordingly. + */ + +#include +#include +#include +#include +#include "scrollText.h" + +extern char *malloc(); +extern char *realloc(); +#define alloc(type) (type *) malloc(sizeof(type)) +#define numalloc(type, num) (type *) malloc((unsigned) (num * sizeof(type))) +#define MAXINT 2147483647 + +extern XAssocTable *XCreateAssocTable(); +extern caddr_t XLookUpAssoc(); + +static XAssocTable *textWindows = (XAssocTable *) 0; + +#define NOOPTION -1 /* Option hasn't been set yet */ +#define NORMSCROLL 0 /* Smooth scroll on LineToTop and TopToHere */ +#define JUMPSCROLL 1 /* Jump scrolling on LineToTop and TopToHere */ + +static int ScrollOption = NOOPTION; + +typedef char *Generic; + +#define DEFAULT_GC textInfo->fontGC[textInfo->curFont] + +#define BARSIZE 15 +#define BARBORDER 1 +#define MAXFONTS 8 +#define INITBUFSIZE 1024 +#define INITLINES 50 +#define INITEXPARY 50 +#define XPADDING 2 +#define YPADDING 2 +#define INTERLINE 5 +#define INTERSPACE 1 +#define CURSORWIDTH 2 +#define EXPANDPERCENT 40 +#define BUFSIZE 1024 +#define CUROFFSET 1 +#define MAXFOREIGN 250 +#define NOINDEX -1 + +/* The wrap line indicator */ +#define WRAPINDSIZE 7 +#define STEMOFFSET 5 +#define arrow_width 7 +#define arrow_height 5 +static char arrow_bits[] = { + 0x24, 0x26, 0x3f, 0x06, 0x04}; + +#define NEWLINE '\n' +#define BACKSPACE '\010' +#define NEWFONT '\006' +#define LOWCHAR '\040' +#define HIGHCHAR '\176' + +#define CHARMASK 0x00ff /* Character mask */ +#define FONTMASK 0x0700 /* Character font */ +#define FONTSHIFT 8 /* Shift amount */ + +#define WRAPFLAG 0x01 /* Line wrap flag */ + +/* + * Lines are represented by a pointer into the overall array of + * 16-bit characters. The lower eight bits is used to indicate the character + * (in ASCII), and the next two bits are used to indicate the font + * the character should be drawn in. + */ + +typedef struct txtLine { + int lineLength; /* Current line length */ + int lineHeight; /* Full height of line in pixels */ + int lineBaseLine; /* Current baseline of the line */ + int lineWidth; /* Drawing position at end of line */ + int lineText; /* Offset into master buffer */ + int lineFlags; /* Line wrap flag is here */ +}; + + +/* + * For ExposeCopy events, we queue up the redraw requests collapsing + * them into line redraw requests until the CopyExpose event arrives. + * The queue is represented as a dynamic array of the following + * structure: + */ + +typedef struct expEvent { + int lineIndex; /* Index of line to redraw */ + int ypos; /* Drawing position of line */ +}; + + +/* + * The text buffer is represented using a dynamic counted array + * of 16-bit quantities. This array expands as needed. + * For the screen representation, a dynamic counted array + * of line structures is used. This array points into the + * text buffer to denote the start of each line and its parameters. + * The windows are configured as one overall window which contains + * the scroll bar as a sub-window along its right edge. Thus, + * the text drawing space is actually w-BARSIZE. + */ + +#define NOTATBOTTOM 0x01 /* Need to scroll to bottom before appending */ +#define FONTNUMWAIT 0x02 /* Waiting for font number */ +#define COPYEXPOSE 0x04 /* Need to process a copy expose event */ +#define SCREENWRONG 0x08 /* TxtJamStr has invalidated screen contents */ + +typedef struct txtWin { + /* Basic text buffer */ + int bufAlloc; /* Allocated size of buffer */ + int bufSpot; /* Current writing position in buffer */ + short *mainBuffer; /* Main buffer of text */ + + /* Line information */ + int numLines; /* Number of display lines in buffer */ + int allocLines; /* Number of lines allocated */ + struct txtLine **txtBuffer; /* Dynamic array of lines */ + + /* Current Window display information */ + Window mainWindow; /* Text display window */ + Window scrollBar; /* Subwindow for scroll bar */ + Pixmap arrowMap; /* line wrap indicator */ + int bgPix, fgPix; /* Background and cursor */ + GC CursorGC; /* gc for the cursor */ + GC bgGC; /* gc for erasing things */ + GC fontGC[MAXFONTS]; /* gc for doing fonts */ + XFontStruct theFonts[MAXFONTS];/* Display fonts */ + int theColors[MAXFONTS]; /* foregrounds of the fonts */ + int curFont; /* current font for tracking */ + int w, h; /* Current size */ + int startLine; /* Top line in display */ + int endLine; /* Bottom line in display */ + int bottomSpace; /* Space at bottom of screen */ + int flagWord; /* If non-zero, not at end */ + + /* For handling ExposeCopy events */ + int exposeSize; /* Current size of array */ + int exposeAlloc; /* Allocated size */ + struct expEvent **exposeAry;/* Array of line indices */ + + /* Drawing position information */ + int curLine; /* Current line in buffer */ + int curX; /* Current horizontal positi */ + int curY; /* Current vertical drawing */ +}; + +/* Flags for the various basic character handling functions */ + +#define DODISP 0x01 /* Update the display */ +#define NONEWLINE 0x02 /* Dont append newline */ + + + +static int InitLine(newLine) +struct txtLine *newLine; /* Newly created line structure */ +/* + * This routine initializes a newly created line structure. + */ +{ + newLine->lineLength = 0; + newLine->lineHeight = 0; + newLine->lineBaseLine = 0; + newLine->lineWidth = XPADDING; + newLine->lineText = NOINDEX; + newLine->lineFlags = 0; + return 1; +} + + + + +int TxtGrab(display, txtWin, program, mainFont, bg, fg, cur) +Display *display; /* display window is on */ +Window txtWin; /* Window to take over as scrollable text */ +char *program; /* Program name for Xdefaults */ +XFontStruct *mainFont; /* Primary text font */ +int bg, fg, cur; /* Background, foreground, and cursor colors */ +/* + * This routine takes control of 'txtWin' and makes it into a scrollable + * text output window. It will create a sub-window for the scroll bar + * with a background of 'bg' and an bar with color 'fg'. Both fixed width + * and variable width fonts are supported. Additional fonts can be loaded + * using 'TxtAddFont'. Returns 0 if there were problems, non-zero if + * everything went ok. + */ +{ + struct txtWin *newWin; /* Text package specific information */ + XWindowAttributes winInfo; /* Window information */ + int index; + XGCValues gc_val; + + if (textWindows == (XAssocTable *) 0) { + textWindows = XCreateAssocTable(32); + if (textWindows == (XAssocTable *) 0) return(0); + } + if (XGetWindowAttributes(display, txtWin, &winInfo) == 0) return 0; + + if (ScrollOption == NOOPTION) { + /* Read to see if the user wants jump scrolling or not */ + if (XGetDefault(display, program, "JumpScroll")) { + ScrollOption = JUMPSCROLL; + } else { + ScrollOption = NORMSCROLL; + } + } + + /* Initialize local structure */ + newWin = alloc(struct txtWin); + + /* Initialize arrow pixmap */ + newWin->arrowMap = XCreatePixmapFromBitmapData(display, txtWin, + arrow_bits, + arrow_width, arrow_height, + cur, bg, + DisplayPlanes(display, 0)); + + newWin->bufAlloc = INITBUFSIZE; + newWin->bufSpot = 0; + newWin->mainBuffer = numalloc(short, INITBUFSIZE); + + newWin->numLines = 1; + newWin->allocLines = INITLINES; + newWin->txtBuffer = numalloc(struct txtLine *, INITLINES); + for (index = 0; index < INITLINES; index++) { + newWin->txtBuffer[index] = alloc(struct txtLine); + InitLine(newWin->txtBuffer[index]); + } + + /* Window display information */ + newWin->mainWindow = txtWin; + newWin->w = winInfo.width; + newWin->h = winInfo.height; + newWin->startLine = 0; + newWin->endLine = 0; + newWin->bottomSpace = winInfo.height + - YPADDING - mainFont->ascent - mainFont->descent - INTERLINE; + newWin->flagWord = 0; + newWin->bgPix = bg; + newWin->fgPix = fg; + + /* Scroll Bar Creation */ + newWin->scrollBar = XCreateSimpleWindow(display, txtWin, + winInfo.width - BARSIZE, + 0, BARSIZE - (2*BARBORDER), + winInfo.height - (2*BARBORDER), + BARBORDER, + fg, bg); + XSelectInput(display, newWin->scrollBar, ExposureMask|ButtonReleaseMask); + XMapRaised(display, newWin->scrollBar); + + /* Font and Color Initialization */ + newWin->theFonts[0] = *mainFont; + newWin->theColors[0] = fg; + gc_val.function = GXcopy; + gc_val.plane_mask = AllPlanes; + gc_val.foreground = fg; + gc_val.background = bg; + gc_val.graphics_exposures = 1; + gc_val.font = mainFont->fid; + gc_val.line_width = 1; + gc_val.line_style = LineSolid; + + newWin->fontGC[0] = XCreateGC(display, txtWin, + GCFunction | GCPlaneMask | + GCForeground | GCBackground | + GCGraphicsExposures | GCFont, + &gc_val); + + gc_val.foreground = cur; + newWin->CursorGC = XCreateGC(display, txtWin, + GCFunction | GCPlaneMask | + GCForeground | GCBackground | + GCLineStyle | GCLineWidth, + &gc_val); + + gc_val.foreground = bg; + newWin->bgGC = XCreateGC(display, txtWin, + GCFunction | GCPlaneMask | + GCForeground | GCBackground | + GCGraphicsExposures | GCFont, + &gc_val); + + + for (index = 1; index < MAXFONTS; index++) { + newWin->theFonts[index].fid = 0; + newWin->fontGC[index] = 0; + } + + + /* Initialize size of first line */ + newWin->txtBuffer[0]->lineHeight = newWin->theFonts[0].ascent + + newWin->theFonts[0].descent; + newWin->txtBuffer[0]->lineText = 0; + + /* ExposeCopy array initialization */ + newWin->exposeSize = 0; + newWin->exposeAlloc = INITEXPARY; + newWin->exposeAry = numalloc(struct expEvent *, INITEXPARY); + for (index = 0; index < newWin->exposeAlloc; index++) + newWin->exposeAry[index] = alloc(struct expEvent); + /* Put plus infinity in last slot for sorting purposes */ + newWin->exposeAry[0]->lineIndex = MAXINT; + + /* Drawing Position Information */ + newWin->curLine = 0; + newWin->curX = 0; + newWin->curY = YPADDING + mainFont->ascent + mainFont->descent; + + /* Attach it to both windows */ + XMakeAssoc(display, textWindows, (XID) txtWin, (caddr_t) newWin); + XMakeAssoc(display, textWindows, (XID) newWin->scrollBar, (caddr_t) newWin); + return 1; +} + + +int TxtRelease(display, w) +Display *display; +Window w; /* Window to release */ +/* + * This routine releases all resources associated with the + * specified window which are consumed by the text + * window package. This includes the entire text buffer, line start + * array, and the scroll bar window. However, the window + * itself is NOT destroyed. The routine will return zero if + * the window is not owned by the text window package. + */ +{ + struct txtWin *textInfo; + int index; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, + textWindows, (XID) w)) == 0) + return 0; + + for (index = 0; index < MAXFONTS; index++) + if (textInfo->fontGC[index] != 0) + XFreeGC(display, textInfo->fontGC[index]); + + free((Generic) textInfo->mainBuffer); + for (index = 0; index < textInfo->numLines; index++) { + free((Generic) textInfo->txtBuffer[index]); + } + free((Generic) textInfo->txtBuffer); + XDestroyWindow(display, textInfo->scrollBar); + for (index = 0; index < textInfo->exposeSize; index++) { + free((Generic) textInfo->exposeAry[index]); + } + free((Generic) textInfo->exposeAry); + XDeleteAssoc(display, textWindows, (XID) w); + free((Generic) textInfo); + return 1; +} + + + +static int RecompBuffer(textInfo) +struct txtWin *textInfo; /* Text window information */ +/* + * This routine recomputes all line breaks in a buffer after + * a change in window size or font. This is done by throwing + * away the old line start array and recomputing it. Although + * a lot of this work is also done elsewhere, it has been included + * inline here for efficiency. + */ +{ + int startPos, endSize, linenum; + register int index, chsize, curfont; + register short *bufptr; + register XFontStruct *fontptr; + register struct txtLine *lineptr; + char theChar; + + /* Record the old position so we can come back to it */ + for (startPos = textInfo->txtBuffer[textInfo->startLine]->lineText; + (startPos > 0) && (textInfo->mainBuffer[startPos] != '\n'); + startPos--) + /* null loop body */; + + /* Clear out the old line start array */ + for (index = 0; index < textInfo->numLines; index++) { + InitLine(textInfo->txtBuffer[index]); + } + + /* Initialize first line */ + textInfo->txtBuffer[0]->lineHeight = + textInfo->theFonts[0].ascent + textInfo->theFonts[0].descent; + textInfo->txtBuffer[0]->lineText = 0; + + /* Process the text back into lines */ + endSize = textInfo->w - BARSIZE - WRAPINDSIZE; + bufptr = textInfo->mainBuffer; + lineptr = textInfo->txtBuffer[0]; + linenum = 0; + fontptr = &(textInfo->theFonts[0]); + curfont = 0; + for (index = 0; index < textInfo->bufSpot; index++) { + theChar = bufptr[index] & CHARMASK; + + if ((bufptr[index] & FONTMASK) != curfont) { + int newFontNum, heightDiff; + + /* Switch fonts */ + newFontNum = (bufptr[index] & FONTMASK) >> FONTSHIFT; + if (textInfo->theFonts[newFontNum].fid != 0) { + /* Valid font */ + curfont = bufptr[index] & FONTMASK; + fontptr = &(textInfo->theFonts[newFontNum]); + heightDiff = (fontptr->ascent + fontptr->descent) - + lineptr->lineHeight; + if (heightDiff < 0) heightDiff = 0; + lineptr->lineHeight += heightDiff; + } + } + if (theChar == '\n') { + /* Handle new line */ + if (linenum >= textInfo->allocLines-1) + /* Expand number of lines */ + ExpandLines(textInfo); + linenum++; + lineptr = textInfo->txtBuffer[linenum]; + /* Initialize next line */ + lineptr->lineHeight = fontptr->ascent + fontptr->descent; + lineptr->lineText = index+1; + /* Check to see if its the starting line */ + if (index == startPos) textInfo->startLine = linenum; + } else { + /* Handle normal character */ + chsize = CharSize(textInfo, linenum, index); + if (lineptr->lineWidth + chsize > endSize) { + /* Handle line wrap */ + lineptr->lineFlags |= WRAPFLAG; + if (linenum >= textInfo->allocLines-1) + /* Expand number of lines */ + ExpandLines(textInfo); + linenum++; + lineptr = textInfo->txtBuffer[linenum]; + /* Initialize next line */ + lineptr->lineHeight = fontptr->ascent + fontptr->descent; + lineptr->lineText = index; + lineptr->lineLength = 1; + lineptr->lineWidth += chsize; + } else { + /* Handle normal addition of character */ + lineptr->lineLength += 1; + lineptr->lineWidth += chsize; + } + } + } + /* We now have a valid line array. Let's clean up some other fields. */ + textInfo->numLines = linenum+1; + if (startPos == 0) { + textInfo->startLine = 0; + } + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + textInfo->curLine = linenum; + /* Check to see if we are at the bottom */ + if (textInfo->endLine >= textInfo->numLines-1) { + textInfo->curY = textInfo->h - textInfo->bottomSpace - + lineptr->lineHeight; + textInfo->flagWord &= (~NOTATBOTTOM); + } else { + textInfo->flagWord |= NOTATBOTTOM; + } + return 1; +} + + + + +int TxtAddFont(display, textWin, fontNumber, newFont, newColor) +Display *display; +Window textWin; /* Scrollable text window */ +int fontNumber; /* Place to add font (0-7) */ +XFontStruct *newFont; /* Font to add */ +int newColor; /* Color of font */ +/* + * This routine loads a new font so that it can be used in a previously + * created text window. There are eight font slots numbered 0 through 7. + * If there is already a font in the specified slot, it will be replaced + * and an automatic redraw of the window will take place. See TxtWriteStr + * for details on using alternate fonts. The color specifies the foreground + * color of the text. The default foreground color is used if this + * parameter is TXT_NO_COLOR. Returns a non-zero value if + * everything went well. + */ +{ + struct txtWin *textInfo; + int redrawFlag; + XGCValues gc_val; + + if ((fontNumber < 0) || (fontNumber >= MAXFONTS)) return 0; + if ((textInfo = (struct txtWin *) + XLookUpAssoc(display, textWindows, (XID) textWin)) == 0) + return 0; + if (newColor == TXT_NO_COLOR) { + newColor = textInfo->fgPix; + } + + gc_val.font = newFont->fid; + gc_val.foreground = newColor; + gc_val.background = textInfo->bgPix; + gc_val.plane_mask = AllPlanes; + gc_val.graphics_exposures = 1; + gc_val.function = GXcopy; + + if (textInfo->fontGC[fontNumber] != 0) + { + XChangeGC(display, textInfo->fontGC[fontNumber], + GCFont | GCForeground, &gc_val); + } + else + textInfo->fontGC[fontNumber] = XCreateGC(display, textWin, + GCFont | + GCForeground | + GCBackground | + GCFunction | + GCPlaneMask | + GCGraphicsExposures, + &gc_val); + + + redrawFlag = (textInfo->theFonts[fontNumber].fid != 0) && + (((newFont) && (newFont->fid != textInfo->theFonts[fontNumber].fid)) || + (newColor != textInfo->theColors[fontNumber])); + if (newFont) { + textInfo->theFonts[fontNumber] = *newFont; + } + textInfo->theColors[fontNumber] = newColor; + + if (redrawFlag) { + RecompBuffer(textInfo); + XClearWindow(display, textWin); + TxtRepaint(display, textWin); + } + return 1; +} + + + +int TxtWinP(display, w) +Display *display; +Window w; +/* + * Returns a non-zero value if the window has been previously grabbed + * using TxtGrab and 0 if it has not. + */ +{ + if (XLookUpAssoc(display, textWindows, (XID) w)) + return(1); + else return(0); +} + + + +static int FindEndLine(textInfo, botSpace) +struct txtWin *textInfo; +int *botSpace; +/* + * Given the starting line in 'textInfo->startLine', this routine + * determines the index of the last line that can be drawn given the + * current size of the screen. If there are not enough lines to + * fill the screen, the index of the last line will be returned. + * The amount of empty bottom space is returned in 'botSpace'. + */ +{ + int index, height, lineHeight; + + height = YPADDING; + index = textInfo->startLine; + while (index < textInfo->numLines) { + lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE; + if (height + lineHeight > textInfo->h) break; + height += lineHeight; + index++; + } + if (botSpace) { + *botSpace = textInfo->h - height; + } + return index - 1; +} + + + +static int UpdateScroll(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * This routine computes the current extent of the scroll bar + * indicator and repaints the bar with the correct information. + */ +{ + int top, bottom; + + if (textInfo->numLines > 1) { + top = textInfo->startLine * (textInfo->h - 2*BARBORDER) / + (textInfo->numLines - 1); + bottom = textInfo->endLine * (textInfo->h - 2*BARBORDER) / + (textInfo->numLines - 1); + } else { + top = 0; + bottom = textInfo->h - (2*BARBORDER); + } + + /* Draw it - make sure there is a little padding */ + if (top == 0) top++; + if (bottom == textInfo->h-(2*BARBORDER)) bottom--; + + XFillRectangle(display, textInfo->scrollBar, + textInfo->bgGC, + 0, 0, BARSIZE, top-1); + XFillRectangle(display, textInfo->scrollBar, + DEFAULT_GC, top, BARSIZE - (2*BARBORDER) - 2, + bottom - top); + XFillRectangle(display, textInfo->scrollBar, DEFAULT_GC, + 0, bottom+1, BARSIZE, + textInfo->h - (2 * BARBORDER) - bottom); + + return 1; +} + + + + +int TxtClear(display, w) +Display *display; +Window w; +/* + * This routine clears a scrollable text window. It resets the current + * writing position to the upper left hand corner of the screen. + * NOTE: THIS ALSO CLEARS THE CONTENTS OF THE TEXT WINDOW BUFFER AND + * RESETS THE SCROLL BAR. Returns 0 if the window is not a text window. + * This should be used *instead* of XClear. + */ +{ + struct txtWin *textInfo; + int index; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) + return 0; + + /* Zero out the arrays */ + textInfo->bufSpot = 0; + for (index = 0; index < textInfo->numLines; index++) { + InitLine(textInfo->txtBuffer[index]); + } + textInfo->txtBuffer[0]->lineHeight = + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent; + + textInfo->numLines = 1; + textInfo->startLine = 0; + textInfo->endLine = 0; + textInfo->curLine = 0; + textInfo->curX = 0; + textInfo->curY = YPADDING + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent; + + textInfo->bottomSpace = textInfo->h - YPADDING - + textInfo->theFonts[textInfo->curFont].ascent - INTERLINE - + textInfo->theFonts[textInfo->curFont].descent; + /* Actually clear the window */ + XClearWindow(display, w); + + /* Draw the current cursor */ + XFillRectangle(display, w, textInfo->CursorGC, + XPADDING + CUROFFSET, textInfo->curY, + CURSORWIDTH, + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent); + + /* Update the scroll bar */ + UpdateScroll(display, textInfo); + return 1; +} + + +static int WarpToBottom(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text Information */ +/* + * This routine causes the specified text window to display its + * last screen of information. It updates the scroll bar + * to the appropriate spot. The implementation scans backward + * through the buffer to find an appropriate starting spot for + * the window. + */ +{ + int index, height, lineHeight; + + index = textInfo->numLines-1; + height = 0; + while (index >= 0) { + lineHeight = textInfo->txtBuffer[index]->lineHeight + INTERLINE; + if (height + lineHeight > textInfo->h) break; + height += lineHeight; + index--; + } + textInfo->startLine = index + 1; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + textInfo->curY = textInfo->h - textInfo->bottomSpace - + textInfo->txtBuffer[textInfo->endLine]->lineHeight; + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + return 1; +} + + + +static int UpdateExposures(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * Before a new scrolling action occurs, the text window package + * must handle all COPYEXPOSE events generated by the last scrolling + * action. This routine is called to do this. Foreign events (those + * not handled by TxtFilter) are queued up and replaced on the queue + * after the processing of the exposure events is complete. + */ +{ +#if 0 + XEvent foreignQueue[MAXFOREIGN]; + int index, lastItem = 0; + + while (textInfo->flagWord & COPYEXPOSE) { + XNextEvent(display, &(foreignQueue[lastItem])); + if (!TxtFilter(display, &(foreignQueue[lastItem]))) + lastItem++; + if (lastItem >= MAXFOREIGN) { + printf("Too many foreign events to queue!\n"); + textInfo->flagWord &= (~COPYEXPOSE); + } + } + for (index = 0; index < lastItem; index++) { + XPutBackEvent(display, &(foreignQueue[index])); + } +#endif + return 1; +} + + +static int ScrollDown(display,textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * This routine scrolls the indicated text window down by one + * line. The line below the current line must exist. The window + * is scrolled so that the line below the last line is fully + * displayed. This may cause many lines to scroll off the top. + * Scrolling is done using XCopyArea. The exposure events should + * be caught using ExposeCopy. + */ +{ + int lineSum, index, targetSpace, freeSpace, updateFlag; + + lineSum = 0; + if (textInfo->endLine + 1 >= textInfo->numLines) return 0; + targetSpace = textInfo->txtBuffer[textInfo->endLine+1]->lineHeight + + INTERLINE; + if (textInfo->bottomSpace < targetSpace) { + index = textInfo->startLine; + while (index < textInfo->endLine) { + lineSum += (textInfo->txtBuffer[index]->lineHeight + INTERLINE); + if (textInfo->bottomSpace + lineSum >= targetSpace) break; + index++; + } + + /* Must move upward by 'lineSum' pixels */ + XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow, + DEFAULT_GC, 0, lineSum, + textInfo->w - BARSIZE, textInfo->h, + 0, 0); + + textInfo->flagWord |= COPYEXPOSE; + /* Repair the damage to the structures */ + textInfo->startLine = index + 1; + updateFlag = 1; + } else { + updateFlag = 0; + } + /* More lines might be able to fit. Let's check. */ + freeSpace = textInfo->bottomSpace + lineSum - targetSpace; + index = textInfo->endLine + 1; + while (index < textInfo->numLines-1) { + if (freeSpace - textInfo->txtBuffer[index+1]->lineHeight - INTERLINE < 0) + break; + freeSpace -= (textInfo->txtBuffer[index+1]->lineHeight + INTERLINE); + index++; + } + textInfo->endLine = index; + textInfo->bottomSpace = freeSpace; + if (updateFlag) { + UpdateExposures(display, textInfo); + } + UpdateScroll(display, textInfo); + return 1; +} + + + + +static int ExpandLines(textInfo) +struct txtWin *textInfo; /* Text Information */ +/* + * This routine allocates and initializes additional space in + * the line start array (txtBuffer). The new space + * is allocated using realloc. The expansion factor is a percentage + * given by EXPANDPERCENT. + */ +{ + int newSize, index; + + newSize = textInfo->allocLines; + newSize += (newSize * EXPANDPERCENT) / 100; + + textInfo->txtBuffer = (struct txtLine **) + realloc((char *) textInfo->txtBuffer, + (unsigned) (newSize * sizeof(struct txtLine *))); + for (index = textInfo->allocLines; index < newSize; index++) { + textInfo->txtBuffer[index] = alloc(struct txtLine); + InitLine(textInfo->txtBuffer[index]); + } + textInfo->allocLines = newSize; + return 1; +} + +static int ExpandBuffer(textInfo) +struct txtWin *textInfo; /* Text information */ +/* + * Expands the basic character buffer using realloc. The expansion + * factor is a percentage given by EXPANDPERCENT. + */ +{ + int newSize; + + newSize = textInfo->bufAlloc + (textInfo->bufAlloc * EXPANDPERCENT) / 100; + textInfo->mainBuffer = (short *) + realloc((char *) textInfo->mainBuffer, (unsigned) newSize * sizeof(short)); + textInfo->bufAlloc = newSize; + return 1; +} + + + +static int HandleNewLine(display, textInfo, flagWord) +Display *display; +struct txtWin *textInfo; /* Text Information */ +int flagWord; /* DODISP or NONEWLINE or both */ +/* + * This routine initializes the next line for drawing by setting + * its height to the current font height, scrolls the screen down + * one line, and updates the current drawing position to the + * left edge of the newly cleared line. If DODISP is specified, + * the screen will be updated (otherwise not). If NONEWLINE is + * specified, no newline character will be added to the text buffer + * (this is for line wrap). + */ +{ + struct txtLine *curLine, *nextLine; + + /* Check to see if a new line must be allocated */ + if (textInfo->curLine >= textInfo->allocLines-1) + /* Expand the number of lines */ + ExpandLines(textInfo); + textInfo->numLines += 1; + + /* Then we initialize the next line */ + nextLine = textInfo->txtBuffer[textInfo->numLines-1]; + nextLine->lineHeight = + textInfo->theFonts[textInfo->curFont].ascent + + textInfo->theFonts[textInfo->curFont].descent; + + curLine = textInfo->txtBuffer[textInfo->curLine]; + if (flagWord & DODISP) { + /* Scroll down a line if required */ + if ((textInfo->curY + curLine->lineHeight + + nextLine->lineHeight + (INTERLINE * 2)) > textInfo->h) + { + ScrollDown(display, textInfo); + } + else + { + /* Update the bottom space appropriately */ + textInfo->bottomSpace -= (nextLine->lineHeight + INTERLINE); + textInfo->endLine += 1; + } + /* Update drawing position */ + textInfo->curY = textInfo->h - + (textInfo->bottomSpace + nextLine->lineHeight); + } + + /* Move down a line */ + textInfo->curLine += 1; + if (!(flagWord & NONEWLINE)) { + /* Append end-of-line to text buffer */ + if (textInfo->bufSpot >= textInfo->bufAlloc) { + /* Allocate more space in main text buffer */ + ExpandBuffer(textInfo); + } + textInfo->mainBuffer[(textInfo->bufSpot)++] = + (textInfo->curFont << FONTSHIFT) | '\n'; + } + nextLine->lineText = textInfo->bufSpot; + textInfo->curX = 0; + return 1; +} + + + +static int CharSize(textInfo, lineNum, charNum) +struct txtWin *textInfo; /* Current Text Information */ +int lineNum; /* Line in buffer */ +int charNum; /* Character in line */ +/* + * This routine determines the size of the specified character. + * It takes in account the font of the character and whether its + * fixed or variable. The size includes INTERSPACE spacing between + * the characters. + */ +{ + register XFontStruct *charFont; + register short *theLine; + register short theChar; + + theLine = &(textInfo->mainBuffer[textInfo->txtBuffer[lineNum]->lineText]); + theChar = theLine[charNum] & CHARMASK; + charFont = &(textInfo->theFonts[(theChar & FONTMASK) >> FONTSHIFT]); + if (theChar <= charFont->min_char_or_byte2 || + theChar >= charFont->max_char_or_byte2 || + charFont->per_char == 0) + return charFont->max_bounds.width + 1; + else + return charFont->per_char[theChar].width + 1; +} + + + + + +static int HandleBackspace(display, textInfo, flagWord) +Display *display; +struct txtWin *textInfo; /* Text Information */ +int flagWord; /* DODISP or nothing */ +/* + * This routine handles a backspace found in the input stream. The + * character before the current writing position will be erased and + * the drawing position will move back one character. If the writing + * position is at the left margin, the drawing position will move + * up to the previous line. If it is a line that has been wrapped, + * the character at the end of the previous line will be erased. + */ +{ + struct txtLine *thisLine, *prevLine; + int chSize; + + thisLine = textInfo->txtBuffer[textInfo->curLine]; + /* First, determine whether we need to go back a line */ + if (thisLine->lineLength == 0) { + /* Bleep if at top of buffer */ + if (textInfo->curLine == 0) { + XBell(display, 50); + return 0; + } + + /* See if we have to scroll in the other direction */ + if ((flagWord & DODISP) && (textInfo->curY <= YPADDING)) { + /* This will display the last lines of the buffer */ + WarpToBottom(display, textInfo); + } + + /* Set drawing position at end of previous line */ + textInfo->curLine -= 1; + prevLine = textInfo->txtBuffer[textInfo->curLine]; + textInfo->numLines -= 1; + if (flagWord & DODISP) { + textInfo->curY -= (prevLine->lineHeight + INTERLINE); + textInfo->bottomSpace += (thisLine->lineHeight + INTERLINE); + textInfo->endLine -= 1; + } + + /* We are unlinewrapping if the previous line has flag set */ + if (prevLine->lineFlags & WRAPFLAG) { + /* Get rid of line wrap indicator */ + if (flagWord & DODISP) { + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + textInfo->w - BARSIZE - WRAPINDSIZE, + textInfo->curY, WRAPINDSIZE, + prevLine->lineHeight); + } + prevLine->lineFlags &= (~WRAPFLAG); + /* Call recursively to wipe out the ending character */ + HandleBackspace(display, textInfo, flagWord); + } else { + /* Delete the end-of-line in the primary buffer */ + textInfo->bufSpot -= 1; + } + } else { + /* Normal deletion of character */ + chSize = + CharSize(textInfo, textInfo->curLine, + textInfo->txtBuffer[textInfo->curLine]->lineLength - 1); + /* Move back appropriate amount and wipe it out */ + thisLine->lineWidth -= chSize; + if (flagWord & DODISP) { + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + thisLine->lineWidth, textInfo->curY, + chSize, thisLine->lineHeight); + } + /* Delete from buffer */ + textInfo->txtBuffer[textInfo->curLine]->lineLength -= 1; + textInfo->bufSpot -= 1; + } + return 1; +} + + + +static int DrawLineWrap(display, win, x, y, h, col) +Display *display; +Window win; /* What window to draw it in */ +int x, y; /* Position of upper left corner */ +int h; /* Height of indicator */ +int col; /* Color of indicator */ +/* + * This routine draws a line wrap indicator at the end of a line. + * Visually, it is an arrow of the specified height directly against + * the scroll bar border. The bitmap used for the arrow is stored + * in 'arrowMap' with size 'arrow_width' and 'arrow_height'. + */ +{ + struct txtWin *textInfo; + + textInfo = (struct txtWin *)XLookUpAssoc(display, textWindows, + (XID) win); + + /* First, draw the arrow */ + XCopyArea(display, textInfo->arrowMap, textInfo->mainWindow, + textInfo->CursorGC, + 0, 0, arrow_width, arrow_height, + x, y + h - arrow_height, 1); + + /* Then draw the stem */ + XDrawLine(display, textInfo->mainWindow, textInfo->CursorGC, + x + STEMOFFSET, y, + x + STEMOFFSET, y + h - arrow_height); + return 1; +} + + + + +static int DrawLine(display, textInfo, lineIndex, ypos) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int lineIndex; /* Index of line to draw */ +int ypos; /* Y position for line */ +/* + * This routine destructively draws the indicated line in the + * indicated window at the indicated position. It does not + * clear to end of line however. It draws a line wrap indicator + * if needed but does not draw a cursor. + */ +{ + int index, startPos, curFont, theColor, curX, saveX, fontIndex; + struct txtLine *someLine; + char lineBuffer[BUFSIZE], *glyph; + short *linePointer; + XFontStruct *theFont; + XGCValues gc; + + /* First, we draw the text */ + index = 0; + curX = XPADDING; + someLine = textInfo->txtBuffer[lineIndex]; + linePointer = &(textInfo->mainBuffer[someLine->lineText]); + while (index < someLine->lineLength) { + startPos = index; + saveX = curX; + curFont = linePointer[index] & FONTMASK; + fontIndex = curFont >> FONTSHIFT; + theFont = &(textInfo->theFonts[fontIndex]); + theColor = textInfo->theColors[fontIndex]; + glyph = &(lineBuffer[0]); + while ((index < someLine->lineLength) && + ((linePointer[index] & FONTMASK) == curFont)) + { + *glyph = linePointer[index] & CHARMASK; + index++; + curX += CharSize(textInfo, lineIndex, index); + glyph++; + } + + /* Flush out the glyphs */ + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + saveX, ypos, + textInfo->w - BARSIZE, + someLine->lineHeight + YPADDING + INTERLINE); + + XDrawString(display, textInfo->mainWindow, + textInfo->fontGC[fontIndex], + saveX, ypos, + lineBuffer, someLine->lineLength); + } + /* Then the line wrap indicator (if needed) */ + if (someLine->lineFlags & WRAPFLAG) { + DrawLineWrap(display, textInfo->mainWindow, + textInfo->w - BARSIZE - WRAPINDSIZE, + ypos, someLine->lineHeight, + textInfo->fgPix); + } + return 1; +} + + + + +static int HandleNewFont(display, fontNum, textInfo, flagWord) +Display *display; +int fontNum; /* Font number */ +struct txtWin *textInfo; /* Text information */ +int flagWord; /* DODISP or nothing */ +/* + * This routine handles a new font request. These requests take + * the form "^F". The parsing is done in TxtWriteStr. + * This routine is called only if the form is valid. It may return + * a failure (0 status) if the requested font is not loaded. + * If the new font is larger than any of the current + * fonts on the line, it will change the line height and redisplay + * the line. + */ +{ + struct txtLine *thisLine; + int heightDiff, baseDiff, redrawFlag; + + if (textInfo->theFonts[fontNum].fid == 0) { + return 0; + } else { + thisLine = textInfo->txtBuffer[textInfo->curLine]; + textInfo->curFont = fontNum; + redrawFlag = 0; + heightDiff = textInfo->theFonts[fontNum].ascent + + textInfo->theFonts[fontNum].descent - + thisLine->lineHeight; + + if (heightDiff > 0) { + redrawFlag = 1; + } else { + heightDiff = 0; + } + + if (redrawFlag) { + if (flagWord & DODISP) { + /* Clear current line */ + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + 0, textInfo->curY, textInfo->w, + thisLine->lineHeight); + + /* Check to see if it requires scrolling */ + if ((textInfo->curY + thisLine->lineHeight + heightDiff + + INTERLINE) > textInfo->h) + { + /* + * General approach: "unscroll" the last line up + * and then call ScrollDown to do the right thing. + */ + textInfo->endLine -= 1; + textInfo->bottomSpace += thisLine->lineHeight + + INTERLINE; + + XFillRectangle(display, textInfo->mainWindow, + textInfo->bgGC, + 0, textInfo->h - textInfo->bottomSpace, + textInfo->w, textInfo->bottomSpace); + + thisLine->lineHeight += heightDiff; + ScrollDown(display, textInfo); + textInfo->curY = textInfo->h - + (textInfo->bottomSpace + INTERLINE + + thisLine->lineHeight); + } + else + { + /* Just update bottom space */ + textInfo->bottomSpace -= heightDiff; + thisLine->lineHeight += heightDiff; + } + /* Redraw the current line */ + DrawLine(display, textInfo, textInfo->curLine, textInfo->curY); + } else { + /* Just update line height */ + thisLine->lineHeight += heightDiff; + } + } + return 1; + } +} + + + +int TxtWriteStr(display, w, str) +Display *display; +Window w; /* Text window */ +register char *str; /* 0 terminated string */ +/* + * This routine writes a string to the specified text window. + * The following notes apply: + * - Text is always appended to the end of the text buffer. + * - If the scroll bar is positioned such that the end of the + * text is not visible, an automatic scroll to the bottom + * will be done before the appending of text. + * - Non-printable ASCII characters are not displayed. + * - The '\n' character causes the current text position to + * advance one line and start at the left. + * - Tabs are not supported. + * - Lines too long for the screen will be wrapped and a line wrap + * indication will be drawn. + * - Backspace clears the previous character. It will do the right + * thing if asked to backspace past a wrapped line. + * - A new font can be chosen using the sequence '^F' where + * is 0-7. The directive will be ignored if + * there is no font in the specified slot. + * Returns 0 if something went wrong. + */ +{ + register int fontIndex; + register struct txtWin *textInfo; + register struct txtLine *thisLine; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w)) == 0) + return 0; + + /* See if screen needs to be updated */ + if (textInfo->flagWord & SCREENWRONG) { + TxtRepaint(display, textInfo->mainWindow); + } + + /* See if we have to scroll down to the bottom */ + if (textInfo->flagWord & NOTATBOTTOM) { + WarpToBottom(display, textInfo); + textInfo->flagWord &= (~NOTATBOTTOM); + } + + /* Undraw the current cursor */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + + XFillRectangle(display, w, textInfo->bgGC, + thisLine->lineWidth + CUROFFSET, + textInfo->curY, + CURSORWIDTH, + thisLine->lineHeight); + + for ( /* str is ok */ ; (*str != 0) ; str++) { + /* Check to see if we are waiting on a font */ + if (textInfo->flagWord & FONTNUMWAIT) { + textInfo->flagWord &= (~FONTNUMWAIT); + fontIndex = *str - '0'; + if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) { + /* Handle font -- go get next character */ + if (HandleNewFont(display, fontIndex, textInfo, DODISP)) + continue; + } + } + + /* Inline code for handling normal character case */ + if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) { + register XFontStruct *thisFont; + register struct txtLine *thisLine; + register int charWidth; + int thisColor; + + /* Determine size of character */ + thisFont = &(textInfo->theFonts[textInfo->curFont]); + thisColor = textInfo->theColors[textInfo->curFont]; + if (*str <= thisFont->min_char_or_byte2 || + *str >= thisFont->max_char_or_byte2 || + thisFont->per_char == 0) + charWidth = thisFont->max_bounds.width + 1; + else + charWidth = thisFont->per_char[*str].width + 1; + + /* Check to see if line wrap is required */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + if (thisLine->lineWidth + charWidth > + (textInfo->w-BARSIZE-WRAPINDSIZE)) + { + DrawLineWrap(display, textInfo->mainWindow, + textInfo->w-BARSIZE-WRAPINDSIZE, + textInfo->curY, thisLine->lineHeight, + textInfo->fgPix); + thisLine->lineFlags |= WRAPFLAG; + /* Handle the spacing problem the same way as a newline */ + HandleNewLine(display, textInfo, DODISP | NONEWLINE); + thisLine = textInfo->txtBuffer[textInfo->curLine]; + } + + /* Ready to draw character */ + XDrawString(display, textInfo->mainWindow, + DEFAULT_GC, + textInfo->curX += charWidth, + textInfo->curY + thisLine->lineHeight, + str, 1); + + /* Append character onto main buffer */ + if (textInfo->bufSpot >= textInfo->bufAlloc) + /* Make room for more characters */ + ExpandBuffer(textInfo); + textInfo->mainBuffer[(textInfo->bufSpot)++] = + (textInfo->curFont << FONTSHIFT) | (*str); + + /* Update the line start array */ + thisLine->lineLength += 1; + thisLine->lineWidth += charWidth; + } else if (*str == NEWLINE) { + HandleNewLine(display, textInfo, DODISP); + } else if (*str == NEWFONT) { + /* Go into waiting for font number mode */ + textInfo->flagWord |= FONTNUMWAIT; + } else if (*str == BACKSPACE) { + HandleBackspace(display, textInfo, DODISP); + } else { + /* Ignore all others */ + } + } + /* Draw the cursor in its new position */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + + XFillRectangle(display, w, textInfo->CursorGC, + thisLine->lineWidth + CUROFFSET, + textInfo->curY /* + thisLine->lineHeight */, + CURSORWIDTH, thisLine->lineHeight); + + return 1; +} + + + +int TxtJamStr(display, w, str) +Display *display; +Window w; /* Text window */ +register char *str; /* NULL terminated string */ +/* + * This is the same as TxtWriteStr except the screen is NOT updated. + * After a call to this routine, TxtRepaint should be called to + * update the screen. This routine is meant to be used to load + * a text buffer with information and then allow the user to + * scroll through it at will. + */ +{ + register int fontIndex; + register struct txtWin *textInfo; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w) + ) == 0) + return 0; + + for ( /* str is ok */ ; (*str != 0) ; str++) { + /* Check to see if we are waiting on a font */ + if (textInfo->flagWord & FONTNUMWAIT) { + textInfo->flagWord &= (~FONTNUMWAIT); + fontIndex = *str - '0'; + if ((fontIndex >= 0) && (fontIndex < MAXFONTS)) { + if (HandleNewFont(display, fontIndex, textInfo, 0)) { + /* Handled font -- go get next character */ + continue; + } + } + } + /* Inline code for handling normal character case */ + if ((*str >= LOWCHAR) && (*str <= HIGHCHAR)) { + register XFontStruct *thisFont; + register struct txtLine *thisLine; + register int charWidth; + + /* Determine size of character */ + thisFont = &(textInfo->theFonts[textInfo->curFont]); + + if (*str <= thisFont->min_char_or_byte2 || + *str >= thisFont->max_char_or_byte2 || + thisFont->per_char == 0) + charWidth = thisFont->max_bounds.width + 1; + else + charWidth = thisFont->per_char[*str].width + 1; + + /* Check to see if line wrap is required */ + thisLine = textInfo->txtBuffer[textInfo->curLine]; + if (thisLine->lineWidth + charWidth > + (textInfo->w-BARSIZE-WRAPINDSIZE)) + { + thisLine->lineFlags |= WRAPFLAG; + /* Handle the spacing problem the same way as a newline */ + HandleNewLine(display, textInfo, NONEWLINE); + thisLine = textInfo->txtBuffer[textInfo->curLine]; + } + /* Append character onto main buffer */ + if (textInfo->bufSpot >= textInfo->bufAlloc) + /* Make room for more characters */ + ExpandBuffer(textInfo); + textInfo->mainBuffer[(textInfo->bufSpot)++] = + (textInfo->curFont << FONTSHIFT) | (*str); + + /* Update the line start array */ + thisLine->lineLength += 1; + thisLine->lineWidth += charWidth; + } else if (*str == NEWLINE) { + HandleNewLine(display, textInfo, 0); + } else if (*str == NEWFONT) { + /* Go into waiting for font number mode */ + textInfo->flagWord |= FONTNUMWAIT; + } else if (*str == BACKSPACE) { + HandleBackspace(display, textInfo, 0); + } else { + /* Ignore all others */ + } + } + textInfo->flagWord |= SCREENWRONG; + return 1; +} + + + +int TxtRepaint(display,w) +Display *display; +Window w; +/* + * Repaints the given scrollable text window. The routine repaints + * the entire window. For handling exposure events, the TxtFilter + * routine should be used. + */ +{ + struct txtWin *textInfo; + int index, ypos; + + if ((textInfo = (struct txtWin *) XLookUpAssoc(display, textWindows, (XID) w) + ) == 0) + return 0; + + /* Check to see if the screen is up to date */ + if (textInfo->flagWord & SCREENWRONG) { + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + textInfo->flagWord &= (~SCREENWRONG); + } + + ypos = YPADDING; + index = textInfo->startLine; + for (;;) { + DrawLine(display, textInfo, index, ypos); + if (index >= textInfo->endLine) break; + ypos += (textInfo->txtBuffer[index]->lineHeight + INTERLINE); + index++; + } + /* Draw the cursor (if on screen) */ + if (textInfo->endLine == textInfo->curLine) { + XFillRectangle(display, w, textInfo->CursorGC, + textInfo->txtBuffer[index]->lineWidth + CUROFFSET, + ypos /* + textInfo->txtBuffer[index]->lineHeight */, + CURSORWIDTH, textInfo->txtBuffer[index]->lineHeight); + + } + /* Update the scroll bar */ + UpdateScroll(display, textInfo); + return 1; +} + + + +static int InsertIndex(textInfo, thisIndex, ypos) +struct txtWin *textInfo; /* Text Window Information */ +int thisIndex; /* Line index of exposed line */ +int ypos; /* Drawing position of line */ +/* + * This routine inserts the supplied line index into the copy + * exposure array for 'textInfo'. The array is kept sorted + * from lowest to highest using insertion sort. The array + * is dynamically expanded if needed. + */ +{ + struct expEvent *newItem; + int newSize, index, downIndex; + + /* Check to see if we need to expand it */ + if ((textInfo->exposeSize + 3) >= textInfo->exposeAlloc) { + newSize = textInfo->exposeAlloc + + (textInfo->exposeAlloc * EXPANDPERCENT / 100); + textInfo->exposeAry = (struct expEvent **) + realloc((char *) textInfo->exposeAry, + (unsigned) (newSize * sizeof(struct expEvent *))); + for (index = textInfo->exposeAlloc; index < newSize; index++) + textInfo->exposeAry[index] = alloc(struct expEvent); + textInfo->exposeAlloc = newSize; + } + /* Find spot for insertion. NOTE: last spot has big number */ + for (index = 0; index <= textInfo->exposeSize; index++) { + if (textInfo->exposeAry[index]->lineIndex >= thisIndex) { + if (textInfo->exposeAry[index]->lineIndex > thisIndex) { + /* Insert before this entry */ + newItem = textInfo->exposeAry[textInfo->exposeSize+1]; + for (downIndex = textInfo->exposeSize; + downIndex >= index; + downIndex--) + { + textInfo->exposeAry[downIndex+1] = + textInfo->exposeAry[downIndex]; + } + /* Put a free structure at this spot */ + textInfo->exposeAry[index] = newItem; + /* Fill it in */ + textInfo->exposeAry[index]->lineIndex = thisIndex; + textInfo->exposeAry[index]->ypos = ypos; + /* Break out of loop */ + textInfo->exposeSize += 1; + } + break; + } + } + return 1; +} + + + +static int ScrollUp(display, textInfo) +Display *display; +struct txtWin *textInfo; /* Text window information */ +/* + * This routine scrolls the indicated text window up by one + * line. The line above the current line must exist. The + * window is scrolled so that the line above the start line + * is displayed at the top of the screen. This may cause + * many lines to scroll off the bottom. The scrolling is + * done using XCopyArea. The exposure events should be caught + * by ExposeCopy. + */ +{ + int targetSpace; + + /* Make sure all exposures have been handled by now */ + if (textInfo->startLine == 0) return 0; + targetSpace = textInfo->txtBuffer[textInfo->startLine-1]->lineHeight + + INTERLINE; + /* Move the area downward by the target amount */ + XCopyArea(display, textInfo->mainWindow, textInfo->mainWindow, + DEFAULT_GC, + 0, YPADDING, textInfo->w - BARSIZE, + textInfo->h, 0, targetSpace); + + textInfo->flagWord |= COPYEXPOSE; + /* Update the text window parameters */ + textInfo->startLine -= 1; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + + /* Clear out bottom space region */ + XClearArea(display, textInfo->mainWindow, + 0, textInfo->h - textInfo->bottomSpace, + textInfo->w, textInfo->bottomSpace); + + UpdateExposures(display, textInfo); + UpdateScroll(display, textInfo); + + return 1; +} + + +static int ScrollToSpot(display, textInfo, ySpot) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int ySpot; /* Button position in scroll window */ +/* + * This routine scrolls the specified text window relative to the + * position of the mouse in the scroll bar. The center of the screen + * will be positioned to correspond to the mouse position. + */ +{ + int targetLine, aboveLines; + + targetLine = textInfo->numLines * ySpot / textInfo->h; + textInfo->startLine = targetLine; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + aboveLines = 0; + /* Make the target line the *center* of the window */ + while ((textInfo->startLine > 0) && + (aboveLines < textInfo->endLine - targetLine)) + { + textInfo->startLine -= 1; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + aboveLines++; + } + if (textInfo->endLine == textInfo->numLines-1) { + WarpToBottom(display, textInfo); + } else { + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + } + return 1; +} + + + +static int LineToTop(display, textInfo, pos) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int pos; /* Y position of mouse */ +/* + * This routine scrolls the screen down until the line at the + * mouse position is at the top of the screen. It stops + * if it can't scroll the buffer down that far. If the + * global 'ScrollOption' is NORMSCROLL, a smooth scroll + * is used. Otherwise, it jumps to the right position + * and repaints the screen. + */ +{ + int index, sum; + + /* First, we find the current line */ + sum = 0; + for (index = textInfo->startLine; index <= textInfo->endLine; index++) { + if (sum + textInfo->txtBuffer[index]->lineHeight + INTERLINE> pos) break; + sum += textInfo->txtBuffer[index]->lineHeight + INTERLINE; + } + /* We always want to scroll down at least one line */ + if (index == textInfo->startLine) index++; + if (ScrollOption == NORMSCROLL) { + /* Scroll down until 'index' is the starting line */ + while ((textInfo->startLine < index) && ScrollDown(display, textInfo)) + { + /* Empty Loop Body */ + } + } else { + /* Immediately jump to correct spot */ + textInfo->startLine = index; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + if (textInfo->endLine == textInfo->numLines-1) { + WarpToBottom(display, textInfo); + } else { + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + } + } + /* Check to see if at end of buffer */ + if (textInfo->endLine >= textInfo->numLines-1) { + textInfo->flagWord &= (~NOTATBOTTOM); + } + return 1; +} + + + +static int TopToHere(display, textInfo, pos) +Display *display; +struct txtWin *textInfo; /* Text window information */ +int pos; /* Y position of mouse */ +/* + * This routine scrolls the screen up until the top line of + * the screen is at the current Y position of the mouse. Again, + * it will stop if it can't scroll that far. If the global + * 'ScrollOption' is NORMSCROLL, a smooth scroll is used. + * If it's not, it will simply redraw the screen at the + * correct spot. + */ +{ + int sum, target, linesup, index; + + target = pos - textInfo->txtBuffer[textInfo->startLine]->lineHeight; + /* We always want to scroll up at least one line */ + if (target <= 0) target = 1; + sum = 0; + linesup = 0; + /* Check to see if we are at the top anyway */ + if (textInfo->startLine == 0) return 0; + if (ScrollOption == NORMSCROLL) { + /* Scroll up until sum of new top lines greater than target */ + while ((sum < target) && ScrollUp(display, textInfo)) { + sum += textInfo->txtBuffer[textInfo->startLine]->lineHeight; + linesup++; + } + } else { + /* Search backward to find index */ + index = textInfo->startLine - 1; + while ((index > 0) && (sum < target)) { + sum += textInfo->txtBuffer[index]->lineHeight; + linesup++; + index--; + } + /* Go directly to the index */ + textInfo->startLine = index; + textInfo->endLine = FindEndLine(textInfo, &(textInfo->bottomSpace)); + XClearWindow(display, textInfo->mainWindow); + TxtRepaint(display, textInfo->mainWindow); + } + /* If we scrolled, assert we are not at bottom of buffer */ + if (linesup > 0) { + textInfo->flagWord |= NOTATBOTTOM; + } + return 1; +} + + + +int TxtFilter(display, evt) +Display *display; +XEvent *evt; +/* + * This routine handles events associated with scrollable text windows. + * It will handle all exposure events and any button released events + * in the scroll bar of a text window. It does NOT handle any other + * events. If it cannot handle the event, it will return 0. + */ +{ + XExposeEvent *expose = &evt->xexpose; + XButtonEvent *btEvt = &evt->xbutton; + XGraphicsExposeEvent *gexpose = &evt->xgraphicsexpose; + XNoExposeEvent *noexpose = &evt->xnoexpose; + struct txtWin *textInfo; + int index, ypos; + Window w, sw; + + if (textWindows == (XAssocTable *) 0) { + textWindows = XCreateAssocTable(32); + if (textWindows == (XAssocTable *) 0) return(0); + } + if (evt->type == Expose) { + w = expose->window; + sw = 0; + } + else if (evt->type == GraphicsExpose) { + w = gexpose->drawable; + sw = 0; + } + else if (evt->type == NoExpose) { + w = noexpose->drawable; + sw = 0; + } + else if (evt->type == ButtonRelease) { + w = btEvt->window; + sw = btEvt->subwindow; + } + else + return 0; + + if ((textInfo = (struct txtWin *) + XLookUpAssoc(display, textWindows, (XID) w)) == 0) + return 0; + + /* Determine whether it's main window or not */ + if ((w == textInfo->mainWindow) && (sw == 0)) { + /* Main Window - handle exposures */ + switch (evt->type) { + case Expose: + ypos = 0 /*YPADDING*/; + for (index = textInfo->startLine; + index <= textInfo->endLine; + index++) + { + int lh = textInfo->txtBuffer[index]->lineHeight; + + if (((ypos + lh) >= expose->y) && + (ypos <= (expose->y + expose->height))) + { + /* Intersection region */ + /* Draw line immediately */ + DrawLine(display, textInfo, index, ypos); + /* And possibly draw cursor */ + if (textInfo->curLine == index) { + XFillRectangle(display, w, textInfo->CursorGC, + textInfo->txtBuffer[index]->lineWidth + + CUROFFSET, + ypos, + CURSORWIDTH, + lh); + } + } + ypos += lh + INTERLINE; + } + break; + case GraphicsExpose: + ypos = 0 /*YPADDING*/; + for (index = textInfo->startLine; + index <= textInfo->endLine; + index++) + { + int lh = textInfo->txtBuffer[index]->lineHeight; + + if (((ypos + lh) >= gexpose->y) && + (ypos <= (gexpose->y + gexpose->height))) + { + /* Intersection region */ + /* Draw line immediately */ + DrawLine(display, textInfo, index, ypos); + /* And possibly draw cursor */ + if (textInfo->curLine == index) { + XFillRectangle(display, w, textInfo->CursorGC, + textInfo->txtBuffer[index]->lineWidth + + CUROFFSET, + ypos, + CURSORWIDTH, + lh); + } + } + ypos += lh + INTERLINE; + } + break; + case NoExpose: + break; + default: + /* Not one of our events */ + return 0; + } + } else { + switch (evt->type) { + case Expose: + UpdateScroll(display, textInfo); + break; + case ButtonRelease: + /* Find out which button */ + switch (btEvt->button) { + case Button1: + /* Scroll up until top line is at mouse position */ + TopToHere(display, textInfo, btEvt->y); + break; + case Button2: + /* Scroll to spot relative to position */ + ScrollToSpot(display, textInfo, btEvt->y); + if (textInfo->endLine >= textInfo->numLines-1) { + textInfo->flagWord &= (~NOTATBOTTOM); + } else { + textInfo->flagWord |= NOTATBOTTOM; + } + break; + case Button3: + /* Scroll down until pointed line is at top */ + LineToTop(display, textInfo, btEvt->y); + break; + } + break; + default: + /* Not one of our events */ + return 0; + } + } + return 1; +} diff --git a/gnu/games/chess/Xchess/scrollText/scrollText.h b/gnu/games/chess/Xchess/scrollText/scrollText.h new file mode 100644 index 000000000000..d9d05b08dc0b --- /dev/null +++ b/gnu/games/chess/Xchess/scrollText/scrollText.h @@ -0,0 +1,32 @@ +/* + * Scrollable Text Window Header File + * + * David Harrison + * University of California, Berkeley + * 1986 + * + * This file contains definitions for a scrollable text window + * with scroll bar support. + */ + +int TxtGrab(); + /* Take hold of a previously created window */ + +#define TXT_NO_COLOR -1 + +int TxtAddFont(); + /* Loads a new font for use later */ +int TxtWinP(); + /* Returns non-zero value if the window is text window */ +int TxtClear(); + /* Clears text window and resets text buffer */ + +int TxtWriteStr(); + /* Writes a string to window with immediate update */ +int TxtJamStr(); + /* Write a string without causing update to screen */ + +int TxtRepaint(); + /* Repaints entire scrollable text window */ +int TxtFilter(); + /* Handles events related to text window */ diff --git a/gnu/games/chess/Xchess/shade.bitmap b/gnu/games/chess/Xchess/shade.bitmap new file mode 100644 index 000000000000..a32ac80611ce --- /dev/null +++ b/gnu/games/chess/Xchess/shade.bitmap @@ -0,0 +1,71 @@ + +#define shade_width 80 +#define shade_height 80 +static char shade_bits[] = { + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x88, 0x88, + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}; diff --git a/gnu/games/chess/Xchess/std.c b/gnu/games/chess/Xchess/std.c new file mode 100644 index 000000000000..c839b912314a --- /dev/null +++ b/gnu/games/chess/Xchess/std.c @@ -0,0 +1,425 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.1 $ on $Date: 86/11/01 17:08:40 $ + * $Source: /users/faustus/xchess/RCS/std.c,v $ + * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group + * + * Utility routines. + */ + +#include "std.h" + +#ifndef IBMPC +#include +#endif not IBMPC +#ifdef UNIX +#include +#include +#endif UNIX +#ifdef BSD +#include +#include +#endif BSD + +extern char **environ; + +bool +prefix(p, s) + register char *p, *s; +{ + while (*p && (*p == *s)) + p++, s++; + if (!*p) + return (true); + else + return (false); +} + +/* Create a copy of a string. */ + +char * +copy(str) + char *str; +{ + char *p, *tmalloc(); + + p = tmalloc(strlen(str) + 1); + strcpy(p, str); + return(p); +} + +/* Determine whether sub is a substring of str. */ + +bool +substring(sub, str) + register char *str, *sub; +{ + register char *s; + + while(*str) { + if(*str == *sub) { + for(s = sub; *s; s++) + if(*s != *str++) + break; + if(*s == '\0') + return (true); + } + str++; + } + return (false); +} + +/* Malloc num bytes and initialize to zero. Fatal error if the space can't + * be malloc'd. + */ + +char * +tmalloc(num) + register int num; +{ + register char *s; + char *malloc(); + + s = malloc((unsigned) num); + if (!s) { + fatal("malloc: can't allocate %d bytes", num); + } + bzero(s, num); + return(s); +} + +char * +trealloc(ptr, num) + char *ptr; + int num; +{ + register char *s; + char *realloc(); + + s = realloc(ptr, (unsigned) num); + if (!s) { + fatal("realloc: can't allocate %d bytes", num); + } + /* Well, this won't be zeroed... Too bad... */ + return(s); +} + +/* Append one character to a string. Don't check for overflow. */ + +void +appendc(s, c) + char *s, c; +{ + while (*s) + s++; + *s++ = c; + *s = '\0'; + return; +} + +int +scannum(str) + char *str; +{ + int i = 0; + + while(isdigit(*str)) + i = i * 10 + *(str++) - '0'; + return(i); +} + +/* Case insensitive prefix. */ + +bool +ciprefix(p, s) + register char *p, *s; +{ + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != + (isupper(*s) ? tolower(*s) : *s)) + return(false); + p++; + s++; + } + return (true); +} + +/* Case insensitive strcmp... */ + +bool +cieq(p, s) + register char *p, *s; +{ + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != + (isupper(*s) ? tolower(*s) : *s)) + return(false); + p++; + s++; + } + return (!*s); +} + +#ifdef BSD + +/* Return the date. Return value is static data. */ + +char * +datestring() +{ + register char *tzn; + struct tm *tp; + static char tbuf[40]; + char *ap; + struct timeval tv; + struct timezone tz; + char *timezone(), *asctime(); + int i; + struct tm *localtime(); + + (void) gettimeofday(&tv, &tz); + tp = localtime((time_t *) &tv.tv_sec); + ap = asctime(tp); + tzn = timezone(tz.tz_minuteswest, tp->tm_isdst); + sprintf(tbuf, "%.20s", ap); + if (tzn) + strcat(tbuf, tzn); + strcat(tbuf, ap + 19); + i = strlen(tbuf); + tbuf[i - 1] = '\0'; + return (tbuf); +} + +#else BSD + +/* Give it a try... */ + +char * +datestring() +{ + long i; + static char buf[64]; + + i = time(0); + strcpy(buf, ctime(&i)); + buf[strlen(buf) - 1] = '\0'; /* Kill the nl. */ + return (buf); +} + +#endif + +/* How many seconds have elapsed in running time. */ + +int +seconds() +{ +#ifdef BSD + struct rusage ruse; + + getrusage(RUSAGE_SELF, &ruse); + return (ruse.ru_utime.tv_sec); +#else BSD +#endif BSD +} + +/* A few things that may not exist on non-unix systems. */ + +#ifndef BSD + +#ifndef index + +char * +index(s, c) + register char *s; + register char c; +{ + while ((*s != c) && (*s != '\0')) + s++; + if (*s == '\0') + return ((char *) 0); + else + return (s); +} + +#endif not index + +#ifndef rindex + +char * +rindex(s, c) + register char *s; + register char c; +{ + register char *t; + + for (t = s; *t != '\0'; t++); + while ((*t != c) && (t != s)) + t--; + if (t == s) + return ((char *) 0); + else + return (t); +} + +#endif not rindex + +#ifndef bcopy + +void +bcopy(from, to, num) + register char *from, *to; + register int num; +{ + while (num-- > 0) + *to++ = *from++; + return; +} + +#endif not bcopy + +#ifndef bzero + +void +bzero(ptr, num) + register char *ptr; + register int num; +{ + while (num-- > 0) + *ptr++ = '\0'; + return; +} + +#endif not bzero + +/* This might not be around... If not then forget about sorting... */ + +void qsort() {} + +#endif BSD + +char * +gettok(s) + char **s; +{ + char buf[BSIZE]; + int i = 0; + + while (isspace(**s)) + (*s)++; + if (!**s) + return (NULL); + while (**s && !isspace(**s)) + buf[i++] = *(*s)++; + buf[i] = '\0'; + while (isspace(**s)) + (*s)++; + return (copy(buf)); +} + +/* Die horribly. */ + +/* VARARGS1 */ +void +fatal(s, args) + char *s; +{ + fputs("Internal Error: ", stderr); + _doprnt(s, &args, stderr); + putc('\n', stderr); + + kill(getpid(), SIGIOT); + /* NOTREACHED */ +} + +void +setenv(name, value) + char *name, *value; +{ + int i; + char **xx, *s; + + s = tmalloc(strlen(name) + 2); + sprintf(s, "%s=", name); + + /* Copy the old environment... */ + for (i = 0; environ[i]; i++) + if (prefix(s, environ[i])) + break; + if (!environ[i]) { + xx = (char **) tmalloc((i + 2) * sizeof (char *)); + for (i = 0; environ[i]; i++) + xx[i] = environ[i]; + xx[i + 1] = NULL; + environ = xx; + } else + xx = environ; + + xx[i] = tmalloc(strlen(name) + strlen(value) + 2); + sprintf(xx[i], "%s=%s", name, value); + return; +} + +char * +getusername() +{ + int i = getuid(); + struct passwd *pw = getpwuid(i); + + return (pw ? pw->pw_name : NULL); +} + +char * +gethome() +{ + int i = getuid(); + struct passwd *pw = getpwuid(i); + + return (pw ? pw->pw_dir : "/strange"); +} + +char * +tildexpand(s) + char *s; +{ + struct passwd *pw; + char *n, buf[64]; + int i; + + if (*s != '~') + return (copy(s)); + + for (s++, i = 0; *s != '/'; s++, i++) + buf[i] = *s; + buf[i] = '\0'; + if (!i) + pw = getpwuid(getuid()); + else + pw = getpwnam(buf); + if (!pw) + return (s); + n = tmalloc(strlen(s) + strlen(pw->pw_dir) + 1); + strcpy(n, pw->pw_dir); + strcat(n, s); + return (n); +} + diff --git a/gnu/games/chess/Xchess/std.h b/gnu/games/chess/Xchess/std.h new file mode 100644 index 000000000000..fc8fa6460dcb --- /dev/null +++ b/gnu/games/chess/Xchess/std.h @@ -0,0 +1,105 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:18:32 $ + * $Source: /users/faustus/xchess/RCS/std.h,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * + * Standard definitions. + */ + +#define UNIX +#define BSD + +#ifndef FILE +#include +#endif +#ifndef isalpha +#include +#endif +#ifndef HUGE +#include +#endif +#include + +typedef int bool; + +#define false 0 +#define true 1 + +/* Externs defined in std.c */ + +extern char *tmalloc(); +extern char *trealloc(); +extern char *copy(); +extern char *datestring(); +extern char *getusername(); +extern char *gethome(); +extern char *gettok(); +extern char *tildexpand(); +extern void fatal(); +extern void setenv(); +extern void appendc(); +extern int scannum(); +extern int seconds(); +extern bool prefix(); +extern bool ciprefix(); +extern bool cieq(); +extern bool substring(); + +/* Externs from libc */ + +extern char *getenv(); +extern int errno; +extern char *sys_errlist[]; + +/* Should use BSIZE instead of BUFSIZ... */ + +#define BSIZE 512 + +/* Some standard macros. */ + +#define eq(a,b) (!strcmp((a), (b))) +#define isalphanum(c) (isalpha(c) || isdigit(c)) +#define alloc(strname) ((struct strname *) tmalloc(sizeof(struct strname))) +#define tfree(ptr) { if (ptr) free((char *) ptr); ptr = 0; } +#define hexnum(c) ((((c) >= '0') && ((c) <= '9')) ? ((c) - '0') : ((((c) >= \ + 'a') && ((c) <= 'f')) ? ((c) - 'a' + 10) : ((((c) >= 'A') && \ + ((c) <= 'F')) ? ((c) - 'A' + 10) : 0))) + +#ifndef BSD +#define random rand +#define srandom srand +#endif BSD + +#ifdef VMS + +#define EXIT_NORMAL 1 +#define EXIT_BAD 0 + +#else VMS + +#define EXIT_NORMAL 0 +#define EXIT_BAD 1 + +#endif VMS + diff --git a/gnu/games/chess/Xchess/valid.c b/gnu/games/chess/Xchess/valid.c new file mode 100644 index 000000000000..3dcdb004d320 --- /dev/null +++ b/gnu/games/chess/Xchess/valid.c @@ -0,0 +1,264 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.3 $ on $Date: 86/11/23 17:18:35 $ + * $Source: /users/faustus/xchess/RCS/valid.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Validate a move. + */ + +#include "xchess.h" + +extern bool ischeck(), couldmove(); + +bool +valid_move(m, b) + move *m; + board *b; +{ + board tb; + + /* First check that the piece can make the move at all... */ + if (!couldmove(m, b)) + return (false); + + /* Now see if the king is in check now. */ + bcopy((char *) b, (char *) &tb, sizeof (board)); + board_move(&tb, m); + if (ischeck(&tb, m->piece.color)) + return (false); + + if (ischeck(&tb, ((m->piece.color == WHITE) ? BLACK : WHITE))) + m->check = true; + + return (true); +} + +static bool +couldmove(m, b) + move *m; + board *b; +{ + int x, y; + + switch (m->type) { + case KCASTLE: + if ((m->piece.color == WHITE) && (b->white_cant_castle_k) || + (m->piece.color == BLACK) && + (b->black_cant_castle_k)) + return (false); + if ((b->square[m->fromy][5].color != NONE) || + (b->square[m->fromy][6].color != NONE)) + return (false); + if (ischeck(b, m->piece.color)) + return (false); + break; + + case QCASTLE: + if ((m->piece.color == WHITE) && (b->white_cant_castle_q) || + (m->piece.color == BLACK) && + (b->black_cant_castle_q)) + return (false); + if ((b->square[m->fromy][1].color != NONE) || + (b->square[m->fromy][2].color != NONE) || + (b->square[m->fromy][3].color != NONE)) + return (false); + if (ischeck(b, m->piece.color)) + return (false); + break; + + case MOVE: + case CAPTURE: + /* There is one special case here, that of taking a pawn + * en passant. In this case we change the move field to + * CAPTURE if it's ok. + */ + switch (m->piece.type) { + case PAWN: + if ((m->type == MOVE) && (m->fromx == m->tox)) { + /* A normal move. */ + if ((m->piece.color == WHITE) && (m->fromy == + m->toy + 1)) + break; + if ((m->piece.color == WHITE) && (m->fromy == + 6) && (m->toy == 4) && + (b->square[5][m->fromx].color + == NONE)) + break; + if ((m->piece.color == BLACK) && (m->fromy == + m->toy - 1)) + break; + if ((m->piece.color == BLACK) && (m->fromy == + 1) && (m->toy == 3) && + (b->square[2][m->fromx].color + == NONE)) + break; + return (false); + } else if (m->type == CAPTURE) { + if ((((m->piece.color == WHITE) && (m->fromy == + m->toy + 1)) || ((m->piece.color == + BLACK) && (m->fromy == m->toy - + 1))) && ((m->fromx == m->tox + 1) || + (m->fromx == m->tox - 1))) + break; + /* Now maybe it's enpassant... We've already + * checked for some of these things in the + * calling routine. + */ + if (m->enpassant) { + if (b->square[(m->piece.color == WHITE) + ? 3 : 4][m->tox].color == + ((m->piece.color == WHITE) ? + BLACK : WHITE)) + break; + } + return (false); + } + return (false); + + case ROOK: + if (m->fromx == m->tox) { + for (y = m->fromy + ((m->fromy > m->toy) ? -1 : + 1); y != m->toy; y += ((m->fromy + > m->toy) ? -1 : 1)) + if (b->square[y][m->tox].color != NONE) + return (false); + break; + } + if (m->fromy == m->toy) { + for (x = m->fromx + ((m->fromx > m->tox) ? -1 : + 1); x != m->tox; x += ((m->fromx + > m->tox) ? -1 : 1)) + if (b->square[m->toy][x].color != NONE) + return (false); + break; + } + return (false); + + case KNIGHT: + x = m->fromx - m->tox; + y = m->fromy - m->toy; + if ((((x == 2) || (x == -2)) && + ((y == 1) || (y == -1))) || + (((x == 1) || (x == -1)) && + ((y == 2) || (y == -2)))) + break; + return (false); + + case BISHOP: + x = m->fromx - m->tox; + y = m->fromy - m->toy; + if ((x != y) && (x != - y)) + return (false); + for (x = m->fromx + ((m->fromx > m->tox) ? -1 : 1), y = + m->fromy + ((m->fromy > m->toy) ? -1 : + 1); x != m->tox; + x += ((m->fromx > m->tox) ? -1 : 1), + y += ((m->fromy > m->toy) ? -1 : 1)) + if (b->square[y][x].color != NONE) + return (false); + break; + + case QUEEN: + if (m->fromx == m->tox) { + for (y = m->fromy + ((m->fromy > m->toy) ? -1 : + 1); y != m->toy; y += ((m->fromy + > m->toy) ? -1 : 1)) + if (b->square[y][m->tox].color != NONE) + return (false); + break; + } + if (m->fromy == m->toy) { + for (x = m->fromx + ((m->fromx > m->tox) ? -1 : + 1); x != m->tox; x += ((m->fromx + > m->tox) ? -1 : 1)) + if (b->square[m->toy][x].color != NONE) + return (false); + break; + } + x = m->fromx - m->tox; + y = m->fromy - m->toy; + if ((x != y) && (x != - y)) + return (false); + for (x = m->fromx + ((m->fromx > m->tox) ? -1 : 1), y = + m->fromy + ((m->fromy > m->toy) ? -1 : + 1); x != m->tox; + x += ((m->fromx > m->tox) ? -1 : 1), + y += ((m->fromy > m->toy) ? -1 : 1)) + if (b->square[y][x].color != NONE) + return (false); + break; + + case KING: + x = m->fromx - m->tox; + y = m->fromy - m->toy; + if ((x >= -1) && (x <= 1) && (y >= -1) && (y <= 1)) + break; + return (false); + } + break; + } + return (true); +} + +/* Say whether either king is in check... If move is non-NULL, say whether he + * in in check after the move takes place. We do this in a rather stupid way. + */ + +static bool +ischeck(b, col) + board *b; + color col; +{ + int x, y, kx, ky; + move ch; + + for (x = 0; x < SIZE; x++) + for (y = 0; y < SIZE; y++) + if ((b->square[y][x].color == col) && + (b->square[y][x].type == KING)) { + kx = x; + ky = y; + } + + for (x = 0; x < SIZE; x++) + for (y = 0; y < SIZE; y++) + if (b->square[y][x].color == ((col == WHITE) ? + BLACK : WHITE)) { + ch.type = CAPTURE; + ch.piece.color = b->square[y][x].color; + ch.piece.type = b->square[y][x].type; + ch.fromx = x; + ch.fromy = y; + ch.tox = kx; + ch.toy = ky; + ch.enpassant = false; + if (couldmove(&ch, b)) + return (true); + } + + return (false); +} + diff --git a/gnu/games/chess/Xchess/window.c b/gnu/games/chess/Xchess/window.c new file mode 100644 index 000000000000..4aae06d9ad90 --- /dev/null +++ b/gnu/games/chess/Xchess/window.c @@ -0,0 +1,952 @@ +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $ + * $Source: /users/faustus/xchess/RCS/window.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Deal with the two (or one) windows. + */ + +#include "xchess.h" +#include +#include + +#include "pawn.bitmap" +#include "rook.bitmap" +#include "knight.bitmap" +#include "bishop.bitmap" +#include "queen.bitmap" +#include "king.bitmap" + +#include "pawn_outline.bitmap" +#include "rook_outline.bitmap" +#include "knight_outline.bitmap" +#include "bishop_outline.bitmap" +#include "queen_outline.bitmap" +#include "king_outline.bitmap" + +#include "pawn_mask.bitmap" +#include "rook_mask.bitmap" +#include "knight_mask.bitmap" +#include "bishop_mask.bitmap" +#include "queen_mask.bitmap" +#include "king_mask.bitmap" + +#include "shade.bitmap" + +#include "xchess.cur" +#include "xchess_mask.cur" + +#include "xchess.icon" + +windata *win1, *win2; +bool win_flashmove = false; + +extern bool setup(); +extern void service(), drawgrid(), icon_refresh(); + +bool +win_setup(disp1, disp2) + char *disp1, *disp2; +{ + win1 = alloc(windata); + if (!oneboard) + win2 = alloc(windata); + + if (!setup(disp1, win1) || (!oneboard && !setup(disp2, win2))) + return (false); + + if (blackflag) { + win1->color = BLACK; + win1->flipped = true; + } else + win1->color = WHITE; + win_drawboard(win1); + + if (!oneboard) { + win2->color = BLACK; + win2->flipped = true; + win_drawboard(win2); + } + + return(true); +} + +/* Draw the chess board... */ + +void +win_drawboard(win) + windata *win; +{ + int i, j; + + drawgrid(win); + + /* Now toss on the squares... */ + for (i = 0; i < SIZE; i++) + for (j = 0; j < SIZE; j++) + win_erasepiece(j, i, win->color); + + return; +} + +/* Draw one piece. */ + +void +win_drawpiece(p, y, x, wnum) + piece *p; + int y, x; + color wnum; +{ + char *bits, *maskbits, *outline; + windata *win; + char buf[BSIZE]; + XImage *tmpImage; + Pixmap tmpPM, maskPM; + XGCValues gc; + + if (oneboard || (wnum == win1->color)) + win = win1; + else + win = win2; + + if (win->flipped) { + y = SIZE - y - 1; + x = SIZE - x - 1; + } + + /* + if (debug) + fprintf(stderr, "draw a %s at (%d, %d) on board %d\n", + piecenames[(int) p->type], y, x, wnum); + */ + + if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1); + + switch (p->type) { + case PAWN: + bits = pawn_bits; + maskbits = pawn_mask_bits; + outline = pawn_outline_bits; + break; + + case ROOK: + bits = rook_bits; + maskbits = rook_mask_bits; + outline = rook_outline_bits; + break; + + case KNIGHT: + bits = knight_bits; + maskbits = knight_mask_bits; + outline = knight_outline_bits; + break; + + case BISHOP: + bits = bishop_bits; + maskbits = bishop_mask_bits; + outline = bishop_outline_bits; + break; + + case QUEEN: + bits = queen_bits; + maskbits = queen_mask_bits; + outline = queen_outline_bits; + break; + + case KING: + bits = king_bits; + maskbits = king_mask_bits; + outline = king_outline_bits; + break; + + default: + fprintf(stderr, + "Internal Error: win_drawpiece: bad piece type %d\n", + p->type); + } + + /* There are two things we can do... If this is a black and white + * display, we have to shade the square and use an outline if the piece + * is white. We also have to use a mask... Since we don't want + * to use up too many bitmaps, create the mask bitmap, put the bits, + * and then destroy it. + */ + if (win->bnw && (p->color == WHITE)) + bits = outline; + if (win->bnw && !iswhite(win, x, y)) { + XSetState(win->display, DefaultGC(win->display, 0), + BlackPixel(win->display, 0), + WhitePixel(win->display, 0), GXcopy, AllPlanes); + + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT); + + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + + XFreePixmap(win->display, tmpPM); + + XSetFunction(win->display, DefaultGC(win->display, 0), + GXandInverted); + maskPM = XCreateBitmapFromData(win->display, win->boardwin, + maskbits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, maskPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, maskPM); + + XSetFunction(win->display, DefaultGC(win->display, 0), + GXor); + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + bits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, tmpPM); + + XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy); + + } else if (win->bnw){ + XSetState(win->display, DefaultGC(win->display, 0), + BlackPixel(win->display, 0), + WhitePixel(win->display, 0), GXcopy, AllPlanes); + + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + bits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, tmpPM); + } else { + XSetState(win->display, DefaultGC(win->display, 0), + ((p->color == WHITE) ? win->whitepiece.pixel : + win->blackpiece.pixel), + (iswhite(win, x, y) ? win->whitesquare.pixel : + win->blacksquare.pixel), + GXcopy, AllPlanes); + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + bits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, tmpPM); + } + + if (!record_english) { + gc.foreground = win->textcolor.pixel; + if (iswhite(win, x, y) || win->bnw) + gc.background = win->whitesquare.pixel; + else + gc.background = win->blacksquare.pixel; + + gc.font = win->small->fid; + + XChangeGC(win->display, DefaultGC(win->display, 0), + GCForeground | GCBackground | GCFont, &gc); + + if (!x) { + sprintf(buf, " %d", SIZE - y); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + 1, (y + 1) * (SQUARE_HEIGHT + + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 2); + } + if (y == SIZE - 1) { + sprintf(buf, "%c", 'A' + x); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + x * (SQUARE_WIDTH + BORDER_WIDTH) + 1, + SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 1); + } + } + return; +} + +void +win_erasepiece(y, x, wnum) + int y, x; + color wnum; +{ + windata *win; + char buf[BSIZE]; + XGCValues gc; + Pixmap tmpPM; + + if (oneboard || (wnum == win1->color)) + win = win1; + else + win = win2; + + if (win->flipped) { + y = SIZE - y - 1; + x = SIZE - x - 1; + } + + /* + if (debug) + fprintf(stderr, "erase square (%d, %d) on board %d\n", y, x, + wnum); + */ + + if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1); + + if (win->bnw && !iswhite(win, x, y)) { + XSetState(win->display, DefaultGC(win->display, 0), + BlackPixel(win->display, 0), + WhitePixel(win->display, 0), GXcopy, AllPlanes); + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT); + + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + + XFreePixmap(win->display, tmpPM); + } else { + XSetFillStyle(win->display, DefaultGC(win->display, 0), + FillSolid); + XSetForeground(win->display, DefaultGC(win->display, 0), + iswhite(win, x, y) ? win->whitesquare.pixel : + win->blacksquare.pixel); + XFillRectangle(win->display, win->boardwin, + DefaultGC(win->display, 0), + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), + SQUARE_WIDTH, SQUARE_HEIGHT); + } + + if (!record_english) { + gc.foreground = win->textcolor.pixel; + if (iswhite(win, x, y) || win->bnw) + gc.background = win->whitesquare.pixel; + else + gc.background = win->blacksquare.pixel; + + gc.font = win->small->fid; + + XChangeGC(win->display, DefaultGC(win->display, 0), + GCForeground | GCBackground | GCFont, &gc); + + if (!x) { + sprintf(buf, " %d", SIZE - y); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + 1, (y + 1) * (SQUARE_HEIGHT + + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 2); + } + if (y == SIZE - 1) { + sprintf(buf, "%c", 'A' + x); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + x * (SQUARE_WIDTH + BORDER_WIDTH) + 1, + SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 1); + } + } + + + return; +} + +void +win_flash(m, wnum) + move *m; + color wnum; +{ + windata *win; + int sx, sy, ex, ey, i; + + if (oneboard || (wnum == win1->color)) + win = win1; + else + win = win2; + + if (win->flipped) { + sx = SIZE - m->fromx - 1; + sy = SIZE - m->fromy - 1; + ex = SIZE - m->tox - 1; + ey = SIZE - m->toy - 1; + } else { + sx = m->fromx; + sy = m->fromy; + ex = m->tox; + ey = m->toy; + } + sx = sx * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2; + sy = sy * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2; + ex = ex * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2; + ey = ey * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2; + + XSetFunction(win->display, DefaultGC(win->display, 0), GXinvert); + XSetLineAttributes(win->display, DefaultGC(win->display, 0), + 0, LineSolid, 0, 0); + for (i = 0; i < num_flashes * 2; i++) { + XDrawLine(win->display,win->boardwin, + DefaultGC(win->display, 0), + sx, sy, ex, ey); + } + + XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy); + return; +} + +/* Handle input from the players. */ + +void +win_process(quick) + bool quick; +{ + int i, rfd = 0, wfd = 0, xfd = 0; + struct timeval timeout; + + timeout.tv_sec = 0; + timeout.tv_usec = (quick ? 0 : 500000); + + if (XPending(win1->display)) + service(win1); + if (!oneboard) { + if (XPending(win1->display)) + service(win2); + } + + if (oneboard) + rfd = 1 << win1->display->fd; + else + rfd = (1 << win1->display->fd) | (1 << win2->display->fd); + if (!(i = select(32, &rfd, &wfd, &xfd, &timeout))) + return; + if (i == -1) { + perror("select"); + exit(1); + } + if (rfd & (1 << win1->display->fd)) + service(win1); + if (!oneboard && (rfd & (1 << win2->display->fd))) + service(win2); + + return; +} + +static void +service(win) + windata *win; +{ + XEvent ev; + + while(XPending(win->display)) { + XNextEvent(win->display, &ev); + if (TxtFilter(win->display, &ev)) + continue; + + if (ev.xany.window == win->boardwin) { + switch (ev.type) { + case ButtonPress: + button_pressed(&ev, win); + break; + + case ButtonRelease: + button_released(&ev, win); + break; + + case Expose: + /* Redraw... */ + win_redraw(win, &ev); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->wclockwin) { + switch (ev.type) { + case Expose: + clock_draw(win, WHITE); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->bclockwin) { + switch (ev.type) { + case Expose: + clock_draw(win, BLACK); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->jailwin) { + switch (ev.type) { + case Expose: + jail_draw(win); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->buttonwin) { + switch (ev.type) { + case ButtonPress: + button_service(win, &ev); + break; + + case Expose: + button_draw(win); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->icon) { + icon_refresh(win); + } else if (ev.xany.window == win->basewin) { + message_send(win, &ev); + } else { + fprintf(stderr, "Internal Error: service: bad win\n"); + fprintf(stderr, "window = %d, event = %d\n", ev.xany.window, + ev.type); + } + } + return; +} + +void +win_redraw(win, event) + windata *win; + XEvent *event; +{ + XExposeEvent *ev = &event->xexpose; + int x1, y1, x2, y2, i, j; + + drawgrid(win); + if (ev) { + x1 = ev->x / (SQUARE_WIDTH + BORDER_WIDTH); + y1 = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH); + x2 = (ev->x + ev->width) / (SQUARE_WIDTH + BORDER_WIDTH); + y2 = (ev->y + ev->height) / (SQUARE_HEIGHT + BORDER_WIDTH); + } else { + x1 = 0; + y1 = 0; + x2 = SIZE - 1; + y2 = SIZE - 1; + } + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 < 0) x2 = 0; + if (y2 < 0) y2 = 0; + if (x1 > SIZE - 1) x1 = SIZE - 1; + if (y1 > SIZE - 1) y1 = SIZE - 1; + if (x2 > SIZE - 1) x2 = SIZE - 1; + if (y2 > SIZE - 1) y2 = SIZE - 1; + + if (win->flipped) { + y1 = SIZE - y2 - 1; + y2 = SIZE - y1 - 1; + x1 = SIZE - x2 - 1; + x2 = SIZE - x1 - 1; + } + + for (i = x1; i <= x2; i++) + for (j = y1; j <= y2; j++) { + if (chessboard->square[j][i].color == NONE) + win_erasepiece(j, i, WHITE); + else + win_drawpiece(&chessboard->square[j][i], j, i, + WHITE); + if (!oneboard) { + if (chessboard->square[j][i].color == NONE) + win_erasepiece(j, i, BLACK); + else + win_drawpiece(&chessboard->square[j][i], + j, i, BLACK); + } + } + + return; +} + +static bool +setup(dispname, win) + char *dispname; + windata *win; +{ + char buf[BSIZE], *s; + Pixmap bm, bmask; + Cursor cur; + extern char *program, *recfile; + XSizeHints xsizes; + + + if (!(win->display = XOpenDisplay(dispname))) + return (false); + + + /* Now get boolean defaults... */ + if ((s = XGetDefault(win->display, program, "noisy")) && eq(s, "on")) + noisyflag = true; + if ((s = XGetDefault(win->display, program, "savemoves")) && eq(s, "on")) + saveflag = true; + if ((s = XGetDefault(win->display, program, "algebraic")) && eq(s, "on")) + record_english = false; + if ((s = XGetDefault(win->display, program, "blackandwhite")) && eq(s, "on")) + bnwflag = true; + if ((s = XGetDefault(win->display, program, "quickrestore")) && eq(s, "on")) + quickflag = true; + if ((s = XGetDefault(win->display, program, "flash")) && eq(s, "on")) + win_flashmove = true; + + /* ... numeric variables ... */ + if (s = XGetDefault(win->display, program, "numflashes")) + num_flashes = atoi(s); + if (s = XGetDefault(win->display, program, "flashsize")) + flash_size = atoi(s); + + /* ... and strings. */ + if (s = XGetDefault(win->display, program, "progname")) + progname = s; + if (s = XGetDefault(win->display, program, "proghost")) + proghost = s; + if (s = XGetDefault(win->display, program, "recordfile")) + recfile = s; + if (s = XGetDefault(win->display, program, "blackpiece")) + black_piece_color = s; + if (s = XGetDefault(win->display, program, "whitepiece")) + white_piece_color = s; + if (s = XGetDefault(win->display, program, "blacksquare")) + black_square_color = s; + if (s = XGetDefault(win->display, program, "whitesquare")) + white_square_color = s; + if (s = XGetDefault(win->display, program, "bordercolor")) + border_color = s; + if (s = XGetDefault(win->display, program, "textcolor")) + text_color = s; + if (s = XGetDefault(win->display, program, "textback")) + text_back = s; + if (s = XGetDefault(win->display, program, "errortext")) + error_text = s; + if (s = XGetDefault(win->display, program, "playertext")) + player_text = s; + if (s = XGetDefault(win->display, program, "cursorcolor")) + cursor_color = s; + + if ((DisplayPlanes(win->display, 0) == 1) || bnwflag) + win->bnw = true; + + /* Allocate colors... */ + if (win->bnw) { + win->blackpiece.pixel = BlackPixel (win->display, 0); + win->whitepiece.pixel = WhitePixel (win->display, 0); + win->blacksquare.pixel = BlackPixel (win->display, 0); + win->whitesquare.pixel = WhitePixel (win->display, 0); + win->border.pixel = BlackPixel (win->display, 0); + win->textcolor.pixel = BlackPixel (win->display, 0); + win->textback.pixel = WhitePixel (win->display, 0); + win->playertext.pixel = BlackPixel (win->display, 0); + win->errortext.pixel = BlackPixel (win->display, 0); + win->cursorcolor.pixel = BlackPixel (win->display, 0) ; + } else { + if (!XParseColor(win->display, + DefaultColormap(win->display, 0), + black_piece_color, &win->blackpiece) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + white_piece_color, &win->whitepiece) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + black_square_color, &win->blacksquare) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + white_square_color, &win->whitesquare) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + border_color, &win->border) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + text_color, &win->textcolor) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + text_back, &win->textback) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + error_text, &win->errortext) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + player_text, &win->playertext) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + cursor_color, &win->cursorcolor) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->blackpiece) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->whitepiece) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->blacksquare) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->whitesquare) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->border) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->textcolor) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->textback) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->errortext) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->playertext) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->cursorcolor)) + fprintf(stderr, "Can't get colors...\n"); + } + + /* Get fonts... */ + if ((win->small = XLoadQueryFont(win->display,SMALL_FONT)) == + NULL) + fprintf(stderr, "Can't get small font...\n"); + + if ((win->medium = XLoadQueryFont(win->display,MEDIUM_FONT)) + == NULL) + fprintf(stderr, "Can't get medium font...\n"); + + if ((win->large = XLoadQueryFont(win->display,LARGE_FONT)) == + NULL) + fprintf(stderr, "Can't get large font...\n"); + + + /* Create the windows... */ + + win->basewin = + XCreateSimpleWindow(win->display,DefaultRootWindow(win->display), + BASE_XPOS, BASE_YPOS, + BASE_WIDTH, BASE_HEIGHT, 0, + BlackPixel(win->display, 0), + WhitePixel(win->display, 0)); + win->boardwin = XCreateSimpleWindow(win->display,win->basewin, + BOARD_XPOS, BOARD_YPOS, + BOARD_WIDTH, BOARD_HEIGHT, + BORDER_WIDTH, + win->border.pixel, + WhitePixel(win->display, 0)); + win->recwin = XCreateSimpleWindow(win->display,win->basewin, + RECORD_XPOS, RECORD_YPOS, + RECORD_WIDTH, RECORD_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->jailwin = XCreateSimpleWindow(win->display,win->basewin, + JAIL_XPOS, JAIL_YPOS, + JAIL_WIDTH, JAIL_HEIGHT, + BORDER_WIDTH, + win->border.pixel, + win->textback.pixel); + win->wclockwin = XCreateSimpleWindow(win->display,win->basewin, + WCLOCK_XPOS, WCLOCK_YPOS, + CLOCK_WIDTH, CLOCK_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->bclockwin = XCreateSimpleWindow(win->display,win->basewin, + BCLOCK_XPOS, BCLOCK_YPOS, + CLOCK_WIDTH, CLOCK_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->messagewin = XCreateSimpleWindow(win->display,win->basewin, + MESS_XPOS, MESS_YPOS, + MESS_WIDTH, MESS_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->buttonwin = XCreateSimpleWindow(win->display,win->basewin, + BUTTON_XPOS, BUTTON_YPOS, + BUTTON_WIDTH, BUTTON_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + + /* Let's define an icon... */ + win->iconpixmap = XCreatePixmapFromBitmapData(win->display, + win->basewin, icon_bits, + icon_width, icon_height, + win->blacksquare.pixel, + win->whitesquare.pixel, + 1); + xsizes.flags = PSize | PMinSize | PPosition; + xsizes.min_width = BASE_WIDTH; + xsizes.min_height = BASE_HEIGHT; + xsizes.x = BASE_XPOS; + xsizes.y = BASE_YPOS; + XSetStandardProperties(win->display, win->basewin, + program, program, win->iconpixmap, + 0, NULL, &xsizes); + + bm = XCreateBitmapFromData(win->display, + win->basewin, xchess_bits, + xchess_width, xchess_height); + bmask = XCreateBitmapFromData(win->display, + win->basewin, xchess_mask_bits, + xchess_width, xchess_height); + cur = XCreatePixmapCursor(win->display, bm, bmask, + &win->cursorcolor, + &WhitePixel(win->display, 0), + xchess_x_hot, xchess_y_hot); + XFreePixmap(win->display, bm); + XFreePixmap(win->display, bmask); + + XDefineCursor(win->display,win->basewin, cur); + + XMapSubwindows(win->display,win->basewin); + XMapRaised(win->display,win->basewin); + + XSelectInput(win->display,win->basewin, KeyPressMask); + XSelectInput(win->display,win->boardwin, + ButtonPressMask | ButtonReleaseMask | ExposureMask); + XSelectInput(win->display,win->recwin, + ButtonReleaseMask | ExposureMask); + XSelectInput(win->display,win->jailwin, ExposureMask); + XSelectInput(win->display,win->wclockwin, ExposureMask); + XSelectInput(win->display,win->bclockwin, ExposureMask); + XSelectInput(win->display,win->messagewin, + ButtonReleaseMask | ExposureMask); + XSelectInput(win->display,win->buttonwin, + ButtonPressMask | ExposureMask); + + message_init(win); + record_init(win); + button_draw(win); + jail_init(win); + clock_init(win, WHITE); + clock_init(win, BLACK); + if (timeunit) { + if (timeunit > 1800) + sprintf(buf, "%d moves every %.2lg hours.\n", + movesperunit, ((double) timeunit) / 3600); + else if (timeunit > 30) + sprintf(buf, "%d moves every %.2lg minutes.\n", + movesperunit, ((double) timeunit) / 60); + else + sprintf(buf, "%d moves every %d seconds.\n", + movesperunit, timeunit); + message_add(win, buf, false); + } + return (true); +} + +static void +drawgrid(win) + windata *win; +{ + int i; + XGCValues gc; + + gc.function = GXcopy; + gc.plane_mask = AllPlanes; + gc.foreground = win->border.pixel; + gc.line_width = 0; + gc.line_style = LineSolid; + + XChangeGC(win->display, + DefaultGC(win->display, 0), + GCFunction | GCPlaneMask | GCForeground | + GCLineWidth | GCLineStyle, &gc); + + /* Draw the lines... horizontal, */ + for (i = 1; i < SIZE; i++) + XDrawLine(win->display, win->boardwin, + DefaultGC(win->display, 0), 0, + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2, + SIZE * (SQUARE_WIDTH + BORDER_WIDTH), + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2); + + /* and vertical... */ + for (i = 1; i < SIZE; i++) + XDrawLine(win->display, win->boardwin, + DefaultGC(win->display, 0), + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2, 0, + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2, + SIZE * (SQUARE_WIDTH + BORDER_WIDTH)); + return; +} + +void +win_restart() +{ + win1->flipped = false; + win_redraw(win1, (XEvent *) NULL); + if (!oneboard) { + win2->flipped = true; + win_redraw(win2, (XEvent *) NULL); + } + return; +} + +static void +icon_refresh(win) + windata *win; +{ + XCopyArea(win->display, win->iconpixmap, win->icon, + DefaultGC(win->display, 0), + 0, 0, icon_width, icon_height, 0, 0); + return; +} + diff --git a/gnu/games/chess/Xchess/window.c.bm b/gnu/games/chess/Xchess/window.c.bm new file mode 100644 index 000000000000..19134d0cdc14 --- /dev/null +++ b/gnu/games/chess/Xchess/window.c.bm @@ -0,0 +1,928 @@ +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $ + * $Source: /users/faustus/xchess/RCS/window.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Deal with the two (or one) windows. + */ + +#include "xchess.h" +#include + +#include "pawn.bitmap" +#include "rook.bitmap" +#include "knight.bitmap" +#include "bishop.bitmap" +#include "queen.bitmap" +#include "king.bitmap" + +#include "pawn_outline.bitmap" +#include "rook_outline.bitmap" +#include "knight_outline.bitmap" +#include "bishop_outline.bitmap" +#include "queen_outline.bitmap" +#include "king_outline.bitmap" + +#include "pawn_mask.bitmap" +#include "rook_mask.bitmap" +#include "knight_mask.bitmap" +#include "bishop_mask.bitmap" +#include "queen_mask.bitmap" +#include "king_mask.bitmap" + +#include "shade.bitmap" + +#include "xchess.cur" +#include "xchess_mask.cur" + +#include "xchess.icon" + +windata *win1, *win2; +bool win_flashmove = false; + +extern bool setup(); +extern void service(), drawgrid(), icon_refresh(); + +bool +win_setup(disp1, disp2) + char *disp1, *disp2; +{ + win1 = alloc(windata); + if (!oneboard) + win2 = alloc(windata); + + if (!setup(disp1, win1) || (!oneboard && !setup(disp2, win2))) + return (false); + + if (blackflag) { + win1->color = BLACK; + win1->flipped = true; + } else + win1->color = WHITE; + win_drawboard(win1); + + if (!oneboard) { + win2->color = BLACK; + win2->flipped = true; + win_drawboard(win2); + } + + return(true); +} + +/* Draw the chess board... */ + +void +win_drawboard(win) + windata *win; +{ + int i, j; + + drawgrid(win); + + /* Now toss on the squares... */ + for (i = 0; i < SIZE; i++) + for (j = 0; j < SIZE; j++) + win_erasepiece(j, i, win->color); + + return; +} + +/* Draw one piece. */ + +void +win_drawpiece(p, y, x, wnum) + piece *p; + int y, x; + color wnum; +{ + char *bits, *maskbits, *outline; + windata *win; + char buf[BSIZE]; + XImage *tmpImage; + Pixmap tmpPM, maskPM; + XGCValues gc; + + if (oneboard || (wnum == win1->color)) + win = win1; + else + win = win2; + + if (win->flipped) { + y = SIZE - y - 1; + x = SIZE - x - 1; + } + + /* + if (debug) + fprintf(stderr, "draw a %s at (%d, %d) on board %d\n", + piecenames[(int) p->type], y, x, wnum); + */ + + if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1); + + switch (p->type) { + case PAWN: + bits = pawn_bits; + maskbits = pawn_mask_bits; + outline = pawn_outline_bits; + break; + + case ROOK: + bits = rook_bits; + maskbits = rook_mask_bits; + outline = rook_outline_bits; + break; + + case KNIGHT: + bits = knight_bits; + maskbits = knight_mask_bits; + outline = knight_outline_bits; + break; + + case BISHOP: + bits = bishop_bits; + maskbits = bishop_mask_bits; + outline = bishop_outline_bits; + break; + + case QUEEN: + bits = queen_bits; + maskbits = queen_mask_bits; + outline = queen_outline_bits; + break; + + case KING: + bits = king_bits; + maskbits = king_mask_bits; + outline = king_outline_bits; + break; + + default: + fprintf(stderr, + "Internal Error: win_drawpiece: bad piece type %d\n", + p->type); + } + + /* There are two things we can do... If this is a black and white + * display, we have to shade the square and use an outline if the piece + * is white. We also have to use a mask... Since we don't want + * to use up too many bitmaps, create the mask bitmap, put the bits, + * and then destroy it. + */ + if (win->bnw && (p->color == WHITE)) + bits = outline; + if (win->bnw && !iswhite(win, x, y)) { + XSetState(win->display, DefaultGC(win->display, 0), + BlackPixel(win->display, 0), + WhitePixel(win->display, 0), GXcopy, AllPlanes); + + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT); + + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + + XFreePixmap(win->display, tmpPM); + + XSetFunction(win->display, DefaultGC(win->display, 0), + GXandInverted); + maskPM = XCreateBitmapFromData(win->display, win->boardwin, + maskbits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, maskPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, maskPM); + + XSetFunction(win->display, DefaultGC(win->display, 0), + GXor); + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + bits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, tmpPM); + + XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy); + + } else if (win->bnw){ + XSetState(win->display, DefaultGC(win->display, 0), + BlackPixel(win->display, 0), + WhitePixel(win->display, 0), GXcopy, AllPlanes); + + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + bits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, tmpPM); + } else { + XSetState(win->display, DefaultGC(win->display, 0), + ((p->color == WHITE) ? win->whitepiece.pixel : + win->blackpiece.pixel), + (iswhite(win, x, y) ? win->whitesquare.pixel : + win->blacksquare.pixel), + GXcopy, AllPlanes); + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + bits, SQUARE_WIDTH, SQUARE_HEIGHT); + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + XFreePixmap(win->display, tmpPM); + } + + if (!record_english) { + gc.foreground = win->textcolor.pixel; + if (iswhite(win, x, y) || win->bnw) + gc.background = win->whitesquare.pixel; + else + gc.background = win->blacksquare.pixel; + + gc.font = win->small->fid; + + XChangeGC(win->display, DefaultGC(win->display, 0), + GCForeground | GCBackground | GCFont, &gc); + + if (!x) { + sprintf(buf, " %d", SIZE - y); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + 1, (y + 1) * (SQUARE_HEIGHT + + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 2); + } + if (y == SIZE - 1) { + sprintf(buf, "%c", 'A' + x); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + x * (SQUARE_WIDTH + BORDER_WIDTH) + 1, + SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 1); + } + } + return; +} + +void +win_erasepiece(y, x, wnum) + int y, x; + color wnum; +{ + windata *win; + char buf[BSIZE]; + XGCValues gc; + Pixmap tmpPM; + + if (oneboard || (wnum == win1->color)) + win = win1; + else + win = win2; + + if (win->flipped) { + y = SIZE - y - 1; + x = SIZE - x - 1; + } + + /* + if (debug) + fprintf(stderr, "erase square (%d, %d) on board %d\n", y, x, + wnum); + */ + + if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1); + + if (win->bnw && !iswhite(win, x, y)) { + XSetState(win->display, DefaultGC(win->display, 0), + BlackPixel(win->display, 0), + WhitePixel(win->display, 0), GXcopy, AllPlanes); + tmpPM = XCreateBitmapFromData(win->display, win->boardwin, + shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT); + + XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0), + 0, 0, SQUARE_WIDTH, SQUARE_HEIGHT, + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), 1); + + XFreePixmap(win->display, tmpPM); + } else { + XSetFillStyle(win->display, DefaultGC(win->display, 0), + FillSolid); + XSetForeground(win->display, DefaultGC(win->display, 0), + iswhite(win, x, y) ? win->whitesquare.pixel : + win->blacksquare.pixel); + XFillRectangle(win->display, win->boardwin, + DefaultGC(win->display, 0), + x * (SQUARE_WIDTH + BORDER_WIDTH), + y * (SQUARE_HEIGHT + BORDER_WIDTH), + SQUARE_WIDTH, SQUARE_HEIGHT); + } + + if (!record_english) { + gc.foreground = win->textcolor.pixel; + if (iswhite(win, x, y) || win->bnw) + gc.background = win->whitesquare.pixel; + else + gc.background = win->blacksquare.pixel; + + gc.font = win->small->fid; + + XChangeGC(win->display, DefaultGC(win->display, 0), + GCForeground | GCBackground | GCFont, &gc); + + if (!x) { + sprintf(buf, " %d", SIZE - y); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + 1, (y + 1) * (SQUARE_HEIGHT + + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 2); + } + if (y == SIZE - 1) { + sprintf(buf, "%c", 'A' + x); + XDrawImageString(win->display, win->boardwin, + DefaultGC(win->display, 0), + x * (SQUARE_WIDTH + BORDER_WIDTH) + 1, + SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH + + win->small->max_bounds.ascent - 1, buf, 1); + } + } + + + return; +} + +void +win_flash(m, wnum) + move *m; + color wnum; +{ + windata *win; + int sx, sy, ex, ey, i; + + if (oneboard || (wnum == win1->color)) + win = win1; + else + win = win2; + + if (win->flipped) { + sx = SIZE - m->fromx - 1; + sy = SIZE - m->fromy - 1; + ex = SIZE - m->tox - 1; + ey = SIZE - m->toy - 1; + } else { + sx = m->fromx; + sy = m->fromy; + ex = m->tox; + ey = m->toy; + } + sx = sx * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2; + sy = sy * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2; + ex = ex * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2; + ey = ey * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2; + + for (i = 0; i < num_flashes * 2; i++) + XDrawLine(win->display,win->boardwin, + DefaultGC(win->display, 0), + sx, sy, ex, ey); + return; +} + +/* Handle input from the players. */ + +void +win_process(quick) + bool quick; +{ + int i, rfd = 0, wfd = 0, xfd = 0; + struct timeval timeout; + + timeout.tv_sec = 0; + timeout.tv_usec = (quick ? 0 : 500000); + + if (XPending(win1->display)) + service(win1); + if (!oneboard) { + if (XPending(win1->display)) + service(win2); + } + + if (oneboard) + rfd = 1 << win1->display->fd; + else + rfd = (1 << win1->display->fd) | (1 << win2->display->fd); + if (!(i = select(32, &rfd, &wfd, &xfd, &timeout))) + return; + if (i == -1) { + perror("select"); + exit(1); + } + if (rfd & (1 << win1->display->fd)) + service(win1); + if (!oneboard && (rfd & (1 << win2->display->fd))) + service(win2); + + return; +} + +static void +service(win) + windata *win; +{ + XEvent ev; + + while(XPending(win->display)) { + XNextEvent(win->display, &ev); + if (TxtFilter(win->display, &ev)) + continue; + + if (ev.xany.window == win->boardwin) { + switch (ev.type) { + case ButtonPress: + button_pressed(&ev, win); + break; + + case ButtonRelease: + button_released(&ev, win); + break; + + case Expose: + /* Redraw... */ + win_redraw(win, &ev); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->wclockwin) { + switch (ev.type) { + case Expose: + clock_draw(win, WHITE); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->bclockwin) { + switch (ev.type) { + case Expose: + clock_draw(win, BLACK); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->jailwin) { + switch (ev.type) { + case Expose: + jail_draw(win); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->buttonwin) { + switch (ev.type) { + case ButtonPress: + button_service(win, &ev); + break; + + case Expose: + button_draw(win); + break; + + case 0: + case NoExpose: + break; + default: + fprintf(stderr, "Bad event type %d\n", ev.type); + exit(1); + } + } else if (ev.xany.window == win->icon) { + icon_refresh(win); + } else if (ev.xany.window == win->basewin) { + message_send(win, &ev); + } else { + fprintf(stderr, "Internal Error: service: bad win\n"); + fprintf(stderr, "window = %d, event = %d\n", ev.xany.window, + ev.type); + } + } + return; +} + +void +win_redraw(win, event) + windata *win; + XEvent *event; +{ + XExposeEvent *ev = &event->xexpose; + int x1, y1, x2, y2, i, j; + + drawgrid(win); + if (ev) { + x1 = ev->x / (SQUARE_WIDTH + BORDER_WIDTH); + y1 = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH); + x2 = (ev->x + ev->width) / (SQUARE_WIDTH + BORDER_WIDTH); + y2 = (ev->y + ev->height) / (SQUARE_HEIGHT + BORDER_WIDTH); + } else { + x1 = 0; + y1 = 0; + x2 = SIZE - 1; + y2 = SIZE - 1; + } + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 < 0) x2 = 0; + if (y2 < 0) y2 = 0; + if (x1 > SIZE - 1) x1 = SIZE - 1; + if (y1 > SIZE - 1) y1 = SIZE - 1; + if (x2 > SIZE - 1) x2 = SIZE - 1; + if (y2 > SIZE - 1) y2 = SIZE - 1; + + if (win->flipped) { + y1 = SIZE - y2 - 1; + y2 = SIZE - y1 - 1; + x1 = SIZE - x2 - 1; + x2 = SIZE - x1 - 1; + } + + for (i = x1; i <= x2; i++) + for (j = y1; j <= y2; j++) { + if (chessboard->square[j][i].color == NONE) + win_erasepiece(j, i, WHITE); + else + win_drawpiece(&chessboard->square[j][i], j, i, + WHITE); + if (!oneboard) { + if (chessboard->square[j][i].color == NONE) + win_erasepiece(j, i, BLACK); + else + win_drawpiece(&chessboard->square[j][i], + j, i, BLACK); + } + } + + return; +} + +static bool +setup(dispname, win) + char *dispname; + windata *win; +{ + char buf[BSIZE], *s; + Pixmap bm, bmask; + Cursor cur; + extern char *program, *recfile; + + + if (!(win->display = XOpenDisplay(dispname))) + return (false); + + + /* Now get boolean defaults... */ + if ((s = XGetDefault(win->display, program, "noisy")) && eq(s, "on")) + noisyflag = true; + if ((s = XGetDefault(win->display, program, "savemoves")) && eq(s, "on")) + saveflag = true; + if ((s = XGetDefault(win->display, program, "algebraic")) && eq(s, "on")) + record_english = false; + if ((s = XGetDefault(win->display, program, "blackandwhite")) && eq(s, "on")) + bnwflag = true; + if ((s = XGetDefault(win->display, program, "quickrestore")) && eq(s, "on")) + quickflag = true; + if ((s = XGetDefault(win->display, program, "flash")) && eq(s, "on")) + win_flashmove = true; + + /* ... numeric variables ... */ + if (s = XGetDefault(win->display, program, "numflashes")) + num_flashes = atoi(s); + if (s = XGetDefault(win->display, program, "flashsize")) + flash_size = atoi(s); + + /* ... and strings. */ + if (s = XGetDefault(win->display, program, "progname")) + progname = s; + if (s = XGetDefault(win->display, program, "proghost")) + proghost = s; + if (s = XGetDefault(win->display, program, "recordfile")) + recfile = s; + if (s = XGetDefault(win->display, program, "blackpiece")) + black_piece_color = s; + if (s = XGetDefault(win->display, program, "whitepiece")) + white_piece_color = s; + if (s = XGetDefault(win->display, program, "blacksquare")) + black_square_color = s; + if (s = XGetDefault(win->display, program, "whitesquare")) + white_square_color = s; + if (s = XGetDefault(win->display, program, "bordercolor")) + border_color = s; + if (s = XGetDefault(win->display, program, "textcolor")) + text_color = s; + if (s = XGetDefault(win->display, program, "textback")) + text_back = s; + if (s = XGetDefault(win->display, program, "errortext")) + error_text = s; + if (s = XGetDefault(win->display, program, "playertext")) + player_text = s; + if (s = XGetDefault(win->display, program, "cursorcolor")) + cursor_color = s; + + if ((DisplayPlanes(win->display, 0) == 1) || bnwflag) + win->bnw = true; + + /* Allocate colors... */ + if (win->bnw) { + win->blackpiece.pixel = BlackPixel (win->display, 0); + win->whitepiece.pixel = WhitePixel (win->display, 0); + win->blacksquare.pixel = BlackPixel (win->display, 0); + win->whitesquare.pixel = WhitePixel (win->display, 0); + win->border.pixel = BlackPixel (win->display, 0); + win->textcolor.pixel = BlackPixel (win->display, 0); + win->textback.pixel = WhitePixel (win->display, 0); + win->playertext.pixel = BlackPixel (win->display, 0); + win->errortext.pixel = BlackPixel (win->display, 0); + win->cursorcolor.pixel = BlackPixel (win->display, 0) ; + } else { + if (!XParseColor(win->display, + DefaultColormap(win->display, 0), + black_piece_color, &win->blackpiece) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + white_piece_color, &win->whitepiece) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + black_square_color, &win->blacksquare) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + white_square_color, &win->whitesquare) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + border_color, &win->border) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + text_color, &win->textcolor) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + text_back, &win->textback) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + error_text, &win->errortext) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + player_text, &win->playertext) || + !XParseColor(win->display, + DefaultColormap(win->display, 0), + cursor_color, &win->cursorcolor) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->blackpiece) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->whitepiece) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->blacksquare) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->whitesquare) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->border) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->textcolor) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->textback) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->errortext) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->playertext) || + !XAllocColor(win->display, + DefaultColormap(win->display, 0), + &win->cursorcolor)) + fprintf(stderr, "Can't get color...\n"); + } + + /* Get fonts... */ + win->small = XLoadQueryFont(win->display,SMALL_FONT); + win->medium = XLoadQueryFont(win->display,MEDIUM_FONT); + win->large = XLoadQueryFont(win->display,LARGE_FONT); + + /* Create the windows... */ + + win->basewin = + XCreateSimpleWindow(win->display,DefaultRootWindow(win->display), + BASE_XPOS, BASE_YPOS, + BASE_WIDTH, BASE_HEIGHT, 0, + BlackPixel(win->display, 0), + WhitePixel(win->display, 0)); + win->boardwin = XCreateSimpleWindow(win->display,win->basewin, + BOARD_XPOS, BOARD_YPOS, + BOARD_WIDTH, BOARD_HEIGHT, + BORDER_WIDTH, + win->border.pixel, + WhitePixel(win->display, 0)); + win->recwin = XCreateSimpleWindow(win->display,win->basewin, + RECORD_XPOS, RECORD_YPOS, + RECORD_WIDTH, RECORD_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->jailwin = XCreateSimpleWindow(win->display,win->basewin, + JAIL_XPOS, JAIL_YPOS, + JAIL_WIDTH, JAIL_HEIGHT, + BORDER_WIDTH, + win->border.pixel, + win->textback.pixel); + win->wclockwin = XCreateSimpleWindow(win->display,win->basewin, + WCLOCK_XPOS, WCLOCK_YPOS, + CLOCK_WIDTH, CLOCK_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->bclockwin = XCreateSimpleWindow(win->display,win->basewin, + BCLOCK_XPOS, BCLOCK_YPOS, + CLOCK_WIDTH, CLOCK_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->messagewin = XCreateSimpleWindow(win->display,win->basewin, + MESS_XPOS, MESS_YPOS, + MESS_WIDTH, MESS_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + win->buttonwin = XCreateSimpleWindow(win->display,win->basewin, + BUTTON_XPOS, BUTTON_YPOS, + BUTTON_WIDTH, BUTTON_HEIGHT, + BORDER_WIDTH, win->border.pixel, + win->textback.pixel); + + /* Let's define an icon... */ + win->iconpixmap = XCreatePixmapFromBitmapData(win->display, + win->basewin, icon_bits, + icon_width, icon_height, + win->blacksquare.pixel, + win->whitesquare.pixel, + 1); + + bm = XCreateBitmapFromData(win->display, + win->basewin, xchess_bits, + xchess_width, xchess_height); + bmask = XCreateBitmapFromData(win->display, + win->basewin, xchess_mask_bits, + xchess_width, xchess_height); + cur = XCreatePixmapCursor(win->display, bm, bmask, + &win->cursorcolor, + &WhitePixel(win->display, 0), + xchess_x_hot, xchess_y_hot); + XFreePixmap(win->display, bm); + XFreePixmap(win->display, bmask); + + XDefineCursor(win->display,win->basewin, cur); + + XMapSubwindows(win->display,win->basewin); + XMapRaised(win->display,win->basewin); + + XSelectInput(win->display,win->basewin, KeyPressMask); + XSelectInput(win->display,win->boardwin, + ButtonPressMask | ButtonReleaseMask | ExposureMask); + XSelectInput(win->display,win->recwin, + ButtonReleaseMask | ExposureMask); + XSelectInput(win->display,win->jailwin, ExposureMask); + XSelectInput(win->display,win->wclockwin, ExposureMask); + XSelectInput(win->display,win->bclockwin, ExposureMask); + XSelectInput(win->display,win->messagewin, + ButtonReleaseMask | ExposureMask); + XSelectInput(win->display,win->buttonwin, + ButtonPressMask | ExposureMask); + + message_init(win); + record_init(win); + button_draw(win); + jail_init(win); + clock_init(win, WHITE); + clock_init(win, BLACK); + if (timeunit) { + if (timeunit > 1800) + sprintf(buf, "%d moves every %.2lg hours.\n", + movesperunit, ((double) timeunit) / 3600); + else if (timeunit > 30) + sprintf(buf, "%d moves every %.2lg minutes.\n", + movesperunit, ((double) timeunit) / 60); + else + sprintf(buf, "%d moves every %d seconds.\n", + movesperunit, timeunit); + message_add(win, buf, false); + } + + return (true); +} + +static void +drawgrid(win) + windata *win; +{ + int i; + XGCValues gc; + + gc.function = GXcopy; + gc.plane_mask = AllPlanes; + gc.foreground = win->border.pixel; + gc.line_width = 0; + gc.line_style = LineSolid; + + XChangeGC(win->display, + DefaultGC(win->display, 0), + GCFunction | GCPlaneMask | GCForeground | + GCLineWidth | GCLineStyle, &gc); + + /* Draw the lines... horizontal, */ + for (i = 1; i < SIZE; i++) + XDrawLine(win->display, win->boardwin, + DefaultGC(win->display, 0), 0, + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2, + SIZE * (SQUARE_WIDTH + BORDER_WIDTH), + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2); + + /* and vertical... */ + for (i = 1; i < SIZE; i++) + XDrawLine(win->display, win->boardwin, + DefaultGC(win->display, 0), + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2, 0, + i * (SQUARE_WIDTH + BORDER_WIDTH) - + BORDER_WIDTH / 2, + SIZE * (SQUARE_WIDTH + BORDER_WIDTH)); + return; +} + +void +win_restart() +{ + win1->flipped = false; + win_redraw(win1, (XEvent *) NULL); + if (!oneboard) { + win2->flipped = true; + win_redraw(win2, (XEvent *) NULL); + } + return; +} + +static void +icon_refresh(win) + windata *win; +{ + XCopyArea(win->display, win->iconpixmap, win->icon, + DefaultGC(win->display, 0), + 0, 0, icon_width, icon_height, 0, 0); + return; +} + diff --git a/gnu/games/chess/Xchess/xchess.1 b/gnu/games/chess/Xchess/xchess.1 new file mode 100644 index 000000000000..e6875136100c --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.1 @@ -0,0 +1,217 @@ + +.TH XCHESS 1 "14 Nov 1986" "X Version 10" +.SH NAME +xchess \- X chess display +.SH SYNOPSIS +.B xchess +[ option ... ] [ white-display ] [ black-display ] +.SH DESCRIPTION +.PP +.B xchess +is a chess display program which allows players to play a game on either +one or two displays, or play a chess-playing program. It uses the +.B X +window system. If one or no display names are given, it will open up one +window and both black and white at the same board. If two displays are +given, +.B xchess +will accept moves from each player in his turn. Black's board will be drawn +with his pieces at the bottom. +.PP +.B xchess +will not allow a player to make an illegal move. It accepts all legal moves, +including castling and pawn capture \fIen passant\fR. +.SH OPTIONS +.TP 8 +.B -d +Turn on debugging. +.TP 8 +.B -f record-file +Use \fBrecord-file\fR for saving the game when the \fBSave\fR button is +selected, or if the \fB-s\fR flag is given. The default is "xchess.game". +.TP 8 +.B -r saved-game +Start with the position at the end of the saved game in the named file. +This file may be the result of the \fBSave\fR command, and may be in +either English or International format. When reading moves, one move +it made per second. +.TP 8 +.B -q +Don't pause for a second every time a move is made when a game is being +restored. +.TP 8 +.B -v +Whenever a piece is moved, outline the path with a "lightning bolt". +This option and the \fB-n\fR option are useful if you don't want to miss +an opponent's move when he makes it. +.TP 8 +.B -i +Use International format for recording moves (squares numbered 1-8, a-h) +as opposed to English (e.g, \fIp/k4xp/q5\fR). +.TP 8 +.B -t moves/timeunit +Allows \fBtimeunit\fR seconds for every \fBmoves\fR moves. If either player +exceeds this allowance both recieve a message saying informing them of +this fact. +.TP 8 +.B -c +Play the computer. +.B xchess +will start up a chess-playing program (currently the only one it knows +how to talk to is \fBGNU Chess\fR). +.TP 8 +.B -p program +The name of the program to use if the \fB-c\fR option is given. The +default is "/usr/public/gnuchess". Note that \fBgnuchess\fR must be +compiled with the \fIcompat\fR flag (in the file "main.c") set to 1. +.TP 8 +.B -b +If the \fB-c\fR flag was given, have the computer play white. +.TP 8 +.B -bnw +If the display has more than one display plane (i.e, is color), pretend +it's black and white. +.TP 8 +.B -s +Save the moves in the record file as they are made. This is useful if +you don't want your game to be lost when \fBxchess\fR core dumps. +.TP 8 +.B -n +Be noisy \- beep after every move is made. +.TP 8 +.B -h host +Run GNU Chess on the specified \fBhost\fR. +.TP 8 +.B -R +Randomly chose who plays white and who plays black, if two displays are +given. +.SH CONTROLS +.PP +The window is divided up into several sub-windows. The pieces are moved by +pushing down any mouse button on top of the piece, moving to the destination +square, and releasing it. Castling is done by moving the king to the +right square. If you push down on a piece and then let the button +up without moving it, you must move that piece. ("Touch it, move it.") +.PP +The progress of the game is listed in the "Game Record" window. Error +messages and such things are printed in the "Message" window. Both these +windows have scroll bars that you can use to move around. +There are also windows for clocks and for a record of the pieces captured. +.PP +If you type any keys in the window, the text will go into the message +window of both players. This provides a simple communication facility. +.PP +There are 9 buttons in the control window. They are as follows: +.TP 8 +.B Draw +Both players must push this button to agree on a draw (just one is ok +if only one display is being used). +.TP 8 +.B Resign +The player whose turn it is to move resigns. +.TP 8 +.B Reset +Start over from the beginning. +.TP 8 +.B Back +Retract a move. If two displays are being used the other player will be +asked to confirm this. +.TP 8 +.B Fwd +This will re-play the most recently retracted move. This button in conjunction +with \fBBack\fR is useful for "scrolling around" in a saved game. +.TP 8 +.B Save +Save the game in the record file. +.TP 8 +.B Flip +Rotate the board so that Black will have his pieces at the bottom. +.TP 8 +.B Switch +Change the mapping of boards to players. +.TP 8 +.B Pause +This button has two functions. When a game is being restored, pieces will +be moved once a second. Hitting \fBPause\fR will stop this process, and +hitting it again will restart it. During the time that it is stopped no +other action can be made except restarting it. While a game is being played, +\fBPause\fR will stop the clock and restart it. +.SH DEFAULTS +.PP +\fBxchess\fR uses the following \fI.Xdefaults\fR: +.TP 8 +.B Noisy +The -n flag. +.TP 8 +.B SaveMoves +The -s flag. +.TP 8 +.B Algebraic +The -i flag. +.TP 8 +.B BlackAndWhite +The -bnw flag. +.TP 8 +.B QuickRestore +The -q flag. +.TP 8 +.B Flash +The -v flag. +.TP 8 +.B NumFlashes +How many times to flash the move. The default is 5. +.TP 8 +.B FlashWidth +How big to make the lightning bolt. The default is 10 pixels. +.TP 8 +.B ProgName +The -p option. This may also be changed in the Makefile (-DDEF_PROG_NAME). +.TP 8 +.B ProgHost +The -h option. +.TP 8 +.B RecordFile +The -f option. +.TP 8 +.B BlackPiece +The color of the black pieces. +.TP 8 +.B WhitePiece +The color of the white pieces. +.TP 8 +.B BorderColor +The color of the borders. +.TP 8 +.B BlackSquare +The color of the black squares. +.TP 8 +.B WhiteSquare +The color of the white squares. +.TP 8 +.B TextColor +The color of routine messages and the move record text. +.TP 8 +.B ErrorText +The color of error messages. +.TP 8 +.B PlayerText +The color of player-entered text. +.TP 8 +.B TextBack +The background color for the two text windows. +.TP 8 +.B CursorColor +The color of the mouse and the text cursors. +.SH "SEE ALSO" +X(8), gnuchess(1), chess(5) +.SH AUTHOR +Wayne A. Christopher (faustus@ic.berkeley.edu) +.SH BUGS +.PP +Checkmate and stalemate are not detected, so the appropriate player must resign +or agree to a draw respectively. +.PP +\fBSwitch\fR doesn't work. +.PP +If you are playing \fBgnuchess\fR, and you select Undo a few times so that it +is \fBgnuchess\fR's turn to move, it won't do anything. diff --git a/gnu/games/chess/Xchess/xchess.c b/gnu/games/chess/Xchess/xchess.c new file mode 100644 index 000000000000..6de6502ddd28 --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.c @@ -0,0 +1,205 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.2 $ on $Date: 89/04/28 08:44:02 $ + * $Source: /usr/local/src/source/X.V11R3/contrib/games/xchess/Xchess/RCS/xchess.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + */ + +#define USAGE "xchess [ -d ] [ -f recordfile ] [ -r savedfile ] [ -i ]\n\ +\t[ -t moves/timeunit ] [ -c ] [ -p program ] [ -b ] [ -bnw ] [ -s ]\n\ +\t[ -n ] [ -h host ] [ -v ] [ -R ] [ whitedisplay ] [ blackdisplay ]" + +#include +#include "xchess.h" + +bool debug = false; +bool oneboard = false; +bool bnwflag = false; +bool progflag = false; +bool blackflag = false; +bool quickflag = false; + +char *progname = DEF_PROGRAM; +char *proghost = NULL; +char *piecenames[] = { "pawn", "rook", "knight", "bishop", "queen", "king" } ; +char *colornames[] = { "white", "black", "none" } ; +char *movetypenames[] = { "move", "qcastle", "kcastle", "capture" } ; +char *dispname1 = NULL, *dispname2 = NULL; + +char *black_piece_color = BLACK_PIECE_COLOR; +char *white_piece_color = WHITE_PIECE_COLOR; +char *black_square_color = BLACK_SQUARE_COLOR; +char *white_square_color = WHITE_SQUARE_COLOR; +char *border_color = BORDER_COLOR; +char *text_color = TEXT_COLOR; +char *text_back = TEXT_BACK; +char *error_text = ERROR_TEXT; +char *player_text = PLAYER_TEXT; +char *cursor_color = CURSOR_COLOR; + +int num_flashes = NUM_FLASHES; +int flash_size = FLASH_SIZE; +char *program; +char *recfile = NULL; + +#ifdef notdef +/* + * Serves no purpose. + */ +die () { +fprintf(stderr, "child proc changed status?!\n"); +} +#endif + +void +main(ac, av) + char **av; +{ + bool randflag = false; + move *m; + char *s; + + program = av[0]; + +#ifdef notdef + signal(SIGCHLD, die); +#endif + + /* Process args. */ + av++; ac--; + while (ac > 0 && **av == '-') { + if (eq(*av, "-d")) { + debug = true; + } else if (eq(*av, "-f")) { + av++; ac--; + if (*av) + record_file = *av; + else + goto usage; + } else if (eq(*av, "-r")) { + av++; ac--; + if (*av) + recfile = *av; + else + goto usage; + } else if (eq(*av, "-i")) { + record_english = false; + } else if (eq(*av, "-R")) { + randflag = true; + } else if (eq(*av, "-v")) { + win_flashmove = true; + } else if (eq(*av, "-q")) { + quickflag = true; + } else if (eq(*av, "-t")) { + av++; ac--; + if (*av) { + movesperunit = atoi(*av); + if (s = index(*av, '/')) + timeunit = atoi(s + 1) * 60; + else + timeunit = 60; + } else + goto usage; + } else if (eq(*av, "-p")) { + av++; ac--; + if (*av) + progname = *av; + else + goto usage; + } else if (eq(*av, "-h")) { + av++; ac--; + if (*av) + proghost = *av; + else + goto usage; + } else if (eq(*av, "-b")) { + blackflag = true; + } else if (eq(*av, "-c")) { + progflag = true; + } else if (eq(*av, "-bnw")) { + bnwflag = true; + } else if (eq(*av, "-s")) { + saveflag = true; + } else if (eq(*av, "-n")) { + noisyflag = true; + } else + goto usage; + av++; ac--; + } + if (ac > 0) + dispname1 = av[0]; + if (ac > 1) + dispname2 = av[1]; + if (ac > 2) + goto usage; + + if (!dispname2) + oneboard = true; + + srandom(getpid()); + + if (!oneboard && randflag && (random() % 2)) { + s = dispname1; + dispname1 = dispname2; + dispname2 = s; + } + + if (!dispname1) + dispname1 = getenv("DISPLAY"); + + /* Set up the board. */ + board_setup(); + + /* Create the windows. */ + win_setup(dispname1, dispname2); + + board_drawall(); + + /* Start the program if necessary. */ + if (progflag) + if (!program_init(progname)) + exit(1); + + if (recfile) + load_game(recfile); + + /* Go into a loop of prompting players alternately for moves, checking + * them, and updating things. + */ + for (;;) { + win_process(false); + clock_update(); + if (progflag && ((!blackflag && (nexttomove == BLACK)) || + (blackflag && (nexttomove == WHITE)))) { + m = program_get(); + if (m) + prog_move(m); + } + } + +usage: fprintf(stderr, "Usage: %s\n", USAGE); + exit(1); +} + diff --git a/gnu/games/chess/Xchess/xchess.c.150 b/gnu/games/chess/Xchess/xchess.c.150 new file mode 100644 index 000000000000..2c17906c3571 --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.c.150 @@ -0,0 +1,197 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:32 $ + * $Source: /users/faustus/xchess/RCS/xchess.c,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + */ + +#define USAGE "xchess [ -d ] [ -f recordfile ] [ -r savedfile ] [ -i ]\n\ +\t[ -t moves/timeunit ] [ -c ] [ -p program ] [ -b ] [ -bnw ] [ -s ]\n\ +\t[ -n ] [ -h host ] [ -v ] [ -R ] [ whitedisplay ] [ blackdisplay ]" + +#include +#include "xchess.h" + +bool debug = false; +bool oneboard = false; +bool bnwflag = false; +bool progflag = false; +bool blackflag = false; +bool quickflag = false; + +char *progname = DEF_PROGRAM; +char *proghost = NULL; +char *piecenames[] = { "pawn", "rook", "knight", "bishop", "queen", "king" } ; +char *colornames[] = { "white", "black", "none" } ; +char *movetypenames[] = { "move", "qcastle", "kcastle", "capture" } ; +char *dispname1 = NULL, *dispname2 = NULL; + +char *black_piece_color = BLACK_PIECE_COLOR; +char *white_piece_color = WHITE_PIECE_COLOR; +char *black_square_color = BLACK_SQUARE_COLOR; +char *white_square_color = WHITE_SQUARE_COLOR; +char *border_color = BORDER_COLOR; +char *text_color = TEXT_COLOR; +char *text_back = TEXT_BACK; +char *error_text = ERROR_TEXT; +char *player_text = PLAYER_TEXT; +char *cursor_color = CURSOR_COLOR; + +int num_flashes = NUM_FLASHES; +int flash_size = FLASH_SIZE; +char *program; +char *recfile = NULL; + +die () { +fprintf(stderr, "child proc changed status?!\n"); +} + +void +main(ac, av) + char **av; +{ + bool randflag = false; + move *m; + char *s; + + program = av[0]; + + signal(SIGCHLD, die); + /* Process args. */ + av++; ac--; + while (ac > 0 && **av == '-') { + if (eq(*av, "-d")) { + debug = true; + } else if (eq(*av, "-f")) { + av++; ac--; + if (*av) + record_file = *av; + else + goto usage; + } else if (eq(*av, "-r")) { + av++; ac--; + if (*av) + recfile = *av; + else + goto usage; + } else if (eq(*av, "-i")) { + record_english = false; + } else if (eq(*av, "-R")) { + randflag = true; + } else if (eq(*av, "-v")) { + win_flashmove = true; + } else if (eq(*av, "-q")) { + quickflag = true; + } else if (eq(*av, "-t")) { + av++; ac--; + if (*av) { + movesperunit = atoi(*av); + if (s = index(*av, '/')) + timeunit = atoi(s + 1) * 60; + else + timeunit = 60; + } else + goto usage; + } else if (eq(*av, "-p")) { + av++; ac--; + if (*av) + progname = *av; + else + goto usage; + } else if (eq(*av, "-h")) { + av++; ac--; + if (*av) + proghost = *av; + else + goto usage; + } else if (eq(*av, "-b")) { + blackflag = true; + } else if (eq(*av, "-c")) { + progflag = true; + } else if (eq(*av, "-bnw")) { + bnwflag = true; + } else if (eq(*av, "-s")) { + saveflag = true; + } else if (eq(*av, "-n")) { + noisyflag = true; + } else + goto usage; + av++; ac--; + } + if (ac > 0) + dispname1 = av[0]; + if (ac > 1) + dispname2 = av[1]; + if (ac > 2) + goto usage; + + if (!dispname2) + oneboard = true; + + srandom(getpid()); + + if (!oneboard && randflag && (random() % 2)) { + s = dispname1; + dispname1 = dispname2; + dispname2 = s; + } + + if (!dispname1) + dispname1 = getenv("DISPLAY"); + + /* Set up the board. */ + board_setup(); + + /* Create the windows. */ + win_setup(dispname1, dispname2); + + board_drawall(); + + /* Start the program if necessary. */ + if (progflag) + if (!program_init(progname)) + exit(1); + + if (recfile) + load_game(recfile); + + /* Go into a loop of prompting players alternately for moves, checking + * them, and updating things. + */ + for (;;) { + win_process(false); + clock_update(); + if (progflag && ((!blackflag && (nexttomove == BLACK)) || + (blackflag && (nexttomove == WHITE)))) { + m = program_get(); + if (m) + prog_move(m); + } + } + +usage: fprintf(stderr, "Usage: %s\n", USAGE); + exit(1); +} + diff --git a/gnu/games/chess/Xchess/xchess.cur b/gnu/games/chess/Xchess/xchess.cur new file mode 100644 index 000000000000..ef3750dbdd7f --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.cur @@ -0,0 +1,9 @@ + +#define xchess_width 16 +#define xchess_height 16 +#define xchess_x_hot 9 +#define xchess_y_hot 8 +static char xchess_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0xff, + 0xc0, 0xff, 0x60, 0xff, 0xb0, 0xfd, 0xd8, 0x66, 0x6c, 0x3b, 0x76, 0x1d, + 0x98, 0x1d, 0xcc, 0x0c, 0x60, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/Xchess/xchess.game b/gnu/games/chess/Xchess/xchess.game new file mode 100644 index 000000000000..2302334080c7 --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.game @@ -0,0 +1,8 @@ + +X Chess -- Sun Sep 18 18:01:17 EDT 1988 + Game played on pitcairn:0 + english + 1. P/kb2-kb4 P/k2-k3 + 2. P/k2-k4 +Draw agreed. +Time: white: 6s, black: 43s diff --git a/gnu/games/chess/Xchess/xchess.h b/gnu/games/chess/Xchess/xchess.h new file mode 100644 index 000000000000..355731d8b403 --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.h @@ -0,0 +1,301 @@ + +/* This file contains code for X-CHESS. + Copyright (C) 1986 Free Software Foundation, Inc. + +This file is part of X-CHESS. + +X-CHESS is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY. No author or distributor +accepts responsibility to anyone for the consequences of using it +or for whether it serves any particular purpose or works at all, +unless he says so in writing. Refer to the X-CHESS General Public +License for full details. + +Everyone is granted permission to copy, modify and redistribute +X-CHESS, but only under the conditions described in the +X-CHESS General Public License. A copy of this license is +supposed to have been given to you along with X-CHESS so you +can know your rights and responsibilities. It should be in a +file named COPYING. Among other things, the copyright notice +and this notice must be preserved on all copies. */ + + +/* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:39 $ + * $Source: /users/faustus/xchess/RCS/xchess.h,v $ + * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group + * Permission is granted to do anything with this code except sell it + * or remove this message. + * + * Definitions for the X chess program. + */ + +#include "std.h" +#include +#include "scrollText/scrollText.h" + +#define SIZE 8 + +typedef enum piecetype { PAWN, ROOK, KNIGHT, BISHOP, QUEEN, KING } piecetype; +typedef enum movetype { MOVE, QCASTLE, KCASTLE, CAPTURE } movetype; +typedef enum color { WHITE, BLACK, NONE } color; + +typedef struct piece { + enum piecetype type; + enum color color; +} piece; + +/* The board has y=0 and black at the top... This probably isn't the best + * place to keep track of who can castle, but it's part of the game state... + */ + +typedef struct board { + piece square[SIZE][SIZE]; + bool white_cant_castle_k; + bool white_cant_castle_q; + bool black_cant_castle_k; + bool black_cant_castle_q; +} board; + +typedef struct move { + movetype type; + piece piece; + piece taken; + int fromx, fromy; + int tox, toy; + struct move *next; + bool enpassant; + bool check; +} move; + +#define iswhite(win, i, j) (!(((i) + (j)) % 2)) + +/* Stuff for the display. */ + +typedef struct windata { + Display *display; + Window basewin; + Window boardwin; + Window recwin; + Window wclockwin; + Window bclockwin; + Window messagewin; + Window buttonwin; + Window jailwin; + Window icon; + Pixmap iconpixmap; + XColor blackpiece; + XColor whitepiece; + XColor blacksquare; + XColor whitesquare; + XColor border; + XColor textcolor; + XColor textback; + XColor errortext; + XColor playertext; + XColor cursorcolor; + XFontStruct *small; + XFontStruct *medium; + XFontStruct *large; + bool bnw; + color color; + bool flipped; + double whitehands[3]; + double blackhands[3]; + char *txtassoc; +} windata; + +#define SMALL_FONT "6x10" +#define MEDIUM_FONT "8x13" +#define LARGE_FONT "9x15" +#define JAIL_FONT "6x10" + +#define SQUARE_WIDTH 80 +#define SQUARE_HEIGHT 80 + +#define BORDER_WIDTH 3 + +#define BOARD_WIDTH 8 * SQUARE_WIDTH + 7 * BORDER_WIDTH +#define BOARD_HEIGHT 8 * SQUARE_HEIGHT + 7 * BORDER_WIDTH +#define BOARD_XPOS 0 +#define BOARD_YPOS 0 + +#define RECORD_WIDTH 265 /* 40 chars * 6 pixels / character. */ +#define RECORD_HEIGHT 433 +#define RECORD_XPOS BOARD_WIDTH + BORDER_WIDTH +#define RECORD_YPOS 0 + +#define JAIL_WIDTH RECORD_WIDTH +#define JAIL_HEIGHT 163 +#define JAIL_XPOS RECORD_XPOS +#define JAIL_YPOS RECORD_YPOS + RECORD_HEIGHT + BORDER_WIDTH + +#define CLOCK_WIDTH 131 +#define CLOCK_HEIGHT 131 + BORDER_WIDTH + 20 +#define WCLOCK_XPOS RECORD_XPOS +#define WCLOCK_YPOS RECORD_HEIGHT + JAIL_HEIGHT + BORDER_WIDTH * 2 +#define BCLOCK_XPOS WCLOCK_XPOS + CLOCK_WIDTH + BORDER_WIDTH +#define BCLOCK_YPOS WCLOCK_YPOS + +#define MESS_WIDTH 329 +#define MESS_HEIGHT 92 +#define MESS_XPOS 0 +#define MESS_YPOS BOARD_HEIGHT + BORDER_WIDTH + +#define BUTTON_WIDTH MESS_WIDTH +#define BUTTON_HEIGHT MESS_HEIGHT +#define BUTTON_XPOS MESS_WIDTH + BORDER_WIDTH +#define BUTTON_YPOS MESS_YPOS + +#define BASE_WIDTH BOARD_WIDTH + RECORD_WIDTH + BORDER_WIDTH * 3 +#define BASE_HEIGHT BOARD_HEIGHT + MESS_HEIGHT + BORDER_WIDTH * 3 + +#define BASE_XPOS 50 +#define BASE_YPOS 50 + +#define BLACK_PIECE_COLOR "#202020" +#define WHITE_PIECE_COLOR "#FFFFCC" +#define BLACK_SQUARE_COLOR "#77A26D" +#define WHITE_SQUARE_COLOR "#C8C365" +#define BORDER_COLOR "#902E39" +#define TEXT_COLOR "#006D6D" +#define TEXT_BACK "#FFFFDD" +#define ERROR_TEXT "Red" +#define PLAYER_TEXT "Blue" +#define CURSOR_COLOR "#FF606F" + +#define DEF_RECORD_FILE "xchess.game" + +#define NUM_FLASHES 5 +#define FLASH_SIZE 10 + +/* xchess.c */ + +extern void main(); +extern bool debug; +extern char *progname; +extern char *proghost; +extern char *piecenames[]; +extern char *colornames[]; +extern char *movetypenames[]; +extern char *dispname1, *dispname2; +extern bool oneboard; +extern bool bnwflag; +extern bool progflag; +extern bool blackflag; +extern bool quickflag; +extern int num_flashes; +extern int flash_size; +extern char *black_piece_color; +extern char *white_piece_color; +extern char *black_square_color; +extern char *white_square_color; +extern char *border_color; +extern char *text_color; +extern char *text_back; +extern char *error_text; +extern char *player_text; +extern char *cursor_color; + +/* board.c */ + +extern void board_setup(); +extern void board_drawall(); +extern void board_move(); +extern board *chessboard; +extern void board_init(); + +/* window.c */ + +extern bool win_setup(); +extern void win_redraw(); +extern void win_restart(); +extern void win_drawboard(); +extern void win_drawpiece(); +extern void win_erasepiece(); +extern void win_process(); +extern void win_flash(); +extern windata *win1, *win2; +extern bool win_flashmove; + +/* control.c */ + +extern void button_pressed(); +extern void button_released(); +extern void move_piece(); +extern void prog_move(); +extern move *moves; +extern move *foremoves; +extern color nexttomove; +extern void replay(); +extern void forward(); +extern void cleanup(); +extern void restart(); +extern bool noisyflag; + +/* valid.c */ + +extern bool valid_move(); + +/* record.c */ + +extern void record_move(); +extern void record_reset(); +extern void record_save(); +extern void record_back(); +extern void record_init(); +extern void record_end(); +extern bool record_english; +extern char *record_file; +extern int movenum; +extern bool saveflag; + +/* message.c */ + +extern void message_init(); +extern void message_add(); +extern void message_send(); + +/* clock.c */ + +extern void clock_init(); +extern void clock_draw(); +extern void clock_update(); +extern void clock_switch(); +extern bool clock_started; +extern int movesperunit; +extern int timeunit; +extern int whiteseconds; +extern int blackseconds; + +/* button.c */ + +extern void button_draw(); +extern void button_service(); + +/* jail.c */ + +extern void jail_init(); +extern void jail_draw(); +extern void jail_add(); +extern void jail_remove(); + +/* program.c */ +extern bool program_init(); +extern void program_end(); +extern void program_send(); +extern void program_undo(); +extern move *program_get(); + +/* parse.c */ + +extern void load_game(); +extern move *parse_file(); +extern move *parse_move(); +extern move *parse_imove(); +extern bool loading_flag; +extern bool loading_paused; + +/* popup.c */ + +extern bool pop_question(); + diff --git a/gnu/games/chess/Xchess/xchess.icon b/gnu/games/chess/Xchess/xchess.icon new file mode 100644 index 000000000000..78c68f1ba46b --- /dev/null +++ b/gnu/games/chess/Xchess/xchess.icon @@ -0,0 +1,28 @@ + +#define icon_width 48 +#define icon_height 48 +static char icon_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xc1, 0xff, 0xff, 0xff, 0xff, 0x83, 0x41, 0x00, 0x00, 0x00, 0x00, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, 0x41, 0xf0, 0xf0, 0xf0, 0xf0, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, 0x41, 0x0f, 0x0f, 0x0f, 0x0f, 0x82, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x82, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x83, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0xc4, 0x89, 0x3c, 0xcf, 0x83, + 0x41, 0x24, 0x88, 0x04, 0x41, 0x80, 0x81, 0x22, 0x88, 0x04, 0x41, 0x80, + 0x01, 0x21, 0xf8, 0x1c, 0xcf, 0x83, 0x81, 0x22, 0x88, 0x04, 0x08, 0x82, + 0x41, 0x24, 0x88, 0x04, 0x08, 0x82, 0x41, 0xc4, 0x89, 0x3c, 0xcf, 0x83, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; diff --git a/gnu/games/chess/Xchess/xchess_mask.cur b/gnu/games/chess/Xchess/xchess_mask.cur new file mode 100644 index 000000000000..6408b7e0b915 --- /dev/null +++ b/gnu/games/chess/Xchess/xchess_mask.cur @@ -0,0 +1,7 @@ + +#define xchess_mask_width 16 +#define xchess_mask_height 16 +static char xchess_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xf8, 0x00, 0xfe, 0x80, 0xff, + 0xc0, 0xff, 0x60, 0xff, 0xb0, 0xfd, 0xd8, 0x66, 0x6c, 0x3b, 0x76, 0x1d, + 0x98, 0x1d, 0xcc, 0x0c, 0x60, 0x00, 0x00, 0x00}; diff --git a/gnu/games/chess/gnuchess.book b/gnu/games/chess/gnuchess.book new file mode 100644 index 000000000000..7e8a3b5d756e --- /dev/null +++ b/gnu/games/chess/gnuchess.book @@ -0,0 +1,3878 @@ +! +! Opening Library for CHESS +! +! Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. +! Copyright (c) 1987 by Stuart Cracraft and John Stanback +! +! This file is part of CHESS. +! +! CHESS is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY. No author or distributor +! accepts responsibility to anyone for the consequences of using it +! or for whether it serves any particular purpose or works at all, +! unless he says so in writing. Refer to the CHESS General Public +! License for full details. +! +! Everyone is granted permission to copy, modify and redistribute +! CHESS, but only under the conditions described in the +! CHESS General Public License. A copy of this license is +! supposed to have been given to you along with CHESS so you +! can know your rights and responsibilities. It should be in a +! file named COPYING. Among other things, the copyright notice +! and this notice must be preserved on all copies. +! +! +! +! Four Knight's Game +e2e4 e7e5 +g1f3 b8c6 +b1c3 g8f6 +f1b5 f8b4 +o-o o-o +d2d3 b4c3 +b2c3 d7d6 +c1g5 d8e7 +f1e1 c6d8 +d3d4 d8e6 +! Giuoco Piano +e2e4 e7e5 +g1f3 b8c6 +f1c4 f8c5 +d2d3 g8f6 +b1c3 d7d6 +c1g5 h7h6 +g5f6 d8f6 +c3d5 f6d8 +! Two Knights Defence +e2e4 e7e5 +g1f3 b8c6 +f1c4 g8f6 +f3g5 d7d5 +e4d5 c6a5 +c4b5 c7c6 +d5c6 b7c6 +b5e2 h7h6 +! Two Knights Defence -- Max Lange Attack +e2e4 e7e5 +g1f3 b8c6 +f1c4 g8f6 +d2d4 e5d4 +o-o f8c5 +e4e5 d7d5 +e5f6 d5c4 +f6g7 h8g8 +! Petrov's Defence +e2e4 e7e5 +g1f3 g8f6 +f3e5 d7d6 +e5f3 f6e4 +d2d4 d6d5 +f1d3 f8d6 +o-o o-o +c2c4 c8g4 +c4d5 f7f5 +b1c3 b8d7 +! Petrov's Defence +e2e4 e7e5 +g1f3 g8f6 +d2d4 e5d4 +e4e5 f6e4 +d1d4 d7d5 +! +! Vienna Game +e2e4 e7e5 +b1c3 f8c5 +g1f3 d7d6 +d2d4 e5d4 +f3d4 g8f6 +c1g5 h7h6 +g5h4 b1c3 +! +e2e4 e7e5 +b1c3 b8c6 +g1f3 g7g6 +d2d4 e5d4 +c3d5 f8g7 +c1g5 c6e7 +f3d4 c7c6 +d5c3 h7h6 +! - - - - - - +! ECO C25/1-2 +e2e4 e7e5 +b1c3 f8c5 +f1c4 d7d6 +d2d3 c8e6 +c4e6 f7f6 +d1h5 e7d7 +c1e3 c5b6 +g1e2 b8c6 +o-o g8f6 +h5h3 d8e8 +! +e2e4 e7e5 +b1c3 f8c5 +g1f3 d7d6 +d2d4 e5d4 +f3d4 g8f6 +c1g5 h7h6 +g5h4 b8c6 +d4c6 b7c6 +f1d3 e8e7 +o-o g7g5 +! ECO C25/3-9 +e2e4 e7e5 +b1c3 b8c6 +f2f4 e5f4 +g1f3 g7g5 +h2h4 g5g4 +f3g5 h7h6 +g5f7 e7f7 +d2d4 d7d5 +c1f4 f8b4 +f1e2 b4c3 +b2c3 g8f6 +! +e2e4 e7e5 +b1c3 b8c6 +f2f4 e5f4 +g1f3 g7g5 +d2d4 g5g4 +f1c4 g4f3 +o-o d7d5 +e4d5 c8g4 +d1d2 c6e7 +d2f4 g8h6 +! +e2e4 e7e5 +b1c3 b8c6 +f2f4 e5f4 +d2d4 d8h4 +e1e2 d7d5 +e4d5 c8g4 +g1f3 o-o-o +d5c6 f8c5 +d1e1 h4h5 +c6b7 e8b8 +e2d2 g4f3 +! +e2e4 e7e5 +b1c3 b8c6 +f2f4 e5f4 +d2d4 d8h4 +e1e2 d7d6 +g1f3 c8g4 +c1f4 o-o-o +e2e3 h4h5 +f1e2 g7g5 +f3g5 f7f5 +h2h3 g4e2 +! +e2e4 e7e5 +b1c3 b8c6 +g2g3 f8c5 +f1g2 a7a6 +g1e2 d7d6 +d1d3 c8g4 +h2h3 g4e6 +o-o g8e7 +c3d5 o-o +c2c3 c5a7 +g1h2 f7f6 +! +e2e4 e7e5 +b1c3 b8c6 +g2g3 f8c5 +f1g2 d7d6 +c3a4 g8e7 +a4c5 d6c5 +d2d3 o-o +g2e3 b7b6 +d1d2 c8e6 +g1e2 d8d7 +o-o a8d8 +! +e2e4 e7e5 +b1c3 b8c6 +f1c4 f8c5 +d1g4 g7g6 +d4f3 g8f6 +g1e2 d7d6 +d2d3 c8g4 +f3g3 h7h6 +f2f4 d7e7 +c3d5 f6d5 +g3g4 d5e3 +! ECO C26/1-10 +e2e4 e7e5 +b1c3 g8f6 +g2g3 c7c6 +f1g2 d7d6 +g1e2 b7b5 +o-o b8d7 +h2h3 d8c7 +g3g4 b5b4 +c3b1 a7a5 +a2a3 c8a6 +a3b4 a5b4 +! +e2e4 e7e5 +b1c3 g8f6 +g2g3 d7d5 +e4d5 f6d5 +f1g2 c8e6 +g1f3 b8c6 +o-o f8e7 +f1e1 e7f6 +c3e4 o-o +d2d3 f6e7 +a2a3 d5b6 +! +e2e4 e7e5 +b1c3 g8f6 +g2g3 d7d5 +e4d5 f6d5 +f1g2 d5c3 +b2c3 f8d6 +g1f3 o-o +o-o b8d7 +d2d3 a1b8 +a2a4 b7b6 +a4a5 c8b7 +! +e2e4 e7e5 +b1c3 g8f6 +g2g3 f8b4 +f1g2 c7c6 +g1e2 o-o +o-o d7d5 +e4d5 c6d5 +d2d4 e5d4 +e2d4 b8c6 +c1g5 b4e7 +f1e1 h7h6 +! +e2e4 e7e5 +b1c3 g8f6 +g2g3 f8c5 +f1g2 b8c6 +g1e2 d7d6 +o-o o-o +d2d3 c8e6 +c3d5 e6d5 +e4d5 c6e7 +c1g5 f6d7 +d3d4 e5d4 +! +e2e4 e7e5 +b1c3 g8f6 +g2g3 f8c5 +f1g2 b8c6 +g1f3 d7d6 +d2d3 a7a6 +o-o o-o +c1g5 h7h6 +g5e3 c5e3 +f2e3 d6d5 +e4d5 f6d5 +! +e2e4 e7e5 +b1c3 g8f6 +g2g3 f8c5 +f1g2 o-o +d2d3 f8e8 +g1e2 c7c6 +o-o d7d5 +e5d5 f6d5 +g1h1 c8g4 +h2h3 g4e6 +c3e4 c5e7 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f8b4 +g1e2 o-o +d2d3 c7c6 +o-o d7d5 +c4b3 d5e4 +c3e4 b8d7 +e2g3 f6e4 +d3e4 d7c5 +d1h5 c5b3 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f8c5 +d2d3 d7d6 +c1g5 c8e6 +d1d2 b8d7 +g1e2 e6c4 +d3c4 h7h6 +g5e3 d8e7 +e2g3 c5e3 +f2e3 g7g6 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f8c5 +d2d3 d7d6 +f2f4 b8c6 +f4f5 b6d4 +g1f3 c7c6 +f3d4 c5d4 +d1f3 b7b5 +c4b3 a7a5 +a2a3 a5a4 +! ECO C27/1-2 +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +h5e5 d8e7 +e5e7 f8e7 +c4b3 d6f5 +c3d5 e7d8 +d5e3 f5d4 +b3c4 c7c6 +g1e2 d4e2 +c4e2 d7d5 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +c4b3 b8c6 +c3b5 g7g6 +h5f3 f7f6 +b5c7 d8c7 +f3f6 b7b6 +g1f3 c8a6 +f3e5 c6e5 +f6e5 e8d8 +! ECO C27/3-5 +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +c4b3 b8c6 +c3b5 g7g6 +h5f3 f7f5 +f3d5 d8e7 +b5c7 e8d8 +c7a8 b7b6 +d2d3 c8b7 +h2h4 f5f4 +d5f3 f8h6 +b3d5 b7a8 +f3g4 h8f8 +g1e2 e5e4 +c1f4 h6f4 +e2f4 e7e5 +g4g5 e5g5 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +c4b3 b8c6 +c3b5 g7g6 +h5f3 f7f5 +f3d5 d8e7 +b5c7 e8d8 +c7a8 b7b6 +g1f3 c8b7 +d3d4 c6d4 +c1g5 d4f3 +d5f3 e7g5 +b3d5 e5e4 +f3b3 b7a6 +b3a4 f8h6 +a4d4 h8e8 +g2g3 g5g4 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +c4b3 b8c6 +c3b5 g7g6 +h5f3 f7f5 +f3d5 d8e7 +b5c7 e8d8 +c7a8 b7b6 +a8b6 a7b6 +d5f3 c8b7 +d2d3 c6d4 +f3h3 e5e4 +c1e3 e4d3 +o-o-o d4c2 +e3b6 d8e8 +h3d3 f8h6 +c1b1 b7e4 +! ECO C27/6-7 +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +c4b3 f8e7 +g1f3 b8c6 +f3e5 o-o +o-o c6d4 +c3d5 d4b3 +a2b3 d6e8 +h5e2 e8f6 +e5c6 d7c6 +d5e7 g8h8 +e7c8 d8c8 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 f6e4 +d1h5 e4d6 +c4b3 f8e7 +g1f3 o-o +h2h4 b8c6 +f3g5 h7h6 +h5g6 e7g5 +h4g5 d8g5 +d2d3 d6f5 +c1g5 c6d4 +c3d5 d4b3 +! ECO C28/1-7 +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +f2f3 f6e4 +g1f3 e4c3 +d2c3 d8e7 +b2b4 d7d6 +o-o c8e6 +c4e6 e7e6 +b4b5 c6d8 +f4e5 d6e5 +f3e5 f8d6 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +d2d3 c6a5 +g1e2 a5c4 +d3c4 d7d6 +o-o c8e6 +b2b3 c7c6 +e2g3 g7g6 +h2h3 h7h5 +d1d3 f8e7 +c1e3 d8d7 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +d2d3 f8c5 +c1g5 h7h6 +g5h4 d7d6 +c3a4 c8e6 +a4c5 d6c5 +b2b3 e6c4 +b3c4 d8d6 +g1e2 c6d4 +h4f6 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +d2d3 f8b4 +g1e2 d7d5 +e4d5 f6d5 +c4d5 d8d5 +o-o d5d8 +f2f4 e5f4 +c1f4 o-o +d1e1 b4d6 +e1g3 b6f4 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +d2d3 f8b4 +c1g5 d7d6 +g1e2 c8e6 +o-o h7h6 +g5f6 d8f6 +c3d5 e6d5 +c4d5 b4c5 +c2c3 o-o +g1h1 c6e7 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +d2d3 f8b4 +c1g5 h7h6 +g5f6 b4c3 +b2c3 d8f6 +g1e2 d7d6 +d1d2 c1e6 +c4b5 f6g5 +e2g3 o-o +b5c6 b7c6 +! +e2e4 e7e5 +b1c3 g8f6 +f1c4 b8c6 +d2d3 f8b4 +g1f3 d7d6 +o-o b4c3 +b2c3 c6a5 +c4b3 a5b3 +a2b3 o-o +c3c4 b7b6 +d1e2 f6d7 +c1g5 f7f6 +! ECO C29/1 +e2e4 e7e5 +b1c3 g8f6 +f1f4 d7d5 +d2d3 e5f4 +e4d5 f6d5 +c3d5 d8d5 +c1f4 f8d6 +f4d6 d5d6 +d1d2 o-o +g1f3 c8g4 +f1e2 g4f3 +! ECO C29/2-12 +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +d1f3 b8c6 +f1b5 e4c3 +b2c3 f8e7 +d2d4 o-o +b5d3 f7f6 +f3h5 g7g6 +d3g6 h7g6 +h5g6 g8h8 +g6h6 h8g8 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +d1f3 f7f5 +d2d3 e4c3 +b2c3 d5d4 +f3g3 b8c6 +f1e2 c8e6 +e2f3 d8d7 +g1e2 f8c5 +c3c4 o-o +o-o e6c4 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +d2d3 d8h4 +g2g3 e4g3 +g1f3 h4h5 +c3d5 c8g4 +f1g2 g3h1 +d5c7 e8d7 +c7h8 b8c6 +c1e3 f7f6 +d3d4 f6e5 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +d2d3 f1b4 +d3e4 d8h4 +e1e2 b8c6 +g1f3 c8g4 +c3d5 o-o-o +c2c3 f7f5 +e5f6 h8e8 +c3b4 e8e4 +c1e3 g7f6 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +d2d3 e4c3 +b2c3 d5d4 +g1f3 b8c6 +c3d4 f8b4 +c1d2 b4d2 +d1d2 c6d4 +c2c3 d4f3 +g2f3 d8h4 +d2f2 h4f2 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +g1f3 f1b4 +d1e2 b4c3 +b2c3 o-o +e2e3 b8c6 +f1d3 f7f5 +o-o c8e6 +c1a3 f8e8 +a1b1 a8b8 +a3b5 e6d7 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +g1f3 b8c6 +f1b5 f8c5 +d2d4 c5b4 +c1d2 b4c3 +b2c3 o-o +o-o c1g4 +d1e1 f7f6 +d2e3 g4d7 +e5f6 d8f6 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +g1f3 f8c5 +d1e2 c5f2 +e1d1 e4c3 +d2c3 f2b6 +c3g5 d8d7 +d1d2 o-o +a1d1 d7a4 +a2a3 c7c5 +d2c1 c8e6 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +g1f3 c8g4 +d1e2 e4g5 +h2h4 g5f3 +g2f3 g4e6 +d2d4 b8c6 +c1e3 f8e7 +e2f2 d8d7 +o-o-o o-o-o +f1b5 a7a6 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +g1f3 f8e7 +d1e2 e4c3 +d2c3 o-o +c1f4 c7c5 +o-o-o d8a5 +c1b1 b8c6 +a4b5 c8e6 +b5a5 f3g5 +! +e2e4 e7e5 +b1c3 g8f6 +f2f4 d7d5 +f4e5 f6e4 +g1f3 f8e7 +d2d4 o-o +f1d3 f7f6 +e5f6 e7f6 +o-o b8c6 +c3e4 d5e4 +d3e4 c6d4 +f3g5 c8f5 +c2c3 f7g5 +! +! Vienna Game +e2e4 e7e5 +b1c3 f8c5 +g1f3 d7d6 +d2d4 e5d4 +f3d4 g8f6 +c1g5 h7h6 +g5h4 b1c3 +! Three Knights Game +e2e4 e7e5 +b1c3 b8c6 +g1f3 g7g6 +d2d4 e5d4 +c3d5 f8g7 +c1g5 c6e7 +f3d4 c7c6 +d5c3 h7h6 +! Bishop's Opening +e2e4 e7e5 +f1c4 g8f6 +d2d4 e5d4 +g1f3 f6e4 +d1d4 e4c5 +o-o c5e6 +f1e1 c7c6 +b1c3 d7d5 +c4d3 f8e7 +! Ruy Lopez -- Classical Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 f8c5 +c2c3 g8f6 +d2d4 e5d4 +e4e5 f6e4 +o-o d7d5 +! Ruy Lopez -- Birds Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 c6d4 +b5a4 f8c5 +o-o d4f3 +d1f3 g8e7 +d2d3 o-o +c1e3 c5b6 +b1c3 d7d6 +! Ruy Lopez -- Schliemann Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 f7f5 +b1c3 f5e4 +c3e4 d7d5 +f3e5 d5e4 +e5c6 d8d5 +c2c4 d5d6 +c6a7 c8d7 +! Ruy Lopez -- Old Steinitz Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 d7d6 +d2d4 c8d7 +b1c3 g8f6 +o-o f8e7 +f1e1 e5d4 +f3d4 o-o +d4f5 f8e8 +! Ruy Lopez -- Old Steinitz Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 d7d6 +d2d4 c8d7 +b1c3 g8f6 +b5c6 d7c6 +d1d3 e5d4 +f3d4 f8e7 +c1g5 c6d7 +! Ruy Lopez -- Modern Steinitz Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 a7a6 +b5a4 d7d6 +d2d4 b7b5 +a4b3 c6d4 +f3d4 e5d4 +c2c3 d4c3 +b1c3 c8b7 +! Ruy Lopez -- Open Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 a7a6 +b5a4 g8f6 +o-o f6e4 +d2d4 b7b5 +a4b3 d7d5 +d4e5 c8e6 +c2c3 f8c5 +b1d2 o-o +! Ruy Lopez -- Open Defence +e2e4 e7e5 +g1f3 b8c6 +f1b5 a7a6 +b5a4 g8f6 +o-o f8e7 +f1e1 b7b5 +a4b3 d7d6 +c2c3 o-o +h2h3 c6a5 +b3c2 c2c4 +d2d4 d8c7 +! Ruy Lopez +e2e4 e7e5 +g1f3 b8c6 +f1b5 a7a6 +b5c6 d7c6 +d2d4 e5d4 +d1d4 d8d4 +f3d4 c8d7 +c1e3 o-o-o +b1d2 g8e7 +! Scotch Game +e2e4 e7e5 +g1f3 b8c6 +d2d4 e5d4 +f3d4 f8c5 +c1e3 d8f6 +c2c3 g8e7 +b1d2 d7d6 +e3c5 d6c5 +! Philidor's Defence +e2e4 e7e5 +g1f3 d7d6 +d2d4 g8f6 +b8c6 b1d2 +f8c5 f1e2 +o-o o-o +d1e2 c7c6 +! Alekhine's Defence +e2e4 g8f6 +e4e5 f6d5 +c2c4 d5b6 +d2d4 d7d6 +f2f4 d6e5 +f4e5 b8c6 +c1e3 c8f5 +b1c3 e7e6 +g1f3 f8e7 +! Alekhine's Defence +e2e4 g8f6 +e4e5 f6d5 +d2d4 d7d6 +g1f3 c8g4 +f1e2 e7e6 +o-o f8e7 +h2h3 g4h5 +c2c4 d5b6 +! Kings Gambit Accepted +e2e4 e7e5 +f2f4 e5f4 +g1f3 d7d6 +f1c4 h7h6 +d2d4 g7g5 +o-o f8g7 +c2c3 b8c6 +d1b3 d8e7 +! Ponziani's Opening +e2e4 e7e5 +g1f3 b8c6 +c2c3 d7d5 +d1a4 g8f6 +f3e5 f8d6 +e5c6 b7c6 +d2d3 o-o +c1g5 h7h6 +! Caro-Kann Defence +e2e4 c7c6 +d2d4 d7d5 +e4d5 c6d5 +c2c4 g8f6 +b1c3 b8c6 +c1g5 e7e6 +c4c5 f8e7 +f1b5 o-o +g1f3 f6e4 +! Caro-Kann Defence +e2e4 c7c6 +d2d4 d7d5 +e4e5 c8f5 +f1d3 f5d3 +d1d3 e7e6 +b1c3 d8b6 +b1d2 c6c5 +d4c5 f8c5 +! Caro-Kann Defence +e2e4 c7c6 +b1c3 d7d5 +g1f3 c8g4 +h2h3 g4f3 +d1f3 e7e6 +d2d4 g8f6 +f1d3 d5e4 +c3e4 d8d4 +c2c3 d4d8 +! French Defence -- Classical +e2e4 e7e6 +d2d4 d7d5 +b1c3 g8f6 +c1g5 f8e7 +e4e5 f6d7 +g5e7 d8e7 +d1d2 o-o +f2f4 c7c5 +g1f3 b8c6 +o-o-o c5c4 +! French Defence -- MacCutcheon +e2e4 e7e6 +d2d4 d7d5 +b1c3 g8f6 +c1g5 c8g4 +e4e5 h7h6 +g5d2 g4f3 +g2f3 f6e4 +d1g4 e8f8 +h2h4 c7c5 +! French Defence -- Rubenstein +e2e4 e7e6 +d2d4 d7d5 +b1c3 d5e4 +c3e4 b8d7 +g1f3 g8f6 +e4f6 d7f6 +f1d3 b7b6 +d1e2 c8b7 +c1g5 f8e7 +! French Defence -- Winawer +e2e4 e7e6 +d2d4 d7d5 +b1c3 f8b4 +e4e5 c7c5 +a2a3 b4c3 +b2c3 b8d7 +d1g4 o-o +g1f3 b8c6 +f1e3 f7f5 +! French Defence -- Tarrasch +e2e4 e7e6 +d2d4 d7d5 +b1d2 b8c6 +g1f3 g8f6 +e4e5 f6d7 +d2b3 f7f6 +f1b5 f8e7 +c1f4 o-o +! Sicilian Defence -- Dragon Variation +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1e2 g7g6 +c1e3 f8g7 +o-o o-o +d4b3 c8e6 +f2f4 c6a5 +f4f5 e6c4 +! Sicilian Defence -- Dragon Variation +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g7g6 +b1c3 f8g7 +c1e3 g8f6 +f1c4 o-o +! Sicilian Defence -- Boleslavsky Variation +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1e2 e7e5 +d4b3 f8e7 +o-o o-o +c1e3 c8e6 +! Sicilian Defence -- Najdorf +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o o-o +! Sicilian Defence -- Najdorf +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +f1e2 e7e5 +d4b3 f8e7 +o-o o-o +f2f4 b7b5 +a2a3 c8b7 +! Sicilian Defence -- Najdorf +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +g2g3 e7e5 +d4e2 c8e6 +f1g2 b7b5 +o-o b8d7 +! Sicilian Defence -- Closed +e2e4 c7c5 +b1c3 b8c6 +g2g3 g7g6 +f1g2 f8g7 +d2d3 e7e6 +c1e3 d7d6 +g1e2 c6d4 +d1d2 d8h4 +o-o g8d7 +! Nimzowitsch Defence +e2e4 b8c6 +d2d4 d7d5 +e4e5 f7f6 +g1f3 c1g4 +f1e2 e7e6 +e5f6 g8f6 +c2c3 f8d6 +c1g5 d8d7 +! Queens Gambit Accepted +d2d4 d7d5 +c2c4 d5c4 +g1f3 g8f6 +e2e3 e7e6 +f1c4 c7c5 +o-o a7a6 +d1e2 b7b5 +c4d3 c5d4 +e3d4 b8c6 +! Queens Gambit -- Catalan +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o f6d7 +d1c2 c7c6 +b1d2 b7b6 +e2e4 c8b7 +b2b3 a8c8 +! Queens Gambit Declined -- Orthodox +d2d4 d7d5 +c2c4 e7e6 +b1c3 g8f6 +c1g5 f8e7 +e2e3 o-o +g1f3 b8d7 +a1c1 c7c6 +f8d3 d5c4 +f1c4 f6d5 +! Queens Gambit Declined -- Cambridge Springs +d2d4 d7d5 +c2c4 e7e6 +b1c3 g8f6 +c1g5 b8d7 +e2e3 c7c6 +g1f3 d8a5 +f3d2 f8b4 +d1c2 o-o +g5h4 c6c5 +! Queens Gambit Declined -- Exchange Var. +d2d4 d7d5 +c2c4 e7e6 +b1c3 g8f6 +c1g5 b8d7 +c4d5 e6d5 +e2e3 c7c6 +f1d3 f8e7 +d1c2 o-o +g1e2 f8e8 +! Queens Gambit Declined -- Semi-Tarrasch +d2d4 d7d5 +c2c4 e7e6 +b1c3 g8f6 +g1f3 c7c5 +c4d5 c5d4 +d1d4 e6d5 +e2e4 b8c6 +f1b5 f6e4 +! Queens Gambit Declined -- Tarrasch +d2d4 d7d5 +c2c4 e7e6 +b1c3 c7c5 +c4d5 e6d5 +g1f3 b8c6 +g2g3 g8f6 +f1g2 f8e7 +o-o o-o +! Queens Gambit Declined -- Vienna +d2d4 d7d5 +c2c4 e7e6 +g1f3 g8f6 +f1b5 f8b4 +b1c3 d5c4 +e2e4 c7c5 +e4e5 c5d4 +d1a4 b8c6 +o-o-o c1d2 +! Queens Gambit Declined -- Slav (Marshall Gambit) +d2d4 d7d5 +c2c4 c7c6 +b1c3 e7e6 +e2e4 d4e4 +c3e4 f8b4 +c1d2 d8d4 +d2b4 d4e4 +f1e2 b8a6 +b4d6 b7b6 +! Queens Gambit --Slav (Krause) +d2d4 d7d5 +c2c4 c7c6 +g1f3 g8f6 +b1c3 d5c4 +a2a4 c8f5 +f3e5 e7e6 +f2f3 f8b4 +c1g5 h7h6 +g5f6 d8f6 +e2e4 f5h7 +! Modern Benoni Counter Gambit +d2d4 g8f6 +c2c4 c7c5 +d4d5 e7e6 +b1c3 e6d5 +c4d5 d7d6 +e2e4 g7g6 +f1d3 f8g7 +g1e2 o-o +o-o a7a6 +a2a4 d8c7 +! Queens Pawn Game +d2d4 d7d5 +g1f3 g8f6 +c1f4 c7c5 +e2e3 b8c6 +c2c3 d8b6 +d1c1 c8f5 +d4c5 b6c5 +b1d2 a8c8 +f3d4 c6d4 +e3d4 c5b6 +! Pirc-Robatsch Defence +d2d4 d7d6 +e2e4 g8f6 +b1c3 g7g6 +c1g5 f8g7 +d1d2 b8d7 +o-o-o e7e5 +d4e5 d6e5 +g1f3 h7h6 +g5h4 g6g5 +h4g3 d8e7 +! Pirc-Robatsch Defence +d2d4 d7d6 +e2e4 g8f6 +b1c3 g7g6 +f1c4 c7c6 +d1e2 f8g7 +g1f3 o-o +c1g5 b7b5 +c4d3 d8c7 +! Queens Indian Defence +d2d4 g8f6 +c2c4 e7e6 +g1f3 b7b6 +g2g3 c8b7 +f1g2 f8e7 +o-o o-o +b1c3 f6e4 +d1c2 e4c3 +c2c3 d7d6 +c3c2 f7f5 +! Queens Indian Defence +d2d4 g8f6 +c2c4 e7e6 +g1f3 b7b6 +e2e3 c8b7 +f1d3 f8e7 +b1c3 d7d5 +o-o o-o +d1e2 b8d7 +! Nimzo-Indian Defence +d2d4 g8f6 +c2c4 e7e6 +b1c3 f8b4 +d1c2 d7d5 +a2a3 b4c3 +c2c3 b8c6 +g1f3 f6e4 +c3b3 c6a5 +b3a4 c7c6 +! Nimzo-Indian Defence (Rubenstein) +d2d4 g8f6 +c2c4 e7e6 +b1c3 f8b4 +e2e3 o-o +f1d3 d7d5 +g1f3 c7c5 +o-o b8c6 +a2a3 b4c3 +b2c3 d5c4 +d3c4 d8c7 +! Nimzo-Indian Defence -- Samisch +d2d4 g8f6 +c2c4 e7e6 +b1c3 f8b4 +a2a3 b4c3 +b2c3 o-o +f2f3 d7d5 +c4d5 e6d5 +e2e3 c8f5 +g1e2 b8d7 +e2g3 f5g6 +! Nimzo-Indian Defence +d2d4 g8f6 +c2c4 e7e6 +b1c3 f8b4 +c1d2 o-o +e2e3 d7d5 +g1f3 c7c5 +a2a3 b4c3 +d2c3 f6e4 +a1c1 e4c3 +c1c3 c5d4 +! Grunfeld Defence +d2d4 g8f6 +c2c4 g7g6 +b1c3 d7d5 +c4d5 f6d5 +e2e4 d5c3 +b2c3 c7c5 +f1c4 f8g7 +g1e2 o-o +o-o c5d4 +c3d4 b8c6 +! Grunfeld Defence -- Smyslov +d2d4 g8f6 +c2c4 g7g6 +b1c3 d7d5 +g1f3 f8g7 +d1b3 d5c4 +b3c4 o-o +e2e4 c8g4 +c1e3 f6d7 +o-o-o b8c6 +! Grunfeld Defence +d2d4 g8f6 +c2c4 g7g6 +b1c3 d7d5 +c1f4 f8g7 +d2d3 o-o +c4d5 f6d5 +c3d5 d8d5 +f4c7 b8c6 +! Kings Indian Defence -- Classical +d2d4 g8f6 +c2c4 g7g6 +b1c3 f8g7 +e2e4 d7d6 +g1f3 o-o +f1e2 e7e5 +o-o b8c6 +c1e3 f8e8 +d4e5 d6e5 +! Kings Indian Defence -- 4 pawns attack +d2d4 g8f6 +c2c4 g7g6 +b1c3 f8g7 +e2e4 d7d6 +f2f4 c7c5 +g1f3 o-o +d4d5 e7e6 +f1d3 e6d5 +c4d5 d8b6 +! Kings Indian Defence -- Samisch +d2d4 g8f6 +c2c4 g7g6 +b1c3 f8g7 +e2e4 d7d6 +f2f3 o-o +c1e3 e7e5 +d4d5 c7c6 +g1e2 c6d5 +c3d5 f6d5 +! Kings Indian Defence -- Main Line +d2d4 g8f6 +c2c4 g7g6 +g2g3 f8g7 +f1g2 o-o +b1c3 d7d6 +g1f3 b8d7 +o-o e7e5 +e2e4 c7c6 +h2h3 d8b6 +! Kings Indian Defence +d2d4 g8f6 +c2c4 g7g6 +b1c3 f8g7 +g1f3 o-o +c1f4 d7d6 +h2h3 b8d7 +e2e3 c7c6 +! Dutch Defence +d2d4 f7f5 +g2g3 e7e6 +f1g2 g8f6 +g1f3 f8e7 +o-o o-o +c2c4 d7d6 +b1c3 d8e8 +d1c2 e8h5 +b2b3 b8c6 +c1a3 a7a5 +! English Opening +c2c4 e7e5 +b1c3 g8f6 +g1f3 b8c6 +e2e4 f8b4 +d2d3 d7d6 +f1e2 o-o +o-o b4c3 +b2c3 d8e7 +! English Opening +c2c4 g8f6 +b1c3 d7d5 +c4d5 f6d5 +e2e4 d5f4 +f1c4 c8e6 +c4e6 f7e6 +! English Opening +c2c4 e7e5 +b1c3 g8f6 +g1f3 b8c6 +g2g3 d7d5 +c4d5 f6d5 +f1g2 d5b6 +o-o f8e7 +d2d3 o-o +c1e3 f7f5 +! Reti -- Accepted +g1f3 d7d5 +c2c4 d5c4 +e2e3 c7c5 +f1c4 e7e6 +o-o g8f6 +b2b3 b8c6 +c1b2 a7a6 +a2a4 f8e7 +! Reti -- Neo Catalan +g1f3 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 f8e7 +o-o o-o +b2b3 c7c5 +c4d5 f6d5 +c1b2 b8c6 +d2d4 b7b6 +b1c3 d5c3 +! Reti -- Barcza +g1f3 d7d5 +g2g3 g8f6 +f1g2 g7g6 +o-o f8g7 +d2d3 o-o +b1d2 b8c6 +e2e4 e7e5 +c2c3 a7a5 +f1e1 d5e4 +d3e4 f6d7 +! Sicilian Najdorf +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +e4e5 d6e5 +f4e5 f6d7 +c3e4 h7h6 +g5h4 a3a2 +b1b3 b8c6 +d4c6 b7c6 +e4d6 f8d6 +e5d6 a6a5 +f1e2 a5a4 +b3c3 a2a1 +e2d1 a4a3 +o-o a3a2 +d2e3 o-o +! # Sicilian Defense col. 2f p. 176 MCO 12. (Incomplete game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +e4e5 d6e5 +f4e5 f6d7 +f1c4 f8b4 +b1b3 a3a5 +o-o o-o +g5f6 d7f6 +e5f6 f8d8 +b3b4 a5b4 +d2g5 g7g6 +f1f4 b7b6 +f4h4 b4f8 +g1f1 a8a7 +! # Sicilian Defense col. 3g p. 176 MCO (Incomplete Game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +e4e5 d6e5 +f4e5 f6d7 +f1c4 a3a5 +c4e6 f7e6 +d4e6 d7e5 +c3d5 a5d2 +e1d2 e8d7 +e6c7 a8a7 +h1e1 e5c4 +! # Parma vs. Fischer, Havana 1965. Sicilian Defense col. 4j p. 176 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +g5f6 g7f6 +f1e2 f8g7 +o-o f6f5 +f1d1 b8c6 +d4c6 g7c3 +d2e3 b7c6 +b1b3 a3c5 +e3c5 d6c5 +b3c3 f5e4 +c3c5 c8d7 +c5e5 f7f5 +g2g4 h8g8 +g1g2 f5g4 +e5e4 h7h5 +g2g3 e8e7 +! # Matanovic, Sicilian Defense col. 5k p. 176 MCO (partial game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +g5f6 g7f6 +f1e2 b8c6 +d4c6 b7c6 +o-o a3a5 +g1h1 f8e7 +f4f5 e6f5 +e4f5 c8f5 +e2a6 a5a6 +f1f5 d6d5 +b1e1 a6b7 +d2h6 o-o-o +h6h3 b7d7 +c3a4 +! # col. 6a +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +f4f5 b8c6 +f5e6 f7e6 +d4c6 b7c6 +e4e5 d6e5 +g5f6 g7f6 +c3e4 f8e7 +f1e2 h7h6 +c2c4 f6f5 +b1b3 a3a4 +o-o f5e4 +g1h1 c6c5 +d2c3 a4c6 +c3e5 h8f8 +! # col. 7d +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +a1b1 b2a3 +f4f5 b8c6 +f5e6 f7e6 +d4c6 b7c6 +e4e5 f6d5 +c3d5 c6d5 +f1e2 d6e5 +o-o a8a7 +g1h1 a3c5 +c2c4 d5d4 +e2h5 g7g6 +h5d1 f8e7 +d1a4 e8d8 +f1f7 h7h6 +g5h6 e5e4 +! # col. 8 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +d4b3 b8d7 +g5f6 g7f6 +f1e2 h7h5 +o-o b2a3 +a1d1 f8e7 +g1h1 d7c5 +e2f3 a8a7 +b3c5 a3c5 +! # col. 9g; Minic-Barczay, Varna 1967 (partial game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +d4b3 b8c6 +f1d3 d6d5 +g5f6 g7f6 +c3a4 b2a3 +a4b6 d5d4 +o-o a8b8 +f4f5 a3b4 +d2b4 f8b4 +b6c8 b8c8 +f5e6 f7e6 +f1f6 e8e7 +a1f1 c6e5 +! # col. 10i; Matulovic-Kavalek, Sousse 1967 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d1d2 b6b2 +d4b3 b8c6 +a1b1 b2a3 +g5f6 g7f6 +f1d3 f8g7 +o-o o-o +f1f3 g8h8 +f3h3 c6e7 +f4f5 e6f5 +e4f5 c8f5 +d3f5 e7f5 +c3d5 +! # col. 11b; Joppen-Bronstein, Belgrade 1954 (partial game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d4b3 b6e3 +d1e2 e3e2 +f1e2 b8d7 +a2a4 f8e7 +o-o-o h7h6 +g5h4 e6e5 +f4f5 b7b6 +e2f3 c8b7 +! # col. 12e; Rajkovic-Udovcic, Yugoslav Chp. 1962 (partial game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 d8b6 +d4b3 b8d7 +d1f3 f8e7 +o-o-o b6c7 +f1d3 h7h6 +g5h4 g7g5 +f4g5 d7e5 +f3e2 f6g4 +b3d4 h6g5 +h4g3 c8d7 +d4f3 c7c5 +! # col. 13i; Fischer-Vukovic (partial game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 f8e7 +d1f3 d8c7 +o-o-o b8d7 +g2g4 b7b5 +g5f6 d7f6 +g4g5 f6d7 +a2a3 a8b8 +h2h4 b5b4 +a3b4 b8b4 +f1h3 o-o +d4e6 f7e6 +h3e6 g8h8 +c3d5 c7c4 +e6f5 f8f5 +e4f5 c8b7 +h1e1 e7f8 +! # col. 14m Parma-Tatai, Athens 1968 (partial game) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 b7b5 +e4e5 d6e5 +f4e5 d8c7 +e5f6 c7e5 +f1e2 e5g5 +d1d3 a8a7 +c3e4 g5e5 +d4f3 e5b2 +o-o a7d7 +d3e3 c8b7 +a1b1 b2c2 +f3g5 c2c6 +f6g7 f8g7 +! # col. 15; slight advantage for white. +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +f2f4 h7h6 +g5h4 d8b6 +d1d3 b6b2 +a1b1 b2a3 +e4e5 f6d5 +c3d5 a3d3 +f1d3 e6d5 +e5e6 +! # col. 16c; Fichtl-Dolezal, CSSR 1954 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +d1f3 b8d7 +o-o-o d8c7 +f3g3 b7b5 +f1b5 a6b5 +d4b5 c7b8 +b5d6 f8d6 +g3d6 b8d6 +d1d6 h7h6 +g5f6 d7f6 +h1d1 c8b7 +f2f3 +! # col. 17e; Vasyukov-Zukharov, USSR 1960 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 e7e6 +d1d2 b8c6 +o-o-o h7h6 +g5h4 f6e4 +d2f4 e4g5 +d4c6 b7c6 +f4a4 d8b6 +f2f4 g5h7 +f4f5 a8b8 +f5e6 c8e6 +f1c4 +! # col. 18g (somewhat questionable) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1g5 b8d7 +f1c4 d8a5 +d1d2 e7e6 +o-o-o b7b5 +c4b3 c8b7 +h1e1 a8c8 +e4e5 d7e5 +d4e6 f7e6 +e1e5 d6e5 +g5f6 +! # col. 19m; Yanofsky-Bolbochan, Stockholm 1962 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +f1e2 e7e5 +d4b3 f8e7 +o-o o-o +f2f4 b7b5 +a2a3 c8b7 +e2f3 b8d7 +g2g3 a8c8 +d1e1 d7b6 +g1h1 b6c4 +b3d2 d8d7 +d2c4 c8c4 +c1d2 d6d5 +! # col. 20p +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +f1e2 e7e5 +d4b3 f8e7 +o-o o-o +c1e3 b8d7 +a2a4 b7b6 +d1d2 c8b7 +f2f3 d8c7 +f1d1 f8c8 +b3c1 +! # col. 21b +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +g2g3 e7e5 +d4e2 f8e7 +f1g2 o-o +o-o b7b5 +h2h3 c8b7 +c3d5 f6d5 +e4d5 b8d7 +a2a4 d7c5 +e2c3 d8d7 +a4b5 a6b5 +a1a8 f8a8 +! # col. 22 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +f2f4 e7e6 +d1f3 d8b6 +d4b3 b8c6 +f1d3 f8e7 +c1e3 b6c7 +o-o o-o +a1e1 c6b4 +! # col. 23f +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +c1e3 e7e5 +d4b3 c8e6 +d1d2 b8d7 +f2f3 f8e7 +g2g4 b7b5 +g4g5 f6h5 +o-o-o o-o +h1g1 a8c8 +c3e2 +! # col. 24k; Kotkov-Polugayevski, USSR 1959 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +f1c4 e7e6 +o-o f8e7 +c4b3 o-o +f2f4 b7b5 +a2a3 c8b7 +f4f5 e6e5 +d4e2 b8d7 +e2g3 d7c5 +b3d5 b7d5 +e4d5 a8c8 +c1g5 c5d7 +g5f6 d7f6 +c3e4 c8c4 +! # col. 25o; Ciocaltea-Minic, Bucharest 1966 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 a7a6 +f1c4 e7e6 +c4b3 b7b5 +f2f4 c8b7 +f4f5 e6e5 +d4e2 b8d7 +o-o f8e7 +e2g3 a8c8 +c1g5 o-o +! # col. 26e +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +c1e3 f8g7 +f2f3 o-o +d1d2 b8c6 +o-o-o d6d5 +e4d5 f6d5 +d4c6 b7c6 +c3d5 c6d5 +d2d5 d8c7 +d5a8 c8f5 +a8f8 g8f8 +d1d2 h7h5 +f1e2 f8g8 +a2a3 c7b8 +! # col. 27i; Bikhovski-Gik, Moscow 1968 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +c1e3 f8g7 +f2f3 o-o +d1d2 b8c6 +f1c4 c8d7 +o-o-o d8a5 +c4b3 f8c8 +g2g4 c6e5 +h2h4 e5c4 +b3c4 c8c4 +d4b3 a5a6 +h4h5 c4c3 +b2c3 d7e6 +c1b1 a8c8 +e3d4 c8c4 +h5g6 h7g6 +! # col. 28k +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +c1e3 f8g7 +f2f3 o-o +d1d2 b8c6 +f1c4 c8d7 +o-o-o d8a5 +c4b3 f8c8 +h2h4 c6e5 +h4h5 f6h5 +e3h6 e5d3 +c1b1 d3b2 +b1b2 g7h6 +d2h6 c8c3 +g2g4 h5f6 +g4g5 f6h5 +! # col. 29m; Ostojic-Honfi, Monte Carlo 1968 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +c1e3 f8g7 +f2f3 o-o +d1d2 b8c6 +f1c4 c8d7 +o-o-o d8a5 +c4b3 f8c8 +c1b1 c6e5 +h2h4 e5c4 +b3c4 c8c4 +d4b3 a5c7 +h4h5 c4c3 +d2c3 c7c3 +b2c3 f6h5 +e3d4 d7e6 +h1e1 h5f6 +e4e5 d6e5 +d4e5 f6d5 +b1b2 a8c8 +! # col. 30p; Karpov-Korchnoi, 2nd match game 1974. +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +c1e3 f8g7 +f2f3 o-o +d1d2 b8c6 +f1c4 c8d7 +h2h4 a8c8 +c4b3 c6e5 +h4h5 f6h5 +o-o-o e5c4 +b3c4 c8c4 +g2g4 h5f6 +d4e2 d8a5 +e3h6 g7h6 +d2h6 f8c8 +d1d3 c4c5 +g4g5 c5g5 +d3d5 g5d5 +c3d5 c8e8 +e2c3 d7c6 +e4e5 c6d5 +e5f6 e7f6 +h6h7 g8f8 +h7h8 f8e7 +c3d5 +! # col. 31 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +g2g3 b8c6 +f1g2 c6d4 +d1d4 f8g7 +o-o o-o +d4d3 c8e6 +c3d5 f6d5 +e4d5 e6f5 +! # col. 32c; Pulsen-Cortlever, Buenos Aires 1939. +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +c1g5 f8g7 +d1d2 b8c6 +o-o-o o-o +d4b3 f8e8 +f2f3 a7a6 +c1b1 b7b5 +h2h4 c8e6 +g2g4 c6e5 +! # col. 33h +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f2f4 b8c6 +d4c6 b7c6 +e4e5 d6e5 +d1d8 e8d8 +f4e5 f6g4 +c1f4 c8e6 +c3e4 f8g7 +e4g5 g7e5 +o-o-o d8c7 +g5e6 f7e6 +f4e5 g4e5 +d1e1 c7d6 +g2g3 e5g4 +f1c4 e6e5 +e1e2 +! # col. 34j +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f2f4 b8c6 +f1b5 d8c7 +c3d5 f6d5 +e4d5 a7a6 +b5c6 b7c6 +d4c6 c8b7 +c1e3 f8g7 +e3d4 g7d4 +d1d4 o-o +o-o b7c6 +! # col. 35l +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f2f4 b8d7 +f1e2 f8g7 +c1e3 o-o +e2f3 d7b6 +d1e2 e7e5 +d4b3 f6g4 +f3g4 d8h4 +g2g3 h4g4 +e2g4 c8g4 +! # col. 36a +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +o-o o-o +d4b3 c8e6 +f2f4 c6a5 +f4f5 e6c4 +b3a5 c4e2 +d1e2 d8a5 +g2g4 a8c8 +g4g5 c8c3 +g5f6 c3e3 +e2e3 g7f6 +c2c3 f8c8 +a2a3 c8c4 +a1e1 b7b5 +! # col. 37c; Domnitz-Kraidman, Tel Aviv 1964 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +o-o o-o +d4b3 c8e6 +f2f4 d8c8 +d1e1 f6g4 +e2g4 e6g4 +f4f5 g6f5 +h2h3 g4h3 +g2h3 f5e4 +e1h4 f7f5 +g1h1 f8f7 +f1g1 c6e5 +c3d5 c8d7 +b3d4 e5g6 +g1g6 h7g6 +a1g1 e7e5 +g1g6 d7d8 +e3g5 d8a5 +d5f6 g8f8 +d4e6 +! # col. 38f; Unzicker-Geller, W. Germany-USSR 1960 (drawn) +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +o-o o-o +d1d2 f6g4 +e2g4 c8g4 +f2f4 c6d4 +e3d4 e7e5 +d4e3 e5f4 +f1f4 g4e6 +f4f2 g7e5 +e3d4 a8c8 +a1d1 d8a5 +a2a3 c8c4 +c3e2 a5d2 +d1d2 +! # col. 39 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +o-o o-o +f2f4 d8b6 +d1d3 f6g4 +c3d5 g7d4 +e2g4 d4e3 +d3e3 b6b2 +g4c8 a8c8 +a1b1 b2a2 +b1b7 e7e6 +! # col. 40h +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +o-o o-o +f2f4 d8b6 +e4e5 d6e5 +f4e5 c6e5 +d4f5 b6b2 +f5e7 g8h8 +e3d4 b2b4 +d4e5 b4e7 +d1d4 f6e8 +e5g7 e8g7 +e2d3 c8e6 +! # col. 41b; Smyslov-Botvinnik, match 1958 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +h2h4 h7h5 +f2f3 o-o +d1d2 d6d5 +d4c6 b7c6 +e4e5 f6e8 +f3f4 f7f6 +o-o-o f6e5 +f4e5 g7e5 +g2g4 c8g4 +e2g4 h5g4 +h4h5 g6g5 +! # col. 42d; Van den Burg-Rajkovic, Orebro 1966 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +d4b3 o-o +f2f4 c6a5 +g2g4 b7b6 +g4g5 f6d7 +o-o c8b7 +e2d3 a8c8 +b3a5 b6a5 +d1e1 d7c5 +f4f5 g7e5 +e1h4 e7e6 +f5f6 h7h5 +d3e2 g8h7 +e2h5 f8h8 +! # col. 43f +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +c1e3 b8c6 +d4b3 o-o +f2f4 c6a5 +g2g4 c8e6 +g4g5 f6d7 +e3d4 f7f6 +h2h4 f6g5 +d4g7 g8g7 +b3d4 e6g8 +f4f5 d8b6 +! # col. 44 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +o-o b8c6 +d4b3 o-o +f2f4 b7b5 +e2f3 b5b4 +c3d5 f6d5 +e4d5 c6a5 +b3a5 d8a5 +f1e1 f8e8 +! # col. 45i; Smyslov-Korchnoi, Moscow 1960 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 g7g6 +f1e2 f8g7 +d4b3 b8c6 +g2g4 b7b6 +f2f4 c8b7 +e2f3 o-o +h2h4 a7a5 +a2a4 c6b4 +h4h5 d6d5 +e4e5 f6g4 +b3d4 g4h6 +h5g6 f7g6 +d4e6 d8d7 +e6f8 a8f8 +c3b5 d5d4 +! # col. 46 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +f3d4 g8f6 +f2f3 e7e5 +f1b5 c8d7 +b5d7 b8d7 +d4f5 d6d5 +e4d5 d8a5 +b1c3 d7b6 +! # col. 47h; Schweber-Najdorf, Buenos Aires 1970 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +d1d4 b8c6 +f1b5 c8d7 +b5c6 d7c6 +c2c4 g8f6 +b1c3 e7e6 +c1g5 f8e7 +o-o o-o +f1e1 h7h6 +g5h4 a7a6 +a1d1 d8a5 +d4d2 a5b6 +f3d4 a8c8 +e1e3 f8e8 +! # col. 48i +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +d1d4 a7a6 +c1e3 g8f6 +b1c3 b8c6 +d4b6 d8b6 +e3b6 g7g6 +o-o-o f8h6 +c1b1 o-o +f3d4 c8d7 +f2f3 c6e5 +d4b3 f8c8 +b3a5 d7c6 +c3d5 c6d5 +e4d5 f6d7 +b6d4 b7b6 +! # col. 49m; Fischer-Korchnoi, Buenos-Aires 1960 +e2e4 c7c5 +g1f3 d7d6 +d2d4 c5d4 +c2c3 d4c3 +b1c3 b8c6 +f1c4 e7e6 +o-o a7a6 +d1e2 g8f6 +f1d1 d8c7 +c1g5 f8e7 +a1c1 o-o +c4b3 h7h6 +g5f4 e6e5 +f4e3 c7d8 +c3d5 f6d5 +b3d5 c8d7 +! # col. 50 +e2e4 c7c5 +g1f3 d7d6 +d2d4 g8f6 +d4c5 f6e4 +c5d6 e7e6 +d1d3 e4d6 +b1c3 b8c6 +c1f4 f7f6 +o-o-o e6e5 +c3b5 +! # col. 51c; Pfeiffer-Kottnauer, Helsinki 1952 +e2e4 c7c5 +g1f3 d7d6 +c2c3 g8f6 +f1d3 b8c6 +d3c2 c8g4 +h2h3 g4h5 +d2d3 d6d5 +d1e2 e7e6 +b1d2 f8e7 +d2f1 d8a5 +! # col. 52d; Brasket-Evans, U.S. Open Chp. 1960 +e2e4 c7c5 +g1f3 d7d6 +c2c3 g8f6 +d2d3 g7g6 +g2g3 f8g7 +b1d2 o-o +f1g2 e7e5 +o-o b8c6 +a2a4 h7h6 +d2b1 d8a5 +! # col. 53h; Ciocaltea-Fischer, Varna 1962 +e2e4 c7c5 +g1f3 d7d6 +g2g3 g7g6 +f1g2 f8g7 +o-o b8c6 +c2c3 e7e5 +d2d3 g8e7 +f3h4 o-o +f2f4 e5f4 +g3f4 f7f5 +b1d2 g8h8 +d2f3 +! # col. 54k; Tarjan-Mednis, U.S. Chp. 1973 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 e7e6 +f1e2 g7g6 +d4b3 +! e2e4 c7c5 +g1f3 d7d6 +b1c3 g8f6 +e4e5 d6e5 +f3e5 a7a6 +f1e2 e7e6 +o-o d8c7 +e5c4 b7b5 +c4e3 f8d6 +h2h3 b8c6 +a2a4 b5b4 +c3b1 c8b7 +d2d3 c6d4 +b1d2 o-o +d2f3 d4e2 +d1e2 f8e8 +e3c4 e6e5 +f3g5 e5e4 +c4d6 c7d6 +g5e4 f6e4 +d3e4 b7e4 +c1e3 d6c6 +! # col. 55o; Medina-Pomar, Santander 1947 +e2e4 c7c5 +g1f3 d7d6 +b2b4 c5b4 +d2d4 g8f6 +f1d3 d6d5 +b1d2 d5e4 +d2e4 b8d7 +e4g5 d8c7 +c2c4 h7h6 +g5h3 g7g5 +h3g1 f8g7 +g1e2 e7e5 +e2g3 e5e4 +d1e2 o-o +! # col. 56e; del Corral-Benko, Mallorca 1968 +e2e4 c7c5 +g1f3 d7d6 +f1b5 c8d7 +b5d7 d8d7 +o-o b8c6 +f1e1 g8f6 +c2c3 e7e6 +d2d3 f8e7 +a2a4 o-o +b1d2 d7c7 +! # col. 57g; Radovich-Lombardy, Leipzig 1960 +e2e4 c7c5 +g1f3 d7d6 +f1b5 b8c6 +o-o a7a6 +b5c6 b7c6 +d2d4 c5d4 +d1d4 e7e5 +d4d3 f7f6 +c2c4 c8e6 +b1c3 d8c7 +! # col. 58j; Gurgenidze-Osnos, Alma Ata 1969 +e2e4 c7c5 +g1f3 b8c6 +f1b5 e7e6 +b1c3 g8e7 +o-o a7a6 +b5c6 e7c6 +d2d4 c5d4 +f3d4 d7d6 +d4c6 b7c6 +d1g4 g7g6 +e4e5 d6d5 +c1g5 f8e7 +! # col. 59m +e2e4 c7c5 +g1f3 b8c6 +f1b5 g7g6 +o-o f8g7 +c2c3 g8f6 +f1e1 o-o +d2d4 c5d4 +c3d4 d7d5 +e4e5 f6e4 +b1c3 e4c3 +b2c3 c6a5 +c1g5 c8f5 +f3d2 f8e8 +! # col. 60o +e2e4 c7c5 +g1f3 b8c6 +f1b5 g7g6 +o-o f8g7 +f1e1 e7e5 +f1e1 o-o +d2d4 c5d4 +c3d4 d7d5 +e4e5 f6e4 +b1c3 e4c3 +b2c3 c6a5 +c1g5 c8f5 +f3d2 f8e8 +! # col. 61c; Barczay-Szilagyi, Hungarian Chp. 1969 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +g5f6 g7f6 +d4b3 h8g8 +g2g3 f6f5 +d1d2 f8g7 +e4f5 d7f5 +f1g2 d8d7 +o-o g7c3 +b2c3 f5h3 +g2h3 d7h3 +! # col. 62e +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d4b3 h7h6 +g5h4 a8c8 +f1e2 g7g5 +h4g3 h6h5 +h2h4 g5g4 +g3f4 c6e5 +d1d4 e5g6 +f4g5 f8g7 +o-o +! # col. 63g; Matulovic-Masic, Sombor 1968 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +f2f4 d8b6 +d4b3 f6g4 +d1e2 c6d4 +c3d5 d4e2 +d5b6 a7b6 +e1e2 h7h6 +g5h4 g7g5 +h4g3 g5f4 +g3f4 f8g7 +c2c3 d7c6 +! # col. 64j; Liberzo-Stein, USSR Chp. 1969-70. Complete game (draw). +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d3 c6d4 +d3d4 d8a5 +f2f4 e7e5 +d4d3 f8e7 +o-o-o d7c6 +c1b1 e5f4 +g5f4 o-o +f1e2 f8e8 +e2f3 e7f8 +c3d5 f6d7 +d3d2 a5d2 +d1d2 a8c8 +h1d1 d7e5 +b2b3 +! # col. 65m; Bronstein-Stein, USSR 1969 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d3 c6d4 +d3d4 d8a5 +f1e2 e7e5 +d4d3 a5c7 +e2g4 f8e7 +g5f6 e7f6 +o-o-o f6e7 +c3b5 d7b5 +d3b5 c7c6 +b5d5 c6d5 +d1d5 +! # col. 66b; Benko-R. Byrne, US Open Chp. 1968 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d2 a8c8 +o-o-o c6d4 +d2d4 d8a5 +g5d2 a7a6 +f1c4 a5c5 +d4c5 c8c5 +c4b3 g7g6 +d2e3 c5c8 +e3d4 f8g7 +c3d5 f6h5 +d4g7 h5g7 +e4e5 c8c6 +d5b4 c6b6 +! # col. 66b alternate; Polgar-Nagy, Hungarian Chp. 1972 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d2 a8c8 +o-o-o c6d4 +d2d4 d8a5 +g5d2 e7e5 +d4d3 a7a6 +c1b1 h7h6 +f2f3 a5c7 +g2g3 f8e7 +h2h4 b7b5 +! # col. 67c; Suetin-Gheorghiu, Hastings 1967/8. Draw. +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d2 a8c8 +o-o-o c6d4 +d2d4 d8a5 +g5e3 a7a6 +f2f3 e7e6 +d4b6 a5b6 +e3b6 d7c6 +f1c4 c6e4 +c4e6 f7e6 +c3e4 f6e4 +f3e4 f8e7 +h1f1 e7g5 +c1b1 e8e7 +c2c3 h8f8 +b1c2 f8f1 +d1f1 c8f8 +! # col. 68d +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d2 a8c8 +o-o-o c6d4 +d2d4 d8a5 +f2f4 e7e6 +e4e5 d6e5 +f4e5 c8c3 +g5d2 a5a2 +d2c3 g7g6 +! # col. 69fA1; Janosevic-Larsen, Belgrade 1964 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d2 a8c8 +o-o-o c6d4 +d2d4 d8a5 +f2f4 c8c3 +b2c3 e7e5 +d4b4 a5b4 +c3b4 f6e4 +f1c4 b7b5 +c4d5 e4c3 +f4e5 h7h6 +g5h4 g7g5 +h4g3 c3e2 +c1b2 e2g3 +h2g3 f8g7 +! # col. 70g; Bednarski-Simagin, Polanica Zdroj 1968 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 c8d7 +d1d2 a8c8 +o-o-o c6d4 +d2d4 c8c3 +d4c3 f6e4 +c3e3 e4g5 +e3g5 d8b6 +f1c4 e7e6 +g5g3 g7g6 +c4b3 f8e7 +h2h4 h7h5 +h1e1 b6b4 +g3e3 a7a5 +e3d4 +! # col. 71d +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o c6d4 +d2d4 o-o +f2f4 h7h6 +g5h4 d8a5 +f1c4 e6e5 +f4e5 d6e5 +d4d3 a5c5 +h4f6 e7f6 +! # col. 72g +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o c6d4 +d2d4 o-o +f2f4 d8a5 +f1c4 c8d7 +c4b3 d7c6 +h1f1 b7b5 +g5f6 e7f6 +d4d6 f6c3 +d6c6 a8c8 +c6d7 c8d8 +d7e7 c3d2 +c1b1 d2f4 +d1d8 a5d8 +! # col. 73i +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o o-o +d4b3 d8b6 +f2f3 a7a6 +g2g4 f8d8 +g5e3 b6c7 +h2h4 b7b5 +g4g5 f6d7 +g5g6 f7g6 +h4h5 g6h5 +h1h5 d7f6 +h5g5 c6e5 +d2g2 e7f8 +f3f4 e5c4 +f1c4 b5c4 +b3d4 a8b8 +d1g1 b8b7 +! # col. 74; Tal-Larsen, match 1969 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o o-o +d4b3 a7a6 +g5f6 g7f6 +f1e2 g8h8 +e2h5 c8d7 +f2f4 b7b5 +c1b1 +! # col. 75k +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o o-o +d4b5 d8a5 +g5f6 e7f6 +b5d6 f8d8 +f2f4 e6e5 +d2d5 a5c7 +f4f5 c6d4 +d6b5 c7a5 +d5c4 c8f5 +b2b4 a5a6 +! # col. 76b; Spasski-Larsen, Santa Monica 1966 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o o-o +f2f4 h7h6 +g5h4 e6e5 +d4f5 c8f5 +e4f5 d8a5 +c1b1 a8d8 +h4f6 e7f6 +c3d5 a5d2 +d5f6 g7f6 +d1d2 e5f4 +! # col. 77e; Kujpers-Minev, Halle 1967 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 f8e7 +o-o-o o-o +f2f4 d6d5 +e4e5 f6d7 +h2h4 d7b6 +d2e3 c8d7 +g5e7 d8e7 +h4h5 c6a5 +d4b3 a5c4 +e3d4 f8c8 +c1b1 a7a5 +f4f5 a5a4 +f5f6 e7f8 +h1h3 c4b2 +b1b2 b6c4 +f1c4 c8c4 +d4d2 +! # col. 78h +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 a7a6 +o-o-o c8d7 +f2f4 h7h6 +g5h4 f6e4 +d2e1 e4f6 +d4f5 d8a5 +f5d6 f8d6 +d1d6 o-o-o +d6d1 e6e5 +f1c4 e5f4 +c3e4 d7e6 +c4e6 f7e6 +e4d6 c8b8 +e1e6 h8f8 +! # col. 79j; O'Kelly-Simagin corr. 1964 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 a7a6 +o-o-o h7h6 +g5h4 f6e4 +d2f4 e4g5 +d4c6 b7c6 +f4a4 d8b6 +f2f4 g5h7 +f4f5 f8e7 +c3e4 a8b8 +a4a3 b6b5 +! # col. 80k; Di Camillo-R. Byrne, US Open Chp. 1958 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d2 h7h6 +g5f6 g7f6 +o-o-o a7a6 +f2f4 c8d7 +f1e2 h6h5 +c1b1 d8b6 +d4b3 o-o-o +h1f1 f8e7 +c3a4 b6a7 +c2c4 c6d4 +! # col. 81b +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d4c6 b7c6 +e4e5 d6e5 +d1f3 f8e7 +f3c6 c8d7 +c6f3 e5e4 +c3e4 f6e4 +g5e7 d8a5 +! # col. 82e +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1g5 e7e6 +d1d3 f8e7 +a1d1 o-o +f1e2 c8d7 +o-o c6d4 +d3d4 d7c6 +g1h1 d8a5 +f2f4 f8e8 +! # col. 83 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +h2h3 g7g6 +c1e3 f8g7 +d1d2 o-o +o-o-o c6d4 +e3d4 d8a5 +c1b1 e7e5 +d4e3 c8e6 +! # BAD! -- col. 84i; Karaklajic-Taimanov, Yugoslavia-USSR, match 1956 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +c1e3 f6g4 +f1b5 g4e3 +f2e3 c8d7 +o-o e7e6 +5c6 b7c6 +e4e5 f8e7 +d1h5 o-o +e5d6 e7d6 +c3e4 d6e7 +a1d1 d8c7 +d4b3 h7h6 +! # col. 85 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +d4e2 e7e6 +g2g3 d6d5 +e4d5 f6d5 +f1g2 d5c3 +d1d8 e8d8 +e2c3 c8d7 +c1d2 f8e7 +! # col. 86c; Carcia-Pomar, Havana 1969 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1c4 e7e5 +d4e2 c8e6 +c4e6 f7e6 +o-o f8e7 +f2f4 o-o +e2g3 e5f4 +f1f4 d8b6 +g1h1 a8d8 +b2b3 d6d5 +e4d5 f6d5 +f4f8 e7f8 +c3d5 d8d5 +d1e1 c6d4 +c1e3 f8c5 +! # col. 87 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1c4 d8b6 +d4b3 e7e6 +o-o f8e7 +c1e3 b6c7 +f2f4 o-o +c4d3 a7a6 +d1f3 +! # col. 88 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1c4 e7e6 +c1e3 d8c7 +d1e2 a7a6 +c4b3 c6a5 +g2g4 b7b5 +g4g5 f6d7 +o-o-o d7c5 +! # col. 89mA; Spasjevic-Ostojic, Belgrade 1966 (draw) +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1c4 e7e6 +c1e3 f8e7 +d1e2 a7a6 +o-o-o o-o +c4b3 d8c7 +g2g4 c6d4 +d1d4 e6e5 +d4c4 c7d8 +g4g5 f6e8 +h1g1 c8d7 +c3d5 d7b5 +e3b6 d8d7 +e2g4 e7d8 +g4d7 b5d7 +c4c3 d7e6 +b6d8 a8d8 +d5e3 d8d7 +b3a4 d7c7 +! # col. 90o; Bogdanovic-Shamkovich, Sarajevo 1963 +e2e4 c7c5 +g1f3 b8c6 +d2d4 c5d4 +f3d4 g8f6 +b1c3 d7d6 +f1c4 e7e6 +c1e3 f8e7 +d1e2 o-o +o-o-o c6d4 +e3d4 d8a5 +e4e5 d6e5 +d4e5 b7b6 +c3b5 c8a6 +e5c3 a5a4 +d1d4 a6b5 +c4b5 a4a2 +h1d1 f8d8 +d4a4 d8d1 +e2d1 a2d5 +d1d5 f6d5 +c3d4 e7g5 +c1b1 h7h5 +b5c6 a8d8 +a4a7 d5b4 +c6d7 b4c6 +! # Queen's Catalan, col. 1c; Kramer-Fichtl, Varna Olympics 1962 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o b8d7 +b1c3 c7c6 +b2b3 b7b6 +c1b2 c8b7 +d1c2 a8c8 +a1d1 d8c7 +e2e4 d5e4 +c3e4 f6e4 +c2e4 c6c5 +d4d5 e7f6 +e4c2 e6d5 +c4d5 f6b2 +c2b2 c8d8 +! # col. 2f +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o b8d7 +b1c3 d5c4 +e2e4 c7c6 +a2a4 a7a5 +d1e2 d7b6 +f1d1 e7b4 +f3e5 d8e7 +c1e3 c8d7 +e5c4 b6c4 +e2c4 e6e5 +d4e5 f6g4 +! # col. 3i; Geller-Medina, Beverwijk 1965 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o b8d7 +d1c2 b7b6 +c4d5 f6d5 +b1c3 c8b7 +c3d5 b7d5 +e2e4 d5b7 +f1d1 c7c5 +d4d5 e6d5 +e4d5 e7f6 +h2h4 h7h6 +! # col. 4k; Geller-Bisguier, Bled 1961 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o b8d7 +d1c2 c7c6 +b2b3 b7b6 +c1b2 c8b7 +b1c3 a8c8 +a1d1 b6b5 +c4c5 b5b4 +c3b1 f6e4 +f3e1 f7f5 +e1d3 a7a5 +d3f4 f8f6 +f2f3 e4g5 +! # col. 5m; Benko-Pachman, Budapest 1948 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o b8d7 +d1c2 c7c6 +b1d2 b7b6 +e2e4 c8b7 +b2b3 a8c8 +f1d1 d8c7 +c1b2 f8d8 +a1c1 c7b8 +c2b1 a7a5 +f3e5 b8a8 +! # col. 6 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 f8e7 +f1g2 o-o +o-o c7c6 +b1c3 b7b6 +f3e5 a7a5 +d1c2 c8a6 +f1d1 b6b5 +! # col. 7d; Evans-Poschel, US Jr. Chp. 1947 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 c7c5 +c4d5 f6d5 +f1g2 c5d4 +o-o f8c5 +f3d4 o-o +a2a3 b8c6 +d4c6 b7c6 +b2b4 c5e7 +c1b2 e7f6 +d1c2 f6b2 +c2b2 a7a5 +! # col. 8g; O'Kelly-Euwe, New York 1951 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 d5c4 +f1g2 c7c5 +o-o b8c6 +d1a4 f6d7 +d4c5 f8c5 +a4c4 o-o +b1c3 a7a6 +c3e4 c5e7 +c1e3 d7b6 +c4b3 b6d5 +f1d1 d8c7 +! # col. 9 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 d5c4 +f1g2 b7b5 +a2a4 c7c6 +o-o c8b7 +f3e5 d8c8 +b2b3 c4b3 +d1b3 b5b4 +a4a5 f6d7 +! # col. 10l; Keres-Korchnoi, Curacao 1962 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +g1f3 d5c4 +d1a4 b8d7 +f1g2 a7a6 +a4c4 c7c5 +d4c5 f8c5 +o-o b7b5 +c4h4 c8b7 +b1d2 c5e7 +d2b3 a8c8 +h4d4 o-o +c1d2 d7c5 +! # col. -- Accelerated Catalan +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 d5c4 +d1a4 b8d7 +b1d2 c7c6 +a4c4 e6e5 +g1f3 d7b6 +c4d3 e5d4 +f3d4 f8e7 +o-o o-o +! # col. 12e; Muller-Ratzek, Vienna 1951 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 d5c4 +d1a4 c8d7 +a4c4 d7c6 +g1f3 c6d5 +c4d3 c7c5 +b1c3 d5c6 +o-o b8d7 +f1d1 d8b6 +e2e4 c5d4 +f3d4 f8c5 +d4c6 c5f2 +g1f1 b7c6 +c3a4 b6a5 +f1f2 a5a4 +d3d6 +! # col. 13f; Smyslov-Kere, USSR Chp. 1948 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 d5c4 +d1a4 c8d7 +a4c4 d7c6 +g1f3 b8d7 +b1c3 d7b6 +c4d3 f8b4 +o-o o-o +f1d1 h7h6 +c1d2 d8e7 +a2a3 b4c3 +d3c3 f8d8 +! # col. 14g +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +b1c3 d5c4 +d1a4 b8c6 +f1g2 c8d7 +a4c4 c6b4 +c4b3 c7c5 +g1f3 c5d4 +f3d4 e6e5 +d4f3 d7e6 +b3a4 e6d7 +! # col. 15; Stoltz-Vidmar, Groningen 1946 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +b1c3 f8e7 +f1g2 o-o +g1f3 d5c4 +d1a4 a7a6 +a4c4 b7b5 +c4d3 c8b7 +! # col. 16 +d2d4 d7d5 +c2c4 e7e6 +g2g3 g8f6 +b1d2 c7c5 +d4c5 f8c5 +f1g2 b8c6 +g1f3 o-o +o-o a7a5 +c4d5 e6d5 +d2b3 c5b6 +! # col. 17d; Mikenas-Aronin, USSR Chp. 1963 +d2d4 d7d5 +c2c4 e7e6 +g2g3 c7c5 +c4d5 e6d5 +g1f3 b8c6 +f1g2 g8f6 +o-o f8e7 +d4c5 e7c5 +b1d2 o-o +d2b3 c5b6 +b3d4 f8e8 +b2b3 c6d4 +f3d4 b6d4 +d1d4 e8e2 +! # col. 18e +d2d4 d7d5 +c2c4 e7e6 +g2g3 d5c4 +d1a4 c8d7 +a4c4 c7c5 +d4c5 d7c6 +g1f3 b8d7 +c1e3 g8f6 +f1g2 d8c7 +o-o c6d5 +c4a4 f8c5 +e3c5 c7c5 +b1c3 d5c6 +! # col. 19 +d2d4 d7d5 +c2c4 e7e6 +g2g3 f8b4 +c1d2 b4d2 +d1d2 g8f6 +g1f3 o-o +f1g2 d8e7 +o-o b8c6 +f1c1 +! # col. 20 +d2d4 d7d5 +c2c4 e7e6 +g2g3 f8b4 +c1d2 b4e7 +f1g2 g8f6 +g1f3 o-o +d1b3 b7b6 +c4d5 e6d5 +b1c3 c8b7 +o-o +! # col. 21 +d2d4 g8f6 +c2c4 e7e6 +g2g3 e6e5 +g1f3 e5d4 +f3d4 d7d5 +f1g2 d5c4 +d1a4 c7c6 +a4c4 f8e7 +o-o o-o +f1d1 +! # col. 22 +d2d4 g8f6 +c2c4 e7e6 +g2g3 c7c5 +g1f3 c5d4 +f3d4 d7d5 +f1g2 e6e5 +d4f3 d5d4 +o-o b8c6 +e2e3 f8e7 +e3d4 e5d4 +! # col. 23g +d2d4 g8f6 +c2c4 e7e6 +g2g3 c7c5 +g1f3 c5d4 +f3d4 b8c6 +f1g2 d8b6 +d4c2 f8c5 +e2e3 o-o +b1c3 b6a6 +d1d2 f8d8 +a2a3 d7d5 +b2b4 d5d4 +c3e4 +! # col. 24j; Smyslov-Petrosian, Moscow 1967 +d2d4 g8f6 +c2c4 e7e6 +g2g3 f8b4 +b1d2 c7c5 +d4c5 b4c5 +f1g2 b8c6 +g1f3 b7b6 +o-o c8b7 +a2a3 o-o +b2b4 c5e7 +c1b2 a8c8 +d1b1 +! # col. 25 +d2d4 g8f6 +c2c4 e7e6 +g2g3 f8b4 +c1d2 b4d2 +d1d2 f6e4 +d2c2 f7f5 +f2f3 e4f6 +e2e4 f5e4 +f3e4 e6e5 +! # Alternate openings leading to the Catalan, line C +g1f3 d7d5 +c2c4 e7e6 +g2g3 g8f6 +d2d4 +! # line D +c2c4 g8f6 +d2d4 e7e6 +g2g3 d7d5 +! # line E +d2d4 g8f6 +c2c4 e7e6 +g2g3 d7d5 +! # The Reti Opening, col. 1c; Muller-Lilenthal, Budapest 1933 +g1f3 d7d5 +c2c4 c7c6 +b2b3 g8f6 +g2g3 c8f5 +c1b2 e7e6 +f1g2 b8d7 +o-o f8d6 +d2d3 o-o +b1c3 d8e7 +f1e1 e6e5 +c4d5 c6d5 +e2e4 d5e4 +d3e4 f5g6 +! # col. 2g; Bilek-Geller, Sousse 1967 +g1f3 d7d5 +c2c4 c7c6 +b2b3 g8f6 +g2g3 c8g4 +f1g2 e7e6 +c1b2 b8d7 +o-o f8e7 +d2d3 o-o +b1d2 a7a5 +a2a3 d8b6 +d1c2 h7h6 +b2c3 f8c8 +f1e1 b6d8 +e2e4 d8f8 +! # col. 3k; Botvinnik-Fine, Nottingham 1936 +g1f3 d7d5 +c2c4 d5c4 +b1a3 c7c5 +a3c4 b8c6 +g2g3 e7e5 +f1g2 f7f6 +b2b3 g8e7 +c1b2 e7d5 +o-o f8e7 +f3h4 o-o +d1b1 f8f7 +h4f5 c8e6 +f2f4 e5f4 +g3f4 d5b6 +g2e4 e6c4 +! # col. 4n; Katetov-Alekhin, Prague 1943 +g1f3 d7d5 +c2c4 d5d4 +e2e3 b8c6 +e3d4 c6d4 +f3d4 d8d4 +b1c3 e7e5 +d2d3 f8c5 +c1e3 d4d6 +c3b5 d6e7 +e3c5 e7c5 +d3d4 e5d4 +d1d4 c5d4 +b5d4 c8g4 +! # col. 5o +g1f3 d7d5 +c2c4 d5d4 +e2e3 c7c5 +e3d4 c5d4 +g2g3 b8c6 +f1g2 g7g6 +d2d3 f8g7 +o-o e7e5 +f1e1 f7f6 +b2b4 c6b4 +d1a4 b4c6 +f3d4 d8d4 +g2c6 c8d7 +! # col. 6 +g1f3 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 f8e7 +o-o o-o +b2b3 c7c5 +c4d5 f6d5 +c1b2 b8c6 +d2d4 d5b4 +a2a3 b4a6 +d4c5 d8d1 +! # col. 7 +g1f3 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 f8e7 +b1c3 o-o +b2b3 c7c5 +c1b2 b8c6 +c4d5 e6d5 +a1c1 c8e6 +o-o a8c8 +d2d4 f8e8 +! # col. 8g; Kashdan-Horowitz, New York 1931 +g1f3 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 b8d7 +b2b3 c7c6 +o-o f8d6 +c1b2 o-o +b1c3 b7b6 +d2d3 c8b7 +e2e4 d5e4 +d3e4 d8c7 +d1e2 f8d8 +f1d1 +! # col. 9h; Abroshin-Krykov corr. 1960 +g1f3 d7d5 +c2c4 e7e6 +g2g3 g8f6 +f1g2 d5c4 +d1a4 c8d7 +a4c4 d7c6 +o-o c6d5 +c4a4 d8d7 +a4c2 b8c6 +b1c3 d5f3 +g2f3 c6d4 +c2d3 c7c6 +! # col. 10m; Teti-Tartakover, Semmering 1926 +g1f3 d7d5 +c2c4 e7e6 +g2g3 d5c4 +d1a4 c8d7 +a4c4 c7c5 +f3e5 b8c6 +e5d7 d8d7 +f1g2 g8f6 +d2d3 f8e7 +o-o c6d4 +b1c3 a8d8 +a2a4 f6d5 +! # Barcza System, col. 11 +g1f3 d7d5 +g2g3 g8f6 +f1g2 c8f5 +o-o c7c6 +c2c4 d5c4 +b1a3 e7e5 +a3c4 e5e4 +f3e1 f8c5 +d2d3 o-o +c1e3 b8d7 +! # col. 12d; Benko-Petrosian, Curacao 1962 +g1f3 d7d5 +g2g3 g8f6 +f1g2 c8f5 +o-o c7c6 +d2d3 b8d7 +b1d2 h7h6 +d1e1 e7e6 +e2e4 f5h7 +e1e2 f8e7 +e4e5 f6g8 +d2b3 e7f8 +c2c4 g8e7 +b3d4 e7f5 +d4f5 h7f5 +c4d5 c6d5 +d3d4 a7a5 +c1e3 f8e7 +f1c1 o-o +! # col. 13f; Bronstein-O'Kelly, Beverwijk 1963 +g1f3 d7d5 +g2g3 g8f6 +f1g2 c7c5 +o-o e7e6 +d2d3 b8c6 +b1d2 f8e7 +e2e4 o-o +f1e1 d8c7 +e4e5 f6d7 +d1e2 b7b5 +h2h4 a7a5 +d2f1 c8a6 +f1h2 c6b4 +h4h5 +! # col. 14i; Evans-Olafsson, Dallas 1957 +g1f3 d7d5 +g2g3 g8f6 +f1g2 g7g6 +o-o f8g7 +d2d3 o-o +b1d2 b8c6 +e2e4 e7e5 +c2c3 a7a5 +f1e1 d5e4 +d3e4 f6d7 +d1e2 b7b6 +d2c4 c8a6 +g2f1 d8f6 +! # col. 15 +g1f3 d7d5 +g2g3 g8f6 +f1g2 g7g6 +d2d4 f8g7 +o-o c7c6 +b2b3 b8d7 +c1b2 e7e5 +d4e5 f6g4 +b1d2 d7e5 +f3e5 g4e5 +! # col. 16d; Larsen-Mecking, Mallorca 1969 +g1f3 d7d5 +g2g3 c7c5 +f1g2 b8c6 +o-o e7e6 +d2d3 g7g6 +b1c3 f8g7 +a2a3 g8e7 +a1b1 o-o +c1d2 a8b8 +b2b4 c5b4 +a3b4 b7b5 +e2e4 a7a5 +! # col. 17h; Benko-Bisguier, US Chp. 1963 +g1f3 d7d5 +g2g3 c8g4 +f1g2 b8d7 +c2c4 c7c6 +c4d5 c6d5 +b1c3 e7e6 +d1b3 d8b6 +b3b6 d7b6 +d2d3 a8c8 +c1e3 f8d6 +c3b5 d6b8 +o-o g8e7 +f1c1 c8c1 +a1c1 e7c6 +f3d4 e8d7 +! # col. 18j; Keene-Basman, Hastings 1966-7 +g1f3 d7d5 +g2g3 c8g4 +f1g2 g8f6 +c2c4 c7c6 +c4d5 g4f3 +g2f3 c6d5 +d1b3 d8d7 +b1c3 e7e6 +o-o b8c6 +f3g2 f8e7 +d2d3 o-o +! # col. 19k +g1f3 d7d5 +g2g3 c8g4 +f1g2 g8f6 +c2c4 c7c6 +d1c2 e7e6 +o-o f8e7 +b2b3 b8d7 +c1b2 o-o +d2d3 a7a5 +b1d2 a5a4 +b2c3 a4b3 +a2b3 d8b6 +! # col. 20m +g1f3 d7d5 +g2g3 c8g4 +f1g2 g8f6 +o-o c7c6 +c2c4 e7e6 +c4d5 g4f3 +g2f3 c6d5 +b1c3 b8c6 +d2d3 f8e7 +f3g2 +! # col. 21b; Savon-Aronin, USSR 1963 +g1f3 d7d5 +g2g3 b8c6 +d2d4 c8f5 +f1g2 c6b4 +b1a3 e7e6 +o-o g8f6 +f3h4 f5g4 +c2c4 c7c6 +a3c2 b4c2 +d1c2 f8e7 +h2h3 g4h5 +f2f3 h5g6 +h4g6 h7g6 +! # col. 22d; Fischer-Ivkov, Santa Monica 1966 +g1f3 d7d5 +g2g3 e7e6 +f1g2 c7c5 +o-o b8c6 +d2d3 f8d6 +e2e4 g8e7 +b1d2 o-o +f3h4 b7b6 +f2f4 d5e4 +d3e4 c8a6 +f1e1 c5c4 +c2c3 +! # col. 23 +g1f3 d7d5 +g2g3 b8d7 +c2c4 e7e6 +f1g2 g8f6 +b1c3 f8e7 +o-o o-o +d2d3 c7c5 +c4d5 e6d5 +c1g5 b7b6 +! # col. 24g; Benko-Bisguier, US Chp. 1976-7 +g1f3 d7d5 +g2g3 g8f6 +f1g2 b7b6 +c2c4 e7e6 +c4d5 e6d5 +o-o f8d6 +d2d4 o-o +b1c3 c7c6 +f3e5 c8b7 +c1g5 h7h6 +g5f6 d8f6 +f2f4 f8d8 +e2e4 +! # col. 25; Rabinovich-Rauser, Moscow 1934 +g1f3 d7d5 +b2b3 c8g4 +c1b2 b8d7 +c2c4 e7e6 +e2e3 g8f6 +f1e2 c7c6 +f3d4 g4e2 +d1e2 f8d6 +f2f4 o-o +! # col. 26e; Evans-Najdorf, Dallas 1967 +g1f3 c7c5 +g2g3 b8c6 +f1g2 g7g6 +o-o f8g7 +e2e4 d7d6 +c2c3 e7e5 +d2d3 g8h6 +f3e1 o-o +f2f4 e5f4 +c1f4 h6g4 +b1a3 g4e5 +g1h1 d8b6 +d1d2 c8e6 +! # col. 27h; Van den Pol-Barden, Holland v. England 1960 +g1f3 f7f5 +g2g3 g8f6 +f1g2 g7g6 +d2d3 f8g7 +b1d2 d7d6 +e2e4 e7e5 +d2c4 o-o +e4f5 g6f5 +c1e3 b8c6 +d3d4 e5e4 +! # col. 28m; Gufeld-Bokuchava, USSR Chp. prelims 1968 +g1f3 f7f5 +g2g3 g8f6 +f1g2 e7e6 +c2c4 f8e7 +o-o o-o +d2d3 d7d6 +b1c3 b8c6 +a1b1 a7a5 +a2a3 d8e8 +b2b4 a5b4 +a3b4 e6e5 +! # col. 29p; Lundin-Tartakover, Groningen 1946 +g1f3 f7f5 +g2g3 g8f6 +f1g2 e7e6 +c2c4 f8e7 +o-o o-o +b2b3 c7c5 +c1b2 b8c6 +b1c3 e6e5 +e2e3 d7d6 +d2d4 +! # col. 30 +g1f3 g7g6 +g2g3 f8g7 +f1g2 e7e5 +d2d3 b8c6 +e2e4 d7d6 +b1c3 g8e7 +c1e3 o-o +d1d2 c6d4 +o-o +! # King's Indian attack, col. 31a +g1f3 g8f6 +g2g3 b7b5 +h2h4 b5b4 +d2d3 c8b7 +e2e4 d7d6 +f1g2 b8d7 +o-o e7e6 +h4h5 a8b8 +b1d2 f8e7 +d2c4 o-o +! # col. 32d +g1f3 g8f6 +g2g3 g7g6 +b2b4 f8g7 +c1b2 o-o +f1g2 d7d5 +o-o c8g4 +c2c4 c7c6 +b1a3 b8d7 +a1c1 a7a5 +b4b5 a5a4 +d2d3 e7e5 +! # col. 33e; Olafsson-Kavalek, Wijik aan Zee 1969 +g1f3 g8f6 +g2g3 g7g6 +b2b3 f8g7 +c1b2 o-o +f1g2 d7d6 +d2d4 f6d7 +b1c3 e7e5 +d1d2 f8e8 +d4e5 d7e5 +f3e5 g7e5 +! # col. 34h +g1f3 g8f6 +g2g3 g7g6 +c2c4 d7d6 +f1g2 f8g7 +o-o o-o +b1c3 b8d7 +d2d3 e7e5 +c1d2 d7c5 +b2b4 c5e6 +a1b1 f6e8 +a2a4 c7c6 +a4a5 e8c7 +! # col. 35 +g1f3 g8f6 +c2c4 g7g6 +b2b3 f8g7 +c1b2 o-o +e2e3 d7d6 +f1e2 e7e5 +o-o f8e8 +b1c3 b8d7 +d2d3 c7c6 +! # col. 36d +g1f3 g8f6 +c2c4 g7g6 +b1c3 d7d5 +c4d5 f6d5 +d1a4 c8d7 +a4b3 d5b6 +d2d4 f8g7 +c1f4 d7e6 +b3c2 b8c6 +a1d1 +! # col. 37f +g1f3 g8f6 +c2c4 b7b6 +g2g3 c8b7 +f1g2 c7c5 +o-o g7g6 +b2b3 f8g7 +c1b2 o-o +b1c3 d7d5 +c3d5 f6d5 +b2g7 g8g7 +c4d5 d8d5 +d2d4 b8a6 +! # col. 38h; Geller-Kholmov, Moscow 1969 +g1f3 g8f6 +c2c4 b7b6 +g2g3 c8b7 +f1g2 e7e6 +o-o f8e7 +b2b3 o-o +c1b2 d7d5 +e2e3 b8d7 +b1c3 f6e4 +c4d5 e4c3 +b2c3 e6d5 +! # col. 39 +g1f3 g8f6 +b2b3 g7g6 +c2c4 f8g7 +c1b2 o-o +g2g3 c7c5 +f1g2 b7b6 +o-o c8b7 +b1c3 e7e6 +a1b1 d8e7 +! # col. 40o; Lombardy-Burger, US Chp. 1969-70 +g1f3 g8f6 +b2b3 d7d5 +c1b2 e7e6 +e2e3 f8e7 +c2c4 o-o +d2d4 b7b6 +f1d3 c8b7 +o-o b8d7 +b1d2 c7c5 +d1e2 f6e4 +a1c1 a8c8 +! diff --git a/gnu/games/chess/gnuchess.c b/gnu/games/chess/gnuchess.c new file mode 100644 index 000000000000..ac62953678d3 --- /dev/null +++ b/gnu/games/chess/gnuchess.c @@ -0,0 +1,2307 @@ +/* + C source for CHESS + + Revision: 4-25-88 + + Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (c) 1988 John Stanback + + This file is part of CHESS. + + CHESS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the CHESS General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + CHESS, but only under the conditions described in the + CHESS General Public License. A copy of this license is + supposed to have been given to you along with CHESS so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. +*/ + + +#include +#include + +#ifdef MSDOS +#include +#include +#include +#define ttblsz 4096 +#else +#include +#include +#define ttblsz 16384 +#define huge +#endif MSDOS + +#include "move.h" + +#define neutral 2 +#define white 0 +#define black 1 +#define no_piece 0 +#define pawn 1 +#define knight 2 +#define bishop 3 +#define rook 4 +#define queen 5 +#define king 6 +#define valueP 100 +#define valueN 350 +#define valueB 355 +#define valueR 550 +#define valueQ 1100 +#define valueK 1200 +#define ctlP 0x4000 +#define ctlN 0x2800 +#define ctlB 0x1800 +#define ctlR 0x0400 +#define ctlQ 0x0200 +#define ctlK 0x0100 +#define ctlBQ 0x1200 +#define ctlRQ 0x0600 +#define ctlNN 0x2000 +#define pxx " PNBRQK" +#define qxx " pnbrqk" +#define rxx "12345678" +#define cxx "abcdefgh" +#define check 0x0001 +#define capture 0x0002 +#define draw 0x0004 +#define promote 0x0008 +#define cstlmask 0x0010 +#define epmask 0x0020 +#define exact 0x0040 +#define pwnthrt 0x0080 +#define truescore 0x0001 +#define lowerbound 0x0002 +#define upperbound 0x0004 +#define maxdepth 30 +#define true 1 +#define false 0 +#define absv(x) ((x) < 0 ? -(x) : (x)) +#if (NEWMOVE < 1) +#define taxicab(a,b) (abs(column[a]-column[b]) + abs(row[a]-row[b])) +#endif +struct leaf + { + short f,t,score,reply; + unsigned short flags; + }; +struct GameRec + { + unsigned short gmove; + short score,depth,time,piece,color; + long nodes; + }; +struct TimeControlRec + { + short moves[2]; + long clock[2]; + }; +struct BookEntry + { + struct BookEntry *next; + unsigned short *mv; + }; +struct hashval + { + unsigned long bd; + unsigned short key; + }; +struct hashentry + { + unsigned long hashbd; + unsigned short mv,flags; + short score,depth; + }; + +char mvstr1[5],mvstr2[5]; +struct leaf Tree[2000],*root; +short TrPnt[maxdepth],board[64],color[64]; +short row[64],column[64],locn[8][8],Pindex[64],svalue[64]; +short PieceList[2][16],PieceCnt[2],atak[2][64],PawnCnt[2][8]; +short castld[2],kingmoved[2],mtl[2],pmtl[2],emtl[2],hung[2]; +short c1,c2,*atk1,*atk2,*PC1,*PC2,EnemyKing; +short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither; +long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft; +long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt; +short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep; +short wking,bking,FROMsquare,TOsquare,timeout,Zscore,zwndw,xwndw,slk; +short INCscore; +short HasPawn[2],HasKnight[2],HasBishop[2],HasRook[2],HasQueen[2]; +short ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth]; +short Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth]; +struct GameRec GameList[240]; +short GameCnt,Game50,epsquare,lpost,rcptr,contempt; +short MaxSearchDepth; +struct BookEntry *Book; +struct TimeControlRec TimeControl; +short TCflag,TCmoves,TCminutes,OperatorTime; +short otherside[3]={1,0,2}; +short rank7[3]={6,1,0}; +short map[64]= + {0,1,2,3,4,5,6,7, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77}; +short unmap[120]= + {0,1,2,3,4,5,6,7,-1,-1,-1,-1,-1,-1,-1,-1, + 8,9,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1, + 16,17,18,19,20,21,22,23,-1,-1,-1,-1,-1,-1,-1,-1, + 24,25,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1, + 32,33,34,35,36,37,38,39,-1,-1,-1,-1,-1,-1,-1,-1, + 40,41,42,43,44,45,46,47,-1,-1,-1,-1,-1,-1,-1,-1, + 48,49,50,51,52,53,54,55,-1,-1,-1,-1,-1,-1,-1,-1, + 56,57,58,59,60,61,62,63}; +short Dcode[120]= + {0,1,1,1,1,1,1,1,0,0,0,0,0,0,0x0E,0x0F, + 0x10,0x11,0x12,0,0,0,0,0,0,0,0,0,0,0,0x0F,0x1F, + 0x10,0x21,0x11,0,0,0,0,0,0,0,0,0,0,0x0F,0,0, + 0x10,0,0,0x11,0,0,0,0,0,0,0,0,0x0F,0,0,0, + 0x10,0,0,0,0x11,0,0,0,0,0,0,0x0F,0,0,0,0, + 0x10,0,0,0,0,0x11,0,0,0,0,0x0F,0,0,0,0,0, + 0x10,0,0,0,0,0,0x11,0,0,0x0F,0,0,0,0,0,0, + 0x10,0,0,0,0,0,0,0x11}; +short Stboard[64]= + {rook,knight,bishop,queen,king,bishop,knight,rook, + pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn, + rook,knight,bishop,queen,king,bishop,knight,rook}; +short Stcolor[64]= + {white,white,white,white,white,white,white,white, + white,white,white,white,white,white,white,white, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + black,black,black,black,black,black,black,black, + black,black,black,black,black,black,black,black}; +short sweep[7]= {false,false,false,true,true,true,false}; +short Dpwn[3]={4,6,0}; +short Dstart[7]={6,4,8,4,0,0,0}; +short Dstop[7]={7,5,15,7,3,7,7}; +short Dir[16]={1,0x10,-1,-0x10,0x0F,0x11,-0x0F,-0x11, + 0x0E,-0x0E,0x12,-0x12,0x1F,-0x1F,0x21,-0x21}; +short Pdir[34]={0,0x38,0,0,0,0,0,0,0,0,0,0,0,0,0x02,0x35, + 0x38,0x35,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0x02, + 0,0x02}; +short pbit[7]={0,0x01,0x02,0x04,0x08,0x10,0x20}; +unsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth]; +unsigned short killr3[maxdepth],PrVar[maxdepth]; +unsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4; +unsigned short hashkey; +unsigned long hashbd; +struct hashval hashcode[2][7][64]; +struct hashentry huge *ttable,*ptbl; +unsigned char history[8192]; + +short Mwpawn[64],Mbpawn[64],Mknight[2][64],Mbishop[2][64]; +short Mking[2][64],Kfield[2][64]; +short value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK}; +short control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK}; +short PassedPawn0[8]={0,60,80,120,200,360,600,800}; +short PassedPawn1[8]={0,30,40,60,100,180,300,800}; +short PassedPawn2[8]={0,15,25,35,50,90,140,800}; +short PassedPawn3[8]={0,5,10,15,20,30,140,800}; +short ISOLANI[8] = {-12,-16,-20,-24,-24,-20,-16,-12}; +short BACKWARD[8] = {-6,-10,-15,-21,-28,-28,-28,-28}; +short BMBLTY[14] = {-2,0,2,4,6,8,10,12,13,14,15,16,16,16}; +short RMBLTY[14] = {0,2,4,6,8,10,11,12,13,14,14,14,14,14}; +short Kthreat[16] = {0,-8,-20,-36,-52,-68,-80,-80,-80,-80,-80,-80, + -80,-80,-80,-80}; +short KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK,KBNKsq; +short PEDRNK2B,PWEAKH,PADVNCM,PADVNCI,PAWNSHIELD,PDOUBLED,PBLOK; +short RHOPN,RHOPNX,KHOPN,KHOPNX,KSFTY; +short ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY,PINVAL; +short stage,stage2,Zwmtl,Zbmtl,Developed[2],PawnStorm; +short PawnBonus,BishopBonus,RookBonus; +short KingOpening[64]= + { 0, 0, -4,-10,-10, -4, 0, 0, + -4, -4, -8,-12,-12, -8, -4, -4, + -12,-16,-20,-20,-20,-20,-16,-12, + -16,-20,-24,-24,-24,-24,-20,-16, + -16,-20,-24,-24,-24,-24,-20,-16, + -12,-16,-20,-20,-20,-20,-16,-12, + -4, -4, -8,-12,-12, -8, -4, -4, + 0, 0, -4,-10,-10, -4, 0, 0}; +short KingEnding[64]= + { 0, 6,12,18,18,12, 6, 0, + 6,12,18,24,24,18,12, 6, + 12,18,24,30,30,24,18,12, + 18,24,30,36,36,30,24,18, + 18,24,30,36,36,30,24,18, + 12,18,24,30,30,24,18,12, + 6,12,18,24,24,18,12, 6, + 0, 6,12,18,18,12, 6, 0}; +short DyingKing[64]= + { 0, 8,16,24,24,16, 8, 0, + 8,32,40,48,48,40,32, 8, + 16,40,56,64,64,56,40,16, + 24,48,64,72,72,64,48,24, + 24,48,64,72,72,64,48,24, + 16,40,56,64,64,56,40,16, + 8,32,40,48,48,40,32, 8, + 0, 8,16,24,24,16, 8, 0}; +short KBNK[64]= + {99,90,80,70,60,50,40,40, + 90,80,60,50,40,30,20,40, + 80,60,40,30,20,10,30,50, + 70,50,30,10, 0,20,40,60, + 60,40,20, 0,10,30,50,70, + 50,30,10,20,30,40,60,80, + 40,20,30,40,50,60,80,90, + 40,40,50,60,70,80,90,99}; +short pknight[64]= + { 0, 4, 8,10,10, 8, 4, 0, + 4, 8,16,20,20,16, 8, 4, + 8,16,24,28,28,24,16, 8, + 10,20,28,32,32,28,20,10, + 10,20,28,32,32,28,20,10, + 8,16,24,28,28,24,16, 8, + 4, 8,16,20,20,16, 8, 4, + 0, 4, 8,10,10, 8, 4, 0}; +short pbishop[64]= + {14,14,14,14,14,14,14,14, + 14,22,18,18,18,18,22,14, + 14,18,22,22,22,22,18,14, + 14,18,22,22,22,22,18,14, + 14,18,22,22,22,22,18,14, + 14,18,22,22,22,22,18,14, + 14,22,18,18,18,18,22,14, + 14,14,14,14,14,14,14,14}; +short PawnAdvance[64]= + { 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 4, 0, 0, 4, 4, 4, + 6, 8, 2,10,10, 2, 8, 6, + 6, 8,12,16,16,12, 8, 6, + 8,12,16,24,24,16,12, 8, + 12,16,24,32,32,24,16,12, + 12,16,24,32,32,24,16,12, + 0, 0, 0, 0, 0, 0, 0, 0}; + + +main(argc,argv) +int argc; char *argv[]; +{ +#ifdef MSDOS + ttable = (struct hashentry huge *)farmalloc(ttblsz * + (unsigned long)sizeof(struct hashentry)); +#else + ttable = (struct hashentry *)malloc(ttblsz * + (unsigned long)sizeof(struct hashentry)); +#endif + Level = 0; TCflag = false; OperatorTime = 0; + if (argc == 2) Level = atoi(argv[1]); + if (argc == 3) + { + TCmoves = atoi(argv[1]); TCminutes = atoi(argv[2]); TCflag = true; + } + Initialize(); + NewGame(); +#if (NEWMOVE > 0) + Initialize_dist(); +#if (NEWMOVE > 1) + Initialize_moves(); +#endif +#endif + while (!(quit)) + { + if (bothsides && !mate) SelectMove(opponent,1); else InputCommand(); + if (!(quit || mate || force)) SelectMove(computer,1); + } + ExitChess(); +} + + + +/* ............ INTERFACE ROUTINES ........................... */ + +int VerifyMove(s,iop,mv) +char s[]; +short iop; +unsigned short *mv; + +/* + Compare the string 's' to the list of legal moves available for the + opponent. If a match is found, make the move on the board. +*/ + +{ +static short pnt,tempb,tempc,tempsf,tempst,cnt; +static struct leaf xnode; +struct leaf *node; + + *mv = 0; + if (iop == 2) + { + UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); + return(false); + } + cnt = 0; + MoveList(opponent,2); + pnt = TrPnt[2]; + while (pnt < TrPnt[3]) + { + node = &Tree[pnt++]; + algbr(node->f,node->t,(short) node->flags & cstlmask); + if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0) + { + cnt++; xnode = *node; + } + } + if (cnt == 1) + { + MakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); + if (SqAtakd(PieceList[opponent][0],computer)) + { + UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); + ShowMessage("Illegal Move!!"); + return(false); + } + else + { + if (iop == 1) return(true); + if (xnode.flags & epmask) UpdateDisplay(0,0,1,0); + else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask); + if (xnode.flags & cstlmask) Game50 = GameCnt; + else if (board[xnode.t] == pawn || (xnode.flags & capture)) + Game50 = GameCnt; + GameList[GameCnt].depth = GameList[GameCnt].score = 0; + GameList[GameCnt].nodes = 0; + ElapsedTime(1); + GameList[GameCnt].time = (short)et; + TimeControl.clock[opponent] -= et; + --TimeControl.moves[opponent]; + *mv = (xnode.f << 8) + xnode.t; + algbr(xnode.f,xnode.t,false); + return(true); + } + } + if (cnt > 1) ShowMessage("Ambiguous Move!"); + return(false); +} + + +NewGame() + +/* + Reset the board and other variables to start a new game. +*/ + +{ +short l,r,c,p; + + mate = quit = reverse = bothsides = post = false; + hashflag = force = PawnStorm = false; + beep = rcptr = easy = true; + lpost = NodeCnt = epsquare = et0 = 0; + dither = 0; + Awindow = 90; + Bwindow = 90; + xwndw = 90; + MaxSearchDepth = 29; + contempt = 0; + GameCnt = -1; Game50 = 0; + Zwmtl = Zbmtl = 0; + Developed[white] = Developed[black] = false; + castld[white] = castld[black] = false; + kingmoved[white] = kingmoved[black] = 0; + PawnThreat[0] = CptrFlag[0] = Threat[0] = false; + Pscore[0] = 12000; Tscore[0] = 12000; + opponent = white; computer = black; + for (r = 0; r < 8; r++) + for (c = 0; c < 8; c++) + { + l = 8*r+c; locn[r][c] = l; + row[l] = r; column[l] = c; + board[l] = Stboard[l]; color[l] = Stcolor[l]; + } + for (c = white; c <= black; c++) + for (p = pawn; p <= king; p++) + for (l = 0; l < 64; l++) + { + hashcode[c][p][l].key = (unsigned short)rand(); + hashcode[c][p][l].bd = ((unsigned long)rand() << 16) + + (unsigned long)rand(); + } + ClrScreen(); + if (TCflag) SetTimeControl(); + else if (Level == 0) SelectLevel(); + UpdateDisplay(0,0,1,0); + InitializeStats(); + time0 = time((long *)0); + ElapsedTime(1); + GetOpenings(); +} + + +algbr(f,t,iscastle) +short f,t,iscastle; +{ + mvstr1[0] = cxx[column[f]]; mvstr1[1] = rxx[row[f]]; + mvstr1[2] = cxx[column[t]]; mvstr1[3] = rxx[row[t]]; + mvstr2[0] = qxx[board[f]]; + mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3]; + mvstr1[4] = '\0'; mvstr2[3] = '\0'; + if (iscastle) + if (t > f) strcpy(mvstr2,"o-o"); + else strcpy(mvstr2,"o-o-o"); +} + + +/* ............ MOVE GENERATION & SEARCH ROUTINES .............. */ + +SelectMove(side,iop) +short side,iop; + +/* + Select a move by calling function search() at progressively deeper + ply until time is up or a mate or draw is reached. An alpha-beta + window of -90 to +90 points is set around the score returned from the + previous iteration. If Sdepth != 0 then the program has correctly + predicted the opponents move and the search will start at a depth of + Sdepth+1 rather than a depth of 1. +*/ + +{ +static short i,alpha,beta,score,tempb,tempc,tempsf,tempst,xside,rpt; + + timeout = false; + xside = otherside[side]; + if (iop != 2) player = side; + if (TCflag) + { + if (((TimeControl.moves[side] + 3) - OperatorTime) != 0) + ResponseTime = (TimeControl.clock[side]) / + (TimeControl.moves[side] + 3) - + OperatorTime; + else ResponseTime = 0; + ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1); + } + else ResponseTime = Level; + if (iop == 2) ResponseTime = 999; + if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft; + else if (ResponseTime < 1) ResponseTime = 1; + ExtraTime = 0; + ExaminePosition(); + ScorePosition(side,&score); + ShowSidetomove(); + + if (Sdepth == 0) + { + ZeroTTable(); + SearchStartStuff(side); + for (i = 0; i < 8192; i++) history[i] = 0; + FROMsquare = TOsquare = -1; + PV = 0; + if (iop != 2) hint = 0; + for (i = 0; i < maxdepth; i++) + PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0; + alpha = score-90; beta = score+90; + rpt = 0; + TrPnt[1] = 0; root = &Tree[0]; + MoveList(side,1); + for (i = TrPnt[1]; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1); + if (Book != NULL) OpeningBook(); + if (Book != NULL) timeout = true; + NodeCnt = ETnodes = EvalNodes = HashCnt = 0; + Zscore = 0; zwndw = 20; + } + + while (!timeout && Sdepth < MaxSearchDepth) + { + Sdepth++; + ShowDepth(' '); + score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt); + for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i]; + if (score < alpha) + { + ShowDepth('-'); + ExtraTime = 10*ResponseTime; + ZeroTTable(); + score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt); + } + if (score > beta && !(root->flags & exact)) + { + ShowDepth('+'); + ExtraTime = 0; + ZeroTTable(); + score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt); + } + score = root->score; + if (!timeout) + for (i = TrPnt[1]+1; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1); + ShowResults(score,PrVar,'.'); + for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i]; + if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0; + else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime; + else ExtraTime = 3*ResponseTime; + if (root->flags & exact) timeout = true; + if (Tree[1].score < -9000) timeout = true; + if (4*et > 2*ResponseTime + ExtraTime) timeout = true; + if (!timeout) + { + Tscore[0] = score; + if (Zscore == 0) Zscore = score; + else Zscore = (Zscore+score)/2; + } + zwndw = 20+abs(Zscore/12); + beta = score + Bwindow; + if (Zscore < score) alpha = Zscore - Awindow - zwndw; + else alpha = score - Awindow - zwndw; + } + + score = root->score; + if (rpt >= 2 || score < -12000) root->flags |= draw; + if (iop == 2) return(0); + if (Book == NULL) hint = PrVar[2]; + ElapsedTime(1); + + if (score > -9999 && rpt <= 2) + { + MakeMove(side,root,&tempb,&tempc,&tempsf,&tempst); + algbr(root->f,root->t,(short) root->flags & cstlmask); + } + else mvstr1[0] = '\0'; + OutputMove(); + if (score == -9999 || score == 9998) mate = true; + if (mate) hint = 0; + if (root->flags & cstlmask) Game50 = GameCnt; + else if (board[root->t] == pawn || (root->flags & capture)) + Game50 = GameCnt; + GameList[GameCnt].score = score; + GameList[GameCnt].nodes = NodeCnt; + GameList[GameCnt].time = (short)et; + GameList[GameCnt].depth = Sdepth; + if (TCflag) + { + TimeControl.clock[side] -= (et + OperatorTime); + if (--TimeControl.moves[side] == 0) SetTimeControl(); + } + if ((root->flags & draw) && bothsides) quit = true; + if (GameCnt > 238) quit = true; + player = xside; + Sdepth = 0; + fflush(stdin); + return(0); +} + + +OpeningBook() + +/* + Go thru each of the opening lines of play and check for a match with + the current game listing. If a match occurs, generate a random number. + If this number is the largest generated so far then the next move in + this line becomes the current "candidate". After all lines are + checked, the candidate move is put at the top of the Tree[] array and + will be played by the program. Note that the program does not handle + book transpositions. +*/ + +{ +short j,pnt; +unsigned short m,*mp; +unsigned r,r0; +struct BookEntry *p; + + srand((unsigned)time0); + r0 = m = 0; + p = Book; + while (p != NULL) + { + mp = p->mv; + for (j = 0; j <= GameCnt; j++) + if (GameList[j].gmove != *(mp++)) break; + if (j > GameCnt) + if ((r=rand()) > r0) + { + r0 = r; m = *mp; + hint = *(++mp); + } + p = p->next; + } + + for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++) + if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0; + pick(TrPnt[1],TrPnt[2]-1); + if (Tree[TrPnt[1]].score < 0) Book = NULL; +} + + +#define UpdateSearchStatus\ +{\ + if (post) ShowCurrentMove(pnt,node->f,node->t);\ + if (pnt > TrPnt[1])\ + {\ + d = best-Zscore; e = best-node->score;\ + if (best < alpha) ExtraTime = 10*ResponseTime;\ + else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\ + else if (d > -zwndw) ExtraTime = 0;\ + else if (d > -3*zwndw) ExtraTime = ResponseTime;\ + else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\ + else ExtraTime = 5*ResponseTime;\ + }\ +} + +int search(side,ply,depth,alpha,beta,bstline,rpt) +short side,ply,depth,alpha,beta,*rpt; +unsigned short bstline[]; + +/* + Perform an alpha-beta search to determine the score for the current + board position. If depth <= 0 only capturing moves, pawn promotions + and responses to check are generated and searched, otherwise all + moves are processed. The search depth is modified for check evasions, + certain re-captures and threats. Extensions may continue for up to 11 + ply beyond the nominal search depth. +*/ + +#define prune (cf && score+node->score < alpha) +#define ReCapture (rcptr && score > alpha && score < beta &&\ + ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2]) +#define MateThreat (ply < Sdepth+4 && ply > 4 &&\ + ChkFlag[ply-2] && ChkFlag[ply-4] &&\ + ChkFlag[ply-2] != ChkFlag[ply-4]) + +{ +register short j,pnt; +short best,tempb,tempc,tempsf,tempst; +short xside,pbst,d,e,cf,score,rcnt; +unsigned short mv,nxtline[maxdepth]; +struct leaf *node,tmp; + + NodeCnt++; + xside = otherside[side]; + if (depth < 0) depth = 0; + + if (ply <= Sdepth+3) repetition(rpt); else *rpt = 0; + if (*rpt >= 2) return(0); + + score = evaluate(side,xside,ply,alpha,beta); + if (score > 9000) + { + bstline[ply] = 0; + return(score); + } + + if (depth > 0) + { + if (InChk || PawnThreat[ply-1] || ReCapture) ++depth; + } + else + { + if (score >= alpha && + (InChk || PawnThreat[ply-1] || Threat[ply-1])) ++depth; + else if (score <= beta && MateThreat) ++depth; + } + + if (depth > 0 && hashflag && ply > 1) + { + ProbeTTable(side,depth,&alpha,&beta,&score); + bstline[ply] = PV; + bstline[ply+1] = 0; + if (beta == -20000) return(score); + if (alpha > beta) return(alpha); + } + + if (Sdepth == 1) d = 7; else d = 11; + if (ply > Sdepth+d || (depth < 1 && score > beta)) return(score); + + if (ply > 1) + if (depth > 0) MoveList(side,ply); + else CaptureList(side,xside,ply); + + if (TrPnt[ply] == TrPnt[ply+1]) return(score); + + cf = (depth < 1 && ply > Sdepth+1 && !ChkFlag[ply-2] && !slk); + + if (depth > 0) best = -12000; else best = score; + if (best > alpha) alpha = best; + + for (pnt = pbst = TrPnt[ply]; + pnt < TrPnt[ply+1] && best <= beta; + pnt++) + { + if (ply > 1) pick(pnt,TrPnt[ply+1]-1); + node = &Tree[pnt]; + mv = (node->f << 8) + node->t; + nxtline[ply+1] = 0; + + if (prune) break; + if (ply == 1) UpdateSearchStatus; + + if (!(node->flags & exact)) + { + MakeMove(side,node,&tempb,&tempc,&tempsf,&tempst); + CptrFlag[ply] = (node->flags & capture); + PawnThreat[ply] = (node->flags & pwnthrt); + Tscore[ply] = node->score; + PV = node->reply; + node->score = -search(xside,ply+1,depth-1,-beta,-alpha, + nxtline,&rcnt); + if (abs(node->score) > 9000) node->flags |= exact; + else if (rcnt == 1) node->score /= 2; + if (rcnt >= 2 || GameCnt-Game50 > 99 || + (node->score == 9999-ply && !ChkFlag[ply])) + { + node->flags |= draw; node->flags |= exact; + if (side == computer) node->score = contempt; + else node->score = -contempt; + } + node->reply = nxtline[ply+1]; + UnmakeMove(side,node,&tempb,&tempc,&tempsf,&tempst); + } + if (node->score > best && !timeout) + { + if (depth > 0) + if (node->score > alpha && !(node->flags & exact)) + node->score += depth; + best = node->score; pbst = pnt; + if (best > alpha) alpha = best; + for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j]; + bstline[j] = 0; + bstline[ply] = mv; + if (ply == 1) + { + if (best == alpha) + { + tmp = Tree[pnt]; + for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j]; + Tree[0] = tmp; + pbst = 0; + } + if (Sdepth > 2) + if (best > beta) ShowResults(best,bstline,'+'); + else if (best < alpha) ShowResults(best,bstline,'-'); + else ShowResults(best,bstline,'&'); + } + } + if (NodeCnt > ETnodes) ElapsedTime(0); + if (timeout) return(-Tscore[ply-1]); + } + + node = &Tree[pbst]; + mv = (node->f<<8) + node->t; + if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha) + PutInTTable(side,best,depth,alpha,beta,mv); + if (depth > 0) + { + j = (node->f<<6) + node->t; if (side == black) j |= 0x1000; + if (history[j] < 150) history[j] += 2*depth; + if (node->t != (GameList[GameCnt].gmove & 0xFF)) + if (best <= beta) killr3[ply] = mv; + else if (mv != killr1[ply]) + { + killr2[ply] = killr1[ply]; + killr1[ply] = mv; + } + if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0; + } + return(best); +} + + +evaluate(side,xside,ply,alpha,beta) +short side,xside,ply,alpha,beta; + +/* + Compute an estimate of the score by adding the positional score from + the previous ply to the material difference. If this score falls + inside a window which is 180 points wider than the alpha-beta window + (or within a 50 point window during quiescence search) call + ScorePosition() to determine a score, otherwise return the estimated + score. If one side has only a king and the other either has no pawns + or no pieces then the function ScoreLoneKing() is called. +*/ + +{ +short s,evflag; + + hung[white] = hung[black] = 0; + slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) || + (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0))); + s = -Pscore[ply-1] + mtl[side] - mtl[xside]; + s -= INCscore; + + if (slk) evflag = false; + else evflag = + (ply == 1 || ply < Sdepth || + ((ply == Sdepth+1 || ply == Sdepth+2) && + (s > alpha-xwndw && s < beta+xwndw)) || + (ply > Sdepth+2 && s >= alpha-25 && s <= beta+25)); + + if (evflag) + { + EvalNodes++; + ataks(side,atak[side]); + if (atak[side][PieceList[xside][0]] > 0) return(10001-ply); + ataks(xside,atak[xside]); + InChk = (atak[xside][PieceList[side][0]] > 0); + ScorePosition(side,&s); + } + else + { + if (SqAtakd(PieceList[xside][0],side)) return(10001-ply); + InChk = SqAtakd(PieceList[side][0],xside); + if (slk) ScoreLoneKing(side,&s); + } + + Pscore[ply] = s - mtl[side] + mtl[xside]; + if (InChk) ChkFlag[ply-1] = Pindex[TOsquare]; + else ChkFlag[ply-1] = 0; + Threat[ply-1] = (hung[side] > 1 && ply == Sdepth+1); + return(s); +} + + +ProbeTTable(side,depth,alpha,beta,score) +short side,depth,*alpha,*beta,*score; + +/* + Look for the current board position in the transposition table. +*/ + +{ +short hindx; + if (side == white) hashkey |= 1; else hashkey &= 0xFFFE; + hindx = (hashkey & (ttblsz-1)); + ptbl = (ttable + hindx); + if (ptbl->depth >= depth && ptbl->hashbd == hashbd) + { + HashCnt++; + PV = ptbl->mv; + if (ptbl->flags & truescore) + { + *score = ptbl->score; + *beta = -20000; + return(true); + } +/* + else if (ptbl->flags & upperbound) + { + if (ptbl->score < *beta) *beta = ptbl->score+1; + } +*/ + else if (ptbl->flags & lowerbound) + { + if (ptbl->score > *alpha) *alpha = ptbl->score-1; + } + } + return(false); +} + + +PutInTTable(side,score,depth,alpha,beta,mv) +short side,score,depth,alpha,beta; +unsigned short mv; + +/* + Store the current board position in the transposition table. +*/ + +{ +short hindx; + if (side == white) hashkey |= 1; else hashkey &= 0xFFFE; + hindx = (hashkey & (ttblsz-1)); + ptbl = (ttable + hindx); + ptbl->hashbd = hashbd; + ptbl->depth = depth; + ptbl->score = score; + ptbl->mv = mv; + ptbl->flags = 0; + if (score < alpha) ptbl->flags |= upperbound; + else if (score > beta) ptbl->flags |= lowerbound; + else ptbl->flags |= truescore; +} + + +ZeroTTable() +{ +int i; + if (hashflag) + for (i = 0; i < ttblsz; i++) + { + ptbl = (ttable + i); + ptbl->depth = 0; + } +} + + +MoveList(side,ply) +short side,ply; + +/* + Fill the array Tree[] with all available moves for side to play. Array + TrPnt[ply] contains the index into Tree[] of the first move at a ply. +*/ + +{ +register short i; +short xside,f; + + xside = otherside[side]; + if (PV == 0) Swag0 = killr0[ply]; else Swag0 = PV; + Swag1 = killr1[ply]; Swag2 = killr2[ply]; + Swag3 = killr3[ply]; Swag4 = 0; + if (ply > 2) Swag4 = killr1[ply-2]; + TrPnt[ply+1] = TrPnt[ply]; + Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; + for (i = PieceCnt[side]; i >= 0; i--) + GenMoves(ply,PieceList[side][i],side,xside); + if (kingmoved[side] == 0 && !castld[side]) + { + f = PieceList[side][0]; + if (castle(side,f,f+2,0)) + { + LinkMove(ply,f,f+2,xside); + Tree[TrPnt[ply+1]-1].flags |= cstlmask; + } + if (castle(side,f,f-2,0)) + { + LinkMove(ply,f,f-2,xside); + Tree[TrPnt[ply+1]-1].flags |= cstlmask; + } + } +} + +#if (NEWMOVE < 11) +GenMoves(ply,sq,side,xside) +short ply,sq,side,xside; + +/* + Generate moves for a piece. The from square is mapped onto a special + board and offsets (taken from array Dir[]) are added to the mapped + location. The newly generated square is tested to see if it falls off + the board by ANDing the square with 88 HEX. Legal moves are linked + into the tree. +*/ + +{ +register short m,u,d; +short i,m0,piece; + + piece = board[sq]; m0 = map[sq]; + if (sweep[piece]) + for (i = Dstart[piece]; i <= Dstop[piece]; i++) + { + d = Dir[i]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; + if (color[u] == neutral) + { + LinkMove(ply,sq,u,xside); + m += d; + } + else if (color[u] == xside) + { + LinkMove(ply,sq,u,xside); + break; + } + else break; + } + } + else if (piece == pawn) + { + if (side == white && color[sq+8] == neutral) + { + LinkMove(ply,sq,sq+8,xside); + if (row[sq] == 1) + if (color[sq+16] == neutral) + LinkMove(ply,sq,sq+16,xside); + } + else if (side == black && color[sq-8] == neutral) + { + LinkMove(ply,sq,sq-8,xside); + if (row[sq] == 6) + if (color[sq-16] == neutral) + LinkMove(ply,sq,sq-16,xside); + } + for (i = Dstart[piece]; i <= Dstop[piece]; i++) + if (!((m = m0+Dir[i]) & 0x88)) + { + u = unmap[m]; + if (color[u] == xside || u == epsquare) + LinkMove(ply,sq,u,xside); + } + } + else + { + for (i = Dstart[piece]; i <= Dstop[piece]; i++) + if (!((m = m0+Dir[i]) & 0x88)) + { + u = unmap[m]; + if (color[u] != side) LinkMove(ply,sq,u,xside); + } + } +} +#endif + +LinkMove(ply,f,t,xside) +short ply,f,t,xside; + +/* + Add a move to the tree. Assign a bonus to order the moves + as follows: + 1. Principle variation + 2. Capture of last moved piece + 3. Other captures (major pieces first) + 4. Killer moves + 5. "history" killers +*/ + +{ +register short s,z; +unsigned short mv; +struct leaf *node; + + node = &Tree[TrPnt[ply+1]]; + ++TrPnt[ply+1]; + node->flags = node->reply = 0; + node->f = f; node->t = t; + mv = (f<<8) + t; + s = 0; + if (mv == Swag0) s = 2000; + else if (mv == Swag1) s = 60; + else if (mv == Swag2) s = 50; + else if (mv == Swag3) s = 40; + else if (mv == Swag4) s = 30; + if (color[t] != neutral) + { + node->flags |= capture; + if (t == TOsquare) s += 500; + s += value[board[t]] - board[f]; + } + if (board[f] == pawn) + if (row[t] == 0 || row[t] == 7) + { + node->flags |= promote; + s += 800; + } + else if (row[t] == 1 || row[t] == 6) + { + node->flags |= pwnthrt; + s += 600; + } + else if (t == epsquare) node->flags |= epmask; + z = (f<<6) + t; if (xside == white) z |= 0x1000; + s += history[z]; + node->score = s - 20000; +} + +#if (NEWMOVE < 10) +CaptureList(side,xside,ply) +short side,xside,ply; + +/* + Generate captures and Pawn promotions only. +*/ + +#define LinkCapture\ +{\ + node->f = sq; node->t = u;\ + node->reply = 0;\ + node->flags = capture;\ + node->score = value[board[u]] + svalue[board[u]] - piece;\ + if (piece == pawn && (u < 8 || u > 55))\ + {\ + node->flags |= promote;\ + node->score = valueQ;\ + }\ + ++node;\ + ++TrPnt[ply+1];\ +} + +{ +register short m,u; +short d,sq,i,j,j1,j2,m0,r7,d0,piece,*PL; +struct leaf *node; + + TrPnt[ply+1] = TrPnt[ply]; + node = &Tree[TrPnt[ply]]; + Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; + if (side == white) + { + r7 = 6; d0 = 8; + } + else + { + r7 = 1; d0 = -8; + } + PL = PieceList[side]; + for (i = 0; i <= PieceCnt[side]; i++) + { + sq = PL[i]; + m0 = map[sq]; piece = board[sq]; + j1 = Dstart[piece]; j2 = Dstop[piece]; + if (sweep[piece]) + for (j = j1; j <= j2; j++) + { + d = Dir[j]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; + if (color[u] == neutral) m += d; + else + { + if (color[u] == xside) LinkCapture; + break; + } + } + } + else + { + for (j = j1; j <= j2; j++) + if (!((m = m0+Dir[j]) & 0x88)) + { + u = unmap[m]; + if (color[u] == xside) LinkCapture; + } + if (piece == pawn && row[sq] == r7) + { + u = sq+d0; + if (color[u] == neutral) LinkCapture; + } + } + } +} +#endif + +int castle(side,kf,kt,iop) +short side,kf,kt,iop; + +/* + Make or Unmake a castling move. +*/ + +{ +short rf,rt,d,t0,xside; + + xside = otherside[side]; + if (kt > kf) + { + rf = kf+3; rt = kt-1; d = 1; + } + else + { + rf = kf-4; rt = kt+1; d = -1; + } + if (iop == 0) + { + if (board[kf] != king || board[rf] != rook || color[rf] != side) + return(false); + if (color[kt] != neutral || color[rt] != neutral) return(false); + if (d == -1 && color[kt+d] != neutral) return(false); + if (SqAtakd(kf,xside)) return(false); + if (SqAtakd(kt,xside)) return(false); + if (SqAtakd(kf+d,xside)) return(false); + } + else + { + if (iop == 1) castld[side] = true; else castld[side] = false; + if (iop == 2) + { + t0 = kt; kt = kf; kf = t0; + t0 = rt; rt = rf; rf = t0; + } + board[kt] = king; color[kt] = side; Pindex[kt] = 0; + board[kf] = no_piece; color[kf] = neutral; + board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf]; + board[rf] = no_piece; color[rf] = neutral; + PieceList[side][Pindex[kt]] = kt; + PieceList[side][Pindex[rt]] = rt; + if (hashflag) + { + UpdateHashbd(side,king,kf,kt); + UpdateHashbd(side,rook,rf,rt); + } + } + return(true); +} + + +EnPassant(xside,f,t,iop) +short xside,f,t,iop; + +/* + Make or unmake an en passant move. +*/ + +{ +short l; + if (t > f) l = t-8; else l = t+8; + if (iop == 1) + { + board[l] = no_piece; color[l] = neutral; + } + else + { + board[l] = pawn; color[l] = xside; + } + InitializeStats(); +} + + +MakeMove(side,node,tempb,tempc,tempsf,tempst) +short side,*tempc,*tempb,*tempsf,*tempst; +struct leaf *node; + +/* + Update Arrays board[], color[], and Pindex[] to reflect the new board + position obtained after making the move pointed to by node. Also + update miscellaneous stuff that changes when a move is made. +*/ + +{ +register short f,t; +short xside,ct,cf; + + xside = otherside[side]; + f = node->f; t = node->t; epsquare = -1; + FROMsquare = f; TOsquare = t; + INCscore = 0; + GameList[++GameCnt].gmove = (f<<8) + t; + if (node->flags & cstlmask) + { + GameList[GameCnt].piece = no_piece; + GameList[GameCnt].color = side; + castle(side,f,t,1); + } + else + { + *tempc = color[t]; *tempb = board[t]; + *tempsf = svalue[f]; *tempst = svalue[t]; + GameList[GameCnt].piece = *tempb; + GameList[GameCnt].color = *tempc; + if (*tempc != neutral) + { + UpdatePieceList(*tempc,t,1); + if (*tempb == pawn) --PawnCnt[*tempc][column[t]]; + if (board[f] == pawn) + { + --PawnCnt[side][column[f]]; + ++PawnCnt[side][column[t]]; + cf = column[f]; ct = column[t]; + if (PawnCnt[side][ct] > 1+PawnCnt[side][cf]) + INCscore -= 15; + else if (PawnCnt[side][ct] < 1+PawnCnt[side][cf]) + INCscore += 15; + else if (ct == 0 || ct == 7 || PawnCnt[side][ct+ct-cf] == 0) + INCscore -= 15; + } + mtl[xside] -= value[*tempb]; + if (*tempb == pawn) pmtl[xside] -= valueP; + if (hashflag) UpdateHashbd(xside,*tempb,-1,t); + INCscore += *tempst; + } + color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f]; + Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t; + color[f] = neutral; board[f] = no_piece; + if (board[t] == pawn) + if (t-f == 16) epsquare = f+8; + else if (f-t == 16) epsquare = f-8; + if (node->flags & promote) + { + board[t] = queen; + --PawnCnt[side][column[t]]; + mtl[side] += valueQ - valueP; + pmtl[side] -= valueP; + HasQueen[side] = true; + if (hashflag) + { + UpdateHashbd(side,pawn,f,-1); + UpdateHashbd(side,queen,f,-1); + } + INCscore -= *tempsf; + } + if (board[t] == king) ++kingmoved[side]; + if (node->flags & epmask) EnPassant(xside,f,t,1); + else if (hashflag) UpdateHashbd(side,board[t],f,t); + } +} + + +UnmakeMove(side,node,tempb,tempc,tempsf,tempst) +short side,*tempc,*tempb,*tempsf,*tempst; +struct leaf *node; + +/* + Take back a move. +*/ + +{ +register short f,t; +short xside; + + xside = otherside[side]; + f = node->f; t = node->t; epsquare = -1; + GameCnt--; + if (node->flags & cstlmask) castle(side,f,t,2); + else + { + color[f] = color[t]; board[f] = board[t]; svalue[f] = *tempsf; + Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f; + color[t] = *tempc; board[t] = *tempb; svalue[t] = *tempst; + if (node->flags & promote) + { + board[f] = pawn; + ++PawnCnt[side][column[t]]; + mtl[side] += valueP - valueQ; + pmtl[side] += valueP; + if (hashflag) + { + UpdateHashbd(side,queen,-1,t); + UpdateHashbd(side,pawn,-1,t); + } + } + if (*tempc != neutral) + { + UpdatePieceList(*tempc,t,2); + if (*tempb == pawn) ++PawnCnt[*tempc][column[t]]; + if (board[f] == pawn) + { + --PawnCnt[side][column[t]]; + ++PawnCnt[side][column[f]]; + } + mtl[xside] += value[*tempb]; + if (*tempb == pawn) pmtl[xside] += valueP; + if (hashflag) UpdateHashbd(xside,*tempb,-1,t); + } + if (board[f] == king) --kingmoved[side]; + if (node->flags & epmask) EnPassant(xside,f,t,2); + else if (hashflag) UpdateHashbd(side,board[f],f,t); + } +} + + +UpdateHashbd(side,piece,f,t) +short side,piece,f,t; + +/* + hashbd contains a 32 bit "signature" of the board position. hashkey + contains a 16 bit code used to address the hash table. When a move is + made, XOR'ing the hashcode of moved piece on the from and to squares + with the hashbd and hashkey values keeps things current. +*/ + +{ + if (f >= 0) + { + hashbd ^= hashcode[side][piece][f].bd; + hashkey ^= hashcode[side][piece][f].key; + } + if (t >= 0) + { + hashbd ^= hashcode[side][piece][t].bd; + hashkey ^= hashcode[side][piece][t].key; + } +} + + +UpdatePieceList(side,sq,iop) +short side,sq,iop; + +/* + Update the PieceList and Pindex arrays when a piece is captured or + when a capture is unmade. +*/ + +{ +register short i; + if (iop == 1) + { + PieceCnt[side]--; + for (i = Pindex[sq]; i <= PieceCnt[side]; i++) + { + PieceList[side][i] = PieceList[side][i+1]; + Pindex[PieceList[side][i]] = i; + } + } + else + { + PieceCnt[side]++; + PieceList[side][PieceCnt[side]] = sq; + Pindex[sq] = PieceCnt[side]; + } +} + + +InitializeStats() + +/* + Scan thru the board seeing what's on each square. If a piece is found, + update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also + determine the material for each side and set the hashkey and hashbd + variables to represent the current board position. Array + PieceList[side][indx] contains the location of all the pieces of + either side. Array Pindex[sq] contains the indx into PieceList for a + given square. +*/ + +{ +register short i,sq; + epsquare = -1; + for (i = 0; i < 8; i++) + PawnCnt[white][i] = PawnCnt[black][i] = 0; + mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0; + PieceCnt[white] = PieceCnt[black] = 0; + hashbd = hashkey = 0; + for (sq = 0; sq < 64; sq++) + if (color[sq] != neutral) + { + mtl[color[sq]] += value[board[sq]]; + if (board[sq] == pawn) + { + pmtl[color[sq]] += valueP; + ++PawnCnt[color[sq]][column[sq]]; + } + if (board[sq] == king) Pindex[sq] = 0; + else Pindex[sq] = ++PieceCnt[color[sq]]; + PieceList[color[sq]][Pindex[sq]] = sq; + hashbd ^= hashcode[color[sq]][board[sq]][sq].bd; + hashkey ^= hashcode[color[sq]][board[sq]][sq].key; + } +} + + +pick(p1,p2) +short p1,p2; + +/* + Find the best move in the tree between indexes p1 and p2. Swap the + best move into the p1 element. +*/ + +{ +register short p,s; +short p0,s0; +struct leaf temp; + + s0 = Tree[p1].score; p0 = p1; + for (p = p1+1; p <= p2; p++) + if ((s = Tree[p].score) > s0) + { + s0 = s; p0 = p; + } + if (p0 != p1) + { + temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp; + } +} + + +repetition(cnt) +short *cnt; + +/* + Check for draw by threefold repetition. +*/ + +{ +register short i,c; +short f,t,b[64]; +unsigned short m; + *cnt = c = 0; + if (GameCnt > Game50+3) + { +/* + memset((char *)b,0,64*sizeof(short)); +*/ + for (i = 0; i < 64; b[i++] = 0); + for (i = GameCnt; i > Game50; i--) + { + m = GameList[i].gmove; f = m>>8; t = m & 0xFF; + if (++b[f] == 0) c--; else c++; + if (--b[t] == 0) c--; else c++; + if (c == 0) (*cnt)++; + } + } +} + +#if (NEWMOVE < 3) +int SqAtakd(sq,side) +short sq,side; + +/* + See if any piece with color 'side' ataks sq. First check for pawns + or king, then try other pieces. Array Dcode is used to check for + knight attacks or R,B,Q co-linearity. +*/ + +{ +register short m,d; +short i,m0,m1,loc,piece,*PL; + + m1 = map[sq]; + if (side == white) m = m1-0x0F; else m = m1+0x0F; + if (!(m & 0x88)) + if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true); + if (side == white) m = m1-0x11; else m = m1+0x11; + if (!(m & 0x88)) + if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true); + if (distance(sq,PieceList[side][0]) == 1) return(true); + + PL = PieceList[side]; + for (i = 1; i <= PieceCnt[side]; i++) + { + loc = PL[i]; piece = board[loc]; + if (piece == pawn) continue; + m0 = map[loc]; d = Dcode[abs(m1-m0)]; + if (d == 0 || (Pdir[d] & pbit[piece]) == 0) continue; + if (piece == knight) return(true); + else + { + if (m1 < m0) d = -d; + for (m = m0+d; m != m1; m += d) + if (color[unmap[m]] != neutral) break; + if (m == m1) return(true); + } + } + return(false); +} +#endif + +#if (NEWMOVE < 2) +ataks(side,a) +short side,*a; + +/* + Fill array atak[][] with info about ataks to a square. Bits 8-15 + are set if the piece (king..pawn) ataks the square. Bits 0-7 + contain a count of total ataks to the square. +*/ + +{ +register short u,m; +short d,c,j,j1,j2,piece,i,m0,sq,*PL; + +/* + memset((char *)a,0,64*sizeof(short)); +*/ + for (u = 0; u < 64; a[u++] = 0); + Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1; + PL = PieceList[side]; + for (i = 0; i <= PieceCnt[side]; i++) + { + sq = PL[i]; + m0 = map[sq]; + piece = board[sq]; + c = control[piece]; j1 = Dstart[piece]; j2 = Dstop[piece]; + if (sweep[piece]) + for (j = j1; j <= j2; j++) + { + d = Dir[j]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; + a[u] = ++a[u] | c; + if (color[u] == neutral) m += d; + else break; + } + } + else + for (j = j1; j <= j2; j++) + if (!((m = m0+Dir[j]) & 0x88)) + { + u = unmap[m]; + a[u] = ++a[u] | c; + } + } +} +#endif + +/* ............ POSITIONAL EVALUATION ROUTINES ............ */ + +ScorePosition(side,score) +short side,*score; + +/* + Perform normal static evaluation of board position. A score is + generated for each piece and these are summed to get a score for each + side. +*/ + +{ +register short sq,s; +short i,xside,pscore[3]; + + wking = PieceList[white][0]; bking = PieceList[black][0]; + UpdateWeights(); + xside = otherside[side]; + pscore[white] = pscore[black] = 0; + + for (c1 = white; c1 <= black; c1++) + { + c2 = otherside[c1]; + if (c1 == white) EnemyKing = bking; else EnemyKing = wking; + atk1 = atak[c1]; atk2 = atak[c2]; + PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; + for (i = 0; i <= PieceCnt[c1]; i++) + { + sq = PieceList[c1][i]; + s = SqValue(sq,side); + pscore[c1] += s; + svalue[sq] = s; + } + } + if (hung[side] > 1) pscore[side] += HUNGX; + if (hung[xside] > 1) pscore[xside] += HUNGX; + + *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10; + if (dither) *score += rand() % dither; + + if (*score > 0 && pmtl[side] == 0) + if (emtl[side] < valueR) *score = 0; + else if (*score < valueR) *score /= 2; + if (*score < 0 && pmtl[xside] == 0) + if (emtl[xside] < valueR) *score = 0; + else if (-*score < valueR) *score /= 2; + + if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200; + if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200; +} + + +ScoreLoneKing(side,score) +short side,*score; + +/* + Static evaluation when loser has only a king and winner has no pawns + or no pieces. +*/ + +{ +short winner,loser,king1,king2,s,i; + + UpdateWeights(); + if (mtl[white] > mtl[black]) winner = white; else winner = black; + loser = otherside[winner]; + king1 = PieceList[winner][0]; king2 = PieceList[loser][0]; + + s = 0; + + if (pmtl[winner] > 0) + for (i = 1; i <= PieceCnt[winner]; i++) + s += ScoreKPK(side,winner,loser,king1,king2,PieceList[winner][i]); + + else if (emtl[winner] == valueB+valueN) + s = ScoreKBNK(winner,king1,king2); + + else if (emtl[winner] > valueB) + s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2); + + if (side == winner) *score = s; else *score = -s; +} + + +int ScoreKPK(side,winner,loser,king1,king2,sq) +short side,winner,loser,king1,king2,sq; + +/* + Score King and Pawns versus King endings. +*/ + +{ +short s,r; + + if (PieceCnt[winner] == 1) s = 50; else s = 120; + if (winner == white) + { + if (side == loser) r = row[sq]-1; else r = row[sq]; + if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq]; + else s = 500+50*row[sq]; + if (row[sq] < 6) sq += 16; else sq += 8; + } + else + { + if (side == loser) r = row[sq]+1; else r = row[sq]; + if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]); + else s = 500+50*(7-row[sq]); + if (row[sq] > 1) sq -= 16; else sq -= 8; + } + s += 8*(taxicab(king2,sq) - taxicab(king1,sq)); + return(s); +} + + +int ScoreKBNK(winner,king1,king2) +short winner,king1,king2; + +/* + Score King+Bishop+Knight versus King endings. + This doesn't work all that well but it's better than nothing. +*/ + +{ +short s; + s = emtl[winner] - 300; + if (KBNKsq == 0) s += KBNK[king2]; + else s += KBNK[locn[row[king2]][7-column[king2]]]; + s -= taxicab(king1,king2); + s -= distance(PieceList[winner][1],king2); + s -= distance(PieceList[winner][2],king2); + return(s); +} + + +SqValue(sq,side) +short sq,side; + +/* + Calculate the positional value for the piece on 'sq'. +*/ + +{ +register short j,fyle,rank; +short s,piece,a1,a2,in_square,r,mob,e,c; + + piece = board[sq]; + a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF); + rank = row[sq]; fyle = column[sq]; + s = 0; + if (piece == pawn && c1 == white) + { + s = Mwpawn[sq]; + if (sq == 11 || sq == 12) + if (color[sq+8] != neutral) s += PEDRNK2B; + if ((fyle == 0 || PC1[fyle-1] == 0) && + (fyle == 7 || PC1[fyle+1] == 0)) + s += ISOLANI[fyle]; + else if (PC1[fyle] > 1) s += PDOUBLED; + if (a1 < ctlP && atk1[sq+8] < ctlP) + { + s += BACKWARD[a2 & 0xFF]; + if (PC2[fyle] == 0) s += PWEAKH; + if (color[sq+8] != neutral) s += PBLOK; + } + if (PC2[fyle] == 0) + { + if (side == black) r = rank-1; else r = rank; + in_square = (row[bking] >= r && distance(sq,bking) < 8-r); + if (a2 == 0 || side == white) e = 0; else e = 1; + for (j = sq+8; j < 64; j += 8) + if (atk2[j] >= ctlP) { e = 2; break; } + else if (atk2[j] > 0 || color[j] != neutral) e = 1; + if (e == 2) s += (stage*PassedPawn3[rank]) / 10; + else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10; + else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10; + else s += PassedPawn0[rank]; + } + } + else if (piece == pawn && c1 == black) + { + s = Mbpawn[sq]; + if (sq == 51 || sq == 52) + if (color[sq-8] != neutral) s += PEDRNK2B; + if ((fyle == 0 || PC1[fyle-1] == 0) && + (fyle == 7 || PC1[fyle+1] == 0)) + s += ISOLANI[fyle]; + else if (PC1[fyle] > 1) s += PDOUBLED; + if (a1 < ctlP && atk1[sq-8] < ctlP) + { + s += BACKWARD[a2 & 0xFF]; + if (PC2[fyle] == 0) s += PWEAKH; + if (color[sq-8] != neutral) s += PBLOK; + } + if (PC2[fyle] == 0) + { + if (side == white) r = rank+1; else r = rank; + in_square = (row[wking] <= r && distance(sq,wking) < r+1); + if (a2 == 0 || side == black) e = 0; else e = 1; + for (j = sq-8; j >= 0; j -= 8) + if (atk2[j] >= ctlP) { e = 2; break; } + else if (atk2[j] > 0 || color[j] != neutral) e = 1; + if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10; + else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10; + else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10; + else s += PassedPawn0[7-rank]; + } + } + else if (piece == knight) + { + s = Mknight[c1][sq]; + } + else if (piece == bishop) + { + s = Mbishop[c1][sq]; + BRscan(sq,&s,&mob); + s += BMBLTY[mob]; + } + else if (piece == rook) + { + s += RookBonus; + BRscan(sq,&s,&mob); + s += RMBLTY[mob]; + if (PC1[fyle] == 0) s += RHOPN; + if (PC2[fyle] == 0) s += RHOPNX; + if (rank == rank7[c1] && pmtl[c2] > 100) s += 10; + if (stage > 2) s += 14 - taxicab(sq,EnemyKing); + } + else if (piece == queen) + { + if (stage > 2) s += 14 - taxicab(sq,EnemyKing); + if (distance(sq,EnemyKing) < 3) s += 12; + } + else if (piece == king) + { + s = Mking[c1][sq]; + if (KSFTY > 0) + if (Developed[c2] || stage > 0) KingScan(sq,&s); + if (castld[c1]) s += KCASTLD; + else if (kingmoved[c1]) s += KMOVD; + + if (PC1[fyle] == 0) s += KHOPN; + if (PC2[fyle] == 0) s += KHOPNX; + if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7) + { + if (PC1[fyle-1] == 0) s += KHOPN; + if (PC2[fyle-1] == 0) s += KHOPNX; + } + if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0) + { + if (PC1[fyle+1] == 0) s += KHOPN; + if (PC2[fyle+1] == 0) s += KHOPNX; + } + if (fyle == 2) + { + if (PC1[0] == 0) s += KHOPN; + if (PC2[0] == 0) s += KHOPNX; + } + if (fyle == 5) + { + if (PC1[7] == 0) s += KHOPN; + if (PC2[7] == 0) s += KHOPNX; + } + } + + if (a2 > 0) + { + c = (control[piece] & 0x4FFF); + if (a1 == 0 || a2 > c+1) + { + s += HUNGP; + ++hung[c1]; + if (piece != king && trapped(sq,piece)) ++hung[c1]; + } + else if (piece != pawn || a2 > a1) + if (a2 >= c || a1 < ctlP) s += ATAKD; + } + return(s); +} + +#if (NEWMOVE > 6) +KingScan(sq,s) +short sq,*s; + +/* + Assign penalties if king can be threatened by checks, if squares + near the king are controlled by the enemy (especially the queen), + or if there are no pawns near the king. +*/ + +#define ScoreThreat\ + if (color[u] != c2)\ + if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\ + else *s -= 3 + +{ +register short m,u; +short d,i,m0,cnt,ok; + + cnt = 0; + m0 = map[sq]; + if (HasBishop[c2] || HasQueen[c2]) + for (i = Dstart[bishop]; i <= Dstop[bishop]; i++) + { + d = Dir[i]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; + if (atk2[u] & ctlBQ) ScoreThreat; + if (color[u] != neutral) break; + m += d; + } + } + if (HasRook[c2] || HasQueen[c2]) + for (i = Dstart[rook]; i <= Dstop[rook]; i++) + { + d = Dir[i]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; + if (atk2[u] & ctlRQ) ScoreThreat; + if (color[u] != neutral) break; + m += d; + } + } + if (HasKnight[c2]) + for (i = Dstart[knight]; i <= Dstop[knight]; i++) + if (!((m = m0+Dir[i]) & 0x88)) + { + u = unmap[m]; + if (atk2[u] & ctlNN) ScoreThreat; + } + *s += (KSFTY*Kthreat[cnt]) / 16; + + cnt = 0; ok = false; + m0 = map[sq]; + for (i = Dstart[king]; i <= Dstop[king]; i++) + if (!((m = m0+Dir[i]) & 0x88)) + { + u = unmap[m]; + if (board[u] == pawn) ok = true; + if (atk2[u] > atk1[u]) + { + ++cnt; + if (atk2[u] & ctlQ) + if (atk2[u] > ctlQ+1 && atk1[u] < ctlQ) *s -= 4*KSFTY; + } + } + if (!ok) *s -= KSFTY; + if (cnt > 1) *s -= KSFTY; +} +#endif + +#if (NEWMOVE < 4) +BRscan(sq,s,mob) +short sq,*s,*mob; + +/* + Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the + hung[] array if a pin is found. +*/ + +{ +register short m,u; +short d,j,m0,piece,pin,*Kf; + + Kf = Kfield[c1]; + *mob = 0; + m0 = map[sq]; piece = board[sq]; + for (j = Dstart[piece]; j <= Dstop[piece]; j++) + { + pin = -1; + d = Dir[j]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; *s += Kf[u]; + if (color[u] == neutral) + { + (*mob)++; + m += d; + } + else if (pin < 0) + { + if (board[u] == pawn || board[u] == king) break; + pin = u; + m += d; + } + else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0)) + { + if (color[pin] == c2) + { + *s += PINVAL; + if (atk2[pin] == 0 || + atk1[pin] > control[board[pin]]+1) + ++hung[c2]; + } + else *s += XRAY; + break; + } + else break; + } + } +} +#endif + +#if (NEWMOVE > 5) +int trapped(sq,piece) +short sq,piece; + +/* + See if the attacked piece has unattacked squares to move to. +*/ + +{ +register short u,m,d; +short i,m0; + + m0 = map[sq]; + if (sweep[piece]) + for (i = Dstart[piece]; i <= Dstop[piece]; i++) + { + d = Dir[i]; m = m0+d; + while (!(m & 0x88)) + { + u = unmap[m]; + if (color[u] == c1) break; + if (atk2[u] == 0 || board[u] >= piece) return(false); + if (color[u] == c2) break; + m += d; + } + } + else if (piece == pawn) + { + if (c1 == white) u = sq+8; else u = sq-8; + if (color[u] == neutral && atk1[u] >= atk2[u]) + return(false); + if (!((m = m0+Dir[Dpwn[c1]]) & 0x88)) + if (color[unmap[m]] == c2) return(false); + if (!((m = m0+Dir[Dpwn[c1]+1]) & 0x88)) + if (color[unmap[m]] == c2) return(false); + } + else + { + for (i = Dstart[piece]; i <= Dstop[piece]; i++) + if (!((m = m0+Dir[i]) & 0x88)) + { + u = unmap[m]; + if (color[u] != c1) + if (atk2[u] == 0 || board[u] >= piece) return(false); + } + } + return(true); +} +#endif + +ExaminePosition() + +/* + This is done one time before the search is started. Set up arrays + Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the + SqValue() function to determine the positional value of each piece. +*/ + +{ +register short i,sq; +short wpadv,bpadv,wstrong,bstrong,z,side,pp,j,val,Pd,fyle,rank; + + wking = PieceList[white][0]; bking = PieceList[black][0]; + ataks(white,atak[white]); ataks(black,atak[black]); + Zwmtl = Zbmtl = 0; + UpdateWeights(); + HasPawn[white] = HasPawn[black] = 0; + HasKnight[white] = HasKnight[black] = 0; + HasBishop[white] = HasBishop[black] = 0; + HasRook[white] = HasRook[black] = 0; + HasQueen[white] = HasQueen[black] = 0; + for (side = white; side <= black; side++) + for (i = 0; i <= PieceCnt[side]; i++) + switch (board[PieceList[side][i]]) + { + case pawn : ++HasPawn[side]; break; + case knight : ++HasKnight[side]; break; + case bishop : ++HasBishop[side]; break; + case rook : ++HasRook[side]; break; + case queen : ++HasQueen[side]; break; + } + if (!Developed[white]) + Developed[white] = (board[1] != knight && board[2] != bishop && + board[5] != bishop && board[6] != knight); + if (!Developed[black]) + Developed[black] = (board[57] != knight && board[58] != bishop && + board[61] != bishop && board[62] != knight); + if (!PawnStorm && stage < 5) + PawnStorm = ((column[wking] < 3 && column[bking] > 4) || + (column[wking] > 4 && column[bking] < 3)); + + CopyBoard(pknight,Mknight[white]); + CopyBoard(pknight,Mknight[black]); + CopyBoard(pbishop,Mbishop[white]); + CopyBoard(pbishop,Mbishop[black]); + BlendBoard(KingOpening,KingEnding,Mking[white]); + BlendBoard(KingOpening,KingEnding,Mking[black]); + + for (sq = 0; sq < 64; sq++) + { + fyle = column[sq]; rank = row[sq]; + wstrong = bstrong = true; + for (i = sq; i < 64; i += 8) + if (atak[black][i] >= ctlP) wstrong = false; + for (i = sq; i >= 0; i -= 8) + if (atak[white][i] >= ctlP) bstrong = false; + wpadv = bpadv = PADVNCM; + if ((fyle == 0 || PawnCnt[white][fyle-1] == 0) && + (fyle == 7 || PawnCnt[white][fyle+1] == 0)) wpadv = PADVNCI; + if ((fyle == 0 || PawnCnt[black][fyle-1] == 0) && + (fyle == 7 || PawnCnt[black][fyle+1] == 0)) bpadv = PADVNCI; + Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10; + Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10; + Mwpawn[sq] += PawnBonus; Mbpawn[sq] += PawnBonus; + if (castld[white] || kingmoved[white]) + { + if ((fyle < 3 || fyle > 4) && distance(sq,wking) < 3) + Mwpawn[sq] += PAWNSHIELD; + } + else if (rank < 3 && (fyle < 2 || fyle > 5)) + Mwpawn[sq] += PAWNSHIELD / 2; + if (castld[black] || kingmoved[black]) + { + if ((fyle < 3 || fyle > 4) && distance(sq,bking) < 3) + Mbpawn[sq] += PAWNSHIELD; + } + else if (rank > 4 && (fyle < 2 || fyle > 5)) + Mbpawn[sq] += PAWNSHIELD / 2; + if (PawnStorm) + { + if ((column[wking] < 4 && fyle > 4) || + (column[wking] > 3 && fyle < 3)) Mwpawn[sq] += 3*rank - 21; + if ((column[bking] < 4 && fyle > 4) || + (column[bking] > 3 && fyle < 3)) Mbpawn[sq] -= 3*rank; + } + + Mknight[white][sq] += 5 - distance(sq,bking); + Mknight[white][sq] += 5 - distance(sq,wking); + Mknight[black][sq] += 5 - distance(sq,wking); + Mknight[black][sq] += 5 - distance(sq,bking); + Mbishop[white][sq] += BishopBonus; + Mbishop[black][sq] += BishopBonus; + for (i = 0; i <= PieceCnt[black]; i++) + if (distance(sq,PieceList[black][i]) < 3) + Mknight[white][sq] += KNIGHTPOST; + for (i = 0; i <= PieceCnt[white]; i++) + if (distance(sq,PieceList[white][i]) < 3) + Mknight[black][sq] += KNIGHTPOST; + if (wstrong) Mknight[white][sq] += KNIGHTSTRONG; + if (bstrong) Mknight[black][sq] += KNIGHTSTRONG; + if (wstrong) Mbishop[white][sq] += BISHOPSTRONG; + if (bstrong) Mbishop[black][sq] += BISHOPSTRONG; + + if (HasBishop[white] == 2) Mbishop[white][sq] += 8; + if (HasBishop[black] == 2) Mbishop[black][sq] += 8; + if (HasKnight[white] == 2) Mknight[white][sq] += 5; + if (HasKnight[black] == 2) Mknight[black][sq] += 5; + + if (board[sq] == bishop) + if (rank % 2 == fyle % 2) KBNKsq = 0; else KBNKsq = 7; + + Kfield[white][sq] = Kfield[black][sq] = 0; + if (distance(sq,wking) == 1) Kfield[black][sq] = KATAK; + if (distance(sq,bking) == 1) Kfield[white][sq] = KATAK; + + Pd = 0; + for (i = 0; i < 64; i++) + if (board[i] == pawn) + { + if (color[i] == white) + { + pp = true; + if (row[i] == 6) z = i+8; else z = i+16; + for (j = i+8; j < 64; j += 8) + if (atak[black][j] > ctlP || board[j] == pawn) pp = false; + } + else + { + pp = true; + if (row[i] == 1) z = i-8; else z = i-16; + for (j = i-8; j >= 0; j -= 8) + if (atak[white][j] > ctlP || board[j] == pawn) pp = false; + } + if (pp) Pd += 5*taxicab(sq,z); else Pd += taxicab(sq,z); + } + if (Pd != 0) + { + val = (Pd*stage2) / 10; + Mking[white][sq] -= val; + Mking[black][sq] -= val; + } + } +} + + +UpdateWeights() + +/* + If material balance has changed, determine the values for the + positional evaluation terms. +*/ + +{ +short tmtl; + + if (mtl[white] != Zwmtl || mtl[black] != Zbmtl) + { + Zwmtl = mtl[white]; Zbmtl = mtl[black]; + emtl[white] = Zwmtl - pmtl[white] - valueK; + emtl[black] = Zbmtl - pmtl[black] - valueK; + tmtl = emtl[white] + emtl[black]; + if (tmtl > 6600) stage = 0; + else if (tmtl < 1400) stage = 10; + else stage = (6600-tmtl) / 520; + if (tmtl > 3600) stage2 = 0; + else if (tmtl < 1400) stage2 = 10; + else stage2 = (3600-tmtl) / 220; + + PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */ + PBLOK = -4; /* blocked backward pawn */ + PDOUBLED = -14; /* doubled pawn */ + PWEAKH = -4; /* weak pawn on half open file */ + PAWNSHIELD = 10-stage; /* pawn near friendly king */ + PADVNCM = 10; /* advanced pawn multiplier */ + PADVNCI = 7; /* muliplier for isolated pawn */ + PawnBonus = stage; + + KNIGHTPOST = (stage+2)/3; /* knight near enemy pieces */ + KNIGHTSTRONG = (stage+6)/2; /* occupies pawn hole */ + + BISHOPSTRONG = (stage+6)/2; /* occupies pawn hole */ + BishopBonus = 2*stage; + + RHOPN = 10; /* rook on half open file */ + RHOPNX = 4; + RookBonus = 6*stage; + + XRAY = 8; /* Xray attack on piece */ + PINVAL = 10; /* Pin */ + + KHOPN = (3*stage-30) / 2; /* king on half open file */ + KHOPNX = KHOPN / 2; + KCASTLD = 10 - stage; + KMOVD = -40 / (stage+1); /* king moved before castling */ + KATAK = (10-stage) / 2; /* B,R attacks near enemy king */ + if (stage < 8) KSFTY = 16-2*stage; else KSFTY = 0; + + ATAKD = -6; /* defender > attacker */ + HUNGP = -8; /* each hung piece */ + HUNGX = -12; /* extra for >1 hung piece */ + } +} + +#if (NEWMOVE < 1) +int distance(a,b) +short a,b; +{ +register short d1,d2; + + d1 = abs(column[a]-column[b]); + d2 = abs(row[a]-row[b]); + return(d1 > d2 ? d1 : d2); +} +#endif + +BlendBoard(a,b,c) +short a[64],b[64],c[64]; +{ +register int sq; + for (sq = 0; sq < 64; sq++) + c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10; +} + + +CopyBoard(a,b) +short a[64],b[64]; +{ +register int sq; + for (sq = 0; sq < 64; sq++) + b[sq] = a[sq]; +} diff --git a/gnu/games/chess/gnuchess.h b/gnu/games/chess/gnuchess.h new file mode 100644 index 000000000000..6e9c74bcbc22 --- /dev/null +++ b/gnu/games/chess/gnuchess.h @@ -0,0 +1,97 @@ +/* + This file contains code for CHESS. + Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + + This file is part of CHESS. + + CHESS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the CHESS General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + CHESS, but only under the conditions described in the + CHESS General Public License. A copy of this license is + supposed to have been given to you along with CHESS so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. +*/ + + +/* Header file for GNU CHESS */ + +#define neutral 2 +#define white 0 +#define black 1 +#define no_piece 0 +#define pawn 1 +#define knight 2 +#define bishop 3 +#define rook 4 +#define queen 5 +#define king 6 +#define pxx " PNBRQK" +#define qxx " pnbrqk" +#define rxx "12345678" +#define cxx "abcdefgh" +#define check 0x0001 +#define capture 0x0002 +#define draw 0x0004 +#define promote 0x0008 +#define cstlmask 0x0010 +#define epmask 0x0020 +#define exact 0x0040 +#define pwnthrt 0x0080 +#define maxdepth 30 +#define true 1 +#define false 0 + +struct leaf + { + short f,t,score,reply; + unsigned short flags; + }; +struct GameRec + { + unsigned short gmove; + short score,depth,time,piece,color; + long nodes; + }; +struct TimeControlRec + { + short moves[2]; + long clock[2]; + }; +struct BookEntry + { + struct BookEntry *next; + unsigned short *mv; + }; + +extern char mvstr1[5],mvstr2[5]; +extern struct leaf Tree[2000],*root; +extern short TrPnt[maxdepth],board[64],color[64]; +extern short row[64],column[64],locn[8][8]; +extern short atak[2][64],PawnCnt[2][8]; +extern short castld[2],kingmoved[2]; +extern short c1,c2,*atk1,*atk2,*PC1,*PC2; +extern short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither; +extern long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft; +extern long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt; +extern short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep,meter; +extern short timeout,xwndw; +extern struct GameRec GameList[240]; +extern short GameCnt,Game50,epsquare,lpost,rcptr,contempt; +extern short MaxSearchDepth; +extern struct BookEntry *Book; +extern struct TimeControlRec TimeControl; +extern short TCflag,TCmoves,TCminutes,OperatorTime; +extern short otherside[3]; +extern short Stboard[64]; +extern short Stcolor[64]; +extern unsigned short hint,PrVar[maxdepth]; + +#define HZ 60 diff --git a/gnu/games/chess/move.c b/gnu/games/chess/move.c new file mode 100644 index 000000000000..4ce686c1b40a --- /dev/null +++ b/gnu/games/chess/move.c @@ -0,0 +1,357 @@ +/* move generator hes@log-sv.se 890318 + Modified: 890606 NEWMOVE Levels 1-6 for easier debugging */ +#include "move.h" +#include "gnuchess.h" + +short distdata[64][64]; +short taxidata[64][64]; + +void Initialize_dist() { +register short a,b,d,di; + + /* init taxi and dist data */ + for(a=0;a<64;a++) + for(b=0;b<64;b++) { + d = abs(column[a]-column[b]); + di = abs(row[a]-row[b]); + taxidata[a][b] = d + di; + distdata[a][b] = (d > di ? d : di); + }; +} + +#if (NEWMOVE > 1) +struct sqdata posdata[3][8][64][64]; + +static short direc[8][8] = { + 0, 0, 0, 0, 0, 0, 0, 0, /* no_piece = 0 */ + -10,-11, -9, 0, 0, 0, 0, 0, /* wpawn = 1 */ + -21,-19,-12, -8, 21, 19, 12, 8, /* knight = 2 */ + -11, -9, 11, 9, 0, 0, 0, 0, /* bishop = 3 */ + -10, -1, 10, 1, 0, 0, 0, 0, /* rook = 4 */ + -11, -9,-10, -1, 11, 9, 10, 1, /* queen = 5 */ + -11, -9,-10, -1, 11, 9, 10, 1, /* king = 6 */ + 0, 0, 0, 0, 0, 0, 0, 0};/* no_piece = 7 */ + +static short dc[3] = {-1,1,0}; + +static short max_steps [8] = {0,2,1,7,7,7,1,0}; + +static short unmap[120] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7,-1, + -1, 8, 9,10,11,12,13,14,15,-1, + -1,16,17,18,19,20,21,22,23,-1, + -1,24,25,26,27,28,29,30,31,-1, + -1,32,33,34,35,36,37,38,39,-1, + -1,40,41,42,43,44,45,46,47,-1, + -1,48,49,50,51,52,53,54,55,-1, + -1,56,57,58,59,60,61,62,63,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; + +void Initialize_moves() { + short c,ptyp,po,p0,d,di,s; + struct sqdata *p; + short dest[8][8]; + short steps[8]; + short sorted[8]; + + /* init posdata */ + for(c=0;c<3;c++) + for(ptyp=0;ptyp<8;ptyp++) + for(po=0;po<64;po++) + for(p0=0;p0<64;p0++) { + posdata[c][ptyp][po][p0].nextpos = po; + posdata[c][ptyp][po][p0].nextdir = po; + }; + /* dest is a function of dir and step */ + for(c=0;c<2;c++) + for(ptyp=1;ptyp<7;ptyp++) + for(po=21;po<99;po++) + if (unmap[po] >= 0) { + p = posdata[c][ptyp][unmap[po]]; + for(d=0;d<8;d++) { + dest[d][0] = unmap[po]; + if (dc[c]*direc[ptyp][d] != 0) { + p0=po; + for(s=0;s0 && (d>0 || Stboard[unmap[po]] != ptyp))) + break; + else + dest[d][s] = unmap[p0]; + } + } + else s=0; + /* sort dest in number of steps order */ + steps[d] = s; + for(di=d;di>0;di--) + if (steps[sorted[di-1]] < s) + sorted[di] = sorted[di-1]; + else + break; + sorted[di] = d; + } + /* update posdata, pawns have two threads (capture and no capture) */ + p0=unmap[po]; + if (ptyp == pawn) { + for(s=0;s 2) +int SqAtakd(sq,side) +short sq,side; + +/* + See if any piece with color 'side' ataks sq. First check pawns + Then Queen, Bishop, Rook and King and last Knight. +*/ + +{ + register short u; + register struct sqdata *p; + + p = posdata[1-side][pawn][sq]; + u = p[sq].nextdir; /* follow captures thread */ + while (u != sq) { + if (board[u] == pawn && color[u] == side) return(true); + u = p[u].nextdir; + } + /* king capture */ + if (distance(sq,PieceList[side][0]) == 1) return(true); + /* try a queen bishop capture */ + p = posdata[side][bishop][sq]; + u = p[sq].nextpos; + while (u != sq) { + if (color[u] == neutral) { + u = p[u].nextpos; + } + else { + if (color[u] == side && + (board[u] == queen || board[u] == bishop)) + return(true); + u = p[u].nextdir; + } + } + /* try a queen rook capture */ + p = posdata[side][rook][sq]; + u = p[sq].nextpos; + while (u != sq) { + if (color[u] == neutral) { + u = p[u].nextpos; + } + else { + if (color[u] == side && + (board[u] == queen || board[u] == rook)) + return(true); + u = p[u].nextdir; + } + } + /* try a knight capture */ + p = posdata[side][knight][sq]; + u = p[sq].nextpos; + while (u != sq) { + if (color[u] == neutral) { + u = p[u].nextpos; + } + else { + if (color[u] == side && board[u] == knight) return(true); + u = p[u].nextdir; + } + } + return(false); +} +#endif + +#if (NEWMOVE > 3) +BRscan(sq,s,mob) +short sq,*s,*mob; +/* + Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the + hung[] array if a pin is found. +*/ +{ + register short u,piece,pin; + register struct sqdata *p; + short *Kf; + + Kf = Kfield[c1]; + *mob = 0; + piece = board[sq]; + p = posdata[color[sq]][piece][sq]; + u = p[sq].nextpos; + pin = -1; /* start new direction */ + while (u != sq) { + *s += Kf[u]; + if (color[u] == neutral) { + (*mob)++; + if (p[u].nextpos == p[u].nextdir) pin = -1; /* oops new direction */ + u = p[u].nextpos; + } + else if (pin < 0) { + if (board[u] == pawn || board[u] == king) + u = p[u].nextdir; + else { + if (p[u].nextpos != p[u].nextdir) + pin = u; /* not on the edge and on to find a pin */ + u = p[u].nextpos; + } + } + else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0)) + { + if (color[pin] == c2) + { + *s += PINVAL; + if (atk2[pin] == 0 || + atk1[pin] > control[board[pin]]+1) + ++hung[c2]; + } + else *s += XRAY; + pin = -1; /* new direction */ + u = p[u].nextdir; + } + else { + pin = -1; /* new direction */ + u = p[u].nextdir; + } + } +} +#endif + +#if (NEWMOVE >= 5) +CaptureList(side,xside,ply) +short side,xside,ply; +{ + register short u,sq; + register struct sqdata *p; + short i,piece,*PL; + struct leaf *node; + + TrPnt[ply+1] = TrPnt[ply]; + node = &Tree[TrPnt[ply]]; + PL = PieceList[side]; + for (i = 0; i <= PieceCnt[side]; i++) + { + sq = PL[i]; + piece = board[sq]; + p = posdata[side][piece][sq]; + if (piece == pawn) { + u = p[sq].nextdir; /* follow captures thread */ + while (u != sq) { + if (color[u] == xside) { + node->f = sq; node->t = u; + node->flags = capture; + if (u < 8 || u > 55) + { + node->flags |= promote; + node->score = valueQ; + } + else + node->score = value[board[u]] + svalue[board[u]] - piece; + ++node; + ++TrPnt[ply+1]; + } + u = p[u].nextdir; + } + } + else { + u = p[sq].nextpos; + while (u != sq) { + if (color[u] == neutral) + u = p[u].nextpos; + else { + if (color[u] == xside) { + node->f = sq; node->t = u; + node->flags = capture; + node->score = value[board[u]] + svalue[board[u]] - piece; + ++node; + ++TrPnt[ply+1]; + } + u = p[u].nextdir; + } + } + } + } +} +#endif + +#if (NEWMOVE > 5) +GenMoves(ply,sq,side,xside) + short ply,sq,side,xside; + +/* + Generate moves for a piece. The moves are taken from the + precalulated array posdata. If the board is free, next move + is choosen from nextpos else from nextdir. +*/ + +{ + register short u,piece; + register struct sqdata *p; + + piece = board[sq]; + p = posdata[side][piece][sq]; + if (piece == pawn) { + u = p[sq].nextdir; /* follow captures thread */ + while (u != sq) { + if (color[u] == xside) LinkMove(ply,sq,u,xside); + u = p[u].nextdir; + } + u = p[sq].nextpos; /* and follow no captures thread */ + while (u != sq) { + if (color[u] == neutral && (u != sq+16 || color[u-8] == neutral) + && (u != sq-16 || color[u+8] == neutral)) { + LinkMove(ply,sq,u,xside); + } + u = p[u].nextpos; + } + } + else { + u = p[sq].nextpos; + while (u != sq) { + if (color[u] == neutral) { + LinkMove(ply,sq,u,xside); + u = p[u].nextpos; + } + else { + if (color[u] == xside) LinkMove(ply,sq,u,xside); + u = p[u].nextdir; + } + } + } +} +#endif diff --git a/gnu/games/chess/move.h b/gnu/games/chess/move.h new file mode 100644 index 000000000000..2f328303763f --- /dev/null +++ b/gnu/games/chess/move.h @@ -0,0 +1,81 @@ +/* header file for move generator hes 890318 + Modified: 890510 minor bug fixed in Newataks + 890606 NEWMOVE levels 1-6 */ + +#if (NEWMOVE >= 1) +extern short distdata[64][64]; +extern short taxidata[64][64]; + +#define taxicab(a,b) taxidata[a][b] +#define distance(a,b) distdata[a][b] + +extern void Initialize_dist(); +#endif + +#if (NEWMOVE >= 2) +struct sqdata { + short nextpos; + short nextdir; +}; +extern struct sqdata posdata[3][8][64][64]; + +extern void Initialize_moves(); + +#define ataks(side,a)\ +{\ + register short u,c,sq;\ + register struct sqdata *p;\ + short i,piece,*PL;\ + \ + for (u = 64; u; a[--u] = 0); \ + PL = PieceList[side];\ + for (i = 0; i <= PieceCnt[side]; i++)\ + {\ + sq = PL[i];\ + piece = board[sq];\ + c = control[piece];\ + p = posdata[side][piece][sq];\ + if (piece == pawn) {\ + u = p[sq].nextdir; /* follow captures thread */\ + while (u != sq) {\ + a[u] = ++a[u] | c;\ + u = p[u].nextdir;\ + }\ + }\ + else {\ + u = p[sq].nextpos;\ + while (u != sq) {\ + a[u] = ++a[u] | c;\ + if (color[u] == neutral)\ + u = p[u].nextpos;\ + else\ + u = p[u].nextdir;\ + }\ + }\ + }\ +} +#endif + +#if (NEWMOVE >= 3) +extern short PieceList[2][16]; + +extern int Sqatakd(); +#endif + +#if (NEWMOVE > 3) +extern short Kfield[2][64],PINVAL,control[7],hung[2],XRAY; + +extern BRscan(); +#endif + +#if (NEWMOVE > 4) +#define valueQ 1100 + +extern short PieceCnt[2],value[7],svalue[64]; + +extern CaptureList(); +#endif + +#if (NEWMOVE > 5) +extern GenMoves(); +#endif diff --git a/gnu/games/chess/nondsp.c b/gnu/games/chess/nondsp.c new file mode 100644 index 000000000000..0b29ad5504c5 --- /dev/null +++ b/gnu/games/chess/nondsp.c @@ -0,0 +1,791 @@ +/* + UNIX & MSDOS NON-DISPLAY, AND CHESSTOOL interface for Chess + + Revision: 4-25-88 + + Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (c) 1988 John Stanback + + This file is part of CHESS. + + CHESS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the CHESS General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + CHESS, but only under the conditions described in the + CHESS General Public License. A copy of this license is + supposed to have been given to you along with CHESS so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. +*/ + + +#include +#include +#ifdef MSDOS +#include +#include +#include +#else +#include +#include +#include +struct tms tmbuf1,tmbuf2; +int TerminateSearch(),Die(); +#endif MSDOS + +#include "gnuchess.h" +#ifdef NEWMOVE +#include "move.h" +#endif + +#define printz printf +#define scanz scanf +int mycnt1,mycnt2; + + +Initialize() +{ + mycnt1 = mycnt2 = 0; +#ifndef MSDOS +#endif +#ifdef CHESSTOOL + setlinebuf(stdout); +/* + setvbuf(stdout,NULL,_IOLBF,BUFSIZ); +*/ + printf("Chess\n"); + if (Level == 0 && !TCflag) Level = 15; +#endif CHESSTOOL +} + +ExitChess() +{ + ListGame(); + exit(0); +} + +#ifndef MSDOS +Die() +{ +char s[80]; + printz("Abort? "); + scanz("%s",s); + if (strcmp(s,"yes") == 0) ExitChess(); +} + +TerminateSearch() +{ + timeout = true; + bothsides = false; +} +#endif MSDOS + + +InputCommand() + +/* + Process the users command. If easy mode is OFF (the computer is + thinking on opponents time) and the program is out of book, then make + the 'hint' move on the board and call SelectMove() to find a response. + The user terminates the search by entering ^C (quit siqnal) before + entering a command. If the opponent does not make the hint move, then + set Sdepth to zero. +*/ + +{ +int i; +short ok,tmp; +long cnt,rate,t1,t2; +unsigned short mv; +char s[80]; + + ok = quit = false; + player = opponent; + ft = 0; + if (hint > 0 && !easy && Book == NULL) + { + fflush(stdout); + time0 = time((long *)0); + algbr(hint>>8,hint & 0xFF,false); + strcpy(s,mvstr1); + tmp = epsquare; + if (VerifyMove(s,1,&mv)) + { + SelectMove(computer,2); + VerifyMove(mvstr1,2,&mv); + if (Sdepth > 0) Sdepth--; + } + ft = time((long *)0) - time0; + epsquare = tmp; + } + +#ifndef MSDOS +#endif + while (!(ok || quit)) + { + PromptForMove(); + i = scanz("%s",s); + if (i == EOF || s[0] == 0) ExitChess(); + player = opponent; + ok = VerifyMove(s,0,&mv); + if (ok && mv != hint) + { + Sdepth = 0; + ft = 0; + } + + if (strcmp(s,"bd") == 0) + { + ClrScreen(); + UpdateDisplay(0,0,1,0); + } + if (strcmp(s,"quit") == 0) quit = true; + if (strcmp(s,"post") == 0) post = !post; + if (strcmp(s,"set") == 0) EditBoard(); + if (strcmp(s,"go") == 0) ok = true; + if (strcmp(s,"help") == 0) help(); + if (strcmp(s,"force") == 0) force = !force; + if (strcmp(s,"book") == 0) Book = NULL; + if (strcmp(s,"new") == 0) NewGame(); + if (strcmp(s,"list") == 0) ListGame(); + if (strcmp(s,"level") == 0) SelectLevel(); + if (strcmp(s,"hash") == 0) hashflag = !hashflag; + if (strcmp(s,"beep") == 0) beep = !beep; + if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow(); + if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow(); + if (strcmp(s,"rcptr") == 0) rcptr = !rcptr; + if (strcmp(s,"hint") == 0) GiveHint(); + if (strcmp(s,"zero") == 0) ZeroTTable(); + if (strcmp(s,"both") == 0) + { + bothsides = !bothsides; + Sdepth = 0; + SelectMove(opponent,1); + ok = true; + } + if (strcmp(s,"reverse") == 0) + { + reverse = !reverse; + ClrScreen(); + UpdateDisplay(0,0,1,0); + } + if (strcmp(s,"switch") == 0) + { + computer = otherside[computer]; + opponent = otherside[opponent]; + force = false; + Sdepth = 0; + ok = true; + } + if (strcmp(s,"white") == 0) + { + computer = white; opponent = black; + ok = true; force = false; + Sdepth = 0; + } + if (strcmp(s,"black") == 0) + { + computer = black; opponent = white; + ok = true; force = false; + Sdepth = 0; + } + if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo(); + if (strcmp(s,"remove") == 0 && GameCnt >= 1) + { + Undo(); Undo(); + } + if (strcmp(s,"get") == 0) GetGame(); + if (strcmp(s,"save") == 0) SaveGame(); + if (strcmp(s,"depth") == 0) ChangeSearchDepth(); + if (strcmp(s,"random") == 0) dither = 6; + if (strcmp(s,"easy") == 0) easy = !easy; + if (strcmp(s,"contempt") == 0) SetContempt(); + if (strcmp(s,"xwndw") == 0) ChangeXwindow(); + if (strcmp(s,"test") == 0) + { + t1 = time(0); + cnt = 0; + for (i = 0; i < 10000; i++) + { + MoveList(opponent,2); + cnt += TrPnt[3] - TrPnt[2]; + } + t2 = time(0); + rate = cnt / (t2-t1); + printz("cnt= %ld rate= %ld\n",cnt,rate); + } + } + + ElapsedTime(1); + if (force) + { + computer = opponent; opponent = otherside[computer]; + } +#ifndef MSDOS + (void) times(&tmbuf1); +#ifdef CHESSTOOL + printf("%d. %s\n",++mycnt2,s); +#endif CHESSTOOL +#endif MSDOS +} + + +help() +{ + ClrScreen(); + printz("CHESS command summary\n"); + printz("g1f3 move from g1 to f3\n"); + printz("nf3 move knight to f3\n"); + printz("o-o castle king side\n"); + printz("o-o-o castle queen side\n"); + printz("set edit board\n"); + printz("switch sides with computer\n"); + printz("white computer plays white\n"); + printz("black computer plays black\n"); + printz("reverse board display\n"); + printz("both computer match\n"); + printz("random randomize play\n"); + printz("undo undo last move\n"); + printz("time change level\n"); + printz("depth set search depth\n"); + printz("post principle variation\n"); + printz("hint suggest a move\n"); + printz("bd redraw board\n"); + printz("clock set time control\n"); + printz("force enter game moves\n"); + printz("list game to chess.lst\n"); + printz("save game to file\n"); + printz("get game from file\n"); + printz("new start new game\n"); + printz("quit exit CHESS\n"); + printz("Computer: "); + if (computer == white) printz("WHITE\n"); else printz("BLACK\n"); + printz("Opponent: "); + if (opponent == white) printz("WHITE\n"); else printz("BLACK\n"); + printz("Response time: %ld",Level," sec.\n"); + printz("Easy mode: "); + if (easy) printz("ON\n"); else printz("OFF\n"); + printz("Depth: %d\n",MaxSearchDepth); + printz("Random: "); + if (dither) printz("ON\n"); else printz("OFF\n"); + printz("Transposition table: "); + if (hashflag) printz("ON\n"); else printz("OFF\n"); + UpdateDisplay(0,0,1,0); +} + + +EditBoard() + +/* + Set up a board position. Pieces are entered by typing the piece + followed by the location. For example, Nf3 will place a knight on + square f3. +*/ + +{ +short a,r,c,sq; +char s[80]; + + ClrScreen(); + UpdateDisplay(0,0,1,0); + printz(". exit to main\n"); + printz("# clear board\n"); + printz("enter piece & location: \n"); + + a = white; + do + { + scanz("%s",s); + if (s[0] == '#') + { + for (sq = 0; sq < 64; sq++) + { + board[sq] = no_piece; color[sq] = neutral; + } + UpdateDisplay(0,0,1,0); + } + if (s[0] == 'c' || s[0] == 'C') a = otherside[a]; + c = s[1]-'a'; r = s[2]-'1'; + if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) + { + sq = locn[r][c]; + color[sq] = a; + if (s[0] == 'p') board[sq] = pawn; + else if (s[0] == 'n') board[sq] = knight; + else if (s[0] == 'b') board[sq] = bishop; + else if (s[0] == 'r') board[sq] = rook; + else if (s[0] == 'q') board[sq] = queen; + else if (s[0] == 'k') board[sq] = king; + else { board[sq] = no_piece; color[sq] = neutral; } + } + } + while (s[0] != '.'); + if (board[4] != king) kingmoved[white] = 10; + if (board[60] != king) kingmoved[black] = 10; + GameCnt = -1; Game50 = 0; Sdepth = 0; + InitializeStats(); + ClrScreen(); + UpdateDisplay(0,0,1,0); +} + + +ShowDepth(ch) +char ch; +{ +} + +ShowResults(score,bstline,ch) +short score; +unsigned short bstline[]; +char ch; +{ +#ifndef CHESSTOOL +register int i; + printz("%2d%c %5d %4ld %7ld ",Sdepth,ch,score,et,NodeCnt); + for (i = 1; bstline[i] > 0; i++) + { + algbr((short)(bstline[i] >> 8),(short)(bstline[i] & 0xFF),false); + if (i == 9 || i == 17) printz("\n "); + printz("%5s ",mvstr1); + } + printz("\n"); +#endif +} + + +SearchStartStuff(side) +short side; +{ +#ifndef MSDOS +#endif +#ifndef CHESSTOOL + printz("\nMove# %d Target= %ld Clock: %ld\n", + TCmoves-TimeControl.moves[side]+1, + ResponseTime,TimeControl.clock[side]); +#endif +} + + +OutputMove() +{ +#ifdef CHESSTOOL + printz("%d. ... %s\n",++mycnt1,mvstr1); + if (root->flags & draw) + { + printz("Draw\n"); + ListGame(); + exit(0); + } + if (root->score == -9999) + { + if (opponent == white) printz("White\n"); else printz("Black\n"); + ListGame(); + exit(0); + } + if (root->score == 9998) + { + if (computer == white) printz("White\n"); else printz("Black\n"); + ListGame(); + exit(0); + } +#else + printz("Nodes= %ld Eval= %ld Hash= %ld Rate= %ld ", + NodeCnt,EvalNodes,HashCnt,evrate); + printz("CPU= %.2ld:%.2ld.%.2ld\n\n", + cputimer/6000,(cputimer % 6000)/100,cputimer % 100); + + if (root->flags & epmask) UpdateDisplay(0,0,1,0); + else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask); + printz("My move is: %s\n\n",mvstr1); + if (beep) printz("%c",7); + + if (root->flags & draw) printz("Draw game!\n"); + else if (root->score == -9999) printz("opponent mates!\n"); + else if (root->score == 9998) printz("computer mates!\n"); + else if (root->score < -9000) printz("opponent will soon mate!\n"); + else if (root->score > 9000) printz("computer will soon mate!\n"); +#endif CHESSTOOL +} + + +ElapsedTime(iop) +short iop; + +/* + Determine the time that has passed since the search was started. If + the elapsed time exceeds the target (ResponseTime+ExtraTime) then set + timeout to true which will terminate the search. +*/ + +{ + et = time((long *)0) - time0; + if (et < 0) et = 0; + ETnodes += 50; + if (et > et0 || iop == 1) + { + if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true; + et0 = et; + if (iop == 1) + { + time0 = time((long *)0); et0 = 0; + } +#ifdef MSDOS + cputimer = 100*et; + if (et > 0) evrate = NodeCnt/(et+ft); else evrate = 0; + if (kbhit() && Sdepth > 1) + { + timeout = true; + bothsides = false; + } +#else + (void) times(&tmbuf2); + cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ; + if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft); + else evrate = 0; +#endif MSDOS + ETnodes = NodeCnt + 50; + } +} + + +SetTimeControl() +{ + if (TCflag) + { + TimeControl.moves[white] = TimeControl.moves[black] = TCmoves; + TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes; + } + else + { + TimeControl.moves[white] = TimeControl.moves[black] = 0; + TimeControl.clock[white] = TimeControl.clock[black] = 0; + Level = 60*(long)TCminutes; + } + et = 0; + ElapsedTime(1); +} + + +ClrScreen() +{ +#ifndef CHESSTOOL + printz("\n"); +#endif +} + + +UpdateDisplay(f,t,flag,iscastle) +short f,t,flag,iscastle; +{ +#ifndef CHESSTOOL +short r,c,l; + if (flag) + { + printz("\n"); + for (r = 7; r >= 0; r--) + { + for (c = 0; c <= 7; c++) + { + if (reverse) l = locn[7-r][7-c]; else l = locn[r][c]; + if (color[l] == neutral) printz(" -"); + else if (color[l] == white) printz(" %c",qxx[board[l]]); + else printz(" %c",pxx[board[l]]); + } + printz("\n"); + } + printz("\n"); + } +#endif CHESSTOOL +} + + +GetOpenings() + +/* + Read in the Opening Book file and parse the algebraic notation for a + move into an unsigned integer format indicating the from and to + square. Create a linked list of opening lines of play, with + entry->next pointing to the next line and entry->move pointing to a + chunk of memory containing the moves. More Opening lines of up to 256 + half moves may be added to gnuchess.book. +*/ + +{ +FILE *fd; +int c,i,j,side; +char buffr[2048]; +struct BookEntry *entry; +unsigned short mv,*mp,tmp[100]; + + if ((fd = fopen("gnuchess.book","r")) != NULL) + { +/* + setvbuf(fd,buffr,_IOFBF,2048); +*/ + Book = NULL; + i = 0; side = white; + while ((c = parse(fd,&mv,side)) >= 0) + if (c == 1) + { + tmp[++i] = mv; + side = otherside[side]; + } + else if (c == 0 && i > 0) + { + entry = (struct BookEntry *)malloc(sizeof(struct BookEntry)); + mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short)); + entry->mv = mp; + entry->next = Book; + Book = entry; + for (j = 1; j <= i; j++) *(mp++) = tmp[j]; + *mp = 0; + i = 0; side = white; + } + fclose(fd); + } +} + + +int parse(fd,mv,side) +FILE *fd; +unsigned short *mv; +short side; +{ +int c,i,r1,r2,c1,c2; +char s[100]; + while ((c = getc(fd)) == ' '); + i = 0; s[0] = c; + while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd); + s[++i] = '\0'; + if (c == EOF) return(-1); + if (s[0] == '!' || i < 3) + { + while (c != '\n' && c != EOF) c = getc(fd); + return(0); + } + if (s[4] == 'o') + if (side == black) *mv = 0x3C3A; else *mv = 0x0402; + else if (s[0] == 'o') + if (side == black) *mv = 0x3C3E; else *mv = 0x0406; + else + { + c1 = s[0] - 'a'; r1 = s[1] - '1'; + c2 = s[2] - 'a'; r2 = s[3] - '1'; + *mv = (locn[r1][c1]<<8) + locn[r2][c2]; + } + return(1); +} + + +GetGame() +{ +FILE *fd; +char fname[40]; +int c; +short sq; +unsigned short m; + + printz("Enter file name: "); + scanz("%s",fname); + if (fname[0] == '\0') strcpy(fname,"chess.000"); + if ((fd = fopen(fname,"r")) != NULL) + { + fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50); + fscanf(fd,"%hd%hd%hd%hd", + &castld[white],&castld[black], + &kingmoved[white],&kingmoved[black]); + fscanf(fd,"%hd%hd",&TCflag,&OperatorTime); + fscanf(fd,"%ld%ld%hd%hd", + &TimeControl.clock[white],&TimeControl.clock[black], + &TimeControl.moves[white],&TimeControl.moves[black]); + for (sq = 0; sq < 64; sq++) + { + fscanf(fd,"%hd",&m); + board[sq] = (m >> 8); color[sq] = (m & 0xFF); + if (color[sq] == 0) color[sq] = neutral; else --color[sq]; + } + GameCnt = -1; c = '?'; + while (c != EOF) + { + ++GameCnt; + c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove, + &GameList[GameCnt].score,&GameList[GameCnt].depth, + &GameList[GameCnt].nodes,&GameList[GameCnt].time, + &GameList[GameCnt].piece,&GameList[GameCnt].color); + if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral; + else --GameList[GameCnt].color; + } + GameCnt--; + if (TimeControl.clock[white] > 0) TCflag = true; + computer--; opponent--; + } + fclose(fd); + InitializeStats(); + UpdateDisplay(0,0,1,0); + Sdepth = 0; +} + + +SaveGame() +{ +FILE *fd; +char fname[40]; +short sq,i,c; + + printz("Enter file name: "); + scanz("%s",fname); + + if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000"); + fd = fopen(fname,"w"); + fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50); + fprintf(fd,"%d %d %d %d\n", + castld[white],castld[black],kingmoved[white],kingmoved[black]); + fprintf(fd,"%d %d\n",TCflag,OperatorTime); + fprintf(fd,"%ld %ld %d %d\n", + TimeControl.clock[white],TimeControl.clock[black], + TimeControl.moves[white],TimeControl.moves[black]); + for (sq = 0; sq < 64; sq++) + { + if (color[sq] == neutral) c = 0; else c = color[sq]+1; + fprintf(fd,"%d\n",256*board[sq] + c); + } + for (i = 0; i <= GameCnt; i++) + { + if (GameList[i].color == neutral) c = 0; + else c = GameList[i].color + 1; + fprintf(fd,"%d %d %d %ld %d %d %d\n", + GameList[i].gmove,GameList[i].score,GameList[i].depth, + GameList[i].nodes,GameList[i].time, + GameList[i].piece,c); + } + fclose(fd); +} + + +ListGame() +{ +FILE *fd; +short i,f,t; + fd = fopen("chess.lst","w"); + fprintf(fd,"\n"); + fprintf(fd," score depth nodes time "); + fprintf(fd," score depth nodes time\n"); + for (i = 0; i <= GameCnt; i++) + { + f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF); + algbr(f,t,false); + if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd," "); + fprintf(fd,"%5s %5d %2d %6ld %5d",mvstr1, + GameList[i].score,GameList[i].depth, + GameList[i].nodes,GameList[i].time); + } + fprintf(fd,"\n\n"); + fclose(fd); +} + + +Undo() + +/* + Undo the most recent half-move. +*/ + +{ +short f,t; + f = GameList[GameCnt].gmove>>8; + t = GameList[GameCnt].gmove & 0xFF; + if (board[t] == king && distance(t,f) > 1) + castle(GameList[GameCnt].color,f,t,2); + else + { + board[f] = board[t]; color[f] = color[t]; + board[t] = GameList[GameCnt].piece; + color[t] = GameList[GameCnt].color; + if (board[f] == king) --kingmoved[color[f]]; + } + if (TCflag) ++TimeControl.moves[color[f]]; + GameCnt--; mate = false; Sdepth = 0; + UpdateDisplay(0,0,1,0); + InitializeStats(); +} + + +ShowMessage(s) +char *s; +{ +#ifndef CHESSTOOL + printz("%s\n"); +#endif CHESSTOOL +} + +ShowSidetomove() +{ +} + +PromptForMove() +{ +#ifndef CHESSTOOL + printz("\nYour move is? "); +#endif CHESSTOOL +} + + +ShowCurrentMove(pnt,f,t) +short pnt,f,t; +{ +} + +ChangeAlphaWindow() +{ + printz("window: "); + scanz("%hd",&Awindow); +} + +ChangeBetaWindow() +{ + printz("window: "); + scanz("%hd",&Bwindow); +} + +GiveHint() +{ + algbr((short)(hint>>8),(short)(hint & 0xFF),false); + printz("try %s\n",mvstr1); +} + + +SelectLevel() +{ + OperatorTime = 30000; + printz("Enter #moves #minutes: "); + scanz("%hd %hd",&TCmoves,&TCminutes); + printz("Operator time= "); + scanz("%hd",&OperatorTime); + TCflag = (TCmoves > 1); + SetTimeControl(); +} + + +ChangeSearchDepth() +{ + printz("depth= "); + scanz("%hd",&MaxSearchDepth); +} + +SetContempt() +{ + printz("contempt= "); + scanz("%hd",&contempt); +} + +ChangeXwindow() +{ + printz("xwndw= "); + scanz("%hd",&xwndw); +} diff --git a/gnu/games/chess/pathnames.h b/gnu/games/chess/pathnames.h new file mode 100644 index 000000000000..b70a0f0d417d --- /dev/null +++ b/gnu/games/chess/pathnames.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)pathnames.h 5.1 (Berkeley) 5/2/90 + */ + +#define _PATH_CHESSBOOK "/usr/share/games/gnuchess.book" diff --git a/gnu/games/chess/uxdsp.c b/gnu/games/chess/uxdsp.c new file mode 100644 index 000000000000..d584738042a9 --- /dev/null +++ b/gnu/games/chess/uxdsp.c @@ -0,0 +1,933 @@ +/* + ALPHA interface for CHESS + + Revision: 4-25-88 + + Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Copyright (c) 1988 John Stanback + + This file is part of CHESS. + + CHESS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. No author or distributor + accepts responsibility to anyone for the consequences of using it + or for whether it serves any particular purpose or works at all, + unless he says so in writing. Refer to the CHESS General Public + License for full details. + + Everyone is granted permission to copy, modify and redistribute + CHESS, but only under the conditions described in the + CHESS General Public License. A copy of this license is + supposed to have been given to you along with CHESS so you + can know your rights and responsibilities. It should be in a + file named COPYING. Among other things, the copyright notice + and this notice must be preserved on all copies. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include "gnuchess.h" +#ifdef NEWMOVE +#include "move.h" +#endif +#include "pathnames.h" + +struct tms tmbuf1,tmbuf2; +void TerminateSearch(),Die(); + +#define scanz fflush(stdout),scanw +#define printz printw + + +Initialize() +{ + signal(SIGINT,Die); signal(SIGQUIT,Die); + initscr(); + crmode(); +} + + +ExitChess() +{ + nocrmode(); + endwin(); + exit(0); +} + + +void +Die() +{ +char s[80]; + signal(SIGINT,SIG_IGN); + signal(SIGQUIT,SIG_IGN); + ShowMessage("Abort? "); + scanz("%s",s); + if (strcmp(s,"yes") == 0) ExitChess(); + signal(SIGINT,Die); signal(SIGQUIT,Die); +} + + +void +TerminateSearch() +{ + signal(SIGINT,SIG_IGN); + signal(SIGQUIT,SIG_IGN); + timeout = true; + bothsides = false; + signal(SIGINT,Die); signal(SIGQUIT,Die); +} + + +InputCommand() + +/* + Process the users command. If easy mode is OFF (the computer is + thinking on opponents time) and the program is out of book, then make + the 'hint' move on the board and call SelectMove() to find a response. + The user terminates the search by entering ^C (quit siqnal) before + entering a command. If the opponent does not make the hint move, then + set Sdepth to zero. +*/ + +{ +short ok,i,tmp; +long cnt,rate,t1,t2; +unsigned short mv; +char s[80]; + + ok = quit = false; + player = opponent; + ShowSidetomove(); + ft = 0; + if (hint > 0 && !easy && Book == NULL) + { + fflush(stdout); + time0 = time((long *)0); + algbr(hint>>8,hint & 0xFF,false); + strcpy(s,mvstr1); + tmp = epsquare; + if (VerifyMove(s,1,&mv)) + { + PromptForMove(); + SelectMove(computer,2); + VerifyMove(mvstr1,2,&mv); + if (Sdepth > 0) Sdepth--; + } + ft = time((time_t *)0) - time0; + epsquare = tmp; + } + + signal(SIGINT,Die); signal(SIGQUIT,Die); + while (!(ok || quit)) + { + PromptForMove(); + scanz("%s",s); + player = opponent; + ok = VerifyMove(s,0,&mv); + if (ok && mv != hint) + { + Sdepth = 0; + ft = 0; + } + + if (strcmp(s,"bd") == 0) + { + ClrScreen(); + UpdateDisplay(0,0,1,0); + } + if (strcmp(s,"quit") == 0) quit = true; + if (strcmp(s,"post") == 0) post = !post; + if (strcmp(s,"edit") == 0) EditBoard(); + if (strcmp(s,"go") == 0) ok = true; + if (strcmp(s,"help") == 0) help(); + if (strcmp(s,"force") == 0) force = !force; + if (strcmp(s,"book") == 0) Book = NULL; + if (strcmp(s,"undo") == 0 && GameCnt >= 0) Undo(); + if (strcmp(s,"new") == 0) NewGame(); + if (strcmp(s,"list") == 0) ListGame(); + if (strcmp(s,"level") == 0) SelectLevel(); + if (strcmp(s,"hash") == 0) hashflag = !hashflag; + if (strcmp(s,"beep") == 0) beep = !beep; + if (strcmp(s,"Awindow") == 0) ChangeAlphaWindow(); + if (strcmp(s,"Bwindow") == 0) ChangeBetaWindow(); + if (strcmp(s,"hint") == 0) GiveHint(); + if (strcmp(s,"both") == 0) + { + bothsides = !bothsides; + Sdepth = 0; + SelectMove(opponent,1); + ok = true; + } + if (strcmp(s,"reverse") == 0) + { + reverse = !reverse; + ClrScreen(); + UpdateDisplay(0,0,1,0); + } + if (strcmp(s,"switch") == 0) + { + computer = otherside[computer]; + opponent = otherside[opponent]; + force = false; + Sdepth = 0; + ok = true; + } + if (strcmp(s,"white") == 0) + { + computer = white; opponent = black; + ok = true; force = false; + Sdepth = 0; + } + if (strcmp(s,"black") == 0) + { + computer = black; opponent = white; + ok = true; force = false; + Sdepth = 0; + } + if (strcmp(s,"remove") == 0 && GameCnt >= 1) + { + Undo(); Undo(); + } + if (strcmp(s,"get") == 0) GetGame(); + if (strcmp(s,"save") == 0) SaveGame(); + if (strcmp(s,"depth") == 0) ChangeSearchDepth(); + if (strcmp(s,"random") == 0) dither = 6; + if (strcmp(s,"easy") == 0) easy = !easy; + if (strcmp(s,"contempt") == 0) SetContempt(); + if (strcmp(s,"xwndw") == 0) ChangeXwindow(); + if (strcmp(s,"test") == 0) + { + t1 = time(0); + cnt = 0; + for (i = 0; i < 10000; i++) + { + MoveList(opponent,2); + cnt += TrPnt[3] - TrPnt[2]; + } + t2 = time(0); + rate = cnt / (t2-t1); + gotoXY(50,24); + printz("cnt= %ld rate= %ld",cnt,rate); + ClrEoln(); + } + if (strcmp(s,"p") == 0) ShowPostnValues(); + if (strcmp(s,"debug") == 0) DoDebug(); + } + + ClearMessage(); + ElapsedTime(1); + if (force) + { + computer = opponent; opponent = otherside[computer]; + } + (void) times(&tmbuf1); + signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch); +} + + +EditBoard() + +/* + Set up a board position. Pieces are entered by typing the piece + followed by the location. For example, Nf3 will place a knight on + square f3. +*/ + +{ +short a,r,c,sq; +char s[80]; + + ClrScreen(); + UpdateDisplay(0,0,1,0); + gotoXY(50,2); printz(". Exit to main"); + gotoXY(50,3); printz("# Clear board"); + gotoXY(49,5); printz("Enter piece & location: "); + a = white; + do + { + gotoXY(73,5); ClrEoln(); scanz("%s",s); + if (s[0] == '#') + { + for (sq = 0; sq < 64; sq++) + { + board[sq] = no_piece; color[sq] = neutral; + } + UpdateDisplay(0,0,1,0); + } + if (s[0] == 'c' || s[0] == 'C') a = otherside[a]; + c = s[1]-'a'; r = s[2]-'1'; + if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) + { + sq = locn[r][c]; + color[sq] = a; + if (s[0] == 'p') board[sq] = pawn; + else if (s[0] == 'n') board[sq] = knight; + else if (s[0] == 'b') board[sq] = bishop; + else if (s[0] == 'r') board[sq] = rook; + else if (s[0] == 'q') board[sq] = queen; + else if (s[0] == 'k') board[sq] = king; + else { board[sq] = no_piece; color[sq] = neutral; } + DrawPiece(sq); + } + } + while (s[0] != '.'); + if (board[4] != king) kingmoved[white] = 10; + if (board[60] != king) kingmoved[black] = 10; + GameCnt = -1; Game50 = 0; Sdepth = 0; + InitializeStats(); + ClrScreen(); + UpdateDisplay(0,0,1,0); +} + + +help() +{ + ClrScreen(); + gotoXY(28,1); printz("CHESS command summary"); + gotoXY(1,3); printz("g1f3 move from g1 to f3"); + gotoXY(1,4); printz("nf3 move knight to f3"); + gotoXY(1,5); printz("o-o castle king side"); + gotoXY(1,6); printz("o-o-o castle queen side"); + gotoXY(1,7); printz("edit edit board"); + gotoXY(1,8); printz("switch sides with computer"); + gotoXY(1,9); printz("white computer plays white"); + gotoXY(1,10); printz("black computer plays black"); + gotoXY(1,11); printz("reverse board display"); + gotoXY(1,12); printz("both computer match"); + gotoXY(1,13); printz("random randomize play"); + gotoXY(1,14); printz("undo undo last move"); + gotoXY(42,3); printz("level change level"); + gotoXY(42,4); printz("depth set search depth"); + gotoXY(42,5); printz("post principle variation"); + gotoXY(42,6); printz("hint suggest a move"); + gotoXY(42,7); printz("bd redraw board"); + gotoXY(42,8); printz("force enter game moves"); + gotoXY(42,9); printz("list game to chess.lst"); + gotoXY(42,10); printz("save game to file"); + gotoXY(42,11); printz("get game from file"); + gotoXY(42,12); printz("new start new game"); + gotoXY(42,13); printz("quit exit CHESS"); + gotoXY(10,21); printz("Computer: "); + if (computer == white) printz("WHITE"); else printz("BLACK"); + gotoXY(10,22); printz("Opponent: "); + if (opponent == white) printz("WHITE"); else printz("BLACK"); + gotoXY(10,23); printz("Level: %ld",Level," sec."); + gotoXY(10,24); printz("Easy mode: "); + if (easy) printz("ON"); else printz("OFF"); + gotoXY(40,21); printz("Depth: %d",MaxSearchDepth); + gotoXY(40,22); printz("Random: "); + if (dither) printz("ON"); else printz("OFF"); + gotoXY(40,23); printz("Transposition table: "); + if (hashflag) printz("ON"); else printz("OFF"); + refresh(); + while (getchar() != 27); + ClrScreen(); + UpdateDisplay(0,0,1,0); +} + + +ShowDepth(ch) +char ch; +{ + gotoXY(50,4); printz("Depth= %d%c ",Sdepth,ch); ClrEoln(); +} + + +ShowResults(score,bstline,ch) +short score; +unsigned short bstline[]; +char ch; +{ +short d,e,ply; + if (post && player == computer) + { + e = lpost; + gotoXY(50,5); printz("Score= %d",score); ClrEoln(); + d = 8; gotoXY(50,d); ClrEoln(); + for (ply = 1; bstline[ply] > 0; ply++) + { + algbr(bstline[ply] >> 8,bstline[ply] & 0xFF,false); + if (ply == 5 || ply == 9 || ply == 13 || ply == 17) + { + gotoXY(50,++d); ClrEoln(); + } + printz("%5s ",mvstr1); + } + ClrEoln(); + lpost = d; + while (++d <= e) + { + gotoXY(50,d); ClrEoln(); + } + } +} + + +SearchStartStuff(side) +short side; +{ +short i; + signal(SIGINT,TerminateSearch); signal(SIGQUIT,TerminateSearch); + if (player == computer) + for (i = 5; i < 14; i++) + { + gotoXY(50,i); ClrEoln(); + } +} + + +OutputMove() +{ + if (root->flags & epmask) UpdateDisplay(0,0,1,0); + else UpdateDisplay(root->f,root->t,0,root->flags & cstlmask); + gotoXY(50,17); printz("My move is: %s",mvstr1); + if (beep) putchar(7); + ClrEoln(); + + gotoXY(50,24); + if (root->flags & draw) printz("Draw game!"); + else if (root->score == -9999) printz("opponent mates!"); + else if (root->score == 9998) printz("computer mates!"); + else if (root->score < -9000) printz("opponent will soon mate!"); + else if (root->score > 9000) printz("computer will soon mate!"); + ClrEoln(); + + if (post) + { + gotoXY(50,22); printz("Nodes= %6ld",NodeCnt); ClrEoln(); + gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); ClrEoln(); + } +} + + +ElapsedTime(iop) + +/* + Determine the time that has passed since the search was started. If + the elapsed time exceeds the target (ResponseTime+ExtraTime) then set + timeout to true which will terminate the search. +*/ + +short iop; +{ + et = time((time_t *)0) - time0; + if (et < 0) et = 0; + ETnodes += 50; + if (et > et0 || iop == 1) + { + if (et > ResponseTime+ExtraTime && Sdepth > 1) timeout = true; + et0 = et; + if (iop == 1) + { + time0 = time((time_t *)0); et0 = 0; + } + (void) times(&tmbuf2); + cputimer = 100*(tmbuf2.tms_utime - tmbuf1.tms_utime) / HZ; + if (cputimer > 0) evrate = (100*NodeCnt)/(cputimer+100*ft); + else evrate = 0; + ETnodes = NodeCnt + 50; + UpdateClocks(); + } +} + + +UpdateClocks() +{ +short m,s; + m = et/60; s = (et - 60*m); + if (TCflag) + { + m = (TimeControl.clock[player] - et) / 60; + s = TimeControl.clock[player] - et - 60*m; + } + if (m < 0) m = 0; + if (s < 0) s = 0; + if (player == white) + if (reverse) gotoXY(20,2); else gotoXY(20,23); + else + if (reverse) gotoXY(20,23); else gotoXY(20,2); + printz("%d:%2d ",m,s); + if (post) + { + gotoXY(50,22); printz("Nodes= %6ld",NodeCnt); + gotoXY(50,23); printz("Nodes/Sec= %4ld",evrate); + } + refresh(); +} + + + +SetTimeControl() +{ + if (TCflag) + { + TimeControl.moves[white] = TimeControl.moves[black] = TCmoves; + TimeControl.clock[white] = TimeControl.clock[black] = 60*(long)TCminutes; + } + else + { + TimeControl.moves[white] = TimeControl.moves[black] = 0; + TimeControl.clock[white] = TimeControl.clock[black] = 0; + Level = 60*(long)TCminutes; + } + et = 0; + ElapsedTime(1); +} + + +gotoXY(x,y) +short x,y; +{ + move(y-1,x-1); +} + + +ClrScreen() +{ + clear(); refresh(); +} + + +ClrEoln() +{ + clrtoeol(); refresh(); +} + + +DrawPiece(sq) +short sq; +{ +short r,c; char x; + if (reverse) r = 7-row[sq]; else r = row[sq]; + if (reverse) c = 7-column[sq]; else c = column[sq]; + if (color[sq] == black) x = '*'; else x = ' '; + gotoXY(5+5*c,5+2*(7-r)); printz("%c%c ",x,pxx[board[sq]]); +} + + +UpdateDisplay(f,t,flag,iscastle) +short f,t,flag,iscastle; +{ +short i,l,z; + if (flag) + { + gotoXY(56,2); printz("CHESS"); + i = 3; + gotoXY(3,++i); + printz("|----|----|----|----|----|----|----|----|"); + while (i<19) + { + gotoXY(1,++i); + if (reverse) z = (i/2)-1; else z = 10-(i/2); + printz("%d | | | | | | | | |",z); + gotoXY(3,++i); + if (i < 19) + printz("+----+----+----+----+----+----+----+----+"); + } + printz("|----|----|----|----|----|----|----|----|"); + gotoXY(3,21); + if (reverse) printz(" h g f e d c b a"); + else printz(" a b c d e f g h"); + if (reverse) gotoXY(5,23); else gotoXY(5,2); + if (computer == black) printz("Computer"); else printz("Human "); + if (reverse) gotoXY(5,2); else gotoXY(5,23); + if (computer == white) printz("Computer"); else printz("Human "); + for (l = 0; l < 64; l++) DrawPiece(l); + } + else + { + DrawPiece(f); DrawPiece(t); + if (iscastle) + if (t > f) + { DrawPiece(f+3); DrawPiece(t-1); } + else + { DrawPiece(f-4); DrawPiece(t+1); } + } + refresh(); +} + + +GetOpenings() + +/* + Read in the Opening Book file and parse the algebraic notation for a + move into an unsigned integer format indicating the from and to + square. Create a linked list of opening lines of play, with + entry->next pointing to the next line and entry->move pointing to a + chunk of memory containing the moves. More Opening lines of up to 256 + half moves may be added to gnuchess.book. +*/ + +{ +FILE *fd; +int c,i,j,side; +struct BookEntry *entry; +unsigned short mv,*mp,tmp[100]; + + if ((fd = fopen(_PATH_CHESSBOOK,"r")) != NULL) + { + Book = NULL; + i = 0; side = white; + while ((c = parse(fd,&mv,side)) >= 0) + if (c == 1) + { + tmp[++i] = mv; + side = otherside[side]; + } + else if (c == 0 && i > 0) + { + entry = (struct BookEntry *)malloc(sizeof(struct BookEntry)); + mp = (unsigned short *)malloc((i+1)*sizeof(unsigned short)); + entry->mv = mp; + entry->next = Book; + Book = entry; + for (j = 1; j <= i; j++) *(mp++) = tmp[j]; + *mp = 0; + i = 0; side = white; + } + fclose(fd); + } + else + { + fprintf(stderr, "\nchess: can't read %s.\n", _PATH_CHESSBOOK); + exit(1); + } +} + + +int parse(fd,mv,side) +FILE *fd; +unsigned short *mv; +short side; +{ +int c,i,r1,r2,c1,c2; +char s[100]; + while ((c = getc(fd)) == ' '); + i = 0; s[0] = c; + while (c != ' ' && c != '\n' && c != EOF) s[++i] = c = getc(fd); + s[++i] = '\0'; + if (c == EOF) return(-1); + if (s[0] == '!' || i < 3) + { + while (c != '\n' && c != EOF) c = getc(fd); + return(0); + } + if (s[4] == 'o') + if (side == black) *mv = 0x3C3A; else *mv = 0x0402; + else if (s[0] == 'o') + if (side == black) *mv = 0x3C3E; else *mv = 0x0406; + else + { + c1 = s[0] - 'a'; r1 = s[1] - '1'; + c2 = s[2] - 'a'; r2 = s[3] - '1'; + *mv = (locn[r1][c1]<<8) + locn[r2][c2]; + } + return(1); +} + + +GetGame() +{ +FILE *fd; +char fname[40]; +int c; +short sq; +unsigned short m; + + ShowMessage("File name: "); + scanz("%s",fname); + if (fname[0] == '\0') strcpy(fname,"chess.000"); + if ((fd = fopen(fname,"r")) != NULL) + { + fscanf(fd,"%hd%hd%hd",&computer,&opponent,&Game50); + fscanf(fd,"%hd%hd%hd%hd", + &castld[white],&castld[black], + &kingmoved[white],&kingmoved[black]); + fscanf(fd,"%hd%hd",&TCflag,&OperatorTime); + fscanf(fd,"%ld%ld%hd%hd", + &TimeControl.clock[white],&TimeControl.clock[black], + &TimeControl.moves[white],&TimeControl.moves[black]); + for (sq = 0; sq < 64; sq++) + { + fscanf(fd,"%hd",&m); + board[sq] = (m >> 8); color[sq] = (m & 0xFF); + if (color[sq] == 0) color[sq] = neutral; else --color[sq]; + } + GameCnt = -1; c = '?'; + while (c != EOF) + { + ++GameCnt; + c = fscanf(fd,"%hd%hd%hd%ld%hd%hd%hd",&GameList[GameCnt].gmove, + &GameList[GameCnt].score,&GameList[GameCnt].depth, + &GameList[GameCnt].nodes,&GameList[GameCnt].time, + &GameList[GameCnt].piece,&GameList[GameCnt].color); + if (GameList[GameCnt].color == 0) GameList[GameCnt].color = neutral; + else --GameList[GameCnt].color; + } + GameCnt--; + if (TimeControl.clock[white] > 0) TCflag = true; + computer--; opponent--; + } + fclose(fd); + InitializeStats(); + UpdateDisplay(0,0,1,0); + Sdepth = 0; +} + + +SaveGame() +{ +FILE *fd; +char fname[40]; +short sq,i,c; + + ShowMessage("File name: "); + scanz("%s",fname); + + if (fname[0] == '\0' || access(fname,W_OK) == -1) strcpy(fname,"chess.000"); + fd = fopen(fname,"w"); + fprintf(fd,"%d %d %d\n",computer+1,opponent+1,Game50); + fprintf(fd,"%d %d %d %d\n", + castld[white],castld[black],kingmoved[white],kingmoved[black]); + fprintf(fd,"%d %d\n",TCflag,OperatorTime); + fprintf(fd,"%ld %ld %d %d\n", + TimeControl.clock[white],TimeControl.clock[black], + TimeControl.moves[white],TimeControl.moves[black]); + for (sq = 0; sq < 64; sq++) + { + if (color[sq] == neutral) c = 0; else c = color[sq]+1; + fprintf(fd,"%d\n",256*board[sq] + c); + } + for (i = 0; i <= GameCnt; i++) + { + if (GameList[i].color == neutral) c = 0; + else c = GameList[i].color + 1; + fprintf(fd,"%d %d %d %ld %d %d %d\n", + GameList[i].gmove,GameList[i].score,GameList[i].depth, + GameList[i].nodes,GameList[i].time, + GameList[i].piece,c); + } + fclose(fd); +} + + +ListGame() +{ +FILE *fd; +short i,f,t; + fd = fopen("chess.lst","w"); + fprintf(fd,"\n"); + fprintf(fd," score depth nodes time "); + fprintf(fd," score depth nodes time\n"); + for (i = 0; i <= GameCnt; i++) + { + f = GameList[i].gmove>>8; t = (GameList[i].gmove & 0xFF); + algbr(f,t,false); + if ((i % 2) == 0) fprintf(fd,"\n"); else fprintf(fd," "); + fprintf(fd,"%5s %5d %2d %6ld %5d",mvstr1, + GameList[i].score,GameList[i].depth, + GameList[i].nodes,GameList[i].time); + } + fprintf(fd,"\n\n"); + fclose(fd); +} + + +Undo() + +/* + Undo the most recent half-move. +*/ + +{ +short f,t; + f = GameList[GameCnt].gmove>>8; + t = GameList[GameCnt].gmove & 0xFF; + if (board[t] == king && distance(t,f) > 1) + castle(GameList[GameCnt].color,f,t,2); + else + { + board[f] = board[t]; color[f] = color[t]; + board[t] = GameList[GameCnt].piece; + color[t] = GameList[GameCnt].color; + if (board[f] == king) --kingmoved[color[f]]; + } + if (TCflag) ++TimeControl.moves[color[f]]; + GameCnt--; mate = false; Sdepth = 0; + UpdateDisplay(0,0,1,0); + InitializeStats(); +} + + +ShowMessage(s) +char *s; +{ + gotoXY(50,24); printz("%s",s); ClrEoln(); +} + +ClearMessage() +{ + gotoXY(50,24); ClrEoln(); +} + +ShowSidetomove() +{ + gotoXY(50,14); + if (player == white) printz("%2d: WHITE",1+(GameCnt+1)/2); + else printz("%2d: BLACK",1+(GameCnt+1)/2); + ClrEoln(); +} + +PromptForMove() +{ + gotoXY(50,19); printz("Your move is? "); ClrEoln(); +} + +ShowCurrentMove(pnt,f,t) +short pnt,f,t; +{ + algbr(f,t,false); + gotoXY(50,7); printz("(%2d) %4s",pnt,mvstr1); +} + +ChangeAlphaWindow() +{ + ShowMessage("window: "); + scanz("%hd",&Awindow); +} + +ChangeBetaWindow() +{ + ShowMessage("window: "); + scanz("%hd",&Bwindow); +} + +GiveHint() +{ +char s[40]; + algbr((short)(hint>>8),(short)(hint & 0xFF),false); + strcpy(s,"try "); + strcat(s,mvstr1); + ShowMessage(s); +} + +ChangeSearchDepth() +{ + ShowMessage("depth= "); + scanz("%hd",&MaxSearchDepth); +} + +SetContempt() +{ + ShowMessage("contempt= "); + scanz("%hd",&contempt); +} + +ChangeXwindow() +{ + ShowMessage("xwndw= "); + scanz("%hd",&xwndw); +} + + +SelectLevel() +{ + ClrScreen(); + gotoXY(32,2); printz("CHESS"); + gotoXY(20,4); printz(" 1. 60 moves in 5 minutes"); + gotoXY(20,5); printz(" 2. 60 moves in 15 minutes"); + gotoXY(20,6); printz(" 3. 60 moves in 30 minutes"); + gotoXY(20,7); printz(" 4. 40 moves in 30 minutes"); + gotoXY(20,8); printz(" 5. 40 moves in 60 minutes"); + gotoXY(20,9); printz(" 6. 40 moves in 120 minutes"); + gotoXY(20,10); printz(" 7. 40 moves in 240 minutes"); + gotoXY(20,11); printz(" 8. 1 move in 15 minutes"); + gotoXY(20,12); printz(" 9. 1 move in 60 minutes"); + gotoXY(20,13); printz("10. 1 move in 600 minutes"); + + OperatorTime = 0; TCmoves = 60; TCminutes = 5; + + gotoXY(20,17); printz("Enter Level: "); + refresh(); + scanz("%ld",&Level); + switch (Level) + { + case 1 : TCmoves = 60; TCminutes = 5; break; + case 2 : TCmoves = 60; TCminutes = 15; break; + case 3 : TCmoves = 60; TCminutes = 30; break; + case 4 : TCmoves = 40; TCminutes = 30; break; + case 5 : TCmoves = 40; TCminutes = 60; break; + case 6 : TCmoves = 40; TCminutes = 120; break; + case 7 : TCmoves = 40; TCminutes = 240; break; + case 8 : TCmoves = 1; TCminutes = 15; break; + case 9 : TCmoves = 1; TCminutes = 60; break; + case 10 : TCmoves = 1; TCminutes = 600; break; + } + + TCflag = (TCmoves > 1); + SetTimeControl(); + ClrScreen(); + UpdateDisplay(0,0,1,0); +} + + +ShowPostnValues() +{ +short i,r,c; + ExaminePosition(); + for (i = 0; i < 64; i++) + { + if (reverse) r = 7-row[i]; else r = row[i]; + if (reverse) c = 7-column[i]; else c = column[i]; + gotoXY(4+5*c,5+2*(7-r)); + c1 = color[i]; c2 = otherside[c1]; + PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; + atk1 = atak[c1]; atk2 = atak[c2]; + if (color[i] == neutral) printz(" "); + else printz("%3d ",SqValue(i,opponent)); + } + ScorePosition(opponent,&i); + gotoXY(50,24); + printz("Score= %d",i); ClrEoln(); +} + + +DoDebug() +{ +short k,p,i,r,c,tp,tc; +char s[40]; + ExaminePosition(); + ShowMessage("Enter piece: "); + scanz("%s",s); + if (s[0] == 'w') k = white; else k = black; + if (s[1] == 'p') p = pawn; + else if (s[1] == 'n') p = knight; + else if (s[1] == 'b') p = bishop; + else if (s[1] == 'r') p = rook; + else if (s[1] == 'q') p = queen; + else if (s[1] == 'k') p = king; + else p = no_piece; + for (i = 0; i < 64; i++) + { + if (reverse) r = 7-row[i]; else r = row[i]; + if (reverse) c = 7-column[i]; else c = column[i]; + gotoXY(4+5*c,5+2*(7-r)); + tp = board[i]; tc = color[i]; + board[i] = p; color[i] = k; + c1 = k; c2 = otherside[c1]; + PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2]; + atk1 = atak[c1]; atk2 = atak[c2]; + printz("%3d ",SqValue(i,opponent)); + board[i] = tp; color[i] = tc; + } + ScorePosition(opponent,&i); + gotoXY(50,24); + printz("Score= %d",i); ClrEoln(); +} diff --git a/share/man/man4/man4.i386/Makefile b/share/man/man4/man4.i386/Makefile new file mode 100644 index 000000000000..b675c4b994cb --- /dev/null +++ b/share/man/man4/man4.i386/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 0.1 (RWGrimes) 3/25/93 + +MAN4= mem.0 spkr.0 +MLINKS= mem.4 kmem.4 +MANSUBDIR=/i386 + +.include diff --git a/share/man/man4/man4.i386/mem.4 b/share/man/man4/man4.i386/mem.4 new file mode 100644 index 000000000000..1080cac5f687 --- /dev/null +++ b/share/man/man4/man4.i386/mem.4 @@ -0,0 +1,82 @@ +.\" Copyright (c) 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)mem.4 5.3 (Berkeley) 5/2/91 +.\" +.Dd May 2, 1991 +.Dt MEM 4 i386 +.Os +.Sh NAME +.Nm mem , +.Nm kmem +.Nd memory files +.Sh DESCRIPTION +The special file +.Nm /dev/mem +is an interface to the physical memory of the computer. +Byte offsets in this file are interpreted as physical memory addresses. +Reading and writing this file is equivalent to reading and writing +memory itself. +Only offsets within the bounds of +.Nm /dev/mem +are allowed. +.Pp +Kernel virtual memory is accessed through the interface +.Nm /dev/kmem +in the same manner as +.Nm /dev/mem . +Only kernel virtual addresses that are currently mapped to memory are allowed. +.Pp +On +.Tn ISA +the +.Tn I/O +memory space begins at physical address 0x000a0000 +and runs to 0x00100000. +The +per-process data +size +for the current process +is +.Dv UPAGES +long, and ends at virtual +address 0xfe000000. +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /dev/mem +.It Pa /dev/kmem +.El +.Sh HISTORY +The +.Nm mem , +.Nm kmem +files appeared in +.At v6 . diff --git a/share/man/man4/man4.i386/spkr.4 b/share/man/man4/man4.i386/spkr.4 new file mode 100644 index 000000000000..b211674893f0 --- /dev/null +++ b/share/man/man4/man4.i386/spkr.4 @@ -0,0 +1,117 @@ +.TH SPKR 4 +.SH NAME +spkr \- console speaker device driver +.SH DESCRIPTION +The speaker device driver allows applications to control the PC console +speaker on an IBM-PC-compatible machine running UNIX. +.PP +Only one process may have this device open at any given time; open() and +close() are used to lock and relinquish it. An attempt to open() when +another process has the device locked will return -1 with an EBUSY error +indication. Writes to the device are interpreted as 'play strings' in a +simple ASCII melody notation. An ioctl() for tone generation at arbitrary +frequencies is also supported. +.PP +Sound-generation does \fInot\fR monopolize the processor; in fact, the driver +spends most of its time sleeping while the PC hardware is emitting +tones. Other processes may emit beeps while the driver is running. +.PP +Applications may call ioctl() on a speaker file descriptor to control the +speaker driver directly; definitions for the ioctl() interface are in +sys/spkr.h. The tone_t structure used in these calls has two fields, +specifying a frequency (in hz) and a duration (in 1/100ths of a second). +A frequency of zero is interpreted as a rest. +.PP +At present there are two such ioctls. SPKRTONE accepts a pointer to a +single tone structure as third argument and plays it. SPKRTUNE accepts a +pointer to the first of an array of tone structures and plays them in +continuous sequence; this array must be terminated by a final member with +a zero duration. +.PP +The play-string language is modelled on the PLAY statement conventions of +IBM BASIC 2.0. The MB, MF and X primitives of PLAY are not useful in a UNIX +environment and are omitted. The `octave-tracking' feature is also new. +.PP +There are 84 accessible notes numbered 1-83 in 7 octaves, each running from +C to B, numbered 0-6; the scale is equal-tempered A440 and octave 3 starts +with middle C. By default, the play function emits half-second notes with the +last 1/16th second being `rest time'. +.PP +Play strings are interpreted left to right as a series of play command groups; +letter case is ignored. Play command groups are as follows: +.PP +CDEFGAB -- letters A through G cause the corresponding note to be played in the +current octave. A note letter may optionally be followed by an \fIaccidental +sign\fR, one of # + or -; the first two of these cause it to be sharped one +half-tone, the last causes it to be flatted one half-tone. It may also be +followed by a time value number and by sustain dots (see below). Time values +are interpreted as for the L command below;. +.PP +O -- if is numeric, this sets the current octave. may also be one +of 'L' or 'N' to enable or disable octave-tracking (it is disabled by default). +When octave-tracking is on, interpretation of a pair of letter notes will +change octaves if necessary in order to make the smallest possible jump between +notes. Thus "olbc" will be played as "olb>c", and "olcb" as "olc, < and O[0123456]. +.PP +> -- bump the current octave up one. +.PP +< -- drop the current octave down one. +.PP +N -- play note n, n being 1 to 84 or 0 for a rest of current time value. +May be followedv by sustain dots. +.PP +L -- sets the current time value for notes. The default is L4, quarter +notes. The lowest possible value is 1; values up to 64 are accepted. L1 sets +whole notes, L2 sets half notes, L4 sets quarter notes, etc.. +.PP +P -- pause (rest), with interpreted as for L. May be followed by +sustain dots. May also be written '~'. +.PP +T -- Sets the number of quarter notes per minute; default is 120. Musical +names for common tempi are: + +.TS +a a a. + Tempo Beats Per Minute +very slow Larghissimo + Largo 40-60 + Larghetto 60-66 + Grave + Lento + Adagio 66-76 +slow Adagietto + Andante 76-108 +medium Andantino + Moderato 108-120 +fast Allegretto + Allegro 120-168 + Vivace + Veloce + Presto 168-208 +very fast Prestissimo +.TE +.PP +M[LNS] -- set articulation. MN (N for normal) is the default; the last 1/8th of +the note's value is rest time. You can set ML for legato (no rest space) or +MS (staccato) 1/4 rest space. +.PP +Notes (that is, CDEFGAB or N command character groups) may be followed by +sustain dots. Each dot causes the note's value to be lengthened by one-half +for each one. Thus, a note dotted once is held for 3/2 of its undotted value; +dotted twice, it is held 9/4, and three times would give 27/8. +.PP +Whitespace in play strings is simply skipped and may be used to separate +melody sections. +.SH BUGS +Due to roundoff in the pitch tables and slop in the tone-generation and timer +hardware (neither of which was designed for precision), neither pitch accuracy +nor timings will be mathematically exact. There is no volume control. +.PP +In play strings which are very long (longer than your system's physical I/O +blocks) note suffixes or numbers may occasionally be parsed incorrectly due +to crossing a block boundary. +.SH FILES +/dev/speaker -- speaker device file +.SH AUTHOR +Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990 diff --git a/share/man/man4/mem.4 b/share/man/man4/mem.4 new file mode 100644 index 000000000000..1080cac5f687 --- /dev/null +++ b/share/man/man4/mem.4 @@ -0,0 +1,82 @@ +.\" Copyright (c) 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)mem.4 5.3 (Berkeley) 5/2/91 +.\" +.Dd May 2, 1991 +.Dt MEM 4 i386 +.Os +.Sh NAME +.Nm mem , +.Nm kmem +.Nd memory files +.Sh DESCRIPTION +The special file +.Nm /dev/mem +is an interface to the physical memory of the computer. +Byte offsets in this file are interpreted as physical memory addresses. +Reading and writing this file is equivalent to reading and writing +memory itself. +Only offsets within the bounds of +.Nm /dev/mem +are allowed. +.Pp +Kernel virtual memory is accessed through the interface +.Nm /dev/kmem +in the same manner as +.Nm /dev/mem . +Only kernel virtual addresses that are currently mapped to memory are allowed. +.Pp +On +.Tn ISA +the +.Tn I/O +memory space begins at physical address 0x000a0000 +and runs to 0x00100000. +The +per-process data +size +for the current process +is +.Dv UPAGES +long, and ends at virtual +address 0xfe000000. +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /dev/mem +.It Pa /dev/kmem +.El +.Sh HISTORY +The +.Nm mem , +.Nm kmem +files appeared in +.At v6 . diff --git a/share/man/man4/spkr.4 b/share/man/man4/spkr.4 new file mode 100644 index 000000000000..b211674893f0 --- /dev/null +++ b/share/man/man4/spkr.4 @@ -0,0 +1,117 @@ +.TH SPKR 4 +.SH NAME +spkr \- console speaker device driver +.SH DESCRIPTION +The speaker device driver allows applications to control the PC console +speaker on an IBM-PC-compatible machine running UNIX. +.PP +Only one process may have this device open at any given time; open() and +close() are used to lock and relinquish it. An attempt to open() when +another process has the device locked will return -1 with an EBUSY error +indication. Writes to the device are interpreted as 'play strings' in a +simple ASCII melody notation. An ioctl() for tone generation at arbitrary +frequencies is also supported. +.PP +Sound-generation does \fInot\fR monopolize the processor; in fact, the driver +spends most of its time sleeping while the PC hardware is emitting +tones. Other processes may emit beeps while the driver is running. +.PP +Applications may call ioctl() on a speaker file descriptor to control the +speaker driver directly; definitions for the ioctl() interface are in +sys/spkr.h. The tone_t structure used in these calls has two fields, +specifying a frequency (in hz) and a duration (in 1/100ths of a second). +A frequency of zero is interpreted as a rest. +.PP +At present there are two such ioctls. SPKRTONE accepts a pointer to a +single tone structure as third argument and plays it. SPKRTUNE accepts a +pointer to the first of an array of tone structures and plays them in +continuous sequence; this array must be terminated by a final member with +a zero duration. +.PP +The play-string language is modelled on the PLAY statement conventions of +IBM BASIC 2.0. The MB, MF and X primitives of PLAY are not useful in a UNIX +environment and are omitted. The `octave-tracking' feature is also new. +.PP +There are 84 accessible notes numbered 1-83 in 7 octaves, each running from +C to B, numbered 0-6; the scale is equal-tempered A440 and octave 3 starts +with middle C. By default, the play function emits half-second notes with the +last 1/16th second being `rest time'. +.PP +Play strings are interpreted left to right as a series of play command groups; +letter case is ignored. Play command groups are as follows: +.PP +CDEFGAB -- letters A through G cause the corresponding note to be played in the +current octave. A note letter may optionally be followed by an \fIaccidental +sign\fR, one of # + or -; the first two of these cause it to be sharped one +half-tone, the last causes it to be flatted one half-tone. It may also be +followed by a time value number and by sustain dots (see below). Time values +are interpreted as for the L command below;. +.PP +O -- if is numeric, this sets the current octave. may also be one +of 'L' or 'N' to enable or disable octave-tracking (it is disabled by default). +When octave-tracking is on, interpretation of a pair of letter notes will +change octaves if necessary in order to make the smallest possible jump between +notes. Thus "olbc" will be played as "olb>c", and "olcb" as "olc, < and O[0123456]. +.PP +> -- bump the current octave up one. +.PP +< -- drop the current octave down one. +.PP +N -- play note n, n being 1 to 84 or 0 for a rest of current time value. +May be followedv by sustain dots. +.PP +L -- sets the current time value for notes. The default is L4, quarter +notes. The lowest possible value is 1; values up to 64 are accepted. L1 sets +whole notes, L2 sets half notes, L4 sets quarter notes, etc.. +.PP +P -- pause (rest), with interpreted as for L. May be followed by +sustain dots. May also be written '~'. +.PP +T -- Sets the number of quarter notes per minute; default is 120. Musical +names for common tempi are: + +.TS +a a a. + Tempo Beats Per Minute +very slow Larghissimo + Largo 40-60 + Larghetto 60-66 + Grave + Lento + Adagio 66-76 +slow Adagietto + Andante 76-108 +medium Andantino + Moderato 108-120 +fast Allegretto + Allegro 120-168 + Vivace + Veloce + Presto 168-208 +very fast Prestissimo +.TE +.PP +M[LNS] -- set articulation. MN (N for normal) is the default; the last 1/8th of +the note's value is rest time. You can set ML for legato (no rest space) or +MS (staccato) 1/4 rest space. +.PP +Notes (that is, CDEFGAB or N command character groups) may be followed by +sustain dots. Each dot causes the note's value to be lengthened by one-half +for each one. Thus, a note dotted once is held for 3/2 of its undotted value; +dotted twice, it is held 9/4, and three times would give 27/8. +.PP +Whitespace in play strings is simply skipped and may be used to separate +melody sections. +.SH BUGS +Due to roundoff in the pitch tables and slop in the tone-generation and timer +hardware (neither of which was designed for precision), neither pitch accuracy +nor timings will be mathematically exact. There is no volume control. +.PP +In play strings which are very long (longer than your system's physical I/O +blocks) note suffixes or numbers may occasionally be parsed incorrectly due +to crossing a block boundary. +.SH FILES +/dev/speaker -- speaker device file +.SH AUTHOR +Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990 diff --git a/usr.bin/symorder/Makefile b/usr.bin/symorder/Makefile new file mode 100644 index 000000000000..5fe1caf67046 --- /dev/null +++ b/usr.bin/symorder/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 5.3 (Berkeley) 5/11/90 + +PROG= symorder + +.include diff --git a/usr.bin/symorder/symorder.1 b/usr.bin/symorder/symorder.1 new file mode 100644 index 000000000000..f113bcafd40d --- /dev/null +++ b/usr.bin/symorder/symorder.1 @@ -0,0 +1,81 @@ +.\" Copyright (c) 1980, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.\" @(#)symorder.1 6.5 (Berkeley) 4/22/91 +.\" +.Dd April 22, 1991 +.Dt SYMORDER 1 +.Os BSD 3 +.Sh NAME +.Nm symorder +.Nd rearrange name list +.Sh SYNOPSIS +.Nm symorder +.Fl t Ar symlist file +.Sh DESCRIPTION +The file +.Ar symlist +contains a list of symbols to be found in +.Ar file, +one symbol per line. +.Pp +The symbol table of +.Ar file +is updated in place; +symbols read from +.Ar symlist +are relocated to the beginning of the table and in the order given. +.Bl -tag -width flag +.It Fl t +Restrict the symbol table to the symbols listed in +.Ar symlist . +.El +.Pp +This program was specifically designed to cut down on the +overhead of getting symbols from +.Pa /vmunix. +.Sh DIAGNOSTICS +The +.Nm symorder +utility exits 0 on success, 1 if a symbol +listed in the +.Ar symlist +file was not found in the symbol +table, and >1 if an error occurs. +.Sh SEE ALSO +.Xr nm 3 , +.Xr nlist 3 , +.Xr strip 3 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/usr.bin/symorder/symorder.c b/usr.bin/symorder/symorder.c new file mode 100644 index 000000000000..4c41a14b7055 --- /dev/null +++ b/usr.bin/symorder/symorder.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 1980 The Regents of the University of California. + * All rights reserved. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)symorder.c 5.8 (Berkeley) 4/1/91"; +#endif /* not lint */ + +/* + * symorder - reorder symbol table + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPACE 500 + +#define OKEXIT 0 +#define NOTFOUNDEXIT 1 +#define ERREXIT 2 + +struct nlist order[SPACE]; + +struct exec exec; +struct stat stb; +struct nlist *newtab, *symtab; +off_t sa; +int nsym, strtabsize, symfound, small; +char *kfile, *newstrings, *strings, asym[BUFSIZ]; + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + register struct nlist *p, *symp; + register FILE *f; + register int i; + register char *start, *t; + int ch, n, o; + + while ((ch = getopt(argc, argv, "t")) != EOF) + switch(ch) { + case 't': + small = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 2) + usage(); + + if ((f = fopen(argv[0], "r")) == NULL) + error(argv[0]); + + for (p = order; fgets(asym, sizeof(asym), f) != NULL;) { + for (t = asym; isspace(*t); ++t); + if (!*(start = t)) + continue; + while (*++t); + if (*--t == '\n') + *t = '\0'; + p->n_un.n_name = strdup(start); + ++p; + ++nsym; + } + (void)fclose(f); + + kfile = argv[1]; + if ((f = fopen(kfile, "r")) == NULL) + error(kfile); + if ((o = open(kfile, O_WRONLY)) < 0) + error(kfile); + + /* read exec header */ + if ((fread(&exec, sizeof(exec), 1, f)) != 1) + badfmt("no exec header"); + if (N_BADMAG(exec)) + badfmt("bad magic number"); + if (exec.a_syms == 0) + badfmt("stripped"); + (void)fstat(fileno(f), &stb); + if (stb.st_size < N_STROFF(exec) + sizeof(off_t)) + badfmt("no string table"); + + /* seek to and read the symbol table */ + sa = N_SYMOFF(exec); + (void)fseek(f, sa, SEEK_SET); + n = exec.a_syms; + if (!(symtab = (struct nlist *)malloc(n))) + error(NULL); + if (fread((void *)symtab, 1, n, f) != n) + badfmt("corrupted symbol table"); + + /* read string table size and string table */ + if (fread((void *)&strtabsize, sizeof(int), 1, f) != 1 || + strtabsize <= 0) + badfmt("corrupted string table"); + strings = malloc(strtabsize); + if (strings == NULL) + error(NULL); + /* + * Subtract four from strtabsize since strtabsize includes itself, + * and we've already read it. + */ + if (fread(strings, 1, strtabsize - sizeof(int), f) != + strtabsize - sizeof(int)) + badfmt("corrupted string table"); + + newtab = (struct nlist *)malloc(n); + if (newtab == (struct nlist *)NULL) + error(NULL); + + i = n / sizeof(struct nlist); + reorder(symtab, newtab, i); + free((void *)symtab); + symtab = newtab; + + newstrings = malloc(strtabsize); + if (newstrings == NULL) + error(NULL); + t = newstrings; + for (symp = symtab; --i >= 0; symp++) { + if (symp->n_un.n_strx == 0) + continue; + if (small && inlist(symp) < 0) continue; + symp->n_un.n_strx -= sizeof(int); + (void)strcpy(t, &strings[symp->n_un.n_strx]); + symp->n_un.n_strx = (t - newstrings) + sizeof(int); + t += strlen(t) + 1; + } + + /* update shrunk sizes */ + if(small) { + strtabsize = t - newstrings + sizeof(int); + n = symfound * sizeof(struct nlist); + /* fix exec sym size */ + (void)lseek(o, 0, SEEK_SET); + exec.a_syms = n; + if (write(o, (void *)&exec, sizeof(exec)) != sizeof(exec)) + error(kfile); + } + + (void)lseek(o, sa, SEEK_SET); + if (write(o, (void *)symtab, n) != n) + error(kfile); + if (write(o, (void *)&strtabsize, sizeof(int)) != sizeof(int)) + error(kfile); + if (write(o, newstrings, strtabsize - sizeof(int)) != + strtabsize - sizeof(int)) + error(kfile); + + if (small) ftruncate(o, lseek(o, 0, SEEK_CUR)); + + if ((i = nsym - symfound) > 0) { + (void)printf("symorder: %d symbol%s not found:\n", + i, i == 1 ? "" : "s"); + for (i = 0; i < nsym; i++) + if (order[i].n_value == 0) + printf("%s\n", order[i].n_un.n_name); + exit(NOTFOUNDEXIT); + } + exit(OKEXIT); +} + +reorder(st1, st2, entries) + register struct nlist *st1, *st2; + int entries; +{ + register struct nlist *p; + register int i, n; + + for (p = st1, n = entries; --n >= 0; ++p) + if (inlist(p) != -1) + ++symfound; + for (p = st2 + symfound, n = entries; --n >= 0; ++st1) { + i = inlist(st1); + if (i == -1) + *p++ = *st1; + else + st2[i] = *st1; + } +} + +inlist(p) + register struct nlist *p; +{ + register char *nam; + register struct nlist *op; + + if (p->n_type & N_STAB) + return (-1); + if (p->n_un.n_strx == 0) + return (-1); + + if (p->n_un.n_strx >= strtabsize) + badfmt("corrupted symbol table"); + + nam = &strings[p->n_un.n_strx - sizeof(int)]; + for (op = &order[nsym]; --op >= order; ) { + if (strcmp(op->n_un.n_name, nam) != 0) + continue; + op->n_value = 1; + return (op - order); + } + return (-1); +} + +badfmt(why) + char *why; +{ + (void)fprintf(stderr, + "symorder: %s: %s: %s\n", kfile, why, strerror(EFTYPE)); + exit(ERREXIT); +} + +error(n) + char *n; +{ + int sverr; + + sverr = errno; + (void)fprintf(stderr, "symorder: "); + if (n) + (void)fprintf(stderr, "%s: ", n); + (void)fprintf(stderr, "%s\n", strerror(sverr)); + exit(ERREXIT); +} + +usage() +{ + (void)fprintf(stderr, "usage: symorder [-t] symlist file\n"); + exit(ERREXIT); +} diff --git a/usr.sbin/dbsym/Makefile b/usr.sbin/dbsym/Makefile new file mode 100644 index 000000000000..95ab527a9dd2 --- /dev/null +++ b/usr.sbin/dbsym/Makefile @@ -0,0 +1,4 @@ +PROG= dbsym +NOMAN= noman + +.include diff --git a/usr.sbin/dbsym/dbsym.c b/usr.sbin/dbsym/dbsym.c new file mode 100644 index 000000000000..46514b4c1e32 --- /dev/null +++ b/usr.sbin/dbsym/dbsym.c @@ -0,0 +1,192 @@ +/* Written by Pace Willisson (pace@blitz.com) + * and placed in the public domain. + */ +#include +#include + +char *malloc (); + +#define FILE_OFFSET(vadr) (((vadr) & ~0xff000000)-N_DATADDR(hdr)+N_DATOFF(hdr)) + +struct nlist *old_syms; +int num_old_syms; +char *old_strtab; +int old_strtab_size; + +struct nlist *new_syms; +int num_new_syms; +int new_syms_bytes; +char *new_strtab; +int new_strtab_size; + +int db_symtabsize_adr; +int db_symtab_adr; + +int avail; + + +usage () +{ + fprintf (stderr, "usage: dbsym file\n"); + exit (1); +} + +struct exec hdr; + +main (argc, argv) +char **argv; +{ + FILE *f; + char *name; + extern int optind; + int c, i; + int need; + char *buf, *p; + struct nlist *nsp, *sp; + int len; + + + while ((c = getopt (argc, argv, "")) != EOF) { + switch (c) { + default: + usage (); + } + } + + if (optind >= argc) + usage (); + + name = argv[optind++]; + + if (optind != argc) + usage (); + + if ((f = fopen (name, "r+")) == NULL) { + fprintf (stderr, "can't open %s\n", name); + exit (1); + } + + if (fread ((char *)&hdr, sizeof hdr, 1, f) != 1) { + fprintf (stderr, "can't read header\n"); + exit (1); + } + + if (N_BADMAG (hdr)) { + fprintf (stderr, "bad magic number\n"); + exit (1); + } + + if (hdr.a_syms == 0) { + fprintf (stderr, "no symbols\n"); + exit (1); + } + + fseek (f, N_STROFF (hdr), 0); + if (fread ((char *)&old_strtab_size, sizeof (int), 1, f) != 1) { + fprintf (stderr, "can't read old strtab size\n"); + exit (1); + } + + if ((old_syms = (struct nlist *)malloc (hdr.a_syms)) == NULL + || ((old_strtab = malloc (old_strtab_size)) == NULL) + || ((new_syms = (struct nlist *)malloc (hdr.a_syms)) == NULL) + || ((new_strtab = malloc (old_strtab_size)) == NULL)) { + fprintf (stderr, "out of memory\n"); + exit (1); + } + + fseek (f, N_SYMOFF (hdr), 0); + if (fread ((char *)old_syms, hdr.a_syms, 1, f) != 1) { + fprintf (stderr, "can't read symbols\n"); + exit (1); + } + + fseek (f, N_STROFF (hdr), 0); + if (fread ((char *)old_strtab, old_strtab_size, 1, f) != 1) { + fprintf (stderr, "can't read string table\n"); + exit (1); + } + + num_old_syms = hdr.a_syms / sizeof (struct nlist); + + new_strtab_size = 4; + + nsp = new_syms; + for (i = 0, sp = old_syms; i < num_old_syms; i++, sp++) { + if (sp->n_type & N_STAB) + continue; + if (sp->n_un.n_strx == 0) + continue; + + if (sp->n_value < 0xfe000000) + continue; + + if (sp->n_value >= 0xff000000) + continue; + + name = old_strtab + sp->n_un.n_strx; + + len = strlen (name); + + if (len == 0) + continue; + + if (len >= 2 && name[len - 2] == '.' && name[len - 1] == 'o') + continue; + + if (strcmp (name, "gcc_compiled.") == 0) + continue; + + *nsp = *sp; + + nsp->n_un.n_strx = new_strtab_size; + strcpy (new_strtab + new_strtab_size, name); + new_strtab_size += len + 1; + nsp++; + + if (strcmp (name, "_db_symtab") == 0) + db_symtab_adr = sp->n_value; + if (strcmp (name, "_db_symtabsize") == 0) + db_symtabsize_adr = sp->n_value; + } + + if (db_symtab_adr == 0 || db_symtabsize_adr == 0) { + fprintf (stderr, "couldn't find db_symtab symbols\n"); + exit (1); + } + + *(int *)new_strtab = new_strtab_size; + num_new_syms = nsp - new_syms; + new_syms_bytes = num_new_syms * sizeof (struct nlist); + + need = sizeof (int) + + num_new_syms * sizeof (struct nlist) + + new_strtab_size; + + fseek (f, FILE_OFFSET (db_symtabsize_adr), 0); + + if (fread ((char *)&avail, sizeof (int), 1, f) != 1) { + fprintf (stderr, "can't read symtabsize\n"); + exit (1); + } + + printf ("dbsym: need %d; avail %d\n", need, avail); + + if (need > avail) { + fprintf (stderr, "not enough room in db_symtab array\n"); + exit (1); + } + + fseek (f, FILE_OFFSET (db_symtab_adr), 0); + fwrite ((char *)&new_syms_bytes, sizeof (int), 1, f); + fwrite ((char *)new_syms, new_syms_bytes, 1, f); + fwrite (new_strtab, new_strtab_size, 1, f); + fflush (f); + + if (feof (f) || ferror (f)) { + fprintf (stderr, "write error\n"); + exit (1); + } + exit (0); +} + diff --git a/usr.sbin/tcpdump/Makefile b/usr.sbin/tcpdump/Makefile new file mode 100644 index 000000000000..0a1f2533744b --- /dev/null +++ b/usr.sbin/tcpdump/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 0.1 (RGrimes) 4/4/93 + +SUBDIR= tcpdump tcpslice + +.include diff --git a/usr.sbin/tcpdump/Makefile.inc b/usr.sbin/tcpdump/Makefile.inc new file mode 100644 index 000000000000..948999506171 --- /dev/null +++ b/usr.sbin/tcpdump/Makefile.inc @@ -0,0 +1,3 @@ +# @(#)Makefile.inc 5.1 (Berkeley) 5/11/90 + +BINDIR?= /usr/local/bin diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile new file mode 100644 index 000000000000..fee95540b94b --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/Makefile @@ -0,0 +1,24 @@ +# @(#)Makefile 0.1 (RWGrimes) 3/24/93 + +PROG= tcpdump +CFLAGS+=-DCSLIP -I. +MAN1= tcpdump.0 +SRCS= version.c addrtoname.c bpf_dump.c bpf_filter.c bpf_image.c etherent.c \ + gencode.c inet.c md.c nametoaddr.c optimize.c os.c pcap.c \ + print-arp.c print-atalk.c print-bootp.c print-domain.c \ + print-egp.c print-ether.c print-fddi.c print-icmp.c print-ip.c \ + print-nfs.c print-ntp.c print-null.c print-ospf.c print-ppp.c \ + print-rip.c print-sl.c print-snmp.c print-sunrpc.c print-tcp.c \ + print-tftp.c print-udp.c savefile.c tcpdump.c tcpgram.c \ + tcplex.c util.c +.PATH: /sys/net +CLEANFILES+= tcpgram.c tcplex.c y.tab.h y.tab.c version.c version.h + +version.c version.h: VERSION + rm -f version.c ; \ + sed 's/.*/char version[] = "&";/' $(.CURDIR)/VERSION > version.c + set `sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \2/' $(.CURDIR)/VERSION` ; \ + { echo '#define VERSION_MAJOR' $$1 ; \ + echo '#define VERSION_MINOR' $$2 ; } > version.h + +.include diff --git a/usr.sbin/tcpdump/tcpdump/VERSION b/usr.sbin/tcpdump/tcpdump/VERSION new file mode 100644 index 000000000000..c043eea7767e --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/VERSION @@ -0,0 +1 @@ +2.2.1 diff --git a/usr.sbin/tcpdump/tcpdump/addrtoname.c b/usr.sbin/tcpdump/tcpdump/addrtoname.c new file mode 100644 index 000000000000..5c7086518a56 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/addrtoname.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 1988, 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Internet, ethernet, port, and protocol string to address + * and address to string conversion routines + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: addrtoname.c,v 1.14 92/05/25 14:29:07 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "nametoaddr.h" +#include "etherent.h" + +/* + * hash tables for whatever-to-name translations + */ + +#define HASHNAMESIZE 4096 + +struct hnamemem { + u_long addr; + char *name; + struct hnamemem *nxt; +}; + +struct hnamemem hnametable[HASHNAMESIZE]; +struct hnamemem tporttable[HASHNAMESIZE]; +struct hnamemem uporttable[HASHNAMESIZE]; +struct hnamemem eprototable[HASHNAMESIZE]; + +struct enamemem { + u_short e_addr0; + u_short e_addr1; + u_short e_addr2; + char *e_name; + struct enamemem *e_nxt; +}; + +struct enamemem enametable[HASHNAMESIZE]; + + +/* + * A faster replacement for inet_ntoa(). + */ +char * +intoa(addr) + u_long addr; +{ + register char *cp; + register u_int byte; + register int n; + static char buf[sizeof(".xxx.xxx.xxx.xxx")]; + + NTOHL(addr); + cp = &buf[sizeof buf]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + return cp + 1; +} + +static u_long f_netmask; +static u_long f_localnet; +static u_long netmask; + +/* + * "getname" is written in this atrocious way to make sure we don't + * wait forever while trying to get hostnames from yp. + */ +#include + +jmp_buf getname_env; + +static void +nohostname() +{ + longjmp(getname_env, 1); +} + +/* + * Return a name for the IP address pointed to by ap. This address + * is assumed to be in network byte order. + */ +char * +getname(ap) + u_char *ap; +{ + register struct hnamemem *p; + register struct hostent *hp; + register char *cp; + u_long addr; + +#ifndef TCPDUMP_ALIGN + addr = *(u_long *)ap; +#else + /* + * Deal with alignment. + */ + switch ((int)ap & 3) { + + case 0: + addr = *(u_long *)ap; + break; + + case 2: +#if BYTE_ORDER == LITTLE_ENDIAN + addr = ((u_long)*(u_short *)(ap + 2) << 16) | + (u_long)*(u_short *)ap; +#else + addr = ((u_long)*(u_short *)ap << 16) | + (u_long)*(u_short *)(ap + 2); +#endif + break; + + default: +#if BYTE_ORDER == LITTLE_ENDIAN + addr = ((u_long)ap[0] << 24) | + ((u_long)ap[1] << 16) | + ((u_long)ap[2] << 8) | + (u_long)ap[3]; +#else + addr = ((u_long)ap[3] << 24) | + ((u_long)ap[2] << 16) | + ((u_long)ap[1] << 8) | + (u_long)ap[0]; +#endif + break; + } +#endif + p = &hnametable[addr & (HASHNAMESIZE-1)]; + for (; p->nxt; p = p->nxt) { + if (p->addr == addr) + return (p->name); + } + p->addr = addr; + p->nxt = (struct hnamemem *)calloc(1, sizeof (*p)); + + /* + * Only print names when: + * (1) -n was not given. + * (2) Address is foreign and -f was given. If -f was not + * present, f_netmask and f_local are 0 and the second + * test will succeed. + * (3) The host portion is not 0 (i.e., a network address). + * (4) The host portion is not broadcast. + */ + if (!nflag && (addr & f_netmask) == f_localnet + && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) { + if (!setjmp(getname_env)) { + (void)signal(SIGALRM, nohostname); + (void)alarm(20); + hp = gethostbyaddr((char *)&addr, 4, AF_INET); + (void)alarm(0); + if (hp) { + char *index(); + char *dotp; + u_int len = strlen(hp->h_name) + 1; + p->name = (char *)malloc(len); + (void)strcpy(p->name, hp->h_name); + if (Nflag) { + /* Remove domain qualifications */ + dotp = index(p->name, '.'); + if (dotp) + *dotp = 0; + } + return (p->name); + } + } + } + cp = intoa(addr); + p->name = (char *)malloc((unsigned)(strlen(cp) + 1)); + (void)strcpy(p->name, cp); + return (p->name); +} + +static char hex[] = "0123456789abcdef"; + + +/* Find the hash node that corresponds the ether address 'ep'. */ + +static inline struct enamemem * +lookup_emem(ep) + u_char *ep; +{ + register u_int i, j, k; + struct enamemem *tp; + + k = (ep[0] << 8) | ep[1]; + j = (ep[2] << 8) | ep[3]; + i = (ep[4] << 8) | ep[5]; + + tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->e_nxt) + if (tp->e_addr0 == i && + tp->e_addr1 == j && + tp->e_addr2 == k) + return tp; + else + tp = tp->e_nxt; + tp->e_addr0 = i; + tp->e_addr1 = j; + tp->e_addr2 = k; + tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); + + return tp; +} + +char * +etheraddr_string(ep) + register u_char *ep; +{ + register u_int i, j; + register char *cp; + register struct enamemem *tp; + + tp = lookup_emem(ep); + if (tp->e_name) + return tp->e_name; + +#ifdef ETHER_SERVICE + if (!nflag) { + cp = ETHER_ntohost(ep); + if (cp) { + tp->e_name = cp; + return cp; + } + } +#endif + tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00")); + + if (j = *ep >> 4) + *cp++ = hex[j]; + *cp++ = hex[*ep++ & 0xf]; + for (i = 5; (int)--i >= 0;) { + *cp++ = ':'; + if (j = *ep >> 4) + *cp++ = hex[j]; + *cp++ = hex[*ep++ & 0xf]; + } + *cp = '\0'; + return (tp->e_name); +} + +char * +etherproto_string(port) + u_short port; +{ + register char *cp; + register struct hnamemem *tp; + register u_long i = port; + + for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->name = cp = (char *)malloc(sizeof("0000")); + tp->addr = i; + tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); + + NTOHS(port); + *cp++ = hex[port >> 12 & 0xf]; + *cp++ = hex[port >> 8 & 0xf]; + *cp++ = hex[port >> 4 & 0xf]; + *cp++ = hex[port & 0xf]; + *cp++ = '\0'; + return (tp->name); +} + +char * +tcpport_string(port) + u_short port; +{ + register struct hnamemem *tp; + register int i = port; + + for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->name = (char *)malloc(sizeof("00000")); + tp->addr = i; + tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); + + (void)sprintf(tp->name, "%d", i); + return (tp->name); +} + +char * +udpport_string(port) + register u_short port; +{ + register struct hnamemem *tp; + register int i = port; + + for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->name = (char *)malloc(sizeof("00000")); + tp->addr = i; + tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); + + (void)sprintf(tp->name, "%d", i); + + return (tp->name); +} + +static void +init_servarray() +{ + struct servent *sv; + register struct hnamemem *table; + register int i; + + while (sv = getservent()) { + NTOHS(sv->s_port); + i = sv->s_port & (HASHNAMESIZE-1); + if (strcmp(sv->s_proto, "tcp") == 0) + table = &tporttable[i]; + else if (strcmp(sv->s_proto, "udp") == 0) + table = &uporttable[i]; + else + continue; + + while (table->name) + table = table->nxt; + if (nflag) { + char buf[32]; + + (void)sprintf(buf, "%d", sv->s_port); + table->name = (char *)malloc((unsigned)strlen(buf)+1); + (void)strcpy(table->name, buf); + } else { + table->name = + (char *)malloc((unsigned)strlen(sv->s_name)+1); + (void)strcpy(table->name, sv->s_name); + } + table->addr = sv->s_port; + table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); + } + endservent(); +} + +#include "etherproto.h" + +/* Static data base of ether protocol types. */ +struct eproto eproto_db[] = { + { "pup", ETHERTYPE_PUP }, + { "xns", ETHERTYPE_NS }, + { "ip", ETHERTYPE_IP }, + { "arp", ETHERTYPE_ARP }, + { "rarp", ETHERTYPE_REVARP }, + { "sprite", ETHERTYPE_SPRITE }, + { "mopdl", ETHERTYPE_MOPDL }, + { "moprc", ETHERTYPE_MOPRC }, + { "decnet", ETHERTYPE_DN }, + { "lat", ETHERTYPE_LAT }, + { "lanbridge", ETHERTYPE_LANBRIDGE }, + { "vexp", ETHERTYPE_VEXP }, + { "vprod", ETHERTYPE_VPROD }, + { "atalk", ETHERTYPE_ATALK }, + { "atalkarp", ETHERTYPE_AARP }, + { "loopback", ETHERTYPE_LOOPBACK }, + { (char *)0, 0 } +}; + +static void +init_eprotoarray() +{ + register int i; + register struct hnamemem *table; + + for (i = 0; eproto_db[i].s; i++) { + int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); + table = &eprototable[j]; + while (table->name) + table = table->nxt; + table->name = eproto_db[i].s; + table->addr = ntohs(eproto_db[i].p); + table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); + } +} + +static void +init_etherarray() +{ +#ifndef ETHER_SERVICE + FILE *fp; + struct etherent *ep; + struct enamemem *tp; + + fp = fopen(ETHERS_FILE, "r"); + if (fp == 0) + /* No data base; will have to settle for + numeric addresses. */ + return; + + while (ep = next_etherent(fp)) { + tp = lookup_emem(ep->addr); + tp->e_name = (char *)malloc((unsigned)strlen(ep->name)+1); + strcpy(tp->e_name, ep->name); + } +#endif +} + +/* + * Initialize the address to name translation machinery. We map all + * non-local IP addresses to numeric addresses if fflag is true (i.e., + * to prevent blocking on the nameserver). localnet is the IP address + * of the local network. mask is its subnet mask. + */ +void +init_addrtoname(fflag, localnet, mask) + int fflag; + u_long localnet; + u_long mask; +{ + netmask = mask; + if (fflag) { + f_localnet = localnet; + f_netmask = mask; + } + if (nflag) + /* + * Simplest way to suppress names. + */ + return; + + init_etherarray(); + init_servarray(); + init_eprotoarray(); +} diff --git a/usr.sbin/tcpdump/tcpdump/addrtoname.h b/usr.sbin/tcpdump/tcpdump/addrtoname.h new file mode 100644 index 000000000000..6dc6979895c9 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/addrtoname.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1988, 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: addrtoname.h,v 1.5 92/03/17 13:41:37 mccanne Exp $ (LBL) + */ + +/* Name to address translation routines. */ + +extern char *etheraddr_string(); +extern char *etherproto_string(); +extern char *tcpport_string(); +extern char *udpport_string(); +extern char *getname(); +extern char *intoa(); + +extern void init_addrtoname(); +extern void no_foreign_names(); + +#define ipaddr_string(p) getname((u_char *)(p)) diff --git a/usr.sbin/tcpdump/tcpdump/appletalk.h b/usr.sbin/tcpdump/tcpdump/appletalk.h new file mode 100644 index 000000000000..90c8c806330f --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/appletalk.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * AppleTalk protocol formats (courtesy Bill Croft of Stanford/SUMEX). + * + * @(#) $Header: appletalk.h,v 1.6 90/10/03 22:14:26 leres Exp $ (LBL) + */ + +/* Datagram Delivery Protocol */ + +struct atDDP { + u_short length; + u_short checksum; + u_short dstNet; + u_short srcNet; + u_char dstNode; + u_char srcNode; + u_char dstSkt; + u_char srcSkt; + u_char type; +}; + +struct atShortDDP { + u_short length; + u_char dstSkt; + u_char srcSkt; + u_char type; +}; + +#define ddpMaxWKS 0x7F +#define ddpMaxData 586 +#define ddpLengthMask 0x3FF +#define ddpHopShift 10 +#define ddpSize 13 /* size of DDP header (avoid struct padding) */ +#define ddpSSize 5 +#define ddpWKS 128 /* boundary of DDP well known sockets */ +#define ddpRTMP 1 /* RTMP type */ +#define ddpRTMPrequest 5 /* RTMP request type */ +#define ddpNBP 2 /* NBP type */ +#define ddpATP 3 /* ATP type */ +#define ddpECHO 4 /* ECHO type */ +#define ddpIP 22 /* IP type */ +#define ddpARP 23 /* ARP type */ +#define ddpKLAP 0x4b /* Kinetics KLAP type */ + + +/* AppleTalk Transaction Protocol */ + +struct atATP { + u_char control; + u_char bitmap; + u_short transID; + long userData; +}; + +#define atpReqCode 0x40 +#define atpRspCode 0x80 +#define atpRelCode 0xC0 +#define atpXO 0x20 +#define atpEOM 0x10 +#define atpSTS 0x08 +#define atpFlagMask 0x3F +#define atpControlMask 0xF8 +#define atpMaxNum 8 +#define atpMaxData 578 + + +/* AppleTalk Echo Protocol */ + +struct atEcho { + u_char echoFunction; + u_char *echoData; +}; + +#define echoSkt 4 /* the echoer socket */ +#define echoSize 1 /* size of echo header */ +#define echoRequest 1 /* echo request */ +#define echoReply 2 /* echo request */ + + +/* Name Binding Protocol */ + +struct atNBP { + u_char control; + u_char id; +}; + +struct atNBPtuple { + u_short net; + u_char node; + u_char skt; + u_char enumerator; +}; + +#define nbpBrRq 0x10 +#define nbpLkUp 0x20 +#define nbpLkUpReply 0x30 + +#define nbpNIS 2 +#define nbpTupleMax 15 + +#define nbpHeaderSize 2 +#define nbpTupleSize 5; + + +/* Routing Table Maint. Protocol */ + +#define rtmpSkt 1 /* number of RTMP socket */ +#define rtmpSize 4 /* minimum size */ +#define rtmpTupleSize 3 + + +/* Zone Information Protocol */ + +struct zipHeader { + u_char command; + u_char netcount; +}; + +#define zipHeaderSize 2 +#define zipQuery 1 +#define zipReply 2 +#define zipTakedown 3 +#define zipBringup 4 +#define ddpZIP 6 +#define zipSkt 6 +#define GetMyZone 7 +#define GetZoneList 8 + +/* + * UDP port range used for ddp-in-udp encapsulation is 16512-16639 + * for client sockets (128-255) and 200-327 for server sockets + * (0-127). We also try to recognize the pre-April 88 server + * socket range of 768-895. + */ +#define atalk_port(p) \ + (((unsigned)((p) - 16512) < 128) || \ + ((unsigned)((p) - 200) < 128) || \ + ((unsigned)((p) - 768) < 128)) diff --git a/usr.sbin/tcpdump/tcpdump/bootp.h b/usr.sbin/tcpdump/tcpdump/bootp.h new file mode 100644 index 000000000000..ab474cf4d638 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/bootp.h @@ -0,0 +1,103 @@ +/* @(#) $Header: bootp.h,v 1.2 90/05/29 21:29:16 leres Exp $ (LBL) */ +/* + * Bootstrap Protocol (BOOTP). RFC951 and RFC1048. + * + * This file specifies the "implementation-independent" BOOTP protocol + * information which is common to both client and server. + * + * Copyright 1988 by Carnegie Mellon. + * + * Permission to use, copy, modify, and distribute this program for any + * purpose and without fee is hereby granted, provided that this copyright + * and permission notice appear on all copies and supporting documentation, + * the name of Carnegie Mellon not be used in advertising or publicity + * pertaining to distribution of the program without specific prior + * permission, and notice be given in supporting documentation that copying + * and distribution is by permission of Carnegie Mellon and Stanford + * University. Carnegie Mellon makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + + +struct bootp { + unsigned char bp_op; /* packet opcode type */ + unsigned char bp_htype; /* hardware addr type */ + unsigned char bp_hlen; /* hardware addr length */ + unsigned char bp_hops; /* gateway hops */ + unsigned long bp_xid; /* transaction ID */ + unsigned short bp_secs; /* seconds since boot began */ + unsigned short bp_unused; + struct in_addr bp_ciaddr; /* client IP address */ + struct in_addr bp_yiaddr; /* 'your' IP address */ + struct in_addr bp_siaddr; /* server IP address */ + struct in_addr bp_giaddr; /* gateway IP address */ + unsigned char bp_chaddr[16]; /* client hardware address */ + unsigned char bp_sname[64]; /* server host name */ + unsigned char bp_file[128]; /* boot file name */ + unsigned char bp_vend[64]; /* vendor-specific area */ +}; + +/* + * UDP port numbers, server and client. + */ +#define IPPORT_BOOTPS 67 +#define IPPORT_BOOTPC 68 + +#define BOOTREPLY 2 +#define BOOTREQUEST 1 + + +/* + * Vendor magic cookie (v_magic) for CMU + */ +#define VM_CMU "CMU" + +/* + * Vendor magic cookie (v_magic) for RFC1048 + */ +#define VM_RFC1048 { 99, 130, 83, 99 } + + + +/* + * RFC1048 tag values used to specify what information is being supplied in + * the vendor field of the packet. + */ + +#define TAG_PAD ((unsigned char) 0) +#define TAG_SUBNET_MASK ((unsigned char) 1) +#define TAG_TIME_OFFSET ((unsigned char) 2) +#define TAG_GATEWAY ((unsigned char) 3) +#define TAG_TIME_SERVER ((unsigned char) 4) +#define TAG_NAME_SERVER ((unsigned char) 5) +#define TAG_DOMAIN_SERVER ((unsigned char) 6) +#define TAG_LOG_SERVER ((unsigned char) 7) +#define TAG_COOKIE_SERVER ((unsigned char) 8) +#define TAG_LPR_SERVER ((unsigned char) 9) +#define TAG_IMPRESS_SERVER ((unsigned char) 10) +#define TAG_RLP_SERVER ((unsigned char) 11) +#define TAG_HOSTNAME ((unsigned char) 12) +#define TAG_BOOTSIZE ((unsigned char) 13) +#define TAG_END ((unsigned char) 255) + + + +/* + * "vendor" data permitted for CMU bootp clients. + */ + +struct cmu_vend { + unsigned char v_magic[4]; /* magic number */ + unsigned long v_flags; /* flags/opcodes, etc. */ + struct in_addr v_smask; /* Subnet mask */ + struct in_addr v_dgate; /* Default gateway */ + struct in_addr v_dns1, v_dns2; /* Domain name servers */ + struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */ + struct in_addr v_ts1, v_ts2; /* Time servers */ + unsigned char v_unused[25]; /* currently unused */ +}; + + +/* v_flags values */ +#define VF_SMASK 1 /* Subnet mask field contains valid data */ diff --git a/usr.sbin/tcpdump/tcpdump/bpf_dump.c b/usr.sbin/tcpdump/tcpdump/bpf_dump.c new file mode 100644 index 000000000000..fab9596d2f44 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/bpf_dump.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: bpf_dump.c,v 1.1 92/01/29 13:25:30 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include + +void +bpf_dump(p, option) + struct bpf_program *p; + int option; +{ + struct bpf_insn *insn; + int i; + int n = p->bf_len; + + insn = p->bf_insns; + if (option > 2) { + printf("%d\n", n); + for (i = 0; i < n; ++insn, ++i) { + printf("%lu %lu %lu %lu\n", insn->code, + insn->jt, insn->jf, insn->k); + } + return ; + } + if (option > 1) { + for (i = 0; i < n; ++insn, ++i) + printf("{ 0x%x, %d, %d, 0x%08x },\n", + insn->code, insn->jt, insn->jf, insn->k); + return; + } + for (i = 0; i < n; ++insn, ++i) { +#ifdef BDEBUG + extern int bids[]; + printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); +#endif + puts(bpf_image(insn, i)); + } +} diff --git a/usr.sbin/tcpdump/tcpdump/bpf_image.c b/usr.sbin/tcpdump/tcpdump/bpf_image.c new file mode 100644 index 000000000000..d36eab252f7c --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/bpf_image.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: bpf_image.c,v 1.10 92/01/26 21:01:16 mccanne Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include +#include + +char * +bpf_image(p, n) + struct bpf_insn *p; + int n; +{ + int v; + char *fmt, *op; + static char image[256]; + char operand[64]; + + v = p->k; + switch (p->code) { + + default: + op = "unimp"; + fmt = "0x%x"; + v = p->code; + break; + + case BPF_RET|BPF_K: + op = "ret"; + fmt = "#%d"; + break; + + case BPF_RET|BPF_A: + op = "ret"; + fmt = ""; + break; + + case BPF_LD|BPF_W|BPF_ABS: + op = "ld"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_H|BPF_ABS: + op = "ldh"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_B|BPF_ABS: + op = "ldb"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_W|BPF_LEN: + op = "ld"; + fmt = "#pktlen"; + break; + + case BPF_LD|BPF_W|BPF_IND: + op = "ld"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_H|BPF_IND: + op = "ldh"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_B|BPF_IND: + op = "ldb"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_IMM: + op = "ld"; + fmt = "#0x%x"; + break; + + case BPF_LDX|BPF_IMM: + op = "ldx"; + fmt = "#0x%x"; + break; + + case BPF_LDX|BPF_MSH|BPF_B: + op = "ldxb"; + fmt = "4*([%d]&0xf)"; + break; + + case BPF_LD|BPF_MEM: + op = "ld"; + fmt = "M[%d]"; + break; + + case BPF_LDX|BPF_MEM: + op = "ldx"; + fmt = "M[%d]"; + break; + + case BPF_ST: + op = "st"; + fmt = "M[%d]"; + break; + + case BPF_STX: + op = "stx"; + fmt = "M[%d]"; + break; + + case BPF_JMP|BPF_JA: + op = "ja"; + fmt = "%d"; + v = n + p->k; + break; + + case BPF_JMP|BPF_JGT|BPF_K: + op = "jgt"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JGE|BPF_K: + op = "jge"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JEQ|BPF_K: + op = "jeq"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JSET|BPF_K: + op = "jset"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JGT|BPF_X: + op = "jgt"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JGE|BPF_X: + op = "jge"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JEQ|BPF_X: + op = "jeq"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JSET|BPF_X: + op = "jset"; + fmt = "x"; + break; + + case BPF_ALU|BPF_ADD|BPF_X: + op = "add"; + fmt = "x"; + break; + + case BPF_ALU|BPF_SUB|BPF_X: + op = "sub"; + fmt = "x"; + break; + + case BPF_ALU|BPF_MUL|BPF_X: + op = "mul"; + fmt = "x"; + break; + + case BPF_ALU|BPF_DIV|BPF_X: + op = "div"; + fmt = "x"; + break; + + case BPF_ALU|BPF_AND|BPF_X: + op = "and"; + fmt = "x"; + break; + + case BPF_ALU|BPF_OR|BPF_X: + op = "or"; + fmt = "x"; + break; + + case BPF_ALU|BPF_LSH|BPF_X: + op = "lsh"; + fmt = "x"; + break; + + case BPF_ALU|BPF_RSH|BPF_X: + op = "rsh"; + fmt = "x"; + break; + + case BPF_ALU|BPF_ADD|BPF_K: + op = "add"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_SUB|BPF_K: + op = "sub"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_MUL|BPF_K: + op = "mul"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_DIV|BPF_K: + op = "div"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_AND|BPF_K: + op = "and"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_OR|BPF_K: + op = "or"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_LSH|BPF_K: + op = "lsh"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_RSH|BPF_K: + op = "rsh"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_NEG: + op = "neg"; + fmt = ""; + break; + + case BPF_MISC|BPF_TAX: + op = "tax"; + fmt = ""; + break; + + case BPF_MISC|BPF_TXA: + op = "txa"; + fmt = ""; + break; + } + (void)sprintf(operand, fmt, v); + (void)sprintf(image, + (BPF_CLASS(p->code) == BPF_JMP && + BPF_OP(p->code) != BPF_JA) ? + "(%03d) %-8s %-16s jt %d\tjf %d" + : "(%03d) %-8s %s", + n, op, operand, n + 1 + p->jt, n + 1 + p->jf); + return image; +} diff --git a/usr.sbin/tcpdump/tcpdump/etherent.c b/usr.sbin/tcpdump/tcpdump/etherent.c new file mode 100644 index 000000000000..9d7ee8009600 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/etherent.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: etherent.c,v 1.2 90/09/20 23:16:06 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include "interface.h" + +#ifndef ETHER_SERVICE + +#include "etherent.h" + +/* Hex digit to integer. */ +static inline int +xdtoi(c) +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +static inline int +skip_space(f) + FILE *f; +{ + int c; + + do { + c = getc(f); + } while (isspace(c) && c != '\n'); + + return c; +} + +static inline int +skip_line(f) + FILE *f; +{ + int c; + + do + c = getc(f); + while (c != '\n' && c != EOF); + + return c; +} + +struct etherent * +next_etherent(fp) + FILE *fp; +{ + register int c, d, i; + char *bp; + static struct etherent e; + static int nline = 1; + top: + while (nline) { + /* Find addr */ + c = skip_space(fp); + if (c == '\n') + continue; + /* If this is a comment, or first thing on line + cannot be etehrnet address, skip the line. */ + else if (!isxdigit(c)) + c = skip_line(fp); + else { + /* must be the start of an address */ + for (i = 0; i < 6; i += 1) { + d = xdtoi(c); + c = getc(fp); + if (c != ':') { + d <<= 4; + d |= xdtoi(c); + c = getc(fp); + } + e.addr[i] = d; + if (c != ':') + break; + c = getc(fp); + } + nline = 0; + } + if (c == EOF) + return 0; + } + + /* If we started a new line, 'c' holds the char past the ether addr, + which we assume is white space. If we are continuning a line, + 'c' is garbage. In either case, we can throw it away. */ + + c = skip_space(fp); + if (c == '\n') { + nline = 1; + goto top; + } + else if (c == '#') { + (void)skip_line(fp); + nline = 1; + goto top; + } + else if (c == EOF) + return 0; + + /* Must be a name. */ + bp = e.name; + /* Use 'd' to prevent buffer overflow. */ + d = sizeof(e.name) - 1; + do { + *bp++ = c; + c = getc(fp); + } while (!isspace(c) && c != EOF && --d > 0); + *bp = '\0'; + if (c == '\n') + nline = 1; + + return &e; +} + +#endif diff --git a/usr.sbin/tcpdump/tcpdump/etherent.h b/usr.sbin/tcpdump/tcpdump/etherent.h new file mode 100644 index 000000000000..83ebaabb8647 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/etherent.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: etherent.h,v 1.2 90/09/20 23:16:17 mccanne Exp $ (LBL) + */ + +/* File name of ethernet address data base. */ + +#define ETHERS_FILE "/etc/ethers" + +struct etherent { + u_char addr[6]; + char name[122]; +}; + +struct etherent *next_etherent(); + diff --git a/usr.sbin/tcpdump/tcpdump/etherproto.h b/usr.sbin/tcpdump/tcpdump/etherproto.h new file mode 100644 index 000000000000..5c0e245cee72 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/etherproto.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: etherproto.h,v 1.7 90/10/10 15:04:04 mccanne Exp $ (LBL) + */ + +/* Map between Ethernet protocol types and names */ + +/* Add other Ethernet packet types here */ +#ifndef ETHERTYPE_SPRITE +#define ETHERTYPE_SPRITE 0x0500 +#endif +#ifndef ETHERTYPE_MOPDL +#define ETHERTYPE_MOPDL 0x6001 +#endif +#ifndef ETHERTYPE_MOPRC +#define ETHERTYPE_MOPRC 0x6002 +#endif +#ifndef ETHERTYPE_DN +#define ETHERTYPE_DN 0x6003 +#endif +#ifndef ETHERTYPE_LAT +#define ETHERTYPE_LAT 0x6004 +#endif +#ifndef ETHERTYPE_LANBRIDGE +#define ETHERTYPE_LANBRIDGE 0x8038 +#endif +#ifndef ETHERTYPE_VEXP +#define ETHERTYPE_VEXP 0x805b +#endif +#ifndef ETHERTYPE_VPROD +#define ETHERTYPE_VPROD 0x805c +#endif +#ifndef ETHERTYPE_LOOPBACK +#define ETHERTYPE_LOOPBACK 0x9000 +#endif + +#ifndef ETHERTYPE_ATALK +#define ETHERTYPE_ATALK 0x809b /* XXX */ +#endif +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 +#endif +#ifndef ETHERTYPE_NS +#define ETHERTYPE_NS 0x0600 +#endif + +struct eproto { + char *s; + u_short p; +}; + +extern struct eproto eproto_db[]; diff --git a/usr.sbin/tcpdump/tcpdump/extract.h b/usr.sbin/tcpdump/tcpdump/extract.h new file mode 100644 index 000000000000..bd45c59b3e9e --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/extract.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: extract.h,v 1.4 92/05/25 14:28:36 mccanne Exp $ (LBL) + */ + +#ifdef TCPDUMP_ALIGN +#if BYTEORDER == LITTLE_ENDIAN +#define EXTRACT_SHORT(p)\ + ((u_short)\ + ((u_short)*((u_char *)p+1)<<8|\ + (u_short)*((u_char *)p+0)<<0)) +#define EXTRACT_LONG(p)\ + ((u_long)*((u_char *)p+3)<<24|\ + (u_long)*((u_char *)p+2)<<16|\ + (u_long)*((u_char *)p+1)<<8|\ + (u_long)*((u_char *)p+0)<<0) +#else +#define EXTRACT_SHORT(p)\ + ((u_short)\ + ((u_short)*((u_char *)p+0)<<8|\ + (u_short)*((u_char *)p+1)<<0)) +#define EXTRACT_LONG(p)\ + ((u_long)*((u_char *)p+0)<<24|\ + (u_long)*((u_char *)p+1)<<16|\ + (u_long)*((u_char *)p+2)<<8|\ + (u_long)*((u_char *)p+3)<<0) +#endif +#else +#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) +#define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) +#endif diff --git a/usr.sbin/tcpdump/tcpdump/gencode.c b/usr.sbin/tcpdump/tcpdump/gencode.c new file mode 100644 index 000000000000..8cb48ea05483 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/gencode.c @@ -0,0 +1,1384 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: gencode.c,v 1.33 92/05/22 16:38:39 mccanne Exp $ (LBL)"; +#endif + +#ifdef __STDC__ +#include +#endif +#include +#include +#include +#include +#include + +#include +#include + +#include "interface.h" +#include "gencode.h" +#include "nametoaddr.h" +#include "extract.h" + +#define JMP(c) ((c)|BPF_JMP|BPF_K) + +extern struct bpf_insn *icode_to_fcode(); +extern u_long net_mask(); +static void init_linktype(); + +static int alloc_reg(); +static void free_reg(); + +static struct block *root; + +/* + * We divy out chunks of memory rather than call malloc each time so + * we don't have to worry about leaking memory. It's probably + * not a big deal if all this memory was wasted but it this ever + * goes into a library that would probably not be a good idea. + */ +#define NCHUNKS 16 +#define CHUNK0SIZE 1024 +struct chunk { + u_int n_left; + void *m; +}; + +static struct chunk chunks[NCHUNKS]; +static int cur_chunk; + +static void * +newchunk(n) + u_int n; +{ + struct chunk *cp; + int k, size; + + /* XXX Round up to nearest long. */ + n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); + + cp = &chunks[cur_chunk]; + if (n > cp->n_left) { + ++cp, k = ++cur_chunk; + if (k >= NCHUNKS) + error("out of memory"); + size = CHUNK0SIZE << k; + cp->m = (void *)malloc(size); + bzero((char *)cp->m, size); + cp->n_left = size; + if (n > size) + error("out of memory"); + } + cp->n_left -= n; + return (void *)((char *)cp->m + cp->n_left); +} + +static void +freechunks() +{ + int i; + + for (i = 0; i < NCHUNKS; ++i) + if (chunks[i].m) + free(chunks[i].m); +} + +static inline struct block * +new_block(code) + int code; +{ + struct block *p; + + p = (struct block *)newchunk(sizeof(*p)); + p->s.code = code; + p->head = p; + + return p; +} + +static inline struct slist * +new_stmt(code) + int code; +{ + struct slist *p; + + p = (struct slist *)newchunk(sizeof(*p)); + p->s.code = code; + + return p; +} + +static struct block * +gen_retblk(v) + int v; +{ + struct block *b = new_block(BPF_RET|BPF_K); + + b->s.k = v; + return b; +} + +static inline void +syntax() +{ + error("syntax error in filter expression"); +} + +static u_long netmask; + +struct bpf_program * +parse(buf, Oflag, linktype, mask) + char *buf; + int Oflag; + int linktype; + u_long mask; +{ + extern int n_errors; + static struct bpf_program F; + struct bpf_insn *p; + int len; + + netmask = mask; + + F.bf_insns = 0; + F.bf_len = 0; + + lex_init(buf ? buf : ""); + init_linktype(linktype); + yyparse(); + + if (n_errors) + syntax(); + + if (root == 0) + root = gen_retblk(snaplen); + + if (Oflag) { + optimize(&root); + if (root == 0 || + (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) + error("expression rejects all packets"); + } + p = icode_to_fcode(root, &len); + F.bf_insns = p; + F.bf_len = len; + + freechunks(); + return &F; +} + +/* + * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates + * which of the jt and jf fields has been resolved and which is a pointer + * back to another unresolved block (or nil). At least one of the fields + * in each block is already resolved. + */ +static void +backpatch(list, target) + struct block *list, *target; +{ + struct block *next; + + while (list) { + if (!list->sense) { + next = JT(list); + JT(list) = target; + } else { + next = JF(list); + JF(list) = target; + } + list = next; + } +} + +/* + * Merge the lists in b0 and b1, using the 'sense' field to indicate + * which of jt and jf is the link. + */ +static void +merge(b0, b1) + struct block *b0, *b1; +{ + register struct block **p = &b0; + + /* Find end of list. */ + while (*p) + p = !((*p)->sense) ? &JT(*p) : &JF(*p); + + /* Concatenate the lists. */ + *p = b1; +} + +void +finish_parse(p) + struct block *p; +{ + backpatch(p, gen_retblk(snaplen)); + p->sense = !p->sense; + backpatch(p, gen_retblk(0)); + root = p->head; +} + +void +gen_and(b0, b1) + struct block *b0, *b1; +{ + backpatch(b0, b1->head); + b0->sense = !b0->sense; + b1->sense = !b1->sense; + merge(b1, b0); + b1->sense = !b1->sense; + b1->head = b0->head; +} + +void +gen_or(b0, b1) + struct block *b0, *b1; +{ + b0->sense = !b0->sense; + backpatch(b0, b1->head); + b0->sense = !b0->sense; + merge(b1, b0); + b1->head = b0->head; +} + +void +gen_not(b) + struct block *b; +{ + b->sense = !b->sense; +} + +static struct block * +gen_cmp(offset, size, v) + u_int offset, size; + long v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; + + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + b->s.k = v; + + return b; +} + +struct block * +gen_mcmp(offset, size, v, mask) + u_int offset, size; + long v; + u_long mask; +{ + struct block *b = gen_cmp(offset, size, v); + struct slist *s; + + if (mask != 0xffffffff) { + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s->s.k = mask; + b->stmts->next = s; + } + return b; +} + +struct block * +gen_bcmp(offset, size, v) + u_int offset; + u_int size; + u_char *v; +{ + struct block *b, *tmp; + int k; + + b = 0; + while (size >= 4) { + k = size - 4; + tmp = gen_cmp(offset + k, BPF_W, EXTRACT_LONG(&v[k])); + if (b != 0) + gen_and(b, tmp); + b = tmp; + size -= 4; + } + while (size >= 2) { + k = size - 2; + tmp = gen_cmp(offset + k, BPF_H, (long)EXTRACT_SHORT(&v[k])); + if (b != 0) + gen_and(b, tmp); + b = tmp; + size -= 2; + } + if (size > 0) { + tmp = gen_cmp(offset, BPF_B, (long)v[0]); + if (b != 0) + gen_and(b, tmp); + b = tmp; + } + return b; +} + +/* + * Various code contructs need to know the layout of the data link + * layer. These variables give the necessary offsets. off_linktype + * is set to -1 for no encapsulation, in which case, IP is assumed. + */ +static u_int off_linktype; +static u_int off_nl; +static int linktype; + +static void +init_linktype(type) + int type; +{ + linktype = type; + + switch (type) { + + case DLT_EN10MB: + off_linktype = 12; + off_nl = 14; + return; + + case DLT_SLIP: + /* + * SLIP doesn't have a link level type. The 16 byte + * header is hacked into our SLIP driver. + */ + off_linktype = -1; + off_nl = 16; + return; + + case DLT_NULL: + off_linktype = -1; + off_nl = 0; + return; + + case DLT_PPP: + off_linktype = 2; + off_nl = 4; + return; + + case DLT_FDDI: + off_linktype = 19; + off_nl = 21; + return; + + case DLT_IEEE802: + off_linktype = 20; + off_nl = 22; + return; + } + error("unknown data link type 0x%x", linktype); + /* NOTREACHED */ +} + +static struct block * +gen_uncond(rsense) + int rsense; +{ + struct block *b; + struct slist *s; + + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = !rsense; + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + + return b; +} + +static inline struct block * +gen_true() +{ + return gen_uncond(1); +} + +static inline struct block * +gen_false() +{ + return gen_uncond(0); +} + +struct block * +gen_linktype(proto) + int proto; +{ + switch (linktype) { + case DLT_SLIP: + if (proto == ETHERTYPE_IP) + return gen_true(); + else + return gen_false(); + + case DLT_PPP: + if (proto == ETHERTYPE_IP) + proto = 0x0021; /* XXX - need ppp.h defs */ + break; + } + return gen_cmp(off_linktype, BPF_H, (long)proto); +} + +static struct block * +gen_hostop(addr, mask, dir, proto, src_off, dst_off) + u_long addr; + u_long mask; + int dir, proto; + u_int src_off, dst_off; +{ + struct block *b0, *b1; + u_int offset; + + switch (dir) { + + case Q_SRC: + offset = src_off; + break; + + case Q_DST: + offset = dst_off; + break; + + case Q_AND: + b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); + gen_or(b0, b1); + return b1; + + default: + abort(); + } + b0 = gen_linktype(proto); + b1 = gen_mcmp(offset, BPF_W, (long)addr, mask); + gen_and(b0, b1); + return b1; +} + +static struct block * +gen_ehostop(eaddr, dir) + u_char *eaddr; + int dir; +{ + struct block *b0, *b1; + + switch (dir) { + case Q_SRC: + return gen_bcmp(6, 6, eaddr); + + case Q_DST: + return gen_bcmp(0, 6, eaddr); + + case Q_AND: + b0 = gen_ehostop(eaddr, Q_SRC); + b1 = gen_ehostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ehostop(eaddr, Q_SRC); + b1 = gen_ehostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +static struct block * +gen_host(addr, mask, proto, dir) + u_long addr; + u_long mask; + int proto; + int dir; +{ + struct block *b0, *b1; + + switch (proto) { + + case Q_DEFAULT: + b0 = gen_host(addr, mask, Q_IP, dir); + b1 = gen_host(addr, mask, Q_ARP, dir); + gen_or(b0, b1); + b0 = gen_host(addr, mask, Q_RARP, dir); + gen_or(b1, b0); + return b0; + + case Q_IP: + return gen_hostop(addr, mask, dir, ETHERTYPE_IP, + off_nl + 12, off_nl + 16); + + case Q_RARP: + return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, + off_nl + 14, off_nl + 24); + + case Q_ARP: + return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, + off_nl + 14, off_nl + 24); + + case Q_TCP: + error("'tcp' modifier applied to host"); + + case Q_UDP: + error("'udp' modifier applied to host"); + + case Q_ICMP: + error("'icmp' modifier applied to host"); + } + abort(); + /* NOTREACHED */ +} + +static struct block * +gen_gateway(eaddr, alist, proto, dir) + u_char *eaddr; + u_long **alist; + int proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + if (dir != 0) + error("direction applied to 'gateway'"); + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + case Q_ARP: + case Q_RARP: + b0 = gen_ehostop(eaddr, Q_OR); + b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR); + while (*alist) { + tmp = gen_host(**alist++, 0xffffffffL, proto, Q_OR); + gen_or(b1, tmp); + b1 = tmp; + } + gen_not(b1); + gen_and(b0, b1); + return b1; + } + error("illegal modifier of 'gateway'"); + /* NOTREACHED */ +} + +struct block * +gen_proto_abbrev(proto) + int proto; +{ + struct block *b0, *b1; + + switch (proto) { + + case Q_TCP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_TCP); + gen_and(b0, b1); + break; + + case Q_UDP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_UDP); + gen_and(b0, b1); + break; + + case Q_ICMP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_ICMP); + gen_and(b0, b1); + break; + + case Q_IP: + b1 = gen_linktype(ETHERTYPE_IP); + break; + + case Q_ARP: + b1 = gen_linktype(ETHERTYPE_ARP); + break; + + case Q_RARP: + b1 = gen_linktype(ETHERTYPE_REVARP); + break; + + case Q_LINK: + error("link layer applied in wrong context"); + + default: + abort(); + } + return b1; +} + +static struct block * +gen_ipfrag() +{ + struct slist *s; + struct block *b; + + /* not ip frag */ + s = new_stmt(BPF_LD|BPF_H|BPF_ABS); + s->s.k = off_nl + 6; + b = new_block(JMP(BPF_JSET)); + b->s.k = 0x1fff; + b->stmts = s; + gen_not(b); + + return b; +} + +static struct block * +gen_portatom(off, v) + int off; + long v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + + s->next = new_stmt(BPF_LD|BPF_IND|BPF_H); + s->next->s.k = off_nl + off; + + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + b->s.k = v; + + return b; +} + +struct block * +gen_portop(port, proto, dir) + int port; + int proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ip proto 'proto' */ + tmp = gen_cmp(off_nl + 9, BPF_B, (long)proto); + b0 = gen_ipfrag(); + gen_and(tmp, b0); + + switch (dir) { + case Q_SRC: + b1 = gen_portatom(0, (long)port); + break; + + case Q_DST: + b1 = gen_portatom(2, (long)port); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portatom(0, (long)port); + b1 = gen_portatom(2, (long)port); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portatom(0, (long)port); + b1 = gen_portatom(2, (long)port); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_port(port, ip_proto, dir) + int port; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ether proto ip */ + b0 = gen_linktype(ETHERTYPE_IP); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + b1 = gen_portop(port, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portop(port, IPPROTO_TCP, dir); + b1 = gen_portop(port, IPPROTO_UDP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} + +int +lookup_proto(name, proto) + char *name; + int proto; +{ + int v; + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + v = s_nametoproto(name); + if (v == PROTO_UNDEF) + error("unknown ip proto '%s'", name); + break; + + case Q_LINK: + /* XXX should look up h/w protocol type based on linktype */ + v = s_nametoeproto(name); + if (v == PROTO_UNDEF) + error("unknown ether proto '%s'", name); + break; + + default: + v = PROTO_UNDEF; + break; + } + return v; +} + +struct block * +gen_proto(v, proto, dir) + int v; + int proto; + int dir; +{ + struct block *b0, *b1; + + if (dir != Q_DEFAULT) + error("direction applied to 'proto'"); + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (long)v); + gen_and(b0, b1); + return b1; + + case Q_ARP: + error("arp does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_RARP: + error("rarp does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_LINK: + return gen_linktype(v); + + case Q_UDP: + error("'udp proto' is bogus"); + + case Q_TCP: + error("'tcp proto' is bogus"); + + case Q_ICMP: + error("'icmp proto' is bogus"); + } + abort(); + /* NOTREACHED */ +} + +struct block * +gen_scode(name, q) + char *name; + struct qual q; +{ + int proto = q.proto; + int dir = q.dir; + u_char *eaddr; + u_long mask, addr, **alist; + struct block *b, *tmp; + int port, real_proto; + + switch (q.addr) { + + case Q_NET: + addr = s_nametonetaddr(name); + if (addr == 0) + error("unknown network '%s'", name); + mask = net_mask(&addr); + return gen_host(addr, mask, proto, dir); + + case Q_DEFAULT: + case Q_HOST: + if (proto == Q_LINK) { + /* XXX Should lookup hw addr based on link layer */ + eaddr = ETHER_hostton(name); + if (eaddr == 0) + error("unknown ether host '%s'", name); + return gen_ehostop(eaddr, dir); + + } else { + alist = s_nametoaddr(name); + if (alist == 0 || *alist == 0) + error("uknown host '%s'", name); + b = gen_host(**alist++, 0xffffffffL, proto, dir); + while (*alist) { + tmp = gen_host(**alist++, 0xffffffffL, + proto, dir); + gen_or(b, tmp); + b = tmp; + } + return b; + } + + case Q_PORT: + if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) + error("illegal qualifier of 'port'"); + if (s_nametoport(name, &port, &real_proto) == 0) + error("unknown port '%s'", name); + if (proto == Q_UDP) { + if (real_proto == IPPROTO_TCP) + error("port '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_UDP; + } + if (proto == Q_TCP) { + if (real_proto == IPPROTO_UDP) + error("port '%s' is udp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_TCP; + } + return gen_port(port, real_proto, dir); + + case Q_GATEWAY: + eaddr = ETHER_hostton(name); + if (eaddr == 0) + error("unknown ether host: %s", name); + + alist = s_nametoaddr(name); + if (alist == 0 || *alist == 0) + error("uknown host '%s'", name); + return gen_gateway(eaddr, alist, proto, dir); + + case Q_PROTO: + real_proto = lookup_proto(name, proto); + if (real_proto >= 0) + return gen_proto(real_proto, proto, dir); + else + error("unknown protocol: %s", name); + + case Q_UNDEF: + syntax(); + /* NOTREACHED */ + } + abort(); + /* NOTREACHED */ +} + +struct block * +gen_ncode(v, q) + u_long v; + struct qual q; +{ + u_long mask; + int proto = q.proto; + int dir = q.dir; + + switch (q.addr) { + + case Q_DEFAULT: + case Q_HOST: + case Q_NET: + mask = net_mask(&v); + return gen_host(v, mask, proto, dir); + + case Q_PORT: + if (proto == Q_UDP) + proto = IPPROTO_UDP; + else if (proto == Q_TCP) + proto = IPPROTO_TCP; + else if (proto == Q_DEFAULT) + proto = PROTO_UNDEF; + else + error("illegal qualifier of 'port'"); + + return gen_port((int)v, proto, dir); + + case Q_GATEWAY: + error("'gateway' requires a name"); + /* NOTREACHED */ + + case Q_PROTO: + return gen_proto((int)v, proto, dir); + + case Q_UNDEF: + syntax(); + /* NOTREACHED */ + } + abort(); + /* NOTREACHED */ +} + +struct block * +gen_ecode(eaddr, q) + u_char *eaddr; + struct qual q; +{ + if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) + return gen_ehostop(eaddr, (int)q.dir); + else + error("ethernet address used in non-ether expression"); + /* NOTREACHED */ +} + +void +sappend(s0, s1) + struct slist *s0, *s1; +{ + /* + * This is definitely not the best way to do this, but the + * lists will rarely get long. + */ + while (s0->next) + s0 = s0->next; + s0->next = s1; +} + +struct slist * +xfer_to_x(a) + struct arth *a; +{ + struct slist *s; + + s = new_stmt(BPF_LDX|BPF_MEM); + s->s.k = a->regno; + return s; +} + +struct slist * +xfer_to_a(a) + struct arth *a; +{ + struct slist *s; + + s = new_stmt(BPF_LD|BPF_MEM); + s->s.k = a->regno; + return s; +} + +struct arth * +gen_load(proto, index, size) + int proto; + struct arth *index; + int size; +{ + struct slist *s, *tmp; + struct block *b; + int regno = alloc_reg(); + + free_reg(index->regno); + switch (size) { + + default: + error("data size must be 1, 2, or 4"); + + case 1: + size = BPF_B; + break; + + case 2: + size = BPF_H; + break; + + case 4: + size = BPF_W; + break; + } + switch (proto) { + default: + error("unsupported index operation"); + + case Q_LINK: + s = xfer_to_x(index); + tmp = new_stmt(BPF_LD|BPF_IND|size); + sappend(s, tmp); + sappend(index->s, s); + break; + + case Q_IP: + case Q_ARP: + case Q_RARP: + /* XXX Note that we assume a fixed link link header here. */ + s = xfer_to_x(index); + tmp = new_stmt(BPF_LD|BPF_IND|size); + tmp->s.k = off_nl; + sappend(s, tmp); + sappend(index->s, s); + + b = gen_proto_abbrev(proto); + if (index->b) + gen_and(index->b, b); + index->b = b; + break; + + case Q_TCP: + case Q_UDP: + case Q_ICMP: + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + sappend(s, xfer_to_a(index)); + sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); + sappend(s, new_stmt(BPF_MISC|BPF_TAX)); + sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); + tmp->s.k = off_nl; + sappend(index->s, s); + + gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); + if (index->b) + gen_and(index->b, b); + index->b = b; + break; + } + index->regno = regno; + s = new_stmt(BPF_ST); + s->s.k = regno; + sappend(index->s, s); + + return index; +} + +struct block * +gen_relation(code, a0, a1, reversed) + int code; + struct arth *a0, *a1; + int reversed; +{ + struct slist *s0, *s1, *s2; + struct block *b, *tmp; + + s0 = xfer_to_x(a1); + s1 = xfer_to_a(a0); + s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); + b = new_block(JMP(code)); + if (reversed) + gen_not(b); + + sappend(s1, s2); + sappend(s0, s1); + sappend(a1->s, s0); + sappend(a0->s, a1->s); + + b->stmts = a0->s; + + free_reg(a0->regno); + free_reg(a1->regno); + + /* 'and' together protocol checks */ + if (a0->b) { + if (a1->b) { + gen_and(a0->b, tmp = a1->b); + } + else + tmp = a0->b; + } else + tmp = a1->b; + + if (tmp) + gen_and(tmp, b); + + return b; +} + +struct arth * +gen_loadlen() +{ + int regno = alloc_reg(); + struct arth *a = (struct arth *)newchunk(sizeof(*a)); + struct slist *s; + + s = new_stmt(BPF_LD|BPF_LEN); + s->next = new_stmt(BPF_ST); + s->next->s.k = regno; + a->s = s; + a->regno = regno; + + return a; +} + +struct arth * +gen_loadi(val) + int val; +{ + struct arth *a; + struct slist *s; + int reg; + + a = (struct arth *)newchunk(sizeof(*a)); + + reg = alloc_reg(); + + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = val; + s->next = new_stmt(BPF_ST); + s->next->s.k = reg; + a->s = s; + a->regno = reg; + + return a; +} + +struct arth * +gen_neg(a) + struct arth *a; +{ + struct slist *s; + + s = xfer_to_a(a); + sappend(a->s, s); + s = new_stmt(BPF_ALU|BPF_NEG); + s->s.k = 0; + sappend(a->s, s); + s = new_stmt(BPF_ST); + s->s.k = a->regno; + sappend(a->s, s); + + return a; +} + +struct arth * +gen_arth(code, a0, a1) + int code; + struct arth *a0, *a1; +{ + struct slist *s0, *s1, *s2; + + s0 = xfer_to_x(a1); + s1 = xfer_to_a(a0); + s2 = new_stmt(BPF_ALU|BPF_X|code); + + sappend(s1, s2); + sappend(s0, s1); + sappend(a1->s, s0); + sappend(a0->s, a1->s); + + free_reg(a1->regno); + + s0 = new_stmt(BPF_ST); + a0->regno = s0->s.k = alloc_reg(); + sappend(a0->s, s0); + + return a0; +} + +/* + * Here we handle simple allocation of the scratch registers. + * If too many registers are alloc'd, the allocator punts. + */ +static int regused[BPF_MEMWORDS]; +static int curreg; + +/* + * Return the next free register. + */ +static int +alloc_reg() +{ + int n = BPF_MEMWORDS; + + while (--n >= 0) { + if (regused[curreg]) + curreg = (curreg + 1) % BPF_MEMWORDS; + else { + regused[curreg] = 1; + return curreg; + } + } + error("too many registers needed to evaluate expression"); + /* NOTREACHED */ +} + +/* + * Return a register to the table so it can + * be used later. + */ +static void +free_reg(n) + int n; +{ + regused[n] = 0; +} + +static struct block * +gen_len(jmp, n) + int jmp; + int n; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_LEN); + s->next = new_stmt(BPF_SUB|BPF_IMM); + s->next->s.k = n; + b = new_block(JMP(jmp)); + b->stmts = s; + + return b; +} + +struct block * +gen_greater(n) + int n; +{ + return gen_len(BPF_JGE, n); +} + +struct block * +gen_less(n) + int n; +{ + struct block *b; + + b = gen_len(BPF_JGT, n); + gen_not(b); + + return b; +} + +struct block * +gen_byteop(op, idx, val) + int op; + int idx; + int val; +{ + struct block *b; + struct slist *s; + + switch (op) { + default: + abort(); + + case '=': + return gen_cmp((u_int)idx, BPF_B, (long)val); + + case '<': + b = gen_cmp((u_int)idx, BPF_B, (long)val); + b->s.code = JMP(BPF_JGE); + gen_not(b); + return b; + + case '>': + b = gen_cmp((u_int)idx, BPF_B, (long)val); + b->s.code = JMP(BPF_JGT); + return b; + + case '|': + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + break; + + case '&': + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + break; + } + s->s.k = val; + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + gen_not(b); + + return b; +} + +struct block * +gen_broadcast(proto) + int proto; +{ + u_long hostmask; + struct block *b0, *b1, *b2; + static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + switch (proto) { + + case Q_DEFAULT: + case Q_LINK: + if (linktype == DLT_EN10MB) + return gen_ehostop(ebroadcast, Q_DST); + error("not a broadcast link"); + break; + + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + hostmask = ~netmask; + b1 = gen_mcmp(off_nl + 16, BPF_W, (long)0, hostmask); + b2 = gen_mcmp(off_nl + 16, BPF_W, + (long)(~0 & hostmask), hostmask); + gen_or(b1, b2); + gen_and(b0, b2); + return b2; + } + error("only ether/ip broadcast filters supported"); +} + +struct block * +gen_multicast(proto) + int proto; +{ + register struct block *b0, *b1, *b2; + register struct slist *s; + + switch (proto) { + + case Q_DEFAULT: + case Q_LINK: + if (linktype != DLT_EN10MB) + break; + + /* ether[0] & 1 != 0 */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b0 = new_block(JMP(BPF_JSET)); + b0->s.k = 1; + b0->stmts = s; + return b0; + + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 16, BPF_B, (long)224); + b1->s.code = JMP(BPF_JGE); + gen_and(b0, b1); + return b1; + } + error("only ether/ip multicast filters supported"); +} diff --git a/usr.sbin/tcpdump/tcpdump/gencode.h b/usr.sbin/tcpdump/tcpdump/gencode.h new file mode 100644 index 000000000000..b8f342d6b629 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/gencode.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: gencode.h,v 1.14 92/02/14 15:18:55 mccanne Exp $ (LBL) + */ + +/* + * filter.h must be included before this file. + */ + +/* Address qualifers. */ + +#define Q_HOST 1 +#define Q_NET 2 +#define Q_PORT 3 +#define Q_GATEWAY 4 +#define Q_PROTO 5 + +/* Protocol qualifiers. */ + +#define Q_LINK 1 +#define Q_IP 2 +#define Q_ARP 3 +#define Q_RARP 4 +#define Q_TCP 5 +#define Q_UDP 6 +#define Q_ICMP 7 + +/* Directional qualifers. */ + +#define Q_SRC 1 +#define Q_DST 2 +#define Q_OR 3 +#define Q_AND 4 + +#define Q_DEFAULT 0 +#define Q_UNDEF 255 + +struct stmt { + int code; + long k; +}; + +struct slist { + struct stmt s; + struct slist *next; +}; + +/* + * A bit vector to represent definition sets. We assume TOT_REGISTERS + * is smaller than 8*sizeof(atomset). + */ +typedef u_long atomset; +#define ATOMMASK(n) (1 << (n)) +#define ATOMELEM(d, n) (d & ATOMMASK(n)) + +/* + * An unbounded set. + */ +typedef u_long *uset; + +/* + * Total number of atomic entities, including accumulator (A) and index (X). + * We treat all these guys similarly during flow analysis. + */ +#define N_ATOMS (BPF_MEMWORDS+2) + +struct edge { + int id; + int code; + uset edom; + struct block *succ; + struct block *pred; + struct edge *next; /* link list of incoming edges for a node */ +}; + +struct block { + int id; + struct slist *stmts; /* side effect stmts */ + struct stmt s; /* branch stmt */ + int mark; + int level; + int offset; + int sense; + struct edge et; + struct edge ef; + struct block *head; + struct block *link; /* link field used by optimizer */ + uset dom; + uset closure; + struct edge *in_edges; + atomset def, kill; + atomset in_use; + atomset out_use; + long oval; + long val[N_ATOMS]; +}; + +struct arth { + struct block *b; /* protocol checks */ + struct slist *s; /* stmt list */ + int regno; /* virtual register number of result */ +}; + +extern struct arth *gen_loadi(); +extern struct arth *gen_load(); +extern struct arth *gen_loadlen(); +extern struct arth *gen_neg(); +extern struct arth *gen_arth(); + +extern void gen_and(); +extern void gen_or(); +extern void gen_not(); + +extern struct block *gen_scode(); +extern struct block *gen_ecode(); +extern struct block *gen_ncode(); +extern struct block *gen_proto_abbrev(); +extern struct block *gen_relation(); +extern struct block *gen_less(); +extern struct block *gen_greater(); +extern struct block *gen_byteop(); +extern struct block *gen_broadcast(); +extern struct block *gen_multicast(); + +extern void optimize(); + +extern void finish_parse(); + +struct qual { + unsigned char addr; + unsigned char proto; + unsigned char dir; + unsigned char pad; +}; + +/* XXX */ +#define JT(b) ((b)->et.succ) +#define JF(b) ((b)->ef.succ) diff --git a/usr.sbin/tcpdump/tcpdump/inet.c b/usr.sbin/tcpdump/tcpdump/inet.c new file mode 100644 index 000000000000..550129e1af55 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/inet.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#)$Header: inet.c,v 1.12 92/01/29 12:46:18 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "interface.h" + +/* Not all systems have IFF_LOOPBACK */ +#ifdef IFF_LOOPBACK +#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) +#else +#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0) +#endif + +/* + * Return the name of a network interface attached to the system, or 0 + * if none can be found. The interface must be configured up; the + * lowest unit number is preferred; loopback is ignored. + */ +char * +lookup_device() +{ + struct ifreq ibuf[16], *ifrp, *ifend, *mp; + struct ifconf ifc; + int fd; + int minunit, n; + char *cp; + static char device[sizeof(ifrp->ifr_name)]; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + perror("tcpdump: socket"); + exit(1); + } + ifc.ifc_len = sizeof ibuf; + ifc.ifc_buf = (caddr_t)ibuf; + + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + perror("tcpdump: SIOCGIFCONF: "); + exit(1); + } + ifrp = ibuf; + ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); + + mp = 0; + minunit = 666; + while (ifrp < ifend) { + struct ifreq ifr; + /* + * Need a template to preserve address info that is + * used below to locate the next entry. (Otherwise, + * SIOCGIFFLAGS stomps over it because the requests + * are returned in a union.) + */ + bcopy(ifrp->ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { + fprintf(stderr, "tcpdump: SIOCGIFFLAGS: "); + perror(ifrp->ifr_name); + exit(1); + } + if ((ifr.ifr_flags & IFF_UP) && !ISLOOPBACK(&ifr)) { + for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) + ; + n = atoi(cp); + if (n < minunit) { + minunit = n; + mp = ifrp; + } + } +#if BSD >= 199006 + n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); + if (n < sizeof(*ifrp)) + ++ifrp; + else + ifrp = (struct ifreq *)((char *)ifrp + n); +#else + ++ifrp; +#endif + } + close(fd); + if (mp == 0) + return (0); + + (void)strcpy(device, mp->ifr_name); + return (device); +} + +/* + * Get the netmask of an IP address. This routine is used if + * SIOCGIFNETMASK doesn't work. + */ +static u_long +ipaddrtonetmask(addr) + u_long addr; +{ + if (IN_CLASSA(addr)) + return (IN_CLASSA_NET); + if (IN_CLASSB(addr)) + return (IN_CLASSB_NET); + if (IN_CLASSC(addr)) + return (IN_CLASSC_NET); + error("unknown IP address class: %08X", addr); + /* NOTREACHED */ +} + +void +lookup_net(device, netp, maskp) + char *device; + u_long *netp; + u_long *maskp; +{ + int fd; + struct ifreq ifr; + struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; + + /* Use data gram socket to get IP address. */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("tcpdump: socket"); + exit(1); + } + (void)strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name); + if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { + /* + * This will fail if an IP address hasn't been assigned. + */ + *netp = 0; + *maskp = 0; + return; + } + *netp = sin->sin_addr.s_addr; + if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) + *maskp = 0; + else + *maskp = sin->sin_addr.s_addr; + if (*maskp == 0) + *maskp = ipaddrtonetmask(*netp); + *netp &= *maskp; + (void)close(fd); +} diff --git a/usr.sbin/tcpdump/tcpdump/interface.h b/usr.sbin/tcpdump/tcpdump/interface.h new file mode 100644 index 000000000000..dfccba6e6730 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/interface.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: interface.h,v 1.46 92/06/02 17:57:22 mccanne Exp $ (LBL) + */ + +#ifdef __GNUC__ +#define inline __inline +#else +#define inline +#endif + +#include "os.h" /* operating system stuff */ +#include "md.h" /* machine dependent stuff */ + +#ifndef __STDC__ +extern char *malloc(); +extern char *calloc(); +#endif + +extern int dflag; /* print filter code */ +extern int eflag; /* print ethernet header */ +extern int nflag; /* leave addresses as numbers */ +extern int Nflag; /* remove domains from printed host names */ +extern int qflag; /* quick (shorter) output */ +extern int Sflag; /* print raw TCP sequence numbers */ +extern int tflag; /* print packet arrival time */ +extern int vflag; /* verbose */ +extern int xflag; /* print packet in hex */ + +extern char *program_name; /* used to generate self-identifying messages */ + +extern int snaplen; +/* global pointers to beginning and end of current packet (during printing) */ +extern unsigned char *packetp; +extern unsigned char *snapend; + +extern long thiszone; /* gmt to local correction */ + +extern void ts_print(); +extern int clock_sigfigs(); + +extern char *lookup_device(); + +extern void error(); +extern void warning(); + +extern char *read_infile(); +extern char *copy_argv(); + +extern void usage(); +extern void show_code(); +extern void init_addrtoname(); + +/* The printer routines. */ + +extern void ether_if_print(); +extern void arp_print(); +extern void ip_print(); +extern void tcp_print(); +extern void udp_print(); +extern void icmp_print(); +extern void default_print(); + +extern void ntp_print(); +extern void nfsreq_print(); +extern void nfsreply_print(); +extern void ns_print(); +extern void ddp_print(); +extern void rip_print(); +extern void tftp_print(); +extern void bootp_print(); +extern void snmp_print(); +extern void sl_if_print(); +extern void ppp_if_print(); +extern void fddi_if_print(); +extern void null_if_print(); +extern void egp_print(); + +#define min(a,b) ((a)>(b)?(b):(a)) +#define max(a,b) ((b)>(a)?(b):(a)) + +/* + * The default snapshot length. This value allows most printers to print + * useful information while keeping the amount of unwanted data down. + * In particular, it allows for an ethernet header, tcp/ip header, and + * 14 bytes of data (assuming no ip options). + */ +#define DEFAULT_SNAPLEN 68 + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#define LITTLE_ENDIAN 1234 +#endif diff --git a/usr.sbin/tcpdump/tcpdump/md.c b/usr.sbin/tcpdump/tcpdump/md.c new file mode 100644 index 000000000000..6bb04b72cade --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/md.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: md-vax.c,v 1.3 90/10/03 14:14:33 mccanne Locked $ (LBL)"; +#endif + +/* Vaxen appear to have clocks accurate to 1 us, + but packetfilter is timestamping to 10 ms. */ + +int +clock_sigfigs() +{ + return 2; +} + diff --git a/usr.sbin/tcpdump/tcpdump/md.h b/usr.sbin/tcpdump/tcpdump/md.h new file mode 100644 index 000000000000..f83d81fcf0e0 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/md.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: md-vax.h,v 1.2 90/09/21 02:23:16 mccanne Exp $ (LBL) + */ + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +/* These should be fixed to be real macros, for speed */ + +#ifndef NTOHL +#define NTOHL(x) (x) = ntohl(x) +#define NTOHS(x) (x) = ntohs(x) +#define HTONL(x) (x) = htonl(x) +#define HTONS(x) (x) = htons(x) +#endif + +#ifndef vax +/* Some Ultrix header files may need this */ +#define vax 1 +#endif vax diff --git a/usr.sbin/tcpdump/tcpdump/mib.h b/usr.sbin/tcpdump/tcpdump/mib.h new file mode 100644 index 000000000000..a81897ce8b2a --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/mib.h @@ -0,0 +1,1256 @@ +/* + * This file was generated by tcpdump/makemib on Wed Sep 26 12:12:31 EDT 1990 + * You probably don't want to edit this by hand! + * + * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer +}; + */ + +/* parse problem: new name "mib" for mgmt.mib(1) ignored */ +/* parse problem: no parent for 0.nullSpecific(0) */ +struct obj +_proteon_obj = { + "proteon", 1, 0, + NULL, NULL +}, +_ibm_obj = { + "ibm", 2, 0, + NULL, &_proteon_obj +}, +_cmu_obj = { + "cmu", 3, 0, + NULL, &_ibm_obj +}, +_unix_obj = { + "unix", 4, 0, + NULL, &_cmu_obj +}, +_acc_obj = { + "acc", 5, 0, + NULL, &_unix_obj +}, +_twg_obj = { + "twg", 6, 0, + NULL, &_acc_obj +}, +_cayman_obj = { + "cayman", 7, 0, + NULL, &_twg_obj +}, +_nysernet_obj = { + "nysernet", 8, 0, + NULL, &_cayman_obj +}, +_cisco_obj = { + "cisco", 9, 0, + NULL, &_nysernet_obj +}, +_nsc_obj = { + "nsc", 10, 0, + NULL, &_cisco_obj +}, +_hp_obj = { + "hp", 11, 0, + NULL, &_nsc_obj +}, +_epilogue_obj = { + "epilogue", 12, 0, + NULL, &_hp_obj +}, +_utennessee_obj = { + "utennessee", 13, 0, + NULL, &_epilogue_obj +}, +_bbn_obj = { + "bbn", 14, 0, + NULL, &_utennessee_obj +}, +_xylogics_obj = { + "xylogics", 15, 0, + NULL, &_bbn_obj +}, +_unisys_obj = { + "unisys", 16, 0, + NULL, &_xylogics_obj +}, +_canstar_obj = { + "canstar", 17, 0, + NULL, &_unisys_obj +}, +_wellfleet_obj = { + "wellfleet", 18, 0, + NULL, &_canstar_obj +}, +_trw_obj = { + "trw", 19, 0, + NULL, &_wellfleet_obj +}, +_mit_obj = { + "mit", 20, 0, + NULL, &_trw_obj +}, +_eon_obj = { + "eon", 21, 0, + NULL, &_mit_obj +}, +_spartacus_obj = { + "spartacus", 22, 0, + NULL, &_eon_obj +}, +_excelan_obj = { + "excelan", 23, 0, + NULL, &_spartacus_obj +}, +_spider_obj = { + "spider", 24, 0, + NULL, &_excelan_obj +}, +_nsfnet_obj = { + "nsfnet", 25, 0, + NULL, &_spider_obj +}, +_sytek_obj = { + "sytek", 26, 0, + NULL, &_nsfnet_obj +}, +_intergraph_obj = { + "intergraph", 27, 0, + NULL, &_sytek_obj +}, +_interlan_obj = { + "interlan", 28, 0, + NULL, &_intergraph_obj +}, +_vitalink_obj = { + "vitalink", 29, 0, + NULL, &_interlan_obj +}, +_ulana_obj = { + "ulana", 30, 0, + NULL, &_vitalink_obj +}, +_nswc_obj = { + "nswc", 31, 0, + NULL, &_ulana_obj +}, +_santacruzoperation_obj = { + "santacruzoperation", 32, 0, + NULL, &_nswc_obj +}, +_xyplex_obj = { + "xyplex", 33, 0, + NULL, &_santacruzoperation_obj +}, +_cray_obj = { + "cray", 34, 0, + NULL, &_xyplex_obj +}, +_bellnorthernresearch_obj = { + "bellnorthernresearch", 35, 0, + NULL, &_cray_obj +}, +_dec_obj = { + "dec", 36, 0, + NULL, &_bellnorthernresearch_obj +}, +_touch_obj = { + "touch", 37, 0, + NULL, &_dec_obj +}, +_networkresearchcorp_obj = { + "networkresearchcorp", 38, 0, + NULL, &_touch_obj +}, +_baylor_obj = { + "baylor", 39, 0, + NULL, &_networkresearchcorp_obj +}, +_nmfeccllnl_obj = { + "nmfeccllnl", 40, 0, + NULL, &_baylor_obj +}, +_sri_obj = { + "sri", 41, 0, + NULL, &_nmfeccllnl_obj +}, +_sun_obj = { + "sun", 42, 0, + NULL, &_sri_obj +}, +_3com_obj = { + "3com", 43, 0, + NULL, &_sun_obj +}, +_cmc_obj = { + "cmc", 44, 0, + NULL, &_3com_obj +}, +_synoptics_obj = { + "synoptics", 45, 0, + NULL, &_cmc_obj +}, +_cheyenne_obj = { + "cheyenne", 46, 0, + NULL, &_synoptics_obj +}, +_prime_obj = { + "prime", 47, 0, + NULL, &_cheyenne_obj +}, +_mcnc_obj = { + "mcnc", 48, 0, + NULL, &_prime_obj +}, +_chipcom_obj = { + "chipcom", 49, 0, + NULL, &_mcnc_obj +}, +_opticaldatasystems_obj = { + "opticaldatasystems", 50, 0, + NULL, &_chipcom_obj +}, +_gated_obj = { + "gated", 51, 0, + NULL, &_opticaldatasystems_obj +}, +_cabletron_obj = { + "cabletron", 52, 0, + NULL, &_gated_obj +}, +_apollo_obj = { + "apollo", 53, 0, + NULL, &_cabletron_obj +}, +_desktalksystems_obj = { + "desktalksystems", 54, 0, + NULL, &_apollo_obj +}, +_ssds_obj = { + "ssds", 55, 0, + NULL, &_desktalksystems_obj +}, +_castlerock_obj = { + "castlerock", 56, 0, + NULL, &_ssds_obj +}, +_mips_obj = { + "mips", 57, 0, + NULL, &_castlerock_obj +}, +_tgv_obj = { + "tgv", 58, 0, + NULL, &_mips_obj +}, +_silicongraphics_obj = { + "silicongraphics", 59, 0, + NULL, &_tgv_obj +}, +_ubc_obj = { + "ubc", 60, 0, + NULL, &_silicongraphics_obj +}, +_merit_obj = { + "merit", 61, 0, + NULL, &_ubc_obj +}, +_fibercom_obj = { + "fibercom", 62, 0, + NULL, &_merit_obj +}, +_apple_obj = { + "apple", 63, 0, + NULL, &_fibercom_obj +}, +_gandalf_obj = { + "gandalf", 64, 0, + NULL, &_apple_obj +}, +_dartmouth_obj = { + "dartmouth", 65, 0, + NULL, &_gandalf_obj +}, +_davidsystems_obj = { + "davidsystems", 66, 0, + NULL, &_dartmouth_obj +}, +_reuter_obj = { + "reuter", 67, 0, + NULL, &_davidsystems_obj +}, +_cornell_obj = { + "cornell", 68, 0, + NULL, &_reuter_obj +}, +_tmac_obj = { + "tmac", 69, 0, + NULL, &_cornell_obj +}, +_locus_obj = { + "locus", 70, 0, + NULL, &_tmac_obj +}, +_nasa_obj = { + "nasa", 71, 0, + NULL, &_locus_obj +}, +_retix_obj = { + "retix", 72, 0, + NULL, &_nasa_obj +}, +_boeing_obj = { + "boeing", 73, 0, + NULL, &_retix_obj +}, +_att_obj = { + "att", 74, 0, + NULL, &_boeing_obj +}, +_ungermannbass_obj = { + "ungermannbass", 75, 0, + NULL, &_att_obj +}, +_digitalanalysis_obj = { + "digitalanalysis", 76, 0, + NULL, &_ungermannbass_obj +}, +_hplanman_obj = { + "hplanman", 77, 0, + NULL, &_digitalanalysis_obj +}, +_netlabs_obj = { + "netlabs", 78, 0, + NULL, &_hplanman_obj +}, +_icl_obj = { + "icl", 79, 0, + NULL, &_netlabs_obj +}, +_auspex_obj = { + "auspex", 80, 0, + NULL, &_icl_obj +}, +_lannet_obj = { + "lannet", 81, 0, + NULL, &_auspex_obj +}, +_ncd_obj = { + "ncd", 82, 0, + NULL, &_lannet_obj +}, +_raycom_obj = { + "raycom", 83, 0, + NULL, &_ncd_obj +}, +_pirellifocom_obj = { + "pirellifocom", 84, 0, + NULL, &_raycom_obj +}, +_datability_obj = { + "datability", 85, 0, + NULL, &_pirellifocom_obj +}, +_networkappltech_obj = { + "networkappltech", 86, 0, + NULL, &_datability_obj +}, +_link_obj = { + "link", 87, 0, + NULL, &_networkappltech_obj +}, +_nyu_obj = { + "nyu", 88, 0, + NULL, &_link_obj +}, +_rnd_obj = { + "rnd", 89, 0, + NULL, &_nyu_obj +}, +_intercon_obj = { + "intercon", 90, 0, + NULL, &_rnd_obj +}, +_learningtree_obj = { + "learningtree", 91, 0, + NULL, &_intercon_obj +}, +_webstercomputer_obj = { + "webstercomputer", 92, 0, + NULL, &_learningtree_obj +}, +_frontier_obj = { + "frontier", 93, 0, + NULL, &_webstercomputer_obj +}, +_nokia_obj = { + "nokia", 94, 0, + NULL, &_frontier_obj +}, +_allenbradley_obj = { + "allenbradley", 95, 0, + NULL, &_nokia_obj +}, +_cern_obj = { + "cern", 96, 0, + NULL, &_allenbradley_obj +}, +_sigma_obj = { + "sigma", 97, 0, + NULL, &_cern_obj +}, +_emergingtech_obj = { + "emergingtech", 98, 0, + NULL, &_sigma_obj +}, +_snmpresearch_obj = { + "snmpresearch", 99, 0, + NULL, &_emergingtech_obj +}, +_ohiostate_obj = { + "ohiostate", 100, 0, + NULL, &_snmpresearch_obj +}, +_ultra_obj = { + "ultra", 101, 0, + NULL, &_ohiostate_obj +}, +_ccur_obj = { + "ccur", 136, 0, + NULL, &_ultra_obj +}, +_enterprises_obj = { + "enterprises", 1, 0, + &_ccur_obj, NULL +}, +_snmpInPkts_obj = { + "snmpInPkts", 1, 0, + NULL, NULL +}, +_snmpOutPkts_obj = { + "snmpOutPkts", 2, 0, + NULL, &_snmpInPkts_obj +}, +_snmpInBadVersions_obj = { + "snmpInBadVersions", 3, 0, + NULL, &_snmpOutPkts_obj +}, +_snmpInBadCommunityNames_obj = { + "snmpInBadCommunityNames", 4, 0, + NULL, &_snmpInBadVersions_obj +}, +_snmpInBadCommunityUses_obj = { + "snmpInBadCommunityUses", 5, 0, + NULL, &_snmpInBadCommunityNames_obj +}, +_snmpInASNParseErrs_obj = { + "snmpInASNParseErrs", 6, 0, + NULL, &_snmpInBadCommunityUses_obj +}, +_snmpInBadTypes_obj = { + "snmpInBadTypes", 7, 0, + NULL, &_snmpInASNParseErrs_obj +}, +_snmpInTooBigs_obj = { + "snmpInTooBigs", 8, 0, + NULL, &_snmpInBadTypes_obj +}, +_snmpInNoSuchNames_obj = { + "snmpInNoSuchNames", 9, 0, + NULL, &_snmpInTooBigs_obj +}, +_snmpInBadValues_obj = { + "snmpInBadValues", 10, 0, + NULL, &_snmpInNoSuchNames_obj +}, +_snmpInReadOnlys_obj = { + "snmpInReadOnlys", 11, 0, + NULL, &_snmpInBadValues_obj +}, +_snmpInGenErrs_obj = { + "snmpInGenErrs", 12, 0, + NULL, &_snmpInReadOnlys_obj +}, +_snmpInTotalReqVars_obj = { + "snmpInTotalReqVars", 13, 0, + NULL, &_snmpInGenErrs_obj +}, +_snmpInTotalSetVars_obj = { + "snmpInTotalSetVars", 14, 0, + NULL, &_snmpInTotalReqVars_obj +}, +_snmpInGetRequests_obj = { + "snmpInGetRequests", 15, 0, + NULL, &_snmpInTotalSetVars_obj +}, +_snmpInGetNexts_obj = { + "snmpInGetNexts", 16, 0, + NULL, &_snmpInGetRequests_obj +}, +_snmpInSetRequests_obj = { + "snmpInSetRequests", 17, 0, + NULL, &_snmpInGetNexts_obj +}, +_snmpInGetResponses_obj = { + "snmpInGetResponses", 18, 0, + NULL, &_snmpInSetRequests_obj +}, +_snmpInTraps_obj = { + "snmpInTraps", 19, 0, + NULL, &_snmpInGetResponses_obj +}, +_snmpOutTooBigs_obj = { + "snmpOutTooBigs", 20, 0, + NULL, &_snmpInTraps_obj +}, +_snmpOutNoSuchNames_obj = { + "snmpOutNoSuchNames", 21, 0, + NULL, &_snmpOutTooBigs_obj +}, +_snmpOutBadValues_obj = { + "snmpOutBadValues", 22, 0, + NULL, &_snmpOutNoSuchNames_obj +}, +_snmpOutReadOnlys_obj = { + "snmpOutReadOnlys", 23, 0, + NULL, &_snmpOutBadValues_obj +}, +_snmpOutGenErrs_obj = { + "snmpOutGenErrs", 24, 0, + NULL, &_snmpOutReadOnlys_obj +}, +_snmpOutGetRequests_obj = { + "snmpOutGetRequests", 25, 0, + NULL, &_snmpOutGenErrs_obj +}, +_snmpOutGetNexts_obj = { + "snmpOutGetNexts", 26, 0, + NULL, &_snmpOutGetRequests_obj +}, +_snmpOutSetRequests_obj = { + "snmpOutSetRequests", 27, 0, + NULL, &_snmpOutGetNexts_obj +}, +_snmpOutGetResponses_obj = { + "snmpOutGetResponses", 28, 0, + NULL, &_snmpOutSetRequests_obj +}, +_snmpOutTraps_obj = { + "snmpOutTraps", 29, 0, + NULL, &_snmpOutGetResponses_obj +}, +_snmpEnableAuthTraps_obj = { + "snmpEnableAuthTraps", 30, 0, + NULL, &_snmpOutTraps_obj +}, +_egpNeighState_obj = { + "egpNeighState", 1, 0, + NULL, NULL +}, +_egpNeighAddr_obj = { + "egpNeighAddr", 2, 0, + NULL, &_egpNeighState_obj +}, +_egpNeighAs_obj = { + "egpNeighAs", 3, 0, + NULL, &_egpNeighAddr_obj +}, +_egpNeighInMsgs_obj = { + "egpNeighInMsgs", 4, 0, + NULL, &_egpNeighAs_obj +}, +_egpNeighInErrs_obj = { + "egpNeighInErrs", 5, 0, + NULL, &_egpNeighInMsgs_obj +}, +_egpNeighOutMsgs_obj = { + "egpNeighOutMsgs", 6, 0, + NULL, &_egpNeighInErrs_obj +}, +_egpNeighOutErrs_obj = { + "egpNeighOutErrs", 7, 0, + NULL, &_egpNeighOutMsgs_obj +}, +_egpNeighInErrMsgs_obj = { + "egpNeighInErrMsgs", 8, 0, + NULL, &_egpNeighOutErrs_obj +}, +_egpNeighOutErrMsgs_obj = { + "egpNeighOutErrMsgs", 9, 0, + NULL, &_egpNeighInErrMsgs_obj +}, +_egpNeighStateUps_obj = { + "egpNeighStateUps", 10, 0, + NULL, &_egpNeighOutErrMsgs_obj +}, +_egpNeighStateDowns_obj = { + "egpNeighStateDowns", 11, 0, + NULL, &_egpNeighStateUps_obj +}, +_egpNeighIntervalHello_obj = { + "egpNeighIntervalHello", 12, 0, + NULL, &_egpNeighStateDowns_obj +}, +_egpNeighIntervalPoll_obj = { + "egpNeighIntervalPoll", 13, 0, + NULL, &_egpNeighIntervalHello_obj +}, +_egpNeighMode_obj = { + "egpNeighMode", 14, 0, + NULL, &_egpNeighIntervalPoll_obj +}, +_egpNeighEventTrigger_obj = { + "egpNeighEventTrigger", 15, 0, + NULL, &_egpNeighMode_obj +}, +_egpNeighEntry_obj = { + "egpNeighEntry", 1, 0, + &_egpNeighEventTrigger_obj, NULL +}, +_egpInMsgs_obj = { + "egpInMsgs", 1, 0, + NULL, NULL +}, +_egpInErrors_obj = { + "egpInErrors", 2, 0, + NULL, &_egpInMsgs_obj +}, +_egpOutMsgs_obj = { + "egpOutMsgs", 3, 0, + NULL, &_egpInErrors_obj +}, +_egpOutErrors_obj = { + "egpOutErrors", 4, 0, + NULL, &_egpOutMsgs_obj +}, +_egpNeighTable_obj = { + "egpNeighTable", 5, 0, + &_egpNeighEntry_obj, &_egpOutErrors_obj +}, +_egpAs_obj = { + "egpAs", 6, 0, + NULL, &_egpNeighTable_obj +}, +_udpLocalAddress_obj = { + "udpLocalAddress", 1, 0, + NULL, NULL +}, +_udpLocalPort_obj = { + "udpLocalPort", 2, 0, + NULL, &_udpLocalAddress_obj +}, +_udpEntry_obj = { + "udpEntry", 1, 0, + &_udpLocalPort_obj, NULL +}, +_udpInDatagrams_obj = { + "udpInDatagrams", 1, 0, + NULL, NULL +}, +_udpNoPorts_obj = { + "udpNoPorts", 2, 0, + NULL, &_udpInDatagrams_obj +}, +_udpInErrors_obj = { + "udpInErrors", 3, 0, + NULL, &_udpNoPorts_obj +}, +_udpOutDatagrams_obj = { + "udpOutDatagrams", 4, 0, + NULL, &_udpInErrors_obj +}, +_udpTable_obj = { + "udpTable", 5, 0, + &_udpEntry_obj, &_udpOutDatagrams_obj +}, +_tcpConnState_obj = { + "tcpConnState", 1, 0, + NULL, NULL +}, +_tcpConnLocalAddress_obj = { + "tcpConnLocalAddress", 2, 0, + NULL, &_tcpConnState_obj +}, +_tcpConnLocalPort_obj = { + "tcpConnLocalPort", 3, 0, + NULL, &_tcpConnLocalAddress_obj +}, +_tcpConnRemAddress_obj = { + "tcpConnRemAddress", 4, 0, + NULL, &_tcpConnLocalPort_obj +}, +_tcpConnRemPort_obj = { + "tcpConnRemPort", 5, 0, + NULL, &_tcpConnRemAddress_obj +}, +_tcpConnEntry_obj = { + "tcpConnEntry", 1, 0, + &_tcpConnRemPort_obj, NULL +}, +_tcpRtoAlgorithm_obj = { + "tcpRtoAlgorithm", 1, 0, + NULL, NULL +}, +_tcpRtoMin_obj = { + "tcpRtoMin", 2, 0, + NULL, &_tcpRtoAlgorithm_obj +}, +_tcpRtoMax_obj = { + "tcpRtoMax", 3, 0, + NULL, &_tcpRtoMin_obj +}, +_tcpMaxConn_obj = { + "tcpMaxConn", 4, 0, + NULL, &_tcpRtoMax_obj +}, +_tcpActiveOpens_obj = { + "tcpActiveOpens", 5, 0, + NULL, &_tcpMaxConn_obj +}, +_tcpPassiveOpens_obj = { + "tcpPassiveOpens", 6, 0, + NULL, &_tcpActiveOpens_obj +}, +_tcpAttemptFails_obj = { + "tcpAttemptFails", 7, 0, + NULL, &_tcpPassiveOpens_obj +}, +_tcpEstabResets_obj = { + "tcpEstabResets", 8, 0, + NULL, &_tcpAttemptFails_obj +}, +_tcpCurrEstab_obj = { + "tcpCurrEstab", 9, 0, + NULL, &_tcpEstabResets_obj +}, +_tcpInSegs_obj = { + "tcpInSegs", 10, 0, + NULL, &_tcpCurrEstab_obj +}, +_tcpOutSegs_obj = { + "tcpOutSegs", 11, 0, + NULL, &_tcpInSegs_obj +}, +_tcpRetransSegs_obj = { + "tcpRetransSegs", 12, 0, + NULL, &_tcpOutSegs_obj +}, +_tcpConnTable_obj = { + "tcpConnTable", 13, 0, + &_tcpConnEntry_obj, &_tcpRetransSegs_obj +}, +_tcpInErrs_obj = { + "tcpInErrs", 14, 0, + NULL, &_tcpConnTable_obj +}, +_tcpOutRsts_obj = { + "tcpOutRsts", 15, 0, + NULL, &_tcpInErrs_obj +}, +_icmpInMsgs_obj = { + "icmpInMsgs", 1, 0, + NULL, NULL +}, +_icmpInErrors_obj = { + "icmpInErrors", 2, 0, + NULL, &_icmpInMsgs_obj +}, +_icmpInDestUnreachs_obj = { + "icmpInDestUnreachs", 3, 0, + NULL, &_icmpInErrors_obj +}, +_icmpInTimeExcds_obj = { + "icmpInTimeExcds", 4, 0, + NULL, &_icmpInDestUnreachs_obj +}, +_icmpInParmProbs_obj = { + "icmpInParmProbs", 5, 0, + NULL, &_icmpInTimeExcds_obj +}, +_icmpInSrcQuenchs_obj = { + "icmpInSrcQuenchs", 6, 0, + NULL, &_icmpInParmProbs_obj +}, +_icmpInRedirects_obj = { + "icmpInRedirects", 7, 0, + NULL, &_icmpInSrcQuenchs_obj +}, +_icmpInEchos_obj = { + "icmpInEchos", 8, 0, + NULL, &_icmpInRedirects_obj +}, +_icmpInEchoReps_obj = { + "icmpInEchoReps", 9, 0, + NULL, &_icmpInEchos_obj +}, +_icmpInTimestamps_obj = { + "icmpInTimestamps", 10, 0, + NULL, &_icmpInEchoReps_obj +}, +_icmpInTimestampReps_obj = { + "icmpInTimestampReps", 11, 0, + NULL, &_icmpInTimestamps_obj +}, +_icmpInAddrMasks_obj = { + "icmpInAddrMasks", 12, 0, + NULL, &_icmpInTimestampReps_obj +}, +_icmpInAddrMaskReps_obj = { + "icmpInAddrMaskReps", 13, 0, + NULL, &_icmpInAddrMasks_obj +}, +_icmpOutMsgs_obj = { + "icmpOutMsgs", 14, 0, + NULL, &_icmpInAddrMaskReps_obj +}, +_icmpOutErrors_obj = { + "icmpOutErrors", 15, 0, + NULL, &_icmpOutMsgs_obj +}, +_icmpOutDestUnreachs_obj = { + "icmpOutDestUnreachs", 16, 0, + NULL, &_icmpOutErrors_obj +}, +_icmpOutTimeExcds_obj = { + "icmpOutTimeExcds", 17, 0, + NULL, &_icmpOutDestUnreachs_obj +}, +_icmpOutParmProbs_obj = { + "icmpOutParmProbs", 18, 0, + NULL, &_icmpOutTimeExcds_obj +}, +_icmpOutSrcQuenchs_obj = { + "icmpOutSrcQuenchs", 19, 0, + NULL, &_icmpOutParmProbs_obj +}, +_icmpOutRedirects_obj = { + "icmpOutRedirects", 20, 0, + NULL, &_icmpOutSrcQuenchs_obj +}, +_icmpOutEchos_obj = { + "icmpOutEchos", 21, 0, + NULL, &_icmpOutRedirects_obj +}, +_icmpOutEchoReps_obj = { + "icmpOutEchoReps", 22, 0, + NULL, &_icmpOutEchos_obj +}, +_icmpOutTimestamps_obj = { + "icmpOutTimestamps", 23, 0, + NULL, &_icmpOutEchoReps_obj +}, +_icmpOutTimestampReps_obj = { + "icmpOutTimestampReps", 24, 0, + NULL, &_icmpOutTimestamps_obj +}, +_icmpOutAddrMasks_obj = { + "icmpOutAddrMasks", 25, 0, + NULL, &_icmpOutTimestampReps_obj +}, +_icmpOutAddrMaskReps_obj = { + "icmpOutAddrMaskReps", 26, 0, + NULL, &_icmpOutAddrMasks_obj +}, +_ipNetToMediaIfIndex_obj = { + "ipNetToMediaIfIndex", 1, 0, + NULL, NULL +}, +_ipNetToMediaPhysAddress_obj = { + "ipNetToMediaPhysAddress", 2, 0, + NULL, &_ipNetToMediaIfIndex_obj +}, +_ipNetToMediaNetAddress_obj = { + "ipNetToMediaNetAddress", 3, 0, + NULL, &_ipNetToMediaPhysAddress_obj +}, +_ipNetToMediaType_obj = { + "ipNetToMediaType", 4, 0, + NULL, &_ipNetToMediaNetAddress_obj +}, +_ipNetToMediaEntry_obj = { + "ipNetToMediaEntry", 1, 0, + &_ipNetToMediaType_obj, NULL +}, +_ipRouteDest_obj = { + "ipRouteDest", 1, 0, + NULL, NULL +}, +_ipRouteIfIndex_obj = { + "ipRouteIfIndex", 2, 0, + NULL, &_ipRouteDest_obj +}, +_ipRouteMetric1_obj = { + "ipRouteMetric1", 3, 0, + NULL, &_ipRouteIfIndex_obj +}, +_ipRouteMetric2_obj = { + "ipRouteMetric2", 4, 0, + NULL, &_ipRouteMetric1_obj +}, +_ipRouteMetric3_obj = { + "ipRouteMetric3", 5, 0, + NULL, &_ipRouteMetric2_obj +}, +_ipRouteMetric4_obj = { + "ipRouteMetric4", 6, 0, + NULL, &_ipRouteMetric3_obj +}, +_ipRouteNextHop_obj = { + "ipRouteNextHop", 7, 0, + NULL, &_ipRouteMetric4_obj +}, +_ipRouteType_obj = { + "ipRouteType", 8, 0, + NULL, &_ipRouteNextHop_obj +}, +_ipRouteProto_obj = { + "ipRouteProto", 9, 0, + NULL, &_ipRouteType_obj +}, +_ipRouteAge_obj = { + "ipRouteAge", 10, 0, + NULL, &_ipRouteProto_obj +}, +_ipRouteMask_obj = { + "ipRouteMask", 11, 0, + NULL, &_ipRouteAge_obj +}, +_ipRouteEntry_obj = { + "ipRouteEntry", 1, 0, + &_ipRouteMask_obj, NULL +}, +_ipAdEntAddr_obj = { + "ipAdEntAddr", 1, 0, + NULL, NULL +}, +_ipAdEntIfIndex_obj = { + "ipAdEntIfIndex", 2, 0, + NULL, &_ipAdEntAddr_obj +}, +_ipAdEntNetMask_obj = { + "ipAdEntNetMask", 3, 0, + NULL, &_ipAdEntIfIndex_obj +}, +_ipAdEntBcastAddr_obj = { + "ipAdEntBcastAddr", 4, 0, + NULL, &_ipAdEntNetMask_obj +}, +_ipAdEntReasmMaxSize_obj = { + "ipAdEntReasmMaxSize", 5, 0, + NULL, &_ipAdEntBcastAddr_obj +}, +_ipAddrEntry_obj = { + "ipAddrEntry", 1, 0, + &_ipAdEntReasmMaxSize_obj, NULL +}, +_ipForwarding_obj = { + "ipForwarding", 1, 0, + NULL, NULL +}, +_ipDefaultTTL_obj = { + "ipDefaultTTL", 2, 0, + NULL, &_ipForwarding_obj +}, +_ipInReceives_obj = { + "ipInReceives", 3, 0, + NULL, &_ipDefaultTTL_obj +}, +_ipInHdrErrors_obj = { + "ipInHdrErrors", 4, 0, + NULL, &_ipInReceives_obj +}, +_ipInAddrErrors_obj = { + "ipInAddrErrors", 5, 0, + NULL, &_ipInHdrErrors_obj +}, +_ipForwDatagrams_obj = { + "ipForwDatagrams", 6, 0, + NULL, &_ipInAddrErrors_obj +}, +_ipInUnknownProtos_obj = { + "ipInUnknownProtos", 7, 0, + NULL, &_ipForwDatagrams_obj +}, +_ipInDiscards_obj = { + "ipInDiscards", 8, 0, + NULL, &_ipInUnknownProtos_obj +}, +_ipInDelivers_obj = { + "ipInDelivers", 9, 0, + NULL, &_ipInDiscards_obj +}, +_ipOutRequests_obj = { + "ipOutRequests", 10, 0, + NULL, &_ipInDelivers_obj +}, +_ipOutDiscards_obj = { + "ipOutDiscards", 11, 0, + NULL, &_ipOutRequests_obj +}, +_ipOutNoRoutes_obj = { + "ipOutNoRoutes", 12, 0, + NULL, &_ipOutDiscards_obj +}, +_ipReasmTimeout_obj = { + "ipReasmTimeout", 13, 0, + NULL, &_ipOutNoRoutes_obj +}, +_ipReasmReqds_obj = { + "ipReasmReqds", 14, 0, + NULL, &_ipReasmTimeout_obj +}, +_ipReasmOKs_obj = { + "ipReasmOKs", 15, 0, + NULL, &_ipReasmReqds_obj +}, +_ipReasmFails_obj = { + "ipReasmFails", 16, 0, + NULL, &_ipReasmOKs_obj +}, +_ipFragOKs_obj = { + "ipFragOKs", 17, 0, + NULL, &_ipReasmFails_obj +}, +_ipFragFails_obj = { + "ipFragFails", 18, 0, + NULL, &_ipFragOKs_obj +}, +_ipFragCreates_obj = { + "ipFragCreates", 19, 0, + NULL, &_ipFragFails_obj +}, +_ipAddrTable_obj = { + "ipAddrTable", 20, 0, + &_ipAddrEntry_obj, &_ipFragCreates_obj +}, +_ipRoutingTable_obj = { + "ipRoutingTable", 21, 0, + &_ipRouteEntry_obj, &_ipAddrTable_obj +}, +_ipNetToMediaTable_obj = { + "ipNetToMediaTable", 22, 0, + &_ipNetToMediaEntry_obj, &_ipRoutingTable_obj +}, +_atIfIndex_obj = { + "atIfIndex", 1, 0, + NULL, NULL +}, +_atPhysAddress_obj = { + "atPhysAddress", 2, 0, + NULL, &_atIfIndex_obj +}, +_atNetAddress_obj = { + "atNetAddress", 3, 0, + NULL, &_atPhysAddress_obj +}, +_atEntry_obj = { + "atEntry", 1, 0, + &_atNetAddress_obj, NULL +}, +_atTable_obj = { + "atTable", 1, 0, + &_atEntry_obj, NULL +}, +_ifIndex_obj = { + "ifIndex", 1, 0, + NULL, NULL +}, +_ifDescr_obj = { + "ifDescr", 2, 0, + NULL, &_ifIndex_obj +}, +_ifType_obj = { + "ifType", 3, 0, + NULL, &_ifDescr_obj +}, +_ifMtu_obj = { + "ifMtu", 4, 0, + NULL, &_ifType_obj +}, +_ifSpeed_obj = { + "ifSpeed", 5, 0, + NULL, &_ifMtu_obj +}, +_ifPhysAddress_obj = { + "ifPhysAddress", 6, 0, + NULL, &_ifSpeed_obj +}, +_ifAdminStatus_obj = { + "ifAdminStatus", 7, 0, + NULL, &_ifPhysAddress_obj +}, +_ifOperStatus_obj = { + "ifOperStatus", 8, 0, + NULL, &_ifAdminStatus_obj +}, +_ifLastChange_obj = { + "ifLastChange", 9, 0, + NULL, &_ifOperStatus_obj +}, +_ifInOctets_obj = { + "ifInOctets", 10, 0, + NULL, &_ifLastChange_obj +}, +_ifInUcastPkts_obj = { + "ifInUcastPkts", 11, 0, + NULL, &_ifInOctets_obj +}, +_ifInNUcastPkts_obj = { + "ifInNUcastPkts", 12, 0, + NULL, &_ifInUcastPkts_obj +}, +_ifInDiscards_obj = { + "ifInDiscards", 13, 0, + NULL, &_ifInNUcastPkts_obj +}, +_ifInErrors_obj = { + "ifInErrors", 14, 0, + NULL, &_ifInDiscards_obj +}, +_ifInUnknownProtos_obj = { + "ifInUnknownProtos", 15, 0, + NULL, &_ifInErrors_obj +}, +_ifOutOctets_obj = { + "ifOutOctets", 16, 0, + NULL, &_ifInUnknownProtos_obj +}, +_ifOutUcastPkts_obj = { + "ifOutUcastPkts", 17, 0, + NULL, &_ifOutOctets_obj +}, +_ifOutNUcastPkts_obj = { + "ifOutNUcastPkts", 18, 0, + NULL, &_ifOutUcastPkts_obj +}, +_ifOutDiscards_obj = { + "ifOutDiscards", 19, 0, + NULL, &_ifOutNUcastPkts_obj +}, +_ifOutErrors_obj = { + "ifOutErrors", 20, 0, + NULL, &_ifOutDiscards_obj +}, +_ifOutQLen_obj = { + "ifOutQLen", 21, 0, + NULL, &_ifOutErrors_obj +}, +_ifSpecific_obj = { + "ifSpecific", 22, 0, + NULL, &_ifOutQLen_obj +}, +_ifEntry_obj = { + "ifEntry", 1, 0, + &_ifSpecific_obj, NULL +}, +_ifNumber_obj = { + "ifNumber", 1, 0, + NULL, NULL +}, +_ifTable_obj = { + "ifTable", 2, 0, + &_ifEntry_obj, &_ifNumber_obj +}, +_sysDescr_obj = { + "sysDescr", 1, 0, + NULL, NULL +}, +_sysObjectID_obj = { + "sysObjectID", 2, 0, + NULL, &_sysDescr_obj +}, +_sysUpTime_obj = { + "sysUpTime", 3, 0, + NULL, &_sysObjectID_obj +}, +_sysContact_obj = { + "sysContact", 4, 0, + NULL, &_sysUpTime_obj +}, +_sysName_obj = { + "sysName", 5, 0, + NULL, &_sysContact_obj +}, +_sysLocation_obj = { + "sysLocation", 6, 0, + NULL, &_sysName_obj +}, +_sysServices_obj = { + "sysServices", 7, 0, + NULL, &_sysLocation_obj +}, +_system_obj = { + "system", 1, 0, + &_sysServices_obj, NULL +}, +_interfaces_obj = { + "interfaces", 2, 0, + &_ifTable_obj, &_system_obj +}, +_at_obj = { + "at", 3, 0, + &_atTable_obj, &_interfaces_obj +}, +_ip_obj = { + "ip", 4, 0, + &_ipNetToMediaTable_obj, &_at_obj +}, +_icmp_obj = { + "icmp", 5, 0, + &_icmpOutAddrMaskReps_obj, &_ip_obj +}, +_tcp_obj = { + "tcp", 6, 0, + &_tcpOutRsts_obj, &_icmp_obj +}, +_udp_obj = { + "udp", 7, 0, + &_udpTable_obj, &_tcp_obj +}, +_egp_obj = { + "egp", 8, 0, + &_egpAs_obj, &_udp_obj +}, +_transmission_obj = { + "transmission", 10, 0, + NULL, &_egp_obj +}, +_snmp_obj = { + "snmp", 11, 0, + &_snmpEnableAuthTraps_obj, &_transmission_obj +}, +_mib_obj = { + "mib", 1, 0, + &_snmp_obj, NULL +}, +_directory_obj = { + "directory", 1, 0, + NULL, NULL +}, +_mgmt_obj = { + "mgmt", 2, 0, + &_mib_obj, &_directory_obj +}, +_experimental_obj = { + "experimental", 3, 0, + NULL, &_mgmt_obj +}, +_private_obj = { + "private", 4, 0, + &_enterprises_obj, &_experimental_obj +}, +_internet_obj = { + "internet", 1, 0, + &_private_obj, NULL +}, +_dod_obj = { + "dod", 6, 0, + &_internet_obj, NULL +}, +_org_obj = { + "org", 3, 0, + &_dod_obj, NULL +}, +_iso_obj = { + "iso", 1, 0, + &_org_obj, NULL +}, +*mibroot = &_iso_obj; diff --git a/usr.sbin/tcpdump/tcpdump/nametoaddr.c b/usr.sbin/tcpdump/tcpdump/nametoaddr.c new file mode 100644 index 000000000000..6f2330f141c1 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/nametoaddr.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Name to id translation routines used by the scanner. + * These functions are not time critical. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: nametoaddr.c,v 1.9 91/02/04 16:56:46 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ultrix +#include +#include +#include +#endif + +#include "interface.h" +#include "etherent.h" +#include "nametoaddr.h" + +/* + * Convert host name to internet address. + * Return 0 upon failure. + */ +u_long ** +s_nametoaddr(name) + char *name; +{ +#ifndef h_addr + static u_long *hlist[2]; +#endif + u_long **p; + struct hostent *hp; + + if (hp = gethostbyname(name)) { +#ifndef h_addr + hlist[0] = (u_long *)hp->h_addr; + NTOHL(hp->h_addr); + return hlist; +#else + for (p = (u_long **)hp->h_addr_list; *p; ++p) + NTOHL(**p); + return (u_long **)hp->h_addr_list; +#endif + } + else + return 0; +} + +/* + * Convert net name to internet address. + * Return 0 upon failure. + */ +u_long +s_nametonetaddr(name) + char *name; +{ + struct netent *np; + + if (np = getnetbyname(name)) + return np->n_net; + else + return 0; +} + +/* + * Convert a port name to its port and protocol numbers. + * We assume only TCP or UDP. + * Return 0 upon failure. + */ +s_nametoport(name, port, proto) + char *name; + int *port; + int *proto; +{ + struct servent *sp; + char *other; + + sp = getservbyname(name, (char *)0); + if (sp != 0) { + NTOHS(sp->s_port); + *port = sp->s_port; + *proto = s_nametoproto(sp->s_proto); + /* + * We need to check /etc/services for ambiguous entries. + * If we find the ambiguous entry, and it has the + * same port number, change the proto to PROTO_UNDEF + * so both TCP and UDP will be checked. + */ + if (*proto == IPPROTO_TCP) + other = "udp"; + else + other = "tcp"; + + sp = getservbyname(name, other); + if (sp != 0) { + NTOHS(sp->s_port); + if (*port != sp->s_port) + /* Can't handle ambigous names that refer + to different port numbers. */ + warning("ambiguous port %s in /etc/services", + name); + *proto = PROTO_UNDEF; + } + return 1; + } +#ifdef ultrix + /* Special hack in case NFS isn't in /etc/services */ + if (strcmp(name, "nfs") == 0) { + *port = NFS_PORT; + *proto = PROTO_UNDEF; + return 1; + } +#endif + return 0; +} + +int +s_nametoproto(str) + char *str; +{ + struct protoent *p; + + p = getprotobyname(str); + if (p != 0) + return p->p_proto; + else + return PROTO_UNDEF; +} + +#include "etherproto.h" + +int +s_nametoeproto(s) + char *s; +{ + struct eproto *p = eproto_db; + + while (p->s != 0) { + if (strcmp(p->s, s) == 0) + return p->p; + p += 1; + } + return PROTO_UNDEF; +} + +/* Hex digit to integer. */ +static inline int +xdtoi(c) +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +u_long +atoin(s) + char *s; +{ + u_long addr = 0; + u_int n; + + while (1) { + n = 0; + while (*s && *s != '.') + n = n * 10 + *s++ - '0'; + addr <<= 8; + addr |= n & 0xff; + if (*s == '\0') + return addr; + ++s; + } + /* NOTREACHED */ +} + + +/* + * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new + * ethernet address. Assumes 's' is well formed. + */ +u_char * +ETHER_aton(s) + char *s; +{ + register u_char *ep, *e; + register u_int d; + + e = ep = (u_char *)malloc(6); + + while (*s) { + if (*s == ':') + s += 1; + d = xdtoi(*s++); + if (isxdigit(*s)) { + d <<= 4; + d |= xdtoi(*s++); + } + *ep++ = d; + } + + return e; +} + +#ifndef ETHER_SERVICE +u_char * +ETHER_hostton(name) + char *name; +{ + struct etherent *ep; + FILE *fp; + u_char *ap; + + fp = fopen(ETHERS_FILE, "r"); + if (fp != 0) { + while (ep = next_etherent(fp)) { + if (strcmp(ep->name, name) == 0) { + ap = (u_char *)malloc(6); + bcopy(ep->addr, ap, 6); + return ap; + } + } + } + return (u_char *)0; +} +#endif diff --git a/usr.sbin/tcpdump/tcpdump/nametoaddr.h b/usr.sbin/tcpdump/tcpdump/nametoaddr.h new file mode 100644 index 000000000000..23da3f2580f7 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/nametoaddr.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: nametoaddr.h,v 1.6 90/09/24 12:50:41 mccanne Exp $ (LBL) + * + * Address to name translation routines. + */ + +extern u_long **s_nametoaddr(); +extern u_long s_nametonetaddr(); + +extern int s_nametoport(); +extern int s_nametoproto(); +extern int s_nametoeproto(); + +extern u_char *ETHER_hostton(); +extern u_char *ETHER_aton(); + +/* + * If a protocol is unknown, PROTO_UNDEF is returned. + * Also, s_nametoport() returns the protocol along with the port number. + * If there are ambiguous entried in /etc/services (i.e. domain + * can be either tcp or udp) PROTO_UNDEF is returned. + */ +#define PROTO_UNDEF -1 + diff --git a/usr.sbin/tcpdump/tcpdump/ntp.h b/usr.sbin/tcpdump/tcpdump/ntp.h new file mode 100644 index 000000000000..493686d95c48 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/ntp.h @@ -0,0 +1,117 @@ +/* $Header: ntp.h,v 1.1 90/08/07 11:08:27 mogul Exp $ */ + +/* + * Based on ntp.h from the U of MD implementation + * This file is based on Version 2 of the NTP spec (RFC1119). + */ + +/* + * Definitions for the masses + */ +#define JAN_1970 2208988800 /* 1970 - 1900 in seconds */ + +/* + * Structure definitions for NTP fixed point values + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Integer Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fraction Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Integer Part | Fraction Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +struct l_fixedpt { + u_long int_part; + u_long fraction; +}; + +struct s_fixedpt { + u_short int_part; + u_short fraction; +}; + +/* ================= Table 3.3. Packet Variables ================= */ +/* + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |LI | VN | Mode| Stratum | Poll | Precision | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Synchronizing Distance | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Synchronizing Dispersion | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reference Clock Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Reference Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Originate Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Receive Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Transmit Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +struct ntpdata { + u_char status; /* status of local clock and leap info */ + u_char stratum; /* Stratum level */ + u_char ppoll; /* poll value */ + int precision:8; + struct s_fixedpt distance; + struct s_fixedpt dispersion; + u_long refid; + struct l_fixedpt reftime; + struct l_fixedpt org; + struct l_fixedpt rec; + struct l_fixedpt xmt; +}; +/* + * Leap Second Codes (high order two bits) + */ +#define NO_WARNING 0x00 /* no warning */ +#define PLUS_SEC 0x40 /* add a second (61 seconds) */ +#define MINUS_SEC 0x80 /* minus a second (59 seconds) */ +#define ALARM 0xc0 /* alarm condition (clock unsynchronized) */ + +/* + * Clock Status Bits that Encode Version + */ +#define NTPVERSION_1 0x08 +#define VERSIONMASK 0x38 +#define LEAPMASK 0xc0 +#define MODEMASK 0x07 + +/* + * Code values + */ +#define MODE_UNSPEC 0 /* unspecified */ +#define MODE_SYM_ACT 1 /* symmetric active */ +#define MODE_SYM_PAS 2 /* symmetric passive */ +#define MODE_CLIENT 3 /* client */ +#define MODE_SERVER 4 /* server */ +#define MODE_BROADCAST 5 /* broadcast */ +#define MODE_RES1 6 /* reserved */ +#define MODE_RES2 7 /* reserved */ + +/* + * Stratum Definitions + */ +#define UNSPECIFIED 0 +#define PRIM_REF 1 /* radio clock */ +#define INFO_QUERY 62 /* **** THIS implementation dependent **** */ +#define INFO_REPLY 63 /* **** THIS implementation dependent **** */ diff --git a/usr.sbin/tcpdump/tcpdump/optimize.c b/usr.sbin/tcpdump/tcpdump/optimize.c new file mode 100644 index 000000000000..50640112fb05 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/optimize.c @@ -0,0 +1,1871 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Optimization module for tcpdump intermediate representation. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: optimize.c,v 1.35 91/07/18 09:27:55 mccanne Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include + +#include "interface.h" +#include "gencode.h" + +#define A_ATOM BPF_MEMWORDS +#define X_ATOM (BPF_MEMWORDS+1) + +#define NOP -1 + +/* + * This define is used to represent *both* the accumulator and + * x register in use-def computations. + * Currently, the use-def code assumes only one definition per instruction. + */ +#define AX_ATOM N_ATOMS + +/* + * A flag to indicate that further optimization is needed. + * Iterative passes are continued until a given pass yields no + * branch movement. + */ +static int done; + +/* + * A block is marked if only if its mark equals the current mark. + * Rather than traverse the code array, marking each item, 'cur_mark' is + * incremented. This automatically makes each element unmarked. + */ +static int cur_mark; +#define isMarked(p) ((p)->mark == cur_mark) +#define unMarkAll() cur_mark += 1 +#define Mark(p) ((p)->mark = cur_mark) + +static void opt_init(); +static void opt_cleanup(); + +static void make_marks(); +static void mark_code(); + +static void intern_blocks(); + +static int eq_slist(); + +static int n_blocks; +struct block **blocks; +static int n_edges; +struct edge **edges; + +/* + * A bit vector set representation of the dominators. + * We round up the set size to the next power of two. + */ +static int nodewords; +static int edgewords; +struct block **levels; +u_long *space; +#define BITS_PER_WORD (8*sizeof(u_long)) +/* + * True if a is in uset {p} + */ +#define SET_MEMBER(p, a) \ +((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD))) + +/* + * Add 'a' to uset p. + */ +#define SET_INSERT(p, a) \ +(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD)) + +/* + * Delete 'a' from uset p. + */ +#define SET_DELETE(p, a) \ +(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD)) + +/* + * a := a intersect b + */ +#define SET_INTERSECT(a, b, n)\ +{\ + register u_long *_x = a, *_y = b;\ + register int _n = n;\ + while (--_n >= 0) *_x++ &= *_y++;\ +} + +/* + * a := a - b + */ +#define SET_SUBTRACT(a, b, n)\ +{\ + register u_long *_x = a, *_y = b;\ + register int _n = n;\ + while (--_n >= 0) *_x++ &=~ *_y++;\ +} + +/* + * a := a union b + */ +#define SET_UNION(a, b, n)\ +{\ + register u_long *_x = a, *_y = b;\ + register int _n = n;\ + while (--_n >= 0) *_x++ |= *_y++;\ +} + +static uset all_dom_sets; +static uset all_closure_sets; +static uset all_edge_sets; + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +static void +find_levels_r(b) + struct block *b; +{ + int level; + + if (isMarked(b)) + return; + + Mark(b); + b->link = 0; + + if (JT(b)) { + find_levels_r(JT(b)); + find_levels_r(JF(b)); + level = MAX(JT(b)->level, JF(b)->level) + 1; + } else + level = 0; + b->level = level; + b->link = levels[level]; + levels[level] = b; +} + +/* + * Level graph. The levels go from 0 at the leaves to + * N_LEVELS at the root. The levels[] array points to the + * first node of the level list, whose elements are linked + * with the 'link' field of the struct block. + */ +static void +find_levels(root) + struct block *root; +{ + bzero((char *)levels, n_blocks * sizeof(*levels)); + unMarkAll(); + find_levels_r(root); +} + +/* + * Find dominator relationships. + * Assumes graph has been leveled. + */ +static void +find_dom(root) + struct block *root; +{ + int i; + struct block *b; + u_long *x; + + /* + * Initialize sets to contain all nodes. + */ + x = all_dom_sets; + i = n_blocks * nodewords; + while (--i >= 0) + *x++ = ~0; + /* Root starts off empty. */ + for (i = nodewords; --i >= 0;) + root->dom[i] = 0; + + /* root->level is the highest level no found. */ + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b; b = b->link) { + SET_INSERT(b->dom, b->id); + if (JT(b) == 0) + continue; + SET_INTERSECT(JT(b)->dom, b->dom, nodewords); + SET_INTERSECT(JF(b)->dom, b->dom, nodewords); + } + } +} + +static void +propedom(ep) + struct edge *ep; +{ + SET_INSERT(ep->edom, ep->id); + if (ep->succ) { + SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords); + SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords); + } +} + +/* + * Compute edge dominators. + * Assumes graph has been leveled and predecessors estabished. + */ +static void +find_edom(root) + struct block *root; +{ + int i; + uset x; + struct block *b; + + x = all_edge_sets; + for (i = n_edges * edgewords; --i >= 0; ) + x[i] = ~0; + + /* root->level is the highest level no found. */ + bzero(root->et.edom, edgewords * sizeof(*(uset)0)); + bzero(root->ef.edom, edgewords * sizeof(*(uset)0)); + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b != 0; b = b->link) { + propedom(&b->et); + propedom(&b->ef); + } + } +} + +/* + * Find the backwards transitive closure of the flow graph. These sets + * are backwards in the sense that we find the set of nodes that reach + * a given node, not the set of nodes that can be reached by a node. + * + * Assumes graph has been leveled. + */ +static void +find_closure(root) + struct block *root; +{ + int i; + struct block *b; + + /* + * Initialize sets to contain no nodes. + */ + bzero((char *)all_closure_sets, + n_blocks * nodewords * sizeof(*all_closure_sets)); + + /* root->level is the highest level no found. */ + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b; b = b->link) { + SET_INSERT(b->closure, b->id); + if (JT(b) == 0) + continue; + SET_UNION(JT(b)->closure, b->closure, nodewords); + SET_UNION(JF(b)->closure, b->closure, nodewords); + } + } +} + +/* + * Return the register number that is used by s. If A and X are both + * used, return AX_ATOM. If no register is used, return -1. + * + * The implementation should probably change to an array access. + */ +static int +atomuse(s) + struct stmt *s; +{ + register int c = s->code; + + if (c == NOP) + return -1; + + switch (BPF_CLASS(c)) { + + case BPF_RET: + return (BPF_RVAL(c) == BPF_A) ? A_ATOM : + (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1; + + case BPF_LD: + case BPF_LDX: + return (BPF_MODE(c) == BPF_IND) ? X_ATOM : + (BPF_MODE(c) == BPF_MEM) ? s->k : -1; + + case BPF_ST: + return A_ATOM; + + case BPF_STX: + return X_ATOM; + + case BPF_JMP: + case BPF_ALU: + if (BPF_SRC(c) == BPF_X) + return AX_ATOM; + return A_ATOM; + + case BPF_MISC: + return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM; + } + abort(); + /* NOTREACHED */ +} + +/* + * Return the register number that is defined by 's'. We assume that + * a single stmt cannot define more than one register. If no register + * is defined, return -1. + * + * The implementation should probably change to an array access. + */ +static int +atomdef(s) + struct stmt *s; +{ + if (s->code == NOP) + return -1; + + switch (BPF_CLASS(s->code)) { + + case BPF_LD: + case BPF_ALU: + return A_ATOM; + + case BPF_LDX: + return X_ATOM; + + case BPF_ST: + case BPF_STX: + return s->k; + + case BPF_MISC: + return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM; + } + return -1; +} + +static void +compute_local_ud(b) + struct block *b; +{ + struct slist *s; + atomset def = 0, use = 0, kill = 0; + int atom; + + for (s = b->stmts; s; s = s->next) { + if (s->s.code == NOP) + continue; + atom = atomuse(&s->s); + if (atom >= 0) { + if (atom == AX_ATOM) { + if (!ATOMELEM(def, X_ATOM)) + use |= ATOMMASK(X_ATOM); + if (!ATOMELEM(def, A_ATOM)) + use |= ATOMMASK(A_ATOM); + } + else if (atom < N_ATOMS) { + if (!ATOMELEM(def, atom)) + use |= ATOMMASK(atom); + } + else + abort(); + } + atom = atomdef(&s->s); + if (atom >= 0) { + if (!ATOMELEM(atom, use)) + kill |= ATOMMASK(atom); + def |= ATOMMASK(atom); + } + } + if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP) + use |= ATOMMASK(A_ATOM); + + b->def = def; + b->kill = kill; + b->in_use = use; +} + +/* + * Assume graph is already leveled. + */ +static void +find_ud(root) + struct block *root; +{ + int i, maxlevel; + struct block *p; + + /* + * root->level is the highest level no found; + * count down from there. + */ + maxlevel = root->level; + for (i = maxlevel; i >= 0; --i) + for (p = levels[i]; p; p = p->link) { + compute_local_ud(p); + p->out_use = 0; + } + + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + p->out_use |= JT(p)->in_use | JF(p)->in_use; + p->in_use |= p->out_use &~ p->kill; + } + } +} + +/* + * These data structures are used in a Cocke and Shwarz style + * value numbering scheme. Since the flowgraph is acyclic, + * exit values can be propagated from a node's predecessors + * provided it is uniquely defined. + */ +struct valnode { + int code; + long v0, v1; + long val; + struct valnode *next; +}; + +#define MODULUS 213 +static struct valnode *hashtbl[MODULUS]; +static int curval; +static int maxval; + +/* Integer constants mapped with the load immediate opcode. */ +#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L) + +struct vmapinfo { + int is_const; + long const_val; +}; + +struct vmapinfo *vmap; +struct valnode *vnode_base; +struct valnode *next_vnode; + +static void +init_val() +{ + curval = 0; + next_vnode = vnode_base; + bzero((char *)vmap, maxval * sizeof(*vmap)); + bzero((char *)hashtbl, sizeof hashtbl); +} + +/* Because we really don't have an IR, this stuff is a little messy. */ +static long +F(code, v0, v1) + int code; + long v0, v1; +{ + u_int hash; + int val; + struct valnode *p; + + hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8); + hash %= MODULUS; + + for (p = hashtbl[hash]; p; p = p->next) + if (p->code == code && p->v0 == v0 && p->v1 == v1) + return p->val; + + val = ++curval; + if (BPF_MODE(code) == BPF_IMM && + (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) { + vmap[val].const_val = v0; + vmap[val].is_const = 1; + } + p = next_vnode++; + p->val = val; + p->code = code; + p->v0 = v0; + p->v1 = v1; + p->next = hashtbl[hash]; + hashtbl[hash] = p; + + return val; +} + +static inline void +vstore(s, valp, newval, alter) + struct stmt *s; + long *valp; + long newval; + int alter; +{ + if (alter && *valp == newval) + s->code = NOP; + else + *valp = newval; +} + +static void +fold_op(s, v0, v1) + struct stmt *s; + long v0, v1; +{ + long a, b; + + a = vmap[v0].const_val; + b = vmap[v1].const_val; + + switch (BPF_OP(s->code)) { + case BPF_ADD: + a += b; + break; + + case BPF_SUB: + a -= b; + break; + + case BPF_MUL: + a *= b; + break; + + case BPF_DIV: + if (b == 0) + error("division by zero"); + a /= b; + break; + + case BPF_AND: + a &= b; + break; + + case BPF_OR: + a |= b; + break; + + case BPF_LSH: + a <<= b; + break; + + case BPF_RSH: + a >>= b; + break; + + case BPF_NEG: + a = -a; + break; + + default: + abort(); + } + s->k = a; + s->code = BPF_LD|BPF_IMM; + done = 0; +} + +static inline struct slist * +this_op(s) + struct slist *s; +{ + while (s != 0 && s->s.code == NOP) + s = s->next; + return s; +} + +static void +opt_not(b) + struct block *b; +{ + struct block *tmp = JT(b); + + JT(b) = JF(b); + JF(b) = tmp; +} + +static void +opt_peep(b) + struct block *b; +{ + struct slist *s; + struct slist *next, *last; + int val; + long v; + + s = b->stmts; + if (s == 0) + return; + + last = s; + while (1) { + s = this_op(s); + if (s == 0) + break; + next = this_op(s->next); + if (next == 0) + break; + last = next; + + /* + * st M[k] --> st M[k] + * ldx M[k] tax + */ + if (s->s.code == BPF_ST && + next->s.code == (BPF_LDX|BPF_MEM) && + s->s.k == next->s.k) { + done = 0; + next->s.code = BPF_MISC|BPF_TAX; + } + /* + * ld #k --> ldx #k + * tax txa + */ + if (s->s.code == (BPF_LD|BPF_IMM) && + next->s.code == (BPF_MISC|BPF_TAX)) { + s->s.code = BPF_LDX|BPF_IMM; + next->s.code = BPF_MISC|BPF_TXA; + done = 0; + } + /* + * This is an ugly special case, but it happens + * when you say tcp[k] or udp[k] where k is a constant. + */ + if (s->s.code == (BPF_LD|BPF_IMM)) { + struct slist *add, *tax, *ild; + + /* + * Check that X isn't used on exit from this + * block (which the optimizer might cause). + * We know the code generator won't generate + * any local dependencies. + */ + if (ATOMELEM(b->out_use, X_ATOM)) + break; + + if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B)) + add = next; + else + add = this_op(next->next); + if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X)) + break; + + tax = this_op(add->next); + if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) + break; + + ild = this_op(tax->next); + if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || + BPF_MODE(ild->s.code) != BPF_IND) + break; + /* + * XXX We need to check that X is not + * subsequently used. We know we can eliminate the + * accumulator modifications since it is defined + * by the last stmt of this sequence. + * + * We want to turn this sequence: + * + * (004) ldi #0x2 {s} + * (005) ldxms [14] {next} -- optional + * (006) addx {add} + * (007) tax {tax} + * (008) ild [x+0] {ild} + * + * into this sequence: + * + * (004) nop + * (005) ldxms [14] + * (006) nop + * (007) nop + * (008) ild [x+2] + * + */ + ild->s.k += s->s.k; + s->s.code = NOP; + add->s.code = NOP; + tax->s.code = NOP; + done = 0; + } + s = next; + } + /* + * If we have a subtract to do a comparsion, and the X register + * is a known constant, we can merge this value into the + * comparison. + */ + if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) && + !ATOMELEM(b->out_use, A_ATOM)) { + val = b->val[X_ATOM]; + if (vmap[val].is_const) { + b->s.k += vmap[val].const_val; + last->s.code = NOP; + done = 0; + } else if (b->s.k == 0) { + /* + * sub x -> nop + * j #0 j x + */ + last->s.code = NOP; + b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) | + BPF_X; + done = 0; + } + } + /* + * Likewise, a constant subtract can be simplified. + */ + else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) && + !ATOMELEM(b->out_use, A_ATOM)) { + b->s.k += last->s.k; + last->s.code = NOP; + done = 0; + } + /* + * and #k nop + * jeq #0 -> jset #k + */ + if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && + !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) { + b->s.k = last->s.k; + b->s.code = BPF_JMP|BPF_K|BPF_JSET; + last->s.code = NOP; + done = 0; + opt_not(b); + } + /* + * If the accumulator is a known constant, we can compute the + * comparison result. + */ + val = b->val[A_ATOM]; + if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) { + v = vmap[val].const_val; + switch (BPF_OP(b->s.code)) { + + case BPF_JEQ: + v = v == b->s.k; + break; + + case BPF_JGT: + v = v > b->s.k; + break; + + case BPF_JGE: + v = v >= b->s.k; + break; + + case BPF_JSET: + v &= b->s.k; + break; + + default: + abort(); + } + if (JF(b) != JT(b)) + done = 0; + if (v) + JF(b) = JT(b); + else + JT(b) = JF(b); + } +} + +/* + * Compute the symbolic value of expression of 's', and update + * anything it defines in the value table 'val'. If 'alter' is true, + * do various optimizations. This code would be cleaner if symblic + * evaluation and code transformations weren't folded together. + */ +static void +opt_stmt(s, val, alter) + struct stmt *s; + long val[]; + int alter; +{ + int op; + long v; + + switch (s->code) { + + case BPF_LD|BPF_ABS|BPF_W: + case BPF_LD|BPF_ABS|BPF_H: + case BPF_LD|BPF_ABS|BPF_B: + v = F(s->code, s->k, 0L); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_IND|BPF_W: + case BPF_LD|BPF_IND|BPF_H: + case BPF_LD|BPF_IND|BPF_B: + v = val[X_ATOM]; + if (alter && vmap[v].is_const) { + s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code); + s->k += vmap[v].const_val; + v = F(s->code, s->k, 0L); + done = 0; + } + else + v = F(s->code, s->k, v); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_LEN: + v = F(s->code, 0L, 0L); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_IMM: + v = K(s->k); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LDX|BPF_IMM: + v = K(s->k); + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_LDX|BPF_MSH|BPF_B: + v = F(s->code, s->k, 0L); + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_ALU|BPF_NEG: + if (alter && vmap[val[A_ATOM]].is_const) { + s->code = BPF_LD|BPF_IMM; + s->k = -vmap[val[A_ATOM]].const_val; + val[A_ATOM] = K(s->k); + } + else + val[A_ATOM] = F(s->code, val[A_ATOM], 0L); + break; + + case BPF_ALU|BPF_ADD|BPF_K: + case BPF_ALU|BPF_SUB|BPF_K: + case BPF_ALU|BPF_MUL|BPF_K: + case BPF_ALU|BPF_DIV|BPF_K: + case BPF_ALU|BPF_AND|BPF_K: + case BPF_ALU|BPF_OR|BPF_K: + case BPF_ALU|BPF_LSH|BPF_K: + case BPF_ALU|BPF_RSH|BPF_K: + op = BPF_OP(s->code); + if (alter) { + if (s->k == 0) { + if (op == BPF_ADD || op == BPF_SUB || + op == BPF_LSH || op == BPF_RSH || + op == BPF_OR) { + s->code = NOP; + break; + } + if (op == BPF_MUL || op == BPF_AND) { + s->code = BPF_LD|BPF_IMM; + val[A_ATOM] = K(s->k); + break; + } + } + if (vmap[val[A_ATOM]].is_const) { + fold_op(s, val[A_ATOM], K(s->k)); + val[A_ATOM] = K(s->k); + break; + } + } + val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); + break; + + case BPF_ALU|BPF_ADD|BPF_X: + case BPF_ALU|BPF_SUB|BPF_X: + case BPF_ALU|BPF_MUL|BPF_X: + case BPF_ALU|BPF_DIV|BPF_X: + case BPF_ALU|BPF_AND|BPF_X: + case BPF_ALU|BPF_OR|BPF_X: + case BPF_ALU|BPF_LSH|BPF_X: + case BPF_ALU|BPF_RSH|BPF_X: + op = BPF_OP(s->code); + if (alter && vmap[val[X_ATOM]].is_const) { + if (vmap[val[A_ATOM]].is_const) { + fold_op(s, val[A_ATOM], val[X_ATOM]); + val[A_ATOM] = K(s->k); + } + else { + s->code = BPF_ALU|BPF_K|op; + s->k = vmap[val[X_ATOM]].const_val; + done = 0; + val[A_ATOM] = + F(s->code, val[A_ATOM], K(s->k)); + } + break; + } + /* + * Check if we're doing something to an accumulator + * that is 0, and simplify. This may not seem like + * much of a simplification but it could open up further + * optimizations. + * XXX We could also check for mul by 1, and -1, etc. + */ + if (alter && vmap[val[A_ATOM]].is_const + && vmap[val[A_ATOM]].const_val == 0) { + if (op == BPF_ADD || op == BPF_OR || + op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) { + s->code = BPF_MISC|BPF_TXA; + vstore(s, &val[A_ATOM], val[X_ATOM], alter); + break; + } + else if (op == BPF_MUL || op == BPF_DIV || + op == BPF_AND) { + s->code = BPF_LD|BPF_IMM; + s->k = 0; + vstore(s, &val[A_ATOM], K(s->k), alter); + break; + } + else if (op == BPF_NEG) { + s->code = NOP; + break; + } + } + val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]); + break; + + case BPF_MISC|BPF_TXA: + vstore(s, &val[A_ATOM], val[X_ATOM], alter); + break; + + case BPF_LD|BPF_MEM: + v = val[s->k]; + if (alter && vmap[v].is_const) { + s->code = BPF_LD|BPF_IMM; + s->k = vmap[v].const_val; + done = 0; + } + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_MISC|BPF_TAX: + vstore(s, &val[X_ATOM], val[A_ATOM], alter); + break; + + case BPF_LDX|BPF_MEM: + v = val[s->k]; + if (alter && vmap[v].is_const) { + s->code = BPF_LDX|BPF_IMM; + s->k = vmap[v].const_val; + done = 0; + } + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_ST: + vstore(s, &val[s->k], val[A_ATOM], alter); + break; + + case BPF_STX: + vstore(s, &val[s->k], val[X_ATOM], alter); + break; + } +} + +static void +deadstmt(s, last) + register struct stmt *s; + register struct stmt *last[]; +{ + register int atom; + + atom = atomuse(s); + if (atom >= 0) { + if (atom == AX_ATOM) { + last[X_ATOM] = 0; + last[A_ATOM] = 0; + } + else + last[atom] = 0; + } + atom = atomdef(s); + if (atom >= 0) { + if (last[atom]) { + done = 0; + last[atom]->code = NOP; + } + last[atom] = s; + } +} + +static void +opt_deadstores(b) + register struct block *b; +{ + register struct slist *s; + register int atom; + struct stmt *last[N_ATOMS]; + + bzero((char *)last, sizeof last); + + for (s = b->stmts; s != 0; s = s->next) + deadstmt(&s->s, last); + deadstmt(&b->s, last); + + for (atom = 0; atom < N_ATOMS; ++atom) + if (last[atom] && !ATOMELEM(b->out_use, atom)) { + last[atom]->code = NOP; + done = 0; + } +} + +static void +opt_blk(b, do_stmts) + struct block *b; +{ + struct slist *s; + struct edge *p; + int i; + long aval; + + /* + * Initialize the atom values. + * If we have no predecessors, everything is undefined. + * Otherwise, we inherent our values from our predecessors. + * If any register has an ambiguous value (i.e. control paths are + * merging) give it the undefined value of 0. + */ + p = b->in_edges; + if (p == 0) + bzero((char *)b->val, sizeof(b->val)); + else { + bcopy((char *)p->pred->val, (char *)b->val, sizeof(b->val)); + while (p = p->next) { + for (i = 0; i < N_ATOMS; ++i) + if (b->val[i] != p->pred->val[i]) + b->val[i] = 0; + } + } + aval = b->val[A_ATOM]; + for (s = b->stmts; s; s = s->next) + opt_stmt(&s->s, b->val, do_stmts); + + /* + * This is a special case: if we don't use anything from this + * block, and we load the accumulator with value that is + * already there, eliminate all the statements. + */ + if (do_stmts && b->out_use == 0 && aval != 0 && + b->val[A_ATOM] == aval) + b->stmts = 0; + else { + opt_peep(b); + opt_deadstores(b); + } + /* + * Set up values for branch optimizer. + */ + if (BPF_SRC(b->s.code) == BPF_K) + b->oval = K(b->s.k); + else + b->oval = b->val[X_ATOM]; + b->et.code = b->s.code; + b->ef.code = -b->s.code; +} + +/* + * Return true if any register that is used on exit from 'succ', has + * an exit value that is different from the corresponding exit value + * from 'b'. + */ +static int +use_conflict(b, succ) + struct block *b, *succ; +{ + int atom; + atomset use = succ->out_use; + + if (use == 0) + return 0; + + for (atom = 0; atom < N_ATOMS; ++atom) + if (ATOMELEM(use, atom)) + if (b->val[atom] != succ->val[atom]) + return 1; + return 0; +} + +struct block * +fold_edge(child, ep) + struct block *child; + struct edge *ep; +{ + int sense; + int aval0, aval1, oval0, oval1; + int code = ep->code; + + if (code < 0) { + code = -code; + sense = 0; + } else + sense = 1; + + if (child->s.code != code) + return 0; + + aval0 = child->val[A_ATOM]; + oval0 = child->oval; + aval1 = ep->pred->val[A_ATOM]; + oval1 = ep->pred->oval; + + if (aval0 != aval1) + return 0; + + if (oval0 == oval1) + /* + * The operands are identical, so the + * result is true if a true branch was + * taken to get here, otherwise false. + */ + return sense ? JT(child) : JF(child); + + if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K)) + /* + * At this point, we only know the comparison if we + * came down the true branch, and it was an equility + * comparison with a constant. We rely on the fact that + * distinct constants have distinct value numbers. + */ + return JF(child); + + return 0; +} + +static void +opt_j(ep) + struct edge *ep; +{ + register int i, k; + register struct block *target; + + if (JT(ep->succ) == 0) + return; + + if (JT(ep->succ) == JF(ep->succ)) { + /* + * Common branch targets can be eliminated, provided + * there is no data dependency. + */ + if (!use_conflict(ep->pred, ep->succ->et.succ)) { + done = 0; + ep->succ = JT(ep->succ); + } + } + /* + * For each edge dominator that matches the successor of this + * edge, promote the edge succesor to the its grandchild. + * + * XXX We violate the set abstraction here in favor a reasonbly + * efficient loop. + */ + top: + for (i = 0; i < edgewords; ++i) { + register u_long x = ep->edom[i]; + + while (x != 0) { + k = ffs(x) - 1; + x &=~ 1 << k; + k += i * BITS_PER_WORD; + + target = fold_edge(ep->succ, edges[k]); + /* + * Check that there is no data dependency between + * nodes that will be violated if we move the edge. + */ + if (target != 0 && !use_conflict(ep->pred, target)) { + done = 0; + ep->succ = target; + if (JT(target) != 0) + /* + * Start over unless we hit a leaf. + */ + goto top; + return; + } + } + } +} + + +static void +or_pullup(b) + struct block *b; +{ + int val, at_top; + struct block *pull; + struct block **diffp, **samep; + struct edge *ep; + + ep = b->in_edges; + if (ep == 0) + return; + + /* + * Make sure each predecessor loads the same value. + * XXX why? + */ + val = ep->pred->val[A_ATOM]; + for (ep = ep->next; ep != 0; ep = ep->next) + if (val != ep->pred->val[A_ATOM]) + return; + + if (JT(b->in_edges->pred) == b) + diffp = &JT(b->in_edges->pred); + else + diffp = &JF(b->in_edges->pred); + + at_top = 1; + while (1) { + if (*diffp == 0) + return; + + if (JT(*diffp) != JT(b)) + return; + + if (!SET_MEMBER((*diffp)->dom, b->id)) + return; + + if ((*diffp)->val[A_ATOM] != val) + break; + + diffp = &JF(*diffp); + at_top = 0; + } + samep = &JF(*diffp); + while (1) { + if (*samep == 0) + return; + + if (JT(*samep) != JT(b)) + return; + + if (!SET_MEMBER((*samep)->dom, b->id)) + return; + + if ((*samep)->val[A_ATOM] == val) + break; + + /* XXX Need to check that there are no data dependencies + between dp0 and dp1. Currently, the code generator + will not produce such dependencies. */ + samep = &JF(*samep); + } +#ifdef notdef + /* XXX This doesn't cover everything. */ + for (i = 0; i < N_ATOMS; ++i) + if ((*samep)->val[i] != pred->val[i]) + return; +#endif + /* Pull up the node. */ + pull = *samep; + *samep = JF(pull); + JF(pull) = *diffp; + + /* + * At the top of the chain, each predecessor needs to point at the + * pulled up node. Inside the chain, there is only one predecessor + * to worry about. + */ + if (at_top) { + for (ep = b->in_edges; ep != 0; ep = ep->next) { + if (JT(ep->pred) == b) + JT(ep->pred) = pull; + else + JF(ep->pred) = pull; + } + } + else + *diffp = pull; + + done = 0; +} + +static void +and_pullup(b) + struct block *b; +{ + int val, at_top; + struct block *pull; + struct block **diffp, **samep; + struct edge *ep; + + ep = b->in_edges; + if (ep == 0) + return; + + /* + * Make sure each predecessor loads the same value. + */ + val = ep->pred->val[A_ATOM]; + for (ep = ep->next; ep != 0; ep = ep->next) + if (val != ep->pred->val[A_ATOM]) + return; + + if (JT(b->in_edges->pred) == b) + diffp = &JT(b->in_edges->pred); + else + diffp = &JF(b->in_edges->pred); + + at_top = 1; + while (1) { + if (*diffp == 0) + return; + + if (JF(*diffp) != JF(b)) + return; + + if (!SET_MEMBER((*diffp)->dom, b->id)) + return; + + if ((*diffp)->val[A_ATOM] != val) + break; + + diffp = &JT(*diffp); + at_top = 0; + } + samep = &JT(*diffp); + while (1) { + if (*samep == 0) + return; + + if (JF(*samep) != JF(b)) + return; + + if (!SET_MEMBER((*samep)->dom, b->id)) + return; + + if ((*samep)->val[A_ATOM] == val) + break; + + /* XXX Need to check that there are no data dependencies + between diffp and samep. Currently, the code generator + will not produce such dependencies. */ + samep = &JT(*samep); + } +#ifdef notdef + /* XXX This doesn't cover everything. */ + for (i = 0; i < N_ATOMS; ++i) + if ((*samep)->val[i] != pred->val[i]) + return; +#endif + /* Pull up the node. */ + pull = *samep; + *samep = JT(pull); + JT(pull) = *diffp; + + /* + * At the top of the chain, each predecessor needs to point at the + * pulled up node. Inside the chain, there is only one predecessor + * to worry about. + */ + if (at_top) { + for (ep = b->in_edges; ep != 0; ep = ep->next) { + if (JT(ep->pred) == b) + JT(ep->pred) = pull; + else + JF(ep->pred) = pull; + } + } + else + *diffp = pull; + + done = 0; +} + +static void +opt_blks(root, do_stmts) + struct block *root; +{ + int i, maxlevel; + struct block *p; + + init_val(); + maxlevel = root->level; + for (i = maxlevel; i >= 0; --i) + for (p = levels[i]; p; p = p->link) + opt_blk(p, do_stmts); + + if (do_stmts) + /* + * No point trying to move branches; it can't possibly + * make a difference at this point. + */ + return; + + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + opt_j(&p->et); + opt_j(&p->ef); + } + } + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + or_pullup(p); + and_pullup(p); + } + } +} + +static inline void +link_inedge(parent, child) + struct edge *parent; + struct block *child; +{ + parent->next = child->in_edges; + child->in_edges = parent; +} + +static void +find_inedges(root) + struct block *root; +{ + int i; + struct block *b; + struct edge *ep; + + for (i = 0; i < n_blocks; ++i) + blocks[i]->in_edges = 0; + + /* + * Traverse the graph, adding each edge to the predecessor + * list of its sucessors. Skip the leaves (i.e. level 0). + */ + for (i = root->level; i > 0; --i) { + for (b = levels[i]; b != 0; b = b->link) { + link_inedge(&b->et, JT(b)); + link_inedge(&b->ef, JF(b)); + } + } +} + +static void +opt_root(b) + struct block **b; +{ + struct slist *tmp, *s; + + s = (*b)->stmts; + (*b)->stmts = 0; + while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b)) + *b = JT(*b); + + tmp = (*b)->stmts; + if (tmp != 0) + sappend(s, tmp); + (*b)->stmts = s; +} + +static void +opt_loop(root, do_stmts) + struct block *root; + int do_stmts; +{ + int passes = 0; +#ifdef BDEBUG + if (dflag > 1) + opt_dump(root); +#endif + do { + done = 1; + find_levels(root); + find_dom(root); + find_closure(root); + find_inedges(root); + find_ud(root); + find_edom(root); + opt_blks(root, do_stmts); +#ifdef BDEBUG + if (dflag > 1) + opt_dump(root); +#endif + } while (!done); +} + +/* + * Optimize the filter code in its dag representation. + */ +void +optimize(rootp) + struct block **rootp; +{ + struct block *root; + + root = *rootp; + + opt_init(root); + opt_loop(root, 0); + opt_loop(root, 1); + intern_blocks(root); + opt_root(rootp); + opt_cleanup(); +} + +static void +make_marks(p) + struct block *p; +{ + if (!isMarked(p)) { + Mark(p); + if (BPF_CLASS(p->s.code) != BPF_RET) { + make_marks(JT(p)); + make_marks(JF(p)); + } + } +} + +/* + * Mark code array such that isMarked(i) is true + * only for nodes that are alive. + */ +static void +mark_code(p) + struct block *p; +{ + cur_mark += 1; + make_marks(p); +} + +/* + * True iff the two stmt lists load the same value from the packet into + * the accumulator. + */ +static int +eq_slist(x, y) + struct slist *x, *y; +{ + while (1) { + while (x && x->s.code == NOP) + x = x->next; + while (y && y->s.code == NOP) + y = y->next; + if (x == 0) + return y == 0; + if (y == 0) + return x == 0; + if (x->s.code != y->s.code || x->s.k != y->s.k) + return 0; + x = x->next; + y = y->next; + } +} + +static inline int +eq_blk(b0, b1) + struct block *b0, *b1; +{ + if (b0->s.code == b1->s.code && + b0->s.k == b1->s.k && + b0->et.succ == b1->et.succ && + b0->ef.succ == b1->ef.succ) + return eq_slist(b0->stmts, b1->stmts); + return 0; +} + +static void +intern_blocks(root) + struct block *root; +{ + struct block *p; + int i, j; + int done; + top: + done = 1; + for (i = 0; i < n_blocks; ++i) + blocks[i]->link = 0; + + mark_code(root); + + for (i = n_blocks - 1; --i >= 0; ) { + if (!isMarked(blocks[i])) + continue; + for (j = i + 1; j < n_blocks; ++j) { + if (!isMarked(blocks[j])) + continue; + if (eq_blk(blocks[i], blocks[j])) { + blocks[i]->link = blocks[j]->link ? + blocks[j]->link : blocks[j]; + break; + } + } + } + for (i = 0; i < n_blocks; ++i) { + p = blocks[i]; + if (JT(p) == 0) + continue; + if (JT(p)->link) { + done = 0; + JT(p) = JT(p)->link; + } + if (JF(p)->link) { + done = 0; + JF(p) = JF(p)->link; + } + } + if (!done) + goto top; +} + +static void +opt_cleanup() +{ + free((void *)vnode_base); + free((void *)vmap); + free((void *)edges); + free((void *)space); + free((void *)levels); + free((void *)blocks); +} + +/* + * Return the number of stmts in 's'. + */ +static int +slength(s) + struct slist *s; +{ + int n = 0; + + for (; s; s = s->next) + if (s->s.code != NOP) + ++n; + return n; +} + +/* + * Return the number of nodes reachable by 'p'. + * All nodes should be initially unmarked. + */ +static int +count_blocks(p) + struct block *p; +{ + if (p == 0 || isMarked(p)) + return 0; + Mark(p); + return count_blocks(JT(p)) + count_blocks(JF(p)) + 1; +} + +/* + * Do a depth first search on the flow graph, numbering the + * the basic blocks, and entering them into the 'blocks' array.` + */ +static void +number_blks_r(p) + struct block *p; +{ + int n; + + if (p == 0 || isMarked(p)) + return; + + Mark(p); + n = n_blocks++; + p->id = n; + blocks[n] = p; + + number_blks_r(JT(p)); + number_blks_r(JF(p)); +} + +/* + * Return the number of stmts in the flowgraph reachable by 'p'. + * The nodes should be unmarked before calling. + */ +static int +count_stmts(p) + struct block *p; +{ + int n; + + if (p == 0 || isMarked(p)) + return 0; + Mark(p); + n = count_stmts(JT(p)) + count_stmts(JF(p)); + return slength(p->stmts) + n + 1; +} + +/* + * Allocate memory. All allocation is done before optimization + * is begun. A linear bound on the size of all data structures is computed + * from the total number of blocks and/or statements. + */ +static void +opt_init(root) + struct block *root; +{ + u_long *p; + int i, n, max_stmts; + + /* + * First, count the blocks, so we can malloc an array to map + * block number to block. Then, put the blocks into the array. + */ + unMarkAll(); + n = count_blocks(root); + blocks = (struct block **)malloc(n * sizeof(*blocks)); + unMarkAll(); + n_blocks = 0; + number_blks_r(root); + + n_edges = 2 * n_blocks; + edges = (struct edge **)malloc(n_edges * sizeof(*edges)); + + /* + * The number of levels is bounded by the number of nodes. + */ + levels = (struct block **)malloc(n_blocks * sizeof(*levels)); + + edgewords = n_edges / (8 * sizeof(u_long)) + 1; + nodewords = n_blocks / (8 * sizeof(u_long)) + 1; + + /* XXX */ + space = (u_long *)malloc(2 * n_blocks * nodewords * sizeof(*space) + + n_edges * edgewords * sizeof(*space)); + p = space; + all_dom_sets = p; + for (i = 0; i < n; ++i) { + blocks[i]->dom = p; + p += nodewords; + } + all_closure_sets = p; + for (i = 0; i < n; ++i) { + blocks[i]->closure = p; + p += nodewords; + } + all_edge_sets = p; + for (i = 0; i < n; ++i) { + register struct block *b = blocks[i]; + + b->et.edom = p; + p += edgewords; + b->ef.edom = p; + p += edgewords; + b->et.id = i; + edges[i] = &b->et; + b->ef.id = n_blocks + i; + edges[n_blocks + i] = &b->ef; + b->et.pred = b; + b->ef.pred = b; + } + max_stmts = 0; + for (i = 0; i < n; ++i) + max_stmts += slength(blocks[i]->stmts) + 1; + /* + * We allocate at most 3 value numbers per statement, + * so this is an upper bound on the number of valnodes + * we'll need. + */ + maxval = 3 * max_stmts; + vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap)); + vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap)); +} + +/* + * Some pointers used to convert the basic block form of the code, + * into the array form that BPF requires. 'fstart' will point to + * the malloc'd array while 'ftail' is used during the recursive traversal. + */ +static struct bpf_insn *fstart; +static struct bpf_insn *ftail; + +#ifdef BDEBUG +int bids[1000]; +#endif + +static void +convert_code_r(p) + struct block *p; +{ + struct bpf_insn *dst; + struct slist *src; + int slen; + u_int off; + + if (p == 0 || isMarked(p)) + return; + Mark(p); + + convert_code_r(JF(p)); + convert_code_r(JT(p)); + + slen = slength(p->stmts); + dst = ftail -= slen + 1; + + p->offset = dst - fstart; + + for (src = p->stmts; src; src = src->next) { + if (src->s.code == NOP) + continue; + dst->code = (u_short)src->s.code; + dst->k = src->s.k; + ++dst; + } +#ifdef BDEBUG + bids[dst - fstart] = p->id + 1; +#endif + dst->code = (u_short)p->s.code; + dst->k = p->s.k; + if (JT(p)) { + off = JT(p)->offset - (p->offset + slen) - 1; + if (off >= 256) + error("long jumps not supported"); + dst->jt = off; + off = JF(p)->offset - (p->offset + slen) - 1; + if (off >= 256) + error("long jumps not supported"); + dst->jf = off; + } +} + + +/* + * Convert flowgraph intermediate representation to the + * BPF array representation. Set *lenp to the number of instructions. + */ +struct bpf_insn * +icode_to_fcode(root, lenp) + struct block *root; + int *lenp; +{ + int n; + struct bpf_insn *fp; + + unMarkAll(); + n = *lenp = count_stmts(root); + + fp = (struct bpf_insn *)malloc(sizeof(*fp) * n); + bzero((char *)fp, sizeof(*fp) * n); + fstart = fp; + ftail = fp + n; + + unMarkAll(); + convert_code_r(root); + + return fp; +} + +#ifdef BDEBUG +opt_dump(root) + struct block *root; +{ + struct bpf_program f; + + bzero(bids, sizeof bids); + f.bf_insns = icode_to_fcode(root, &f.bf_len); + bpf_dump(&f, 1); + putchar('\n'); + free((char *)f.bf_insns); +} +#endif diff --git a/usr.sbin/tcpdump/tcpdump/os.c b/usr.sbin/tcpdump/tcpdump/os.c new file mode 100644 index 000000000000..856fb5a2bc66 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/os.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: os-bsd.c,v 1.2 90/09/21 02:12:17 mccanne Exp $ (LBL)"; +#endif + diff --git a/usr.sbin/tcpdump/tcpdump/os.h b/usr.sbin/tcpdump/tcpdump/os.h new file mode 100644 index 000000000000..e0d01cf9484a --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/os.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: os-bsd.h,v 1.15 91/05/05 23:59:11 mccanne Exp $ (LBL) + */ + +#include + +#ifndef BSD +#define BSD +#endif + +#define SHA(ap) ((ap)->arp_sha) +#define SPA(ap) ((ap)->arp_spa) +#define THA(ap) ((ap)->arp_tha) +#define TPA(ap) ((ap)->arp_tpa) + +#define EDST(ep) ((ep)->ether_dhost) +#define ESRC(ep) ((ep)->ether_shost) + +#ifndef ETHERTYPE_REVARP +#define ETHERTYPE_REVARP 0x8035 +#endif + +#ifndef IPPROTO_ND +/* From on a Sun somewhere. */ +#define IPPROTO_ND 77 +#endif + +#ifndef REVARP_REQUEST +#define REVARP_REQUEST 3 +#endif +#ifndef REVARP_REPLY +#define REVARP_REPLY 4 +#endif + +/* newish RIP commands */ +#ifndef RIPCMD_POLL +#define RIPCMD_POLL 5 +#endif +#ifndef RIPCMD_POLLENTRY +#define RIPCMD_POLLENTRY 6 +#endif + +/* + * Map BSD names to SunOS names. + */ +#if BSD >= 199006 +#define RFS_NULL NFSPROC_NULL +#define RFS_GETATTR NFSPROC_GETATTR +#define RFS_SETATTR NFSPROC_SETATTR +#define RFS_ROOT NFSPROC_ROOT +#define RFS_LOOKUP NFSPROC_LOOKUP +#define RFS_READLINK NFSPROC_READLINK +#define RFS_READ NFSPROC_READ +#define RFS_WRITECACHE NFSPROC_WRITECACHE +#define RFS_WRITE NFSPROC_WRITE +#define RFS_CREATE NFSPROC_CREATE +#define RFS_REMOVE NFSPROC_REMOVE +#define RFS_RENAME NFSPROC_RENAME +#define RFS_LINK NFSPROC_LINK +#define RFS_SYMLINK NFSPROC_SYMLINK +#define RFS_MKDIR NFSPROC_MKDIR +#define RFS_RMDIR NFSPROC_RMDIR +#define RFS_READDIR NFSPROC_READDIR +#define RFS_STATFS NFSPROC_STATFS +#define RFS_NPROC NFSPROC_NPROC +#endif diff --git a/usr.sbin/tcpdump/tcpdump/ospf.h b/usr.sbin/tcpdump/tcpdump/ospf.h new file mode 100644 index 000000000000..e3a3a6d65d3e --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/ospf.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) + */ +#define OSPF_TYPE_UMD 0 /* UMd's special monitoring packets */ +#define OSPF_TYPE_HELLO 1 /* Hello */ +#define OSPF_TYPE_DB 2 /* Database Description */ +#define OSPF_TYPE_LSR 3 /* Link State Request */ +#define OSPF_TYPE_LSU 4 /* Link State Update */ +#define OSPF_TYPE_LSA 5 /* Link State Ack */ +#define OSPF_TYPE_MAX 6 + +/* Options *_options */ +#define OSPF_OPTION_T 0x01 /* T bit: TOS support */ +#define OSPF_OPTION_E 0x02 /* E bit: External routes advertised */ +#define OSPF_OPTION_MC 0x04 /* MC bit: Multicast capable */ + +/* ospf_authtype */ +#define OSPF_AUTH_NONE 0 /* No auth-data */ +#define OSPF_AUTH_SIMPLE 1 /* Simple password */ + +/* db_flags */ +#define OSPF_DB_INIT 0x04 /* */ +#define OSPF_DB_MORE 0x02 +#define OSPF_DB_MASTER 0x01 + +/* ls_type */ +#define LS_TYPE_ROUTER 1 /* router link */ +#define LS_TYPE_NETWORK 2 /* network link */ +#define LS_TYPE_SUM_IP 3 /* summary link */ +#define LS_TYPE_SUM_ABR 4 /* summary area link */ +#define LS_TYPE_ASE 5 /* ASE */ +#define LS_TYPE_GROUP 6 /* Group membership (multicast */ + /* extensions 23 July 1991) */ +#define LS_TYPE_MAX 7 + +/************************************************* + * + * is the above a bug in the documentation? + * + *************************************************/ + + +/* rla_link.link_type */ +#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ +#define RLA_TYPE_TRANSIT 2 /* connection to transit network */ +#define RLA_TYPE_STUB 3 /* connection to stub network */ +#define RLA_TYPE_VIRTUAL 4 /* virtual link */ + +/* rla_flags */ +#define RLA_FLAG_B 0x01 +#define RLA_FLAG_E 0x02 +#define RLA_FLAG_W1 0x04 +#define RLA_FLAG_W2 0x08 + +/* sla_tosmetric breakdown */ +#define SLA_MASK_TOS 0x7f000000 +#define SLA_MASK_METRIC 0x00ffffff +#define SLA_SHIFT_TOS 24 + +/* asla_tosmetric breakdown */ +#define ASLA_FLAG_EXTERNAL 0x80000000 +#define ASLA_MASK_TOS 0x7f000000 +#define ASLA_SHIFT_TOS 24 +#define ASLA_MASK_METRIC 0x00ffffff + +/* multicast vertex type */ +#define MCLA_VERTEX_ROUTER 1 +#define MCLA_VERTEX_NETWORK 2 + +/* link state advertisement header */ +struct lsa_hdr { + u_short ls_age; + u_char ls_options; + u_char ls_type; + struct in_addr ls_stateid; + struct in_addr ls_router; + u_long ls_seq; + u_short ls_chksum; + u_short ls_length; +} ; + +/* link state advertisement */ +struct lsa { + struct lsa_hdr ls_hdr; + + /* Link state types */ + union { + /* Router links advertisements */ + struct { + u_char rla_flags; + u_char rla_zero[1]; + u_short rla_count; + struct rlalink { + struct in_addr link_id; + struct in_addr link_data; + u_char link_type; + u_char link_toscount; + u_short link_tos0metric; + } rla_link[1]; /* may repeat */ + } un_rla; + + /* Network links advertisements */ + struct { + struct in_addr nla_mask; + struct in_addr nla_router[1]; /* may repeat */ + } un_nla; + + /* Summary links advertisements */ + struct { + struct in_addr sla_mask; + u_long sla_tosmetric[1]; /* may repeat */ + } un_sla; + + /* AS external links advertisements */ + struct { + struct in_addr asla_mask; + struct aslametric { + u_long asla_tosmetric; + struct in_addr asla_forward; + struct in_addr asla_tag; + } asla_metric[1]; /* may repeat */ + } un_asla; + + /* Multicast group membership */ + struct mcla { + u_long mcla_vtype; + struct in_addr mcla_vid; + } un_mcla[1]; + } lsa_un; +} ; + + +/* + * TOS metric struct (will be 0 or more in router links update) + */ +struct tos_metric { + u_char tos_type; + u_char tos_zero; + u_short tos_metric; +} ; + +#define OSPF_AUTH_SIZE 8 + +/* + * the main header + */ +struct ospfhdr { + u_char ospf_version; + u_char ospf_type; + u_short ospf_len; + struct in_addr ospf_routerid; + struct in_addr ospf_areaid; + u_short ospf_chksum; + u_short ospf_authtype; + u_char ospf_authdata[OSPF_AUTH_SIZE]; + union { + + /* Hello packet */ + struct { + struct in_addr hello_mask; + u_short hello_helloint; + u_char hello_options; + u_char hello_priority; + u_long hello_deadint; + struct in_addr hello_dr; + struct in_addr hello_bdr; + struct in_addr hello_neighbor[1]; /* may repeat */ + } un_hello; + + /* Database Description packet */ + struct { + u_char db_zero[2]; + u_char db_options; + u_char db_flags; + u_long db_seq; + struct lsa_hdr db_lshdr[1]; /* may repeat */ + } un_db; + + /* Link State Request */ + struct lsr { + u_long ls_type; + struct in_addr ls_stateid; + struct in_addr ls_router; + } un_lsr[1]; /* may repeat */ + + /* Link State Update */ + struct { + u_long lsu_count; + struct lsa lsu_lsa[1]; /* may repeat */ + } un_lsu; + + /* Link State Acknowledment */ + struct { + struct lsa_hdr lsa_lshdr[1]; /* may repeat */ + } un_lsa ; + } ospf_un ; +} ; + +#define ospf_hello ospf_un.un_hello +#define ospf_db ospf_un.un_db +#define ospf_lsr ospf_un.un_lsr +#define ospf_lsu ospf_un.un_lsu +#define ospf_lsa ospf_un.un_lsa + diff --git a/usr.sbin/tcpdump/tcpdump/pcap.c b/usr.sbin/tcpdump/tcpdump/pcap.c new file mode 100644 index 000000000000..04c96953766b --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/pcap.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#)$Header: pcap-bpf.c,v 1.29 92/06/02 17:57:29 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include /* optionally get BSD define */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" + +extern int errno; + +static void +bpf_stats(fd) + int fd; +{ + struct bpf_stat s; + + if (ioctl(fd, BIOCGSTATS, &s) < 0) + return; + + (void)fflush(stdout); + (void)fprintf(stderr, "%d packets received by filter\n", s.bs_recv); + (void)fprintf(stderr, "%d packets dropped by kernel\n", s.bs_drop); +} + +void +readloop(cnt, if_fd, fp, printit) + int cnt; + int if_fd; + struct bpf_program *fp; + void (*printit)(); +{ + u_char *buf; + u_int bufsize; + int cc; + + if (ioctl(if_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) { + perror("tcpdump: BIOCGBLEN"); + exit(1); + } + buf = (u_char *)malloc(bufsize); + + if (ioctl(if_fd, BIOCSETF, (caddr_t)fp) < 0) { + perror("tcpdump: BIOCSETF"); + exit(1); + } + while (1) { + register u_char *bp, *ep; + + if ((cc = read(if_fd, (char *)buf, (int)bufsize)) < 0) { + /* Don't choke when we get ptraced */ + if (errno == EINTR) + continue; +#if defined(sun) && !defined(BSD) + /* + * Due to a SunOS bug, after 2^31 bytes, the kernel + * file offset overflows and read fails with EINVAL. + * The lseek() to 0 will fix things. + */ + if (errno == EINVAL && + (long)(tell(if_fd) + bufsize) < 0) { + (void)lseek(if_fd, 0, 0); + continue; + } +#endif + perror("tcpdump: read"); + exit(1); + } + /* + * Loop through each packet. + */ +#define bhp ((struct bpf_hdr *)bp) + bp = buf; + ep = bp + cc; + while (bp < ep) { + register int caplen, hdrlen; + if (cnt >= 0 && --cnt < 0) + goto out; + (*printit)(bp + (hdrlen = bhp->bh_hdrlen), + &bhp->bh_tstamp, bhp->bh_datalen, + caplen = bhp->bh_caplen); + bp += BPF_WORDALIGN(caplen + hdrlen); + } +#undef bhp + } + out: + wrapup(if_fd); +} + +wrapup(fd) + int fd; +{ + bpf_stats(fd); + close(fd); +} + +static inline int +bpf_open() +{ + int fd; + int n = 0; + char device[sizeof "/dev/bpf000"]; + + /* + * Go through all the minors and find one that isn't in use. + */ + do { + (void)sprintf(device, "/dev/bpf%d", n++); + fd = open(device, O_RDONLY); + } while (fd < 0 && errno == EBUSY); + + if (fd < 0) { + (void) fprintf(stderr, "tcpdump: "); + perror(device); + exit(-1); + } + return fd; +} + +int +initdevice(device, pflag, linktype) + char *device; + int pflag; + int *linktype; +{ + struct timeval timeout; + int if_fd; + struct ifreq ifr; + struct bpf_version bv; + + if_fd = bpf_open(); + + if (ioctl(if_fd, BIOCVERSION, (caddr_t)&bv) < 0) + warning("kernel bpf interpreter may be out of date"); + else if (bv.bv_major != BPF_MAJOR_VERSION || + bv.bv_minor < BPF_MINOR_VERSION) + error("requires bpf language %d.%d or higher; kernel is %d.%d", + BPF_MAJOR_VERSION, BPF_MINOR_VERSION, + bv.bv_major, bv.bv_minor); + + (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + if (ioctl(if_fd, BIOCSETIF, (caddr_t)&ifr) < 0) { + (void) fprintf(stderr, "tcpdump: BIOCSETIF: "); + perror(device); + exit(-1); + } + /* Get the data link layer type. */ + if (ioctl(if_fd, BIOCGDLT, (caddr_t)linktype) < 0) { + perror("tcpdump: BIOCGDLT"); + exit(-1); + } + /* set timeout */ + timeout.tv_sec = 1; + timeout.tv_usec = 0; + if (ioctl(if_fd, BIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { + perror("tcpdump: BIOCSRTIMEOUT"); + exit(-1); + } + /* set promiscuous mode if requested, but only for broadcast nets */ + if (pflag == 0) { + switch (*linktype) { + + case DLT_SLIP: + case DLT_PPP: + case DLT_NULL: + break; + + default: + if (ioctl(if_fd, BIOCPROMISC, (void *)0) < 0) { + perror("tcpdump: BIOCPROMISC"); + exit(-1); + } + } + } + return(if_fd); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-arp.c b/usr.sbin/tcpdump/tcpdump/print-arp.c new file mode 100644 index 000000000000..3f0671a4ba58 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-arp.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-arp.c,v 1.16 91/04/19 10:45:56 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +void +arp_print(ap, length, caplen) + register struct ether_arp *ap; + int length; + int caplen; +{ + if ((u_char *)(ap + 1) > snapend) { + printf("[|arp]"); + return; + } + if (length < sizeof(struct ether_arp)) { + (void)printf("truncated-arp"); + default_print((u_short *)ap, length); + return; + } + + NTOHS(ap->arp_hrd); + NTOHS(ap->arp_pro); + NTOHS(ap->arp_op); + + if (ap->arp_hrd != ARPHRD_ETHER + || (ap->arp_pro != ETHERTYPE_IP + && ap->arp_pro != ETHERTYPE_TRAIL) + || ap->arp_hln != sizeof(SHA(ap)) + || ap->arp_pln != sizeof(SPA(ap))) { + (void)printf("arp-req #%d for proto #%d (%d) hardware %d (%d)", + ap->arp_op, ap->arp_pro, ap->arp_pln, + ap->arp_hrd, ap->arp_hln); + return; + } + if (ap->arp_pro == ETHERTYPE_TRAIL) + (void)printf("trailer"); + switch (ap->arp_op) { + + case ARPOP_REQUEST: + (void)printf("arp who-has %s tell %s", + ipaddr_string(TPA(ap)), + ipaddr_string(SPA(ap))); + break; + + case ARPOP_REPLY: + (void)printf("arp reply %s is-at %s", + ipaddr_string(SPA(ap)), + etheraddr_string(SHA(ap))); + break; + + case REVARP_REQUEST: + (void)printf("rarp who-is %s tell %s", + etheraddr_string(THA(ap)), + etheraddr_string(SHA(ap))); + break; + + case REVARP_REPLY: + (void)printf("rarp reply %s at %s", + etheraddr_string(THA(ap)), + ipaddr_string(TPA(ap))); + break; + + default: + (void)printf("arp-%d", ap->arp_op); + default_print((u_short *)ap, caplen); + break; + } +} diff --git a/usr.sbin/tcpdump/tcpdump/print-atalk.c b/usr.sbin/tcpdump/tcpdump/print-atalk.c new file mode 100644 index 000000000000..203585ef5a8b --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-atalk.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print AppleTalk packets. + */ +#ifndef lint +static char rcsid[] = + "@(#)$Header: print-atalk.c,v 1.22 92/03/26 14:15:34 mccanne Exp $ (LBL)"; +#endif + +#ifdef __STDC__ +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "appletalk.h" +#include +#include "extract.h" + +static char *ataddr_string(); +static struct atNBPtuple *nbp_tuple_print(); +static struct atNBPtuple *nbp_name_print(); +static void atp_print(); +static void nbp_print(); +static void atp_bitmap_print(); + +/* + * Print AppleTalk Datagram Delivery Protocol packets. + */ +void +ddp_print(dp, length) + register struct atDDP *dp; + int length; +{ + if (length < ddpSize) { + (void)printf(" truncated-ddp %d", length); + return; + } + (void)printf("%s.%d > %s.%d:", + ataddr_string(EXTRACT_SHORT(&dp->srcNet), dp->srcNode), + dp->srcSkt, + ataddr_string(EXTRACT_SHORT(&dp->dstNet), dp->dstNode), + dp->dstSkt); + + /* 'type' is the last field of 'dp' so we need the whole thing. + If we cannot determine the type, bail out. (This last byte + happens to be *one* byte past the end of tcpdump's minimum + snapshot length.) */ + if ((u_char *)(dp + 1) > snapend) { + printf(" [|atalk]"); + return; + } + + length -= ddpSize; + switch (dp->type) { + + case ddpRTMP: + (void)printf(" at-rtmp %d", length); + break; + case ddpRTMPrequest: + (void)printf(" at-rtmpReq %d", length); + break; + case ddpNBP: + nbp_print((struct atNBP *)((u_char *)dp + ddpSize), + length, dp); + break; + case ddpATP: + atp_print((struct atATP *)((u_char *)dp + ddpSize), length); + break; + case ddpECHO: + (void)printf(" at-echo %d", length); + break; + case ddpIP: + (void)printf(" at-IP %d", length); + break; + case ddpARP: + (void)printf(" at-ARP %d", length); + break; + case ddpKLAP: + (void)printf(" at-KLAP %d", length); + break; + default: + (void)printf(" at-#%d %d", length); + break; + } +} + +static void +atp_print(ap, length) + register struct atATP *ap; + int length; +{ + char c; + long data; + + if ((u_char *)(ap + 1) > snapend) { + /* Just bail if we don't have the whole chunk. */ + printf(" [|atalk]"); + return; + } + length -= sizeof(*ap); + switch (ap->control & 0xc0) { + + case atpReqCode: + (void)printf(" atp-req%s %d", + ap->control & atpXO? " " : "*", + EXTRACT_SHORT(&ap->transID)); + + atp_bitmap_print(ap->bitmap); + + if (length != 0) + (void)printf(" [len=%d]", length); + + switch (ap->control & (atpEOM|atpSTS)) { + case atpEOM: + (void)printf(" [EOM]"); + break; + case atpSTS: + (void)printf(" [STS]"); + break; + case atpEOM|atpSTS: + (void)printf(" [EOM,STS]"); + break; + } + break; + + case atpRspCode: + (void)printf(" atp-resp%s%d:%d (%d)", + ap->control & atpEOM? "*" : " ", + EXTRACT_SHORT(&ap->transID), ap->bitmap, length); + switch (ap->control & (atpXO|atpSTS)) { + case atpXO: + (void)printf(" [XO]"); + break; + case atpSTS: + (void)printf(" [STS]"); + break; + case atpXO|atpSTS: + (void)printf(" [XO,STS]"); + break; + } + break; + + case atpRelCode: + (void)printf(" atp-rel %d", EXTRACT_SHORT(&ap->transID)); + + atp_bitmap_print(ap->bitmap); + + /* length should be zero */ + if (length) + (void)printf(" [len=%d]", length); + + /* there shouldn't be any control flags */ + if (ap->control & (atpXO|atpEOM|atpSTS)) { + c = '['; + if (ap->control & atpXO) { + (void)printf("%cXO", c); + c = ','; + } + if (ap->control & atpEOM) { + (void)printf("%cEOM", c); + c = ','; + } + if (ap->control & atpSTS) { + (void)printf("%cSTS", c); + c = ','; + } + (void)printf("]"); + } + break; + + default: + (void)printf(" atp-0x%x %d (%d)", ap->control, + EXTRACT_SHORT(&ap->transID), length); + break; + } + data = EXTRACT_LONG(&ap->userData); + if (data != 0) + (void)printf(" 0x%x", data); +} + +static void +atp_bitmap_print(bm) + register u_char bm; +{ + register char c; + register int i; + + /* + * The '& 0xff' below is needed for compilers that want to sign + * extend a u_char, which is the case with the Ultrix compiler. + * (gcc is smart enough to eliminate it, at least on the Sparc). + */ + if ((bm + 1) & (bm & 0xff)) { + c = '<'; + for (i = 0; bm; ++i) { + if (bm & 1) { + (void)printf("%c%d", c, i); + c = ','; + } + bm >>= 1; + } + (void)printf(">"); + } else { + for (i = 0; bm; ++i) + bm >>= 1; + if (i > 1) + (void)printf("<0-%d>", i - 1); + else + (void)printf("<0>"); + } +} + +static void +nbp_print(np, length, dp) + register struct atNBP *np; + int length; + register struct atDDP *dp; +{ + register struct atNBPtuple *tp = + (struct atNBPtuple *)((u_char *)np + nbpHeaderSize); + int i = length; + u_char *ep; + + length -= nbpHeaderSize; + if (length < 8) { + /* must be room for at least one tuple */ + (void)printf(" truncated-nbp %d", length + nbpHeaderSize); + return; + } + /* ep points to end of available data */ + ep = snapend; + if ((u_char *)tp > ep) { + printf(" [|atalk]"); + return; + } + switch (i = np->control & 0xf0) { + + case nbpBrRq: + case nbpLkUp: + (void)printf(i == nbpLkUp? " nbp-lkup %d:":" nbp-brRq %d:", + np->id); + if ((u_char *)(tp + 1) > ep) { + printf(" [|atalk]"); + return; + } + (void)nbp_name_print(tp, ep); + /* + * look for anomalies: the spec says there can only + * be one tuple, the address must match the source + * address and the enumerator should be zero. + */ + if ((np->control & 0xf) != 1) + (void)printf(" [ntup=%d]", np->control & 0xf); + if (tp->enumerator) + (void)printf(" [enum=%d]", tp->enumerator); + if (EXTRACT_SHORT(&tp->net) != EXTRACT_SHORT(&dp->srcNet) || + tp->node != dp->srcNode || tp->skt != dp->srcSkt) + (void)printf(" [addr=%s.%d]", + ataddr_string(EXTRACT_SHORT(&tp->net), + tp->node), + tp->skt); + break; + + case nbpLkUpReply: + (void)printf(" nbp-reply %d:", np->id); + + /* print each of the tuples in the reply */ + for (i = np->control & 0xf; --i >= 0 && tp; ) + tp = nbp_tuple_print(tp, ep, dp); + break; + + default: + (void)printf(" nbp-0x%x %d (%d)", np->control, np->id, + length); + break; + } +} + +/* print a counted string */ +static char * +print_cstring(cp, ep) + register char *cp; + register u_char *ep; +{ + register int length; + + if (cp >= (char *)ep) { + (void)printf("[|atalk]"); + return (0); + } + length = *cp++; + + /* Spec says string can be at most 32 bytes long */ + if (length < 0 || length > 32) { + (void)printf("[len=%d]", length); + return (0); + } + while (--length >= 0) { + if (cp >= (char *)ep) { + (void)printf("[|atalk]"); + return (0); + } + putchar(*cp++); + } + return (cp); +} + +static struct atNBPtuple * +nbp_tuple_print(tp, ep, dp) + register struct atNBPtuple *tp; + register u_char *ep; + register struct atDDP *dp; +{ + register struct atNBPtuple *tpn; + + if ((u_char *)(tp + 1) > ep) { + printf(" [|atalk]"); + return 0; + } + tpn = nbp_name_print(tp, ep); + + /* if the enumerator isn't 1, print it */ + if (tp->enumerator != 1) + (void)printf("(%d)", tp->enumerator); + + /* if the socket doesn't match the src socket, print it */ + if (tp->skt != dp->srcSkt) + (void)printf(" %d", tp->skt); + + /* if the address doesn't match the src address, it's an anomaly */ + if (EXTRACT_SHORT(&tp->net) != EXTRACT_SHORT(&dp->srcNet) || + tp->node != dp->srcNode) + (void)printf(" [addr=%s]", + ataddr_string(EXTRACT_SHORT(&tp->net), tp->node)); + + return (tpn); +} + +static struct atNBPtuple * +nbp_name_print(tp, ep) + struct atNBPtuple *tp; + register u_char *ep; +{ + register char *cp = (char *)tp + nbpTupleSize; + + putchar(' '); + + /* Object */ + putchar('"'); + if (cp = print_cstring(cp, ep)) { + /* Type */ + putchar(':'); + if (cp = print_cstring(cp, ep)) { + /* Zone */ + putchar('@'); + if (cp = print_cstring(cp, ep)) + putchar('"'); + } + } + return ((struct atNBPtuple *)cp); +} + + +#define HASHNAMESIZE 4096 + +struct hnamemem { + int addr; + char *name; + struct hnamemem *nxt; +}; + +static struct hnamemem hnametable[HASHNAMESIZE]; + +static char * +ataddr_string(atnet, athost) + u_short atnet; + u_char athost; +{ + register struct hnamemem *tp, *tp2; + register int i = (atnet << 8) | athost; + char nambuf[256]; + static int first = 1; + FILE *fp; + + /* + * if this is the first call, see if there's an AppleTalk + * number to name map file. + */ + if (first && (first = 0, !nflag) + && (fp = fopen("/etc/atalk.names", "r"))) { + char line[256]; + int i1, i2, i3; + + while (fgets(line, sizeof(line), fp)) { + if (line[0] == '\n' || line[0] == 0 || line[0] == '#') + continue; + if (sscanf(line, "%d.%d.%d %s", &i1, &i2, &i3, + nambuf) == 4) + /* got a hostname. */ + i3 |= ((i1 << 8) | i2) << 8; + else if (sscanf(line, "%d.%d %s", &i1, &i2, + nambuf) == 3) + /* got a net name */ + i3 = (((i1 << 8) | i2) << 8) | 255; + else + continue; + + for (tp = &hnametable[i3 & (HASHNAMESIZE-1)]; + tp->nxt; tp = tp->nxt) + ; + tp->addr = i3; + tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); + i3 = strlen(nambuf) + 1; + tp->name = strcpy(malloc((unsigned) i3), nambuf); + } + fclose(fp); + } + + for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + /* didn't have the node name -- see if we've got the net name */ + i |= 255; + for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt) + if (tp2->addr == i) { + tp->addr = (atnet << 8) | athost; + tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); + (void)sprintf(nambuf, "%s.%d", tp2->name, athost); + i = strlen(nambuf) + 1; + tp->name = strcpy(malloc((unsigned) i), nambuf); + return (tp->name); + } + + tp->addr = (atnet << 8) | athost; + tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); + if (athost != 255) + (void)sprintf(nambuf, "%d.%d.%d", + atnet >> 8, atnet & 0xff, athost); + else + (void)sprintf(nambuf, "%d.%d", atnet >> 8, atnet & 0xff); + i = strlen(nambuf) + 1; + tp->name = strcpy(malloc((unsigned) i), nambuf); + + return (tp->name); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-bootp.c b/usr.sbin/tcpdump/tcpdump/print-bootp.c new file mode 100644 index 000000000000..0641d825ff4f --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-bootp.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print bootp packets. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-bootp.c,v 1.17 91/11/14 22:21:34 leres Exp $ (LBL)"; +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "bootp.h" + +void rfc1048_print(); +void cmu_print(); + +/* + * Print bootp requests + */ +void +bootp_print(bp, length, sport, dport) + register struct bootp *bp; + int length; + u_short sport, dport; +{ + static char tstr[] = " [|bootp]"; + static unsigned char vm_cmu[4] = VM_CMU; + static unsigned char vm_rfc1048[4] = VM_RFC1048; + u_char *ep; + +#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc + + /* Note funny sized packets */ + if (length != sizeof(struct bootp)) + (void)printf(" [len=%d]", length); + + /* 'ep' points to the end of avaible data. */ + ep = (u_char *)snapend; + + switch (bp->bp_op) { + + case BOOTREQUEST: + /* Usually, a request goes from a client to a server */ + if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS) + printf(" (request)"); + break; + + case BOOTREPLY: + /* Usually, a reply goes from a server to a client */ + if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC) + printf(" (reply)"); + break; + + default: + printf(" bootp-#%d", bp->bp_op); + } + + NTOHL(bp->bp_xid); + NTOHS(bp->bp_secs); + + /* The usual hardware address type is 1 (10Mb Ethernet) */ + if (bp->bp_htype != 1) + printf(" htype-#%d", bp->bp_htype); + + /* The usual length for 10Mb Ethernet address is 6 bytes */ + if (bp->bp_htype != 1 || bp->bp_hlen != 6) + printf(" hlen:%d", bp->bp_hlen); + + /* Only print interesting fields */ + if (bp->bp_hops) + printf(" hops:%d", bp->bp_hops); + if (bp->bp_xid) + printf(" xid:0x%x", bp->bp_xid); + if (bp->bp_secs) + printf(" secs:%d", bp->bp_secs); + + /* Client's ip address */ + TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr)); + if (bp->bp_ciaddr.s_addr) + printf(" C:%s", ipaddr_string(&bp->bp_ciaddr)); + + /* 'your' ip address (bootp client) */ + TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr)); + if (bp->bp_yiaddr.s_addr) + printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr)); + + /* Server's ip address */ + TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr)); + if (bp->bp_siaddr.s_addr) + printf(" S:%s", ipaddr_string(&bp->bp_siaddr)); + + /* Gateway's ip address */ + TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr)); + if (bp->bp_giaddr.s_addr) + printf(" G:%s", ipaddr_string(&bp->bp_giaddr)); + + /* Client's Ethernet address */ + if (bp->bp_htype == 1 && bp->bp_hlen == 6) { + register struct ether_header *eh; + register char *e; + + TCHECK(bp->bp_chaddr[0], 6); + eh = (struct ether_header *)packetp; + if (bp->bp_op == BOOTREQUEST) + e = (char *)ESRC(eh); + else if (bp->bp_op == BOOTREPLY) + e = (char *)EDST(eh); + else + e = 0; + if (e == 0 || bcmp((char *)bp->bp_chaddr, e, 6) != 0) + printf(" ether %s", etheraddr_string(bp->bp_chaddr)); + } + + TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname)); + if (*bp->bp_sname) { + printf(" sname "); + if (printfn(bp->bp_sname, ep)) { + fputs(tstr + 1, stdout); + return; + } + } + TCHECK(bp->bp_file[0], sizeof(bp->bp_file)); + if (*bp->bp_file) { + printf(" file "); + if (printfn(bp->bp_file, ep)) { + fputs(tstr + 1, stdout); + return; + } + } + + /* Don't try to decode the vendor buffer unless we're verbose */ + if (vflag <= 0) + return; + + TCHECK(bp->bp_vend[0], sizeof(bp->bp_vend)); + printf(" vend"); + if (bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_long)) == 0) + rfc1048_print(bp->bp_vend, sizeof(bp->bp_vend)); + else if (bcmp(bp->bp_vend, vm_cmu, sizeof(u_long)) == 0) + cmu_print(bp->bp_vend, sizeof(bp->bp_vend)); + else { + u_long ul; + + bcopy((char *)bp->bp_vend, (char *)&ul, sizeof(ul)); + printf("-#0x%x", ul); + } + + return; +trunc: + fputs(tstr, stdout); +#undef TCHECK +} + +void +rfc1048_print(bp, length) + register u_char *bp; + int length; +{ + u_char tag; + u_char *ep; + register int i; + u_long ul; + + printf("-rfc1048"); + + /* Step over magic cookie */ + bp += sizeof(long); + + /* Setup end pointer */ + ep = bp + length; + + while (bp < ep) { + tag = *bp++; + i = *bp++; + switch (tag) { + + case TAG_PAD: + /* no-op */ + break; + + case TAG_SUBNET_MASK: + ul = 0; + bcopy((char *)bp, (char *)&ul, i); + printf(" SM:%s", ipaddr_string(&ul)); + break; + + case TAG_TIME_SERVER: + ul = 0; + bcopy((char *)bp, (char *)&ul, i); + printf(" TS:%s", ipaddr_string(&ul)); + break; + + case TAG_GATEWAY: + ul = 0; + bcopy((char *)bp, (char *)&ul, i); + printf(" G:%s", ipaddr_string(&ul)); + break; + + case TAG_TIME_OFFSET: + case TAG_NAME_SERVER: + case TAG_DOMAIN_SERVER: + case TAG_LOG_SERVER: + case TAG_COOKIE_SERVER: + case TAG_LPR_SERVER: + case TAG_IMPRESS_SERVER: + case TAG_RLP_SERVER: + case TAG_HOSTNAME: + case TAG_BOOTSIZE: + printf(" tag-#%d", tag); + if (i == sizeof(long)) { + bcopy((char *)bp, (char *)&ul, sizeof(long)); + printf(":0x%x", ul); + } else + printf(":?"); + break; + + case TAG_END: + return; + + default: + printf("[tag-#%d]", tag); + return; + } + } +} + +void +cmu_print(bp, length) + register u_char *bp; + int length; +{ + /* XXX not really implemented */ + printf("-cmu [...]"); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-domain.c b/usr.sbin/tcpdump/tcpdump/print-domain.c new file mode 100644 index 000000000000..04cf5aa47ea6 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-domain.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-domain.c,v 1.16 92/05/25 14:28:59 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +static char *ns_ops[] = { + "", " inv_q", " stat", " op3", " op4", " op5", " op6", " op7", + " op8", " updataA", " updateD", " updateDA", + " updateM", " updateMA", " zoneInit", " zoneRef", +}; + +static char *ns_resp[] = { + "", " FormErr", " ServFail", " NXDomain", + " NotImp", " Refused", " Resp6", " Resp7", + " Resp8", " Resp9", " Resp10", " Resp11", + " Resp12", " Resp13", " Resp14", " NoChange", +}; + + +/* skip over a domain name */ +static u_char * +ns_nskip(cp) + register u_char *cp; +{ + register u_char i; + + if (((i = *cp++) & 0xc0) == 0xc0) + return (cp + 1); + while (i) { + cp += i; + i = *cp++; + } + return (cp); +} + +/* print a domain name */ +static void +ns_nprint(cp, bp, ep) + register u_char *cp; + register u_char *bp; + register u_char *ep; +{ + register u_int i; + + putchar(' '); + if (i = *cp++) + while (i && cp < ep) { + if ((i & 0xc0) == 0xc0) { + cp = bp + (((i << 8) | *cp) & 0x3fff); + i = *cp++; + continue; + } + do { + putchar(*cp++); + } while (--i); + putchar('.'); + i = *cp++; + } + else + putchar('.'); +} + + +/* print a query */ +static void +ns_qprint(cp, bp, ep) + register u_char *cp; + register u_char *bp; + register u_char *ep; +{ + u_char *np = cp; + register u_int i; + + cp = ns_nskip(cp); + + if (cp + 4 > ep) + return; + + /* print the qtype and qclass (if it's not IN) */ + i = *cp++ << 8; + switch (i |= *cp++) { + case T_A: printf(" A"); break; + case T_NS: printf(" NS"); break; + case T_MD: printf(" MD"); break; + case T_MF: printf(" MF"); break; + case T_CNAME: printf(" CNAME"); break; + case T_SOA: printf(" SOA"); break; + case T_MB: printf(" MB"); break; + case T_MG: printf(" MG"); break; + case T_MR: printf(" MR"); break; + case T_NULL: printf(" NULL"); break; + case T_WKS: printf(" WKS"); break; + case T_PTR: printf(" PTR"); break; + case T_HINFO: printf(" HINFO"); break; + case T_MINFO: printf(" MINFO"); break; + case T_MX: printf(" MX"); break; + case T_UINFO: printf(" UINFO"); break; + case T_UID: printf(" UID"); break; + case T_GID: printf(" GID"); break; +#ifdef T_UNSPEC + case T_UNSPEC: printf(" UNSPEC"); break; +#endif + case T_AXFR: printf(" AXFR"); break; + case T_MAILB: printf(" MAILB"); break; + case T_MAILA: printf(" MAILA"); break; + case T_ANY: printf(" ANY"); break; + default: printf(" Type%d", i); break; + } + i = *cp++ << 8; + if ((i |= *cp++) != C_IN) + if (i == C_ANY) + printf("(c_any)"); + else + printf("(Class %d)", i); + + putchar('?'); + ns_nprint(np, bp, ep); +} + + +/* print a reply */ +static void +ns_rprint(cp, bp, ep) + register u_char *cp; + register u_char *bp; + register u_char *ep; +{ + register u_int i; + u_short typ; + + cp = ns_nskip(cp); + + if (cp + 10 > ep) + return; + + /* print the type/qtype and class (if it's not IN) */ + typ = *cp++ << 8; + typ |= *cp++; + i = *cp++ << 8; + if ((i |= *cp++) != C_IN) + if (i == C_ANY) + printf("(c_any)"); + else + printf("(Class %d)", i); + + /* ignore ttl & len */ + cp += 6; + switch (typ) { + case T_A: printf(" A %s", ipaddr_string(cp)); break; + case T_NS: printf(" NS"); ns_nprint(cp, bp, ep); break; + case T_MD: printf(" MD"); break; + case T_MF: printf(" MF"); break; + case T_CNAME: printf(" CNAME"); ns_nprint(cp, bp, ep); break; + case T_SOA: printf(" SOA"); break; + case T_MB: printf(" MB"); break; + case T_MG: printf(" MG"); break; + case T_MR: printf(" MR"); break; + case T_NULL: printf(" NULL"); break; + case T_WKS: printf(" WKS"); break; + case T_PTR: printf(" PTR"); ns_nprint(cp, bp, ep); break; + case T_HINFO: printf(" HINFO"); break; + case T_MINFO: printf(" MINFO"); break; + case T_MX: printf(" MX"); ns_nprint(cp+2, bp, ep); +#ifndef TCPDUMP_ALIGN + printf(" %d", *(short *)cp); +#else + { + u_short x = *cp | cp[1] << 8; + printf(" %d", ntohs(x)); + } +#endif + break; + case T_UINFO: printf(" UINFO"); break; + case T_UID: printf(" UID"); break; + case T_GID: printf(" GID"); break; +#ifdef T_UNSPEC + case T_UNSPEC: printf(" UNSPEC"); break; +#endif + case T_AXFR: printf(" AXFR"); break; + case T_MAILB: printf(" MAILB"); break; + case T_MAILA: printf(" MAILA"); break; + case T_ANY: printf(" ANY"); break; + default: printf(" Type%d", typ); break; + } +} + +void +ns_print(np, length) + register HEADER *np; + int length; +{ + u_char *ep = (u_char *)snapend; + + /* get the byte-order right */ + NTOHS(np->id); + NTOHS(np->qdcount); + NTOHS(np->ancount); + NTOHS(np->nscount); + NTOHS(np->arcount); + + if (np->qr) { + /* this is a response */ + printf(" %d%s%s%s%s%s", + np->id, + ns_ops[np->opcode], + ns_resp[np->rcode], + np->aa? "*" : "", + np->ra? "" : "-", + np->tc? "|" : ""); + if (np->qdcount != 1) + printf(" [%dq]", np->qdcount); + printf(" %d/%d/%d", np->ancount, np->nscount, np->arcount); + if (np->ancount) + ns_rprint(ns_nskip((u_char *)(np + 1)) + 4, + (u_char *)np, ep); + } + else { + /* this is a request */ + printf(" %d%s%s", + np->id, + ns_ops[np->opcode], + np->rd? "+" : ""); + + /* any weirdness? */ + if (*(((u_short *)np)+1) & htons(0x6ff)) + printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1))); + + if (np->opcode == IQUERY) { + if (np->qdcount) + printf(" [%dq]", np->qdcount); + if (np->ancount != 1) + printf(" [%da]", np->ancount); + } + else { + if (np->ancount) + printf(" [%da]", np->ancount); + if (np->qdcount != 1) + printf(" [%dq]", np->qdcount); + } + if (np->nscount) + printf(" [%dn]", np->nscount); + if (np->arcount) + printf(" [%dau]", np->arcount); + + ns_qprint((u_char *)(np + 1), (u_char *)np, ep); + } + printf(" (%d)", length); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-egp.c b/usr.sbin/tcpdump/tcpdump/print-egp.c new file mode 100644 index 000000000000..a88a68364525 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-egp.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 1991 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Lawrence Berkeley Laboratory, + * Berkeley, CA. The name of the University may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU). + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +struct egp_packet { + u_char egp_version; +#define EGP_VERSION 2 + u_char egp_type; +#define EGPT_ACQUIRE 3 +#define EGPT_REACH 5 +#define EGPT_POLL 2 +#define EGPT_UPDATE 1 +#define EGPT_ERROR 8 + u_char egp_code; +#define EGPC_REQUEST 0 +#define EGPC_CONFIRM 1 +#define EGPC_REFUSE 2 +#define EGPC_CEASE 3 +#define EGPC_CEASEACK 4 +#define EGPC_HELLO 0 +#define EGPC_HEARDU 1 + u_char egp_status; +#define EGPS_UNSPEC 0 +#define EGPS_ACTIVE 1 +#define EGPS_PASSIVE 2 +#define EGPS_NORES 3 +#define EGPS_ADMIN 4 +#define EGPS_GODOWN 5 +#define EGPS_PARAM 6 +#define EGPS_PROTO 7 +#define EGPS_INDET 0 +#define EGPS_UP 1 +#define EGPS_DOWN 2 +#define EGPS_UNSOL 0x80 + u_short egp_checksum; + u_short egp_as; + u_short egp_sequence; + union { + u_short egpu_hello; + u_char egpu_gws[2]; + u_short egpu_reason; +#define EGPR_UNSPEC 0 +#define EGPR_BADHEAD 1 +#define EGPR_BADDATA 2 +#define EGPR_NOREACH 3 +#define EGPR_XSPOLL 4 +#define EGPR_NORESP 5 +#define EGPR_UVERSION 6 + } egp_handg; +#define egp_hello egp_handg.egpu_hello +#define egp_intgw egp_handg.egpu_gws[0] +#define egp_extgw egp_handg.egpu_gws[1] +#define egp_reason egp_handg.egpu_reason + union { + u_short egpu_poll; + u_long egpu_sourcenet; + } egp_pands; +#define egp_poll egp_pands.egpu_poll +#define egp_sourcenet egp_pands.egpu_sourcenet +}; + +char *egp_acquire_codes[] = { + "request", + "confirm", + "refuse", + "cease", + "cease_ack" +}; + +char *egp_acquire_status[] = { + "unspecified", + "active_mode", + "passive_mode", + "insufficient_resources", + "administratively_prohibited", + "going_down", + "parameter_violation", + "protocol_violation" +}; + +char *egp_reach_codes[] = { + "hello", + "i-h-u" +}; + +char *egp_status_updown[] = { + "indeterminate", + "up", + "down" +}; + +char *egp_reasons[] = { + "unspecified", + "bad_EGP_header_format", + "bad_EGP_data_field_format", + "reachability_info_unavailable", + "excessive_polling_rate", + "no_response", + "unsupported_version" +}; + +static void +egpnrprint(egp, length) + register struct egp_packet *egp; + register int length; +{ + register u_char *cp, *ep; +#define TCHECK(n) if (cp > ep - n) goto trunc + register u_long addr; + register u_long net; + register int netlen; + int gateways, distances, networks; + int t_gateways; + char *comma; + + addr = egp->egp_sourcenet; + if (IN_CLASSA(addr)) { + net = addr & IN_CLASSA_NET; + netlen = 1; + } else if (IN_CLASSB(addr)) { + net = addr & IN_CLASSB_NET; + netlen = 2; + } else if (IN_CLASSC(addr)) { + net = addr & IN_CLASSC_NET; + netlen = 3; + } else { + net = 0; + netlen = 0; + } + cp = (u_char *)(egp + 1); + ep = snapend; + + t_gateways = egp->egp_intgw + egp->egp_extgw; + for (gateways = 0; gateways < t_gateways; ++gateways) { + /* Pickup host part of gateway address */ + addr = 0; + TCHECK(4 - netlen); + switch (netlen) { + + case 1: + addr = *cp++; + /* fall through */ + case 2: + addr = (addr << 8) | *cp++; + /* fall through */ + case 3: + addr = (addr << 8) | *cp++; + } + addr |= net; + TCHECK(1); + distances = *cp++; + printf(" %s %s ", + gateways < egp->egp_intgw ? "int" : "ext", + intoa(addr)); + + comma = ""; + putchar('('); + while (--distances >= 0) { + TCHECK(2); + printf("%sd%d:", comma, (int)*cp++); + comma = ", "; + networks = *cp++; + while (--networks >= 0) { + /* Pickup network number */ + TCHECK(1); + addr = (u_long)*cp++ << 24; + if (IN_CLASSB(addr)) { + TCHECK(1); + addr |= (u_long)*cp++ << 16; + } else if (!IN_CLASSA(addr)) { + TCHECK(2); + addr |= (u_long)*cp++ << 16; + addr |= (u_long)*cp++ << 8; + } + printf(" %s", intoa(addr)); + } + } + putchar(')'); + } + return; +trunc: + fputs("[|]", stdout); +} + +void +egp_print(egp, length, ip) + register struct egp_packet *egp; + register int length; + register struct ip *ip; +{ + register int status; + register int code; + register int type; + + (void)printf("%s > %s: egp: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + if (egp->egp_version != EGP_VERSION) { + printf("[version %d]", egp->egp_version); + return; + } + printf("as:%d seq:%d", ntohs(egp->egp_as), ntohs(egp->egp_sequence)); + + type = egp->egp_type; + code = egp->egp_code; + status = egp->egp_status; + + switch (type) { + case EGPT_ACQUIRE: + printf(" acquire"); + switch (code) { + case EGPC_REQUEST: + case EGPC_CONFIRM: + printf(" %s", egp_acquire_codes[code]); + switch (status) { + case EGPS_UNSPEC: + case EGPS_ACTIVE: + case EGPS_PASSIVE: + printf(" %s", egp_acquire_status[status]); + break; + + default: + printf(" [status %d]", status); + break; + } + printf(" hello:%d poll:%d", + ntohs(egp->egp_hello), + ntohs(egp->egp_poll)); + break; + + case EGPC_REFUSE: + case EGPC_CEASE: + case EGPC_CEASEACK: + printf(" %s", egp_acquire_codes[code]); + switch (status ) { + case EGPS_UNSPEC: + case EGPS_NORES: + case EGPS_ADMIN: + case EGPS_GODOWN: + case EGPS_PARAM: + case EGPS_PROTO: + printf(" %s", egp_acquire_status[status]); + break; + + default: + printf("[status %d], status"); + break; + } + break; + + default: + printf("[code %d]", code); + break; + } + break; + + case EGPT_REACH: + switch (code) { + + case EGPC_HELLO: + case EGPC_HEARDU: + printf(" %s", egp_reach_codes[code]); + if (status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d], status"); + break; + + default: + printf("[reach code %d], code"); + break; + } + break; + + case EGPT_POLL: + printf(" poll"); + if (egp->egp_status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d]", status); + printf(" net:%s", intoa(egp->egp_sourcenet)); + break; + + case EGPT_UPDATE: + printf(" update"); + if (status & EGPS_UNSOL) { + status &= ~EGPS_UNSOL; + printf(" unsolicitied"); + } + if (status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d]", status); + printf(" %s int %d ext %d", + intoa(egp->egp_sourcenet), + egp->egp_intgw, + egp->egp_extgw); + if (vflag) + egpnrprint(egp, length); + break; + + case EGPT_ERROR: + printf(" error"); + if (status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status]", status); + + if (ntohs(egp->egp_reason) <= EGPR_UVERSION) + printf(" %s", egp_reasons[ntohs(egp->egp_reason)]); + else + printf(" [reason]", ntohs(egp->egp_reason)); + break; + + default: + printf("[type %d]", type); + break; + } +} diff --git a/usr.sbin/tcpdump/tcpdump/print-ether.c b/usr.sbin/tcpdump/tcpdump/print-ether.c new file mode 100644 index 000000000000..2d01c17ce17c --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-ether.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-ether.c,v 1.22 91/10/07 20:18:28 leres Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +u_char *packetp; +u_char *snapend; + +static inline void +ether_print(ep, length) + register struct ether_header *ep; + int length; +{ + if (qflag) + (void)printf("%s %s %d: ", + etheraddr_string(ESRC(ep)), + etheraddr_string(EDST(ep)), + length); + else + (void)printf("%s %s %s %d: ", + etheraddr_string(ESRC(ep)), + etheraddr_string(EDST(ep)), + etherproto_string(ep->ether_type), + length); +} + +/* + * This is the top level routine of the printer. 'p' is the points + * to the ether header of the packet, 'tvp' is the timestamp, + * 'length' is the length of the packet off the wire, and 'caplen' + * is the number of bytes actually captured. + */ +void +ether_if_print(p, tvp, length, caplen) + u_char *p; + struct timeval *tvp; + int length; + int caplen; +{ + struct ether_header *ep; + register int i; + + ts_print(tvp); + + if (caplen < sizeof(struct ether_header)) { + printf("[|ether]"); + goto out; + } + + if (eflag) + ether_print((struct ether_header *)p, length); + + /* + * Some printers want to get back at the ethernet addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = p; + snapend = p + caplen; + + length -= sizeof(struct ether_header); + ep = (struct ether_header *)p; + p += sizeof(struct ether_header); + switch (ntohs(ep->ether_type)) { + + case ETHERTYPE_IP: + ip_print((struct ip *)p, length); + break; + + case ETHERTYPE_ARP: + case ETHERTYPE_REVARP: + arp_print((struct ether_arp *)p, length, caplen - sizeof(*ep)); + break; + + default: + if (!eflag) + ether_print(ep, length); + if (!xflag && !qflag) + default_print((u_short *)p, caplen - sizeof(*ep)); + break; + } + if (xflag) + default_print((u_short *)p, caplen - sizeof(*ep)); + out: + putchar('\n'); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-fddi.c b/usr.sbin/tcpdump/tcpdump/print-fddi.c new file mode 100644 index 000000000000..77831126088e --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-fddi.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#)$Header: print-fddi.c,v 1.4 92/02/03 16:04:02 van Exp $ (LBL)"; +#endif + +#ifdef FDDI +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" + +/* + * NOTE: This is a very preliminary hack for FDDI support. + * There are all sorts of wired in constants & nothing (yet) + * to print SMT packets as anything other than hex dumps. + * Most of the necessary changes are waiting on my redoing + * the "header" that a kernel fddi driver supplies to bpf: I + * want it to look like one byte of 'direction' (0 or 1 + * depending on whether the packet was inbound or outbound), + * two bytes of system/driver dependent data (anything an + * implementor thinks would be useful to filter on and/or + * save per-packet, then the real 21-byte FDDI header. + * Steve McCanne & I have also talked about adding the + * 'direction' byte to all bpf headers (e.g., in the two + * bytes of padding on an ethernet header). It's not clear + * we could do this in a backwards compatible way & we hate + * the idea of an incompatible bpf change. Discussions are + * proceeding. + * + * Also, to really support FDDI (and better support 802.2 + * over ethernet) we really need to re-think the rather simple + * minded assumptions about fixed length & fixed format link + * level headers made in gencode.c. One day... + * + * - vj + */ + +/* XXX This goes somewhere else. */ +#define FDDI_HDRLEN 21 + +static u_char fddi_bit_swap[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +static inline void +fddi_print(p, length) + u_char *p; + int length; +{ + u_char fsrc[6], fdst[6]; + register char *srcname, *dstname; + register int i; + + /* + * bit-swap the fddi addresses (isn't the IEEE standards + * process wonderful!) then convert them to names. + */ + + for (i = 0; i < sizeof(fdst); ++i) + fdst[i] = fddi_bit_swap[p[i+1]]; + for (i = 0; i < sizeof(fsrc); ++i) + fsrc[i] = fddi_bit_swap[p[i+7]]; + dstname = etheraddr_string(fdst); + srcname = etheraddr_string(fsrc); + + if (vflag) + printf("%s %s %02x %02x %02x %02x %02x%02x%02x %s %d: ", + dstname, srcname, + p[0], + p[13], p[14], p[15], + p[16], p[17], p[18], + etherproto_string((p[19] << 8) | p[20]), + length); + else if (qflag) + printf("%s %s %d: ", dstname, srcname, length); + else + printf("%s %s %02x %s %d: ", + dstname, srcname, + p[0], + etherproto_string((p[19] << 8) | p[20]), + length); +} + +void +fddi_if_print(p, tvp, length, caplen) + u_char *p; + struct timeval *tvp; + int length; + int caplen; +{ + struct ip *ip; + u_short type; + + ts_print(tvp); + + if (caplen < FDDI_HDRLEN) { + printf("[|fddi]"); + goto out; + } + + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = (u_char *)p; + snapend = (u_char *)p + caplen; + + /* + * If the frame is not an LLC frame or is not an LLC/UI frame + * or doesn't have SNAP as a dest NSAP, use the default printer. + * (XXX - should interpret SMT packets here.) + */ + if ((p[0] & 0xf8) != 0x50) + /* not LLC frame -- use default printer */ + type = 0; + else if ((p[15] &~ 0x10) != 0x03) + /* not UI frame -- use default printer */ + type = 0; + else if (p[13] != 170) + /* DSAP not SNAP -- use default printer */ + type = 0; + else + type = (p[19] << 8) | p[20]; + if (eflag) + fddi_print(p, length); + + length -= FDDI_HDRLEN; + p += FDDI_HDRLEN; + + switch (ntohs(type)) { + + case ETHERTYPE_IP: + ip_print((struct ip *)p, length); + break; + + case ETHERTYPE_ARP: + case ETHERTYPE_REVARP: + arp_print((struct ether_arp *)p, length, caplen - FDDI_HDRLEN); + break; + + default: + if (!eflag) + fddi_print(p, length); + if (!xflag && !qflag) + default_print((u_short *)p, caplen - FDDI_HDRLEN); + break; + } + if (xflag) + default_print((u_short *)p, caplen - sizeof(FDDI_HDRLEN)); +out: + putchar('\n'); +} +#else +#include +void +fddi_if_print() +{ + void error(); + + error("not configured for fddi"); + /* NOTREACHED */ +} +#endif diff --git a/usr.sbin/tcpdump/tcpdump/print-icmp.c b/usr.sbin/tcpdump/tcpdump/print-icmp.c new file mode 100644 index 000000000000..928d8664517d --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-icmp.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-icmp.c,v 1.11 91/03/27 17:42:58 leres Exp $ (LBL)"; +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" + +void +icmp_print(dp, ip) + register struct icmp *dp; + register struct ip *ip; +{ + char buf[256]; + register char *str = buf; + register struct ip *oip; + register struct udphdr *ouh; + register int hlen; + u_char *ep; + +#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc + + /* 'ep' points to the end of avaible data. */ + ep = (u_char *)snapend; + + (void)printf("%s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + strcpy(str, "[?]"); + + TCHECK(dp->icmp_code, sizeof(dp->icmp_code)); + switch (dp->icmp_type) { + case ICMP_ECHOREPLY: + str = "echo reply"; + break; + case ICMP_UNREACH: + TCHECK(dp->icmp_ip.ip_dst, sizeof(dp->icmp_ip.ip_dst)); + switch (dp->icmp_code) { + case ICMP_UNREACH_NET: + (void)sprintf(buf, "net %s unreachable", + ipaddr_string(&dp->icmp_ip.ip_dst)); + break; + case ICMP_UNREACH_HOST: + (void)sprintf(buf, "host %s unreachable", + ipaddr_string(&dp->icmp_ip.ip_dst)); + break; + case ICMP_UNREACH_PROTOCOL: + TCHECK(dp->icmp_ip.ip_p, sizeof(dp->icmp_ip.ip_p)); + (void)sprintf(buf, "%s protocol %d unreachable", + ipaddr_string(&dp->icmp_ip.ip_dst), + dp->icmp_ip.ip_p); + break; + case ICMP_UNREACH_PORT: + TCHECK(dp->icmp_ip.ip_p, sizeof(dp->icmp_ip.ip_p)); + oip = &dp->icmp_ip; + hlen = oip->ip_hl * 4; + ouh = (struct udphdr *)(((u_char *)oip) + hlen); + NTOHS(ouh->uh_dport); + switch (oip->ip_p) { + case IPPROTO_TCP: + (void)sprintf(buf, + "%s tcp port %s unreachable", + ipaddr_string(&oip->ip_dst), + tcpport_string(ouh->uh_dport)); + break; + case IPPROTO_UDP: + (void)sprintf(buf, + "%s udp port %s unreachable", + ipaddr_string(&oip->ip_dst), + udpport_string(ouh->uh_dport)); + break; + default: + (void)sprintf(buf, + "%s protocol %d port %d unreachable", + ipaddr_string(&oip->ip_dst), + oip->ip_p, ouh->uh_dport); + break; + } + break; + case ICMP_UNREACH_NEEDFRAG: + (void)sprintf(buf, "%s unreachable - need to frag", + ipaddr_string(&dp->icmp_ip.ip_dst)); + break; + case ICMP_UNREACH_SRCFAIL: + (void)sprintf(buf, + "%s unreachable - source route failed", + ipaddr_string(&dp->icmp_ip.ip_dst)); + break; + } + break; + case ICMP_SOURCEQUENCH: + str = "source quench"; + break; + case ICMP_REDIRECT: + TCHECK(dp->icmp_ip.ip_dst, sizeof(dp->icmp_ip.ip_dst)); + switch (dp->icmp_code) { + case ICMP_REDIRECT_NET: + (void)sprintf(buf, "redirect %s to net %s", + ipaddr_string(&dp->icmp_ip.ip_dst), + ipaddr_string(&dp->icmp_gwaddr)); + break; + case ICMP_REDIRECT_HOST: + (void)sprintf(buf, "redirect %s to host %s", + ipaddr_string(&dp->icmp_ip.ip_dst), + ipaddr_string(&dp->icmp_gwaddr)); + break; + case ICMP_REDIRECT_TOSNET: + (void)sprintf(buf, "redirect-tos %s to net %s", + ipaddr_string(&dp->icmp_ip.ip_dst), + ipaddr_string(&dp->icmp_gwaddr)); + break; + case ICMP_REDIRECT_TOSHOST: + (void)sprintf(buf, "redirect-tos %s to host %s", + ipaddr_string(&dp->icmp_ip.ip_dst), + ipaddr_string(&dp->icmp_gwaddr)); + break; + } + break; + case ICMP_ECHO: + str = "echo request"; + break; + case ICMP_TIMXCEED: + TCHECK(dp->icmp_ip.ip_dst, sizeof(dp->icmp_ip.ip_dst)); + switch (dp->icmp_code) { + case ICMP_TIMXCEED_INTRANS: + str = "time exceeded in-transit"; + break; + case ICMP_TIMXCEED_REASS: + str = "ip reassembly time exceeded"; + break; + } + break; + case ICMP_PARAMPROB: + if (dp->icmp_code) + (void)sprintf(buf, "parameter problem - code %d", + dp->icmp_code); + else { + TCHECK(dp->icmp_pptr, sizeof(dp->icmp_pptr)); + (void)sprintf(buf, "parameter problem - octet %d", + dp->icmp_pptr); + } + break; + case ICMP_TSTAMP: + str = "time stamp request"; + break; + case ICMP_TSTAMPREPLY: + str = "time stamp reply"; + break; + case ICMP_IREQ: + str = "information request"; + break; + case ICMP_IREQREPLY: + str = "information reply"; + break; + case ICMP_MASKREQ: + str = "address mask request"; + break; + case ICMP_MASKREPLY: + TCHECK(dp->icmp_mask, sizeof(dp->icmp_mask)); + (void)sprintf(buf, "address mask is 0x%08x", dp->icmp_mask); + break; + } + (void)printf("icmp: %s", str); + return; +trunc: + fputs("[|icmp]", stdout); +#undef TCHECK +} diff --git a/usr.sbin/tcpdump/tcpdump/print-ip.c b/usr.sbin/tcpdump/tcpdump/print-ip.c new file mode 100644 index 000000000000..8716a016d14a --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-ip.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-ip.c,v 1.28 92/05/25 14:29:02 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +void +igmp_print(cp, len, ip) + register u_char *cp; + register int len; + register struct ip *ip; +{ + register u_char *ep = (u_char *)snapend; + + (void)printf("%s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + if (cp + 7 > ep) { + (void)printf("[|igmp]"); + return; + } + switch (cp[0] & 0xf) { + case 1: + (void)printf("igmp query"); + if (*(int *)&cp[4]) + (void)printf(" [gaddr %s]", ipaddr_string(&cp[4])); + if (len != 8) + (void)printf(" [len %d]", len); + break; + case 2: + (void)printf("igmp report %s", ipaddr_string(&cp[4])); + if (len != 8) + (void)printf(" [len %d]", len); + break; + case 3: + (void)printf("igmp dvmrp", ipaddr_string(&cp[4])); + if (len < 8) + (void)printf(" [len %d]", len); + break; + default: + (void)printf("igmp-%d", cp[0] & 0xf); + break; + } + if ((cp[0] >> 4) != 1) + (void)printf(" [v%d]", cp[0] >> 4); + if (cp[1]) + (void)printf(" [b1=0x%x]", cp[1]); +} + +/* + * print the recorded route in an IP RR, LSRR or SSRR option. + */ +static void +ip_printroute(type, cp, length) + char *type; + register u_char *cp; + int length; +{ + int ptr = cp[2] - 1; + int len; + + printf(" %s{", type); + if ((length + 1) & 3) + printf(" [bad length %d]", length); + if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) + printf(" [bad ptr %d]", cp[2]); + + type = ""; + for (len = 3; len < length; len += 4) { + if (ptr == len) + type = "#"; +#ifdef TCPDUMP_ALIGN + { + struct in_addr addr; + bcopy((char *)&cp[len], (char *)&addr, sizeof(addr)); + printf("%s%s", type, ipaddr_string(&addr)); + } +#else + printf("%s%s", type, ipaddr_string(&cp[len])); +#endif + type = " "; + } + printf("%s}", ptr == len? "#" : ""); +} + +/* + * print IP options. + */ +static void +ip_optprint(cp, length) + register u_char *cp; + int length; +{ + int len; + + for (; length > 0; cp += len, length -= len) { + int tt = *cp; + + len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1]; + if (&cp[1] >= snapend || cp + len > snapend) { + printf("[|ip]"); + return; + } + switch (tt) { + + case IPOPT_EOL: + printf(" EOL"); + if (length > 1) + printf("-%d", length - 1); + return; + + case IPOPT_NOP: + printf(" NOP"); + break; + + case IPOPT_TS: + printf(" TS{%d}", len); + break; + + case IPOPT_SECURITY: + printf(" SECURITY{%d}", len); + break; + + case IPOPT_RR: + printf(" RR{%d}=", len); + ip_printroute("RR", cp, len); + break; + + case IPOPT_SSRR: + ip_printroute("SSRR", cp, len); + break; + + case IPOPT_LSRR: + ip_printroute("LSRR", cp, len); + break; + + default: + printf(" IPOPT-%d{%d}", cp[0], len); + break; + } + } +} + +/* + * print an IP datagram. + */ +void +ip_print(ip, length) + register struct ip *ip; + register int length; +{ + register int hlen; + register int len; + register unsigned char *cp; + +#ifdef TCPDUMP_ALIGN + static u_char *abuf; + /* + * The IP header is not word aligned, so copy into abuf. + * This will never happen with BPF. It does happen raw packet + * dumps from -r. + */ + if ((int)ip & (sizeof(long)-1)) { + if (abuf == 0) + abuf = (u_char *)malloc(snaplen); + bcopy((char *)ip, (char *)abuf, min(length, snaplen)); + snapend += abuf - (u_char *)ip; + packetp = abuf; + ip = (struct ip *)abuf; + } +#endif + if ((u_char *)(ip + 1) > snapend) { + printf("[|ip]"); + return; + } + if (length < sizeof (struct ip)) { + (void)printf("truncated-ip %d", length); + return; + } + hlen = ip->ip_hl * 4; + + NTOHS(ip->ip_len); + NTOHS(ip->ip_off); + NTOHS(ip->ip_id); + + len = ip->ip_len - hlen; + if (length < ip->ip_len) + (void)printf("truncated-ip - %d bytes missing!", + ip->ip_len - length); + + /* + * If this is fragment zero, hand it to the next higher + * level protocol. + */ + if ((ip->ip_off & 0x1fff) == 0) { + cp = (unsigned char *)ip + hlen; + switch (ip->ip_p) { + + case IPPROTO_TCP: + tcp_print((struct tcphdr *)cp, len, ip); + break; + case IPPROTO_UDP: + udp_print((struct udphdr *)cp, len, ip); + break; + case IPPROTO_ICMP: + icmp_print((struct icmp *)cp, ip); + break; + case IPPROTO_ND: + (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + (void)printf(" nd %d", len); + break; + case IPPROTO_EGP: + egp_print((struct egp_packet *)cp, len, ip); + break; +#ifndef IPPROTO_OSPF +#define IPPROTO_OSPF 89 +#endif + case IPPROTO_OSPF: + ospf_print((struct ospfhdr *)cp, len, ip); + break; +#ifndef IPPROTO_IGMP +#define IPPROTO_IGMP 2 +#endif + case IPPROTO_IGMP: + igmp_print(cp, len, ip); + break; + default: + (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + (void)printf(" ip-proto-%d %d", ip->ip_p, len); + break; + } + } + /* + * for fragmented datagrams, print id:size@offset. On all + * but the last stick a "+". For unfragmented datagrams, note + * the don't fragment flag. + */ + if (ip->ip_off & 0x3fff) { + /* + * if this isn't the first frag, we're missing the + * next level protocol header. print the ip addr. + */ + if (ip->ip_off & 0x1fff) + (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + (void)printf(" (frag %d:%d@%d%s)", ip->ip_id, len, + (ip->ip_off & 0x1fff) * 8, + (ip->ip_off & IP_MF)? "+" : ""); + } else if (ip->ip_off & IP_DF) + (void)printf(" (DF)"); + + if (ip->ip_tos) + (void)printf(" [tos 0x%x]", (int)ip->ip_tos); + if (ip->ip_ttl <= 1) + (void)printf(" [ttl %d]", (int)ip->ip_ttl); + + if (vflag) { + char *sep = ""; + + printf(" ("); + if (ip->ip_ttl > 1) { + (void)printf("%sttl %d", sep, (int)ip->ip_ttl); + sep = ", "; + } + if ((ip->ip_off & 0x3fff) == 0) { + (void)printf("%sid %d", sep, (int)ip->ip_id); + sep = ", "; + } + if ((hlen -= sizeof(struct ip)) > 0) { + (void)printf("%soptlen=%d", sep, hlen); + ip_optprint((u_char *)(ip + 1), hlen); + } + printf(")"); + } +} diff --git a/usr.sbin/tcpdump/tcpdump/print-nfs.c b/usr.sbin/tcpdump/tcpdump/print-nfs.c new file mode 100644 index 000000000000..8b3169771184 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-nfs.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 1990, 1991, 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-nfs.c,v 1.24 92/01/31 12:27:46 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +/* These must come after interface.h for BSD. */ +#if BSD >= 199006 +#include +#include +#endif +#include + +#include "addrtoname.h" +#include "extract.h" + +static void nfs_printfh(); +static void nfs_printfn(); + +#if BYTE_ORDER == LITTLE_ENDIAN +/* + * Byte swap an array of n words. + * Assume input is word-aligned. + * Check that buffer is bounded by "snapend". + */ +static void +bswap(bp, n) + register u_long *bp; + register u_int n; +{ + register int nwords = ((char *)snapend - (char *)bp) / sizeof(*bp); + + if (nwords > n) + nwords = n; + for (; --nwords >= 0; ++bp) + *bp = ntohl(*bp); +} +#endif + +void +nfsreply_print(rp, length, ip) + register struct rpc_msg *rp; + int length; + register struct ip *ip; +{ +#if BYTE_ORDER == LITTLE_ENDIAN + bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long)); +#endif + if (!nflag) + (void)printf("%s.nfs > %s.%x: reply %s %d", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst), + rp->rm_xid, + rp->rm_reply.rp_stat == MSG_ACCEPTED? "ok":"ERR", + length); + else + (void)printf("%s.%x > %s.%x: reply %s %d", + ipaddr_string(&ip->ip_src), + NFS_PORT, + ipaddr_string(&ip->ip_dst), + rp->rm_xid, + rp->rm_reply.rp_stat == MSG_ACCEPTED? "ok":"ERR", + length); +} + +/* + * Return a pointer to the first file handle in the packet. + * If the packet was truncated, return 0. + */ +static u_long * +parsereq(rp, length) + register struct rpc_msg *rp; + register int length; +{ + register u_long *dp = (u_long *)&rp->rm_call.cb_cred; + register u_long *ep = (u_long *)snapend; + + /* + * find the start of the req data (if we captured it) + * note that dp[1] was already byte swapped by bswap() + */ + if (dp < ep && dp[1] < length) { + dp += (dp[1] + (2*sizeof(u_long) + 3)) / sizeof(u_long); + if ((dp < ep) && (dp[1] < length)) { + dp += (dp[1] + (2*sizeof(u_long) + 3)) / + sizeof(u_long); + if (dp < ep) + return (dp); + } + } + return (0); +} + +/* + * Print out an NFS file handle and return a pointer to following word. + * If packet was truncated, return 0. + */ +static u_long * +parsefh(dp) + register u_long *dp; +{ + if (dp + 8 <= (u_long *)snapend) { + nfs_printfh(dp); + return (dp + 8); + } + return (0); +} + +/* + * Print out a file name and return pointer to longword past it. + * If packet was truncated, return 0. + */ +static u_long * +parsefn(dp) + register u_long *dp; +{ + register int len; + register u_char *cp; + + /* Bail if we don't have the string length */ + if ((u_char *)dp > snapend - sizeof(*dp)) + return(0); + + /* Fetch string length; convert to host order */ + len = *dp++; + NTOHL(len); + + cp = (u_char *)dp; + /* Update long pointer (NFS filenames are padded to long) */ + dp += ((len + 3) & ~3) / sizeof(*dp); + if ((u_char *)dp > snapend) + return (0); + nfs_printfn(cp, len); + + return (dp); +} + +/* + * Print out file handle and file name. + * Return pointer to longword past file name. + * If packet was truncated (or there was some other error), return 0. + */ +static u_long * +parsefhn(dp) + register u_long *dp; +{ + dp = parsefh(dp); + if (dp == 0) + return (0); + putchar(' '); + return (parsefn(dp)); +} + +void +nfsreq_print(rp, length, ip) + register struct rpc_msg *rp; + int length; + register struct ip *ip; +{ + register u_long *dp; + register u_char *ep = snapend; +#define TCHECK(p, l) if ((u_char *)(p) > ep - l) break + +#if BYTE_ORDER == LITTLE_ENDIAN + bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long)); +#endif + + if (!nflag) + (void)printf("%s.%x > %s.nfs: %d", + ipaddr_string(&ip->ip_src), + rp->rm_xid, + ipaddr_string(&ip->ip_dst), + length); + else + (void)printf("%s.%x > %s.%x: %d", + ipaddr_string(&ip->ip_src), + rp->rm_xid, + ipaddr_string(&ip->ip_dst), + NFS_PORT, + length); + + switch (rp->rm_call.cb_proc) { +#ifdef NFSPROC_NOOP + case NFSPROC_NOOP: + printf(" nop"); + return; +#else +#define NFSPROC_NOOP -1 +#endif + case RFS_NULL: + printf(" null"); + return; + + case RFS_GETATTR: + printf(" getattr"); + if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) + return; + break; + + case RFS_SETATTR: + printf(" setattr"); + if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) + return; + break; + +#if RFS_ROOT != NFSPROC_NOOP + case RFS_ROOT: + printf(" root"); + break; +#endif + case RFS_LOOKUP: + printf(" lookup"); + if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) + return; + break; + + case RFS_READLINK: + printf(" readlink"); + if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) + return; + break; + + case RFS_READ: + printf(" read"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefh(dp)) != 0) { + TCHECK(dp, 3 * sizeof(*dp)); + printf(" %lu (%lu) bytes @ %lu", + ntohl(dp[1]), ntohl(dp[2]), ntohl(dp[0])); + return; + } + break; + +#if RFS_WRITECACHE != NFSPROC_NOOP + case RFS_WRITECACHE: + printf(" writecache"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefh(dp)) != 0) { + TCHECK(dp, 4 * sizeof(*dp)); + printf(" %lu (%lu) bytes @ %lu (%lu)", + ntohl(dp[3]), ntohl(dp[2]), + ntohl(dp[1]), ntohl(dp[0])); + return; + } + break; +#endif + case RFS_WRITE: + printf(" write"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefh(dp)) != 0) { + TCHECK(dp, 4 * sizeof(*dp)); + printf(" %lu (%lu) bytes @ %lu (%lu)", + ntohl(dp[3]), ntohl(dp[2]), + ntohl(dp[1]), ntohl(dp[0])); + return; + } + break; + + case RFS_CREATE: + printf(" create"); + if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) + return; + break; + + case RFS_REMOVE: + printf(" remove"); + if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) + return; + break; + + case RFS_RENAME: + printf(" rename"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefhn(dp)) != 0) { + fputs(" ->", stdout); + if (parsefhn(dp) != 0) + return; + } + break; + + case RFS_LINK: + printf(" link"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefh(dp)) != 0) { + fputs(" ->", stdout); + if (parsefhn(dp) != 0) + return; + } + break; + + case RFS_SYMLINK: + printf(" symlink"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefhn(dp)) != 0) { + fputs(" -> ", stdout); + if (parsefn(dp) != 0) + return; + } + break; + + case RFS_MKDIR: + printf(" mkdir"); + if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) + return; + break; + + case RFS_RMDIR: + printf(" rmdir"); + if ((dp = parsereq(rp, length)) != 0 && parsefhn(dp) != 0) + return; + break; + + case RFS_READDIR: + printf(" readdir"); + if ((dp = parsereq(rp, length)) != 0 && + (dp = parsefh(dp)) != 0) { + TCHECK(dp, 2 * sizeof(*dp)); + printf(" %lu bytes @ %lu", ntohl(dp[1]), ntohl(dp[0])); + return; + } + break; + + case RFS_STATFS: + printf(" statfs"); + if ((dp = parsereq(rp, length)) != 0 && parsefh(dp) != 0) + return; + break; + + default: + printf(" proc-%lu", rp->rm_call.cb_proc); + return; + } + fputs(" [|nfs]", stdout); +#undef TCHECK +} + +/* + * Print out an NFS file handle. + * We assume packet was not truncated before the end of the + * file handle pointed to by dp. + */ +static void +nfs_printfh(dp) + register u_long *dp; +{ + /* + * take a wild guess at the structure of file handles. + * On sun 3s, there are 2 longs of fsid, a short + * len == 8, a long of inode & a long of generation number. + * On sun 4s, the len == 10 & there are 2 bytes of + * padding immediately following it. + */ + if (dp[2] == 0xa0000) { + if (dp[1]) + (void) printf(" fh %ld.%ld.%lu", dp[0], dp[1], dp[3]); + else + (void) printf(" fh %ld.%ld", dp[0], dp[3]); + } else if ((dp[2] >> 16) == 8) + /* + * 'dp' is longword aligned, so we must use the extract + * macros below for dp+10 which cannot possibly be aligned. + */ + if (dp[1]) + (void) printf(" fh %ld.%ld.%lu", dp[0], dp[1], + EXTRACT_LONG((u_char *)dp + 10)); + else + (void) printf(" fh %ld.%ld", dp[0], + EXTRACT_LONG((u_char *)dp + 10)); + /* On Ultrix pre-4.0, three longs: fsid, fno, fgen and then zeros */ + else if (dp[3] == 0) { + (void)printf(" fh %d,%d/%ld.%ld", major(dp[0]), minor(dp[0]), + dp[1], dp[2]); + } + /* + * On Ultrix 4.0, + * five longs: fsid, fno, fgen, eno, egen and then zeros + */ + else if (dp[5] == 0) { + (void)printf(" fh %d,%d/%ld.%ld", major(dp[0]), minor(dp[0]), + dp[1], dp[2]); + if (vflag) { + /* print additional info */ + (void)printf("[%ld.%ld]", dp[3], dp[4]); + } + } + else + (void) printf(" fh %lu.%lu.%lu.%lu", + dp[0], dp[1], dp[2], dp[3]); +} + +/* + * Print out an NFS filename. + * Assumes that len bytes from cp are present in packet. + */ +static void +nfs_printfn(cp, len) + register u_char *cp; + register int len; +{ + register char c; + + /* Sanity */ + if (len >= 64) { + fputs("[\">]", stdout); + return; + } + /* Print out the filename */ + putchar('"'); + while (--len >= 0) { + c = toascii(*cp++); + if (!isascii(c)) { + c = toascii(c); + putchar('M'); + putchar('-'); + } + if (!isprint(c)) { + c ^= 0x40; /* DEL to ?, others to alpha */ + putchar('^'); + } + putchar(c); + } + putchar('"'); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-ntp.c b/usr.sbin/tcpdump/tcpdump/print-ntp.c new file mode 100644 index 000000000000..86f6ba76c1f2 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-ntp.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print ntp packets. + * By Jeffrey Mogul/DECWRL + * loosely based on print-bootp.c + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-ntp.c,v 1.7 92/01/04 01:45:16 leres Exp $ (LBL)"; +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ntp.h" + +/* + * Print ntp requests + */ +void +ntp_print(bp, length) + register struct ntpdata *bp; + int length; +{ + u_char *ep; + int mode, version, leapind; + static char rclock[5]; + +#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc + + /* Note funny sized packets */ + if (length != sizeof(struct ntpdata)) + (void)printf(" [len=%d]", length); + + /* 'ep' points to the end of avaible data. */ + ep = (u_char *)snapend; + + TCHECK(bp->status, sizeof(bp->status)); + + version = (bp->status & VERSIONMASK) >> 3; + printf(" v%d", version); + + leapind = bp->status & LEAPMASK; + switch (leapind) { + + case NO_WARNING: + break; + + case PLUS_SEC: + fputs(" +1s", stdout); + break; + + case MINUS_SEC: + fputs(" -1s", stdout); + break; + } + + mode = bp->status & MODEMASK; + switch (mode) { + + case MODE_UNSPEC: /* unspecified */ + fputs(" unspec", stdout); + break; + + case MODE_SYM_ACT: /* symmetric active */ + fputs(" sym_act", stdout); + break; + + case MODE_SYM_PAS: /* symmetric passive */ + fputs(" sym_pas", stdout); + break; + + case MODE_CLIENT: /* client */ + fputs(" client", stdout); + break; + + case MODE_SERVER: /* server */ + fputs(" server", stdout); + break; + + case MODE_BROADCAST: /* broadcast */ + fputs(" bcast", stdout); + break; + + case MODE_RES1: /* reserved */ + fputs(" res1", stdout); + break; + + case MODE_RES2: /* reserved */ + fputs(" res2", stdout); + break; + + } + + TCHECK(bp->stratum, sizeof(bp->stratum)); + printf(" strat %d", bp->stratum); + + TCHECK(bp->ppoll, sizeof(bp->ppoll)); + printf(" poll %d", bp->ppoll); + + /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */ + TCHECK(bp->distance, 0); + printf(" prec %d", bp->precision); + + if (!vflag) + return; + + TCHECK(bp->distance, sizeof(bp->distance)); + fputs(" dist ", stdout); + p_sfix(&bp->distance); + + TCHECK(bp->dispersion, sizeof(bp->dispersion)); + fputs(" disp ", stdout); + p_sfix(&bp->dispersion); + + TCHECK(bp->refid, sizeof(bp->refid)); + fputs(" ref ", stdout); + /* Interpretation depends on stratum */ + switch (bp->stratum) { + + case UNSPECIFIED: + case PRIM_REF: + strncpy(rclock, (char *)&(bp->refid), 4); + rclock[4] = '\0'; + fputs(rclock, stdout); + break; + + case INFO_QUERY: + printf("%s INFO_QUERY", ipaddr_string(&(bp->refid))); + /* this doesn't have more content */ + return; + + case INFO_REPLY: + printf("%s INFO_REPLY", ipaddr_string(&(bp->refid))); + /* this is too complex to be worth printing */ + return; + + default: + printf("%s", ipaddr_string(&(bp->refid))); + break; + } + + TCHECK(bp->reftime, sizeof(bp->reftime)); + putchar('@'); + p_ntp_time(&(bp->reftime)); + + TCHECK(bp->org, sizeof(bp->org)); + fputs(" orig ", stdout); + p_ntp_time(&(bp->org)); + + TCHECK(bp->rec, sizeof(bp->rec)); + fputs(" rec ", stdout); + p_ntp_delta(&(bp->org), &(bp->rec)); + + TCHECK(bp->xmt, sizeof(bp->xmt)); + fputs(" xmt ", stdout); + p_ntp_delta(&(bp->org), &(bp->xmt)); + + return; + +trunc: + fputs(" [|ntp]", stdout); +#undef TCHECK +} + +p_sfix(sfp) + register struct s_fixedpt *sfp; +{ + register int i; + register int f; + register float ff; + + i = ntohs(sfp->int_part); + f = ntohs(sfp->fraction); + ff = f / 65536.0; /* shift radix point by 16 bits */ + f = ff * 1000000.0; /* Treat fraction as parts per million */ + printf("%d.%06d", i, f); +} + +#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ + +p_ntp_time(lfp) + register struct l_fixedpt *lfp; +{ + register long i; + register unsigned long uf; + register unsigned long f; + register float ff; + + i = ntohl(lfp->int_part); + uf = ntohl(lfp->fraction); + ff = uf; + if (ff < 0.0) /* some compilers are buggy */ + ff += FMAXINT; + ff = ff / FMAXINT; /* shift radix point by 32 bits */ + f = ff * 1000000000.0; /* treat fraction as parts per billion */ + printf("%lu.%09d", i, f); +} + +/* Prints time difference between *lfp and *olfp */ +p_ntp_delta(olfp, lfp) + register struct l_fixedpt *olfp; + register struct l_fixedpt *lfp; +{ + register long i; + register unsigned long uf; + register unsigned long ouf; + register unsigned long f; + register float ff; + int signbit; + + i = ntohl(lfp->int_part) - ntohl(olfp->int_part); + + uf = ntohl(lfp->fraction); + ouf = ntohl(olfp->fraction); + + if (i > 0) { /* new is definitely greater than old */ + signbit = 0; + f = uf - ouf; + if (ouf > uf) /* must borrow from high-order bits */ + i -= 1; + } else if (i < 0) { /* new is definitely less than old */ + signbit = 1; + f = ouf - uf; + if (uf > ouf) /* must carry into the high-order bits */ + i += 1; + i = -i; + } else { /* int_part is zero */ + if (uf > ouf) { + signbit = 0; + f = uf - ouf; + } else { + signbit = 1; + f = ouf - uf; + } + } + + ff = f; + if (ff < 0.0) /* some compilers are buggy */ + ff += FMAXINT; + ff = ff / FMAXINT; /* shift radix point by 32 bits */ + f = ff * 1000000000.0; /* treat fraction as parts per billion */ + if (signbit) + putchar('-'); + else + putchar('+'); + printf("%d.%09d", i, f); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-null.c b/usr.sbin/tcpdump/tcpdump/print-null.c new file mode 100644 index 000000000000..b1860685b84d --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-null.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#)$Header: print-null.c,v 1.3 91/10/07 20:19:11 leres Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" + +#define NULL_HDRLEN 4 + +static void +null_print(p, ip, length) + u_char *p; + struct ip *ip; + int length; +{ + u_int family; + + bcopy(p, &family, sizeof(family)); + + if (nflag) { + /* XXX just dump the header */ + return; + } + switch (family) { + + case AF_INET: + printf("ip: "); + break; + + case AF_NS: + printf("ns: "); + break; + + default: + printf("AF %d: ", family); + break; + } +} + +void +null_if_print(p, tvp, length, caplen) + u_char *p; + struct timeval *tvp; + int length; + int caplen; +{ + struct ip *ip; + + ts_print(tvp); + + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = (u_char *)p; + snapend = (u_char *)p + caplen; + + length -= NULL_HDRLEN; + + ip = (struct ip *)(p + NULL_HDRLEN); + + if (eflag) + null_print(p, ip, length); + + ip_print(ip, length); + + if (xflag) + default_print((u_short *)ip, caplen - NULL_HDRLEN); + putchar('\n'); +} + diff --git a/usr.sbin/tcpdump/tcpdump/print-ospf.c b/usr.sbin/tcpdump/tcpdump/print-ospf.c new file mode 100644 index 000000000000..90daf9447a05 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-ospf.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-ospf.c,v 1.1 92/01/29 12:44:17 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ospf.h" +#include "interface.h" +#include "addrtoname.h" + +#ifndef __GNUC__ +#define inline +#endif + +#if !defined(__STDC__) && !defined(const) +#define const +#endif /* !defined(__STDC__) && !defined(const) */ + +struct bits { + u_long bit; + const char *str; +}; + +static const struct bits ospf_option_bits[] = { + OSPF_OPTION_T, "T", + OSPF_OPTION_E, "E", + OSPF_OPTION_MC, "MC", + 0, (char *) 0 +}; + +static const struct bits ospf_rla_flag_bits[] = { + RLA_FLAG_B, "B", + RLA_FLAG_E, "E", + RLA_FLAG_W1, "W1", + RLA_FLAG_W2, "W2", + 0, (char *) 0 +}; + +static const char *ospf_types[OSPF_TYPE_MAX] = { + (char *) 0, + "hello", + "dd", + "ls_req", + "ls_upd", + "ls_ack" +}; + +static inline void +ospf_print_seqage(seq, us) +register u_long seq; +register time_t us; +{ + register time_t sec = us % 60; + register time_t mins = (us / 60) % 60; + register time_t hour = us/3600; + + printf(" S %X age ", + seq); + if (hour) { + printf("%d:%02d:%02d", + hour, + mins, + sec); + } else if (mins) { + printf("%d:%02d", + mins, + sec); + } else { + printf("%d", + sec); + } +} + + +static inline void +ospf_print_bits(bp, options) +register struct bits *bp; +register u_char options; +{ + char sep = ' '; + + do { + if (options & bp->bit) { + printf("%c%s", + sep, + bp->str); + sep = '/'; + } + } while ((++bp)->bit) ; +} + + +#define LS_PRINT(lsp, type) switch (type) { \ + case LS_TYPE_ROUTER: \ + printf(" rtr %s ", ipaddr_string(&lsp->ls_router)); break; \ + case LS_TYPE_NETWORK: \ + printf(" net dr %s if %s", ipaddr_string(&lsp->ls_router), ipaddr_string(&lsp->ls_stateid)); break; \ + case LS_TYPE_SUM_IP: \ + printf(" sum %s abr %s", ipaddr_string(&lsp->ls_stateid), ipaddr_string(&lsp->ls_router)); break; \ + case LS_TYPE_SUM_ABR: \ + printf(" abr %s rtr %s", ipaddr_string(&lsp->ls_router), ipaddr_string(&lsp->ls_stateid)); break; \ + case LS_TYPE_ASE: \ + printf(" ase %s asbr %s", ipaddr_string(&lsp->ls_stateid), ipaddr_string(&lsp->ls_router)); break; \ + case LS_TYPE_GROUP: \ + printf(" group %s rtr %s", ipaddr_string(&lsp->ls_stateid), ipaddr_string(&lsp->ls_router)); break; \ + } + +static int +ospf_print_lshdr(lshp, end) +register struct lsa_hdr *lshp; +caddr_t end; +{ + if ((caddr_t) (lshp + 1) > end) { + return 1; + } + + printf(" {"); + + if (!lshp->ls_type || lshp->ls_type >= LS_TYPE_MAX) { + printf(" ??LS type %d?? }", + lshp->ls_type); + return 1; + } + + ospf_print_bits(ospf_option_bits, lshp->ls_options); + ospf_print_seqage(ntohl(lshp->ls_seq), + ntohs(lshp->ls_age)); + + LS_PRINT(lshp, lshp->ls_type); + + return 0; +} + + +/* + * Print a single link state advertisement. If truncated return 1, else 0. + */ + +static int +ospf_print_lsa(lsap, end) +register struct lsa *lsap; +caddr_t end; +{ + register caddr_t ls_end; + struct rlalink *rlp; + struct tos_metric *tosp; + struct in_addr *ap; + struct aslametric *almp; + struct mcla *mcp; + u_long *lp; + int j, k; + + if (ospf_print_lshdr(&lsap->ls_hdr, end)) { + return 1; + } + + ls_end = (caddr_t) lsap + ntohs(lsap->ls_hdr.ls_length); + + if (ls_end > end) { + printf(" }"); + return 1; + } + + switch (lsap->ls_hdr.ls_type) { + case LS_TYPE_ROUTER: + ospf_print_bits(ospf_rla_flag_bits, lsap->lsa_un.un_rla.rla_flags); + + j = ntohs(lsap->lsa_un.un_rla.rla_count); + rlp = lsap->lsa_un.un_rla.rla_link; + while (j--) { + struct rlalink *rln = (struct rlalink *) ((caddr_t) (rlp + 1) + ((rlp->link_toscount) * sizeof (struct tos_metric))); + + if ((caddr_t) rln > ls_end) { + break; + } + printf(" {"); + + switch (rlp->link_type) { + case RLA_TYPE_VIRTUAL: + printf(" virt"); + /* Fall through */ + + case RLA_TYPE_ROUTER: + printf(" nbrid %s if %s", + ipaddr_string(&rlp->link_id), + ipaddr_string(&rlp->link_data)); + break; + + case RLA_TYPE_TRANSIT: + printf(" dr %s if %s", + ipaddr_string(&rlp->link_id), + ipaddr_string(&rlp->link_data)); + break; + + case RLA_TYPE_STUB: + printf(" net %s mask %s", + ipaddr_string(&rlp->link_id), + ipaddr_string(&rlp->link_data)); + break; + + default: + printf(" ??RouterLinksType %d?? }", + rlp->link_type); + return 0; + } + printf(" tos 0 metric %d", + ntohs(rlp->link_tos0metric)); + tosp = (struct tos_metric *) ((sizeof rlp->link_tos0metric) + (caddr_t) rlp); + for (k = 0; k < rlp->link_toscount; k++, tosp++) { + printf(" tos %d metric %d", + ntohs(tosp->tos_type), + ntohs(tosp->tos_metric)); + } + printf(" }"); + rlp = rln; + } + break; + + case LS_TYPE_NETWORK: + printf(" mask %s rtrs", + ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); + for (ap = lsap->lsa_un.un_nla.nla_router; + (caddr_t) (ap + 1) <= ls_end; + ap++) { + printf(" %s", + ipaddr_string(ap)); + } + break; + + case LS_TYPE_SUM_IP: + printf(" mask %s", + ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); + /* Fall through */ + + case LS_TYPE_SUM_ABR: + + for (lp = lsap->lsa_un.un_sla.sla_tosmetric; + (caddr_t) (lp + 1) <= ls_end; + lp++) { + u_long ul = ntohl(*lp); + + printf(" tos %d metric %d", + (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, + ul & SLA_MASK_METRIC); + } + break; + + case LS_TYPE_ASE: + printf(" mask %s", + ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); + + for (almp = lsap->lsa_un.un_asla.asla_metric; + (caddr_t) (almp + 1) <= ls_end; + almp++) { + u_long ul = ntohl(almp->asla_tosmetric); + + printf(" type %d tos %d metric %d", + (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, + (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS, + (ul & ASLA_MASK_METRIC)); + if (almp->asla_forward.s_addr) { + printf(" forward %s", + ipaddr_string(&almp->asla_forward)); + } + if (almp->asla_tag.s_addr) { + printf(" tag %s", + ipaddr_string(&almp->asla_tag)); + } + } + break; + + case LS_TYPE_GROUP: + /* Multicast extensions as of 23 July 1991 */ + for (mcp = lsap->lsa_un.un_mcla; + (caddr_t) (mcp + 1) <= ls_end; + mcp++) { + switch (ntohl(mcp->mcla_vtype)) { + case MCLA_VERTEX_ROUTER: + printf(" rtr rtrid %s", + ipaddr_string(&mcp->mcla_vid)); + break; + + case MCLA_VERTEX_NETWORK: + printf(" net dr %s", + ipaddr_string(&mcp->mcla_vid)); + break; + + default: + printf(" ??VertexType %d??", + ntohl(mcp->mcla_vtype)); + break; + } + } + } + + printf(" }"); + return 0; +} + + +void +ospf_print(dat, length, ip) +u_char *dat; +int length; +struct ip *ip; +{ + register struct ospfhdr *op = (struct ospfhdr *) dat; + register caddr_t end = (caddr_t)snapend; + register struct lsa *lsap; + register struct lsa_hdr *lshp; + char sep; + int i, j; + struct in_addr *ap; + struct lsr *lsrp; + + /* Print the source and destination address */ + (void) printf(" %s > %s:", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + if ((caddr_t) (&op->ospf_len + 1) > end) { + goto trunc_test; + } + + /* If the type is valid translate it, or just print the type */ + /* value. If it's not valid, say so and return */ + if (op->ospf_type || op->ospf_type < OSPF_TYPE_MAX) { + printf(" OSPFv%d-%s %d:", + op->ospf_version, + ospf_types[op->ospf_type], + length); + } else { + printf(" ospf-v%d-??type %d?? %d:", + op->ospf_version, + op->ospf_type, + length); + return; + } + + if (length != ntohs(op->ospf_len)) { + printf(" ??len %d??", + ntohs(op->ospf_len)); + goto trunc_test; + } + + if ((caddr_t) (&op->ospf_routerid + 1) > end) { + goto trunc_test; + } + + /* Print the routerid if it is not the same as the source */ + if (ip->ip_src.s_addr != op->ospf_routerid.s_addr) { + printf(" rtrid %s", + ipaddr_string(&op->ospf_routerid)); + } + + if ((caddr_t) (&op->ospf_areaid + 1) > end) { + goto trunc_test; + } + + if (op->ospf_areaid.s_addr) { + printf(" area %s", + ipaddr_string(&op->ospf_areaid)); + } else { + printf(" backbone"); + } + + if ((caddr_t) (op->ospf_authdata + OSPF_AUTH_SIZE) > end) { + goto trunc_test; + } + + if (vflag) { + /* Print authentication data (should we really do this?) */ + switch (ntohs(op->ospf_authtype)) { + case OSPF_AUTH_NONE: + break; + + case OSPF_AUTH_SIMPLE: + printf(" auth "); + j = 0; + for (i = 0; i < sizeof (op->ospf_authdata); i++) { + if (!isprint(op->ospf_authdata[i])) { + j = 1; + break; + } + } + if (j) { + /* Print the auth-data as a string of octets */ + printf("%s.%s", + ipaddr_string((struct in_addr *) op->ospf_authdata), + ipaddr_string((struct in_addr *) &op->ospf_authdata[sizeof (struct in_addr)])); + } else { + /* Print the auth-data as a text string */ + printf("'%.8s'", + op->ospf_authdata); + } + break; + + default: + printf(" ??authtype-%d??", + ntohs(op->ospf_authtype)); + return; + } + } + + + /* Do rest according to version. */ + switch (op->ospf_version) { + case 2: + /* ospf version 2 */ + switch (op->ospf_type) { + case OSPF_TYPE_UMD: /* Rob Coltun's special monitoring packets; do nothing */ + break; + + case OSPF_TYPE_HELLO: + if ((caddr_t) (&op->ospf_hello.hello_deadint + 1) > end) { + break; + } + if (vflag) { + ospf_print_bits(ospf_option_bits, op->ospf_hello.hello_options); + printf(" mask %s int %d pri %d dead %d", + ipaddr_string(&op->ospf_hello.hello_mask), + ntohs(op->ospf_hello.hello_helloint), + op->ospf_hello.hello_priority, + ntohl(op->ospf_hello.hello_deadint)); + } + + if ((caddr_t) (&op->ospf_hello.hello_dr + 1) > end) { + break; + } + if (op->ospf_hello.hello_dr.s_addr) { + printf(" dr %s", + ipaddr_string(&op->ospf_hello.hello_dr)); + } + + if ((caddr_t) (&op->ospf_hello.hello_bdr + 1) > end) { + break; + } + if (op->ospf_hello.hello_bdr.s_addr) { + printf(" bdr %s", + ipaddr_string(&op->ospf_hello.hello_bdr)); + } + + if (vflag) { + if ((caddr_t) (op->ospf_hello.hello_neighbor + 1) > end) { + break; + } + printf(" nbrs"); + for (ap = op->ospf_hello.hello_neighbor; + (caddr_t) (ap + 1) <= end; + ap++) { + printf(" %s", + ipaddr_string(ap)); + } + } + break; /* HELLO */ + + case OSPF_TYPE_DB: + if ((caddr_t) (&op->ospf_db.db_seq + 1) > end) { + break; + } + ospf_print_bits(ospf_option_bits, op->ospf_db.db_options); + sep = ' '; + if (op->ospf_db.db_flags & OSPF_DB_INIT) { + printf("%cI", + sep); + sep = '/'; + } + if (op->ospf_db.db_flags & OSPF_DB_MORE) { + printf("%cM", + sep); + sep = '/'; + } + if (op->ospf_db.db_flags & OSPF_DB_MASTER) { + printf("%cMS", + sep); + sep = '/'; + } + printf(" S %X", + ntohl(op->ospf_db.db_seq)); + + if (vflag) { + /* Print all the LS adv's */ + lshp = op->ospf_db.db_lshdr; + + while (!ospf_print_lshdr(lshp, end)) { + printf(" }"); + lshp++; + } + } + break; + + case OSPF_TYPE_LSR: + if (vflag) { + for (lsrp = op->ospf_lsr; (caddr_t) (lsrp+1) <= end; lsrp++) { + long type; + + if ((caddr_t) (lsrp + 1) > end) { + break; + } + + printf(" {"); + if (!(type = lsrp->ls_type) || type >= LS_TYPE_MAX) { + printf(" ??LinkStateType %d }", + type); + printf(" }"); + break; + } + + LS_PRINT(lsrp, type); + printf(" }"); + } + } + break; + + case OSPF_TYPE_LSU: + if (vflag) { + lsap = op->ospf_lsu.lsu_lsa; + i = ntohl(op->ospf_lsu.lsu_count); + + while (i-- && + !ospf_print_lsa(lsap, end)) { + lsap = (struct lsa *) ((caddr_t) lsap + ntohs(lsap->ls_hdr.ls_length)); + } + } + break; + + + case OSPF_TYPE_LSA: + if (vflag) { + lshp = op->ospf_lsa.lsa_lshdr; + + while (!ospf_print_lshdr(lshp, end)) { + printf(" }"); + lshp++; + } + break; + } + } /* end switch on v2 packet type */ + break; + + default: + printf(" ospf [version %d]", + op->ospf_version); + break; + } /* end switch on version */ + + trunc_test: + if ((snapend - dat) < length) { + printf(" [|]"); + } + + return; /* from ospf_print */ +} + + diff --git a/usr.sbin/tcpdump/tcpdump/print-ppp.c b/usr.sbin/tcpdump/tcpdump/print-ppp.c new file mode 100644 index 000000000000..c83cc7d41dfd --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-ppp.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#)$Header: print-ppp.c,v 1.7 91/10/07 20:18:33 leres Exp $ (LBL)"; +#endif + +#ifdef PPP +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" + +/* XXX This goes somewhere else. */ +#define PPP_HDRLEN 4 + +void +ppp_if_print(p, tvp, length, caplen) + u_char *p; + struct timeval *tvp; + int length; + int caplen; +{ + struct ip *ip; + + ts_print(tvp); + + if (caplen < PPP_HDRLEN) { + printf("[|ppp]"); + goto out; + } + + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = (u_char *)p; + snapend = (u_char *)p + caplen; + + if (eflag) + printf("%c %4d %02x %04x: ", p[0] ? 'O' : 'I', length, + p[1], ntohs(*(u_short *)&p[2])); + + length -= PPP_HDRLEN; + ip = (struct ip *)(p + PPP_HDRLEN); + ip_print(ip, length); + + if (xflag) + default_print((u_short *)ip, caplen - PPP_HDRLEN); +out: + putchar('\n'); +} +#else +#include +void +ppp_if_print() +{ + void error(); + + error("not configured for ppp"); + /* NOTREACHED */ +} +#endif diff --git a/usr.sbin/tcpdump/tcpdump/print-rip.c b/usr.sbin/tcpdump/tcpdump/print-rip.c new file mode 100644 index 000000000000..d123fe9a48bb --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-rip.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-rip.c,v 1.12 91/04/19 10:46:46 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" + +static void +rip_entry_print(ni) + register struct netinfo *ni; +{ + if (ntohs(ni->rip_dst.sa_family) != AF_INET) { + register int i; + + printf(" [family %d:", ntohs(ni->rip_dst.sa_family)); + for (i = 0; i < 14; i += 2) + printf(" %02x%02x", ni->rip_dst.sa_data[i], + ni->rip_dst.sa_data[i+1]); + printf("]"); + } else { + register struct sockaddr_in *sin = + (struct sockaddr_in *)&ni->rip_dst; + printf(" %s", ipaddr_string(&sin->sin_addr)); + if (sin->sin_port) + printf(" [port %d]", sin->sin_port); + } + printf("(%d)", ntohl(ni->rip_metric)); +} + +void +rip_print(dat, length) + u_char *dat; + int length; +{ + register struct rip *rp = (struct rip *)dat; + register struct netinfo *ni; + register int amt = (u_char *)snapend - dat; + register int i = min(length, amt) - + (sizeof(struct rip) - sizeof(struct netinfo)); + int j; + int trunc; + + if (i < 0) + return; + + switch (rp->rip_cmd) { + + case RIPCMD_REQUEST: + printf(" rip-req %d", length); + break; + case RIPCMD_RESPONSE: + j = length / sizeof(*ni); + if (j * sizeof(*ni) != length - 4) + printf(" rip-resp %d[%d]:", j, length); + else + printf(" rip-resp %d:", j); + trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); + for (ni = rp->rip_nets; (i -= sizeof(*ni)) >= 0; ++ni) + rip_entry_print(ni); + if (trunc) + printf("[|rip]"); + break; + case RIPCMD_TRACEON: + printf(" rip-traceon %d: \"%s\"", length, rp->rip_tracefile); + break; + case RIPCMD_TRACEOFF: + printf(" rip-traceoff %d", length); + break; + case RIPCMD_POLL: + printf(" rip-poll %d", length); + break; + case RIPCMD_POLLENTRY: + printf(" rip-pollentry %d", length); + break; + default: + printf(" rip-%d ?? %d", rp->rip_cmd, length); + break; + } + if (rp->rip_vers != RIPVERSION) + printf(" [vers %d]", rp->rip_vers); +} diff --git a/usr.sbin/tcpdump/tcpdump/print-sl.c b/usr.sbin/tcpdump/tcpdump/print-sl.c new file mode 100644 index 000000000000..2c89b42d4322 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-sl.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#)$Header: print-sl.c,v 1.17 91/10/07 20:18:35 leres Exp $ (LBL)"; +#endif + +#ifdef CSLIP +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +static int lastlen[2][256]; +static int lastconn = 255; + +static void compressed_sl_print(); + +void +sl_if_print(p, tvp, length, caplen) + u_char *p; + struct timeval *tvp; + int length; + int caplen; +{ + struct ip *ip; + + ts_print(tvp); + + if (caplen < SLIP_HDRLEN) { + printf("[|slip]"); + goto out; + } + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = (u_char *)p; + snapend = (u_char *)p + caplen; + + length -= SLIP_HDRLEN; + + ip = (struct ip *)(p + SLIP_HDRLEN); + + if (eflag) + sliplink_print(p, ip, length); + + ip_print(ip, length); + + if (xflag) + default_print((u_short *)ip, caplen - SLIP_HDRLEN); + out: + putchar('\n'); +} + +sliplink_print(p, ip, length) + u_char *p; + struct ip *ip; + int length; +{ + int dir; + int hlen; + + dir = p[SLX_DIR]; + putchar(dir == SLIPDIR_IN ? 'I' : 'O'); + putchar(' '); + + if (nflag) { + /* XXX just dump the header */ + int i; + + for (i = 0; i < 15; ++i) + printf("%02x.", p[SLX_CHDR + i]); + printf("%02x: ", p[SLX_CHDR + 15]); + return; + } + switch (p[SLX_CHDR] & 0xf0) { + + case TYPE_IP: + printf("ip %d: ", length + SLIP_HDRLEN); + break; + + case TYPE_UNCOMPRESSED_TCP: + /* + * The connection id is stode in the IP protcol field. + */ + lastconn = ip->ip_p; + hlen = ip->ip_hl; + hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off; + lastlen[dir][lastconn] = length - (hlen << 2); + printf("utcp %d: ", lastconn); + break; + + default: + if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { + compressed_sl_print(&p[SLX_CHDR], ip, length, dir); + printf(": "); + } else + printf("slip-%d!: ", p[SLX_CHDR]); + } +} + +static u_char * +print_sl_change(str, cp) + char *str; + register u_char *cp; +{ + register u_int i; + + if ((i = *cp++) == 0) { + i = (cp[0] << 8) | cp[1]; + cp += 2; + } + printf(" %s%d", str, i); + return (cp); +} + +static u_char * +print_sl_winchange(cp) + register u_char *cp; +{ + register short i; + + if ((i = *cp++) == 0) { + i = (cp[0] << 8) | cp[1]; + cp += 2; + } + if (i >= 0) + printf(" W+%d", i); + else + printf(" W%d", i); + return (cp); +} + +static void +compressed_sl_print(chdr, ip, length, dir) + u_char *chdr; + int length; + struct ip *ip; + int dir; +{ + register u_char *cp = chdr; + register u_int flags; + int hlen; + + flags = *cp++; + if (flags & NEW_C) { + lastconn = *cp++; + printf("ctcp %d", lastconn); + } else + printf("ctcp *"); + + /* skip tcp checksum */ + cp += 2; + + switch (flags & SPECIALS_MASK) { + case SPECIAL_I: + printf(" *SA+%d", lastlen[dir][lastconn]); + break; + + case SPECIAL_D: + printf(" *S+%d", lastlen[dir][lastconn]); + break; + + default: + if (flags & NEW_U) + cp = print_sl_change("U=", cp); + if (flags & NEW_W) + cp = print_sl_winchange(cp); + if (flags & NEW_A) + cp = print_sl_change("A+", cp); + if (flags & NEW_S) + cp = print_sl_change("S+", cp); + break; + } + if (flags & NEW_I) + cp = print_sl_change("I+", cp); + + /* + * 'hlen' is the length of the uncompressed TCP/IP header (in longs). + * 'cp - chdr' is the length of the compressed header. + * 'length - hlen' is the amount of data in the packet. + */ + hlen = ip->ip_hl; + hlen += ((struct tcphdr *)&((long *)ip)[hlen])->th_off; + lastlen[dir][lastconn] = length - (hlen << 2); + printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr); +} +#else +#include +void +sl_if_print() +{ + void error(); + + error("not configured for slip"); + /* NOTREACHED */ +} +#endif diff --git a/usr.sbin/tcpdump/tcpdump/print-snmp.c b/usr.sbin/tcpdump/tcpdump/print-snmp.c new file mode 100644 index 000000000000..d1996c07a292 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-snmp.c @@ -0,0 +1,1043 @@ +/* + * Copyright (c) 1990, by John Robert LoVerso. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by John Robert LoVerso. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * This implementaion has been influenced by the CMU SNMP release, + * by Steve Waldbusser. However, this shares no code with that system. + * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_. + * Earlier forms of this implemention were derived and/or inspired by an + * awk script originally written by C. Philip Wood of LANL (but later + * heavily modified by John Robert LoVerso). The copyright notice for + * that work is preserved below, even though it may not rightly apply + * to this file. + * + * This started out as a very simple program, but the incremental decoding + * (into the BE structure) complicated things. + * + # Los Alamos National Laboratory + # + # Copyright, 1990. The Regents of the University of California. + # This software was produced under a U.S. Government contract + # (W-7405-ENG-36) by Los Alamos National Laboratory, which is + # operated by the University of California for the U.S. Department + # of Energy. The U.S. Government is licensed to use, reproduce, + # and distribute this software. Permission is granted to the + # public to copy and use this software without charge, provided + # that this Notice and any statement of authorship are reproduced + # on all copies. Neither the Government nor the University makes + # any warranty, express or implied, or assumes any liability or + # responsibility for the use of this software. + # @(#)snmp.awk.x 1.1 (LANL) 1/15/90 + */ +#ifndef lint +static char rcsid[] = + "@(#) $Id: print-snmp.c,v 3.10 91/01/17 01:18:13 loverso Exp Locker: loverso $ (jlv)"; +#endif + +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +/* + * Universal ASN.1 types + * (we only care about the tag values for those allowed in the Internet SMI) + */ +char *Universal[] = { + "U-0", + "Boolean", + "Integer", +#define INTEGER 2 + "Bitstring", + "String", +#define STRING 4 + "Null", +#define ASN_NULL 5 + "ObjID", +#define OBJECTID 6 + "ObjectDes", + "U-8","U-9","U-10","U-11", /* 8-11 */ + "U-12","U-13","U-14","U-15", /* 12-15 */ + "Sequence", +#define SEQUENCE 16 + "Set" +}; + +/* + * Application-wide ASN.1 types from the Internet SMI and their tags + */ +char *Application[] = { + "IpAddress", +#define IPADDR 0 + "Counter", +#define COUNTER 1 + "Gauge", +#define GAUGE 2 + "TimeTicks", +#define TIMETICKS 3 + "Opaque" +}; + +/* + * Context-specific ASN.1 types for the SNMP PDUs and their tags + */ +char *Context[] = { + "GetRequest", +#define GETREQ 0 + "GetNextRequest", +#define GETNEXTREQ 1 + "GetResponse", +#define GETRESP 2 + "SetRequest", +#define SETREQ 3 + "Trap" +#define TRAP 4 +}; + +/* + * Private ASN.1 types + * The Internet SMI does not specify any + */ +char *Private[] = { + "P-0" +}; + +/* + * error-status values for any SNMP PDU + */ +char *ErrorStatus[] = { + "noError", + "tooBig", + "noSuchName", + "badValue", + "readOnly", + "genErr" +}; +#define DECODE_ErrorStatus(e) \ + ( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \ + ? ErrorStatus[e] : (sprintf(errbuf, "err=%d", e), errbuf)) + +/* + * generic-trap values in the SNMP Trap-PDU + */ +char *GenericTrap[] = { + "coldStart", + "warmStart", + "linkDown", + "linkUp", + "authenticationFailure", + "egpNeighborLoss", + "enterpriseSpecific" +#define GT_ENTERPRISE 7 +}; +#define DECODE_GenericTrap(t) \ + ( t >= 0 && t <= sizeof(GenericTrap)/sizeof(GenericTrap[0]) \ + ? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf)) + +/* + * ASN.1 type class table + * Ties together the preceding Universal, Application, Context, and Private + * type definitions. + */ +#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */ +struct { + char *name; + char **Id; + int numIDs; +} Class[] = { + defineCLASS(Universal), +#define UNIVERSAL 0 + defineCLASS(Application), +#define APPLICATION 1 + defineCLASS(Context), +#define CONTEXT 2 + defineCLASS(Private), +#define PRIVATE 3 +}; + +/* + * defined forms for ASN.1 types + */ +char *Form[] = { + "Primitive", +#define PRIMITIVE 0 + "Constructed", +#define CONSTRUCTED 1 +}; + +/* + * A structure for the OID tree for the compiled-in MIB. + * This is stored as a general-order tree. + */ +struct obj { + char *desc; /* name of object */ + u_char oid; /* sub-id following parent */ + u_char type; /* object type (unused) */ + struct obj *child, *next; /* child and next sibling pointers */ +} *objp = NULL; + +/* + * Include the compiled in SNMP MIB. "mib.h" is produced by feeding + * RFC-1156 format files into "makemib". "mib.h" MUST define at least + * a value for `mibroot'. + * + * In particluar, this is gross, as this is including initialized structures, + * and by right shouldn't be an "include" file. + */ +#include "mib.h" + +/* + * This defines a list of OIDs which will be abreviated on output. + * Currently, this includes the prefixes for the Internet MIB, the + * private enterprises tree, and the experimental tree. + */ +struct obj_abrev { + char *prefix; /* prefix for this abrev */ + struct obj *node; /* pointer into object table */ + char *oid; /* ASN.1 encoded OID */ +} obj_abrev_list[] = { +#ifndef NO_ABREV_MIB + /* .iso.org.dod.internet.mgmt.mib */ + { "", &_mib_obj, "\53\6\1\2\1" }, +#endif +#ifndef NO_ABREV_ENTER + /* .iso.org.dod.internet.private.enterprises */ + { "E:", &_enterprises_obj, "\53\6\1\4\1" }, +#endif +#ifndef NO_ABREV_EXPERI + /* .iso.org.dod.internet.experimental */ + { "X:", &_experimental_obj, "\53\6\1\3" }, +#endif + { 0,0,0 } +}; + +/* + * This is used in the OID print routine to walk down the object tree + * rooted at `mibroot'. + */ +#define OBJ_PRINT(o, suppressdot) \ +{ \ + if (objp) { \ + do { \ + if ((o) == objp->oid) \ + break; \ + } while (objp = objp->next); \ + } \ + if (objp) { \ + printf(suppressdot?"%s":".%s", objp->desc); \ + objp = objp->child; \ + } else \ + printf(suppressdot?"%u":".%u", (o)); \ +} + +/* + * This is the definition for the Any-Data-Type storage used purely for + * temporary internal representation while decoding an ASN.1 data stream. + */ +struct be { + unsigned long asnlen; + union { + caddr_t raw; + long integer; + unsigned long uns; + unsigned char *str; + } data; + unsigned char form, class, id; /* tag info */ + u_char type; +#define BE_ANY 255 +#define BE_NONE 0 +#define BE_NULL 1 +#define BE_OCTET 2 +#define BE_OID 3 +#define BE_INT 4 +#define BE_UNS 5 +#define BE_STR 6 +#define BE_SEQ 7 +#define BE_INETADDR 8 +#define BE_PDU 9 +}; + +/* + * Defaults for SNMP PDU components + */ +#define DEF_COMMUNITY "public" +#define DEF_VERSION 0 + +/* + * constants for ASN.1 decoding + */ +#define OIDMUX 40 +#define ASNLEN_INETADDR 4 +#define ASN_SHIFT7 7 +#define ASN_SHIFT8 8 +#define ASN_BIT8 0x80 +#define ASN_LONGLEN 0x80 + +#define ASN_ID_BITS 0x1f +#define ASN_FORM_BITS 0x20 +#define ASN_FORM_SHIFT 5 +#define ASN_CLASS_BITS 0xc0 +#define ASN_CLASS_SHIFT 6 + +#define ASN_ID_EXT 0x1f /* extension ID in tag field */ + +/* + * truncated==1 means the packet was complete, but we don't have all of + * it to decode. + */ +static int truncated; +#define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else + +/* + * This decodes the next ASN.1 object in the stream pointed to by "p" + * (and of real-length "len") and stores the intermediate data in the + * provided BE object. + * + * This returns -l if it fails (i.e., the ASN.1 stream is not valid). + * O/w, this returns the number of bytes parsed from "p". + */ +int +asn1_parse(p, len, elem) + register u_char *p; + int len; + struct be *elem; +{ + unsigned char form, class, id; + int indent=0, i, hdr; + char *classstr; + + elem->asnlen = 0; + elem->type = BE_ANY; + if (len < 1) { + ifNotTruncated puts("[nothing to parse], stdout"); + return -1; + } + + /* + * it would be nice to use a bit field, but you can't depend on them. + * +---+---+---+---+---+---+---+---+ + * + class |frm| id | + * +---+---+---+---+---+---+---+---+ + * 7 6 5 4 3 2 1 0 + */ + id = *p & ASN_ID_BITS; /* lower 5 bits, range 00-1f */ +#ifdef notdef + form = (*p & 0xe0) >> 5; /* move upper 3 bits to lower 3 */ + class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */ + form &= 0x1; /* bit 5 -> bit 0, range 0-1 */ +#else + form = (*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT; + class = (*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT; +#endif + elem->form = form; + elem->class = class; + elem->id = id; + if (vflag) + printf("|%.2x", *p); + p++; len--; hdr = 1; + /* extended tag field */ + if (id == ASN_ID_EXT) { + for (id = 0; *p & ASN_BIT8 && len > 0; len--, hdr++, p++) { + if (vflag) + printf("|%.2x", *p); + id += *p & ~ASN_BIT8; + } + if (len == 0 && *p & ASN_BIT8) { + ifNotTruncated fputs("[Xtagfield?]", stdout); + return -1; + } + } + if (len < 1) { + ifNotTruncated fputs("[no asnlen]", stdout); + return -1; + } + elem->asnlen = *p; + if (vflag) + printf("|%.2x", *p); + p++; len--; hdr++; + if (elem->asnlen & ASN_BIT8) { + int noct = elem->asnlen % ASN_BIT8; + elem->asnlen = 0; + if (len < noct) { + ifNotTruncated printf("[asnlen? %d<%d]", len, noct); + return -1; + } + for (; noct-- > 0; len--, hdr++) { + if (vflag) + printf("|%.2x", *p); + elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++; + } + } + if (len < elem->asnlen) { + if (!truncated) { + printf("[len%dasnlen); + return -1; + } + /* maybe should check at least 4? */ + elem->asnlen = len; + } + if (form >= sizeof(Form)/sizeof(Form[0])) { + ifNotTruncated printf("[form?%d]", form); + return -1; + } + if (class >= sizeof(Class)/sizeof(Class[0])) { + ifNotTruncated printf("[class?%c/%d]", *Form[form], class); + return -1; + } + if (id >= Class[class].numIDs) { + ifNotTruncated printf("[id?%c/%s/%d]", *Form[form], + Class[class].name, id); + return -1; + } + + switch (form) { + case PRIMITIVE: + switch (class) { + case UNIVERSAL: + switch (id) { + case STRING: + elem->type = BE_STR; + elem->data.str = p; + break; + + case INTEGER: { + register long data; + elem->type = BE_INT; + data = 0; + + if (*p & ASN_BIT8) /* negative */ + data = -1; + for (i = elem->asnlen; i-- > 0; p++) + data = (data << ASN_SHIFT8) | *p; + elem->data.integer = data; + break; + } + + case OBJECTID: + elem->type = BE_OID; + elem->data.raw = (caddr_t)p; + break; + + case ASN_NULL: + elem->type = BE_NULL; + elem->data.raw = NULL; + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("[P/U/%s]", + Class[class].Id[id]); + break; + } + break; + + case APPLICATION: + switch (id) { + case IPADDR: + elem->type = BE_INETADDR; + elem->data.raw = (caddr_t)p; + break; + + case COUNTER: + case GAUGE: + case TIMETICKS: { + register unsigned long data; + elem->type = BE_UNS; + data = 0; + for (i = elem->asnlen; i-- > 0; p++) + data = (data << 8) + *p; + elem->data.uns = data; + break; + } + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("[P/A/%s]", + Class[class].Id[id]); + break; + } + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("[P/%s/%s]", + Class[class].name, Class[class].Id[id]); + break; + } + break; + + case CONSTRUCTED: + switch (class) { + case UNIVERSAL: + switch (id) { + case SEQUENCE: + elem->type = BE_SEQ; + elem->data.raw = (caddr_t)p; + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("C/U/%s", Class[class].Id[id]); + break; + } + break; + + case CONTEXT: + elem->type = BE_PDU; + elem->data.raw = (caddr_t)p; + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("C/%s/%s", + Class[class].name, Class[class].Id[id]); + break; + } + break; + } + p += elem->asnlen; + len -= elem->asnlen; + return elem->asnlen + hdr; +} + +/* + * Display the ASN.1 object represented by the BE object. + * This used to be an integral part of asn1_parse() before the intermediate + * BE form was added. + */ +void +asn1_print(elem) + struct be *elem; +{ + u_char *p = (u_char *)elem->data.raw; + u_long asnlen = elem->asnlen; + int i; + + switch (elem->type) { + + case BE_OCTET: + for (i = asnlen; i-- > 0; p++); + printf("_%.2x", *p); + break; + + case BE_NULL: + break; + + case BE_OID: { + int o = 0, first = -1, i = asnlen; + + if (!nflag && asnlen > 2) { + struct obj_abrev *a = &obj_abrev_list[0]; + for (; a->node; a++) { + if (!memcmp(a->oid, p, strlen(a->oid))) { + objp = a->node->child; + i -= strlen(a->oid); + p += strlen(a->oid); + fputs(a->prefix, stdout); + first = 1; + break; + } + } + } + for (; i-- > 0; p++) { + o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8); + if (*p & ASN_LONGLEN) + continue; + + /* + * first subitem encodes two items with 1st*OIDMUX+2nd + */ + if (first < 0) { + if (!nflag) + objp = mibroot; + first = 0; + OBJ_PRINT(o/OIDMUX, first); + o %= OIDMUX; + } + OBJ_PRINT(o, first); + if (--first < 0) + first = 0; + o = 0; + } + break; + } + + case BE_INT: + printf("%ld", elem->data.integer); + break; + + case BE_UNS: + printf("%ld", elem->data.uns); + break; + + case BE_STR: { + register int printable = 1, first = 1; + u_char *p = elem->data.str; + for (i = asnlen; printable && i-- > 0; p++) + printable = isprint(*p) || isspace(*p); + p = elem->data.str; + if (printable) + (void)printfn(p, p+asnlen); + else + for (i = asnlen; i-- > 0; p++) { + printf(first ? "%.2x" : "_%.2x", *p); + first = 0; + } + break; + } + + case BE_SEQ: + printf("Seq(%d)", elem->asnlen); + break; + + case BE_INETADDR: { + char sep; + if (asnlen != ASNLEN_INETADDR) + printf("[inetaddr len!=%d]", ASNLEN_INETADDR); + sep='['; + for (i = asnlen; i-- > 0; p++) { + printf("%c%u", sep, *p); + sep='.'; + } + putchar(']'); + break; + } + + case BE_PDU: + printf("%s(%d)", + Class[CONTEXT].Id[elem->id], elem->asnlen); + break; + + case BE_ANY: + fputs("[BE_ANY!?]", stdout); + break; + + default: + fputs("[be!?]", stdout); + break; + } +} + +#ifdef notdef +/* + * This is a brute force ASN.1 printer: recurses to dump an entire structure. + * This will work for any ASN.1 stream, not just an SNMP PDU. + * + * By adding newlines and spaces at the correct places, this would print in + * Rose-Normal-Form. + * + * This is not currently used. + */ +void +asn1_decode(p, length) + u_char *p; + int length; +{ + struct be elem; + int i = 0; + + while (i >= 0 && length > 0) { + i = asn1_parse(p, length, &elem); + if (i >= 0) { + fputs(" ", stdout); + asn1_print(&elem); + if (elem.type == BE_SEQ || elem.type == BE_PDU) { + fputs(" {", stdout); + asn1_decode(elem.data.raw, elem.asnlen); + fputs(" }", stdout); + } + length -= i; + p += i; + } + } +} +#endif + +/* + * General SNMP header + * SEQUENCE { + * version INTEGER {version-1(0)}, + * community OCTET STRING, + * data ANY -- PDUs + * } + * PDUs for all but Trap: (see rfc1157 from page 15 on) + * SEQUENCE { + * request-id INTEGER, + * error-status INTEGER, + * error-index INTEGER, + * varbindlist SEQUENCE OF + * SEQUENCE { + * name ObjectName, + * value ObjectValue + * } + * } + * PDU for Trap: + * SEQUENCE { + * enterprise OBJECT IDENTIFIER, + * agent-addr NetworkAddress, + * generic-trap INTEGER, + * specific-trap INTEGER, + * time-stamp TimeTicks, + * varbindlist SEQUENCE OF + * SEQUENCE { + * name ObjectName, + * value ObjectValue + * } + * } + */ + +/* + * Decode SNMP varBind + */ +void +varbind_print (pduid, np, length, error) + u_char pduid, *np; + int length, error; +{ + struct be elem; + int count = 0, index; + + /* Sequence of varBind */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_SEQ) { + fputs("[!SEQ of varbind]", stdout); + asn1_print(&elem); + return; + } + if (count < length) + printf("[%d extra after SEQ of varbind]", length - count); + /* descend */ + length = elem.asnlen; + np = (u_char *)elem.data.raw; + + for (index = 1; length > 0; index++) { + u_char *vbend; + int vblength; + + if (!error || index == error) + fputs(" ", stdout); + + /* Sequence */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_SEQ) { + fputs("[!varbind]", stdout); + asn1_print(&elem); + return; + } + vbend = np + count; + vblength = length - count; + /* descend */ + length = elem.asnlen; + np = (u_char *)elem.data.raw; + + /* objName (OID) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_OID) { + fputs("[objName!=OID]", stdout); + asn1_print(&elem); + return; + } + if (!error || index == error) + asn1_print(&elem); + length -= count; + np += count; + + if (pduid != GETREQ && pduid != GETNEXTREQ && !error) + fputs("=", stdout); + + /* objVal (ANY) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (pduid == GETREQ || pduid == GETNEXTREQ) { + if (elem.type != BE_NULL) { + fputs("[objVal!=NULL]", stdout); + asn1_print(&elem); + } + } else + if (error && index == error && elem.type != BE_NULL) + fputs("[err objVal!=NULL]", stdout); + if (!error || index == error) + asn1_print(&elem); + + length = vblength; + np = vbend; + } +} + +/* + * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest + */ +void +snmppdu_print (pduid, np, length) + u_char pduid, *np; + int length; +{ + struct be elem; + int count = 0, error; + + /* reqId (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[reqId!=INT]", stdout); + asn1_print(&elem); + return; + } + /* ignore the reqId */ + length -= count; + np += count; + + /* errorStatus (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[errorStatus!=INT]", stdout); + asn1_print(&elem); + return; + } + error = 0; + if ((pduid == GETREQ || pduid == GETNEXTREQ) + && elem.data.integer != 0) { + char errbuf[10]; + printf("[errorStatus(%s)!=0]", + DECODE_ErrorStatus(elem.data.integer)); + } else if (elem.data.integer != 0) { + char errbuf[10]; + printf(" %s", DECODE_ErrorStatus(elem.data.integer)); + error = elem.data.integer; + } + length -= count; + np += count; + + /* errorIndex (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[errorIndex!=INT]", stdout); + asn1_print(&elem); + return; + } + if ((pduid == GETREQ || pduid == GETNEXTREQ) + && elem.data.integer != 0) + printf("[errorIndex(%d)!=0]", elem.data.integer); + else if (elem.data.integer != 0) { + if (!error) + printf("[errorIndex(%d) w/o errorStatus]", + elem.data.integer); + else { + printf("@%d", elem.data.integer); + error = elem.data.integer; + } + } else if (error) { + fputs("[errorIndex==0]", stdout); + error = 0; + } + length -= count; + np += count; + + varbind_print(pduid, np, length, error); + return; +} + +/* + * Decode SNMP Trap PDU + */ +void +trap_print (np, length) + u_char *np; + int length; +{ + struct be elem; + int count = 0, generic; + + putchar(' '); + + /* enterprise (oid) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_OID) { + fputs("[enterprise!=OID]", stdout); + asn1_print(&elem); + return; + } + asn1_print(&elem); + length -= count; + np += count; + + putchar(' '); + + /* agent-addr (inetaddr) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INETADDR) { + fputs("[agent-addr!=INETADDR]", stdout); + asn1_print(&elem); + return; + } + asn1_print(&elem); + length -= count; + np += count; + + /* generic-trap (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[generic-trap!=INT]", stdout); + asn1_print(&elem); + return; + } + generic = elem.data.integer; + { + char buf[10]; + printf(" %s", DECODE_GenericTrap(generic)); + } + length -= count; + np += count; + + /* specific-trap (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[specific-trap!=INT]", stdout); + asn1_print(&elem); + return; + } + if (generic != GT_ENTERPRISE) { + if (elem.data.integer != 0) + printf("[specific-trap(%d)!=0]", elem.data.integer); + } else + printf(" s=%d", elem.data.integer); + length -= count; + np += count; + + putchar(' '); + + /* time-stamp (TimeTicks) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_UNS) { /* XXX */ + fputs("[time-stamp!=TIMETICKS]", stdout); + asn1_print(&elem); + return; + } + asn1_print(&elem); + length -= count; + np += count; + + varbind_print (TRAP, np, length, 0); + return; +} + +/* + * Decode SNMP header and pass on to PDU printing routines + */ +void +snmp_print (np, length) + u_char *np; + int length; +{ + struct be elem, pdu; + int count = 0; + + truncated = 0; + + /* truncated packet? */ + if (np + length > snapend) { + truncated = 1; + length = snapend - np; + } + + putchar(' '); + + /* initial Sequence */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_SEQ) { + fputs("[!init SEQ]", stdout); + asn1_print(&elem); + return; + } + if (count < length) + printf("[%d extra after iSEQ]", length - count); + /* descend */ + length = elem.asnlen; + np = (u_char *)elem.data.raw; + /* Version (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[version!=INT]", stdout); + asn1_print(&elem); + return; + } + /* only handle version==0 */ + if (elem.data.integer != DEF_VERSION) { + printf("[version(%d)!=0]", elem.data.integer); + return; + } + length -= count; + np += count; + + /* Community (String) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_STR) { + fputs("[comm!=STR]", stdout); + asn1_print(&elem); + return; + } + /* default community */ + if (strncmp(elem.data.str, DEF_COMMUNITY, sizeof(DEF_COMMUNITY)-1)) + /* ! "public" */ + printf("C=%.*s ", elem.asnlen, elem.data.str); + length -= count; + np += count; + + /* PDU (Context) */ + if ((count = asn1_parse(np, length, &pdu)) < 0) + return; + if (pdu.type != BE_PDU) { + fputs("[no PDU]", stdout); + return; + } + if (count < length) + printf("[%d extra after PDU]", length - count); + asn1_print(&pdu); + /* descend into PDU */ + length = pdu.asnlen; + np = (u_char *)pdu.data.raw; + + switch (pdu.id) { + case TRAP: + trap_print(np, length); + break; + case GETREQ: + case GETNEXTREQ: + case GETRESP: + case SETREQ: + snmppdu_print(pdu.id, np, length); + break; + } + return; +} diff --git a/usr.sbin/tcpdump/tcpdump/print-sunrpc.c b/usr.sbin/tcpdump/tcpdump/print-sunrpc.c new file mode 100644 index 000000000000..ad28e93b46c0 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-sunrpc.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-sunrpc.c,v 1.1 92/06/02 11:36:37 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "interface.h" + +#include "addrtoname.h" +#include "extract.h" + +#if BYTE_ORDER == LITTLE_ENDIAN +/* + * Byte swap an array of n words. + * Assume input is word-aligned. + * Check that buffer is bounded by "snapend". + */ +static void +bswap(bp, n) + register u_long *bp; + register u_int n; +{ + register int nwords = ((char *)snapend - (char *)bp) / sizeof(*bp); + + if (nwords > n) + nwords = n; + for (; --nwords >= 0; ++bp) + *bp = ntohl(*bp); +} +#endif + +void +sunrpcrequest_print(rp, length, ip) + register struct rpc_msg *rp; + int length; + register struct ip *ip; +{ + register u_long *dp; + register u_char *ep = snapend; +#define TCHECK(p, l) if ((u_char *)(p) > ep - l) break + +#if BYTE_ORDER == LITTLE_ENDIAN + bswap((u_long *)rp, sizeof(*rp) / sizeof(u_long)); +#endif + + if (!nflag) + (void)printf("%s.%x > %s.sunrpc: %d", + ipaddr_string(&ip->ip_src), + rp->rm_xid, + ipaddr_string(&ip->ip_dst), + length); + else + (void)printf("%s.%x > %s.%x: %d", + ipaddr_string(&ip->ip_src), + rp->rm_xid, + ipaddr_string(&ip->ip_dst), + PMAPPORT, + length); + + switch (rp->rm_call.cb_proc) { + + case PMAPPROC_NULL: + printf(" null"); + break; + + case PMAPPROC_SET: + printf(" set"); + break; + + case PMAPPROC_UNSET: + printf(" unset"); + break; + + case PMAPPROC_GETPORT: + printf(" getport"); + break; + + case PMAPPROC_DUMP: + printf(" dump"); + break; + + case PMAPPROC_CALLIT: + printf(" callit"); + break; + + default: + printf(" proc #%d", rp->rm_call.cb_proc); + } + printf(" prog #%d", rp->rm_call.cb_prog); + putchar('\n'); +} + diff --git a/usr.sbin/tcpdump/tcpdump/print-tcp.c b/usr.sbin/tcpdump/tcpdump/print-tcp.c new file mode 100644 index 000000000000..9974b3c0d027 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-tcp.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-tcp.c,v 1.18 92/05/25 14:29:04 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef X10 +#include +#include +#endif + +#include "interface.h" +#include "addrtoname.h" + +#ifndef TCPOPT_WSCALE +#define TCPOPT_WSCALE 3 /* window scale factor (rfc1072) */ +#endif +#ifndef TCPOPT_SACKOK +#define TCPOPT_SACKOK 4 /* selective ack ok (rfc1072) */ +#endif +#ifndef TCPOPT_SACK +#define TCPOPT_SACK 5 /* selective ack (rfc1072) */ +#endif +#ifndef TCPOPT_ECHO +#define TCPOPT_ECHO 6 /* echo (rfc1072) */ +#endif +#ifndef TCPOPT_ECHOREPLY +#define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */ +#endif + +struct tha { + struct in_addr src; + struct in_addr dst; + u_int port; +}; + +struct tcp_seq_hash { + struct tcp_seq_hash *nxt; + struct tha addr; + tcp_seq seq; + tcp_seq ack; +}; + +#define TSEQ_HASHSIZE 919 + +static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE]; + + +void +tcp_print(tp, length, ip) + register struct tcphdr *tp; + register int length; + register struct ip *ip; +{ + register u_char flags; + register int hlen; + + if ((u_char *)(tp + 1) > snapend) { + printf("[|tcp]"); + return; + } + if (length < sizeof(struct tcphdr)) { + (void)printf("truncated-tcp %d", length); + return; + } + + NTOHS(tp->th_sport); + NTOHS(tp->th_dport); + NTOHL(tp->th_seq); + NTOHL(tp->th_ack); + NTOHS(tp->th_win); + NTOHS(tp->th_urp); + + (void)printf("%s.%s > %s.%s: ", + ipaddr_string(&ip->ip_src), tcpport_string(tp->th_sport), + ipaddr_string(&ip->ip_dst), tcpport_string(tp->th_dport)); + + if (!qflag) { +#ifdef X10 + register int be; + + if ((be = (tp->th_sport == X_TCP_BI_PORT || + tp->th_dport == X_TCP_BI_PORT)) || + tp->th_sport == X_TCP_LI_PORT || + tp->th_dport == X_TCP_LI_PORT) { + register XReq *xp = (XReq *)(tp + 1); + + x10_print(xp, length - sizeof(struct tcphdr), be); + return; + } +#endif + } + + if (qflag) { + (void)printf("tcp %d", length - tp->th_off * 4); + return; + } + if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) { + if (flags & TH_SYN) + putchar('S'); + if (flags & TH_FIN) + putchar('F'); + if (flags & TH_RST) + putchar('R'); + if (flags & TH_PUSH) + putchar('P'); + } else + putchar('.'); + + if (!Sflag && (flags & TH_ACK)) { + register struct tcp_seq_hash *th; + register int rev; + struct tha tha; + /* + * Find (or record) the initial sequence numbers for + * this conversation. (we pick an arbitrary + * collating order so there's only one entry for + * both directions). + */ + if (tp->th_sport < tp->th_dport || + (tp->th_sport == tp->th_dport && + ip->ip_src.s_addr < ip->ip_dst.s_addr)) { + tha.src = ip->ip_src, tha.dst = ip->ip_dst; + tha.port = tp->th_sport << 16 | tp->th_dport; + rev = 0; + } else { + tha.src = ip->ip_dst, tha.dst = ip->ip_src; + tha.port = tp->th_dport << 16 | tp->th_sport; + rev = 1; + } + + for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; + th->nxt; th = th->nxt) + if (!bcmp((char *)&tha, (char *)&th->addr, + sizeof(th->addr))) + break; + + if (!th->nxt || flags & TH_SYN) { + /* didn't find it or new conversation */ + if (!th->nxt) + th->nxt = (struct tcp_seq_hash *) + calloc(1, sizeof (*th)); + th->addr = tha; + if (rev) + th->ack = tp->th_seq, th->seq = tp->th_ack - 1; + else + th->seq = tp->th_seq, th->ack = tp->th_ack - 1; + } else { + if (rev) + tp->th_seq -= th->ack, tp->th_ack -= th->seq; + else + tp->th_seq -= th->seq, tp->th_ack -= th->ack; + } + } + hlen = tp->th_off * 4; + length -= hlen; + if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) + (void)printf(" %lu:%lu(%d)", tp->th_seq, tp->th_seq + length, + length); + if (flags & TH_ACK) + (void)printf(" ack %lu", tp->th_ack); + + (void)printf(" win %d", tp->th_win); + + if (flags & TH_URG) + (void)printf(" urg %d", tp->th_urp); + /* + * Handle any options. + */ + if ((hlen -= sizeof(struct tcphdr)) > 0) { + register u_char *cp = (u_char *)tp + sizeof(struct tcphdr); + int i; + char ch = '<'; + + putchar(' '); + while (--hlen >= 0) { + putchar(ch); + switch (*cp++) { + case TCPOPT_MAXSEG: + { + u_short mss; +#ifdef TCPDUMP_ALIGN + bcopy((char *)cp + 1, (char *)&mss, + sizeof(mss)); +#else + mss = *(u_short *)(cp + 1); +#endif + (void)printf("mss %d", ntohs(mss)); + if (*cp != 4) + (void)printf("[len %d]", *cp); + cp += 3; + hlen -= 3; + break; + } + case TCPOPT_EOL: + (void)printf("eol"); + break; + case TCPOPT_NOP: + (void)printf("nop"); + break; + case TCPOPT_WSCALE: + (void)printf("wscale %d", cp[1]); + if (*cp != 3) + (void)printf("[len %d]", *cp); + cp += 2; + hlen -= 2; + break; + case TCPOPT_SACKOK: + (void)printf("sackOK"); + if (*cp != 2) + (void)printf("[len %d]", *cp); + cp += 1; + hlen -= 1; + break; + case TCPOPT_ECHO: + { + u_long v; +#ifdef TCPDUMP_ALIGN + bcopy((char *)cp + 1, (char *)&v, + sizeof(v)); +#else + v = *(u_long *)(cp + 1); +#endif + (void)printf("echo %lu", v); + if (*cp != 6) + (void)printf("[len %d]", *cp); + cp += 5; + hlen -= 5; + break; + } + case TCPOPT_ECHOREPLY: + { + u_long v; +#ifdef TCPDUMP_ALIGN + bcopy((char *)cp + 1, (char *)&v, + sizeof(v)); +#else + v = *(u_long *)(cp + 1); +#endif + (void)printf("echoreply %lu", v); + if (*cp != 6) + (void)printf("[len %d]", *cp); + cp += 5; + hlen -= 5; + break; + } + default: + (void)printf("opt-%d:", cp[-1]); + for (i = *cp++ - 2, hlen -= i + 1; i > 0; --i) + (void)printf("%02x", *cp++); + break; + } + ch = ','; + } + putchar('>'); + } +} + diff --git a/usr.sbin/tcpdump/tcpdump/print-tftp.c b/usr.sbin/tcpdump/tcpdump/print-tftp.c new file mode 100644 index 000000000000..3f8f079a6106 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-tftp.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print trivial file transfer protocol packets. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-tftp.c,v 1.13 91/04/19 10:46:57 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include + +#include "interface.h" +#include +#include + +struct int2str { + int code; + char *str; +}; + +/* op code to string mapping */ +static struct int2str op2str[] = { + RRQ, "RRQ", /* read request */ + WRQ, "WRQ", /* write request */ + DATA, "DATA", /* data packet */ + ACK, "ACK", /* acknowledgement */ + ERROR, "ERROR", /* error code */ + 0, 0 +}; + +/* error code to string mapping */ +static struct int2str err2str[] = { + EUNDEF, "EUNDEF", /* not defined */ + ENOTFOUND, "ENOTFOUND", /* file not found */ + EACCESS, "EACCESS", /* access violation */ + ENOSPACE, "ENOSPACE", /* disk full or allocation exceeded *? + EBADOP, "EBADOP", /* illegal TFTP operation */ + EBADID, "EBADID", /* unknown transfer ID */ + EEXISTS, "EEXISTS", /* file already exists */ + ENOUSER, "ENOUSER", /* no such user */ + 0, 0 +}; + +/* + * Print trivial file transfer program requests + */ +void +tftp_print(tp, length) + register struct tftphdr *tp; + int length; +{ + register struct int2str *ts; + register u_char *ep; +#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc + static char tstr[] = " [|tftp]"; + + /* 'ep' points to the end of avaible data. */ + ep = (u_char *)snapend; + + /* Print length */ + printf(" %d", length); + + /* Print tftp request type */ + TCHECK(tp->th_opcode, sizeof(tp->th_opcode)); + NTOHS(tp->th_opcode); + putchar(' '); + for (ts = op2str; ts->str; ++ts) + if (ts->code == tp->th_opcode) { + fputs(ts->str, stdout); + break; + } + if (ts->str == 0) { + /* Bail if bogus opcode */ + printf("tftp-#%d", tp->th_opcode); + return; + } + + switch (tp->th_opcode) { + + case RRQ: + case WRQ: + putchar(' '); + if (printfn((u_char *)tp->th_stuff, ep)) { + fputs(&tstr[1], stdout); + return; + } + break; + + case DATA: + TCHECK(tp->th_block, sizeof(tp->th_block)); + NTOHS(tp->th_block); + printf(" block %d", tp->th_block); + break; + + case ACK: + break; + + case ERROR: + /* Print error code string */ + TCHECK(tp->th_code, sizeof(tp->th_code)); + NTOHS(tp->th_code); + putchar(' '); + for (ts = err2str; ts->str; ++ts) + if (ts->code == tp->th_code) { + fputs(ts->str, stdout); + break; + } + if (ts->str == 0) + printf("tftp-err-#%d", tp->th_code); + + /* Print error message string */ + putchar(' '); + if (printfn((u_char *)tp->th_data, ep)) { + fputs(&tstr[1], stdout); + return; + } + break; + + default: + /* We shouldn't get here */ + printf("(unknown #%d)", tp->th_opcode); + break; + } + return; +trunc: + fputs(tstr, stdout); +#undef TCHECK +} diff --git a/usr.sbin/tcpdump/tcpdump/print-udp.c b/usr.sbin/tcpdump/tcpdump/print-udp.c new file mode 100644 index 000000000000..cd5180890219 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/print-udp.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: print-udp.c,v 1.26 92/05/22 19:43:17 leres Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +/* These must come after interface.h for BSD. */ +#if BSD >= 199006 +#include +#include +#endif +#include + +#include "addrtoname.h" +#include "appletalk.h" + +#include "bootp.h" + +/* XXX probably should use getservbyname() and cache answers */ +#define TFTP_PORT 69 /*XXX*/ +#define SUNRPC_PORT 111 /*XXX*/ +#define SNMP_PORT 161 /*XXX*/ +#define NTP_PORT 123 /*XXX*/ +#define SNMPTRAP_PORT 162 /*XXX*/ +#define RIP_PORT 520 /*XXX*/ + +void +udp_print(up, length, ip) + register struct udphdr *up; + int length; + register struct ip *ip; +{ + register u_char *cp = (u_char *)(up + 1); + + if (cp > snapend) { + printf("[|udp]"); + return; + } + if (length < sizeof(struct udphdr)) { + (void)printf(" truncated-udp %d", length); + return; + } + length -= sizeof(struct udphdr); + + NTOHS(up->uh_sport); + NTOHS(up->uh_dport); + NTOHS(up->uh_ulen); + + if (! qflag) { + register struct rpc_msg *rp; + enum msg_type direction; + + rp = (struct rpc_msg *)(up + 1); + direction = (enum msg_type)ntohl(rp->rm_direction); + if (up->uh_dport == NFS_PORT && direction == CALL) { + nfsreq_print(rp, length, ip); + return; + } + else if (up->uh_sport == NFS_PORT && direction == REPLY) { + nfsreply_print(rp, length, ip); + return; + } +#ifdef notdef + else if (up->uh_dport == SUNRPC_PORT && direction == CALL) { + sunrpcrequest_print(rp, length, ip); + return; + } +#endif + else if (cp[2] == 2 && (atalk_port(up->uh_sport) || + atalk_port(up->uh_dport))) { + ddp_print((struct atDDP *)(&cp[3]), length - 3); + return; + } + } + (void)printf("%s.%s > %s.%s:", + ipaddr_string(&ip->ip_src), udpport_string(up->uh_sport), + ipaddr_string(&ip->ip_dst), udpport_string(up->uh_dport)); + + if (!qflag) { +#define ISPORT(p) (up->uh_dport == (p) || up->uh_sport == (p)) + if (ISPORT(NAMESERVER_PORT)) + ns_print((HEADER *)(up + 1), length); + else if (ISPORT(TFTP_PORT)) + tftp_print((struct tftphdr *)(up + 1), length); + else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS)) + bootp_print((struct bootp *)(up + 1), length, + up->uh_sport, up->uh_dport); + else if (up->uh_dport == RIP_PORT) + rip_print((u_char *)(up + 1), length); + else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT)) + snmp_print((u_char *)(up + 1), length); + else if (ISPORT(NTP_PORT)) + ntp_print((struct ntpdata *)(up + 1), length); + else + (void)printf(" udp %d", up->uh_ulen - sizeof(*up)); +#undef ISPORT + } else + (void)printf(" udp %d", up->uh_ulen - sizeof(*up)); +} diff --git a/usr.sbin/tcpdump/tcpdump/savefile.c b/usr.sbin/tcpdump/tcpdump/savefile.c new file mode 100644 index 000000000000..79bb9e8afc68 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/savefile.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 1990,1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#)$Header: savefile.c,v 1.27 92/01/26 21:29:26 mccanne Exp $ (LBL)"; +#endif + +/* + * savefile.c - supports offline use of tcpdump + * Extraction/creation by Jeffrey Mogul, DECWRL + * Modified by Steve McCanne, LBL. + * + * Used to save the received packet headers, after filtering, to + * a file, and then read them later. + * The first record in the file contains saved values for the machine + * dependent values so we can print the dump file on any architecture. + */ + +#include +#include +#include +#include + +#include "version.h" +#include "savefile.h" + +#define TCPDUMP_MAGIC 0xa1b2c3d4 + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are longs so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + */ +struct file_header { + u_long magic; + u_short version_major; + u_short version_minor; + long thiszone; /* gmt to local correction */ + u_long sigfigs; /* accuracy of timestamps */ + u_long snaplen; /* max length saved portion of each pkt */ + u_long linktype; +}; + +int sf_swapped; + +FILE *sf_readfile; +FILE *sf_writefile; + +static int +sf_write_header(fp, linktype, thiszone, snaplen, precision) + FILE *fp; + int linktype; + int thiszone; + int snaplen; + int precision; +{ + struct file_header hdr; + + hdr.magic = TCPDUMP_MAGIC; + hdr.version_major = VERSION_MAJOR; + hdr.version_minor = VERSION_MINOR; + + hdr.thiszone = thiszone; + hdr.snaplen = snaplen; + hdr.sigfigs = precision; + hdr.linktype = linktype; + + if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) + return -1; + + return 0; +} + +static void +swap_hdr(hp) + struct file_header *hp; +{ + hp->version_major = SWAPSHORT(hp->version_major); + hp->version_minor = SWAPSHORT(hp->version_minor); + hp->thiszone = SWAPLONG(hp->thiszone); + hp->sigfigs = SWAPLONG(hp->sigfigs); + hp->snaplen = SWAPLONG(hp->snaplen); + hp->linktype = SWAPLONG(hp->linktype); +} + +int +sf_read_init(fname, linktypep, thiszonep, snaplenp, precision) + char *fname; + int *linktypep, *thiszonep, *snaplenp, *precision; +{ + register FILE *fp; + struct file_header hdr; + + if (fname[0] == '-' && fname[1] == '\0') + fp = stdin; + else { + fp = fopen(fname, "r"); + if (fp == 0) { + (void) fprintf(stderr, "tcpdump: fopen: "); + perror(fname); + exit(1); + } + } + if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { + (void) fprintf(stderr, "tcpdump: fread: "); + perror(fname); + exit(1); + } + if (hdr.magic != TCPDUMP_MAGIC) { + if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) + return SFERR_BADF; + sf_swapped = 1; + swap_hdr(&hdr); + } + if (hdr.version_major < VERSION_MAJOR) + return SFERR_BADVERSION; + + *thiszonep = hdr.thiszone; + *snaplenp = hdr.snaplen; + *linktypep = hdr.linktype; + *precision = hdr.sigfigs; + + sf_readfile = fp; + + return 0; +} + +/* + * Print out packets stored in the file initilized by sf_read_init(). + * If cnt >= 0, return after 'cnt' packets, otherwise continue until eof. + */ +int +sf_read(filtp, cnt, snaplen, printit) + struct bpf_program *filtp; + int cnt, snaplen; + void (*printit)(); +{ + struct packet_header h; + u_char *buf; + struct bpf_insn *fcode = filtp->bf_insns; + int status = 0; + + buf = (u_char *)malloc(snaplen); + + while (status == 0) { + status = sf_next_packet(&h, buf, snaplen); + + if (status) + break; + /* + * XXX It's possible (and likely) for us to screw up the + * network layer alignment when we pass down packets from + * this point (ip_print deals by copying the ip header + * to an aligned buffer). There doesn't seem to be a + * clean way to fix this. We could compute an offset + * from the link type (which would have to be passed in), + * but that only works for fixed size headers. + */ + if (bpf_filter(fcode, buf, h.len, h.caplen)) { + if (cnt >= 0 && --cnt < 0) + break; + (*printit)(buf, &h.ts, h.len, h.caplen); + } + } + + if (status == SFERR_EOF) + /* treat EOF's as okay status */ + status = 0; + + free((char *)buf); + return status; +} + +/* + * Read sf_readfile and return the next packet. Return the header in hdr + * and the contents in buf. Return 0 on success, SFERR_EOF if there were + * no more packets, and SFERR_TRUNC if a partial packet was encountered. + */ +int +sf_next_packet(hdr, buf, buflen) + struct packet_header *hdr; + u_char *buf; + int buflen; +{ + FILE *fp = sf_readfile; + + /* read the stamp */ + if (fread((char *)hdr, sizeof(struct packet_header), 1, fp) != 1) { + /* probably an EOF, though could be a truncated packet */ + return SFERR_EOF; + } + + if (sf_swapped) { + /* these were written in opposite byte order */ + hdr->caplen = SWAPLONG(hdr->caplen); + hdr->len = SWAPLONG(hdr->len); + hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec); + hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec); + } + + if (hdr->caplen > buflen) + return SFERR_BADF; + + /* read the packet itself */ + + if (fread((char *)buf, hdr->caplen, 1, fp) != 1) + return SFERR_TRUNC; + + return 0; +} + +/* + * Initialize so that sf_write() will output to the file named 'fname'. + */ +void +sf_write_init(fname, linktype, thiszone, snaplen, precision) + char *fname; + int linktype; + int thiszone; + int snaplen; + int precision; +{ + if (fname[0] == '-' && fname[1] == '\0') + sf_writefile = stdout; + else { + sf_writefile = fopen(fname, "w"); + if (sf_writefile == 0) { + (void) fprintf(stderr, "tcpdump: fopen: "); + perror(fname); + exit(1); + } + } + (void)sf_write_header(sf_writefile, + linktype, thiszone, snaplen, precision); +} + +/* + * Output a packet to the intialized dump file. + */ +void +sf_write(sp, tvp, length, caplen) + u_char *sp; + struct timeval *tvp; + int length; + int caplen; +{ + struct packet_header h; + + h.ts.tv_sec = tvp->tv_sec; + h.ts.tv_usec = tvp->tv_usec; + h.len = length; + h.caplen = caplen; + + (void)fwrite((char *)&h, sizeof h, 1, sf_writefile); + (void)fwrite((char *)sp, caplen, 1, sf_writefile); +} + +void +sf_err(code) + int code; +{ + switch (code) { + case SFERR_BADVERSION: + error("archaic file format"); + /* NOTREACHED */ + + case SFERR_BADF: + error("bad dump file format"); + /* NOTREACHED */ + + case SFERR_TRUNC: + error("truncated dump file"); + /* NOTREACHED */ + + case SFERR_EOF: + error("EOF reading dump file"); + /* NOTREACHED */ + + default: + error("unknown dump file error code in sf_err()"); + /* NOTREACHED */ + } + abort(); +} diff --git a/usr.sbin/tcpdump/tcpdump/savefile.h b/usr.sbin/tcpdump/tcpdump/savefile.h new file mode 100644 index 000000000000..a5082f9fb276 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/savefile.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Header: savefile.h,v 1.10 90/12/17 13:48:58 mccanne Exp $ + * + * Header for offline storage info. + * Extraction/creation by Jeffrey Mogul, DECWRL. + * + * Used to save the received packet headers, after filtering, to + * a file, and then read them later. + */ + +/* + * Each packet in the dump file is prepended with this generic header. + * This gets around the problem of different headers for different + * packet interfaces. + */ +struct packet_header { + struct timeval ts; /* time stamp */ + u_long len; /* length this packet (off wire) */ + u_long caplen; /* length of portion present */ +}; + +/* true if the contents of the savefile being read are byte-swapped */ +extern int sf_swapped; + +/* macros for when sf_swapped is true: */ +/* + * We use the "receiver-makes-right" approach to byte order, + * because time is at a premium when we are writing the file. + * In other words, the file_header and packet_header records + * are written in host byte order. + * Note that the packets are always written in network byte order. + * + * ntoh[ls] aren't sufficient because we might need to swap on a big-endian + * machine (if the file was written in little-end order). + */ +#define SWAPLONG(y) \ +((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ + ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) + + +extern FILE *sf_readfile; /* dump file being read from */ +extern FILE *sf_writefile; /* dump file being written to */ + +int sf_read_init(); +int sf_read(); +int sf_next_packet(); +void sf_write_init(); +void sf_write(); +void sf_err(); + +#define SFERR_TRUNC 1 +#define SFERR_BADVERSION 2 +#define SFERR_BADF 3 +#define SFERR_EOF 4 /* not really an error, just a status */ + diff --git a/usr.sbin/tcpdump/tcpdump/tcpdump.1 b/usr.sbin/tcpdump/tcpdump/tcpdump.1 new file mode 100644 index 000000000000..2406319e0ffc --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/tcpdump.1 @@ -0,0 +1,1067 @@ +.\" @(#) $Header: tcpdump.1,v 1.40 92/01/29 16:56:02 mccanne Exp $ (LBL) +.\" +.\" Copyright (c) 1988, 1989, 1990, 1991, 1992 +.\" The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that: (1) source code distributions +.\" retain the above copyright notice and this paragraph in its entirety, (2) +.\" distributions including binary code include the above copyright notice and +.\" this paragraph in its entirety in the documentation or other materials +.\" provided with the distribution, and (3) all advertising materials mentioning +.\" features or use of this software display the following acknowledgement: +.\" ``This product includes software developed by the University of California, +.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of +.\" the University nor the names of its contributors may be used to endorse +.\" or promote products derived from this software without specific prior +.\" written permission. +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.TH TCPDUMP 1 "4 Jan 1992" +.SH NAME +tcpdump \- dump traffic on a network +.SH SYNOPSIS +.na +.B tcpdump +[ +.B \-deflnNOpqStvx +] [ +.B \-c +.I count +] [ +.B \-F +.I file +] +.br +.ti +8 +[ +.B \-i +.I interface +] [ +.B \-r +.I file +] +[ +.B \-s +.I snaplen +] +.br +.ti +8 +[ +.B \-w +.I file +] +.I expression +.br +.ad +.SH DESCRIPTION +.LP +\fITcpdump\fP prints out the headers of packets on a network interface +that match the boolean \fIexpression\fP. +.B Under SunOS: +You must be root to invoke \fItcpdump\fP or it must be installed +setuid to root. +.B Under Ultrix: +Any user can invoke \fItcpdump\fP once the super-user has enabled +promiscuous-mode operation using +.IR pfconfig (8). +.B Under BSD: +Access is controlled by the permissions on +.I /dev/bpf0, +etc. +.SH OPTIONS +.TP +.B \-c +Exit after receiving \fIcount\fP packets. +.TP +.B \-d +Dump the compiled packet-matching code to standard output and stop. +.TP +.B \-e +Print the link-level header on each dump line. +.TP +.B \-f +Print `foreign' internet addresses numerically rather than symbolically +(this option is intended to get around serious brain damage in +Sun's yp server \(em usually it hangs forever translating non-local +internet numbers). +.TP +.B \-F +Use \fIfile\fP as input for the filter expression. +An additional expression given on the command line is ignored. +.TP +.B \-i +Listen on \fIinterface\fP. +If unspecified, \fItcpdump\fP searches the system interface list for the +lowest numbered, configured up interface (excluding loopback). +Ties are broken by choosing the earliest match. +.TP +.B \-l +Make stdout line buffered. Useful if you want to see the data +while capturing it. E.g., +.br +``tcpdump\ \ \-l\ \ |\ \ tee dat'' or +``tcpdump\ \ \-l \ \ > dat\ \ &\ \ tail\ \ \-f\ \ dat''. +.TP +.B \-n +Don't convert addresses (i.e., host addresses, port numbers, etc.) to names. +.TP +.B \-N +Don't print domain name qualification of host names. E.g., +if you give this flag then \fItcpdump\fP will print ``nic'' +instead of ``nic.ddn.mil''. +.TP +.B \-O +Do not run the packet-matching code optimizer. This is useful only +if you suspect a bug in the optimizer. +.TP +.B \-p +\fIDon't\fP put the interface +into promiscuous mode. Note that the interface might be in promiscuous +for some other reason; hence, `-p' cannot be used as an abbreviation for +`ether host {localhost} or broadcast'. +.TP +.B \-q +Quick (quiet?) output. Print less protocol information so output +lines are shorter. +.TP +.B \-r +Read packets from \fIfile\fR (which was created with the -w option). +Standard input is used if \fIfile\fR is ``-''. +.TP +.B \-s +Snarf \fIsnaplen\fP bytes of data from each packet rather than the +default of 68 (with NIT, the minimum is actually 96). +68 bytes is adequate for IP, ICMP, TCP +and UDP but may truncate protocol information from name server and NFS +packets (see below). Packets truncated because of a limited snapshot +are indicated in the output with ``[|\fIproto\fP]'', where \fIproto\fP +is the name of the protocol level at which the truncation has occured. +Note that taking larger snapshots both increases +the amount of time it takes to process packets and, effectively, +decreases the amount of packet buffering. This may cause packets to be +lost. You should limit \fIsnaplen\fP to the smallest number that will +capture the protocol information you're interested in. +.TP +.B \-S +Print absolute, rather than relative, TCP sequence numbers. +.TP +.B \-t +\fIDon't\fP print a timestamp on each dump line. +.TP +.B \-tt +Print an unformatted timestamp on each dump line. +.TP +.B \-v +(Slightly more) verbose output. For example, the time to live +and type of service information in an IP packet is printed. +.TP +.B \-w +Write the raw packets to \fIfile\fR rather than parsing and printing +them out. They can later be printed with the \-r option. +Standard output is used if \fIfile\fR is ``-''. +.TP +.B \-x +Print each packet (minus its link level header) in hex. +The smaller of the entire packet or +.I snaplen +bytes will be printed. +.IP "\fI expression\fP" +.RS +selects which packets will be dumped. If no \fIexpression\fP +is given, all packets on the net will be dumped. Otherwise, +only packets for which \fIexpression\fP is `true' will be dumped. +.LP +The \fIexpression\fP consists of one or more +.I primitives. +Primitives usually consist of an +.I id +(name or number) preceded by one or more qualifiers. There are three +different kinds of qualifier: +.IP \fItype\fP +qualifiers say what kind of thing the id name or number refers to. +Possible types are +.BR host , +.B net +and +.BR port . +E.g., `host foo', `net 128.3', `port 20'. If there is no type +qualifier, +.B host +is assumed. +.IP \fIdir\fP +qualifiers specify a particular tranfer direction to and/or from +.I id. +Possible directions are +.BR src , +.BR dst , +.B "src or dst" +and +.BR "src and dst" . +E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'. If +there is no dir qualifier, +.B "src or dst" +is assumed. +.IP \fIproto\fP +qualifiers restrict the match to a particular protocol. Possible +protos are: +.BR ether , +.BR ip , +.BR arp , +.BR rarp , +.B tcp +and +.BR udp . +E.g., `ether src foo', `arp net 128.3', `tcp port 21'. If there is +no proto qualifier, all protocols consistent with the type are +assumed. E.g., `src foo' means `(ip or arp or rarp) src foo' +(except the latter is not legal syntax), `net bar' means `(ip or +arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'. +.LP +In addition to the above, there are some special `primitive' keywords +that don't follow the pattern: +.BR gateway , +.BR broadcast , +.BR less , +.B greater +and arithmetic expressions. All of these are described below. +.LP +More complex filter expressions are built up by using the words +.BR and , +.B or +and +.B not +to combine primitives. E.g., `host foo and not port ftp and not port ftp-data'. +To save typing, identical qualifier lists can be omitted. E.g., +`tcp dst port ftp or ftp-data or domain' is exactly the same as +`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'. +.LP +Allowable primitives are: +.IP "\fBdst host \fIhost\fR" +True if the IP destination field of the packet is \fIhost\fP, +which may be either an address or a name. +.IP "\fBsrc host \fIhost\fR" +True if the IP source field of the packet is \fIhost\fP. +.IP "\fBhost \fIhost\fP +True if either the IP source or destination of the packet is \fIhost\fP. +Any of the above host expressions can be prepended with the keywords, +\fBip\fP, \fBarp\fP, or \fBrarp\fP as in: +.in +.5i +.nf +\fBip host \fIhost\fR +.fi +.in -.5i +which is equivalent to: +.in +.5i +.nf +\fBether proto \fI\\ip\fB and host \fIhost\fR +.fi +.in -.5i +If \fIhost\fR is a name with multiple IP addresses, each address will +be checked for a match. +.IP "\fBether dst \fIehost\fP +True if the ethernet destination address is \fIehost\fP. \fIEhost\fP +may be either a name from /etc/ethers or a number (see +.IR ethers (3N) +for numeric format). +.IP "\fBether src \fIehost\fP +True if the ethernet source address is \fIehost\fP. +.IP "\fBether host \fIehost\fP +True if either the ethernet source or destination address is \fIehost\fP. +.IP "\fBgateway\fP \fIhost\fP +True if the packet used \fIhost\fP as a gateway. I.e., the ethernet +source or destination address was \fIhost\fP but neither the IP source +nor the IP destination was \fIhost\fP. \fIHost\fP must be a name and +must be found in both /etc/hosts and /etc/ethers. (An equivalent +expression is +.in +.5i +.nf +\fBether host \fIehost \fBand not host \fIhost\fR +.fi +.in -.5i +which can be used with either names or numbers for \fIhost / ehost\fP.) +.IP "\fBdst net \fInet\fR" +True if the IP destination address of the packet has a network +number of \fInet\fP, which may be either an address or a name. +.IP "\fBsrc net \fInet\fR" +True if the IP source address of the packet has a network +number of \fInet\fP. +.IP "\fBnet \fInet\fR" +True if either the IP source or destination address of the packet has a network +number of \fInet\fP. +.IP "\fBdst port \fIport\fR" +True if the packet is ip/tcp or ip/udp and has a +destination port value of \fIport\fP. +The \fIport\fP can be a number or a name used in /etc/services (see +.IR tcp (4P) +and +.IR udp (4P)). +If a name is used, both the port +number and protocol are checked. If a number or ambiguous name is used, +only the port number is checked (e.g., \fBdst port 513\fR will print both +tcp/login traffic and udp/who traffic, and \fBport domain\fR will print +both tcp/domain and udp/domain traffic). +.IP "\fBsrc port \fIport\fR" +True if the packet has a source port value of \fIport\fP. +.IP "\fBport \fIport\fR" +True if either the source or destination port of the packet is \fIport\fP. +Any of the above port expressions can be prepended with the keywords, +\fBtcp\fP or \fBudp\fP, as in: +.in +.5i +.nf +\fBtcp src port \fIport\fR +.fi +.in -.5i +which matches only tcp packets. +.IP "\fBless \fIlength\fR" +True if the packet has a length less than or equal to \fIlength\fP. +This is equivalent to: +.in +.5i +.nf +\fBlen <= \fIlength\fP. +.fi +.in -.5i +.IP "\fBgreater \fIlength\fR" +True if the packet has a length greater than or equal to \fIlength\fP. +This is equivalent to: +.in +.5i +.nf +\fBlen >= \fIlength\fP. +.fi +.in -.5i +.IP "\fBip proto \fIprotocol\fR" +True if the packet is an ip packet (see +.IR ip (4P)) +of protocol type \fIprotocol\fP. +\fIProtocol\fP can be a number or one of the names +\fIicmp\fP, \fIudp\fP, \fInd\fP, or \fItcp\fP. +Note that the identifiers \fItcp\fP, \fIudp\fP, and \fIicmp\fP are also +keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell. +.IP "\fBether broadcast\fR" +True if the packet is an ethernet broadcast packet. The \fIether\fP +keyword is optional. +.IP "\fBip broadcast\fR" +True if the packet is an IP broadcast packet. It checks for both +the all-zeroes and all-ones broadcast conventions, and looks up +the local subnet mask. +.IP "\fBether multicast\fR" +True if the packet is an ethernet multicast packet. The \fIether\fP +keyword is optional. +This is shorthand for `\fBether[0] & 1 != 0\fP'. +.IP "\fBip multicast\fR" +True if the packet is an IP multicast packet. +.IP "\fBether proto \fIprotocol\fR" +True if the packet is of ether type \fIprotocol\fR. +\fIProtocol\fP can be a number or a name like +\fIip\fP, \fIarp\fP, or \fIrarp\fP. +Note these identifiers are also keywords +and must be escaped via backslash (\\). +.IP "\fBip\fR, \fBarp\fR, \fBrarp\fR" +Abbreviations for: +.in +.5i +.nf +\fBether proto \fIp\fR +.fi +.in -.5i +where \fIp\fR is one of the above protocols. +.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR" +Abbreviations for: +.in +.5i +.nf +\fBip proto \fIp\fR +.fi +.in -.5i +where \fIp\fR is one of the above protocols. +.IP "\fIexpr relop expr\fR" +True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =, !=, +and \fIexpr\fR is an arithmetic expression composed of integer constants +(expressed in standard C syntax), the normal binary operators +[+, -, *, /, &, |], a length operator, and special packet data accessors. +To access +data inside the packet, use the following syntax: +.in +.5i +.nf +\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR +.fi +.in -.5i +\fIProto\fR is one of \fBether, ip, arp, rarp, tcp, udp, \fRor \fBicmp\fR, and +indicates the protocol layer for the index operation. +The byte offset, relative to the indicated protocol layer, is +given by \fIexpr\fR. +\fISize\fR is optional and indicates the number of bytes in the +field of interest; it can be either one, two, or four, and defaults to one. +The length operator, indicated by the keyword \fBlen\fP, gives the +length of the packet. + +For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic. +The expression `\fBip[0] & 0xf != 5\fP' +catches all IP packets with options. The expression +`\fBip[2:2] & 0x1fff = 0\fP' +catches only unfragmented datagrams and frag zero of fragmented datagrams. +This check is implicitly applied to the \fBtcp\fP and \fBudp\fP +index opertations. +For instance, \fBtcp[0]\fP always means the first +byte of the TCP \fIheader\fP, and never means the first byte of an +intervening fragment. +.LP +Primitives may be combined using: +.IP +A parenthesized group of primitives and operators +(parentheses are special to the Shell and must be escaped). +.IP +Negation (`\fB!\fP' or `\fBnot\fP'). +.IP +Concatenation (`\fBand\fP'). +.IP +Alternation (`\fBor\fP'). +.LP +Negation has highest precedence. +Alternation and concatenation have equal precedence and associate +left to right. Note that explicit \fBand\fR tokens, not juxtaposition, +are now required for concatenation. +.LP +If an identifier is given without a keyword, the most recent keyword +is assumed. +For example, +.in +.5i +.nf +\fBnot host vs and ace\fR +.fi +.in -.5i +is short for +.in +.5i +.nf +\fBnot host vs and host ace\fR +.fi +.in -.5i +which should not be confused with +.in +.5i +.nf +\fBnot ( host vs or ace )\fR +.fi +.in -.5i +.LP +Expression arguments can be passed to tcpdump as either a single argument +or as multiple arguments, whichever is more convenient. +Generally, if the expression contains Shell metacharacters, it is +easier to pass it as a single, quoted argument. +Multiple arguments are concatenated with spaces before being parsed. +.SH EXAMPLES +.LP +To print all packets arriving at or departing from \fIsundown\fP: +.RS +.nf +\fBtcpdump host sundown\fP +.fi +.RE +.LP +To print traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR: +.RS +.nf +\fBtcpdump host helios and \\( hot or ace \\)\fP +.fi +.RE +.LP +To print all IP packets between \fIace\fR and any host except \fIhelios\fR: +.RS +.nf +\fBtcpdump ip host ace and not helios\fP +.fi +.RE +.LP +To print all traffic between local hosts and hosts at Berkeley: +.RS +.nf +.B +tcpdump net ucb-ether +.fi +.RE +.LP +To print all ftp traffic through internet gateway \fIsnup\fP: +(note that the expression is quoted to prevent the shell from +(mis-)interpreting the parentheses): +.RS +.nf +.B +tcpdump 'gateway snup and (port ftp or ftp-data)' +.fi +.RE +.LP +To print traffic neither sourced from nor destined for local hosts +(if you gateway to one other net, this stuff should never make it +onto your local net). +.RS +.nf +.B +tcpdump ip and not net \fIlocalnet\fP +.fi +.RE +.LP +To print the start and end packets (the SYN and FIN packets) of each +TCP conversation that involves a non-local host. +.RS +.nf +.B +tcpdump 'tcp[13] & 3 != 0 and not src and dst net \fIlocalnet\fP' +.fi +.RE +.LP +To print IP packets longer than 576 bytes sent through gateway \fIsnup\fP: +.RS +.nf +.B +tcpdump 'gateway snup and ip[2:2] > 576' +.fi +.RE +.LP +To print IP broadcast or multicast packets that were +.I not +sent via ethernet broadcast or multicast: +.RS +.nf +.B +tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224' +.fi +.RE +.LP +To print all ICMP packets that are not echo requests/replies (i.e., not +ping packets): +.RS +.nf +.B +tcpdump 'icmp[0] != 8 and icmp[0] != 0" +.fi +.RE +.SH OUTPUT FORMAT +.LP +The output of \fItcpdump\fP is protocol dependent. The following +gives a brief description and examples of most of the formats. +.de HD +.sp 1.5 +.B +.. +.HD +Link Level Headers +.LP +If the '-e' option is given, the link level header is printed out. +On ethernets, the source and destination addresses, protocol, +and packet length are printed. +.LP +\fI(N.B.: The following description assumes familiarity with +the SLIP compression algorithm described in RFC-1144.)\fP +.LP +On SLIP links, a direction indicator (``I'' for inbound, ``O'' for outbound), +packet type, and compression information are printed out. +The packet type is printed first. +The three types are \fIip\fP, \fIutcp\fP, and \fIctcp\fP. +No further link information is printed for \fIip\fR packets. +For TCP packets, the connection identifier is printed following the type. +If the packet is compressed, its encoded header is printed out. +The special cases are printed out as +\fB*S+\fIn\fR and \fB*SA+\fIn\fR, where \fIn\fR is the amount by which +the sequence number (or sequence number and ack) has changed. +If it is not a special case, +zero or more changes are printed. +A change is indicated by U (urgent pointer), W (window), A (ack), +S (sequence number), and I (packet ID), followed by a delta (+n or -n), +or a new value (=n). +Finally, the amount of data in the packet and compressed header length +are printed. +.LP +For example, the following line shows an outbound compressed TCP packet, +with an implicit connection identifier; the ack has changed by 6, +the sequence number by 49, and the packet ID by 6; there are 3 bytes of +data and 6 bytes of compressed header: +.RS +.nf +\fBO ctcp * A+6 S+49 I+6 3 (6)\fP +.fi +.RE +.HD +ARP/RARP Packets +.LP +Arp/rarp output shows the type of request and its arguments. The +format is intended to be self explanatory. +Here is a short sample taken from the start of an `rlogin' from +host \fIrtsg\fP to host \fIcsam\fP: +.RS +.nf +.sp .5 +\f(CWarp who-has csam tell rtsg +arp reply csam is-at CSAM\fP +.sp .5 +.fi +.RE +The first line says that rtsg sent an arp packet asking +for the ethernet address of internet host csam. Csam +replies with its ethernet address (in this example, ethernet addresses +are in caps and internet addresses in lower case). +.LP +This would look less redundant if we had done \fBtcpdump \-n\fP: +.RS +.nf +.sp .5 +\f(CWarp who-has 128.3.254.6 tell 128.3.254.68 +arp reply 128.3.254.6 is-at 02:07:01:00:01:c4\fP +.fi +.RE +.LP +If we had done \fBtcpdump \-e\fP, the fact that the first packet is +broadcast and the second is point-to-point would be visible: +.RS +.nf +.sp .5 +\f(CWRTSG Broadcast 0806 64: arp who-has csam tell rtsg +CSAM RTSG 0806 64: arp reply csam is-at CSAM\fP +.sp .5 +.fi +.RE +For the first packet this says the ethernet source address is RTSG, the +destination is the broadcast address, the type field +contained hex 0806 (type ETHER_ARP) and the total length was 64 bytes. +.HD +TCP Packets +.LP +\fI(N.B.:The following description assumes familiarity with +the TCP protocol described in RFC-793. If you are not familiar +with the protocol, neither this description nor tcpdump will +be of much use to you.)\fP +.LP +The general format of a tcp protocol line is: +.RS +.nf +.sp .5 +\fIsrc > dst: flags data-seqno ack window urgent options\fP +.sp .5 +.fi +.RE +\fISrc\fP and \fIdst\fP are the source and destination IP +addresses and ports. \fIFlags\fP are some combination of S (SYN), +F (FIN), P (PUSH) or R (RST) or a single `.' (no flags). +\fIData-seqno\fP describes the portion of sequence space covered +by the data in this packet (see example below). +\fIAck\fP is sequence number of the next data expected the other +direction on this connection. +\fIWindow\fP is the number of bytes of receive buffer space available +the other direction on this connection. +\fIUrg\fP indicates there is `urgent' data in the packet. +\fIOptions\fP are tcp options enclosed in angle brackets (e.g., ). +.LP +\fISrc, dst\fP and \fIflags\fP are always present. The other fields +depend on the contents of the packet's tcp protocol header and +are output only if appropriate. +.LP +Here is the opening portion of an rlogin from host \fIrtsg\fP to +host \fIcsam\fP. +.RS +.nf +.sp .5 +\s-2\f(CWrtsg.1023 > csam.login: S 768512:768512(0) win 4096 +csam.login > rtsg.1023: S 947648:947648(0) ack 768513 win 4096 +rtsg.1023 > csam.login: . ack 1 win 4096 +rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096 +csam.login > rtsg.1023: . ack 2 win 4096 +rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096 +csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077 +csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1 +csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1\fP\s+2 +.sp .5 +.fi +.RE +The first line says that tcp port 1023 on rtsg sent a packet +to port \fIlogin\fP +on csam. The \fBS\fP indicates that the \fISYN\fP flag was set. +The packet sequence number was 768512 and it contained no data. +(The notation is `first:last(nbytes)' which means `sequence +numbers \fIfirst\fP +up to but not including \fIlast\fP which is \fInbytes\fP bytes of user data'.) +There was no piggy-backed ack, the available receive window was 4096 +bytes and there was a max-segment-size option requesting an mss of +1024 bytes. +.LP +Csam replies with a similar packet except it includes a piggy-backed +ack for rtsg's SYN. Rtsg then acks csam's SYN. The `.' means no +flags were set. +The packet contained no data so there is no data sequence number. +Note that the ack sequence +number is a small integer (1). The first time \fBtcpdump\fP sees a +tcp `conversation', it prints the sequence number from the packet. +On subsequent packets of the conversation, the difference between +the current packet's sequence number and this initial sequence number +is printed. This means that sequence numbers after the +first can be interpreted +as relative byte positions in the conversation's data stream (with the +first data byte each direction being `1'). `-S' will override this +feature, causing the original sequence numbers to be output. +.LP +On the 6th line, rtsg sends csam 19 bytes of data (bytes 2 through 20 +in the rtsg \(-> csam side of the conversation). +The PUSH flag is set in the packet. +On the 7th line, csam says it's received data sent by rtsg up to +but not including byte 21. Most of this data is apparently sitting in the +socket buffer since csam's receive window has gotten 19 bytes smaller. +Csam also sends one byte of data to rtsg in this packet. +On the 8th and 9th lines, +csam sends two bytes of urgent, pushed data to rtsg. +.HD +.B +UDP Packets +.LP +UDP format is illustrated by this rwho packet: +.RS +.nf +.sp .5 +\f(CWactinide.who > broadcast.who: udp 84\fP +.sp .5 +.fi +.RE +This says that port \fIwho\fP on host \fIactinide\fP sent a udp +datagram to port \fIwho\fP on host \fIbroadcast\fP, the Internet +broadcast address. The packet contained 84 bytes of user data. +.LP +Some UDP services are recognized (from the source or destination +port number) and the higher level protocol information printed. +In particular, Domain Name service requests (RFC-1034/1035) and Sun +RPC calls (RFC-1050) to NFS. +.HD +UDP Name Server Requests +.LP +\fI(N.B.:The following description assumes familiarity with +the Domain Service protocol described in RFC-1035. If you are not familiar +with the protocol, the following description will appear to be written +in greek.)\fP +.LP +Name server requests are formatted as +.RS +.nf +.sp .5 +\fIsrc > dst: id op? flags qtype qclass name (len)\fP +.sp .5 +\f(CWh2opolo.1538 > helios.domain: 3+ A? ucbvax.berkeley.edu. (37)\fP +.sp .5 +.fi +.RE +Host \fIh2opolo\fP asked the domain server on \fIhelios\fP for an +address record (qtype=A) associated with the name \fIucbvax.berkeley.edu.\fP +The query id was `3'. The `+' indicates the \fIrecursion desired\fP flag +was set. The query length was 37 bytes, not including the UDP and +IP protocol headers. The query operation was the normal one, \fIQuery\fP, +so the op field was omitted. If the op had been anything else, it would +have been printed between the `3' and the `+'. +Similarly, the qclass was the normal one, +\fIC_IN\fP, and omitted. Any other qclass would have been printed +immediately after the `A'. +.LP +A few anomalies are checked and may result in extra fields enclosed in +square brackets: If a query contains an answer, name server or +authority section, +.IR ancount , +.IR nscount , +or +.I arcount +are printed as `[\fIn\fPa]', `[\fIn\fPn]' or `[\fIn\fPau]' where \fIn\fP +is the appropriate count. +If any of the response bits are set (AA, RA or rcode) or any of the +`must be zero' bits are set in bytes two and three, `[b2&3=\fIx\fP]' +is printed, where \fIx\fP is the hex value of header bytes two and three. +.HD +UDP Name Server Responses +.LP +Name server responses are formatted as +.RS +.nf +.sp .5 +\fIsrc > dst: id op rcode flags a/n/au type class data (len)\fP +.sp .5 +\f(CWhelios.domain > h2opolo.1538: 3 3/3/7 A 128.32.137.3 (273) +helios.domain > h2opolo.1537: 2 NXDomain* 0/1/0 (97)\fP +.sp .5 +.fi +.RE +In the first example, \fIhelios\fP responds to query id 3 from \fIh2opolo\fP +with 3 answer records, 3 name server records and 7 authority records. +The first answer record is type A (address) and its data is internet +address 128.32.137.3. The total size of the response was 273 bytes, +excluding UDP and IP headers. The op (Query) and response code +(NoError) were omitted, as was the class (C_IN) of the A record. +.LP +In the second example, \fIhelios\fP responds to query 2 with a +response code of non-existent domain (NXDomain) with no answers, +one name server and no authority records. The `*' indicates that +the \fIauthoritative answer\fP bit was set. Since there were no +answers, no type, class or data were printed. +.LP +Other flag characters that might appear are `\-' (recursion available, +RA, \fInot\fP set) and `|' (truncated message, TC, set). If the +`question' section doesn't contain exactly one entry, `[\fIn\fPq]' +is printed. +.LP +Note that name server requests and responses tend to be large and the +default \fIsnaplen\fP of 96 bytes may not capture enough of the packet +to print. Use the \fB\-s\fP flag to increase the snaplen if you +need to seriously investigate name server traffic. `\fB\-s 128\fP' +has worked well for me. + +.HD +NFS Requests +.LP +Sun NFS (Network File System) requests and replies are printed as: +.RS +.nf +.sp .5 +\fIsrc.xid > dst.nfs: len op args\fP +\fIsrc.nfs > dst.xid: reply stat len\fP +.sp .5 +\f(CWvs.e2766 > helios.nfs: 136 readdir fh 6.5197 8192 bytes @ 0 +helios.nfs > vs.e2766: reply ok 384 +vs.e2767 > helios.nfs: 136 lookup fh 6.5197 `RCS'\fP +.sp .5 +.fi +.RE +In the first line, host \fIvs\fP sends a transaction with id \fIe2766\fP +to \fIhelios\fP (note that the number following the src host is a +transaction id, \fInot\fP the source port). The request was 136 bytes, +excluding the UDP and IP headers. The operation was a \fIreaddir\fP +(read directory) on file handle (\fIfh\fP) 6.5197. 8192 bytes are +read, starting at offset 0. \fIHelios\fP replies `ok' with 384 +bytes of data. (The design of Sun's RPC protocol makes it difficult to +interpret replies. I don't bother.) +.LP +In the third line, \fIvs\fP asks \fIhelios\fP to lookup the name +`\fIRCS\fP' in directory file 6.5197. Note that the data printed +depends on the operation type. The format is intended to be self +explanatory (at least, to me) if read in conjunction with +an NFS protocol spec. +.LP +Note that NFS requests are very large and the above won't be printed +unless \fIsnaplen\fP is increased. I use `\fB\-s 192\fP' to watch +NFS traffic. + +.HD +KIP Appletalk (DDP in UDP) +.LP +Appletalk DDP packets encapsulated in UDP datagrams are de-encapsulated +and dumped as DDP packets (i.e., all the UDP header information is +discarded). The file +.I /etc/atalk.names +is used to translate appletalk net and node numbers to names. +Lines in this file have the form +.RS +.nf +.sp .5 +\fInumber name\fP + +\f(CW1.254 ether +16.1 icsd-net +1.254.110 ace\fP +.sp .5 +.fi +.RE +The first two lines give the names of appletalk networks. The third +line gives the name of a particular host (a host is distinguished +from a net by the 3rd octet in the number \- +a net number \fImust\fP have two octets and a host number \fImust\fP +have three octets.) The number and name should be separated by +whitespace (blanks or tabs). +The +.I /etc/atalk.names +file may contain blank lines or comment lines (lines starting with +a `#'). +.LP +Appletalk addresses are printed in the form +.RS +.nf +.sp .5 +\fInet.host.port\fP + +\f(CW144.1.209.2 > icsd-net.112.220 +office.2 > icsd-net.112.220 +jssmag.149.235 > icsd-net.2\fP +.sp .5 +.fi +.RE +(If the +.I /etc/atalk.names +doesn't exist or doesn't contain an entry for some appletalk +host/net number, addresses are printed in numeric form.) +In the first example, NBP (DDP port 2) on net 144.1 node 209 +is sending to whatever is listening on port 220 of net icsd node 112. +The second line is the same except the full name of the source node +is known (`office'). The third line is a send from port 235 on +net jssmag node 149 to broadcast on the icsd-net NBP port (note that +the broadcast address (255) is indicated by a net name with no host +number \- for this reason it's a good idea to keep node names and +net names distinct in /etc/atalk.names). +.LP +NBP (name binding protocol) and ATP (Appletalk transaction protocol) +packets have their contents interpreted. Other protocols just dump +the protocol name (or number if no name is registered for the +protocol) and packet size. + +\fBNBP packets\fP are formatted like the following examples: +.RS +.nf +.sp .5 +\s-2\f(CWicsd-net.112.220 > jssmag.2: nbp-lkup 190: "=:LaserWriter@*" +jssmag.209.2 > icsd-net.112.220: nbp-reply 190: "RM1140:LaserWriter@*" 250 +techpit.2 > icsd-net.112.220: nbp-reply 190: "techpit:LaserWriter@*" 186\fP\s+2 +.sp .5 +.fi +.RE +The first line is a name lookup request for laserwriters sent by net icsd host +112 and broadcast on net jssmag. The nbp id for the lookup is 190. +The second line shows a reply for this request (note that it has the +same id) from host jssmag.209 saying that it has a laserwriter +resource named "RM1140" registered on port 250. The third line is +another reply to the same request saying host techpit has laserwriter +"techpit" registered on port 186. + +\fBATP packet\fP formatting is demonstrated by the following example: +.RS +.nf +.sp .5 +\s-2\f(CWjssmag.209.165 > helios.132: atp-req 12266<0-7> 0xae030001 +helios.132 > jssmag.209.165: atp-resp 12266:0 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:1 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:2 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:4 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:6 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp*12266:7 (512) 0xae040000 +jssmag.209.165 > helios.132: atp-req 12266<3,5> 0xae030001 +helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000 +helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000 +jssmag.209.165 > helios.132: atp-rel 12266<0-7> 0xae030001 +jssmag.209.133 > helios.132: atp-req* 12267<0-7> 0xae030002\fP\s+2 +.sp .5 +.fi +.RE +Jssmag.209 initiates transaction id 12266 with host helios by requesting +up to 8 packets (the `<0-7>'). The hex number at the end of the line +is the value of the `userdata' field in the request. +.LP +Helios responds with 8 512-byte packets. The `:digit' following the +transaction id gives the packet sequence number in the transaction +and the number in parens is the amount of data in the packet, +excluding the atp header. The `*' on packet 7 indicates that the +EOM bit was set. +.LP +Jssmag.209 then requests that packets 3 & 5 be retransmitted. Helios +resends them then jssmag.209 releases the transaction. Finally, +jssmag.209 initiates the next request. The `*' on the request +indicates that XO (`exactly once') was \fInot\fP set. + +.HD +IP Fragmentation +.LP +Fragmented Internet datagrams are printed as +.RS +.nf +.sp .5 +\fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB+)\fR +\fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB)\fR +.sp .5 +.fi +.RE +(The first form indicates there are more fragments. The second +indicates this is the last fragment.) +.LP +\fIId\fP is the fragment id. \fISize\fP is the fragment +size (in bytes) excluding the IP header. \fIOffset\fP is this +fragment's offset (in bytes) in the original datagram. +.LP +The fragment information is output for each fragment. The first +fragment contains the higher level protocol header and the frag +info is printed after the protocol info. Fragments +after the first contain no higher level protocol header and the +frag info is printed after the source and destination addresses. +For example, here is part of an ftp from arizona.edu to lbl-rtsg.arpa +over a CSNET connection that doesn't appear to handle 576 byte datagrams: +.RS +.nf +.sp .5 +\s-2\f(CWarizona.ftp-data > rtsg.1170: . 1024:1332(308) ack 1 win 4096 (frag 595a:328@0+) +arizona > rtsg: (frag 595a:204@328) +rtsg.1170 > arizona.ftp-data: . ack 1536 win 2560\fP\s+2 +.sp .5 +.fi +.RE +There are a couple of things to note here: First, addresses in the +2nd line don't include port numbers. This is because the TCP +protocol information is all in the first fragment and we have no idea +what the port or sequence numbers are when we print the later fragments. +Second, the tcp sequence information in the first line is printed as if there +were 308 bytes of user data when, in fact, there are 512 bytes (308 in +the first frag and 204 in the second). If you are looking for holes +in the sequence space or trying to match up acks +with packets, this can fool you. +.LP +A packet with the IP \fIdon't fragment\fP flag is marked with a +trailing \fB(DF)\fP. +.HD +Timestamps +.LP +By default, all output lines are preceded by a timestamp. The timestamp +is the current clock time in the form +.RS +.nf +\fIhh:mm:ss.frac\fP +.fi +.RE +and is as accurate as the kernel's clock (e.g., \(+-10ms on a Sun-3). +The timestamp reflects the time the kernel first saw the packet. No attempt +is made to account for the time lag between when the +ethernet interface removed the packet from the wire and when the kernel +serviced the `new packet' interrupt (of course, +with Sun's lousy clock resolution this time lag is negligible.) +.SH "SEE ALSO" +traffic(1C), nit(4P), bpf(4) +.SH AUTHORS +Van Jacobson (van@helios.ee.lbl.gov), +Craig Leres (leres@helios.ee.lbl.gov) and +Steven McCanne (mccanne@helios.ee.lbl.gov), all of +Lawrence Berkeley Laboratory, University of California, Berkeley, CA. +.SH BUGS +The clock resolution on most Suns is pathetic (20ms). +If you want to use the timestamp to generate some of the important +performance distributions (like packet interarrival time) it's best +to watch something that generates packets slowly (like an Arpanet +gateway or a MicroVax running VMS). +.LP +NIT doesn't let you watch your own outbound traffic, BPF will. +We recommend that you use the latter. +.LP +\fItcpdump\fP for Ultrix requires Ultrix version 4.0 or later; the kernel +has to have been built with the \fIpacketfilter\fP pseudo-device driver +(see +.IR packetfilter (4)). +As of this writing, Ultrix does not let you +watch either your own outbound or inbound traffic. +.LP +Under SunOS 4.1, the packet capture code (or Streams NIT) is not what +you'd call efficient. Don't plan on doing much with your Sun while +you're monitoring a busy network. +.LP +On Sun systems prior to release 3.2, NIT is very buggy. +If run on an old system, tcpdump may crash the machine. +.LP +Some attempt should be made to reassemble IP fragments or, at least +to compute the right length for the higher level protocol. +.LP +Name server inverse queries are not dumped correctly: The (empty) +question section is printed rather than real query in the answer +section. Some believe that inverse queries are themselves a bug and +prefer to fix the program generating them rather than tcpdump. +.LP +Apple Ethertalk DDP packets could be dumped as easily as KIP DDP +packets but aren't. +Even if we were inclined to do anything to promote the use of +Ethertalk (we aren't), LBL doesn't allow Ethertalk on any of its +networks so we'd would have no way of testing this code. +.LP +A packet trace that crosses a daylight savings time change will give +skewed time stamps (the time change is ignored). diff --git a/usr.sbin/tcpdump/tcpdump/tcpdump.c b/usr.sbin/tcpdump/tcpdump/tcpdump.c new file mode 100644 index 000000000000..9a0ccc4bbd63 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/tcpdump.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 1987-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +char copyright[] = + "@(#) Copyright (c) 1987-1990 The Regents of the University of California.\nAll rights reserved.\n"; +static char rcsid[] = + "@(#)$Header: tcpdump.c,v 1.68 92/06/02 17:57:41 mccanne Exp $ (LBL)"; +#endif + +/* + * tcpdump - monitor tcp/ip traffic on an ethernet. + * + * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. + * Mercilessly hacked and occasionally improved since then via the + * combined efforts of Van, Steve McCanne and Craig Leres of LBL. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "savefile.h" +#include "addrtoname.h" + +int fflag; /* don't translate "foreign" IP address */ +int nflag; /* leave addresses as numbers */ +int Nflag; /* remove domains from printed host names */ +int pflag; /* don't go promiscuous */ +int qflag; /* quick (shorter) output */ +int tflag = 1; /* print packet arrival time */ +int eflag; /* print ethernet header */ +int vflag; /* verbose */ +int xflag; /* print packet in hex */ +int Oflag = 1; /* run filter code optimizer */ +int Sflag; /* print raw TCP sequence numbers */ + +int dflag; /* print filter code */ + +char *program_name; + +long thiszone; /* gmt to local correction */ + +static void cleanup(); + +/* Length of saved portion of packet. */ +int snaplen = DEFAULT_SNAPLEN; + +static int if_fd = -1; + +struct printer { + void (*f)(); + int type; +}; + +static struct printer printers[] = { + { ether_if_print, DLT_EN10MB }, + { sl_if_print, DLT_SLIP }, + { ppp_if_print, DLT_PPP }, + { fddi_if_print, DLT_FDDI }, + { null_if_print, DLT_NULL }, + { 0, 0 }, +}; + +void +(*lookup_printer(type))() + int type; +{ + struct printer *p; + + for (p = printers; p->f; ++p) + if (type == p->type) + return p->f; + + error("unknown data link type 0x%x", type); + /* NOTREACHED */ +} + +void +main(argc, argv) + int argc; + char **argv; +{ + struct bpf_program *parse(); + void bpf_dump(); + + int cnt = -1, i; + struct timeb zt; + struct bpf_program *fcode; + int op; + void (*printit)(); + char *infile = 0; + char *cmdbuf; + int linktype; + int err; + u_long localnet; + u_long netmask; + + char *RFileName = 0; /* -r argument */ + char *WFileName = 0; /* -w argument */ + + char *device = 0; + + int precision = clock_sigfigs(); + + extern char *optarg; + extern int optind, opterr; + + program_name = argv[0]; + + opterr = 0; + while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:Stvw:xY")) != EOF) + switch (op) { + case 'c': + cnt = atoi(optarg); + break; + + case 'd': + ++dflag; + break; + + case 'e': + ++eflag; + break; + + case 'f': + ++fflag; + break; + + case 'F': + infile = optarg; + break; + + case 'i': + device = optarg; + break; + + case 'l': + setlinebuf(stdout); + break; + + case 'n': + ++nflag; + break; + + case 'N': + ++Nflag; + break; + + case 'O': + Oflag = 0; + break; + + case 'p': + ++pflag; + break; + + case 'q': + ++qflag; + break; + + case 'r': + RFileName = optarg; + break; + + case 's': + snaplen = atoi(optarg); + break; + + case 'S': + ++Sflag; + break; + + case 't': + --tflag; + break; + + case 'v': + ++vflag; + break; + + case 'w': + WFileName = optarg; + break; +#ifdef YYDEBUG + case 'Y': + { + extern int yydebug; + yydebug = 1; + } + break; +#endif + case 'x': + ++xflag; + break; + + default: + usage(); + /* NOTREACHED */ + } + + if (tflag > 0) { + struct timeval now; + struct timezone tz; + + if (gettimeofday(&now, &tz) < 0) { + perror("tcpdump: gettimeofday"); + exit(1); + } + thiszone = tz.tz_minuteswest * -60; + if (localtime((time_t *)&now.tv_sec)->tm_isdst) + thiszone += 3600; + } + + if (RFileName) { + /* + * We don't need network access, so set it back to the user id. + * Also, this prevents the user from reading anyone's + * trace file. + */ + setuid(getuid()); + + err = sf_read_init(RFileName, &linktype, &thiszone, &snaplen, + &precision); + if (err) + sf_err(err); + localnet = 0; + netmask = 0; + if (fflag != 0) + error("-f and -r options are incompatible"); + } else { + if (device == 0) { + device = lookup_device(); + if (device == 0) + error("can't find any interfaces"); + } + if_fd = initdevice(device, pflag, &linktype); + lookup_net(device, &localnet, &netmask); + /* + * Let user own process after socket has been opened. + */ + setuid(getuid()); + } + + if (infile) + cmdbuf = read_infile(infile); + else + cmdbuf = copy_argv(&argv[optind]); + + fcode = parse(cmdbuf, Oflag, linktype, netmask); + if (dflag) { + bpf_dump(fcode, dflag); + exit(0); + } + init_addrtoname(fflag, localnet, netmask); + + (void)signal(SIGTERM, cleanup); + (void)signal(SIGINT, cleanup); + (void)signal(SIGHUP, cleanup); + + printit = lookup_printer(linktype); + + if (WFileName) { + sf_write_init(WFileName, linktype, thiszone, snaplen, + precision); + printit = sf_write; + } + if (RFileName) { + err = sf_read(fcode, cnt, snaplen, printit); + if (err) + sf_err(err); + } else { + fprintf(stderr, "%s: listening on %s\n", program_name, device); + fflush(stderr); + readloop(cnt, if_fd, fcode, printit); + } + exit(0); +} + +/* make a clean exit on interrupts */ +static void +cleanup() +{ + if (if_fd >= 0) { + putc('\n', stderr); + wrapup(if_fd); + } + exit(0); +} + +void +default_print(sp, length) + register u_short *sp; + register int length; +{ + register u_int i; + register int nshorts; + + nshorts = (unsigned) length / sizeof(u_short); + i = 0; + while (--nshorts >= 0) { + if ((i++ % 8) == 0) + (void)printf("\n\t\t\t"); + (void)printf(" %04x", ntohs(*sp++)); + } + if (length & 1) { + if ((i % 8) == 0) + (void)printf("\n\t\t\t"); + (void)printf(" %02x", *(u_char *)sp); + } +} + +void +usage() +{ + extern char version[]; + + (void)fprintf(stderr, "Version %s\n", version); + (void)fprintf(stderr, +"Usage: tcpdump [-deflnOpqtvx] [-c count] [-i interface]\n"); + (void)fprintf(stderr, +"\t\t[-r filename] [-w filename] [expr]\n"); + exit(-1); +} diff --git a/usr.sbin/tcpdump/tcpdump/tcpgram.y b/usr.sbin/tcpdump/tcpdump/tcpgram.y new file mode 100644 index 000000000000..da235d0b1068 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/tcpgram.y @@ -0,0 +1,232 @@ +%{ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Grammar for tcpdump. + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: tcpgram.y,v 1.29 92/03/17 13:45:08 mccanne Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include +#include + +#include "interface.h" + +#include +#include + +#include "gencode.h" + +#define QSET(q, p, d, a) (q).proto = (p),\ + (q).dir = (d),\ + (q).addr = (a) + +int n_errors = 0; + +static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; + +static void +yyerror() +{ + ++n_errors; +} + +%} + +%union { + int i; + u_long h; + u_char *e; + char *s; + struct stmt *stmt; + struct arth *a; + struct { + struct qual q; + struct block *b; + } blk; + struct block *rblk; +} + +%type expr id nid pid term rterm qid +%type head +%type pqual dqual aqual ndaqual +%type arth narth +%type byteop pname pnum relop irelop +%type and or paren not null prog +%type other + +%token DST SRC HOST GATEWAY +%token NET PORT LESS GREATER PROTO BYTE +%token ARP RARP IP TCP UDP ICMP +%token TK_BROADCAST TK_MULTICAST +%token NUM +%token LINK +%token GEQ LEQ NEQ +%token ID EID HID +%token LSH RSH +%token LEN + +%type ID +%type EID +%type HID +%type NUM + +%left OR AND +%nonassoc '!' +%left '|' +%left '&' +%left LSH RSH +%left '+' '-' +%left '*' '/' +%nonassoc UMINUS +%% +prog: null expr +{ + finish_parse($2.b); +} + | null + ; +null: /* null */ { $$.q = qerr; } + ; +expr: term + | expr and term { gen_and($1.b, $3.b); $$ = $3; } + | expr and id { gen_and($1.b, $3.b); $$ = $3; } + | expr or term { gen_or($1.b, $3.b); $$ = $3; } + | expr or id { gen_or($1.b, $3.b); $$ = $3; } + ; +and: AND { $$ = $0; } + ; +or: OR { $$ = $0; } + ; +id: nid + | pnum { $$.b = gen_ncode((u_long)$1, + $$.q = $0.q); } + | paren pid ')' { $$ = $2; } + ; +nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } + | HID { $$.b = gen_ncode($1, $$.q = $0.q); } + | EID { $$.b = gen_ecode($1, $$.q = $0.q); } + | not id { gen_not($2.b); $$ = $2; } + ; +not: '!' { $$ = $0; } + ; +paren: '(' { $$ = $0; } + ; +pid: nid + | qid and id { gen_and($1.b, $3.b); $$ = $3; } + | qid or id { gen_or($1.b, $3.b); $$ = $3; } + ; +qid: pnum { $$.b = gen_ncode((u_long)$1, + $$.q = $0.q); } + | pid + ; +term: rterm + | not term { gen_not($2.b); $$ = $2; } + ; +head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } + | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } + | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } + | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } + | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } + ; +rterm: head id { $$ = $2; } + | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } + | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; } + | arth relop arth { $$.b = gen_relation($2, $1, $3, 0); + $$.q = qerr; } + | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1); + $$.q = qerr; } + | other { $$.b = $1; $$.q = qerr; } + ; +/* protocol level qualifiers */ +pqual: pname + | { $$ = Q_DEFAULT; } + ; +/* 'direction' qualifiers */ +dqual: SRC { $$ = Q_SRC; } + | DST { $$ = Q_DST; } + | SRC OR DST { $$ = Q_OR; } + | DST OR SRC { $$ = Q_OR; } + | SRC AND DST { $$ = Q_AND; } + | DST AND SRC { $$ = Q_AND; } + ; +/* address type qualifiers */ +aqual: HOST { $$ = Q_HOST; } + | NET { $$ = Q_NET; } + | PORT { $$ = Q_PORT; } + ; +/* non-directional address type qualifiers */ +ndaqual: GATEWAY { $$ = Q_GATEWAY; } + ; +pname: LINK { $$ = Q_LINK; } + | IP { $$ = Q_IP; } + | ARP { $$ = Q_ARP; } + | RARP { $$ = Q_RARP; } + | TCP { $$ = Q_TCP; } + | UDP { $$ = Q_UDP; } + | ICMP { $$ = Q_ICMP; } + ; +other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } + | pqual TK_MULTICAST { $$ = gen_multicast($1); } + | LESS NUM { $$ = gen_less($2); } + | GREATER NUM { $$ = gen_greater($2); } + | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } + ; +relop: '>' { $$ = BPF_JGT; } + | GEQ { $$ = BPF_JGE; } + | '=' { $$ = BPF_JEQ; } + ; +irelop: LEQ { $$ = BPF_JGT; } + | '<' { $$ = BPF_JGE; } + | NEQ { $$ = BPF_JEQ; } + ; +arth: pnum { $$ = gen_loadi($1); } + | narth + ; +narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } + | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } + | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } + | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } + | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } + | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } + | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } + | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } + | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } + | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } + | '-' arth %prec UMINUS { $$ = gen_neg($2); } + | paren narth ')' { $$ = $2; } + | LEN { $$ = gen_loadlen(); } + ; +byteop: '&' { $$ = '&'; } + | '|' { $$ = '|'; } + | '<' { $$ = '<'; } + | '>' { $$ = '>'; } + | '=' { $$ = '='; } + ; +pnum: NUM + | paren pnum ')' { $$ = $2; } + ; +%% diff --git a/usr.sbin/tcpdump/tcpdump/tcplex.l b/usr.sbin/tcpdump/tcpdump/tcplex.l new file mode 100644 index 000000000000..840590addcd3 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/tcplex.l @@ -0,0 +1,146 @@ +%{ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: tcplex.l,v 1.26 92/02/14 15:16:35 mccanne Exp $ (LBL)"; +#endif + +/* + * Compiling with gcc under SunOS will cause problems unless we have this + * cruft here. The flex skeleton includes stddef.h which defines these types + * (under gcc). They will conflict with Sun's definitions in sys/types.h. + */ +#define size_t xxxsize_t +#define ptrdiff_t xxxptrdiff_t +#define wchar_t xxxwchar_t +#include +#undef size_t +#undef ptrdiff_t +#undef wchar_t + +#include "nametoaddr.h" + +/* + * We need bpf since enum bpf_code is in YYSTYPE. + */ +#include +#include + +#include "gencode.h" +#include "y.tab.h" /* "tokdefs.h" */ + +#ifdef FLEX_SCANNER +#undef YY_INPUT +#define YY_INPUT(buf, result, max)\ + {\ + char *src = in_buffer;\ + int i;\ +\ + if (*src == 0)\ + result = YY_NULL;\ + else {\ + for (i = 0; *src && i < max; ++i)\ + buf[i] = *src++;\ + in_buffer += i;\ + result = i;\ + }\ + } +#else +#undef getc +#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) +#endif + +extern YYSTYPE yylval; +static char *in_buffer; + +%} + +N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) +B ([0-9A-Fa-f][0-9A-Fa-f]?) + +%a 3000 + +%% +dst return DST; +src return SRC; + +link|ether|ppp|slip return LINK; +arp return ARP; +rarp return RARP; +ip return IP; +tcp return TCP; +udp return UDP; +icmp return ICMP; + +host return HOST; +net return NET; +port return PORT; +proto return PROTO; + +gateway return GATEWAY; + +less return LESS; +greater return GREATER; +byte return BYTE; +broadcast return TK_BROADCAST; +multicast return TK_MULTICAST; + +and return AND; +or return OR; +not return '!'; + +len return LEN; + +[ \n\t] ; +[+\-*/:\[\]!<>()&|=] return yytext[0]; +">=" return GEQ; +"<=" return LEQ; +"!=" return NEQ; +"==" return '='; +"<<" return LSH; +">>" return RSH; +{N} { yylval.i = stoi(yytext); return NUM; } +({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { + yylval.h = atoin(yytext); return HID; +} +{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = ETHER_aton(yytext); return EID; } +{B}:+({B}:+)+ { error("bogus ethernet address %s", yytext); } +[A-Za-z][-_.A-Za-z0-9]* { yylval.s = yytext; return ID; } +"\\"[^ !()\n\t]+ { yylval.s = yytext + 1; return ID; } +[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { error("illegal token: %s\n", yytext); } +. { error("illegal char '%c'", *yytext); } +%% +void +lex_init(buf) + char *buf; +{ + in_buffer = buf; +} +#ifndef FLEX_SCANNER +int +yywrap() +/* so we don't need -ll */ +{ + return 1; +} +#endif diff --git a/usr.sbin/tcpdump/tcpdump/util.c b/usr.sbin/tcpdump/tcpdump/util.c new file mode 100644 index 000000000000..ec58c3f56cb1 --- /dev/null +++ b/usr.sbin/tcpdump/tcpdump/util.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 1988-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: util.c,v 1.12 91/10/28 22:09:31 mccanne Exp $ (LBL)"; +#endif + +#include +#ifdef __STDC__ +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "interface.h" + +/* Hex digit to integer. */ +static inline int +xdtoi(c) +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +/* + * Convert string to integer. Just like atoi(), but checks for + * preceding 0x or 0 and uses hex or octal instead of decimal. + */ +int +stoi(s) + char *s; +{ + int base = 10; + int n = 0; + + if (*s == '0') { + if (s[1] == 'x' || s[1] == 'X') { + s += 2; + base = 16; + } + else { + base = 8; + s += 1; + } + } + while (*s) + n = n * base + xdtoi(*s++); + + return n; +} + +/* + * Print out a filename (or other ascii string). + * Return true if truncated. + */ +int +printfn(s, ep) + register u_char *s, *ep; +{ + register u_char c; + + putchar('"'); + while (c = *s++) { + if (s > ep) { + putchar('"'); + return(1); + } + if (!isascii(c)) { + c = toascii(c); + putchar('M'); + putchar('-'); + } + if (!isprint(c)) { + c ^= 0x40; /* DEL to ?, others to alpha */ + putchar('^'); + } + putchar(c); + } + putchar('"'); + return(0); +} + +/* + * Print the timestamp + */ +void +ts_print(tvp) + register struct timeval *tvp; +{ + register int i; + + if (tflag > 0) { + /* Default */ + i = (tvp->tv_sec + thiszone) % 86400; + (void)printf("%02d:%02d:%02d.%06d ", + i / 3600, (i % 3600) / 60, i % 60, tvp->tv_usec); + } else if (tflag < 0) { + /* Unix timeval style */ + (void)printf("%d.%06d ", tvp->tv_sec, tvp->tv_usec); + } +} + +#ifdef NOVFPRINTF +/* + * Stock 4.3 doesn't have vfprintf. + * This routine is due to Chris Torek. + */ +vfprintf(f, fmt, args) + FILE *f; + char *fmt; + va_list args; +{ + int ret; + + if ((f->_flag & _IOWRT) == 0) { + if (f->_flag & _IORW) + f->_flag |= _IOWRT; + else + return EOF; + } + ret = _doprnt(fmt, args, f); + return ferror(f) ? EOF : ret; +} +#endif + +static char * +stripdir(s) + register char *s; +{ + register char *cp; + char *rindex(); + + cp = rindex(s, '/'); + return (cp != 0) ? cp + 1 : s; +} + +/* VARARGS */ +void +error(va_alist) + va_dcl +{ + register char *cp; + va_list ap; + + (void)fprintf(stderr, "%s: ", stripdir(program_name)); + + va_start(ap); + cp = va_arg(ap, char *); + (void)vfprintf(stderr, cp, ap); + va_end(ap); + if (*cp) { + cp += strlen(cp); + if (cp[-1] != '\n') + (void)fputc('\n', stderr); + } + exit(1); + /* NOTREACHED */ +} + +/* VARARGS */ +void +warning(va_alist) + va_dcl +{ + register char *cp; + va_list ap; + + (void)fprintf(stderr, "%s: warning: ", stripdir(program_name)); + + va_start(ap); + cp = va_arg(ap, char *); + (void)vfprintf(stderr, cp, ap); + va_end(ap); + if (*cp) { + cp += strlen(cp); + if (cp[-1] != '\n') + (void)fputc('\n', stderr); + } +} + + +/* + * Copy arg vector into a new buffer, concatenating arguments with spaces. + */ +char * +copy_argv(argv) + register char **argv; +{ + register char **p; + register int len = 0; + char *buf; + char *src, *dst; + + p = argv; + if (*p == 0) + return 0; + + while (*p) + len += strlen(*p++) + 1; + + buf = malloc(len); + + p = argv; + dst = buf; + while (src = *p++) { + while (*dst++ = *src++) + ; + dst[-1] = ' '; + } + dst[-1] = '\0'; + + return buf; +} + +char * +read_infile(fname) + char *fname; +{ + struct stat buf; + int fd; + char *p; + + fd = open(fname, O_RDONLY); + if (fd < 0) + error("can't open '%s'", fname); + + if (fstat(fd, &buf) < 0) + error("can't state '%s'", fname); + + p = malloc((unsigned)buf.st_size); + if (read(fd, p, (int)buf.st_size) != buf.st_size) + error("problem reading '%s'", fname); + + return p; +} + +/* + * Left justify 'addr' and return its resulting network mask. + */ +u_long +net_mask(addr) + u_long *addr; +{ + register u_long m = 0xffffffff; + + if (*addr) + while ((*addr & 0xff000000) == 0) + *addr <<= 8, m <<= 8; + + return m; +} diff --git a/usr.sbin/tcpdump/tcpslice/Makefile b/usr.sbin/tcpdump/tcpslice/Makefile new file mode 100644 index 000000000000..d1cd63b19ff4 --- /dev/null +++ b/usr.sbin/tcpdump/tcpslice/Makefile @@ -0,0 +1,18 @@ +# @(#)Makefile 0.1 (RWGrimes) 3/24/93 + +PROG= tcpslice +CFLAGS+=-DCSLIP -I. -I$(.CURDIR)/../tcpdump +MAN1= tcpslice.0 +SRCS= version.c tcpslice.c gwtm2secs.c search.c \ + savefile.c bpf_filter.c md.c util.c +.PATH: ${.CURDIR}/../tcpdump /sys/net +CLEANFILES+= version.c version.h + +version.c version.h: $(.CURDIR)/../tcpdump/VERSION + rm -f version.c ; \ + sed 's/.*/char version[] = "&";/' $(.CURDIR)/../tcpdump/VERSION > version.c + set `sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \2/' $(.CURDIR)/../tcpdump/VERSION` ; \ + { echo '#define VERSION_MAJOR' $$1 ; \ + echo '#define VERSION_MINOR' $$2 ; } > version.h + +.include diff --git a/usr.sbin/tcpdump/tcpslice/gwtm2secs.c b/usr.sbin/tcpdump/tcpslice/gwtm2secs.c new file mode 100644 index 000000000000..aeb377fd932d --- /dev/null +++ b/usr.sbin/tcpdump/tcpslice/gwtm2secs.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#)$Header: gwtm2secs.c,v 1.1 92/06/02 11:35:19 mccanne Exp $ (LBL)"; +#endif + +/* + * gwtm2secs.c - convert "tm" structs for Greenwich time to Unix timestamp + */ + +#include +#include +#include + +static int days_in_month[] = + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +#define IS_LEAP_YEAR(year) \ + (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + +time_t gwtm2secs( tm ) +struct tm *tm; + { + int i, days, year; + + year = tm->tm_year; + + /* Allow for year being specified with either 2 digits or 4 digits. + * 2-digit years are either 19xx or 20xx - a simple heuristic + * distinguishes them, since we can't represent any time < 1970. + */ + if ( year < 100 ) + if ( year >= 70 ) + year += 1900; + else + year += 2000; + + days = 0; + for ( i = 1970; i < year; ++i ) + { + days += 365; + if ( IS_LEAP_YEAR(i) ) + ++days; + } + + for ( i = 0; i < tm->tm_mon; ++i ) + days += days_in_month[i]; + + if ( IS_LEAP_YEAR(year) && tm->tm_mon > 1 ) /* 1 is February */ + ++days; + + days += tm->tm_mday - 1; /* -1 since days are numbered starting at 1 */ + + return days * 86400 + tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; + } diff --git a/usr.sbin/tcpdump/tcpslice/search.c b/usr.sbin/tcpdump/tcpslice/search.c new file mode 100644 index 000000000000..8bea0d2fabf1 --- /dev/null +++ b/usr.sbin/tcpdump/tcpslice/search.c @@ -0,0 +1,563 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#)$Header: search.c,v 1.3 92/05/01 15:14:45 vern Exp $ (LBL)"; +#endif + +/* + * search.c - supports fast searching through tcpdump files for timestamps + */ + +#include +#include +#include + +#include "interface.h" +#include "savefile.h" + + +/* Maximum number of seconds that we can conceive of a dump file spanning. */ +#define MAX_REASONABLE_FILE_SPAN (3600*24*366) /* one year */ + +/* Maximum packet length we ever expect to see. */ +#define MAX_REASONABLE_PACKET_LENGTH 65535 + +/* Size of a packet header in bytes; easier than typing the sizeof() all + * the time ... + */ +#define PACKET_HDR_LEN (sizeof( struct packet_header )) + +/* The maximum size of a packet, including its header. */ +#define MAX_PACKET_SIZE (PACKET_HDR_LEN + snaplen) + +/* Number of contiguous bytes from a dumpfile in which there's guaranteed + * to be enough information to find a "definite" header if one exists + * therein. This takes 3 full packets - the first to be just misaligned + * (one byte short of a full packet), missing its timestamp; the second + * to have the legitimate timestamp; and the third to provide confirmation + * that the second is legit, making it a "definite" header. We could + * scrimp a bit here since not the entire third packet is required, but + * it doesn't seem worth it + */ +#define MAX_BYTES_FOR_DEFINITE_HEADER (3 * MAX_PACKET_SIZE) + +/* Maximum number of seconds that might reasonably separate two headers. */ +#define MAX_REASONABLE_HDR_SEPARATION (3600 * 24 * 7) /* one week */ + +/* When searching a file for a packet, if we think we're within this many + * bytes of the packet we just search linearly. Since linear searches are + * probably much faster than random ones (random ones require searching for + * the beginning of the packet, which may be unaligned in memory), we make + * this value pretty hefty. + */ +#define STRAIGHT_SCAN_THRESHOLD (100 * MAX_PACKET_SIZE) + +/* Extracts a long integer from a possibly unaligned buffer containing + * unsigned characters. + */ +#define EXTRACT_LONG(buf) (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) + + +/* Given a header and an acceptable first and last time stamp, returns non-zero + * if the header looks reasonable and zero otherwise. + */ +static int reasonable_header( hdr, first_time, last_time ) +struct packet_header *hdr; +long first_time, last_time; + { + if ( last_time == 0 ) + last_time = first_time + MAX_REASONABLE_FILE_SPAN; + + return hdr->ts.tv_sec >= first_time && + hdr->ts.tv_sec <= last_time && + hdr->len > 0 && + hdr->len <= MAX_REASONABLE_PACKET_LENGTH && + hdr->caplen > 0 && + hdr->caplen <= MAX_REASONABLE_PACKET_LENGTH; + } + + +/* Given a buffer, extracts a (properly aligned) packet header from it. */ + +static void extract_header( buf, hdr ) +u_char *buf; +struct packet_header *hdr; + { + hdr->ts.tv_sec = EXTRACT_LONG(buf); + buf += sizeof( long ); + hdr->ts.tv_usec = EXTRACT_LONG(buf); + buf += sizeof( long ); + hdr->len = EXTRACT_LONG(buf); + buf += sizeof( long ); + hdr->caplen = EXTRACT_LONG(buf); + + if ( sf_swapped ) + { + hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec); + hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec); + hdr->len = SWAPLONG(hdr->len); + hdr->caplen = SWAPLONG(hdr->caplen); + } + } + + +/* Search a buffer to locate the first header within it. Return values + * are HEADER_NONE, HEADER_CLASH, HEADER_PERHAPS, and HEADER_DEFINITELY. + * The first indicates that no evidence of a header was found; the second + * that two or more possible headers were found, neither more convincing + * than the other(s); the third that exactly one "possible" header was + * found; and the fourth that exactly one "definite" header was found. + * + * Headers are detected by looking for positions in the buffer which have + * reasonable timestamps and lengths. If there is enough room in the buffer + * for another header to follow a candidate header, a check is made for + * that following header. If it is present then the header is *definite* + * (unless another "perhaps" or "definite" header is found); if not, then + * the header is discarded. If there is not enough room in the buffer for + * another header then the candidate is *perhaps* (unless another header + * is subsequently found). A "tie" between a "definite" header and a + * "perhaps" header is resolved in favor of the definite header. Any + * other tie leads to HEADER_CLASH. + * + * The buffer position of the header is returned in hdrpos_addr and + * for convenience the corresponding header in return_hdr. + * + * first_time is the earliest possible acceptable timestamp in the + * header. last_time, if non-zero, is the last such timestamp. If + * zero, then up to MAX_REASONABLE_FILE_SPAN seconds after first_time + * is acceptable. + */ + +#define HEADER_NONE 0 +#define HEADER_CLASH 1 +#define HEADER_PERHAPS 2 +#define HEADER_DEFINITELY 3 + +static int find_header( buf, buf_len, first_time, last_time, + hdrpos_addr, return_hdr ) +u_char *buf; +unsigned buf_len; +long first_time, last_time; +u_char **hdrpos_addr; +struct packet_header *return_hdr; + { + u_char *bufptr, *bufend, *last_pos_to_try; + struct packet_header hdr, hdr2; + int status = HEADER_NONE; + int saw_PERHAPS_clash = 0; + + /* Initially, try each buffer position to see whether it looks like + * a valid packet header. We may later restrict the positions we look + * at to avoid seeing a sequence of legitimate headers as conflicting + * with one another. + */ + bufend = buf + buf_len; + last_pos_to_try = bufend - PACKET_HDR_LEN; + + for ( bufptr = buf; bufptr < last_pos_to_try; ++bufptr ) + { + extract_header( bufptr, &hdr ); + + if ( reasonable_header( &hdr, first_time, last_time ) ) + { + u_char *next_header = bufptr + PACKET_HDR_LEN + hdr.caplen; + + if ( next_header + PACKET_HDR_LEN < bufend ) + { /* check for another good header */ + extract_header( next_header, &hdr2 ); + + if ( reasonable_header( &hdr2, hdr.ts.tv_sec, + hdr.ts.tv_sec + MAX_REASONABLE_HDR_SEPARATION ) ) + { /* a confirmed header */ + switch ( status ) + { + case HEADER_NONE: + case HEADER_PERHAPS: + status = HEADER_DEFINITELY; + *hdrpos_addr = bufptr; + *return_hdr = hdr; + + /* Make sure we don't demote this "definite" + * to a "clash" if we stumble across its + * successor. + */ + last_pos_to_try = next_header - PACKET_HDR_LEN; + break; + + case HEADER_DEFINITELY: + return HEADER_CLASH; + + default: + error( "bad status in find_header()" ); + } + } + + /* ... else the header is bogus - we've verified that it's + * not followed by a reasonable header. + */ + } + + else + { /* can't check for another good header */ + switch ( status ) + { + case HEADER_NONE: + status = HEADER_PERHAPS; + *hdrpos_addr = bufptr; + *return_hdr = hdr; + break; + + case HEADER_PERHAPS: + /* We don't immediately turn this into a + * clash because perhaps we'll later see a + * "definite" which will save us ... + */ + saw_PERHAPS_clash = 1; + break; + + case HEADER_DEFINITELY: + /* Keep the definite in preference to this one. */ + break; + + default: + error( "bad status in find_header()" ); + } + } + } + } + + if ( status == HEADER_PERHAPS && saw_PERHAPS_clash ) + status = HEADER_CLASH; + + return status; + } + + +/* Positions the sf_readfile stream such that the next sf_read() will + * read the final full packet in the file. Returns non-zero if + * successful, zero if unsuccessful. If successful, returns the + * timestamp of the last packet in last_timestamp. + * + * Note that this routine is a special case of sf_find_packet(). In + * order to use sf_find_packet(), one first must use this routine in + * order to give sf_find_packet() an upper bound on the timestamps + * present in the dump file. + */ +int sf_find_end( first_timestamp, last_timestamp ) +struct timeval *first_timestamp; +struct timeval *last_timestamp; + { + long first_time = first_timestamp->tv_sec; + unsigned num_bytes; + u_char *buf, *bufpos, *bufend; + u_char *hdrpos; + struct packet_header hdr, successor_hdr; + int status; + + /* Allow enough room for at least two full (untruncated) packets, + * perhaps followed by a truncated packet, so we have a shot at + * finding a "definite" header and following its chain to the + * end of the file. + */ + num_bytes = MAX_BYTES_FOR_DEFINITE_HEADER; + if ( fseek( sf_readfile, (long) -num_bytes, 2 ) < 0 ) + return 0; + + buf = (u_char *)malloc((unsigned) num_bytes); + if ( ! buf ) + return 0; + + status = 0; + bufpos = buf; + bufend = buf + num_bytes; + + if ( fread( (char *) bufpos, num_bytes, 1, sf_readfile ) != 1 ) + goto done; + + if ( find_header( bufpos, num_bytes, first_time, 0L, &hdrpos, &hdr ) != + HEADER_DEFINITELY ) + goto done; + + /* Okay, we have a definite header in our hands. Follow its + * chain till we find the last valid packet in the file ... + */ + for ( ; ; ) + { + /* move to the next header position */ + bufpos = hdrpos + PACKET_HDR_LEN + hdr.caplen; + + /* bufpos now points to a candidate packet, which if valid + * should replace the current packet pointed to by hdrpos as + * the last valid packet ... + */ + if ( bufpos >= bufend - PACKET_HDR_LEN ) + /* not enough room for another header */ + break; + + extract_header( bufpos, &successor_hdr ); + + first_time = hdr.ts.tv_sec; + if ( ! reasonable_header( &successor_hdr, first_time, 0L ) ) + /* this bodes ill - it means bufpos is perhaps a + * bogus packet header after all ... + */ + break; + + /* Note that the following test is for whether the next + * packet starts at a position > bufend, *not* for a + * position >= bufend. If this is the last packet in the + * file and there isn't a subsequent partial packet, then + * we expect the first buffer position beyond this packet + * to be just beyond the end of the buffer, i.e., at bufend + * itself. + */ + if ( bufpos + PACKET_HDR_LEN + successor_hdr.caplen > bufend ) + /* the packet is truncated */ + break; + + /* Accept this packet as fully legit. */ + hdrpos = bufpos; + hdr = successor_hdr; + } + + /* Success! Last valid packet is at hdrpos. */ + *last_timestamp = hdr.ts; + status = 1; + + /* Seek so that the next read will start at last valid packet. */ + if ( fseek( sf_readfile, (long) -(bufend - hdrpos), 2 ) < 0 ) + error( "final fseek() failed in sf_find_end()" ); + + done: + free( (char *) buf ); + + return status; + } + + +/* Takes two timeval's and returns the difference, tv2 - tv1, as a double. */ + +static double timeval_diff( tv1, tv2 ) +struct timeval *tv1, *tv2; + { + double result = (tv2->tv_sec - tv1->tv_sec); + result += (tv2->tv_usec - tv1->tv_usec) / 1000000.0; + + return result; + } + + +/* Returns true if timestamp t1 is chronologically less than timestamp t2. */ + +int sf_timestamp_less_than( t1, t2 ) +struct timeval *t1, *t2; + { + return t1->tv_sec < t2->tv_sec || + (t1->tv_sec == t2->tv_sec && + t1->tv_usec < t2->tv_usec); + } + + +/* Given two timestamps on either side of desired_time and their positions, + * returns the interpolated position of the desired_time packet. Returns a + * negative value if the desired_time is outside the given range. + */ + +static +long interpolated_position( min_time, min_pos, max_time, max_pos, desired_time ) +struct timeval *min_time, *max_time, *desired_time; +long min_pos, max_pos; + { + double full_span = timeval_diff( max_time, min_time ); + double desired_span = timeval_diff( desired_time, min_time ); + long full_span_pos = max_pos - min_pos; + double fractional_offset = desired_span / full_span; + + if ( fractional_offset < 0.0 || fractional_offset > 1.0 ) + return -1; + + return min_pos + (long) (fractional_offset * (double) full_span_pos); + } + + +/* Reads packets linearly until one with a time >= the given desired time + * is found; positions the dump file so that the next read will start + * at the given packet. Returns non-zero on success, 0 if an EOF was + * first encountered. + */ + +static int read_up_to( desired_time ) +struct timeval *desired_time; + { + int status = 1; + struct packet_header hdr; + u_char *buf; + long pos; + + buf = (u_char *) malloc( (unsigned) snaplen ); + + for ( ; ; ) + { + struct timeval *timestamp; + + pos = ftell( sf_readfile ); + status = sf_next_packet( &hdr, buf, snaplen ); + + if ( status ) + { + if ( status == SFERR_EOF ) + { + status = 0; + break; + } + + error( "bad status %d in read_up_to()", status ); + } + + timestamp = &hdr.ts; + + if ( ! sf_timestamp_less_than( timestamp, desired_time ) ) + break; + } + + if ( fseek( sf_readfile, pos, 0 ) < 0 ) + error( "fseek() failed in read_up_to()" ); + + free( (char *) buf ); + + return status; + } + + +/* Positions the sf_readfile stream so that the next sf_read() will + * return the first packet with a time greater than or equal to + * desired_time. desired_time must be greater than min_time and less + * than max_time, which should correspond to actual packets in the + * file. min_pos is the file position (byte offset) corresponding to + * the min_time packet and max_pos is the same for the max_time packet. + * + * Returns non-zero on success, 0 if the given position is beyond max_pos. + * + * NOTE: when calling this routine, the sf_readfile stream *must* be + * already aligned so that the next call to sf_next_packet() will yield + * a valid packet. + */ + +int sf_find_packet( min_time, min_pos, max_time, max_pos, desired_time ) +struct timeval *min_time, *max_time; +long min_pos, max_pos; +struct timeval *desired_time; + { + int status = 1; + struct timeval min_time_copy, max_time_copy; + unsigned num_bytes = MAX_BYTES_FOR_DEFINITE_HEADER; + int num_bytes_read; + long desired_pos, present_pos; + u_char *buf, *hdrpos; + struct packet_header hdr; + + buf = (u_char *) malloc( num_bytes ); + if ( ! buf ) + error( "malloc() failured in sf_find_packet()" ); + + min_time_copy = *min_time; + min_time = &min_time_copy; + + max_time_copy = *max_time; + max_time = &max_time_copy; + + for ( ; ; ) /* loop until positioned correctly */ + { + desired_pos = + interpolated_position( min_time, min_pos, + max_time, max_pos, + desired_time ); + + if ( desired_pos < 0 ) + { + status = 0; + break; + } + + present_pos = ftell( sf_readfile ); + + if ( present_pos <= desired_pos && + desired_pos - present_pos < STRAIGHT_SCAN_THRESHOLD ) + { /* we're close enough to just blindly read ahead */ + status = read_up_to( desired_time ); + break; + } + + /* Undershoot the target a little bit - it's much easier to + * then scan straight forward than to try to read backwards ... + */ + desired_pos -= STRAIGHT_SCAN_THRESHOLD / 2; + if ( desired_pos < min_pos ) + desired_pos = min_pos; + + if ( fseek( sf_readfile, desired_pos, 0 ) < 0 ) + error( "fseek() failed in sf_find_packet()" ); + + num_bytes_read = + fread( (char *) buf, 1, num_bytes, sf_readfile ); + + if ( num_bytes_read == 0 ) + /* This shouldn't ever happen because we try to + * undershoot, unless the dump file has only a + * couple packets in it ... + */ + error( "fread() failed in sf_find_packet()" ); + + if ( find_header( buf, num_bytes, min_time->tv_sec, + max_time->tv_sec, &hdrpos, &hdr ) != + HEADER_DEFINITELY ) + error( "can't find header at position %ld in dump file", + desired_pos ); + + /* Correct desired_pos to reflect beginning of packet. */ + desired_pos += (hdrpos - buf); + + /* Seek to the beginning of the header. */ + if ( fseek( sf_readfile, desired_pos, 0 ) < 0 ) + error( "fseek() failed in sf_find_packet()" ); + + if ( sf_timestamp_less_than( &hdr.ts, desired_time ) ) + { /* too early in the file */ + *min_time = hdr.ts; + min_pos = desired_pos; + } + + else if ( sf_timestamp_less_than( desired_time, &hdr.ts ) ) + { /* too late in the file */ + *max_time = hdr.ts; + max_pos = desired_pos; + } + + else + /* got it! */ + break; + } + + free( (char *) buf ); + + return status; + } diff --git a/usr.sbin/tcpdump/tcpslice/tcpslice.1 b/usr.sbin/tcpdump/tcpslice/tcpslice.1 new file mode 100644 index 000000000000..b130f2c22a7e --- /dev/null +++ b/usr.sbin/tcpdump/tcpslice/tcpslice.1 @@ -0,0 +1,260 @@ +.\" @(#) $Header: tcpslice.1,v 1.2 91/10/16 11:42:46 vern Exp $ (LBL) +.\" +.\" Copyright (c) 1988-1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that: (1) source code distributions +.\" retain the above copyright notice and this paragraph in its entirety, (2) +.\" distributions including binary code include the above copyright notice and +.\" this paragraph in its entirety in the documentation or other materials +.\" provided with the distribution, and (3) all advertising materials mentioning +.\" features or use of this software display the following acknowledgement: +.\" ``This product includes software developed by the University of California, +.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of +.\" the University nor the names of its contributors may be used to endorse +.\" or promote products derived from this software without specific prior +.\" written permission. +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" +.TH TCPSLICE 1 "14 Oct 1991" +.SH NAME +tcpslice \- extract pieces of and/or glue together tcpdump files +.SH SYNOPSIS +.na +.B tcpslice +[ +.B \-dRrt +] [ +.B \-w +.I file +] +.br +.ti +9 +[ +.I start-time +[ +.I end-time +] ] +.I file ... +.br +.ad +.SH DESCRIPTION +.LP +.I Tcpslice +is a program for extracting portions of packet-trace files generated using +\fItcpdump(l)\fP's +.B \-w +flag. +It can also be used to glue together several such files, as discussed +below. +.LP +The basic operation of +.I tcpslice +is to copy to +.I stdout +all packets from its input file(s) whose timestamps fall +within a given range. The starting and ending times of the range +may be specified on the command line. All ranges are inclusive. +The starting time defaults +to the time of the first packet in the first input file; we call +this the +.I first time. +The ending time defaults to ten years after the starting time. +Thus, the command +.I tcpslice trace-file +simply copies +.I trace-file +to \fIstdout\fP (assuming the file does not include more than +ten years' worth of data). +.LP +There are a number of ways to specify times. The first is using +Unix timestamps of the form +.I sssssssss.uuuuuu +(this is the format specified by \fItcpdump\fP's +.B \-tt +flag). +For example, +.B 654321098.7654 +specifies 38 seconds and 765,400 microseconds +after 8:51PM PDT, Sept. 25, 1990. +.LP +All examples in this manual are given +for PDT times, but when displaying times and interpreting times symbolically +as discussed below, +.I tcpslice +uses the local timezone, regardless of the timezone in which the \fItcpdump\fP +file was generated. The daylight-savings setting used is that which is +appropriate for the local timezone at the date in question. For example, +times associated with summer months will usually include daylight-savings +effects, and those with winter months will not. +.LP +Times may also be specified relative +to either the +.I first time +(when specifying a starting time) +or the starting time (when specifying an ending time) +by preceding a numeric value in seconds with a `+'. +For example, a starting time of +.B +200 +indicates 200 seconds after the +.I first time, +and the two arguments +.B +200 +300 +indicate from 200 seconds after the +.I first time +through 500 seconds after the +.I first time. +.LP +Times may also be specified in terms of years (y), months (m), days (d), +hours (h), minutes (m), seconds (s), and microseconds(u). For example, +the Unix timestamp 654321098.7654 discussed above could also be expressed +as +.B 90y9m25d20h51m38s765400u. +.LP +When specifying times using this style, fields that are omitted default +as follows. If the omitted field is a unit +.I greater +than that of the first specified field, then its value defaults to +the corresponding value taken from either +.I first time +(if the starting time is being specified) or the starting time +(if the ending time is being specified). +If the omitted field is a unit +.I less +than that of the first specified field, then it defaults to zero. +For example, suppose that the input file has a +.I first time +of the Unix timestamp mentioned above, i.e., 38 seconds and 765,400 microseconds +after 8:51PM PDT, Sept. 25, 1990. To specify 9:36PM PDT (exactly) on the +same date we could use +.B 21h36m. +To specify a range from 9:36PM PDT through 1:54AM PDT the next day we +could use +.B 21h36m 26d1h54m. +.LP +Relative times can also be specified when using the +.I ymdhmsu +format. Omitted fields then default to 0 if the unit of the field is +.I greater +than that of the first specified field, and to the corresponding value +taken from either the +.I first time +or the starting time if the omitted field's unit is +.I less +than that of the first specified field. Given a +.I first time +of the Unix timestamp mentioned above, +.B 22h +1h10m +specifies a range from 10:00PM PDT on that date through 11:10PM PDT, and +.B +1h +1h10m +specifies a range from 38.7654 seconds after 9:51PM PDT through 38.7654 +seconds after 11:01PM PDT. The first hour of the file could be extracted +using +.B +0 +1h. +.LP +Note that with the +.I ymdhmsu +format there is an ambiguity between using +.I m +for `month' or for `minute'. The ambiguity is resolved as follows: if an +.I m +field is followed by a +.I d +field then it is interpreted as specifying months; otherwise it +specifies minutes. +.LP +If more than one input file is specified then +.I tcpslice +first copies packets lying in the given range from the first file; it +then increases the starting time of the range to lie just beyond the +timestamp of the last packet in the first file, repeats the process +with the second file, and so on. Thus files with interleaved packets +are +.I not +merged. For a given file, only packets that are newer than any in the +preceding files will be considered. This mechanism avoids any possibility +of a packet occurring more than once in the output. +.SH OPTIONS +.LP +If any of +.B \-R, +.B \-r +or +.B \-t +are specified then +.I tcpslice +reports the timestamps of the first and last packets in each input file +and exits. Only one of these three options may be specified. +.TP +.B \-d +Dump the start and end times specified by the given range and +exit. This option is useful for checking that the given range actually +specifies the times you think it does. If one of +.B \-R, +.B \-r +or +.B \-t +has been specified then the times are dumped in the corresponding +format; otherwise, raw format (\fB \-R\fP) is used. +.TP +.B \-R +Dump the timestamps of the first and last packets in each input file +as raw timestamps (i.e., in the form \fI sssssssss.uuuuuu\fP). +.TP +.B \-r +Same as +.B \-R +except the timestamps are dumped in human-readable format, similar +to that used by \fI date(1)\fP. +.TP +.B \-t +Same as +.B \-R +except the timestamps are dumped in +.I tcpslice +format, i.e., in the +.I ymdhmsu +format discussed above. +.TP +.B \-w +Direct the output to \fIfile\fR rather than \fIstdout\fP. +.SH "SEE ALSO" +tcpdump(l) +.SH AUTHOR +Vern Paxson (vern@ee.lbl.gov), of +Lawrence Berkeley Laboratory, University of California, Berkeley, CA. +.SH BUGS +An input filename that beings with a digit or a `+' can be confused +with a start/end time. Such filenames can be specified with a +leading `./'; for example, specify the file `04Jul76.trace' as +`./04Jul76.trace'. +.LP +.I tcpslice +cannot read its input from \fIstdin\fP, since it uses random-access +to rummage through its input files. +.LP +.I tcpslice +refuses to write to its output if it is a terminal +(as indicated by \fIisatty(3)\fP). This is not a bug but a feature, +to prevent it from spraying binary data to the user's terminal. +Note that this means you must either redirect \fIstdout\fP or specify an +output file via \fB\-w\fP. +.LP +.I tcpslice +will not work properly on \fItcpdump\fP files spanning more than one year; +with files containing portions of packets whose original length was +more than 65,535 bytes; nor with files containing fewer than three packets. +Such files result in +the error message: `couldn't find final packet in file'. These problems +are due to the interpolation scheme used by +.I tcpslice +to greatly speed up its processing when dealing with large trace files. +Note that +.I tcpslice +can efficiently extract slices from the middle of trace files of any +size, and can also work with truncated trace files (i.e., the final packet +in the file is only partially present, typically due to \fItcpdump\fP +being ungracefully killed). diff --git a/usr.sbin/tcpdump/tcpslice/tcpslice.c b/usr.sbin/tcpdump/tcpslice/tcpslice.c new file mode 100644 index 000000000000..b5b6eeafb527 --- /dev/null +++ b/usr.sbin/tcpdump/tcpslice/tcpslice.c @@ -0,0 +1,645 @@ +/* + * Copyright (c) 1987-1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +char copyright[] = + "@(#) Copyright (c) 1987-1990 The Regents of the University of California.\nAll rights reserved.\n"; +static char rcsid[] = + "@(#)$Header: tcpslice.c,v 1.10 92/06/02 17:57:44 mccanne Exp $ (LBL)"; +#endif + +/* + * tcpslice - extract pieces of and/or glue together tcpdump files + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "savefile.h" +#include "version.h" + + +int tflag = 0; /* global that util routines are sensitive to */ + +char *program_name; + +long thiszone; /* gmt to local correction in trace file */ + +/* Length of saved portion of packet. */ +int snaplen; + +/* Length of saved portion of data past link level protocol. */ +int snapdlen; + +/* Precision of clock used to generate trace file. */ +int precision; + +static int linkinfo; + +/* Style in which to print timestamps; RAW is "secs.usecs"; READABLE is + * ala the Unix "date" tool; and PARSEABLE is tcpslice's custom format, + * designed to be easy to parse. The default is RAW. + */ +enum stamp_styles { TIMESTAMP_RAW, TIMESTAMP_READABLE, TIMESTAMP_PARSEABLE }; +enum stamp_styles timestamp_style = TIMESTAMP_RAW; + + +time_t gwtm2secs( /* struct tm *tmp */ ); + + +long local_time_zone( /* timestamp */ ); +struct timeval parse_time(/* time_string, base_time*/); +void fill_tm(/* time_string, is_delta, t, usecs_addr */); +void get_file_range( /* filename, first_time, last_time */ ); +struct timeval first_packet_time(/* filename */); +void extract_slice(/* filename, start_time, stop_time */); +char *timestamp_to_string( /* timestamp */ ); +void dump_times(/* filename */); +void usage(); + + +int +main(argc, argv) + int argc; + char **argv; +{ + int op; + int dump_flag = 0; + int report_times = 0; + char *start_time_string = 0; + char *stop_time_string = 0; + char *write_file_name = "-"; /* default is stdout */ + struct timeval first_time, start_time, stop_time; + + extern char *optarg; + extern int optind, opterr; + + program_name = argv[0]; + + opterr = 0; + while ((op = getopt(argc, argv, "dRrtw:")) != EOF) + switch (op) { + + case 'd': + dump_flag = 1; + break; + + case 'R': + ++report_times; + timestamp_style = TIMESTAMP_RAW; + break; + + case 'r': + ++report_times; + timestamp_style = TIMESTAMP_READABLE; + break; + + case 't': + ++report_times; + timestamp_style = TIMESTAMP_PARSEABLE; + break; + + case 'w': + write_file_name = optarg; + break; + + default: + usage(); + /* NOTREACHED */ + } + + if ( report_times > 1 ) + error( "only one of -R, -r, or -t can be specified" ); + + + if (optind < argc) + /* See if the next argument looks like a possible + * start time, and if so assume it is one. + */ + if (isdigit(argv[optind][0]) || argv[optind][0] == '+') + start_time_string = argv[optind++]; + + if (optind < argc) + if (isdigit(argv[optind][0]) || argv[optind][0] == '+') + stop_time_string = argv[optind++]; + + + if (optind >= argc) + error("at least one input file must be given"); + + + first_time = first_packet_time(argv[optind]); + fclose( sf_readfile ); + + + if (start_time_string) + start_time = parse_time(start_time_string, first_time); + else + start_time = first_time; + + if (stop_time_string) + stop_time = parse_time(stop_time_string, start_time); + + else + { + stop_time = start_time; + stop_time.tv_sec += 86400*3660; /* + 10 years; "forever" */ + } + + + if (report_times) { + for (; optind < argc; ++optind) + dump_times(argv[optind]); + } + + if (dump_flag) { + printf( "start\t%s\nstop\t%s\n", + timestamp_to_string( &start_time ), + timestamp_to_string( &stop_time ) ); + } + + if (! report_times && ! dump_flag) { + if ( ! strcmp( write_file_name, "-" ) && + isatty( fileno(stdout) ) ) + error("stdout is a terminal; redirect or use -w"); + + sf_write_init(write_file_name, linkinfo, thiszone, snaplen, + precision); + + for (; optind < argc; ++optind) + extract_slice(argv[optind], &start_time, &stop_time); + + fclose( sf_writefile ); + } + + return 0; +} + + +/* Returns non-zero if a string matches the format for a timestamp, + * 0 otherwise. + */ +int is_timestamp( str ) +char *str; + { + while ( isdigit(*str) || *str == '.' ) + ++str; + + return *str == '\0'; + } + + +/* Return the correction in seconds for the local time zone with respect + * to Greenwich time. + */ +long local_time_zone(timestamp) +long timestamp; +{ + struct timeval now; + struct timezone tz; + long localzone; + + if (gettimeofday(&now, &tz) < 0) { + perror("tcpslice: gettimeofday"); + exit(1); + } + localzone = tz.tz_minuteswest * -60; + + if (localtime((time_t *) ×tamp)->tm_isdst) + localzone += 3600; + + return localzone; +} + +/* Given a string specifying a time (or a time offset) and a "base time" + * from which to compute offsets and fill in defaults, returns a timeval + * containing the specified time. + */ + +struct timeval +parse_time(time_string, base_time) + char *time_string; + struct timeval base_time; +{ + struct tm *bt = localtime((time_t *) &base_time.tv_sec); + struct tm t; + struct timeval result; + time_t usecs = 0; + int is_delta = (time_string[0] == '+'); + + if ( is_delta ) + ++time_string; /* skip over '+' sign */ + + if ( is_timestamp( time_string ) ) + { /* interpret as a raw timestamp or timestamp offset */ + char *time_ptr; + + result.tv_sec = atoi( time_string ); + time_ptr = strchr( time_string, '.' ); + + if ( time_ptr ) + { /* microseconds are specified, too */ + int num_digits = strlen( time_ptr + 1 ); + result.tv_usec = atoi( time_ptr + 1 ); + + /* turn 123.456 into 123 seconds plus 456000 usec */ + while ( num_digits++ < 6 ) + result.tv_usec *= 10; + } + + else + result.tv_usec = 0; + + if ( is_delta ) + { + result.tv_sec += base_time.tv_sec; + result.tv_usec += base_time.tv_usec; + + if ( result.tv_usec > 1000000 ) + { + result.tv_usec -= 1000000; + ++result.tv_sec; + } + } + + return result; + } + + if (is_delta) { + t = *bt; + usecs = base_time.tv_usec; + } else { + /* Zero struct (easy way around lack of tm_gmtoff/tm_zone + * under older systems) */ + bzero((char *)&t, sizeof(t)); + + /* Set values to "not set" flag so we can later identify + * and default them. + */ + t.tm_sec = t.tm_min = t.tm_hour = t.tm_mday = t.tm_mon = + t.tm_year = -1; + } + + fill_tm(time_string, is_delta, &t, &usecs); + + /* Now until we reach a field that was specified, fill in the + * missing fields from the base time. + */ +#define CHECK_FIELD(field_name) \ + if (t.field_name < 0) \ + t.field_name = bt->field_name; \ + else \ + break + + do { /* bogus do-while loop so "break" in CHECK_FIELD will work */ + CHECK_FIELD(tm_year); + CHECK_FIELD(tm_mon); + CHECK_FIELD(tm_mday); + CHECK_FIELD(tm_hour); + CHECK_FIELD(tm_min); + CHECK_FIELD(tm_sec); + } while ( 0 ); + + /* Set remaining unspecified fields to 0. */ +#define ZERO_FIELD_IF_NOT_SET(field_name,zero_val) \ + if (t.field_name < 0) \ + t.field_name = zero_val + + if (! is_delta) { + ZERO_FIELD_IF_NOT_SET(tm_year,90); /* should never happen */ + ZERO_FIELD_IF_NOT_SET(tm_mon,0); + ZERO_FIELD_IF_NOT_SET(tm_mday,1); + ZERO_FIELD_IF_NOT_SET(tm_hour,0); + ZERO_FIELD_IF_NOT_SET(tm_min,0); + ZERO_FIELD_IF_NOT_SET(tm_sec,0); + } + + result.tv_sec = gwtm2secs(&t); + result.tv_sec -= local_time_zone(result.tv_sec); + result.tv_usec = usecs; + + return result; +} + + +/* Fill in (or add to, if is_delta is true) the time values in the + * tm struct "t" as specified by the time specified in the string + * "time_string". "usecs_addr" is updated with the specified number + * of microseconds, if any. + */ +void +fill_tm(time_string, is_delta, t, usecs_addr) + char *time_string; + int is_delta; /* if true, add times in instead of replacing */ + struct tm *t; /* tm struct to be filled from time_string */ + time_t *usecs_addr; +{ + char *t_start, *t_stop, format_ch; + int val; + +#define SET_VAL(lhs,rhs) \ + if (is_delta) \ + lhs += rhs; \ + else \ + lhs = rhs + + /* Loop through the time string parsing one specification at + * a time. Each specification has the form + * where indicates the amount of time and + * the units. + */ + for (t_stop = t_start = time_string; *t_start; t_start = ++t_stop) { + if (! isdigit(*t_start)) + error("bad date format %s, problem starting at %s", + time_string, t_start); + + while (isdigit(*t_stop)) + ++t_stop; + if (! t_stop) + error("bad date format %s, problem starting at %s", + time_string, t_start); + + val = atoi(t_start); + + format_ch = *t_stop; + if ( isupper( format_ch ) ) + format_ch = tolower( format_ch ); + + switch (format_ch) { + case 'y': + if ( val > 1900 ) + val -= 1900; + SET_VAL(t->tm_year, val); + break; + + case 'm': + if (strchr(t_stop+1, 'D') || + strchr(t_stop+1, 'd')) + /* it's months */ + SET_VAL(t->tm_mon, val - 1); + else /* it's minutes */ + SET_VAL(t->tm_min, val); + break; + + case 'd': + SET_VAL(t->tm_mday, val); + break; + + case 'h': + SET_VAL(t->tm_hour, val); + break; + + case 's': + SET_VAL(t->tm_sec, val); + break; + + case 'u': + SET_VAL(*usecs_addr, val); + break; + + default: + error( + "bad date format %s, problem starting at %s", + time_string, t_start); + } + } +} + + +/* Return in first_time and last_time the timestamps of the first and + * last packets in the given file. + */ +void +get_file_range( filename, first_time, last_time ) + char filename[]; + struct timeval *first_time; + struct timeval *last_time; +{ + *first_time = first_packet_time( filename ); + + if ( ! sf_find_end( first_time, last_time ) ) + error( "couldn't find final packet in file %s", filename ); +} + + +/* Returns the timestamp of the first packet in the given tcpdump save + * file, which as a side-effect is initialized for further save-file + * reading. + */ + +struct timeval +first_packet_time(filename) + char filename[]; +{ + struct packet_header hdr; + u_char *buf; + + if (sf_read_init(filename, &linkinfo, &thiszone, &snaplen, &precision)) + error( "bad tcpdump file %s", filename ); + + buf = (u_char *)malloc((unsigned)snaplen); + + if (sf_next_packet(&hdr, buf, snaplen)) + error( "bad status reading first packet in %s", filename ); + + free((char *)buf); + + return hdr.ts; +} + + +/* Extract from the given file all packets with timestamps between + * the two time values given (inclusive). These packets are written + * to the save file output set up by a previous call to sf_write_init(). + * Upon return, start_time is adjusted to reflect a time just after + * that of the last packet written to the output. + */ + +void +extract_slice(filename, start_time, stop_time) + char filename[]; + struct timeval *start_time; + struct timeval *stop_time; +{ + long start_pos, stop_pos; + struct timeval file_start_time, file_stop_time; + int status; + struct packet_header hdr; + u_char *buf; + + + if (sf_read_init(filename, &linkinfo, &thiszone, &snaplen, &precision)) + error( "bad tcpdump file %s", filename ); + + buf = (u_char *)malloc((unsigned)snaplen); + + start_pos = ftell( sf_readfile ); + + + if ( (status = sf_next_packet( &hdr, buf, snaplen )) ) + error( "bad status %d reading packet in %s", + status, filename ); + + file_start_time = hdr.ts; + + + if ( ! sf_find_end( &file_start_time, &file_stop_time ) ) + error( "problems finding end packet of file %s", + filename ); + + stop_pos = ftell( sf_readfile ); + + + /* sf_find_packet() requires that the time it's passed as its last + * argument be in the range [min_time, max_time], so we enforce + * that constraint here. + */ + if ( sf_timestamp_less_than( start_time, &file_start_time ) ) + *start_time = file_start_time; + + if ( sf_timestamp_less_than( &file_stop_time, start_time ) ) + return; /* there aren't any packets of interest in the file */ + + + sf_find_packet( &file_start_time, start_pos, + &file_stop_time, stop_pos, + start_time ); + + for ( ; ; ) + { + struct timeval *timestamp; + status = sf_next_packet( &hdr, buf, snaplen ); + + if ( status ) + { + if ( status != SFERR_EOF ) + error( "bad status %d reading packet in %s", + status, filename ); + break; + } + + timestamp = &hdr.ts; + + if ( ! sf_timestamp_less_than( timestamp, start_time ) ) + { /* packet is recent enough */ + if ( sf_timestamp_less_than( stop_time, timestamp ) ) + /* We've gone beyond the end of the region + * of interest ... We're done with this file. + */ + break; + + sf_write( buf, timestamp, (int) hdr.len, + (int) hdr.caplen ); + *start_time = *timestamp; + + /* We know that each packet is guaranteed to have + * a unique timestamp, so we push forward the + * allowed minimum time to weed out duplicate + * packets. + */ + ++start_time->tv_usec; + } + } + + fclose( sf_readfile ); + free( (char *) buf ); +} + + +/* Translates a timestamp to the time format specified by the user. + * Returns a pointer to the translation residing in a static buffer. + * There are two such buffers, which are alternated on subseqeuent + * calls, so two calls may be made to this routine without worrying + * about the results of the first call being overwritten by the + * results of the second. + */ + +char * +timestamp_to_string(timestamp) + struct timeval *timestamp; +{ + struct tm *t; +#define NUM_BUFFERS 2 + static char buffers[NUM_BUFFERS][128]; + static int buffer_to_use = 0; + char *buf; + + buf = buffers[buffer_to_use]; + buffer_to_use = (buffer_to_use + 1) % NUM_BUFFERS; + + switch ( timestamp_style ) + { + case TIMESTAMP_RAW: + sprintf( buf, "%d.%d", timestamp->tv_sec, timestamp->tv_usec ); + break; + + case TIMESTAMP_READABLE: + t = localtime((time_t *) ×tamp->tv_sec); + strcpy( buf, asctime( t ) ); + buf[24] = '\0'; /* nuke final newline */ + break; + + case TIMESTAMP_PARSEABLE: + t = localtime((time_t *) ×tamp->tv_sec); + sprintf( buf, "%02dy%02dm%02dd%02dh%02dm%02ds%06du", + t->tm_year, t->tm_mon + 1, t->tm_mday, t->tm_hour, + t->tm_min, t->tm_sec, timestamp->tv_usec ); + break; + + } + + return buf; +} + + +/* Given a tcpdump save filename, reports on the times of the first + * and last packets in the file. + */ + +void +dump_times(filename) + char filename[]; +{ + struct timeval first_time, last_time; + + get_file_range( filename, &first_time, &last_time ); + + printf( "%s\t%s\t%s\n", + filename, + timestamp_to_string( &first_time ), + timestamp_to_string( &last_time ) ); +} + +void +usage() +{ + (void)fprintf(stderr, "tcpslice for tcpdump version %d.%d\n", + VERSION_MAJOR, VERSION_MINOR); + (void)fprintf(stderr, +"Usage: tcpslice [-dRrt] [-w file] [start-time [end-time]] file ... \n"); + + exit(-1); +}